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/.gdbinit b/.gdbinit index c4705b2f59a95..4477828265e0e 100644 --- a/.gdbinit +++ b/.gdbinit @@ -42,7 +42,7 @@ define print_cvs printf "Compiled variables count: %d\n\n", $cv_count while $cv_idx < $cv_count - printf "[%d] '%s'\n", $cv_idx, $cv[$cv_idx].val + printf "[%d] '$%s'\n", $cv_idx, $cv[$cv_idx].val@$cv[$cv_idx].len set $zvalue = ((zval *) $cv_ex_ptr) + $callFrameSize + $cv_idx printzv $zvalue set $cv_idx = $cv_idx + 1 diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2bd2f6d94ef9f..c01cbfe0954f8 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -16,19 +16,19 @@ /.github @TimWolla /build/gen_stub.php @kocsismate -/ext/bcmath @Girgias @nielsdos @SakiTakamachi +/ext/bcmath @ndossche @SakiTakamachi /ext/curl @adoy /ext/date @derickr /ext/dba @Girgias -/ext/dom @nielsdos +/ext/dom @ndossche /ext/ffi @dstogov /ext/gd @devnexen /ext/gettext @devnexen /ext/gmp @Girgias /ext/intl @devnexen /ext/json @bukka -/ext/lexbor @kocsismate @nielsdos -/ext/libxml @nielsdos +/ext/lexbor @kocsismate @ndossche +/ext/libxml @ndossche /ext/mbstring @alexdowad @youkidearitai /ext/mysqli @bukka @kamil-tekiela /ext/mysqlnd @bukka @kamil-tekiela @SakiTakamachi @@ -47,16 +47,17 @@ /ext/random @TimWolla @zeriyoshi /ext/reflection @DanielEScherzer /ext/session @Girgias -/ext/simplexml @nielsdos -/ext/soap @nielsdos +/ext/simplexml @ndossche +/ext/soap @ndossche /ext/sockets @devnexen /ext/spl @Girgias /ext/standard @bukka -/ext/uri @kocsismate -/ext/xml @nielsdos -/ext/xmlreader @nielsdos -/ext/xmlwriter @nielsdos -/ext/xsl @nielsdos +/ext/tidy @ndossche +/ext/uri @kocsismate @TimWolla +/ext/xml @ndossche +/ext/xmlreader @ndossche +/ext/xmlwriter @ndossche +/ext/xsl @ndossche /main @bukka /sapi/fpm @bukka /Zend/Optimizer @dstogov diff --git a/.github/actions/apk/action.yml b/.github/actions/apk/action.yml index 039fc64a5491e..0cda4963a6a9c 100644 --- a/.github/actions/apk/action.yml +++ b/.github/actions/apk/action.yml @@ -6,6 +6,11 @@ runs: run: | set -x + OPCACHE_TLS_TESTS_DEPS="clang gcc binutils-gold lld" + # compiler-rt provides libclang_rt.asan-x86_64.a for clang20 + # https://pkgs.alpinelinux.org/contents?file=libclang_rt.asan-x86_64.a&path=&name=&branch=v3.22 + ASAN_DEPS="clang20 compiler-rt" + apk update -q apk add \ util-linux \ @@ -50,7 +55,9 @@ runs: net-snmp-dev \ openldap-dev \ unixodbc-dev \ - postgresql14-dev \ + postgresql-dev \ tzdata \ musl-locales \ - musl-locales-lang + musl-locales-lang \ + $OPCACHE_TLS_TESTS_DEPS \ + $ASAN_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/configure-unit-tests/action.yml b/.github/actions/configure-unit-tests/action.yml new file mode 100644 index 0000000000000..ef8239b7111c7 --- /dev/null +++ b/.github/actions/configure-unit-tests/action.yml @@ -0,0 +1,10 @@ +name: ./configure (unit tests) +description: Configure PHP with minimal settings for unit testing +runs: + using: composite + steps: + - shell: bash + run: | + set -x + ./buildconf --force + ./configure --disable-all --enable-embed=static 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 98163d28a82e9..456d88dd1f877 100644 --- a/.github/actions/freebsd/action.yml +++ b/.github/actions/freebsd/action.yml @@ -3,13 +3,16 @@ 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. @@ -17,6 +20,8 @@ runs: prepare: | cd $GITHUB_WORKSPACE + OPCACHE_TLS_TESTS_DEPS="gcc" + kldload accf_http pkg install -y \ autoconf \ @@ -41,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 \ @@ -106,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/actions/macos-update-clang/action.yml b/.github/actions/macos-update-clang/action.yml new file mode 100644 index 0000000000000..916b4dfe41f48 --- /dev/null +++ b/.github/actions/macos-update-clang/action.yml @@ -0,0 +1,17 @@ +name: Update clang +runs: + using: composite + steps: + - shell: bash + run: | + softwareupdate -l + label=$((softwareupdate -l 2>/dev/null | grep 'Label:' | grep -o 'Command Line Tools for Xcode.*' | head -1) || echo '') + if [ -n "$label" ]; then + softwareupdate -i "$label" + xcode_path=$(ls -1 '/Applications' | grep 'Xcode_.*\.app' | sort -r | head -1) + sudo xcode-select -s "/Applications/$xcode_path" + else + echo "Not found." + fi + which clang + clang -v diff --git a/.github/actions/notify-slack/action.yml b/.github/actions/notify-slack/action.yml deleted file mode 100644 index 1ff425b51c6ac..0000000000000 --- a/.github/actions/notify-slack/action.yml +++ /dev/null @@ -1,10 +0,0 @@ -name: Notify Slack -inputs: - token: - required: true -runs: - using: composite - steps: - - shell: bash - run: >- - curl -X POST -H 'Content-type: application/json' --data '{"attachments": [{"text": "Job in *nightly* failed", "footer": "", "color": "danger", "mrkdwn_in": ["text"]}]}' ${{ inputs.token }} diff --git a/.github/actions/verify-generated-files/action.yml b/.github/actions/verify-generated-files/action.yml index 5228105f25908..79c49dbfcfffb 100644 --- a/.github/actions/verify-generated-files/action.yml +++ b/.github/actions/verify-generated-files/action.yml @@ -12,5 +12,5 @@ runs: Zend/zend_vm_gen.php ext/tokenizer/tokenizer_data_gen.php build/gen_stub.php -f --generate-optimizer-info --verify - # Use the -a flag for a bug in git 2.46.0, which doesn't consider changed -diff files. - git add . -N && git diff -a --exit-code + ext/phar/makestub.php + .github/scripts/test-directory-unchanged.sh . diff --git a/.github/labeler.yml b/.github/labeler.yml index 92f9c50962349..b9f0f36e147d4 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -492,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/nightly_matrix.php b/.github/nightly_matrix.php index 311176ef5e53e..0032da7dbcea8 100644 --- a/.github/nightly_matrix.php +++ b/.github/nightly_matrix.php @@ -1,11 +1,11 @@ 'master', 'version' => [8, 5]], + ['ref' => 'master', 'version' => [8, 6]], + ['ref' => 'PHP-8.5', 'version' => [8, 5]], ['ref' => 'PHP-8.4', 'version' => [8, 4]], ['ref' => 'PHP-8.3', 'version' => [8, 3]], ['ref' => 'PHP-8.2', 'version' => [8, 2]], - ['ref' => 'PHP-8.1', 'version' => [8, 1]], ]; function get_branch_commit_cache_file_path(): string { @@ -48,8 +48,8 @@ function get_current_version(): array { $trigger = $argv[1] ?? 'schedule'; $attempt = (int) ($argv[2] ?? 1); -$monday = date('w', time()) === '1'; -$discard_cache = $monday +$sunday = date('w', time()) === '0'; +$discard_cache = $sunday || ($trigger === 'schedule' && $attempt !== 1) || $trigger === 'workflow_dispatch'; if ($discard_cache) { diff --git a/.github/scripts/download-bundled/pcre2.sh b/.github/scripts/download-bundled/pcre2.sh new file mode 100755 index 0000000000000..b43554206c929 --- /dev/null +++ b/.github/scripts/download-bundled/pcre2.sh @@ -0,0 +1,32 @@ +#!/bin/sh +set -ex +cd "$(dirname "$0")/../../.." + +revision=refs/tags/pcre2-10.44 + +git clone --depth 1 --recurse-submodules --revision="$revision" https://github.com/PCRE2Project/pcre2.git /tmp/php-src-bundled/pcre2 + +rm -rf ext/pcre/pcre2lib +cp -R /tmp/php-src-bundled/pcre2/src ext/pcre/pcre2lib + +cd ext/pcre/pcre2lib + +# remove unneeded files +rm config.h.generic +rm pcre2.h.in +rm pcre2_dftables.c +rm pcre2_fuzzsupport.c +rm pcre2_jit_test.c +rm pcre2demo.c +rm pcre2grep.c +rm pcre2posix.c +rm pcre2posix.h +rm pcre2posix_test.c +rm pcre2test.c + +# move renamed files +mv pcre2.h.generic pcre2.h +mv pcre2_chartables.c.dist pcre2_chartables.c + +# add extra files +git restore config.h # based on config.h.generic but with many changes diff --git a/.github/scripts/test-directory-unchanged.sh b/.github/scripts/test-directory-unchanged.sh new file mode 100755 index 0000000000000..0ce7fd4cc4afd --- /dev/null +++ b/.github/scripts/test-directory-unchanged.sh @@ -0,0 +1,13 @@ +#!/bin/sh +set -ex + +cd "$(dirname "$0")/../../$1" + +# notify git about untracked (except ignored) files +git add -N . + +# display overview of changed files +git status . + +# display diff of working directory vs HEAD commit and set exit code +git diff -a --exit-code HEAD . diff --git a/.github/scripts/windows/find-target-branch.bat b/.github/scripts/windows/find-target-branch.bat index a0b47f2488946..44b0bde1ec8ca 100644 --- a/.github/scripts/windows/find-target-branch.bat +++ b/.github/scripts/windows/find-target-branch.bat @@ -3,6 +3,6 @@ for /f "usebackq tokens=3" %%i in (`findstr PHP_MAJOR_VERSION main\php_version.h`) do set BRANCH=%%i for /f "usebackq tokens=3" %%i in (`findstr PHP_MINOR_VERSION main\php_version.h`) do set BRANCH=%BRANCH%.%%i -if /i "%BRANCH%" equ "8.5" ( +if /i "%BRANCH%" equ "8.6" ( set BRANCH=master ) diff --git a/.github/scripts/windows/test_task.bat b/.github/scripts/windows/test_task.bat index 43e7763e70294..4ce2bd96ce660 100644 --- a/.github/scripts/windows/test_task.bat +++ b/.github/scripts/windows/test_task.bat @@ -36,8 +36,7 @@ if %errorlevel% neq 0 exit /b 3 rem setup PostgreSQL related exts set PGUSER=postgres set PGPASSWORD=Password12! -rem set PGSQL_TEST_CONNSTR=host=127.0.0.1 dbname=test port=5432 user=postgres password=Password12! -echo ^ >> "./ext/pgsql/tests/config.inc" +set PGSQL_TEST_CONNSTR=host=127.0.0.1 dbname=test port=5432 user=%PGUSER% password=%PGPASSWORD% set PDO_PGSQL_TEST_DSN=pgsql:host=127.0.0.1 port=5432 dbname=test user=%PGUSER% password=%PGPASSWORD% set TMP_POSTGRESQL_BIN=%PGBIN% "%TMP_POSTGRESQL_BIN%\createdb.exe" test @@ -128,7 +127,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..0ab56f77ab3f8 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@v6 - name: Install dependencies run: pip install -r docs/requirements.txt - name: Check formatting diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index dbddbdc5d89b3..4cf6357c491fd 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -12,6 +12,6 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: actions/labeler@v5 + - uses: actions/labeler@v6 with: repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/nightly-results.yml b/.github/workflows/nightly-results.yml new file mode 100644 index 0000000000000..a222582da1c6f --- /dev/null +++ b/.github/workflows/nightly-results.yml @@ -0,0 +1,16 @@ +name: Nightly results +on: + workflow_run: + workflows: + - Nightly + types: + - completed +jobs: + on-failure: + runs-on: ubuntu-latest + if: ${{ github.repository == 'php/php-src' && github.event.workflow_run.conclusion == 'failure' }} + steps: + - run: | + export DEBIAN_FRONTEND=noninteractive + sudo apt-get install -y curl + curl -X POST -H 'Content-type: application/json' --data '{"attachments": [{"text": "Job(s) in *nightly* failed", "footer": "<${{ github.event.workflow_run.html_url }}|View Run>", "color": "danger", "mrkdwn_in": ["text"]}]}' ${{ secrets.ACTION_MONITORING_SLACK }} diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 5817c647a871a..9ab95da2d935d 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -14,6 +14,9 @@ on: libmysqlclient_with_mysqli: required: true type: boolean + macos_arm64_version: + required: true + type: string run_alpine: required: true type: boolean @@ -38,12 +41,15 @@ on: skip_laravel: required: true type: boolean - skip_symfony: + symfony_version: required: true - type: boolean + type: string skip_wordpress: required: true type: boolean + variation_enable_zend_max_execution_timers: + required: true + type: boolean permissions: contents: read jobs: @@ -54,7 +60,7 @@ jobs: runs-on: [self-hosted, gentoo, ppc64] steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: ref: ${{ inputs.branch }} - name: System info @@ -85,24 +91,21 @@ 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 - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 container: - image: 'alpine:3.20.1' + image: 'alpine:3.22' steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: ref: ${{ inputs.branch }} - name: apk uses: ./.github/actions/apk - - name: LLVM 17 (ASAN-only) - # libclang_rt.asan-x86_64.a is provided by compiler-rt, and only for clang17: - # https://pkgs.alpinelinux.org/contents?file=libclang_rt.asan-x86_64.a&path=&name=&branch=v3.20 - run: | - apk add clang17 compiler-rt - name: System info run: | echo "::group::Show host CPU info" @@ -117,8 +120,8 @@ jobs: configurationParameters: >- CFLAGS="-fsanitize=undefined,address -fno-sanitize=function -DZEND_TRACK_ARENA_ALLOC" LDFLAGS="-fsanitize=undefined,address -fno-sanitize=function" - CC=clang-17 - CXX=clang++-17 + CC=clang-20 + CXX=clang++-20 --enable-debug --enable-zts skipSlow: true # FIXME: This should likely include slow extensions @@ -132,14 +135,9 @@ jobs: jitType: tracing runTestsParameters: >- --asan -x - -d zend_extension=opcache.so -d opcache.enable_cli=1 - - name: Notify Slack - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} - + - name: Extra tests + uses: ./.github/actions/extra-tests LINUX_X64: services: mysql: @@ -195,6 +193,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 @@ -203,7 +202,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@v6 with: ref: ${{ inputs.branch }} - name: Create MSSQL container @@ -246,14 +245,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 @@ -264,15 +261,11 @@ 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 - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} LINUX_X32: strategy: fail-fast: false @@ -304,7 +297,7 @@ jobs: FIREBIRD_PASSWORD: test steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: ref: ${{ inputs.branch }} - name: apt @@ -338,14 +331,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 @@ -353,29 +344,27 @@ jobs: jitType: function runTestsParameters: >- ${{ matrix.run_tests_parameters }} - -d zend_extension=opcache.so -d opcache.enable_cli=1 - - name: Notify Slack - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} + - name: Extra tests + uses: ./.github/actions/extra-tests MACOS: strategy: fail-fast: false matrix: debug: [true, false] zts: [true, false] - os: ['13', '14'] + arch: ['X64', 'ARM64'] exclude: - - os: ${{ !inputs.run_macos_arm64 && '14' || '*never*' }} - name: "MACOS_${{ matrix.os == '13' && 'X64' || 'ARM64' }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}" - runs-on: macos-${{ matrix.os }} + - arch: ${{ !inputs.run_macos_arm64 && 'ARM64' || '*never*' }} + name: "MACOS_${{ matrix.arch }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}" + runs-on: macos-${{ matrix.arch == 'X64' && '15-intel' || inputs.macos_arm64_version }} steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: ref: ${{ inputs.branch }} + - name: Update clang + uses: ./.github/actions/macos-update-clang - name: brew uses: ./.github/actions/brew - name: ./configure @@ -393,34 +382,28 @@ jobs: - name: Test uses: ./.github/actions/test-macos - name: Test Tracing JIT - if: matrix.os != '14' || !matrix.zts + if: matrix.arch == 'X64' || !matrix.zts uses: ./.github/actions/test-macos 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 + if: matrix.arch == 'X64' || !matrix.zts uses: ./.github/actions/test-macos 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 - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} COVERAGE_DEBUG_NTS: if: inputs.branch == 'master' services: @@ -449,7 +432,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: ref: ${{ inputs.branch }} - name: Create MSSQL container @@ -474,19 +457,13 @@ 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 token: ${{ secrets.CODECOV_TOKEN }} verbose: true - - name: Notify Slack - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} COMMUNITY: strategy: fail-fast: false @@ -503,7 +480,7 @@ jobs: USE_TRACKED_ALLOC: 1 steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: ref: ${{ inputs.branch }} - name: apt @@ -528,7 +505,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 @@ -555,14 +531,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 @@ -586,14 +565,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 @@ -610,23 +592,27 @@ jobs: exit 1 fi - name: Test Symfony - if: ${{ !cancelled() && !inputs.skip_symfony }} + if: ${{ !cancelled() && inputs.symfony_version != '' }} run: | - git clone https://github.com/symfony/symfony.git --depth=1 + git clone https://github.com/symfony/symfony.git --depth=1 --branch="${{ inputs.symfony_version }}" cd symfony git rev-parse HEAD 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 @@ -642,7 +628,8 @@ jobs: exit 1 fi - name: 'Symfony Preloading' - if: ${{ !cancelled() && !inputs.skip_symfony }} + # composer create-project will automatically pick the right Symfony version for us. + if: ${{ !cancelled() && inputs.symfony_version != '' }} run: | php /usr/bin/composer create-project symfony/symfony-demo symfony_demo --no-progress --ignore-platform-req=php+ cd symfony_demo @@ -664,11 +651,6 @@ jobs: if [ $EXIT_CODE -gt 128 ]; then exit 1 fi - - name: Notify Slack - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} OPCACHE_VARIATION: services: mysql: @@ -697,7 +679,7 @@ jobs: runs-on: ubuntu-${{ inputs.ubuntu_version }} steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: ref: ${{ inputs.branch }} - name: Create MSSQL container @@ -719,21 +701,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 @@ -741,7 +720,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 @@ -749,23 +727,17 @@ 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 - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files - - name: Notify Slack - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} MSAN: name: MSAN runs-on: ubuntu-${{ inputs.ubuntu_version }} steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: ref: ${{ inputs.branch }} - name: apt @@ -843,21 +815,15 @@ 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 - - name: Notify Slack - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} LIBMYSQLCLIENT: name: LIBMYSQLCLIENT runs-on: ubuntu-${{ inputs.ubuntu_version }} steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: ref: ${{ inputs.branch }} - name: apt @@ -894,11 +860,6 @@ jobs: withMysqli: ${{ inputs.libmysqlclient_with_mysqli }} - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files - - name: Notify Slack - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} PECL: if: inputs.branch == 'master' runs-on: ubuntu-22.04 @@ -907,38 +868,38 @@ jobs: CXX: ccache g++ steps: - name: git checkout PHP - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: path: php ref: ${{ inputs.branch }} - name: git checkout apcu - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: repository: krakjoe/apcu path: apcu - name: git checkout imagick - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: repository: Imagick/imagick path: imagick - name: git checkout memcached - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: repository: php-memcached-dev/php-memcached path: memcached - name: git checkout redis - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: repository: phpredis/phpredis path: redis - name: git checkout xdebug if: false - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: repository: xdebug/xdebug path: xdebug - name: git checkout yaml - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: repository: php/pecl-file_formats-yaml path: yaml @@ -1006,11 +967,6 @@ jobs: /opt/php/bin/phpize ./configure --prefix=/opt/php --with-php-config=/opt/php/bin/php-config make -j$(/usr/bin/nproc) - - name: Notify Slack - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} WINDOWS: strategy: fail-fast: false @@ -1036,7 +992,7 @@ jobs: PHP_BUILD_CACHE_BASE_DIR: C:\build-cache 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_SDK_BRANCH: php-sdk-2.5.0 PHP_BUILD_CRT: ${{ inputs.vs_crt_version }} PLATFORM: ${{ matrix.x64 && 'x64' || 'x86' }} THREAD_SAFE: "${{ matrix.zts && '1' || '0' }}" @@ -1048,7 +1004,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@v6 with: ref: ${{ inputs.branch }} - name: Setup @@ -1066,9 +1022,10 @@ jobs: - 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@v6 with: ref: ${{ inputs.branch }} - name: FreeBSD @@ -1076,3 +1033,4 @@ jobs: with: configurationParameters: >- --${{ matrix.zts && 'enable' || 'disable' }}-zts + runExtraTests: true diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 2f82179b90ec6..64dc1ce6b60ed 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -1,7 +1,7 @@ name: Push on: push: - paths-ignore: + paths-ignore: &ignore_paths - docs/** - NEWS - UPGRADING @@ -16,18 +16,10 @@ on: - PHP-8.2 - PHP-8.3 - PHP-8.4 + - PHP-8.5 - master pull_request: - paths-ignore: - - docs/** - - NEWS - - UPGRADING - - UPGRADING.INTERNALS - - '**/README.*' - - CONTRIBUTING.md - - CODING_STANDARDS.md - - .cirrus.yml - - .circleci/** + paths-ignore: *ignore_paths branches: - '**' workflow_dispatch: ~ @@ -40,6 +32,47 @@ env: CC: ccache gcc CXX: ccache g++ jobs: + ALPINE: + if: github.repository == 'php/php-src' || github.event_name == 'pull_request' + name: ALPINE_X64_ASAN_UBSAN_DEBUG_ZTS + runs-on: ubuntu-24.04 + container: + image: 'alpine:3.22' + steps: + - name: git checkout + uses: actions/checkout@v6 + - name: apk + uses: ./.github/actions/apk + - name: System info + run: | + echo "::group::Show host CPU info" + lscpu + echo "::endgroup::" + echo "::group::Show installed package versions" + apk list + echo "::endgroup::" + - name: ./configure + uses: ./.github/actions/configure-alpine + with: + configurationParameters: >- + CFLAGS="-fsanitize=undefined,address -fno-sanitize=function -DZEND_TRACK_ARENA_ALLOC" + LDFLAGS="-fsanitize=undefined,address -fno-sanitize=function" + CC=clang-20 + CXX=clang++-20 + --enable-debug + --enable-zts + skipSlow: true # FIXME: This should likely include slow extensions + - name: make + run: make -j$(/usr/bin/nproc) >/dev/null + - name: make install + uses: ./.github/actions/install-alpine + - name: Test Tracing JIT + uses: ./.github/actions/test-alpine + with: + jitType: tracing + runTestsParameters: >- + --asan -x + -d opcache.enable_cli=1 LINUX_X64: if: github.repository == 'php/php-src' || github.event_name == 'pull_request' services: @@ -82,7 +115,7 @@ jobs: timeout-minutes: 50 steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: apt uses: ./.github/actions/apt-x64 - name: System info @@ -112,6 +145,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 +164,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 +200,7 @@ jobs: FIREBIRD_PASSWORD: test steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: apt uses: ./.github/actions/apt-x32 - name: ccache @@ -175,6 +208,7 @@ jobs: with: key: "${{github.job}}-${{hashFiles('main/php_version.h')}}" append-timestamp: false + save: ${{ github.event_name != 'pull_request' }} - name: ./configure uses: ./.github/actions/configure-x32 with: @@ -190,7 +224,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 +231,16 @@ 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@v6 + - name: Update clang + uses: ./.github/actions/macos-update-clang - name: brew uses: ./.github/actions/brew - name: ccache @@ -229,7 +264,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 @@ -242,7 +276,7 @@ jobs: PHP_BUILD_CACHE_BASE_DIR: C:\build-cache 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_SDK_BRANCH: php-sdk-2.5.0 PHP_BUILD_CRT: vs17 PLATFORM: x64 THREAD_SAFE: "1" @@ -253,7 +287,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@v6 - name: Setup uses: ./.github/actions/setup-windows - name: Build @@ -267,7 +301,7 @@ jobs: timeout-minutes: 50 steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: fetch-depth: 0 # ASLR can cause a lot of noise due to missed sse opportunities for memcpy @@ -299,7 +333,6 @@ jobs: ./configure \ --disable-debug \ --enable-mbstring \ - --enable-opcache \ --enable-option-checking=fatal \ --enable-sockets \ --enable-werror \ @@ -319,7 +352,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 +363,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@v6 with: repository: php/benchmarking-data ssh-key: ${{ secrets.BENCHMARKING_DATA_DEPLOY_KEY }} @@ -362,7 +394,7 @@ jobs: ${{ github.sha }} \ $(git merge-base ${{ github.event.pull_request.base.sha }} ${{ github.sha }}) \ > $GITHUB_STEP_SUMMARY - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v6 with: name: profiles path: ${{ github.workspace }}/benchmark/profiles @@ -371,8 +403,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@v6 - name: FreeBSD uses: ./.github/actions/freebsd diff --git a/.github/workflows/real-time-benchmark.yml b/.github/workflows/real-time-benchmark.yml index 9e1fa9fdbe6a2..9276539841e72 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@v6 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@v6 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@v6 + 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@v6 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@v6 + 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 96943a8cfb2aa..123ccc17c611d 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -13,14 +13,14 @@ jobs: outputs: branches: ${{ steps.set-matrix.outputs.branches }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: # Set fetch-depth to 0 to clone the full repository # including all branches. This is required to find # the correct commit hashes. fetch-depth: 0 - name: Grab the commit mapping - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: branch-commit-cache.json # The cache key needs to change every time for the @@ -31,11 +31,6 @@ jobs: - name: Generate Matrix id: set-matrix run: php .github/nightly_matrix.php "${{ github.event_name }}" "${{ github.run_attempt }}" "${{ github.head_ref || github.ref_name }}" - - name: Notify Slack - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} NIGHTLY: needs: GENERATE_MATRIX name: ${{ matrix.branch.ref }} @@ -52,6 +47,7 @@ jobs: branch: ${{ matrix.branch.ref }} community_verify_type_inference: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} libmysqlclient_with_mysqli: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] == 1) }} + macos_arm64_version: ${{ ((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 5) || matrix.branch.version[0] >= 9) && '15' || '14' }} 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 }} @@ -62,6 +58,7 @@ jobs: 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 }} + symfony_version: ${{ (((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9) && '8.1') || '7.4' }} 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/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml new file mode 100644 index 0000000000000..6338a1cb945db --- /dev/null +++ b/.github/workflows/unit-tests.yml @@ -0,0 +1,75 @@ +name: Unit Tests +on: + push: + paths: + - 'main/network.c' + - 'tests/unit/**' + - '.github/workflows/unit-tests.yml' + branches: + - master + pull_request: + paths: + - 'main/network.c' + - 'tests/unit/**' + - '.github/workflows/unit-tests.yml' + branches: + - '**' + workflow_dispatch: ~ + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.url || github.run_id }} + cancel-in-progress: true + +env: + CC: ccache gcc + CXX: ccache g++ + +jobs: + UNIT_TESTS: + if: github.repository == 'php/php-src' || github.event_name == 'pull_request' + name: UNIT_TESTS_LINUX_X64 + runs-on: ubuntu-24.04 + timeout-minutes: 20 + steps: + - name: git checkout + uses: actions/checkout@v6 + + - name: Install dependencies + run: | + set -x + sudo apt-get update + sudo apt-get install -y \ + libcmocka-dev \ + autoconf \ + gcc \ + make \ + unzip \ + bison \ + re2c \ + locales \ + ccache + + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: "unit-tests-${{hashFiles('main/php_version.h')}}" + append-timestamp: false + save: ${{ github.event_name != 'pull_request' }} + + - name: ./configure (minimal build) + uses: ./.github/actions/configure-unit-tests + + - name: make libphp.a + run: | + set -x + make -j$(/usr/bin/nproc) >/dev/null + + - name: Run unit tests + run: | + set -x + cd tests/unit + make test + diff --git a/.github/workflows/verify-bundled-files.yml b/.github/workflows/verify-bundled-files.yml new file mode 100644 index 0000000000000..6cce1a14cf7f3 --- /dev/null +++ b/.github/workflows/verify-bundled-files.yml @@ -0,0 +1,43 @@ +name: Verify Bundled Files + +on: + push: + paths: &paths + - '.github/scripts/download-bundled/pcre2.sh' + - 'ext/pcre/pcre2lib/**' + pull_request: + paths: *paths + schedule: + - cron: "0 1 * * *" + workflow_dispatch: ~ + +permissions: + contents: read + +jobs: + VERIFY_BUNDLED_FILES: + name: Verify Bundled Files + runs-on: ubuntu-24.04 + steps: + - name: git checkout + uses: actions/checkout@v6 + + - name: Detect changed files + uses: dorny/paths-filter@v3 + id: changes + with: + base: master + filters: | + pcre2: + - '.github/scripts/download-bundled/pcre2.sh' + - 'ext/pcre/pcre2lib/**' + + - name: PCRE2 + if: ${{ !cancelled() && (steps.changes.outputs.pcre2 == 'true' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') }} + run: | + echo "::group::Download" + .github/scripts/download-bundled/pcre2.sh + echo "::endgroup::" + echo "::group::Verify files" + .github/scripts/test-directory-unchanged.sh ext/pcre/pcre2lib + echo "::endgroup::" diff --git a/.gitignore b/.gitignore index 1e92e88fb77fa..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 diff --git a/CODING_STANDARDS.md b/CODING_STANDARDS.md index c599194ed50e3..47b76717c8391 100644 --- a/CODING_STANDARDS.md +++ b/CODING_STANDARDS.md @@ -276,7 +276,7 @@ rewritten to comply with these rules. 1. The length of constant string literals should be calculated via ``strlen()`` instead of using ``sizeof()-1`` as it is clearer and any modern compiler - will optimize it away. Legacy usages of the latter style exists within the + will optimize it away. Legacy usages of the latter style exist within the codebase but should not be refactored, unless larger refactoring around that code is taking place. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a91545fa9bd79..32e8098c08e48 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 @@ -99,6 +100,7 @@ scattered across different websites, and often outdated. Nonetheless, they can provide a good starting point for learning about the fundamentals of the code base. +* https://php.github.io/php-src/ * https://www.phpinternalsbook.com/ * https://www.npopov.com/ * [Internal value representation](https://www.npopov.com/2015/05/05/Internal-value-representation-in-PHP-7-part-1.html), [part 2](https://www.npopov.com/2015/06/19/Internal-value-representation-in-PHP-7-part-2.html) @@ -356,7 +358,8 @@ Currently, we have the following branches in use: | Branch | | | --------- | --------- | -| master | Active development branch for PHP 8.5, which is open for backwards incompatible changes and major internal API changes. | +| master | Active development branch for PHP 8.6, which is open for backwards incompatible changes and major internal API changes. | +| PHP-8.5 | Is used to release the PHP 8.5.x series. This is a current stable version and is open for bugfixes only. | | PHP-8.4 | Is used to release the PHP 8.4.x series. This is a current stable version and is open for bugfixes only. | | PHP-8.3 | Is used to release the PHP 8.3.x series. This is a current stable version and is open for bugfixes only. | | PHP-8.2 | Is used to release the PHP 8.2.x series. This is an old stable version and is open for security fixes only. | @@ -385,11 +388,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 +422,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 +452,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 01685748b5e09..f040afcced6e9 100644 --- a/EXTENSIONS +++ b/EXTENSIONS @@ -495,6 +495,7 @@ EXTENSION: tidy PRIMARY MAINTAINER: John Coggeshall (2003 - 2006) Ilia Alshanetsky (2003 - 2009) Nuno Lopes (2006 - 2012) + Niels Dossche (2025 - 2025) MAINTENANCE: Maintained STATUS: Working ------------------------------------------------------------------------------- @@ -506,6 +507,7 @@ STATUS: Working ------------------------------------------------------------------------------- EXTENSION: uri PRIMARY MAINTAINER Máté Kocsis (2025 - 2025) + Tim Düsterhus (2025 - 2025) MAINTENANCE: Maintained STATUS: Working SINCE: 8.5.0 diff --git a/LICENSE b/LICENSE index 0815d7eb79119..b155a18c2fb73 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ -------------------------------------------------------------------- The PHP License, version 3.01 -Copyright (c) 1999 - 2024 The PHP Group. All rights reserved. +Copyright (c) 1999 - 2025 The PHP Group. All rights reserved. -------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without diff --git a/NEWS b/NEWS index 0c925ea0b1179..12740c65c3c89 100644 --- a/NEWS +++ b/NEWS @@ -1,351 +1,87 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.5.0alpha3 - -- Curl: - . Add support for CURLINFO_CONN_ID in curl_getinfo() (thecaliskan) - . Add support for CURLINFO_QUEUE_TIME_T in curl_getinfo() (thecaliskan) - -- Sockets: - . socket_set_option for multicast context throws a ValueError - when the socket family is not of AF_INET/AF_INET6 family. (David Carlier) - -- 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) - -17 Jul 2025, PHP 8.5.0alpha2 +?? ??? ????, PHP 8.6.0alpha1 - 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) + . Added first-class callable cache to share instances for the duration of the + request. (ilutov) + . It is now possible to use reference assign on WeakMap without the key + needing to be present beforehand. (ndossche) + . Added `clamp()`. (kylekatarnls, thinkverse) -- 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) - . If the result is 0, n_scale is set to 0. (SakiTakamachi) - . If size of BC_VECTOR array is within 64 bytes, stack area is now used. - (SakiTakamachi) - -- CLI: - . Add --ini=diff to print INI settings changed from the builtin default. - (timwolla) - . Drop support for -z CLI/CGI flag. (nielsdos) - . Fixed GH-17956 - development server 404 page does not adapt to mobiles. - (pascalchevrel) - -- CURL: - . Added CURLFOLLOW_ALL, CURLFOLLOW_OBEYCODE and CURLFOLLOW_FIRSTONLY - values for CURLOPT_FOLLOLOCATION curl_easy_setopt option. (David Carlier) - -- COM: - . Fixed property access of PHP objects wrapped in variant. (cmb) - . Fixed method calls for PHP objects wrapped in variant. (cmb) - -- Core: - . Fixed bug GH-16665 (\array and \callable should not be usable in - class_alias). (nielsdos) - . Added PHP_BUILD_DATE constant. (cmb) - . Added support for Closures and first class callables in constant - expressions. (timwolla, Volker Dusch) - . Use `clock_gettime_nsec_np()` for high resolution timer on macOS - if available. (timwolla) - . Implement GH-15680 (Enhance zend_dump_op_array to properly represent - non-printable characters in string literals). (nielsdos, WangYihang) - . Add support for backtraces for fatal errors. (enorris) - . Fixed bug GH-17442 (Engine UAF with reference assign and dtor). (nielsdos) - . Improved error message of UnhandledMatchError for - zend.exception_string_param_max_len=0. (timwolla) - . Fixed bug GH-17959 (Relax missing trait fatal error to error exception). - (ilutov) - . Fixed bug GH-18033 (NULL-ptr dereference when using register_tick_function - in destructor). (nielsdos) - . Fixed bug GH-18026 (Improve "expecting token" error for ampersand). (ilutov) - . Added the #[\NoDiscard] attribute to indicate that a function's return - value is important and should be consumed. (timwolla, Volker Dusch) - . Added the (void) cast to indicate that not using a value is intentional. - (timwolla, Volker Dusch) - . Added get_error_handler(), get_exception_handler() functions. (Arnaud) - . Fixed bug GH-15753 and GH-16198 (Bind traits before parent class). (ilutov) - . Added support for casts in constant expressions. (nielsdos) - . Fixed bugs GH-17711 and GH-18022 (Infinite recursion on deprecated attribute - evaluation) and GH-18464 (Recursion protection for deprecation constants not - released on bailout). (DanielEScherzer and ilutov) - . Fixed AST printing for immediately invoked Closure. (Dmitrii Derepko) - . Properly handle __debugInfo() returning an array reference. (nielsdos) - . Properly handle reference return value from __toString(). (nielsdos) - . Added the pipe (|>) operator. (crell) - . 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) - . Fixed bug GH-19081 (Wrong lineno in property error with constructor property - promotion). (ilutov) - -- Curl: - . Added curl_multi_get_handles(). (timwolla) - . Added curl_share_init_persistent(). (enorris) - . Added CURLINFO_USED_PROXY, CURLINFO_HTTPAUTH_USED, and CURLINFO_PROXYAUTH_USED - support to curl_getinfo. (Ayesh Karunaratne) - -- Date: - . Fix undefined behaviour problems regarding integer overflow in extreme edge - cases. (nielsdos, cmb, ilutov) - -- 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) - . Added enchant_dict_remove(). (nielsdos) - . Fix missing empty string checks. (nielsdos) - -- EXIF: - . Add OffsetTime* Exif tags. (acc987) - -- Fileinfo: - . Upgrade to file 5.46. (nielsdos) - . Change return type of finfo_close() to true. (timwolla) - -- FPM: - . Fixed GH-17645 (FPM with httpd ProxyPass does not decode script path). - (Jakub Zelenka) - -- GD: - . Fixed bug #68629 (Transparent artifacts when using imagerotate). (pierre, - cmb) - . Fixed bug #64823 (ZTS GD fails to to find system TrueType font). (cmb) +- Hash: + . Upgrade xxHash to 0.8.2. (timwolla) - Intl: - . Bumped ICU requirement to ICU >= 57.1. (cmb) - . IntlDateFormatter::setTimeZone()/datefmt_set_timezone() throws an exception - with uninitialised classes or clone failure. (David Carlier) - . Added DECIMAL_COMPACT_SHORT/DECIMAL_COMPACT_LONG for NumberFormatter class. + . Added IntlNumberRangeFormatter class to format an interval of two numbers + with a given skeleton, locale, collapse type and identity fallback. (BogdanUngureanu) - . Added Locale::isRightToLeft to check if a locale is written right to left. - (David Carlier) - . Added null bytes presence in locale inputs for Locale class. (David Carlier) - . 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) - . Fixed bug GH-18566 ([intl] Weird numeric sort in Collator). (nielsdos) + . Fixed bug GH-20426 (Spoofchecker::setRestrictionLevel() error message + suggests missing constants). (DanielEScherzer) -- LDAP: - . Allow ldap_get_option to retrieve global option by allowing NULL for - connection instance ($ldap). (Remi) +- Mbstring + . Fixed bug GH-20674 (Fix GH-20674 mb_decode_mimeheader does not handle + separator). (Yuya Hamada) -- MySQLi: - . Fixed bugs GH-17900 and GH-8084 (calling mysqli::__construct twice). - (nielsdos) +- Fibers: + . Fixed bug GH-20483 (ASAN stack overflow with fiber.stack_size INI + small value). (David Carlier) -- MySQLnd: - . Added mysqlnd.collect_memory_statistics to ini quick reference. - (hauk92) +- Mbstring: + . ini_set() with mbstring.detect_order changes the order of mb_detect_order + as intended, since mbstring.detect_order is an INI_ALL setting. (tobee94) + . Added GB18030-2022 to default encoding list for zh-CN. (HeRaNO) + . Fixed bug GH-20674 (Fix GH-20674 mb_decode_mimeheader does not handle + separator). (Yuya Hamada) - Opcache: - . Fixed ZTS OPcache build on Cygwin. (cmb) - . Added opcache.file_cache_read_only. (Samuel Melrose) - . Updated default value of opcache.jit_hot_loop. (Arnaud) - . 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 verious parts of the extension to use the custom libctx. - (Jakub Zelenka) - -- Output: - . Fixed calculation of aligned buffer size. (cmb) - -- PCNTL: - . Extend pcntl_waitid with rusage parameter. (vrza) - -- PCRE: - . Upgraded to pre2lib from 10.44 to 10.45. (nielsdos) - . Remove PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK from pcre compile options. - (mvorisek) + . Fixed bug GH-20051 (apache2 shutdowns when restart is requested during + preloading). (Arnaud, welcomycozyhom) - PDO_PGSQL: - . Added Iterable support for PDO::pgsqlCopyFromArray. (KentarouTakeda) - . Implement GH-15387 Pdo\Pgsql::setAttribute(PDO::ATTR_PREFETCH, 0) or - Pdo\Pgsql::prepare(…, [ PDO::ATTR_PREFETCH => 0 ]) make fetch() lazy - instead of storing the whole result set in memory (Guillaume Outters) - -- PDO_SQLITE: - . throw on null bytes / resolve GH-13952 (divinity76). - . Implement GH-17321: Add setAuthorizer to Pdo\Sqlite. (nielsdos) - . PDO::sqliteCreateCollation now throws a TypeError if the callback - has a wrong return type. (David Carlier) - . Added Pdo_Sqlite::ATTR_BUSY_STATEMENT constant to check - if a statement is currently executing. (David Carlier) - . Added Pdo_Sqlite::ATTR_EXPLAIN_STATEMENT constant to set a statement - in either EXPLAIN_MODE_PREPARED, EXPLAIN_MODE_EXPLAIN, - EXPLAIN_MODE_EXPLAIN_QUERY_PLAN modes. (David Carlier) - -- PGSQL: - . Added pg_close_stmt to close a prepared statement while allowing - its name to be reused. (David Carlier) - . Added Iterable support for pgsql_copy_from. (David Carlier) - . pg_connect checks if connection_string contains any null byte, - pg_close_stmt check if the statement contains any null byte. - (David Carlier) - . Added pg_service to get the connection current service identifier. - (David Carlier) - -- POSIX: - . Added POSIX_SC_OPEN_MAX constant to get the number of file descriptors - a process can handle. (David Carlier) - . posix_ttyname() sets last_error to EBADF on invalid file descriptors, - posix_isatty() raises E_WARNING on invalid file descriptors, - posix_fpathconf checks invalid file descriptors. (David Carlier) + . Clear session-local state disconnect-equivalent processing. + (KentarouTakeda) -- Random: - . Moves from /dev/urandom usage to arc4random_buf on Haiku. (David Carlier) +- Phar: + . Support reference values in Phar::mungServer(). (ndossche) + . Invalid values now throw in Phar::mungServer() instead of being silently + ignored. (ndossche) + . Support overridden methods in SplFileInfo for getMTime() and getPathname() + when building a phar. (ndossche) - Reflection: - . Added ReflectionConstant::getExtension() and ::getExtensionName(). - (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 - for enums). (DanielEScherzer) - -- Session: - . session_start() throws a ValueError on option argument if not a hashmap - or a TypeError if read_and_close value is not compatible with int. - (David Carlier) + . Fixed bug GH-20217 (ReflectionClass::isIterable() incorrectly returns true + for classes with property hooks). (alexandre-daubois) -- SimpleXML: - . Fixed bug GH-12231 (SimpleXML xpath should warn when returning other return - types than node lists). (nielsdos) - -- SNMP: - . snmpget, snmpset, snmp_get2, snmp_set2, snmp_get3, snmp_set3 and - SNMP::__construct() throw an exception on invalid hostname, community - timeout and retries arguments. (David Carlier) - -- SOAP: - . Fixed bug #49169 (SoapServer calls wrong function, although "SOAP action" - header is correct). (nielsdos) - . Fix namespace handling of WSDL and XML schema in SOAP, - fixing at least GH-16320 and bug #68576. (nielsdos) - . Fixed bug #70951 (Segmentation fault on invalid WSDL cache). (nielsdos) - . Implement request #55503 (Extend __getTypes to support enumerations). - (nielsdos, datibbaw) - . Implement request #61105 (Support Soap 1.2 SoapFault Reason Text lang - attribute). (nielsdos) +- Soap: + . Soap::__setCookie() when cookie name is a digit is now not stored and represented + as a string anymore but a int. (David Carlier) - Sockets: - . Added IPPROTO_ICMP/IPPROTO_ICMPV6 to create raw socket for ICMP usage. - (David Carlier) - . Added TCP_FUNCTION_BLK to change the TCP stack algorithm on FreeBSD. - (David Carlier) - . socket_set_option() catches possible overflow with SO_RCVTIMEO/SO_SNDTIMEO - with timeout setting on windows. (David Carlier) - . Added TCP_FUNCTION_ALIAS, TCP_REUSPORT_LB_NUMA, TCP_REUSPORT_LB_NUMA_NODOM, - TCP_REUSPORT_LB_CURDOM, TCP_BBR_ALGORITHM constants. - . socket_create_listen() throws an exception on invalid port value. - (David Carlier) - . socket_bind() throws an exception on invalid port value. - (David Carlier) - . socket_sendto() throws an exception on invalid port value. - (David Carlier) - . socket_addrinfo_lookup throws an exception on invalid hints value types. - (David Carlier) - . socket_addrinfo_lookup throws an exception if any of the hints value - overflows. (David Carlier) - . socket_addrinfo_lookup throws an exception if one or more hints entries - has an index as numeric. (David Carlier) - . socket_set_option with the options MCAST_LEAVE_GROUP/MCAST_LEAVE_SOURCE_GROUP - will throw an exception if its value is not a valid array/object. - (David Carlier) - . socket_getsockname/socket_create/socket_bind handled AF_PACKET family socket. - (David Carlier) - . Added IP_BINDANY for a socket to bind to any address. (David Carlier) - . Added SO_BUSY_POOL to reduce packets poll latency. (David Carlier) - - Added UDP_SEGMENT support to optimise multiple large datagrams over UDP - if the kernel and hardware supports it. (David Carlier) - - Added SHUT_RD, SHUT_WR and SHUT_RDWR constants for socket_shutdown(). - (David Carlier) + . Added the TCP_USER_TIMEOUT constant for Linux to set the maximum time in milliseconds + transmitted data can remain unacknowledged. (James Lucas) -- Sodium: - . Fix overall theorical overflows on zend_string buffer allocations. - (David Carlier/nielsdos) +- SPL: + . DirectoryIterator key can now work better with filesystem supporting larger + directory indexing. (David Carlier) -- Sqlite: - . Added Sqlite3Stmt::busy to check if a statement is still being executed. - (David Carlier) - . Added Sqlite3Stmt::explain to produce a explain query plan from - the statement. (David Carlier) - . Added Sqlite3Result::fetchAll to returns all results at once from a query. - (David Carlier) +- Sqlite3: + . Fix NUL byte truncation in sqlite3 TEXT column handling. (ndossche) - Standard: - . Fixed crypt() tests on musl when using --with-external-libcrypt - (Michael Orlitzky). - . Fixed bug GH-18062 (is_callable(func(...), callable_name: $name) for first - class callables returns wrong name). (timwolla) - . Added array_first() and array_last(). (nielsdos) - . Fixed bug GH-18823 (setlocale's 2nd and 3rd argument ignores strict_types). - (nielsdos) - . Fixed exit code handling of sendmail cmd and added warnings. - (Jesse Hathaway) - . Fixed bug GH-18897 (printf: empty precision is interpreted as precision 6, - not as precision 0). (nielsdos) + . Fixed bug GH-19926 (reset internal pointer earlier while splicing array + while COW violation flag is still set). (alexandre-daubois) - Streams: - . Fixed bug GH-16889 (stream_select() timeout useless for pipes on Windows). - (cmb) - -- Tests: - . Allow to shuffle tests even in non-parallell mode. (dhuang00) - -- Tidy: - . tidy::__construct/parseFile/parseString methods throw an exception if - the configuration argument is invalid. (David Carlier) - -- Windows: - . Fixed bug GH-10992 (Improper long path support for relative paths). (cmb, - nielsdos) - . Fixed bug GH-16843 (Windows phpize builds ignore source subfolders). (cmb) - -- XMLWriter: - . Improved performance and reduce memory consumption. (nielsdos) - -- XSL: - . Implement request #30622 (make $namespace parameter functional). (nielsdos) - -- Zlib: - . gzfile, gzopen and readgzfile, their "use_include_path" argument - is now a boolean. (David Carlier) - . Fixed bug GH-16883 (gzopen() does not use the default stream context when - opening HTTP URLs). (nielsdos) - . Implemented GH-17668 (zlib streams should support locking). (nielsdos) + . Added so_reuseaddr streams context socket option that allows disabling + address resuse. + . Fixed bug GH-20370 (User stream filters could violate typed property + constraints). (alexandre-daubois) +- Zip: + . Fixed ZipArchive callback being called after executor has shut down. + (ilutov) + . Support minimum version for libzip dependency updated to 1.0.0. + (David Carlier) <<< NOTE: Insert NEWS from last stable release here prior to actual release! >>> diff --git a/README.md b/README.md index 39c6b89fbbd74..5b8ec6f0d7dc0 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ sudo dnf install re2c bison autoconf make libtool ccache libxml2-devel sqlite-de On MacOS, you can install these using `brew`: ```shell -brew install autoconf bison re2c iconv libxml2 sqlite +brew install autoconf bison re2c libiconv libxml2 sqlite ``` or with `MacPorts`: diff --git a/UPGRADING b/UPGRADING index dba8d29755c96..d52827bf96154 100644 --- a/UPGRADING +++ b/UPGRADING @@ -1,4 +1,4 @@ -PHP 8.5 UPGRADE NOTES +PHP 8.6 UPGRADE NOTES 1. Backward Incompatible Changes 2. New Features @@ -19,467 +19,66 @@ 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(). - . Loosely comparing uncomparable objects (e.g. enums, \CurlHandle and other - internal classes) to booleans was previously inconsistent. If compared to a - boolean literal $object == true, it would behave the same way as (bool) - $object. If compared to a statically unknown value $object == $true, it - would always return false. This behavior was consolidated to always follow - the behavior of (bool) $object. - . The return value of gc_collect_cycles() no longer includes strings and - resources that were indirectly collected through cycles. - . It is now allowed to substitute static with self or the concrete class name - in final subclasses. - . The tick handlers are now deactivated after all shutdown functions, destructors - have run and the output handlers have been cleaned up. - This is a consequence of fixing GH-18033. - . 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. - -- 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 - TypeError when $filename contains nul bytes. - This aligns the type of Error thrown to be consistent with the rest of - the language. - -- Intl: - . The extension now requires at least ICU 57.1. - . The behaviour of Collator::SORT_REGULAR with respect to handling numeric - strings is now aligned with the behaviour of SORT_REGULAR in ext/standard. - This is a consequence of fixing bug GH-18566. - -- LDAP: - . ldap_get_option() and ldap_set_option() now throw a ValueError when - passing an invalid option. - -- MySQLi: - . Calling the mysqli constructor on an already-constructed object - is now no longer possible and throws an Error. - -- PCNTL: - . pcntl_exec() now throws ValueErrors when entries of the $args parameter - contain null bytes. - . pcntl_exec() now throws ValueErrors when entries or keys of the - $env_vars parameter contain null bytes. - -- PCRE: - . The extension is compiled without semi-deprecated - PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK compile option. - https://github.com/PCRE2Project/pcre2/issues/736#issuecomment-2754024651 - -- PDO: - . The constructor arguments set in conjunction with PDO::FETCH_CLASS now - follow the usual CUFA (call_user_func_array) semantics. - This means string keys will act like a named argument. - Moreover, automatic wrapping for by-value arguments passed to a by-ref - parameter has been removed, and the usual E_WARNING about this is now - emitted. - To pass a variable by-ref to a constructor argument use the general - array value reference assignment: $ctor_args = [&$valByRef] - . Attempting to call PDOStatement::setFetchMode during a call to PDO::fetch(), - PDO::fetchObject(), PDO::fetchAll(), - for example using tricks such as passing the statement object as a constructor - argument when fetching into an object, will now throw an Error. - . The value of the constants PDO::FETCH_GROUP, PDO::FETCH_UNIQUE, - PDO::FETCH_CLASSTYPE, PDO::FETCH_PROPS_LATE, and PDO::FETCH_SERIALIZE - have changed. - . A ValueError is now thrown if PDO::FETCH_PROPS_LATE is used with a fetch - mode different than PDO::FETCH_CLASS, consistent with other fetch flags. - . A ValueError is now thrown if PDO::FETCH_INTO is used as a fetch mode in - PDO::fetchAll(), similar to PDO::FETCH_LAZY. - -- PDO_FIREBIRD: - . A ValueError is now thrown when trying to set a cursor name that is too - long on a PDOStatement resulting from the Firebird driver. - -- Session: - . Attempting to write session data where $_SESSION has a key containing - the pipe character will now emit a warning instead of silently failing. - -- SimpleXML: - . Passing an XPath expression that returns something other than a node set - to SimpleXMLElement::xpath() will now emit a warning and return false, - instead of silently failing and returning an empty array. - -- SPL: - . ArrayObject no longer accepts enums, as modifying the $name or $value - properties can break engine assumptions. - . SplFileObject::fwrite's parameter $length is now nullable. The default - value changed from 0 to null. - -- Standard: - . Using a printf-family function with a formatter that did not specify the - precision previously incorrectly reset the precision instead of treating - it as a precision of 0. See GH-18897. +- Phar: + . Invalid values now throw in Phar::mungServer() instead of being silently + ignored. ======================================== 2. New Features ======================================== - Core: - . Closure is now a proper subtype of callable - . Added support for Closures and first class callables in constant - expressions. - RFC: https://wiki.php.net/rfc/closures_in_const_expr - RFC: https://wiki.php.net/rfc/fcc_in_const_expr - . Fatal Errors (such as an exceeded maximum execution time) now include a - backtrace. - RFC: https://wiki.php.net/rfc/error_backtraces_v2 - . Added the #[\NoDiscard] attribute to indicate that a function's return - value is important and should be consumed. - RFC: https://wiki.php.net/rfc/marking_return_value_as_important - . Added the (void) cast to indicate that not using a value is intentional. - The (void) cast has no effect on the program's execution by itself, but - it can be used to suppress warnings emitted by #[\NoDiscard] and possibly - also diagnostics emitted by external IDEs or static analysis tools. - RFC: https://wiki.php.net/rfc/marking_return_value_as_important - . Added asymmetric visibility support for static properties. - RFC: https://wiki.php.net/rfc/static-aviz - . Added support for casts in constant expressions. - . Added support for attributes on compile-time non-class constants. - RFC: https://wiki.php.net/rfc/attributes-on-constants - . The #[\Deprecated] attribute can now be used on constants. - RFC: https://wiki.php.net/rfc/attributes-on-constants - . Added the pipe (|>) operator. - 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 - -- Curl: - . Added support for share handles that are persisted across multiple PHP - requests, safely allowing for more effective connection reuse. - RFC: https://wiki.php.net/rfc/curl_share_persistence_improvement - . Added support for CURLINFO_USED_PROXY (libcurl >= 8.7.0), - CURLINFO_HTTPAUTH_USED, and CURLINFO_PROXYAUTH_USED - (libcurl >= 8.12.0) to the curl_getinfo() function. - When curl_getinfo() returns an array, the same information - is available as "used_proxy", "httpauth_used", and "proxyauth_used" - keys. - CURLINFO_USED_PROXY gets zero set if no proxy was used in the - previous transfer or a non-zero value if a proxy was used. - CURLINFO_HTTPAUTH_USED and CURLINFO_PROXYAUTH_USED get bitmasks - indicating the HTTP and proxy authentication methods that were - used in the previous request. See CURLAUTH_* constants for - possible values. - . Added CURLOPT_INFILESIZE_LARGE Curl option, which is a safe - replacement for CURLOPT_INFILESIZE. On certain systems, - CURLOPT_INFILESIZE only accepts a 32-bit signed integer as the file - size (2.0 GiB) even on 64-bit systems. CURLOPT_INFILESIZE_LARGE - accepts the largest integer value the system can handle. - . Added CURLFOLLOW_OBEYCODE, CURLFOLLOW_FIRSTONLY and CURLFOLLOW_ALL values for - CURLOPT_FOLLOWLOCATION curl_easy_setopt option. - CURLFOLLOW_OBEYCODE to follow more strictly in regard to redirect - if they are allowed. CURLFOLLOW_FIRSTONLY to follow only the - 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. - -- DOM: - . Added Dom\Element::$outerHTML. - . Added $children property to Dom\ParentNode implementations. - -- EXIF: - . Add OffsetTime* Exif tags. + . It is now possible to use reference assign on WeakMap without the key + needing to be present beforehand. - Intl: - . Added class constants NumberFormatter::CURRENCY_ISO, - NumberFormatter::CURRENCY_PLURAL, NumberFormatter::CASH_CURRENCY, - and NumberFormatter::CURRENCY_STANDARD for various currency-related - number formats. - . Added Locale::addLikelySubtags and Locale::minimizeSubtags to - handle likely tags on a given locale. - . Added IntlListFormatter class to format, order, and punctuate - a list of items with a given locale, IntlListFormatter::TYPE_AND, - IntlListFormatter::TYPE_OR, IntlListFormatter::TYPE_UNITS operands and - IntlListFormatter::WIDTH_WIDE, IntlListFormatter::WIDTH_SHORT and - IntlListFormatter::WIDTH_NARROW widths. - It is supported from icu 67. - -- PDO_Sqlite: - . Added class constant Pdo_Sqlite::ATTR_BUSY_STATEMENT. - . 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. - -- SOAP: - . Enumeration cases are now dumped in __getTypes(). - . Implemented request #61105: - support for Soap 1.2 Reason Text xml:lang attribute. - The signature of SoapFault::__construct() and SoapServer::fault() therefore - now have an optional $lang parameter. - This support solves compatibility with .NET SOAP clients. - -- Sqlite: - . Added class constants Sqlite3Stmt::EXPLAIN_MODE_PREPARED, - Sqlite3Stmt::EXPLAIN_MODE_EXPLAIN and - Sqlite3Stmt::EXPLAIN_MODE_EXPLAIN_QUERY_PLAN. + . Added IntlNumberRangeFormatter class to format an interval of two numbers with a given skeleton, locale, IntlNumberRangeFormatter::COLLAPSE_AUTO, IntlNumberRangeFormatter::COLLAPSE_NONE, IntlNumberRangeFormatter::COLLAPSE_UNIT, IntlNumberRangeFormatter::COLLAPSE_ALL collapse and + IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE, IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE, IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY and + IntlNumberRangeFormatter::IDENTITY_FALLBACK_RANGE identity fallbacks. + It is supported from icu 63. -- Standard: - . mail() now returns the actual sendmail error and detects if the sendmail - 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. - -- XSL: - . The $namespace argument of XSLTProcessor::getParameter(), - XSLTProcessor::setParameter() and XSLTProcessor::removeParameter() - now actually works instead of being treated as empty. - This only works if the $name argument does not use Clark notation - and is not a QName because in those cases the namespace is taken - from the namespace href or prefix respectively. - -- Zlib: - . flock() is now supported on zlib streams. Previously, this always - failed to perform any locking action. +- Phar: + . Overriding the getMTime() and getPathname() methods of SplFileInfo now + influences the result of the phar buildFrom family of functions. + This makes it possible to override the timestamp and names of files. + +- Streams: + . Added stream socket context option so_reuseaddr that allows disabling + address reuse (SO_REUSEADDR) and explicitly uses SO_EXCLUSIVEADDRUSE on + Windows. ======================================== 3. Changes in SAPI modules ======================================== -- CLI: - . Trying to set a process title that is too long with cli_set_process_title() - will now fail instead of silently truncating the given title. - . Added a new --ini=diff option to print INI settings changed from the builtin - default. - -- FPM: - . FPM with httpd ProxyPass decodes the full script path. Added - fastcgi.script_path_encoded INI setting to prevent this new behavior. - ======================================== 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 - -- 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 - ======================================== 5. Changed Functions ======================================== -- Intl: - . IntlDateFormatter::setTimeZone()/datefmt_set_timezone() - throws an IntlException on uninitialised classes/clone failures. - . grapheme_extract() properly assigns $next value when skipping over - invalid starting bytes. Previously there were cases where it would - point to the start of the grapheme boundary instead of the end. - . Locale:: methods throw a ValueError when locale inputs contain null - bytes. - . transliterator_get_error_code(), transliterator_get_error_message() - TransLiterator::getErrorCode(), and TransLiterator::getErrorMessage() - have dropped the false from the return type union. Returning false - was actually never possible. - -- LDAP: - . ldap_get_option() now accepts a NULL connection, as ldap_set_option(), - to allow retrieval of global options. - -- libxml: - . libxml_set_external_entity_loader() now has a formal return type of true. - -- PCNTL: - . pcntl_exec() now has a formal return type of false. - . pcntl_waitid() takes an additional resource_usage argument to - gather various platform specific metrics about the child process. - -- PDO_PGSQL: - . PDO::pgsqlCopyFromArray also supports inputs as Iterable. - . Pdo\Pgsql::setAttribute and Pdo\Pgsql::prepare supports - PDO::ATTR_PREFETCH sets to 0 which set to lazy fetch mode. - In this mode, statements cannot be run in parallel. - -- PDO_SQLITE: - . SQLite PDO::quote() will now throw an exception or emit a warning, - depending on the error mode, if the string contains a null byte. - . PDO::sqliteCreateCollation will now throw an exception - if the callback has the wrong return type, making it more - in line with Pdo_Sqlite::createCollation behavior. - -- PGSQL: - . pg_copy_from also supports inputs as Iterable. - . pg_connect checks if the connection_string argument contains - any null byte. - . pg_close_stmt checks if the statement_name argument contains - any null byte. - -- POSIX: - . posix_ttyname sets last_error to EBADF when encountering - an invalid file descriptor. - . posix_isatty raises an E_WARNING message when encountering - an invalid file descriptor. - . posix_fpathconf checks invalid file descriptors and sets - last_error to EBADF and raises an E_WARNING message. - -- Reflection: - . 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. - -- 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 - compatible with int. - -- SNMP: - . snmpget, snmpset, snmp_get2, snmp_set2, snmp_get3, snmp_set3 - and SNMP::__construct() throw a ValueError when the hostname - is too large, contains any null byte or if the port is given - when negative or greater than 65535, timeout and retries values - are lower than -1 or too large. +- Phar: + . Phar::mungServer() now supports reference values. -- 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. - . 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. - . socket_set_option with MCAST_LEAVE_GROUP/MCAST_LEAVE_SOURCE_GROUP - options will throw an exception if the value isn't a valid object - or array. - . 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 - if the configuration contains an invalid or set a read-only - internal entry, a TypeError contains, at least, one element - when the key is not a string. - -- Zlib: - . The "use_include_path" argument for the - gzfile, gzopen and readgzfile functions had been changed - from int to boolean. - . gzfile, gzopen and readgzfile functions now respect the default - stream context. +- Zip: + . ZipArchive::extractTo now raises a TypeError for the + files argument if one or more of the entries is not + a string. ======================================== 6. New Functions ======================================== -- Core: - . get_error_handler() allows retrieving the current user-defined error handler - function. - RFC: https://wiki.php.net/rfc/get-error-exception-handler - . 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. - RFC: https://wiki.php.net/rfc/clone_with_v2 - -- Curl: - . curl_multi_get_handles() allows retrieving all CurlHandles current - attached to a CurlMultiHandle. This includes both handles added using - curl_multi_add_handle() and handles accepted by CURLMOPT_PUSHFUNCTION. - . curl_share_init_persistent() allows creating a share handle that is - persisted across multiple PHP requests. - RFC: https://wiki.php.net/rfc/curl_share_persistence_improvement - -- DOM: - . Added Dom\Element::getElementsByClassName(). - . Added Dom\Element::insertAdjacentHTML(). - -- Enchant: - . Added enchant_dict_remove_from_session() to remove a word added to the - spellcheck session via enchant_dict_add_to_session(). - . Added enchant_dict_remove() to put a word on the exclusion list and - remove it from the session dictionary. - -- Intl: - . Added locale_is_right_to_left/Locale::isRightToLeft, returns true if - the locale is written right to left (after its enrichment with likely subtags). - . 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 - pdo version returns void. - -- PGSQL: - . pg_close_stmt offers an alternative way to close a prepared - statement from the DEALLOCATE sql command in that we can reuse - its name afterwards. - . pg_service returns the ongoing service name of the connection. - -- Reflection: - . ReflectionConstant::getFileName() was introduced. - . ReflectionConstant::getExtension() and - ReflectionConstant::getExtensionName() were introduced. - . ReflectionConstant::getAttributes() was introduced. - RFC: https://wiki.php.net/rfc/attributes-on-constants - -- Sqlite: - . Sqlite3Stmt::busy to check if a statement had been fetched - but not completely. - - Standard: - . Added array_first() and array_last(). - RFC: https://wiki.php.net/rfc/array_first_last + . `clamp()` returns the given value if in range, else return the nearest bound. + RFC: https://wiki.php.net/rfc/clamp_v2 ======================================== 7. New Classes and Interfaces ======================================== -- 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 ======================================== @@ -488,202 +87,68 @@ PHP 8.5 UPGRADE NOTES 9. Other Changes to Extensions ======================================== -- Curl: - . curl_easy_setopt with CURLOPT_FOLLOWLOCATION option's value no longer - is treated as boolean but integer to handle CURLFOLLOW_OBEYCODE and - CURLFOLLOW_FIRSTONLY. - -- Fileinfo: - . Upgraded to file 5.46. - . The return type of finfo_close() has been changed to true, rather - than bool. - -- 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. - -- 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. - -- PDO_Sqlite: - . Increased minimum release version support from 3.7.7 to 3.7.17. - -- Readline: - . The return types of readline_add_history(), readline_clear_history(), and - readline_callback_handler_install() have been changed to true, rather - than bool. +- Hash: + . The bundled version of xxHash was upgraded to 0.8.2. ======================================== 10. New Global Constants ======================================== -- Core: - . PHP_BUILD_DATE. - -- Curl: - . CURLINFO_USED_PROXY. - . CURLINFO_HTTPAUTH_USED. - . CURLINFO_PROXYAUTH_USED. - . CURLINFO_CONN_ID. - . CURLINFO_QUEUE_TIME_T. - . CURLOPT_INFILESIZE_LARGE. - . CURLFOLLOW_ALL. - . CURLFOLLOW_OBEYCODE. - . CURLFOLLOW_FIRSTONLY. - -- Intl: - . DECIMAL_COMPACT_SHORT. - . DECIMAL_COMPACT_LONG. - -- POSIX: - . POSIX_SC_OPEN_MAX. - - Sockets: - . IPPROTO_ICMP/IPPROTO_ICMPV6. - . TCP_FUNCTION_BLK (FreeBSD only). - . TCP_FUNCTION_ALIAS (FreeBSD only). - . TCP_REUSPORT_LB_NUMA (FreeBSD only). - . TCP_REUSPORT_LB_NUMA_NODOM (FreeBSD only). - . TCP_REUSPORT_LB_NUMA_CURDOM (FreeBSD only). - . TCP_BBR_ALGORITHM (FreeBSD only). - . AF_PACKET (Linux only). - . IP_BINDANY (FreeBSD/NetBSD/OpenBSD only). - . SO_BUSY_POLL (Linux only). - . UDP_SEGMENT (Linux only). - - SHUT_RD. - - SHUT_WR. - - SHUT_RDWR. - -- Tokenizer: - . T_VOID_CAST. - . T_PIPE. + . TCP_USER_TIMEOUT (Linux only). ======================================== 11. Changes to INI File Handling ======================================== -- Core: - . Added fatal_error_backtraces to control whether fatal errors should include - a backtrace. - RFC: https://wiki.php.net/rfc/error_backtraces_v2 +- Mysqli: + . mysqli.default_port now checks the validity of the value which should be + between 0 and 65535 included. - Opcache: - . Added opcache.file_cache_read_only to support a read-only - opcache.file_cache directory, for use with read-only file systems - (e.g. read-only Docker containers). - Best used with opcache.validate_timestamps=0, - opcache.enable_file_override=1, - and opcache.file_cache_consistency_checks=0. - Note: A cache generated with a different build of PHP, a different file - path, or different settings (including which extensions are loaded), may be - ignored. - . 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. + . opcache.jit_debug accepts a new flag: ZEND_JIT_DEBUG_TRACE_EXIT_INFO_SRC. + When used along with ZEND_JIT_DEBUG_TRACE_EXIT_INFO, the source of exit + points is printed in exit info output, in debug builds. -- 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. +- Mbstring: + . The mbstring.detect_order INI directive now updates the internal detection + order when changed at runtime via ini_set(). Previously, runtime changes + using ini_set() did not take effect for mb_detect_order(). Setting the + directive to NULL or an empty string at runtime now leaves the previously + configured detection order unchanged. ======================================== 12. Windows Support ======================================== -* The configuration variables PHP_VERSION, PHP_MINOR_VERSION, and - PHP_RELEASE_VERSION are now always numbers. Previously, they have been - strings for buildconf builds. - -* phpize builds now reflect the source tree in the build dir (like that already - worked for in-tree builds); some extension builds (especially when using - Makefile.frag.w32) may need adjustments. - -* --enable-sanitizer is now supported for MSVC builds. This enables ASan and - debug assertions, and is supported as of MSVC 16.10 and Windows 10. - -* The --with-uncritical-warn-choke configuration option for clang builds is - no longer supported. Select warnings to suppress via CFLAGS instead. - -* COM: - . The extension is now build shared by default; previously it defaulted to a - static extension, although the official Windows binaries built a shared - extension. - -* FFI: - . It is no longer necessary to specify the library when using FFI::cdef() - and FFI::load(). However, this convenience feature should not be used in - production. - -* Streams: - . If only pipe streams are contained in the $read array, and the $write and - $except arrays are empty, stream_select() now behaves similar to POSIX - systems, i.e. the function only returns if at least one pipe is ready to be - read, or after the timeout expires. Previously, stream_select() returned - immediately, reporting all streams as ready to read. - ======================================== 13. Other Changes ======================================== -- Core: - . The high resolution timer (`hrtime()`) on macOS now uses the recommended - `clock_gettime_nsec_np(CLOCK_UPTIME_RAW)` API instead of - `mach_absolute_time()`. - -- CLI/CGI: - . 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 ======================================== - Core: - . Remove OPcodes for identity comparisons against booleans, particularly - for the match(true) pattern. - . Add OPcode specialization for `=== []` and `!== []` comparisons. - . 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. + . `printf()` using only `%s` and `%d` will be compiled into the equivalent + string interpolation, avoiding the overhead of a function call and repeatedly + parsing the format string. + . Arguments are now passed more efficiently to known constructors (e.g. when + using new self()). -- Intl: - . Now avoids creating extra string copies when converting strings - for use in the collator. - -- MBString: - . The parts of the code that used SSE2 have been adapted to use SIMD - with ARM NEON as well. - -- ReflectionProperty: - . Improved performance of the following methods: getValue(), getRawValue(), - isInitialized(), setValue(), setRawValue(). +- DOM: + . Made splitText() faster and consume less memory. -- SPL: - . Improved performance of dimension accessors and methods of SplFixedArray. +- JSON: + . Improve performance of encoding arrays and objects. - Standard: - . Improved performance of array functions with callbacks - (array_find, array_filter, array_map, usort, ...). - . Improved performance of urlencode() and rawurlencode(). - . Improved unpack() performance with nameless repetitions by avoiding - creating temporary strings and reparsing them. - . Improved pack() performance. - -- XMLReader: - . Improved property access performance. - -- XMLWriter: - . Improved performance and reduce memory consumption. + . Improved performance of array_fill_keys(). + . Improved performance of array_map() with multiple arrays passed. + . Improved performance of array_unshift(). + . Improved performance of array_walk(). + . Improved performance of intval('+0b...', 2) and intval('0b...', 2). + . Improved performance of str_split(). + +- Zip: + . Avoid string copies in ZipArchive::addFromString(). diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 7a14a4907ea62..3ec54f49391b8 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -1,4 +1,4 @@ -PHP 8.5 INTERNALS UPGRADE NOTES +PHP 8.6 INTERNALS UPGRADE NOTES 1. Internal API changes @@ -14,121 +14,61 @@ 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 - where dlmopen with LM_ID_NEWLM is available: - this means shared library symbol isolation (if needed) must be enabled on - 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 - . 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 - could interfere. - . zend_get_callable_name() now returns the name of the underlying function - for fake closures. - . Added smart_string_append_printf() matching smart_str_append_printf() for - char* instead of zend_string*-based smart strings. - . Added php_build_provider() to retrieve the value of PHP_BUILD_PROVIDER at - runtime. - . Removed the cache_slot argument of zend_check_user_type_slow() because - now it only relies on the CE cache. - . Added ZEND_NONSTRING attribute macro for character arrays that do not - represent strings. This allows to silence the GCC 15.x - `-Wunterminated-string-initialization` warning. - . 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*. + . ZSTR_INIT_LITERAL(), zend_string_starts_with_literal(), and + zend_string_starts_with_literal_ci() now support strings containing NUL + bytes. Passing non-literal char* is no longer supported. + . The misnamed ZVAL_IS_NULL() has been removed. Use Z_ISNULL() instead. + . New zend_class_entry.ce_flags2 and zend_function.fn_flags2 fields were + added, given the primary flags were running out of bits. + . The zval_is_true() alias of zend_is_true() has been removed. Call + zend_is_true() directly instead. + . The _zval_get_*() compatibility macros for PHP 7.2 have been removed + call the variant without the leading underscore instead. + Affected: _zval_get_long, _zval_get_double, _zval_get_string, + _zval_get_long_func, _zval_get_double_func, _zval_get_string_func + . CHECK_ZVAL_NULL_PATH() and CHECK_NULL_PATH() have been removed, use + zend_str_has_nul_byte(Z_STR_P(...)) and zend_char_has_nul_byte() + respectively. + . ZEND_LTOA() (and ZEND_LTOA_BUF_LEN) has been removed, as it was + unsafe. Directly use ZEND_LONG_FMT with a function from the + printf family. + . The zval_dtor() alias of zval_ptr_dtor_nogc() has been removed. + Call zval_ptr_dtor_nogc() directly instead. + . The internal zend_copy_parameters_array() function is no longer exposed. + . The zend_make_callable() function has been removed, if a callable zval + needs to be obtained use the zend_get_callable_zval_from_fcc() function + instead. If this was used to store a callable, then an FCC should be + stored instead. + . The zend_active_function{_ex}() functions now return a const zend_function + pointer. + . The zend_get_call_trampoline_func() API now takes the __call or + __callStatic zend_function* instead of a CE and a boolean argument. + . The zend_set_hash_symbol() API has been removed. + . Added zend_hash_str_lookup(). + . The WRONG_PARAM_COUNT and ZEND_WRONG_PARAM_COUNT() macros have been + removed. Call zend_wrong_param_count(); followed by RETURN_THROWS(); + instead. + . PHP_HAVE_STREAMS macro removed from . + . zend_function.arg_info is now always a zend_arg_info*. Before, it was a + zend_internal_arg_info on internal functions, unless the + ZEND_ACC_USER_ARG_INFO flag was set. ======================== 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 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) - 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 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 - . 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 - . 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 - . The refcount APIs now return an `unsigned int` instead of an `int`. - . Removed php_libxml_xmlCheckUTF8(). Use xmlCheckUTF8() from libxml instead. - -- ext/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/xml: + . Removed the XML_ExpatVersion() libxml compatibility wrapper, + as it was unused. + . Removed the XML_GetCurrentByteCount() libxml compatibility wrapper, + as it was unused and could return the wrong result. -- ext/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. +- ext/mbstring: + . Added GB18030-2022 to default encoding list for zh-CN. ======================== 4. OpCode changes diff --git a/Zend/Optimizer/block_pass.c b/Zend/Optimizer/block_pass.c index 96a0e81f03825..b1fd8e44222e5 100644 --- a/Zend/Optimizer/block_pass.c +++ b/Zend/Optimizer/block_pass.c @@ -30,9 +30,9 @@ #include "zend_dump.h" /* Checks if a constant (like "true") may be replaced by its value */ -bool zend_optimizer_get_persistent_constant(zend_string *name, zval *result, int copy) +bool zend_optimizer_get_persistent_constant(zend_string *name, zval *result, bool copy) { - zend_constant *c = zend_hash_find_ptr(EG(zend_constants), name); + const zend_constant *c = zend_hash_find_ptr(EG(zend_constants), name); if (c) { if ((ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT) && !(ZEND_CONSTANT_FLAGS(c) & CONST_DEPRECATED) @@ -42,9 +42,9 @@ bool zend_optimizer_get_persistent_constant(zend_string *name, zval *result, int if (copy) { Z_TRY_ADDREF_P(result); } - return 1; + return true; } else { - return 0; + return false; } } @@ -52,9 +52,9 @@ bool zend_optimizer_get_persistent_constant(zend_string *name, zval *result, int c = zend_get_special_const(ZSTR_VAL(name), ZSTR_LEN(name)); if (c) { ZVAL_COPY_VALUE(result, &c->value); - return 1; + return true; } - return 0; + return false; } /* Data dependencies macros */ @@ -62,9 +62,9 @@ bool zend_optimizer_get_persistent_constant(zend_string *name, zval *result, int #define VAR_SOURCE(op) Tsource[VAR_NUM(op.var)] #define SET_VAR_SOURCE(opline) Tsource[VAR_NUM(opline->result.var)] = opline -static void strip_leading_nops(zend_op_array *op_array, zend_basic_block *b) +static void strip_leading_nops(const zend_op_array *op_array, zend_basic_block *b) { - zend_op *opcodes = op_array->opcodes; + const zend_op *opcodes = op_array->opcodes; do { b->start++; @@ -72,7 +72,7 @@ static void strip_leading_nops(zend_op_array *op_array, zend_basic_block *b) } while (b->len > 0 && opcodes[b->start].opcode == ZEND_NOP); } -static void strip_nops(zend_op_array *op_array, zend_basic_block *b) +static void strip_nops(const zend_op_array *op_array, zend_basic_block *b) { uint32_t i, j; @@ -106,7 +106,7 @@ static void strip_nops(zend_op_array *op_array, zend_basic_block *b) } } -static int get_const_switch_target(zend_cfg *cfg, zend_op_array *op_array, zend_basic_block *block, zend_op *opline, zval *val) { +static uint32_t get_const_switch_target(const zend_cfg *cfg, const zend_op_array *op_array, const zend_basic_block *block, zend_op *opline, const zval *val) { HashTable *jumptable = Z_ARRVAL(ZEND_OP2_LITERAL(opline)); zval *zv; if ((opline->opcode == ZEND_SWITCH_LONG && Z_TYPE_P(val) != IS_LONG) @@ -371,7 +371,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array } } else if(flen == sizeof("constant")-1 && zend_binary_strcasecmp(fname, flen, "constant", sizeof("constant")-1) == 0) { zval c; - if (zend_optimizer_get_persistent_constant(Z_STR_P(arg), &c, 1 ELS_CC)) { + if (zend_optimizer_get_persistent_constant(Z_STR_P(arg), &c, true ELS_CC)) { literal_dtor(arg); MAKE_NOP(sv); MAKE_NOP(fcall); @@ -409,7 +409,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array break; } if (opline->op1_type == IS_CONST) { - int target = get_const_switch_target(cfg, op_array, block, opline, &ZEND_OP1_LITERAL(opline)); + uint32_t target = get_const_switch_target(cfg, op_array, block, opline, &ZEND_OP1_LITERAL(opline)); literal_dtor(&ZEND_OP1_LITERAL(opline)); literal_dtor(&ZEND_OP2_LITERAL(opline)); opline->opcode = ZEND_JMP; @@ -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: @@ -428,18 +436,11 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array Tsource[VAR_NUM(opline->op1.var)] = NULL; break; } - ZEND_FALLTHROUGH; - - case ZEND_IS_EQUAL: - case ZEND_IS_NOT_EQUAL: if (opline->op1_type == IS_CONST && opline->op2_type == IS_CONST) { goto optimize_constant_binary_op; } - /* IS_EQ(TRUE, X) => BOOL(X) - * IS_EQ(FALSE, X) => BOOL_NOT(X) - * IS_NOT_EQ(TRUE, X) => BOOL_NOT(X) - * IS_NOT_EQ(FALSE, X) => BOOL(X) + /* * CASE(TRUE, X) => BOOL(X) * CASE(FALSE, X) => BOOL_NOT(X) */ @@ -470,6 +471,21 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array goto optimize_bool; } break; + + case ZEND_IS_EQUAL: + case ZEND_IS_NOT_EQUAL: + if (opline->op1_type == IS_CONST && + opline->op2_type == IS_CONST) { + goto optimize_constant_binary_op; + } + /* IS_EQ(TRUE, X) => BOOL(X) + * IS_EQ(FALSE, X) => BOOL_NOT(X) + * IS_NOT_EQ(TRUE, X) => BOOL_NOT(X) + * IS_NOT_EQ(FALSE, X) => BOOL(X) + * Those optimizations are not safe if the other operand ends up being NAN + * as BOOL/BOOL_NOT will warn, while IS_EQUAL/IS_NOT_EQUAL do not. + */ + break; case ZEND_IS_IDENTICAL: if (opline->op1_type == IS_CONST && opline->op2_type == IS_CONST) { @@ -806,7 +822,6 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array src->extended_value == IS_STRING && src->op1_type != IS_CONST) { /* convert T1 = CAST(STRING, X), T2 = CONCAT(Y, T1) to T2 = CONCAT(Y,X) */ - zend_op *src = VAR_SOURCE(opline->op2); VAR_SOURCE(opline->op2) = NULL; COPY_NODE(opline->op2, src->op1); MAKE_NOP(src); @@ -933,14 +948,14 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array src = VAR_SOURCE(opline->op1); if (src && src->opcode == ZEND_QM_ASSIGN) { zend_op *op = src + 1; - bool optimize = 1; + bool optimize = true; while (op < opline) { if ((op->op1_type == opline->op1_type && op->op1.var == opline->op1.var) || (op->op2_type == opline->op1_type && op->op2.var == opline->op1.var)) { - optimize = 0; + optimize = false; break; } op++; @@ -993,10 +1008,10 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array } /* Rebuild plain (optimized) op_array from CFG */ -static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_optimizer_ctx *ctx) +static void assemble_code_blocks(const zend_cfg *cfg, zend_op_array *op_array, zend_optimizer_ctx *ctx) { zend_basic_block *blocks = cfg->blocks; - zend_basic_block *end = blocks + cfg->blocks_count; + const zend_basic_block *end = blocks + cfg->blocks_count; zend_basic_block *b; zend_op *new_opcodes; zend_op *opline; @@ -1009,7 +1024,7 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op if (b->flags & (ZEND_BB_REACHABLE|ZEND_BB_UNREACHABLE_FREE)) { opline = op_array->opcodes + b->start + b->len - 1; if (opline->opcode == ZEND_JMP) { - zend_basic_block *next = b + 1; + const zend_basic_block *next = b + 1; while (next < end && !(next->flags & ZEND_BB_REACHABLE)) { next++; @@ -1026,9 +1041,9 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op len += b->len; } else { /* this block will not be used, delete all constants there */ - zend_op *op = op_array->opcodes + b->start; - zend_op *end = op + b->len; - for (; op < end; op++) { + const zend_op *op = op_array->opcodes + b->start; + const zend_op *last_op = op + b->len; + for (; op < last_op; op++) { if (op->op1_type == IS_CONST) { literal_dtor(&ZEND_OP1_LITERAL(op)); } @@ -1093,7 +1108,7 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op case ZEND_SWITCH_STRING: case ZEND_MATCH: { - HashTable *jumptable = Z_ARRVAL(ZEND_OP2_LITERAL(opline)); + const HashTable *jumptable = Z_ARRVAL(ZEND_OP2_LITERAL(opline)); zval *zv; uint32_t s = 0; ZEND_ASSERT(b->successors_count == (opline->opcode == ZEND_MATCH ? 1 : 2) + zend_hash_num_elements(jumptable)); @@ -1109,7 +1124,7 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op /* adjust exception jump targets & remove unused try_catch_array entries */ if (op_array->last_try_catch) { - int i, j; + uint32_t i, j; uint32_t *map; ALLOCA_FLAG(use_heap); @@ -1144,15 +1159,15 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op } if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) { - zend_op *opline = new_opcodes; - zend_op *end = opline + len; - while (opline < end) { - if (opline->opcode == ZEND_FAST_RET && - opline->op2.num != (uint32_t)-1 && - opline->op2.num < (uint32_t)j) { - opline->op2.num = map[opline->op2.num]; + zend_op *finally_opline = new_opcodes; + const zend_op *last_finally_op = finally_opline + len; + while (finally_opline < last_finally_op) { + if (finally_opline->opcode == ZEND_FAST_RET && + finally_opline->op2.num != (uint32_t)-1 && + finally_opline->op2.num < j) { + finally_opline->op2.num = map[finally_opline->op2.num]; } - opline++; + finally_opline++; } } } @@ -1168,7 +1183,7 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op } } -static zend_always_inline zend_basic_block *get_target_block(const zend_cfg *cfg, zend_basic_block *block, int n, uint32_t *opt_count) +static zend_always_inline zend_basic_block *get_target_block(const zend_cfg *cfg, const zend_basic_block *block, int n, uint32_t *opt_count) { int b; zend_basic_block *target_block = cfg->blocks + block->successors[n]; @@ -1184,7 +1199,7 @@ static zend_always_inline zend_basic_block *get_target_block(const zend_cfg *cfg return target_block; } -static zend_always_inline zend_basic_block *get_follow_block(const zend_cfg *cfg, zend_basic_block *block, int n, uint32_t *opt_count) +static zend_always_inline zend_basic_block *get_follow_block(const zend_cfg *cfg, const zend_basic_block *block, int n, uint32_t *opt_count) { int b; zend_basic_block *target_block = cfg->blocks + block->successors[n]; @@ -1203,7 +1218,7 @@ static zend_always_inline zend_basic_block *get_follow_block(const zend_cfg *cfg static zend_always_inline zend_basic_block *get_next_block(const zend_cfg *cfg, zend_basic_block *block) { zend_basic_block *next_block = block + 1; - zend_basic_block *end = cfg->blocks + cfg->blocks_count; + const zend_basic_block *end = cfg->blocks + cfg->blocks_count; while (1) { if (next_block == end) { @@ -1221,7 +1236,7 @@ static zend_always_inline zend_basic_block *get_next_block(const zend_cfg *cfg, /* we use "jmp_hitlist" to avoid infinity loops during jmp optimization */ -static zend_always_inline bool in_hitlist(int target, int *jmp_hitlist, int jmp_hitlist_count) +static zend_always_inline bool in_hitlist(int target, const int *jmp_hitlist, int jmp_hitlist_count) { int i; @@ -1467,7 +1482,7 @@ static void zend_jmp_optimization(zend_basic_block *block, zend_op_array *op_arr /* Find a set of variables which are used outside of the block where they are * defined. We won't apply some optimization patterns for such variables. */ -static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset used_ext, zend_optimizer_ctx *ctx) +static void zend_t_usage(const zend_cfg *cfg, const zend_op_array *op_array, zend_bitset used_ext, zend_optimizer_ctx *ctx) { int n; zend_basic_block *block, *next_block; @@ -1550,14 +1565,14 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use } if (ctx->debug_level & ZEND_DUMP_BLOCK_PASS_VARS) { - bool printed = 0; + bool printed = false; uint32_t i; for (i = op_array->last_var; i< op_array->T; i++) { if (zend_bitset_in(used_ext, i)) { if (!printed) { fprintf(stderr, "NON-LOCAL-VARS: %d", i); - printed = 1; + printed = true; } else { fprintf(stderr, ", %d", i); } @@ -1671,7 +1686,7 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use zend_arena_release(&ctx->arena, checkpoint); } -static void zend_merge_blocks(zend_op_array *op_array, zend_cfg *cfg, uint32_t *opt_count) +static void zend_merge_blocks(const zend_op_array *op_array, const zend_cfg *cfg, uint32_t *opt_count) { int i; zend_basic_block *b, *bb; @@ -1691,7 +1706,7 @@ static void zend_merge_blocks(zend_op_array *op_array, zend_cfg *cfg, uint32_t * for (bb = prev + 1; bb != b; bb++) { zend_op *op = op_array->opcodes + bb->start; - zend_op *end = op + bb->len; + const zend_op *end = op + bb->len; while (op < end) { if (op->op1_type == IS_CONST) { literal_dtor(&ZEND_OP1_LITERAL(op)); diff --git a/Zend/Optimizer/compact_literals.c b/Zend/Optimizer/compact_literals.c index d0aaccec7ce2c..447a034530e1b 100644 --- a/Zend/Optimizer/compact_literals.c +++ b/Zend/Optimizer/compact_literals.c @@ -110,7 +110,7 @@ static zend_string *create_str_cache_key(zval *literal, uint8_t num_related) void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx *ctx) { zend_op *opline, *end; - int i, j, n, *map; + int n, *map; uint32_t cache_size; zval zv, *pos; literal_info *info; @@ -124,6 +124,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx int *const_slot, *class_slot, *func_slot, *bind_var_slot, *property_slot, *method_slot, *jmp_slot; if (op_array->last_literal) { + uint32_t j; info = (literal_info*)zend_arena_calloc(&ctx->arena, op_array->last_literal, sizeof(literal_info)); /* Mark literals of specific types */ @@ -258,9 +259,9 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx op_array->function_name ? op_array->function_name->val : "main"); fprintf(stderr, "Literals table size %d\n", op_array->last_literal); - for (int i = 0; i < op_array->last_literal; i++) { + for (uint32_t i = 0; i < op_array->last_literal; i++) { zend_string *str = zval_get_string(op_array->literals + i); - fprintf(stderr, "Literal %d, val (%zu):%s\n", i, ZSTR_LEN(str), ZSTR_VAL(str)); + fprintf(stderr, "Literal %" PRIu32 ", val (%zu):%s\n", i, ZSTR_LEN(str), ZSTR_VAL(str)); zend_string_release(str); } fflush(stderr); @@ -272,7 +273,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx zend_hash_init(&hash, op_array->last_literal, NULL, NULL, 0); map = (int*)zend_arena_alloc(&ctx->arena, op_array->last_literal * sizeof(int)); memset(map, 0, op_array->last_literal * sizeof(int)); - for (i = 0; i < op_array->last_literal; i++) { + for (uint32_t i = 0; i < op_array->last_literal; i++) { if (!info[i].num_related) { /* unset literal */ zval_ptr_dtor_nogc(&op_array->literals[i]); @@ -740,6 +741,12 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx cache_size += 2 * sizeof(void *); } break; + case ZEND_CALLABLE_CONVERT: + if (opline->extended_value != (uint32_t)-1) { + opline->extended_value = cache_size; + cache_size += sizeof(void *); + } + break; } opline++; } @@ -770,9 +777,9 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx { fprintf(stderr, "Optimized literals table size %d\n", op_array->last_literal); - for (int i = 0; i < op_array->last_literal; i++) { + for (uint32_t i = 0; i < op_array->last_literal; i++) { zend_string *str = zval_get_string(op_array->literals + i); - fprintf(stderr, "Literal %d, val (%zu):%s\n", i, ZSTR_LEN(str), ZSTR_VAL(str)); + fprintf(stderr, "Literal %" PRIu32 ", val (%zu):%s\n", i, ZSTR_LEN(str), ZSTR_VAL(str)); zend_string_release(str); } fflush(stderr); diff --git a/Zend/Optimizer/dce.c b/Zend/Optimizer/dce.c index a00fd8bc6ad30..41fd0f6c30af4 100644 --- a/Zend/Optimizer/dce.c +++ b/Zend/Optimizer/dce.c @@ -62,17 +62,17 @@ typedef struct { static inline bool is_bad_mod(const zend_ssa *ssa, int use, int def) { if (def < 0) { /* This modification is not tracked by SSA, assume the worst */ - return 1; + return true; } if (ssa->var_info[use].type & MAY_BE_REF) { /* Modification of reference may have side-effect */ - return 1; + return true; } - return 0; + return false; } static inline bool may_have_side_effects( - zend_op_array *op_array, zend_ssa *ssa, + const zend_op_array *op_array, const zend_ssa *ssa, const zend_op *opline, const zend_ssa_op *ssa_op, bool reorder_dtor_effects) { switch (opline->opcode) { @@ -124,19 +124,20 @@ static inline bool may_have_side_effects( case ZEND_FUNC_NUM_ARGS: case ZEND_FUNC_GET_ARGS: case ZEND_ARRAY_KEY_EXISTS: + case ZEND_COPY_TMP: /* No side effects */ - return 0; + return false; case ZEND_FREE: return opline->extended_value == ZEND_FREE_VOID_CAST; case ZEND_ADD_ARRAY_ELEMENT: /* TODO: We can't free two vars. Keep instruction alive. "$b"]; */ if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) && (opline->op2_type & (IS_VAR|IS_TMP_VAR))) { - return 1; + return true; } - return 0; + return false; case ZEND_ROPE_END: /* TODO: Rope dce optimization, see #76446 */ - return 1; + return true; case ZEND_JMP: case ZEND_JMPZ: case ZEND_JMPNZ: @@ -149,7 +150,7 @@ static inline bool may_have_side_effects( case ZEND_BIND_INIT_STATIC_OR_JMP: case ZEND_JMP_FRAMELESS: /* For our purposes a jumps and branches are side effects. */ - return 1; + return true; case ZEND_BEGIN_SILENCE: case ZEND_END_SILENCE: case ZEND_ECHO: @@ -164,7 +165,7 @@ static inline bool may_have_side_effects( case ZEND_YIELD_FROM: case ZEND_VERIFY_NEVER_TYPE: /* Intrinsic side effects */ - return 1; + return true; case ZEND_DO_FCALL: case ZEND_DO_FCALL_BY_NAME: case ZEND_DO_ICALL: @@ -174,31 +175,31 @@ static inline bool may_have_side_effects( case ZEND_FRAMELESS_ICALL_2: case ZEND_FRAMELESS_ICALL_3: /* For now assume all calls have side effects */ - return 1; + return true; case ZEND_RECV: case ZEND_RECV_INIT: /* Even though RECV_INIT can be side-effect free, these cannot be simply dropped * due to the prologue skipping code. */ - return 1; + return true; case ZEND_ASSIGN_REF: - return 1; + return true; case ZEND_ASSIGN: { if (is_bad_mod(ssa, ssa_op->op1_use, ssa_op->op1_def)) { - return 1; + return true; } if (!reorder_dtor_effects) { if (opline->op2_type != IS_CONST && (OP2_INFO() & MAY_HAVE_DTOR) && ssa->vars[ssa_op->op2_use].escape_state != ESCAPE_STATE_NO_ESCAPE) { /* DCE might shorten lifetime */ - return 1; + return true; } } - return 0; + return false; } case ZEND_UNSET_VAR: - return 1; + return true; case ZEND_UNSET_CV: { uint32_t t1 = OP1_INFO(); @@ -207,9 +208,9 @@ static inline bool may_have_side_effects( * an unset may be considered dead even if there is a later assignment to the * variable. Removing the unset in this case would not be correct if the variable * is a reference, because unset breaks references. */ - return 1; + return true; } - return 0; + return false; } case ZEND_PRE_INC: case ZEND_POST_INC: @@ -223,7 +224,7 @@ static inline bool may_have_side_effects( case ZEND_ASSIGN_OBJ: if (is_bad_mod(ssa, ssa_op->op1_use, ssa_op->op1_def) || ssa->vars[ssa_op->op1_def].escape_state != ESCAPE_STATE_NO_ESCAPE) { - return 1; + return true; } if (!reorder_dtor_effects) { opline++; @@ -231,33 +232,33 @@ static inline bool may_have_side_effects( if (opline->op1_type != IS_CONST && (OP1_INFO() & MAY_HAVE_DTOR)) { /* DCE might shorten lifetime */ - return 1; + return true; } } - return 0; + return false; case ZEND_PRE_INC_OBJ: case ZEND_PRE_DEC_OBJ: case ZEND_POST_INC_OBJ: case ZEND_POST_DEC_OBJ: if (is_bad_mod(ssa, ssa_op->op1_use, ssa_op->op1_def) || ssa->vars[ssa_op->op1_def].escape_state != ESCAPE_STATE_NO_ESCAPE) { - return 1; + return true; } - return 0; + return false; case ZEND_BIND_STATIC: if (op_array->static_variables) { /* Implicit and Explicit bind static is effectively prologue of closure so report it has side effects like RECV, RECV_INIT; This allows us to reflect on the closure and discover used variable at runtime */ if ((opline->extended_value & (ZEND_BIND_IMPLICIT|ZEND_BIND_EXPLICIT))) { - return 1; + return true; } /* Modifies static variables which are observable through reflection */ if ((opline->extended_value & ZEND_BIND_REF) && opline->op2_type != IS_UNUSED) { - return 1; + return true; } } - return 0; + return false; case ZEND_CHECK_VAR: return (OP1_INFO() & MAY_BE_UNDEF) != 0; case ZEND_FE_RESET_R: @@ -267,12 +268,12 @@ static inline bool may_have_side_effects( return (OP1_INFO() & MAY_BE_ANY) != MAY_BE_ARRAY; default: /* For everything we didn't handle, assume a side-effect */ - return 1; + return true; } } -static zend_always_inline void add_to_worklists(context *ctx, int var_num, int check) { - zend_ssa_var *var = &ctx->ssa->vars[var_num]; +static zend_always_inline void add_to_worklists(const context *ctx, int var_num, int check) { + const zend_ssa_var *var = &ctx->ssa->vars[var_num]; if (var->definition >= 0) { if (!check || zend_bitset_in(ctx->instr_dead, var->definition)) { zend_bitset_incl(ctx->instr_worklist, var->definition); @@ -284,14 +285,14 @@ static zend_always_inline void add_to_worklists(context *ctx, int var_num, int c } } -static inline void add_to_phi_worklist_no_val(context *ctx, int var_num) { - zend_ssa_var *var = &ctx->ssa->vars[var_num]; +static inline void add_to_phi_worklist_no_val(const context *ctx, int var_num) { + const zend_ssa_var *var = &ctx->ssa->vars[var_num]; if (var->definition_phi && zend_bitset_in(ctx->phi_dead, var_num)) { zend_bitset_incl(ctx->phi_worklist_no_val, var_num); } } -static zend_always_inline void add_operands_to_worklists(context *ctx, zend_op *opline, zend_ssa_op *ssa_op, zend_ssa *ssa, int check) { +static zend_always_inline void add_operands_to_worklists(const context *ctx, const zend_op *opline, const zend_ssa_op *ssa_op, const zend_ssa *ssa, int check) { if (ssa_op->result_use >= 0) { add_to_worklists(ctx, ssa_op->result_use, check); } @@ -315,16 +316,16 @@ static zend_always_inline void add_operands_to_worklists(context *ctx, zend_op * } } -static zend_always_inline void add_phi_sources_to_worklists(context *ctx, zend_ssa_phi *phi, int check) { - zend_ssa *ssa = ctx->ssa; +static zend_always_inline void add_phi_sources_to_worklists(const context *ctx, zend_ssa_phi *phi, int check) { + const zend_ssa *ssa = ctx->ssa; int source; FOREACH_PHI_SOURCE(phi, source) { add_to_worklists(ctx, source, check); } FOREACH_PHI_SOURCE_END(); } -static inline bool is_var_dead(context *ctx, int var_num) { - zend_ssa_var *var = &ctx->ssa->vars[var_num]; +static inline bool is_var_dead(const context *ctx, int var_num) { + const zend_ssa_var *var = &ctx->ssa->vars[var_num]; if (var->definition_phi) { return zend_bitset_in(ctx->phi_dead, var_num); } else if (var->definition >= 0) { @@ -338,9 +339,9 @@ static inline bool is_var_dead(context *ctx, int var_num) { } // Sometimes we can mark the var as EXT_UNUSED -static bool try_remove_var_def(context *ctx, int free_var, int use_chain, zend_op *opline) { +static bool try_remove_var_def(const context *ctx, int free_var, int use_chain, const zend_op *opline) { if (use_chain >= 0) { - return 0; + return false; } zend_ssa_var *var = &ctx->ssa->vars[free_var]; int def = var->definition; @@ -381,54 +382,56 @@ static bool try_remove_var_def(context *ctx, int free_var, int use_chain, zend_o def_opline->result.var = 0; def_op->result_def = -1; var->definition = -1; - return 1; + return true; default: break; } } } - return 0; + return false; } static zend_always_inline bool may_be_refcounted(uint32_t type) { return (type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) != 0; } -static inline bool is_free_of_live_var(context *ctx, zend_op *opline, zend_ssa_op *ssa_op) { +static inline bool is_free_of_live_var(const context *ctx, const zend_op *opline, const zend_ssa_op *ssa_op) { switch (opline->opcode) { case ZEND_FREE: /* It is always safe to remove FREEs of non-refcounted values, even if they are live. */ if ((ctx->ssa->var_info[ssa_op->op1_use].type & (MAY_BE_REF|MAY_BE_ANY|MAY_BE_UNDEF)) != 0 && !may_be_refcounted(ctx->ssa->var_info[ssa_op->op1_use].type)) { - return 0; + return false; } ZEND_FALLTHROUGH; case ZEND_FE_FREE: return !is_var_dead(ctx, ssa_op->op1_use); default: - return 0; + return false; } } /* Returns whether the instruction has been DCEd */ -static bool dce_instr(context *ctx, zend_op *opline, zend_ssa_op *ssa_op) { - zend_ssa *ssa = ctx->ssa; +static bool dce_instr(const context *ctx, zend_op *opline, zend_ssa_op *ssa_op) { + const zend_ssa *ssa = ctx->ssa; int free_var = -1; uint8_t free_var_type; if (opline->opcode == ZEND_NOP) { - return 0; + return false; } /* We mark FREEs as dead, but they're only really dead if the destroyed var is dead */ if (is_free_of_live_var(ctx, opline, ssa_op)) { - return 0; + return false; } - if ((opline->op1_type & (IS_VAR|IS_TMP_VAR))&& !is_var_dead(ctx, ssa_op->op1_use)) { + if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) && !is_var_dead(ctx, ssa_op->op1_use)) { if (!try_remove_var_def(ctx, ssa_op->op1_use, ssa_op->op1_use_chain, opline)) { if (may_be_refcounted(ssa->var_info[ssa_op->op1_use].type) - && opline->opcode != ZEND_CASE && opline->opcode != ZEND_CASE_STRICT) { + && opline->opcode != ZEND_CASE + && opline->opcode != ZEND_CASE_STRICT + && opline->opcode != ZEND_COPY_TMP) { free_var = ssa_op->op1_use; free_var_type = opline->op1_type; } @@ -440,7 +443,7 @@ static bool dce_instr(context *ctx, zend_op *opline, zend_ssa_op *ssa_op) { if (free_var >= 0) { // TODO: We can't free two vars. Keep instruction alive. zend_bitset_excl(ctx->instr_dead, opline - ctx->op_array->opcodes); - return 0; + return false; } free_var = ssa_op->op2_use; free_var_type = opline->op2_type; @@ -459,12 +462,12 @@ static bool dce_instr(context *ctx, zend_op *opline, zend_ssa_op *ssa_op) { ssa_op->op1_use = free_var; ssa_op->op1_use_chain = ssa->vars[free_var].use_chain; ssa->vars[free_var].use_chain = ssa_op - ssa->ops; - return 0; + return false; } - return 1; + return true; } -static inline int get_common_phi_source(zend_ssa *ssa, zend_ssa_phi *phi) { +static inline int get_common_phi_source(const zend_ssa *ssa, zend_ssa_phi *phi) { int common_source = -1; int source; FOREACH_PHI_SOURCE(phi, source) { @@ -484,7 +487,7 @@ static inline int get_common_phi_source(zend_ssa *ssa, zend_ssa_phi *phi) { return common_source; } -static void try_remove_trivial_phi(context *ctx, zend_ssa_phi *phi) { +static void try_remove_trivial_phi(const context *ctx, zend_ssa_phi *phi) { zend_ssa *ssa = ctx->ssa; if (phi->pi < 0) { /* Phi assignment with identical source operands */ @@ -507,17 +510,17 @@ static void try_remove_trivial_phi(context *ctx, zend_ssa_phi *phi) { static inline bool may_break_varargs(const zend_op_array *op_array, const zend_ssa *ssa, const zend_ssa_op *ssa_op) { if (ssa_op->op1_def >= 0 && ssa->vars[ssa_op->op1_def].var < op_array->num_args) { - return 1; + return true; } if (ssa_op->op2_def >= 0 && ssa->vars[ssa_op->op2_def].var < op_array->num_args) { - return 1; + return true; } if (ssa_op->result_def >= 0 && ssa->vars[ssa_op->result_def].var < op_array->num_args) { - return 1; + return true; } - return 0; + return false; } static inline bool may_throw_dce_exception(const zend_op *opline) { @@ -567,7 +570,7 @@ int dce_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *optimizer int op_data = -1; b--; - zend_basic_block *block = &ssa->cfg.blocks[b]; + const zend_basic_block *block = &ssa->cfg.blocks[b]; if (!(block->flags & ZEND_BB_REACHABLE)) { continue; } diff --git a/Zend/Optimizer/dfa_pass.c b/Zend/Optimizer/dfa_pass.c index bf85764c93b49..796e998493d76 100644 --- a/Zend/Optimizer/dfa_pass.c +++ b/Zend/Optimizer/dfa_pass.c @@ -226,7 +226,7 @@ static void zend_ssa_remove_nops(zend_op_array *op_array, zend_ssa *ssa, zend_op } /* update try/catch array */ - for (j = 0; j < op_array->last_try_catch; j++) { + for (uint32_t j = 0; j < op_array->last_try_catch; j++) { op_array->try_catch_array[j].try_op -= shiftlist[op_array->try_catch_array[j].try_op]; op_array->try_catch_array[j].catch_op -= shiftlist[op_array->try_catch_array[j].catch_op]; if (op_array->try_catch_array[j].finally_op) { @@ -256,11 +256,11 @@ static void zend_ssa_remove_nops(zend_op_array *op_array, zend_ssa *ssa, zend_op static bool safe_instanceof(const zend_class_entry *ce1, const zend_class_entry *ce2) { if (ce1 == ce2) { - return 1; + return true; } if (!(ce1->ce_flags & ZEND_ACC_LINKED)) { /* This case could be generalized, similarly to unlinked_instanceof */ - return 0; + return false; } return instanceof_function(ce1, ce2); } @@ -297,7 +297,7 @@ static inline bool can_elide_return_type_check( zend_ssa_var_info *use_info = &ssa->var_info[ssa_op->op1_use]; uint32_t use_type = use_info->type & (MAY_BE_ANY|MAY_BE_UNDEF); if (use_type & MAY_BE_REF) { - return 0; + return false; } if (use_type & MAY_BE_UNDEF) { @@ -322,20 +322,20 @@ static bool opline_supports_assign_contraction( zend_op_array *op_array, zend_ssa *ssa, zend_op *opline, int src_var, uint32_t cv_var) { if (opline->opcode == ZEND_NEW) { /* see Zend/tests/generators/aborted_yield_during_new.phpt */ - return 0; + return false; } /* Frameless calls override the return value, but the return value may overlap with the arguments. */ switch (opline->opcode) { case ZEND_FRAMELESS_ICALL_3: - if ((opline + 1)->op1_type == IS_CV && (opline + 1)->op1.var == cv_var) return 0; + if ((opline + 1)->op1_type == IS_CV && (opline + 1)->op1.var == cv_var) return false; ZEND_FALLTHROUGH; case ZEND_FRAMELESS_ICALL_2: - if (opline->op2_type == IS_CV && opline->op2.var == cv_var) return 0; + if (opline->op2_type == IS_CV && opline->op2.var == cv_var) return false; ZEND_FALLTHROUGH; case ZEND_FRAMELESS_ICALL_1: - if (opline->op1_type == IS_CV && opline->op1.var == cv_var) return 0; - return 1; + if (opline->op1_type == IS_CV && opline->op1.var == cv_var) return false; + return true; } if (opline->opcode == ZEND_DO_ICALL || opline->opcode == ZEND_DO_UCALL @@ -374,10 +374,10 @@ static bool opline_supports_assign_contraction( && opline->op1_type == IS_CV && opline->op1.var == cv_var && zend_may_throw(opline, &ssa->ops[ssa->vars[src_var].definition], op_array, ssa)) { - return 0; + return false; } - return 1; + return true; } static bool variable_defined_or_used_in_range(zend_ssa *ssa, int var, int start, int end) @@ -391,11 +391,11 @@ static bool variable_defined_or_used_in_range(zend_ssa *ssa, int var, int start, (ssa_op->op2_use >= 0 && ssa->vars[ssa_op->op2_use].var == var) || (ssa_op->result_use >= 0 && ssa->vars[ssa_op->result_use].var == var) ) { - return 1; + return true; } start++; } - return 0; + return false; } int zend_dfa_optimize_calls(zend_op_array *op_array, zend_ssa *ssa) @@ -414,19 +414,19 @@ int zend_dfa_optimize_calls(zend_op_array *op_array, zend_ssa *ssa) && call_info->callee_func && zend_string_equals_literal_ci(call_info->callee_func->common.function_name, "in_array")) { - bool strict = 0; + bool strict = false; bool has_opdata = op->opcode == ZEND_FRAMELESS_ICALL_3; ZEND_ASSERT(!call_info->is_prototype); if (has_opdata) { if (zend_is_true(CT_CONSTANT_EX(op_array, (op + 1)->op1.constant))) { - strict = 1; + strict = true; } } if (op->op2_type == IS_CONST && Z_TYPE_P(CT_CONSTANT_EX(op_array, op->op2.constant)) == IS_ARRAY) { - bool ok = 1; + bool ok = true; HashTable *src = Z_ARRVAL_P(CT_CONSTANT_EX(op_array, op->op2.constant)); HashTable *dst; @@ -443,7 +443,7 @@ int zend_dfa_optimize_calls(zend_op_array *op_array, zend_ssa *ssa) zend_hash_index_add(dst, Z_LVAL_P(val), &tmp); } else { zend_array_destroy(dst); - ok = 0; + ok = false; break; } } ZEND_HASH_FOREACH_END(); @@ -451,7 +451,7 @@ int zend_dfa_optimize_calls(zend_op_array *op_array, zend_ssa *ssa) ZEND_HASH_FOREACH_VAL(src, val) { if (Z_TYPE_P(val) != IS_STRING || ZEND_HANDLE_NUMERIC(Z_STR_P(val), idx)) { zend_array_destroy(dst); - ok = 0; + ok = false; break; } zend_hash_add(dst, Z_STR_P(val), &tmp); @@ -711,12 +711,12 @@ static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa) uint32_t op_num; zend_op *opline; zend_ssa_op *ssa_op; - bool can_follow = 1; + bool can_follow = true; while (next_block_num < ssa->cfg.blocks_count && !(ssa->cfg.blocks[next_block_num].flags & ZEND_BB_REACHABLE)) { if (ssa->cfg.blocks[next_block_num].flags & ZEND_BB_UNREACHABLE_FREE) { - can_follow = 0; + can_follow = false; } next_block_num++; } @@ -989,7 +989,7 @@ static bool zend_dfa_try_to_replace_result(zend_op_array *op_array, zend_ssa *ss if ((opline->op1_type == IS_CV && opline->op1.var == cv) || (opline->op2_type == IS_CV && opline->op2.var == cv) || (opline->result_type == IS_CV && opline->result.var == cv)) { - return 0; + return false; } opline--; i--; @@ -1026,12 +1026,12 @@ static bool zend_dfa_try_to_replace_result(zend_op_array *op_array, zend_ssa *ss op_array->opcodes[use].result.var = cv; } - return 1; + return true; } } } - return 0; + return false; } void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx, zend_ssa *ssa, zend_call_info **call_map) diff --git a/Zend/Optimizer/escape_analysis.c b/Zend/Optimizer/escape_analysis.c index 840a18341a0ff..00ee329845026 100644 --- a/Zend/Optimizer/escape_analysis.c +++ b/Zend/Optimizer/escape_analysis.c @@ -155,7 +155,7 @@ static bool is_allocation_def(zend_op_array *op_array, zend_ssa *ssa, int def, i if (ssa_op->result_def == var) { switch (opline->opcode) { case ZEND_INIT_ARRAY: - return 1; + return true; case ZEND_NEW: { /* objects with destructors should escape */ zend_class_entry *ce = zend_optimizer_get_class_entry_from_op1( @@ -175,22 +175,22 @@ static bool is_allocation_def(zend_op_array *op_array, zend_ssa *ssa, int def, i && !ce->__set && !(ce->ce_flags & forbidden_flags) && (ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) { - return 1; + return true; } break; } case ZEND_QM_ASSIGN: if (opline->op1_type == IS_CONST && Z_TYPE_P(CRT_CONSTANT(opline->op1)) == IS_ARRAY) { - return 1; + return true; } if (opline->op1_type == IS_CV && (OP1_INFO() & MAY_BE_ARRAY)) { - return 1; + return true; } break; case ZEND_ASSIGN: if (opline->op1_type == IS_CV && (OP1_INFO() & MAY_BE_ARRAY)) { - return 1; + return true; } break; } @@ -199,22 +199,22 @@ static bool is_allocation_def(zend_op_array *op_array, zend_ssa *ssa, int def, i case ZEND_ASSIGN: if (opline->op2_type == IS_CONST && Z_TYPE_P(CRT_CONSTANT(opline->op2)) == IS_ARRAY) { - return 1; + return true; } if (opline->op2_type == IS_CV && (OP2_INFO() & MAY_BE_ARRAY)) { - return 1; + return true; } break; case ZEND_ASSIGN_DIM: if (OP1_INFO() & (MAY_BE_UNDEF | MAY_BE_NULL | MAY_BE_FALSE)) { /* implicit object/array allocation */ - return 1; + return true; } break; } } - return 0; + return false; } /* }}} */ @@ -229,7 +229,7 @@ static bool is_local_def(zend_op_array *op_array, zend_ssa *ssa, int def, int va case ZEND_ADD_ARRAY_ELEMENT: case ZEND_QM_ASSIGN: case ZEND_ASSIGN: - return 1; + return true; case ZEND_NEW: { /* objects with destructors should escape */ zend_class_entry *ce = zend_optimizer_get_class_entry_from_op1( @@ -243,7 +243,7 @@ static bool is_local_def(zend_op_array *op_array, zend_ssa *ssa, int def, int va && !ce->__get && !ce->__set && !ce->parent) { - return 1; + return true; } break; } @@ -260,11 +260,11 @@ static bool is_local_def(zend_op_array *op_array, zend_ssa *ssa, int def, int va case ZEND_PRE_DEC_OBJ: case ZEND_POST_INC_OBJ: case ZEND_POST_DEC_OBJ: - return 1; + return true; } } - return 0; + return false; } /* }}} */ @@ -282,7 +282,7 @@ static bool is_escape_use(zend_op_array *op_array, zend_ssa *ssa, int use, int v if (opline->op1_type == IS_CV) { if (OP1_INFO() & MAY_BE_OBJECT) { /* object aliasing */ - return 1; + return true; } } break; @@ -294,7 +294,7 @@ static bool is_escape_use(zend_op_array *op_array, zend_ssa *ssa, int use, int v case ZEND_FETCH_OBJ_IS: break; case ZEND_ASSIGN_OP: - return 1; + return true; case ZEND_ASSIGN_DIM_OP: case ZEND_ASSIGN_OBJ_OP: case ZEND_ASSIGN_STATIC_PROP_OP: @@ -310,22 +310,22 @@ static bool is_escape_use(zend_op_array *op_array, zend_ssa *ssa, int use, int v case ZEND_INIT_ARRAY: case ZEND_ADD_ARRAY_ELEMENT: if (opline->extended_value & ZEND_ARRAY_ELEMENT_REF) { - return 1; + return true; } if (OP1_INFO() & MAY_BE_OBJECT) { /* object aliasing */ - return 1; + return true; } /* reference dependencies processed separately */ break; case ZEND_OP_DATA: if ((opline-1)->opcode != ZEND_ASSIGN_DIM && (opline-1)->opcode != ZEND_ASSIGN_OBJ) { - return 1; + return true; } if (OP1_INFO() & MAY_BE_OBJECT) { /* object aliasing */ - return 1; + return true; } opline--; ssa_op--; @@ -333,12 +333,12 @@ static bool is_escape_use(zend_op_array *op_array, zend_ssa *ssa, int use, int v || (OP1_INFO() & MAY_BE_REF) || (ssa_op->op1_def >= 0 && ssa->vars[ssa_op->op1_def].alias)) { /* assignment into escaping structure */ - return 1; + return true; } /* reference dependencies processed separately */ break; default: - return 1; + return true; } } @@ -349,17 +349,17 @@ static bool is_escape_use(zend_op_array *op_array, zend_ssa *ssa, int use, int v || (OP1_INFO() & MAY_BE_REF) || (ssa_op->op1_def >= 0 && ssa->vars[ssa_op->op1_def].alias)) { /* assignment into escaping variable */ - return 1; + return true; } if (opline->op2_type == IS_CV || opline->result_type != IS_UNUSED) { if (OP2_INFO() & MAY_BE_OBJECT) { /* object aliasing */ - return 1; + return true; } } break; default: - return 1; + return true; } } @@ -371,11 +371,11 @@ static bool is_escape_use(zend_op_array *op_array, zend_ssa *ssa, int use, int v case ZEND_ADD_ARRAY_ELEMENT: break; default: - return 1; + return true; } } - return 0; + return false; } /* }}} */ @@ -393,12 +393,12 @@ zend_result zend_ssa_escape_analysis(const zend_script *script, zend_op_array *o return SUCCESS; } - has_allocations = 0; + has_allocations = false; for (i = op_array->last_var; i < ssa_vars_count; i++) { if (ssa_vars[i].definition >= 0 && (ssa->var_info[i].type & (MAY_BE_ARRAY|MAY_BE_OBJECT)) && is_allocation_def(op_array, ssa, ssa_vars[i].definition, i, script)) { - has_allocations = 1; + has_allocations = true; break; } } @@ -470,7 +470,7 @@ zend_result zend_ssa_escape_analysis(const zend_script *script, zend_op_array *o bool changed; do { - changed = 0; + changed = false; for (i = 0; i < ssa_vars_count; i++) { if (ssa_vars[i].use_chain >= 0) { root = ees[i]; @@ -506,13 +506,13 @@ zend_result zend_ssa_escape_analysis(const zend_script *script, zend_op_array *o if (ssa_vars[root].escape_state == ESCAPE_STATE_GLOBAL_ESCAPE) { num_non_escaped--; if (num_non_escaped == 0) { - changed = 0; + changed = false; } else { - changed = 1; + changed = true; } break; } else { - changed = 1; + changed = true; } } } FOREACH_USE_END(); diff --git a/Zend/Optimizer/nop_removal.c b/Zend/Optimizer/nop_removal.c index fd5a87cbfb287..7de3919ee8cb2 100644 --- a/Zend/Optimizer/nop_removal.c +++ b/Zend/Optimizer/nop_removal.c @@ -32,21 +32,20 @@ void zend_optimizer_nop_removal(zend_op_array *op_array, zend_optimizer_ctx *ctx) { - zend_op *end, *opline; + zend_op *opline; uint32_t new_count, i, shift; - int j; uint32_t *shiftlist; ALLOCA_FLAG(use_heap); shiftlist = (uint32_t *)do_alloca(sizeof(uint32_t) * op_array->last, use_heap); i = new_count = shift = 0; - end = op_array->opcodes + op_array->last; + const zend_op *end = op_array->opcodes + op_array->last; for (opline = op_array->opcodes; opline < end; opline++) { /* Kill JMP-over-NOP-s */ if (opline->opcode == ZEND_JMP && ZEND_OP1_JMP_ADDR(opline) > op_array->opcodes + i) { /* check if there are only NOPs under the branch */ - zend_op *target = ZEND_OP1_JMP_ADDR(opline) - 1; + const zend_op *target = ZEND_OP1_JMP_ADDR(opline) - 1; while (target->opcode == ZEND_NOP) { target--; @@ -81,7 +80,7 @@ void zend_optimizer_nop_removal(zend_op_array *op_array, zend_optimizer_ctx *ctx } /* update try/catch array */ - for (j = 0; j < op_array->last_try_catch; j++) { + for (uint32_t j = 0; j < op_array->last_try_catch; j++) { op_array->try_catch_array[j].try_op -= shiftlist[op_array->try_catch_array[j].try_op]; op_array->try_catch_array[j].catch_op -= shiftlist[op_array->try_catch_array[j].catch_op]; if (op_array->try_catch_array[j].finally_op) { diff --git a/Zend/Optimizer/optimize_func_calls.c b/Zend/Optimizer/optimize_func_calls.c index 8b29f47c94976..62b50464e87ba 100644 --- a/Zend/Optimizer/optimize_func_calls.c +++ b/Zend/Optimizer/optimize_func_calls.c @@ -37,7 +37,7 @@ typedef struct _optimizer_call_info { uint32_t func_arg_num; } optimizer_call_info; -static void zend_delete_call_instructions(zend_op_array *op_array, zend_op *opline) +static void zend_delete_call_instructions(const zend_op_array *op_array, zend_op *opline) { int call = 0; @@ -76,7 +76,7 @@ static void zend_delete_call_instructions(zend_op_array *op_array, zend_op *opli } } -static void zend_try_inline_call(zend_op_array *op_array, zend_op *fcall, zend_op *opline, zend_function *func) +static void zend_try_inline_call(zend_op_array *op_array, const zend_op *fcall, zend_op *opline, const zend_function *func) { const uint32_t no_discard = RETURN_VALUE_USED(opline) ? 0 : ZEND_ACC_NODISCARD; @@ -153,7 +153,7 @@ static bool has_known_send_mode(const optimizer_call_info *info, uint32_t arg_nu void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx) { zend_op *opline = op_array->opcodes; - zend_op *end = opline + op_array->last; + const zend_op *end = opline + op_array->last; int call = 0; void *checkpoint; optimizer_call_info *call_stack; @@ -237,7 +237,7 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx) } call_stack[call].func = NULL; call_stack[call].opline = NULL; - call_stack[call].try_inline = 0; + call_stack[call].try_inline = false; call_stack[call].func_arg_num = (uint32_t)-1; break; case ZEND_FETCH_FUNC_ARG: @@ -265,7 +265,7 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx) && opline->op2_type == IS_UNUSED) { /* FETCH_DIM_FUNC_ARG supports UNUSED op2, while FETCH_DIM_R does not. * Performing the replacement would create an invalid opcode. */ - call_stack[call - 1].try_inline = 0; + call_stack[call - 1].try_inline = false; break; } @@ -279,7 +279,7 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx) break; case ZEND_SEND_VAL_EX: if (opline->op2_type == IS_CONST) { - call_stack[call - 1].try_inline = 0; + call_stack[call - 1].try_inline = false; break; } @@ -291,7 +291,7 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx) break; case ZEND_CHECK_FUNC_ARG: if (opline->op2_type == IS_CONST) { - call_stack[call - 1].try_inline = 0; + call_stack[call - 1].try_inline = false; call_stack[call - 1].func_arg_num = (uint32_t)-1; break; } @@ -305,7 +305,7 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx) /* Don't transform SEND_FUNC_ARG if any FETCH opcodes weren't transformed. */ if (call_stack[call - 1].last_check_func_arg_opline == NULL) { if (opline->op2_type == IS_CONST) { - call_stack[call - 1].try_inline = 0; + call_stack[call - 1].try_inline = false; } break; } @@ -314,7 +314,7 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx) ZEND_FALLTHROUGH; case ZEND_SEND_VAR_EX: if (opline->op2_type == IS_CONST) { - call_stack[call - 1].try_inline = 0; + call_stack[call - 1].try_inline = false; break; } @@ -329,7 +329,7 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx) break; case ZEND_SEND_VAR_NO_REF_EX: if (opline->op2_type == IS_CONST) { - call_stack[call - 1].try_inline = 0; + call_stack[call - 1].try_inline = false; break; } @@ -347,14 +347,14 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx) case ZEND_SEND_VAR: case ZEND_SEND_REF: if (opline->op2_type == IS_CONST) { - call_stack[call - 1].try_inline = 0; + call_stack[call - 1].try_inline = false; break; } break; case ZEND_SEND_UNPACK: case ZEND_SEND_USER: case ZEND_SEND_ARRAY: - call_stack[call - 1].try_inline = 0; + call_stack[call - 1].try_inline = false; break; default: break; diff --git a/Zend/Optimizer/pass1.c b/Zend/Optimizer/pass1.c index fe92db583fcd9..4be966c25d896 100644 --- a/Zend/Optimizer/pass1.c +++ b/Zend/Optimizer/pass1.c @@ -149,7 +149,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) if (opline->op2_type == IS_CONST && Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) { /* substitute persistent constants */ - if (!zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP2_LITERAL(opline)), &result, 1)) { + if (!zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP2_LITERAL(opline)), &result, true)) { if (!ctx->constants || !zend_optimizer_get_collected_constant(ctx->constants, &ZEND_OP2_LITERAL(opline), &result)) { break; } @@ -171,7 +171,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) if (Z_TYPE_P(c) == IS_CONSTANT_AST) { zend_ast *ast = Z_ASTVAL_P(c); if (ast->kind != ZEND_AST_CONSTANT - || !zend_optimizer_get_persistent_constant(zend_ast_get_constant_name(ast), &result, 1) + || !zend_optimizer_get_persistent_constant(zend_ast_get_constant_name(ast), &result, true) || Z_TYPE(result) == IS_CONSTANT_AST) { break; } @@ -193,7 +193,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) if (send1_opline->opcode != ZEND_SEND_VAL || send1_opline->op1_type != IS_CONST) { /* don't collect constants after unknown function call */ - collect_constants = 0; + collect_constants = false; break; } if (send1_opline->op2.num == 2) { @@ -205,7 +205,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) if (send1_opline->opcode != ZEND_SEND_VAL || send1_opline->op1_type != IS_CONST) { /* don't collect constants after unknown function call */ - collect_constants = 0; + collect_constants = false; break; } } @@ -217,7 +217,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) init_opline->op2_type != IS_CONST || Z_TYPE(ZEND_OP2_LITERAL(init_opline)) != IS_STRING) { /* don't collect constants after unknown function call */ - collect_constants = 0; + collect_constants = false; break; } @@ -261,9 +261,19 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) } /* don't collect constants after any other function call */ - collect_constants = 0; + collect_constants = false; break; } + case ZEND_DO_UCALL: + case ZEND_DO_FCALL: + case ZEND_DO_FCALL_BY_NAME: + case ZEND_FRAMELESS_ICALL_0: + case ZEND_FRAMELESS_ICALL_1: + case ZEND_FRAMELESS_ICALL_2: + case ZEND_FRAMELESS_ICALL_3: + /* don't collect constants after any UCALL/FCALL/FRAMELESS ICALL */ + collect_constants = 0; + break; case ZEND_STRLEN: if (opline->op1_type == IS_CONST && zend_optimizer_eval_strlen(&result, &ZEND_OP1_LITERAL(opline)) == SUCCESS) { @@ -271,7 +281,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) } break; case ZEND_DEFINED: - if (!zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline)), &result, 0)) { + if (!zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline)), &result, false)) { break; } ZVAL_TRUE(&result); @@ -309,7 +319,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) } } } - collect_constants = 0; + collect_constants = false; break; case ZEND_JMPZ: @@ -331,7 +341,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) break; } } - collect_constants = 0; + collect_constants = false; break; case ZEND_RETURN: @@ -354,7 +364,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) case ZEND_VERIFY_NEVER_TYPE: case ZEND_BIND_INIT_STATIC_OR_JMP: case ZEND_JMP_FRAMELESS: - collect_constants = 0; + collect_constants = false; break; } opline++; diff --git a/Zend/Optimizer/pass3.c b/Zend/Optimizer/pass3.c index 2cbd0e3406521..5c31de7bc49c4 100644 --- a/Zend/Optimizer/pass3.c +++ b/Zend/Optimizer/pass3.c @@ -37,10 +37,10 @@ static zend_always_inline bool in_hitlist(zend_op *target, zend_op **jmp_hitlist for (i = 0; i < jmp_hitlist_count; i++) { if (jmp_hitlist[i] == target) { - return 1; + return true; } } - return 0; + return false; } #define CHECK_LOOP(target) \ diff --git a/Zend/Optimizer/sccp.c b/Zend/Optimizer/sccp.c index c86672a8dd248..38a28dcd48894 100644 --- a/Zend/Optimizer/sccp.c +++ b/Zend/Optimizer/sccp.c @@ -244,7 +244,7 @@ static bool can_replace_op1( case ZEND_SEND_ARRAY: case ZEND_SEND_USER: case ZEND_FE_RESET_RW: - return 0; + return false; /* Do not accept CONST */ case ZEND_ROPE_ADD: case ZEND_ROPE_END: @@ -254,7 +254,7 @@ static bool can_replace_op1( case ZEND_MAKE_REF: case ZEND_UNSET_CV: case ZEND_ISSET_ISEMPTY_CV: - return 0; + return false; case ZEND_INIT_ARRAY: case ZEND_ADD_ARRAY_ELEMENT: return !(opline->extended_value & ZEND_ARRAY_ELEMENT_REF); @@ -262,18 +262,18 @@ static bool can_replace_op1( return !(op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE); case ZEND_VERIFY_RETURN_TYPE: // TODO: This would require a non-local change ??? - return 0; + return false; case ZEND_OP_DATA: return (opline - 1)->opcode != ZEND_ASSIGN_OBJ_REF && (opline - 1)->opcode != ZEND_ASSIGN_STATIC_PROP_REF; default: if (ssa_op->op1_def != -1) { ZEND_UNREACHABLE(); - return 0; + return false; } } - return 1; + return true; } static bool can_replace_op2( @@ -284,9 +284,9 @@ static bool can_replace_op2( case ZEND_BIND_LEXICAL: case ZEND_FE_FETCH_R: case ZEND_FE_FETCH_RW: - return 0; + return false; } - return 1; + return true; } static bool try_replace_op1( @@ -295,11 +295,11 @@ static bool try_replace_op1( zval zv; ZVAL_COPY(&zv, value); if (zend_optimizer_update_op1_const(ctx->scdf.op_array, opline, &zv)) { - return 1; + return true; } zval_ptr_dtor_nogc(&zv); } - return 0; + return false; } static bool try_replace_op2( @@ -308,11 +308,11 @@ static bool try_replace_op2( zval zv; ZVAL_COPY(&zv, value); if (zend_optimizer_update_op2_const(ctx->scdf.op_array, opline, &zv)) { - return 1; + return true; } zval_ptr_dtor_nogc(&zv); } - return 0; + return false; } static inline zend_result ct_eval_binary_op(zval *result, uint8_t binop, zval *op1, zval *op2) { @@ -335,6 +335,10 @@ static inline zend_result ct_eval_bool_cast(zval *result, zval *op) { ZVAL_TRUE(result); return SUCCESS; } + /* NAN warns when casting */ + if (Z_TYPE_P(op) == IS_DOUBLE && zend_isnan(Z_DVAL_P(op))) { + return FAILURE; + } ZVAL_BOOL(result, zend_is_true(op)); return SUCCESS; @@ -371,7 +375,7 @@ static inline zend_result fetch_array_elem(zval **result, zval *op1, zval *op2) *result = zend_hash_index_find(Z_ARR_P(op1), Z_LVAL_P(op2)); return SUCCESS; case IS_DOUBLE: { - zend_long lval = zend_dval_to_lval(Z_DVAL_P(op2)); + zend_long lval = zend_dval_to_lval_silent(Z_DVAL_P(op2)); if (!zend_is_long_compatible(Z_DVAL_P(op2), lval)) { return FAILURE; } @@ -459,7 +463,7 @@ static inline zend_result ct_eval_del_array_elem(zval *result, const zval *key) zend_hash_index_del(Z_ARR_P(result), Z_LVAL_P(key)); break; case IS_DOUBLE: { - zend_long lval = zend_dval_to_lval(Z_DVAL_P(key)); + zend_long lval = zend_dval_to_lval_silent(Z_DVAL_P(key)); if (!zend_is_long_compatible(Z_DVAL_P(key), lval)) { return FAILURE; } @@ -504,7 +508,7 @@ static inline zend_result ct_eval_add_array_elem(zval *result, zval *value, cons value = zend_hash_index_update(Z_ARR_P(result), Z_LVAL_P(key), value); break; case IS_DOUBLE: { - zend_long lval = zend_dval_to_lval(Z_DVAL_P(key)); + zend_long lval = zend_dval_to_lval_silent(Z_DVAL_P(key)); if (!zend_is_long_compatible(Z_DVAL_P(key), lval)) { return FAILURE; } @@ -714,7 +718,7 @@ static inline zend_result ct_eval_in_array(zval *result, uint32_t extended_value if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { res = zend_hash_index_exists(ht, Z_LVAL_P(op1)); } else { - res = 0; + res = false; } } else if (Z_TYPE_P(op1) <= IS_FALSE) { res = zend_hash_exists(ht, ZSTR_EMPTY_ALLOC()); @@ -722,11 +726,11 @@ static inline zend_result ct_eval_in_array(zval *result, uint32_t extended_value zend_string *key; zval key_tmp; - res = 0; + res = false; ZEND_HASH_MAP_FOREACH_STR_KEY(ht, key) { ZVAL_STR(&key_tmp, key); if (zend_compare(op1, &key_tmp) == 0) { - res = 1; + res = true; break; } } ZEND_HASH_FOREACH_END(); @@ -838,9 +842,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; } @@ -1104,6 +1106,11 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o if (op2) { SKIP_IF_TOP(op2); + if (Z_TYPE_P(op2) == IS_NULL) { + /* Emits deprecation at run-time. */ + SET_RESULT_BOT(result); + return; + } } /* We want to avoid keeping around intermediate arrays for each SSA variable in the @@ -1648,7 +1655,6 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o { zend_call_info *call; zval *name, *args[3] = {NULL}; - int i; if (!ctx->call_map) { SET_RESULT_BOT(result); @@ -1670,7 +1676,7 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o break; } - for (i = 0; i < call->num_args; i++) { + for (uint32_t i = 0; i < call->num_args; i++) { zend_op *opline = call->arg_info[i].opline; if (opline->opcode != ZEND_SEND_VAL && opline->opcode != ZEND_SEND_VAR) { SET_RESULT_BOT(result); @@ -2036,7 +2042,7 @@ static void join_phi_values(zval *a, zval *b, bool escape) { } } -static void sccp_visit_phi(scdf_ctx *scdf, zend_ssa_phi *phi) { +static void sccp_visit_phi(scdf_ctx *scdf, const zend_ssa_phi *phi) { sccp_ctx *ctx = (sccp_ctx *) scdf; zend_ssa *ssa = scdf->ssa; ZEND_ASSERT(phi->ssa_var >= 0); @@ -2086,7 +2092,6 @@ static int remove_call(sccp_ctx *ctx, zend_op *opline, zend_ssa_op *ssa_op) zend_ssa *ssa = ctx->scdf.ssa; zend_op_array *op_array = ctx->scdf.op_array; zend_call_info *call; - int i; ZEND_ASSERT(ctx->call_map); call = ctx->call_map[opline - op_array->opcodes]; @@ -2096,7 +2101,7 @@ static int remove_call(sccp_ctx *ctx, zend_op *opline, zend_ssa_op *ssa_op) zend_ssa_remove_instr(ssa, call->caller_init_opline, &ssa->ops[call->caller_init_opline - op_array->opcodes]); - for (i = 0; i < call->num_args; i++) { + for (uint32_t i = 0; i < call->num_args; i++) { zend_ssa_remove_instr(ssa, call->arg_info[i].opline, &ssa->ops[call->arg_info[i].opline - op_array->opcodes]); } @@ -2120,11 +2125,11 @@ static int remove_call(sccp_ctx *ctx, zend_op *opline, zend_ssa_op *ssa_op) * we need to collect. * d) The ordinary DCE pass cannot collect construction of dead non-escaping arrays and objects. */ -static int try_remove_definition(sccp_ctx *ctx, int var_num, zend_ssa_var *var, zval *value) +static uint32_t try_remove_definition(sccp_ctx *ctx, int var_num, zend_ssa_var *var, zval *value) { zend_ssa *ssa = ctx->scdf.ssa; zend_op_array *op_array = ctx->scdf.op_array; - int removed_ops = 0; + uint32_t removed_ops = 0; if (var->definition >= 0) { zend_op *opline = &op_array->opcodes[var->definition]; @@ -2368,12 +2373,12 @@ static int try_remove_definition(sccp_ctx *ctx, int var_num, zend_ssa_var *var, /* This will try to replace uses of SSA variables we have determined to be constant. Not all uses * can be replaced, because some instructions don't accept constant operands or only accept them * if they have a certain type. */ -static int replace_constant_operands(sccp_ctx *ctx) { +static uint32_t replace_constant_operands(sccp_ctx *ctx) { zend_ssa *ssa = ctx->scdf.ssa; zend_op_array *op_array = ctx->scdf.op_array; int i; zval tmp; - int removed_ops = 0; + uint32_t removed_ops = 0; /* We iterate the variables backwards, so we can eliminate sequences like INIT_ROPE * and INIT_ARRAY. */ @@ -2466,10 +2471,10 @@ static void sccp_context_free(sccp_ctx *sccp) { } } -int sccp_optimize_op_array(zend_optimizer_ctx *ctx, zend_op_array *op_array, zend_ssa *ssa, zend_call_info **call_map) +uint32_t sccp_optimize_op_array(zend_optimizer_ctx *ctx, zend_op_array *op_array, zend_ssa *ssa, zend_call_info **call_map) { sccp_ctx sccp; - int removed_ops = 0; + uint32_t removed_ops = 0; void *checkpoint = zend_arena_checkpoint(ctx->arena); sccp_context_init(ctx, &sccp, ssa, op_array, call_map); diff --git a/Zend/Optimizer/scdf.c b/Zend/Optimizer/scdf.c index 54925e8287b62..e5c40b8c90cf9 100644 --- a/Zend/Optimizer/scdf.c +++ b/Zend/Optimizer/scdf.c @@ -70,9 +70,8 @@ void scdf_mark_edge_feasible(scdf_ctx *scdf, int from, int to) { } else { /* Block is already executable, only a new edge became feasible. * Reevaluate phi nodes to account for changed source operands. */ - zend_ssa_block *ssa_block = &scdf->ssa->blocks[to]; - zend_ssa_phi *phi; - for (phi = ssa_block->phis; phi; phi = phi->next) { + const zend_ssa_block *ssa_block = &scdf->ssa->blocks[to]; + for (const zend_ssa_phi *phi = ssa_block->phis; phi; phi = phi->next) { zend_bitset_excl(scdf->phi_var_worklist, phi->ssa_var); scdf->handlers.visit_phi(scdf, phi); } @@ -101,7 +100,7 @@ void scdf_init(zend_optimizer_ctx *ctx, scdf_ctx *scdf, zend_op_array *op_array, } void scdf_solve(scdf_ctx *scdf, const char *name) { - zend_ssa *ssa = scdf->ssa; + const zend_ssa *ssa = scdf->ssa; DEBUG_PRINT("Start SCDF solve (%s)\n", name); while (!zend_bitset_empty(scdf->instr_worklist, scdf->instr_worklist_len) || !zend_bitset_empty(scdf->phi_var_worklist, scdf->phi_var_worklist_len) @@ -109,7 +108,7 @@ void scdf_solve(scdf_ctx *scdf, const char *name) { ) { int i; while ((i = zend_bitset_pop_first(scdf->phi_var_worklist, scdf->phi_var_worklist_len)) >= 0) { - zend_ssa_phi *phi = ssa->vars[i].definition_phi; + const zend_ssa_phi *phi = ssa->vars[i].definition_phi; ZEND_ASSERT(phi); if (zend_bitset_in(scdf->executable_blocks, phi->block)) { scdf->handlers.visit_phi(scdf, phi); @@ -140,17 +139,14 @@ void scdf_solve(scdf_ctx *scdf, const char *name) { while ((i = zend_bitset_pop_first(scdf->block_worklist, scdf->block_worklist_len)) >= 0) { /* This block is now live. Interpret phis and instructions in it. */ zend_basic_block *block = &ssa->cfg.blocks[i]; - zend_ssa_block *ssa_block = &ssa->blocks[i]; + const zend_ssa_block *ssa_block = &ssa->blocks[i]; DEBUG_PRINT("Pop block %d from worklist\n", i); zend_bitset_incl(scdf->executable_blocks, i); - { - zend_ssa_phi *phi; - for (phi = ssa_block->phis; phi; phi = phi->next) { - zend_bitset_excl(scdf->phi_var_worklist, phi->ssa_var); - scdf->handlers.visit_phi(scdf, phi); - } + for (const zend_ssa_phi *phi = ssa_block->phis; phi; phi = phi->next) { + zend_bitset_excl(scdf->phi_var_worklist, phi->ssa_var); + scdf->handlers.visit_phi(scdf, phi); } if (block->len == 0) { @@ -158,7 +154,7 @@ void scdf_solve(scdf_ctx *scdf, const char *name) { scdf_mark_edge_feasible(scdf, i, block->successors[0]); } else { zend_op *opline = NULL; - int j, end = block->start + block->len; + uint32_t j, end = block->start + block->len; for (j = block->start; j < end; j++) { opline = &scdf->op_array->opcodes[j]; zend_bitset_excl(scdf->instr_worklist, j); @@ -185,7 +181,7 @@ void scdf_solve(scdf_ctx *scdf, const char *name) { * not eliminate the latter. While it cannot be reached, the FREE opcode of the loop var * is necessary for the correctness of temporary compaction. */ static bool is_live_loop_var_free( - scdf_ctx *scdf, const zend_op *opline, const zend_ssa_op *ssa_op) { + const scdf_ctx *scdf, const zend_op *opline, const zend_ssa_op *ssa_op) { if (!zend_optimizer_is_loop_var_free(opline)) { return false; } @@ -195,7 +191,7 @@ static bool is_live_loop_var_free( return false; } - zend_ssa_var *ssa_var = &scdf->ssa->vars[var]; + const zend_ssa_var *ssa_var = &scdf->ssa->vars[var]; uint32_t def_block; if (ssa_var->definition >= 0) { def_block = scdf->ssa->cfg.map[ssa_var->definition]; @@ -205,7 +201,7 @@ static bool is_live_loop_var_free( return zend_bitset_in(scdf->executable_blocks, def_block); } -static bool kept_alive_by_loop_var_free(scdf_ctx *scdf, const zend_basic_block *block) { +static bool kept_alive_by_loop_var_free(const scdf_ctx *scdf, const zend_basic_block *block) { const zend_op_array *op_array = scdf->op_array; const zend_cfg *cfg = &scdf->ssa->cfg; if (!(cfg->flags & ZEND_FUNC_FREE_LOOP_VAR)) { @@ -220,7 +216,7 @@ static bool kept_alive_by_loop_var_free(scdf_ctx *scdf, const zend_basic_block * return false; } -static uint32_t cleanup_loop_var_free_block(scdf_ctx *scdf, zend_basic_block *block) { +static uint32_t cleanup_loop_var_free_block(const scdf_ctx *scdf, const zend_basic_block *block) { zend_ssa *ssa = scdf->ssa; const zend_op_array *op_array = scdf->op_array; const zend_cfg *cfg = &ssa->cfg; @@ -256,12 +252,12 @@ static uint32_t cleanup_loop_var_free_block(scdf_ctx *scdf, zend_basic_block *bl /* Removes unreachable blocks. This will remove both the instructions (and phis) in the * blocks, as well as remove them from the successor / predecessor lists and mark them * unreachable. Blocks already marked unreachable are not removed. */ -uint32_t scdf_remove_unreachable_blocks(scdf_ctx *scdf) { +uint32_t scdf_remove_unreachable_blocks(const scdf_ctx *scdf) { zend_ssa *ssa = scdf->ssa; int i; uint32_t removed_ops = 0; for (i = 0; i < ssa->cfg.blocks_count; i++) { - zend_basic_block *block = &ssa->cfg.blocks[i]; + const zend_basic_block *block = &ssa->cfg.blocks[i]; if (!zend_bitset_in(scdf->executable_blocks, i) && (block->flags & ZEND_BB_REACHABLE)) { if (!kept_alive_by_loop_var_free(scdf, block)) { removed_ops += block->len; diff --git a/Zend/Optimizer/scdf.h b/Zend/Optimizer/scdf.h index 0d90147e84cb1..49222880f22b8 100644 --- a/Zend/Optimizer/scdf.h +++ b/Zend/Optimizer/scdf.h @@ -39,7 +39,7 @@ typedef struct _scdf_ctx { void (*visit_instr)( struct _scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_op); void (*visit_phi)( - struct _scdf_ctx *scdf, zend_ssa_phi *phi); + struct _scdf_ctx *scdf, const zend_ssa_phi *phi); void (*mark_feasible_successors)( struct _scdf_ctx *scdf, int block_num, zend_basic_block *block, zend_op *opline, zend_ssa_op *ssa_op); @@ -49,10 +49,10 @@ typedef struct _scdf_ctx { void scdf_init(zend_optimizer_ctx *ctx, scdf_ctx *scdf, zend_op_array *op_array, zend_ssa *ssa); void scdf_solve(scdf_ctx *scdf, const char *name); -uint32_t scdf_remove_unreachable_blocks(scdf_ctx *scdf); +uint32_t scdf_remove_unreachable_blocks(const scdf_ctx *scdf); /* Add uses to worklist */ -static inline void scdf_add_to_worklist(scdf_ctx *scdf, int var_num) { +static inline void scdf_add_to_worklist(const scdf_ctx *scdf, int var_num) { const zend_ssa *ssa = scdf->ssa; const zend_ssa_var *var = &ssa->vars[var_num]; int use; @@ -66,7 +66,7 @@ static inline void scdf_add_to_worklist(scdf_ctx *scdf, int var_num) { } /* This should usually not be necessary, however it's used for type narrowing. */ -static inline void scdf_add_def_to_worklist(scdf_ctx *scdf, int var_num) { +static inline void scdf_add_def_to_worklist(const scdf_ctx *scdf, int var_num) { const zend_ssa_var *var = &scdf->ssa->vars[var_num]; if (var->definition >= 0) { zend_bitset_incl(scdf->instr_worklist, var->definition); diff --git a/Zend/Optimizer/ssa_integrity.c b/Zend/Optimizer/ssa_integrity.c index b525f8d5ee226..793fb1c06c8b0 100644 --- a/Zend/Optimizer/ssa_integrity.c +++ b/Zend/Optimizer/ssa_integrity.c @@ -25,20 +25,20 @@ static inline bool is_in_use_chain(zend_ssa *ssa, int var, int check) { int use; FOREACH_USE(&ssa->vars[var], use) { if (use == check) { - return 1; + return true; } } FOREACH_USE_END(); - return 0; + return false; } static inline bool is_in_phi_use_chain(zend_ssa *ssa, int var, zend_ssa_phi *check) { zend_ssa_phi *phi; FOREACH_PHI_USE(&ssa->vars[var], phi) { if (phi == check) { - return 1; + return true; } } FOREACH_PHI_USE_END(); - return 0; + return false; } static inline bool is_used_by_op(zend_ssa *ssa, int op, int check) { @@ -59,30 +59,30 @@ static inline bool is_in_phi_sources(zend_ssa *ssa, zend_ssa_phi *phi, int check int source; FOREACH_PHI_SOURCE(phi, source) { if (source == check) { - return 1; + return true; } } FOREACH_PHI_SOURCE_END(); - return 0; + return false; } static inline bool is_in_predecessors(zend_cfg *cfg, zend_basic_block *block, int check) { int i, *predecessors = &cfg->predecessors[block->predecessor_offset]; for (i = 0; i < block->predecessors_count; i++) { if (predecessors[i] == check) { - return 1; + return true; } } - return 0; + return false; } static inline bool is_in_successors(zend_basic_block *block, int check) { int s; for (s = 0; s < block->successors_count; s++) { if (block->successors[s] == check) { - return 1; + return true; } } - return 0; + return false; } static inline bool is_var_type(uint8_t type) { diff --git a/Zend/Optimizer/zend_call_graph.c b/Zend/Optimizer/zend_call_graph.c index 8a2f8ea2a7e1a..645edd2f99914 100644 --- a/Zend/Optimizer/zend_call_graph.c +++ b/Zend/Optimizer/zend_call_graph.c @@ -146,7 +146,7 @@ ZEND_API void zend_analyze_calls(zend_arena **arena, zend_script *script, uint32 case ZEND_SEND_USER: if (call_info) { if (opline->op2_type == IS_CONST) { - call_info->named_args = 1; + call_info->named_args = true; break; } @@ -160,7 +160,7 @@ ZEND_API void zend_analyze_calls(zend_arena **arena, zend_script *script, uint32 case ZEND_SEND_ARRAY: case ZEND_SEND_UNPACK: if (call_info) { - call_info->send_unpack = 1; + call_info->send_unpack = true; } break; } @@ -169,26 +169,26 @@ ZEND_API void zend_analyze_calls(zend_arena **arena, zend_script *script, uint32 free_alloca(call_stack, use_heap); } -static bool zend_is_indirectly_recursive(zend_op_array *root, zend_op_array *op_array, zend_bitset visited) +static bool zend_is_indirectly_recursive(const zend_op_array *root, const zend_op_array *op_array, zend_bitset visited) { - zend_func_info *func_info; + const zend_func_info *func_info; zend_call_info *call_info; - bool ret = 0; + bool ret = false; if (op_array == root) { - return 1; + return true; } func_info = ZEND_FUNC_INFO(op_array); if (zend_bitset_in(visited, func_info->num)) { - return 0; + return false; } zend_bitset_incl(visited, func_info->num); call_info = func_info->caller_info; while (call_info) { if (zend_is_indirectly_recursive(root, call_info->caller_op_array, visited)) { - call_info->recursive = 1; - ret = 1; + call_info->recursive = true; + ret = true; } call_info = call_info->next_caller; } @@ -197,16 +197,15 @@ static bool zend_is_indirectly_recursive(zend_op_array *root, zend_op_array *op_ static void zend_analyze_recursion(zend_call_graph *call_graph) { - zend_op_array *op_array; + const zend_op_array *op_array; zend_func_info *func_info; zend_call_info *call_info; - int i; - int set_len = zend_bitset_len(call_graph->op_arrays_count); + uint32_t set_len = zend_bitset_len(call_graph->op_arrays_count); zend_bitset visited; ALLOCA_FLAG(use_heap); visited = ZEND_BITSET_ALLOCA(set_len, use_heap); - for (i = 0; i < call_graph->op_arrays_count; i++) { + for (uint32_t i = 0; i < call_graph->op_arrays_count; i++) { op_array = call_graph->op_arrays[i]; func_info = call_graph->func_infos + i; call_info = func_info->caller_info; @@ -216,12 +215,12 @@ static void zend_analyze_recursion(zend_call_graph *call_graph) continue; } if (call_info->caller_op_array == op_array) { - call_info->recursive = 1; + call_info->recursive = true; func_info->flags |= ZEND_FUNC_RECURSIVE | ZEND_FUNC_RECURSIVE_DIRECTLY; } else { memset(visited, 0, sizeof(zend_ulong) * set_len); if (zend_is_indirectly_recursive(op_array, call_info->caller_op_array, visited)) { - call_info->recursive = 1; + call_info->recursive = true; func_info->flags |= ZEND_FUNC_RECURSIVE | ZEND_FUNC_RECURSIVE_INDIRECTLY; } } @@ -252,9 +251,7 @@ ZEND_API void zend_build_call_graph(zend_arena **arena, zend_script *script, zen ZEND_API void zend_analyze_call_graph(zend_arena **arena, zend_script *script, zend_call_graph *call_graph) /* {{{ */ { - int i; - - for (i = 0; i < call_graph->op_arrays_count; i++) { + for (uint32_t i = 0; i < call_graph->op_arrays_count; i++) { zend_analyze_calls(arena, script, 0, call_graph->op_arrays[i], call_graph->func_infos + i); } zend_analyze_recursion(call_graph); @@ -262,7 +259,7 @@ ZEND_API void zend_analyze_call_graph(zend_arena **arena, zend_script *script, z } /* }}} */ -ZEND_API zend_call_info **zend_build_call_map(zend_arena **arena, zend_func_info *info, const zend_op_array *op_array) /* {{{ */ +ZEND_API zend_call_info **zend_build_call_map(zend_arena **arena, const zend_func_info *info, const zend_op_array *op_array) /* {{{ */ { zend_call_info **map, *call; if (!info->callee_info) { @@ -272,13 +269,12 @@ ZEND_API zend_call_info **zend_build_call_map(zend_arena **arena, zend_func_info map = zend_arena_calloc(arena, sizeof(zend_call_info *), op_array->last); for (call = info->callee_info; call; call = call->next_callee) { - int i; map[call->caller_init_opline - op_array->opcodes] = call; if (call->caller_call_opline) { map[call->caller_call_opline - op_array->opcodes] = call; } if (!call->is_frameless) { - for (i = 0; i < call->num_args; i++) { + for (uint32_t i = 0; i < call->num_args; i++) { if (call->arg_info[i].opline) { map[call->arg_info[i].opline - op_array->opcodes] = call; } diff --git a/Zend/Optimizer/zend_call_graph.h b/Zend/Optimizer/zend_call_graph.h index b2cbb6822bcf3..8810dc1a560e7 100644 --- a/Zend/Optimizer/zend_call_graph.h +++ b/Zend/Optimizer/zend_call_graph.h @@ -39,12 +39,12 @@ struct _zend_call_info { bool named_args; /* Function has named arguments */ bool is_prototype; /* An overridden child method may be called */ bool is_frameless; /* A frameless function sends arguments through operands */ - int num_args; /* Number of arguments, excluding named and variadic arguments */ + uint32_t num_args; /* Number of arguments, excluding named and variadic arguments */ zend_send_arg_info arg_info[1]; }; struct _zend_func_info { - int num; + uint32_t num; uint32_t flags; zend_ssa ssa; /* Static Single Assignment Form */ zend_call_info *caller_info; /* where this function is called from */ @@ -54,7 +54,7 @@ struct _zend_func_info { }; typedef struct _zend_call_graph { - int op_arrays_count; + uint32_t op_arrays_count; zend_op_array **op_arrays; zend_func_info *func_infos; } zend_call_graph; @@ -63,7 +63,7 @@ BEGIN_EXTERN_C() ZEND_API void zend_build_call_graph(zend_arena **arena, zend_script *script, zend_call_graph *call_graph); ZEND_API void zend_analyze_call_graph(zend_arena **arena, zend_script *script, zend_call_graph *call_graph); -ZEND_API zend_call_info **zend_build_call_map(zend_arena **arena, zend_func_info *info, const zend_op_array *op_array); +ZEND_API zend_call_info **zend_build_call_map(zend_arena **arena, const zend_func_info *info, const zend_op_array *op_array); ZEND_API void zend_analyze_calls(zend_arena **arena, zend_script *script, uint32_t build_flags, zend_op_array *op_array, zend_func_info *func_info); END_EXTERN_C() diff --git a/Zend/Optimizer/zend_cfg.c b/Zend/Optimizer/zend_cfg.c index a0d08b67aa70c..32d5f49ef7df4 100644 --- a/Zend/Optimizer/zend_cfg.c +++ b/Zend/Optimizer/zend_cfg.c @@ -274,13 +274,12 @@ ZEND_API void zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, { uint32_t flags = 0; uint32_t i; - int j; uint32_t *block_map; zend_function *fn; int blocks_count = 0; zend_basic_block *blocks; zval *zv; - bool extra_entry_block = 0; + bool extra_entry_block = false; cfg->flags = build_flags & (ZEND_CFG_STACKLESS|ZEND_CFG_RECV_ENTRY); @@ -445,11 +444,11 @@ ZEND_API void zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, /* If the entry block has predecessors, we may need to split it */ if ((build_flags & ZEND_CFG_NO_ENTRY_PREDECESSORS) && op_array->last > 0 && block_map[0] > 1) { - extra_entry_block = 1; + extra_entry_block = true; } if (op_array->last_try_catch) { - for (j = 0; j < op_array->last_try_catch; j++) { + for (uint32_t j = 0; j < op_array->last_try_catch; j++) { BB_START(op_array->try_catch_array[j].try_op); if (op_array->try_catch_array[j].catch_op) { BB_START(op_array->try_catch_array[j].catch_op); @@ -494,7 +493,7 @@ ZEND_API void zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, blocks_count++; /* Build CFG, Step 3: Calculate successors */ - for (j = 0; j < blocks_count; j++) { + for (int j = 0; j < blocks_count; j++) { zend_basic_block *block = &blocks[j]; zend_op *opline; if (block->len == 0) { diff --git a/Zend/Optimizer/zend_cfg.h b/Zend/Optimizer/zend_cfg.h index 93d455060686e..1f3885f511f5d 100644 --- a/Zend/Optimizer/zend_cfg.h +++ b/Zend/Optimizer/zend_cfg.h @@ -46,12 +46,12 @@ typedef struct _zend_basic_block { uint32_t len; /* number of opcodes */ int successors_count; /* number of successors */ int predecessors_count; /* number of predecessors */ - int predecessor_offset; /* offset of 1-st predecessor */ - int idom; /* immediate dominator block */ + int predecessor_offset; /* offset of 1-st predecessor, or -1 */ + int idom; /* immediate dominator block, or -1 */ int loop_header; /* closest loop header, or -1 */ - int level; /* steps away from the entry in the dom. tree */ - int children; /* list of dominated blocks */ - int next_child; /* next dominated block */ + int level; /* steps away from the entry in the dom. tree, or -1 */ + int children; /* list of dominated blocks, or -1 */ + int next_child; /* next dominated block, or -1 */ int successors_storage[2]; /* up to 2 successor blocks */ } zend_basic_block; diff --git a/Zend/Optimizer/zend_dfg.c b/Zend/Optimizer/zend_dfg.c index 101523141be94..c14d67e873a24 100644 --- a/Zend/Optimizer/zend_dfg.c +++ b/Zend/Optimizer/zend_dfg.c @@ -19,7 +19,7 @@ #include "zend_compile.h" #include "zend_dfg.h" -static zend_always_inline void _zend_dfg_add_use_def_op(const zend_op_array *op_array, const zend_op *opline, uint32_t build_flags, zend_bitset use, zend_bitset def) /* {{{ */ +static zend_always_inline void zend_dfg_add_use_def_op_impl(const zend_op_array *op_array, const zend_op *opline, uint32_t build_flags, zend_bitset use, zend_bitset def) /* {{{ */ { uint32_t var_num; const zend_op *next; @@ -245,20 +245,19 @@ static zend_always_inline void _zend_dfg_add_use_def_op(const zend_op_array *op_ ZEND_API void zend_dfg_add_use_def_op(const zend_op_array *op_array, const zend_op *opline, uint32_t build_flags, zend_bitset use, zend_bitset def) /* {{{ */ { - _zend_dfg_add_use_def_op(op_array, opline, build_flags, use, def); + zend_dfg_add_use_def_op_impl(op_array, opline, build_flags, use, def); } /* }}} */ -void zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg *dfg, uint32_t build_flags) /* {{{ */ +void zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, const zend_dfg *dfg, uint32_t build_flags) /* {{{ */ { - int set_size; + uint32_t set_size = dfg->size; zend_basic_block *blocks = cfg->blocks; int blocks_count = cfg->blocks_count; zend_bitset tmp, def, use, in, out; int k; int j; - set_size = dfg->size; tmp = dfg->tmp; def = dfg->def; use = dfg->use; @@ -267,7 +266,7 @@ void zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg /* Collect "def" and "use" sets */ for (j = 0; j < blocks_count; j++) { - zend_op *opline, *end; + const zend_op *opline, *end; zend_bitset b_use, b_def; if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0) { @@ -280,7 +279,7 @@ void zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg b_def = DFG_BITSET(def, set_size, j); for (; opline < end; opline++) { if (opline->opcode != ZEND_OP_DATA) { - _zend_dfg_add_use_def_op(op_array, opline, build_flags, b_use, b_def); + zend_dfg_add_use_def_op_impl(op_array, opline, build_flags, b_use, b_def); } } } @@ -318,7 +317,7 @@ void zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg /* Add predecessors of changed block to worklist */ { - int *predecessors = &cfg->predecessors[blocks[j].predecessor_offset]; + const int *predecessors = &cfg->predecessors[blocks[j].predecessor_offset]; for (k = 0; k < blocks[j].predecessors_count; k++) { zend_bitset_incl(worklist, predecessors[k]); } diff --git a/Zend/Optimizer/zend_dfg.h b/Zend/Optimizer/zend_dfg.h index b59dc62790901..af3d761ba29f8 100644 --- a/Zend/Optimizer/zend_dfg.h +++ b/Zend/Optimizer/zend_dfg.h @@ -43,7 +43,7 @@ typedef struct _zend_dfg { BEGIN_EXTERN_C() -void zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg *dfg, uint32_t build_flags); +void zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, const zend_dfg *dfg, uint32_t build_flags); ZEND_API void zend_dfg_add_use_def_op(const zend_op_array *op_array, const zend_op *opline, uint32_t build_flags, zend_bitset use, zend_bitset def); END_EXTERN_C() diff --git a/Zend/Optimizer/zend_dump.c b/Zend/Optimizer/zend_dump.c index 4e46b38a8eb5e..9c51ad223e060 100644 --- a/Zend/Optimizer/zend_dump.c +++ b/Zend/Optimizer/zend_dump.c @@ -30,11 +30,11 @@ void zend_dump_ht(HashTable *ht) zend_ulong index; zend_string *key; zval *val; - bool first = 1; + bool first = true; ZEND_HASH_FOREACH_KEY_VAL(ht, index, key, val) { if (first) { - first = 0; + first = false; } else { fprintf(stderr, ", "); } @@ -188,36 +188,36 @@ static void zend_dump_range(const zend_ssa_range *r) static void zend_dump_type_info(uint32_t info, zend_class_entry *ce, int is_instanceof, uint32_t dump_flags) { - bool first = 1; + bool first = true; fprintf(stderr, " ["); if (info & MAY_BE_GUARD) { fprintf(stderr, "!"); } if (info & MAY_BE_UNDEF) { - if (first) first = 0; else fprintf(stderr, ", "); + if (first) first = false; else fprintf(stderr, ", "); fprintf(stderr, "undef"); } if (info & MAY_BE_INDIRECT) { - if (first) first = 0; else fprintf(stderr, ", "); + if (first) first = false; else fprintf(stderr, ", "); fprintf(stderr, "ind"); } if (info & MAY_BE_REF) { - if (first) first = 0; else fprintf(stderr, ", "); + if (first) first = false; else fprintf(stderr, ", "); fprintf(stderr, "ref"); } if (dump_flags & ZEND_DUMP_RC_INFERENCE) { if (info & MAY_BE_RC1) { - if (first) first = 0; else fprintf(stderr, ", "); + if (first) first = false; else fprintf(stderr, ", "); fprintf(stderr, "rc1"); } if (info & MAY_BE_RCN) { - if (first) first = 0; else fprintf(stderr, ", "); + if (first) first = false; else fprintf(stderr, ", "); fprintf(stderr, "rcn"); } } if (info & MAY_BE_CLASS) { - if (first) first = 0; else fprintf(stderr, ", "); + if (first) first = false; else fprintf(stderr, ", "); fprintf(stderr, "class"); if (ce) { if (is_instanceof) { @@ -227,37 +227,37 @@ static void zend_dump_type_info(uint32_t info, zend_class_entry *ce, int is_inst } } } else if ((info & MAY_BE_ANY) == MAY_BE_ANY) { - if (first) first = 0; else fprintf(stderr, ", "); + if (first) first = false; else fprintf(stderr, ", "); fprintf(stderr, "any"); } else { if (info & MAY_BE_NULL) { - if (first) first = 0; else fprintf(stderr, ", "); + if (first) first = false; else fprintf(stderr, ", "); fprintf(stderr, "null"); } if ((info & MAY_BE_FALSE) && (info & MAY_BE_TRUE)) { - if (first) first = 0; else fprintf(stderr, ", "); + if (first) first = false; else fprintf(stderr, ", "); fprintf(stderr, "bool"); } else if (info & MAY_BE_FALSE) { - if (first) first = 0; else fprintf(stderr, ", "); + if (first) first = false; else fprintf(stderr, ", "); fprintf(stderr, "false"); } else if (info & MAY_BE_TRUE) { - if (first) first = 0; else fprintf(stderr, ", "); + if (first) first = false; else fprintf(stderr, ", "); fprintf(stderr, "true"); } if (info & MAY_BE_LONG) { - if (first) first = 0; else fprintf(stderr, ", "); + if (first) first = false; else fprintf(stderr, ", "); fprintf(stderr, "long"); } if (info & MAY_BE_DOUBLE) { - if (first) first = 0; else fprintf(stderr, ", "); + if (first) first = false; else fprintf(stderr, ", "); fprintf(stderr, "double"); } if (info & MAY_BE_STRING) { - if (first) first = 0; else fprintf(stderr, ", "); + if (first) first = false; else fprintf(stderr, ", "); fprintf(stderr, "string"); } if (info & MAY_BE_ARRAY) { - if (first) first = 0; else fprintf(stderr, ", "); + if (first) first = false; else fprintf(stderr, ", "); if (info & MAY_BE_PACKED_GUARD) { fprintf(stderr, "!"); } @@ -268,18 +268,18 @@ static void zend_dump_type_info(uint32_t info, zend_class_entry *ce, int is_inst } else if (MAY_BE_HASH_ONLY(info)) { fprintf(stderr, "hash "); } else if ((info & MAY_BE_ARRAY_KEY_ANY) != MAY_BE_ARRAY_KEY_ANY && (info & MAY_BE_ARRAY_KEY_ANY) != 0) { - bool afirst = 1; + bool afirst = true; fprintf(stderr, "["); if (info & MAY_BE_ARRAY_EMPTY) { - if (afirst) afirst = 0; else fprintf(stderr, ", "); + if (afirst) afirst = false; else fprintf(stderr, ", "); fprintf(stderr, "empty"); } if (MAY_BE_PACKED(info)) { - if (afirst) afirst = 0; else fprintf(stderr, ", "); + if (afirst) afirst = false; else fprintf(stderr, ", "); fprintf(stderr, "packed"); } if (MAY_BE_HASH(info)) { - if (afirst) afirst = 0; else fprintf(stderr, ", "); + if (afirst) afirst = false; else fprintf(stderr, ", "); fprintf(stderr, "hash"); } fprintf(stderr, "] "); @@ -288,71 +288,71 @@ static void zend_dump_type_info(uint32_t info, zend_class_entry *ce, int is_inst if ((info & (MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING)) != 0 && ((info & MAY_BE_ARRAY_KEY_LONG) == 0 || (info & MAY_BE_ARRAY_KEY_STRING) == 0)) { - bool afirst = 1; + bool afirst = true; fprintf(stderr, " ["); if (info & MAY_BE_ARRAY_KEY_LONG) { - if (afirst) afirst = 0; else fprintf(stderr, ", "); + if (afirst) afirst = false; else fprintf(stderr, ", "); fprintf(stderr, "long"); } if (info & MAY_BE_ARRAY_KEY_STRING) { - if (afirst) afirst = 0; else fprintf(stderr, ", "); + if (afirst) afirst = false; else fprintf(stderr, ", "); fprintf(stderr, "string"); } fprintf(stderr, "]"); } if (info & (MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF)) { - bool afirst = 1; + bool afirst = true; fprintf(stderr, " of ["); if ((info & MAY_BE_ARRAY_OF_ANY) == MAY_BE_ARRAY_OF_ANY) { - if (afirst) afirst = 0; else fprintf(stderr, ", "); + if (afirst) afirst = false; else fprintf(stderr, ", "); fprintf(stderr, "any"); } else { if (info & MAY_BE_ARRAY_OF_NULL) { - if (afirst) afirst = 0; else fprintf(stderr, ", "); + if (afirst) afirst = false; else fprintf(stderr, ", "); fprintf(stderr, "null"); } if (info & MAY_BE_ARRAY_OF_FALSE) { - if (afirst) afirst = 0; else fprintf(stderr, ", "); + if (afirst) afirst = false; else fprintf(stderr, ", "); fprintf(stderr, "false"); } if (info & MAY_BE_ARRAY_OF_TRUE) { - if (afirst) afirst = 0; else fprintf(stderr, ", "); + if (afirst) afirst = false; else fprintf(stderr, ", "); fprintf(stderr, "true"); } if (info & MAY_BE_ARRAY_OF_LONG) { - if (afirst) afirst = 0; else fprintf(stderr, ", "); + if (afirst) afirst = false; else fprintf(stderr, ", "); fprintf(stderr, "long"); } if (info & MAY_BE_ARRAY_OF_DOUBLE) { - if (afirst) afirst = 0; else fprintf(stderr, ", "); + if (afirst) afirst = false; else fprintf(stderr, ", "); fprintf(stderr, "double"); } if (info & MAY_BE_ARRAY_OF_STRING) { - if (afirst) afirst = 0; else fprintf(stderr, ", "); + if (afirst) afirst = false; else fprintf(stderr, ", "); fprintf(stderr, "string"); } if (info & MAY_BE_ARRAY_OF_ARRAY) { - if (afirst) afirst = 0; else fprintf(stderr, ", "); + if (afirst) afirst = false; else fprintf(stderr, ", "); fprintf(stderr, "array"); } if (info & MAY_BE_ARRAY_OF_OBJECT) { - if (afirst) afirst = 0; else fprintf(stderr, ", "); + if (afirst) afirst = false; else fprintf(stderr, ", "); fprintf(stderr, "object"); } if (info & MAY_BE_ARRAY_OF_RESOURCE) { - if (afirst) afirst = 0; else fprintf(stderr, ", "); + if (afirst) afirst = false; else fprintf(stderr, ", "); fprintf(stderr, "resource"); } } if (info & MAY_BE_ARRAY_OF_REF) { - if (afirst) afirst = 0; else fprintf(stderr, ", "); + if (afirst) afirst = false; else fprintf(stderr, ", "); fprintf(stderr, "ref"); } fprintf(stderr, "]"); } } if (info & MAY_BE_OBJECT) { - if (first) first = 0; else fprintf(stderr, ", "); + if (first) first = false; else fprintf(stderr, ", "); fprintf(stderr, "object"); if (ce) { if (is_instanceof) { @@ -363,7 +363,7 @@ static void zend_dump_type_info(uint32_t info, zend_class_entry *ce, int is_inst } } if (info & MAY_BE_RESOURCE) { - if (first) first = 0; else fprintf(stderr, ", "); + if (first) first = false; else fprintf(stderr, ", "); fprintf(stderr, "resource"); } } @@ -1056,7 +1056,7 @@ ZEND_API void zend_dump_op_array(const zend_op_array *op_array, uint32_t dump_fl } if (op_array->last_live_range && (dump_flags & ZEND_DUMP_LIVE_RANGES)) { fprintf(stderr, "LIVE RANGES:\n"); - for (int i = 0; i < op_array->last_live_range; i++) { + for (uint32_t i = 0; i < op_array->last_live_range; i++) { fprintf(stderr, " %u: %04u - %04u ", EX_VAR_TO_NUM(op_array->live_range[i].var & ~ZEND_LIVE_MASK), @@ -1083,7 +1083,7 @@ ZEND_API void zend_dump_op_array(const zend_op_array *op_array, uint32_t dump_fl } if (op_array->last_try_catch) { fprintf(stderr, "EXCEPTION TABLE:\n"); - for (int i = 0; i < op_array->last_try_catch; i++) { + for (uint32_t i = 0; i < op_array->last_try_catch; i++) { fprintf(stderr, " BB%u", cfg->map[op_array->try_catch_array[i].try_op]); if (op_array->try_catch_array[i].catch_op) { @@ -1116,7 +1116,7 @@ ZEND_API void zend_dump_op_array(const zend_op_array *op_array, uint32_t dump_fl } if (op_array->last_live_range && (dump_flags & ZEND_DUMP_LIVE_RANGES)) { fprintf(stderr, "LIVE RANGES:\n"); - for (int i = 0; i < op_array->last_live_range; i++) { + for (uint32_t i = 0; i < op_array->last_live_range; i++) { fprintf(stderr, " %u: %04u - %04u ", EX_VAR_TO_NUM(op_array->live_range[i].var & ~ZEND_LIVE_MASK), @@ -1143,7 +1143,7 @@ ZEND_API void zend_dump_op_array(const zend_op_array *op_array, uint32_t dump_fl } if (op_array->last_try_catch) { fprintf(stderr, "EXCEPTION TABLE:\n"); - for (int i = 0; i < op_array->last_try_catch; i++) { + for (uint32_t i = 0; i < op_array->last_try_catch; i++) { fprintf(stderr, " %04u", op_array->try_catch_array[i].try_op); @@ -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"); @@ -1216,14 +1216,14 @@ void zend_dump_ssa_variables(const zend_op_array *op_array, const zend_ssa *ssa, static void zend_dump_var_set(const zend_op_array *op_array, const char *name, zend_bitset set) { - bool first = 1; + bool first = true; uint32_t i; fprintf(stderr, " ; %s = {", name); for (i = 0; i < op_array->last_var + op_array->T; i++) { if (zend_bitset_in(set, i)) { if (first) { - first = 0; + first = false; } else { fprintf(stderr, ", "); } diff --git a/Zend/Optimizer/zend_func_info.c b/Zend/Optimizer/zend_func_info.c index 121d2d2cfe570..f3b0d663dd6df 100644 --- a/Zend/Optimizer/zend_func_info.c +++ b/Zend/Optimizer/zend_func_info.c @@ -57,7 +57,7 @@ static uint32_t zend_range_info(const zend_call_info *call_info, const zend_ssa && (call_info->num_args == 2 || call_info->num_args == 3) && ssa && !(ssa->cfg.flags & ZEND_SSA_TSSA)) { - zend_op_array *op_array = call_info->caller_op_array; + const zend_op_array *op_array = call_info->caller_op_array; uint32_t t1 = _ssa_op1_info(op_array, ssa, call_info->arg_info[0].opline, ssa->ops ? &ssa->ops[call_info->arg_info[0].opline - op_array->opcodes] : NULL); uint32_t t2 = _ssa_op1_info(op_array, ssa, call_info->arg_info[1].opline, @@ -116,7 +116,7 @@ uint32_t zend_get_internal_func_info( return 0; } - func_info_t *info = Z_PTR_P(zv); + const func_info_t *info = Z_PTR_P(zv); if (info->info_func) { return call_info ? info->info_func(call_info, ssa) : 0; } else { @@ -136,7 +136,7 @@ ZEND_API uint32_t zend_get_func_info( uint32_t ret = 0; const zend_function *callee_func = call_info->callee_func; *ce = NULL; - *ce_is_instanceof = 0; + *ce_is_instanceof = false; if (callee_func->type == ZEND_INTERNAL_FUNCTION) { uint32_t internal_ret = zend_get_internal_func_info(callee_func, call_info, ssa); @@ -178,7 +178,7 @@ ZEND_API uint32_t zend_get_func_info( } else { if (!call_info->is_prototype) { // FIXME: the order of functions matters!!! - zend_func_info *info = ZEND_FUNC_INFO((zend_op_array*)callee_func); + const zend_func_info *info = ZEND_FUNC_INFO((zend_op_array*)callee_func); if (info) { ret = info->return_info.type; *ce = info->return_info.ce; @@ -198,13 +198,13 @@ ZEND_API uint32_t zend_get_func_info( return ret; } -static void zend_func_info_add(const func_info_t *func_infos, size_t n) +static void zend_func_info_add(const func_info_t *new_func_infos, size_t n) { for (size_t i = 0; i < n; i++) { - zend_string *key = zend_string_init_interned(func_infos[i].name, func_infos[i].name_len, 1); + zend_string *key = zend_string_init_interned(new_func_infos[i].name, new_func_infos[i].name_len, 1); - if (zend_hash_add_ptr(&func_info, key, (void**)&func_infos[i]) == NULL) { - fprintf(stderr, "ERROR: Duplicate function info for \"%s\"\n", func_infos[i].name); + if (zend_hash_add_ptr(&func_info, key, (void**)&new_func_infos[i]) == NULL) { + fprintf(stderr, "ERROR: Duplicate function info for \"%s\"\n", new_func_infos[i].name); } zend_string_release_ex(key, 1); diff --git a/Zend/Optimizer/zend_func_info.h b/Zend/Optimizer/zend_func_info.h index b53683bdf5e70..db00d843ee10e 100644 --- a/Zend/Optimizer/zend_func_info.h +++ b/Zend/Optimizer/zend_func_info.h @@ -39,7 +39,7 @@ #define ZEND_FUNC_JIT_ON_PROF_REQUEST (1<<14) /* used by JIT */ #define ZEND_FUNC_JIT_ON_HOT_COUNTERS (1<<15) /* used by JIT */ #define ZEND_FUNC_JIT_ON_HOT_TRACE (1<<16) /* used by JIT */ - +#define ZEND_FUNC_JITED (1<<17) /* used by JIT */ typedef struct _zend_func_info zend_func_info; typedef struct _zend_call_info zend_call_info; diff --git a/Zend/Optimizer/zend_func_infos.h b/Zend/Optimizer/zend_func_infos.h index 5313a85d7a6c0..b7b118c710c53 100644 --- a/Zend/Optimizer/zend_func_infos.h +++ b/Zend/Optimizer/zend_func_infos.h @@ -510,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 f146a741439d5..54670c804d006 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -266,7 +266,7 @@ typedef struct _zend_scc_iterator { }; } zend_scc_iterator; -static int zend_scc_next(const zend_op_array *op_array, zend_ssa *ssa, int var, zend_scc_iterator *iterator) /* {{{ */ +static int zend_scc_next(const zend_op_array *op_array, const zend_ssa *ssa, int var, zend_scc_iterator *iterator) /* {{{ */ { zend_ssa_phi *phi; int use, var2; @@ -487,14 +487,14 @@ ZEND_API void zend_ssa_find_sccs(const zend_op_array *op_array, zend_ssa *ssa) / #endif -ZEND_API void zend_ssa_find_false_dependencies(const zend_op_array *op_array, zend_ssa *ssa) /* {{{ */ +ZEND_API void zend_ssa_find_false_dependencies(const zend_op_array *op_array, const zend_ssa *ssa) /* {{{ */ { zend_ssa_var *ssa_vars = ssa->vars; - zend_ssa_op *ssa_ops = ssa->ops; + const zend_ssa_op *ssa_ops = ssa->ops; int ssa_vars_count = ssa->vars_count; zend_bitset worklist; int i, j, use; - zend_ssa_phi *p; + const zend_ssa_phi *p; ALLOCA_FLAG(use_heap); if (!op_array->function_name || !ssa->vars || !ssa->ops) { @@ -1068,7 +1068,7 @@ static bool zend_inference_calc_binary_op_range( return 0; } -static bool zend_inference_calc_range(const zend_op_array *op_array, const zend_ssa *ssa, int var, int widening, int narrowing, zend_ssa_range *tmp) +static bool zend_inference_calc_range(const zend_op_array *op_array, const zend_ssa *ssa, int var, int widening, bool narrowing, zend_ssa_range *tmp) { uint32_t line; const zend_op *opline; @@ -1597,7 +1597,7 @@ ZEND_API bool zend_inference_propagate_range(const zend_op_array *op_array, cons return 0; } -static void zend_inference_init_range(const zend_op_array *op_array, zend_ssa *ssa, int var, bool underflow, zend_long min, zend_long max, bool overflow) +static void zend_inference_init_range(const zend_op_array *op_array, const zend_ssa *ssa, int var, bool underflow, zend_long min, zend_long max, bool overflow) { if (underflow) { min = ZEND_LONG_MIN; @@ -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 && @@ -1641,7 +1645,7 @@ static bool zend_inference_widening_meet(zend_ssa_var_info *var_info, zend_ssa_r return 1; } -static bool zend_ssa_range_widening(const zend_op_array *op_array, zend_ssa *ssa, int var, int scc) +static bool zend_ssa_range_widening(const zend_op_array *op_array, const zend_ssa *ssa, int var, int scc) { zend_ssa_range tmp; @@ -1686,7 +1690,7 @@ static bool zend_inference_narrowing_meet(zend_ssa_var_info *var_info, zend_ssa_ return 1; } -static bool zend_ssa_range_narrowing(const zend_op_array *op_array, zend_ssa *ssa, int var, int scc) +static bool zend_ssa_range_narrowing(const zend_op_array *op_array, const zend_ssa *ssa, int var, int scc) { zend_ssa_range tmp; @@ -1731,7 +1735,7 @@ static void zend_infer_ranges_warmup(const zend_op_array *op_array, zend_ssa *ss zend_bitset worklist = do_alloca(sizeof(zend_ulong) * worklist_len * 2, use_heap); zend_bitset visited = worklist + worklist_len; #ifdef NEG_RANGE - int has_inner_cycles = 0; + bool has_inner_cycles = false; memset(worklist, 0, sizeof(zend_ulong) * worklist_len); memset(visited, 0, sizeof(zend_ulong) * worklist_len); @@ -1739,7 +1743,7 @@ static void zend_infer_ranges_warmup(const zend_op_array *op_array, zend_ssa *ss while (j >= 0) { if (!zend_bitset_in(visited, j) && zend_check_inner_cycles(op_array, ssa, worklist, visited, j)) { - has_inner_cycles = 1; + has_inner_cycles = true; break; } j = next_scc_var[j]; @@ -1858,7 +1862,7 @@ static void zend_infer_ranges(const zend_op_array *op_array, zend_ssa *ssa) /* { } else if (zend_inference_calc_range(op_array, ssa, j, 0, 1, &tmp)) { zend_inference_init_range(op_array, ssa, j, tmp.underflow, tmp.min, tmp.max, tmp.overflow); } else { - zend_inference_init_range(op_array, ssa, j, 1, ZEND_LONG_MIN, ZEND_LONG_MAX, 1); + zend_inference_init_range(op_array, ssa, j, true, ZEND_LONG_MIN, ZEND_LONG_MAX, true); } } else { /* Find SCC entry points */ @@ -1893,7 +1897,8 @@ static void zend_infer_ranges(const zend_op_array *op_array, zend_ssa *ssa) /* { for (j = scc_var[scc]; j >= 0; j = next_scc_var[j]) { if (!ssa->var_info[j].has_range && !(ssa->var_info[j].type & MAY_BE_REF)) { - zend_inference_init_range(op_array, ssa, j, 1, ZEND_LONG_MIN, ZEND_LONG_MAX, 1); + zend_inference_init_range(op_array, ssa, j, true, ZEND_LONG_MIN, ZEND_LONG_MAX, + true); FOR_EACH_VAR_USAGE(j, ADD_SCC_VAR); } } @@ -2024,10 +2029,10 @@ static uint32_t get_ssa_alias_types(zend_ssa_alias_kind alias) { } \ } while (0) -static void add_usages(const zend_op_array *op_array, zend_ssa *ssa, zend_bitset worklist, int var) +static void add_usages(const zend_op_array *op_array, const zend_ssa *ssa, zend_bitset worklist, int var) { if (ssa->vars[var].phi_use_chain) { - zend_ssa_phi *p = ssa->vars[var].phi_use_chain; + const zend_ssa_phi *p = ssa->vars[var].phi_use_chain; do { zend_bitset_incl(worklist, p->ssa_var); p = zend_ssa_next_use_phi(ssa, var, p); @@ -2035,7 +2040,7 @@ static void add_usages(const zend_op_array *op_array, zend_ssa *ssa, zend_bitset } if (ssa->vars[var].use_chain >= 0) { int use = ssa->vars[var].use_chain; - zend_ssa_op *op; + const zend_ssa_op *op; do { op = ssa->ops + use; @@ -2077,7 +2082,7 @@ static void add_usages(const zend_op_array *op_array, zend_ssa *ssa, zend_bitset } } -static void emit_type_narrowing_warning(const zend_op_array *op_array, zend_ssa *ssa, int var) +static void emit_type_narrowing_warning(const zend_op_array *op_array, const zend_ssa *ssa, int var) { int def_op_num = ssa->vars[var].definition; const zend_op *def_opline = def_op_num >= 0 ? &op_array->opcodes[def_op_num] : NULL; @@ -2125,7 +2130,7 @@ ZEND_API uint32_t ZEND_FASTCALL zend_array_type_info(const zval *zv) } -ZEND_API uint32_t zend_array_element_type(uint32_t t1, uint8_t op_type, int write, int insert) +ZEND_API uint32_t zend_array_element_type(uint32_t t1, uint8_t op_type, bool write, bool insert) { uint32_t tmp = 0; @@ -2253,7 +2258,7 @@ static uint32_t assign_dim_result_type( /* For binary ops that have compound assignment operators */ static uint32_t binary_op_result_type( - zend_ssa *ssa, uint8_t opcode, uint32_t t1, uint32_t t2, int result_var, + const zend_ssa *ssa, uint8_t opcode, uint32_t t1, uint32_t t2, int result_var, zend_long optimization_level) { uint32_t tmp = 0; uint32_t t1_type = (t1 & MAY_BE_ANY) | (t1 & MAY_BE_UNDEF ? MAY_BE_NULL : 0); @@ -2430,7 +2435,7 @@ static const zend_property_info *lookup_prop_info(const zend_class_entry *ce, ze return NULL; } -static const zend_property_info *zend_fetch_prop_info(const zend_op_array *op_array, zend_ssa *ssa, const zend_op *opline, const zend_ssa_op *ssa_op) +static const zend_property_info *zend_fetch_prop_info(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op *opline, const zend_ssa_op *ssa_op) { const zend_property_info *prop_info = NULL; if (opline->op2_type == IS_CONST) { @@ -2457,9 +2462,9 @@ static const zend_property_info *zend_fetch_static_prop_info(const zend_script * { const zend_property_info *prop_info = NULL; if (opline->op1_type == IS_CONST) { - zend_class_entry *ce = NULL; + const zend_class_entry *ce = NULL; if (opline->op2_type == IS_UNUSED) { - int fetch_type = opline->op2.num & ZEND_FETCH_CLASS_MASK; + uint32_t fetch_type = opline->op2.num & ZEND_FETCH_CLASS_MASK; switch (fetch_type) { case ZEND_FETCH_CLASS_SELF: case ZEND_FETCH_CLASS_STATIC: @@ -2474,12 +2479,12 @@ static const zend_property_info *zend_fetch_static_prop_info(const zend_script * break; } } else if (opline->op2_type == IS_CONST) { - zval *zv = CRT_CONSTANT(opline->op2); + const zval *zv = CRT_CONSTANT(opline->op2); ce = zend_optimizer_get_class_entry(script, op_array, Z_STR_P(zv + 1)); } if (ce) { - zval *zv = CRT_CONSTANT(opline->op1); + const zval *zv = CRT_CONSTANT(opline->op1); prop_info = lookup_prop_info(ce, Z_STR_P(zv), op_array->scope); if (prop_info && !(prop_info->flags & ZEND_ACC_STATIC)) { prop_info = NULL; @@ -2501,13 +2506,13 @@ static uint32_t zend_fetch_prop_type(const zend_script *script, const zend_prope return zend_convert_type(script, prop_info->type, pce); } -static bool result_may_be_separated(zend_ssa *ssa, zend_ssa_op *ssa_op) +static bool result_may_be_separated(const zend_ssa *ssa, const zend_ssa_op *ssa_op) { int tmp_var = ssa_op->result_def; if (ssa->vars[tmp_var].use_chain >= 0 && !ssa->vars[tmp_var].phi_use_chain) { - zend_ssa_op *use_op = &ssa->ops[ssa->vars[tmp_var].use_chain]; + const zend_ssa_op *use_op = &ssa->ops[ssa->vars[tmp_var].use_chain]; /* TODO: analyze instructions between ssa_op and use_op */ if (use_op == ssa_op + 1) { @@ -3023,7 +3028,7 @@ static zend_always_inline zend_result _zend_update_type_info( break; case ZEND_ASSIGN_OBJ: if (opline->op1_type == IS_CV) { - zend_class_entry *ce = ssa_var_info[ssa_op->op1_use].ce; + const zend_class_entry *ce = ssa_var_info[ssa_op->op1_use].ce; bool add_rc = (t1 & (MAY_BE_OBJECT|MAY_BE_REF)) && (!ce || ce->__set /* Non-default write_property may be set within create_object. */ @@ -4115,15 +4120,16 @@ ZEND_API zend_result zend_update_type_info( const zend_op_array *op_array, zend_ssa *ssa, const zend_script *script, - zend_op *opline, + const zend_op *opline, zend_ssa_op *ssa_op, const zend_op **ssa_opcodes, zend_long optimization_level) { - return _zend_update_type_info(op_array, ssa, script, NULL, opline, ssa_op, ssa_opcodes, optimization_level, 0); + return _zend_update_type_info(op_array, ssa, script, NULL, opline, ssa_op, ssa_opcodes, optimization_level, + false); } -static uint32_t get_class_entry_rank(zend_class_entry *ce) { +static uint32_t get_class_entry_rank(const zend_class_entry *ce) { uint32_t rank = 0; if (ce->ce_flags & ZEND_ACC_LINKED) { while (ce->parent) { @@ -4136,7 +4142,7 @@ static uint32_t get_class_entry_rank(zend_class_entry *ce) { /* Compute least common ancestor on class inheritance tree only */ static zend_class_entry *join_class_entries( - zend_class_entry *ce1, zend_class_entry *ce2, int *is_instanceof) { + zend_class_entry *ce1, zend_class_entry *ce2, bool *is_instanceof) { uint32_t rank1, rank2; if (ce1 == ce2) { return ce1; @@ -4164,12 +4170,12 @@ static zend_class_entry *join_class_entries( } if (ce1) { - *is_instanceof = 1; + *is_instanceof = true; } return ce1; } -static bool safe_instanceof(zend_class_entry *ce1, zend_class_entry *ce2) { +static bool safe_instanceof(const zend_class_entry *ce1, const zend_class_entry *ce2) { if (ce1 == ce2) { return 1; } @@ -4182,7 +4188,7 @@ static bool safe_instanceof(zend_class_entry *ce1, zend_class_entry *ce2) { static zend_result zend_infer_types_ex(const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_bitset worklist, zend_long optimization_level) { - zend_basic_block *blocks = ssa->cfg.blocks; + const zend_basic_block *blocks = ssa->cfg.blocks; zend_ssa_var *ssa_vars = ssa->vars; zend_ssa_var_info *ssa_var_info = ssa->var_info; int ssa_vars_count = ssa->vars_count; @@ -4198,11 +4204,11 @@ static zend_result zend_infer_types_ex(const zend_op_array *op_array, const zend zend_ssa_phi *p = ssa_vars[j].definition_phi; if (p->pi >= 0) { zend_class_entry *ce = ssa_var_info[p->sources[0]].ce; - int is_instanceof = ssa_var_info[p->sources[0]].is_instanceof; + bool is_instanceof = ssa_var_info[p->sources[0]].is_instanceof; tmp = get_ssa_var_info(ssa, p->sources[0]); if (!p->has_range_constraint) { - zend_ssa_type_constraint *constraint = &p->constraint.type; + const zend_ssa_type_constraint *constraint = &p->constraint.type; tmp &= constraint->type_mask; if (!(tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) { tmp &= ~(MAY_BE_RC1|MAY_BE_RCN); @@ -4210,7 +4216,7 @@ static zend_result zend_infer_types_ex(const zend_op_array *op_array, const zend if ((tmp & MAY_BE_OBJECT) && constraint->ce && ce != constraint->ce) { if (!ce) { ce = constraint->ce; - is_instanceof = 1; + is_instanceof = true; } else if (is_instanceof && safe_instanceof(constraint->ce, ce)) { ce = constraint->ce; } else { @@ -4227,8 +4233,8 @@ static zend_result zend_infer_types_ex(const zend_op_array *op_array, const zend UPDATE_SSA_OBJ_TYPE(ce, is_instanceof, j); } } else { - int first = 1; - int is_instanceof = 0; + bool first = true; + bool is_instanceof = false; zend_class_entry *ce = NULL; tmp = 0; @@ -4245,7 +4251,7 @@ static zend_result zend_infer_types_ex(const zend_op_array *op_array, const zend if (first) { ce = info->ce; is_instanceof = info->is_instanceof; - first = 0; + first = false; } else { is_instanceof |= info->is_instanceof; ce = join_class_entries(ce, info->ce, &is_instanceof); @@ -4256,7 +4262,7 @@ static zend_result zend_infer_types_ex(const zend_op_array *op_array, const zend } } else if (ssa_vars[j].definition >= 0) { i = ssa_vars[j].definition; - if (_zend_update_type_info(op_array, ssa, script, worklist, op_array->opcodes + i, ssa->ops + i, NULL, optimization_level, 1) == FAILURE) { + if (_zend_update_type_info(op_array, ssa, script, worklist, op_array->opcodes + i, ssa->ops + i, NULL, optimization_level, true) == FAILURE) { return FAILURE; } } @@ -4264,18 +4270,18 @@ static zend_result zend_infer_types_ex(const zend_op_array *op_array, const zend return SUCCESS; } -static bool is_narrowable_instr(zend_op *opline) { +static bool is_narrowable_instr(const zend_op *opline) { return opline->opcode == ZEND_ADD || opline->opcode == ZEND_SUB || opline->opcode == ZEND_MUL || opline->opcode == ZEND_DIV; } -static bool is_effective_op1_double_cast(zend_op *opline, zval *op2) { +static bool is_effective_op1_double_cast(const zend_op *opline, const zval *op2) { return (opline->opcode == ZEND_ADD && Z_LVAL_P(op2) == 0) || (opline->opcode == ZEND_SUB && Z_LVAL_P(op2) == 0) || (opline->opcode == ZEND_MUL && Z_LVAL_P(op2) == 1) || (opline->opcode == ZEND_DIV && Z_LVAL_P(op2) == 1); } -static bool is_effective_op2_double_cast(zend_op *opline, zval *op1) { +static bool is_effective_op2_double_cast(const zend_op *opline, const zval *op1) { /* In PHP it holds that (double)(0-$int) is bitwise identical to 0.0-(double)$int, * so allowing SUB here is fine. */ return (opline->opcode == ZEND_ADD && Z_LVAL_P(op1) == 0) @@ -4487,19 +4493,18 @@ static zend_result zend_type_narrowing(const zend_op_array *op_array, const zend return SUCCESS; } -static bool is_recursive_tail_call(const zend_op_array *op_array, - zend_op *opline) +static bool is_recursive_tail_call(const zend_op_array *op_array, const zend_op *opline) { - zend_func_info *info = ZEND_FUNC_INFO(op_array); + const zend_func_info *info = ZEND_FUNC_INFO(op_array); if (info->ssa.ops && info->ssa.vars && info->call_map && info->ssa.ops[opline - op_array->opcodes].op1_use >= 0 && info->ssa.vars[info->ssa.ops[opline - op_array->opcodes].op1_use].definition >= 0) { - zend_op *op = op_array->opcodes + info->ssa.vars[info->ssa.ops[opline - op_array->opcodes].op1_use].definition; + const zend_op *op = op_array->opcodes + info->ssa.vars[info->ssa.ops[opline - op_array->opcodes].op1_use].definition; if (op->opcode == ZEND_DO_UCALL) { - zend_call_info *call_info = info->call_map[op - op_array->opcodes]; + const zend_call_info *call_info = info->call_map[op - op_array->opcodes]; if (call_info && op_array == &call_info->callee_func->op_array) { return 1; } @@ -4515,7 +4520,7 @@ uint32_t zend_get_return_info_from_signature_only( if (func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE && (use_tentative_return_info || !ZEND_ARG_TYPE_IS_TENTATIVE(func->common.arg_info - 1)) ) { - zend_arg_info *ret_info = func->common.arg_info - 1; + const zend_arg_info *ret_info = func->common.arg_info - 1; type = zend_fetch_arg_info_type(script, ret_info, ce); *ce_is_instanceof = ce != NULL; } else { @@ -4530,7 +4535,7 @@ uint32_t zend_get_return_info_from_signature_only( && !(func->common.fn_flags & ZEND_ACC_GENERATOR)) { type |= MAY_BE_REF; *ce = NULL; - *ce_is_instanceof = 0; + *ce_is_instanceof = false; } return type; } @@ -4543,7 +4548,7 @@ ZEND_API void zend_init_func_return_info( zend_ssa_range tmp_range = {0, 0, 0, 0}; bool is_instanceof = false; ret->type = zend_get_return_info_from_signature_only( - (zend_function *) op_array, script, &ret->ce, &is_instanceof, /* use_tentative_return_info */ 1); + (zend_function *) op_array, script, &ret->ce, &is_instanceof, /* use_tentative_return_info */ true); ret->is_instanceof = is_instanceof; ret->range = tmp_range; ret->has_range = 0; @@ -4551,21 +4556,21 @@ ZEND_API void zend_init_func_return_info( static void zend_func_return_info(const zend_op_array *op_array, const zend_script *script, - int recursive, - int widening, + bool recursive, + bool widening, zend_ssa_var_info *ret) { - zend_func_info *info = ZEND_FUNC_INFO(op_array); - zend_ssa *ssa = &info->ssa; + const zend_func_info *info = ZEND_FUNC_INFO(op_array); + const zend_ssa *ssa = &info->ssa; int blocks_count = info->ssa.cfg.blocks_count; - zend_basic_block *blocks = info->ssa.cfg.blocks; + const zend_basic_block *blocks = info->ssa.cfg.blocks; int j; uint32_t t1; uint32_t tmp = 0; zend_class_entry *tmp_ce = NULL; int tmp_is_instanceof = -1; zend_class_entry *arg_ce; - int arg_is_instanceof; + bool arg_is_instanceof; zend_ssa_range tmp_range = {0, 0, 0, 0}; int tmp_has_range = -1; @@ -4589,7 +4594,7 @@ static void zend_func_return_info(const zend_op_array *op_array, zend_op *opline = op_array->opcodes + blocks[j].start + blocks[j].len - 1; if (opline->opcode == ZEND_RETURN || opline->opcode == ZEND_RETURN_BY_REF) { - zend_ssa_op *ssa_op = ssa->ops ? &ssa->ops[opline - op_array->opcodes] : NULL; + const zend_ssa_op *ssa_op = ssa->ops ? &ssa->ops[opline - op_array->opcodes] : NULL; if (!recursive && ssa_op && info->ssa.var_info && ssa_op->op1_use >= 0 && info->ssa.var_info[ssa_op->op1_use].recursive) { @@ -4620,7 +4625,7 @@ static void zend_func_return_info(const zend_op_array *op_array, arg_is_instanceof = info->ssa.var_info[ssa_op->op1_use].is_instanceof; } else { arg_ce = NULL; - arg_is_instanceof = 0; + arg_is_instanceof = false; } if (tmp_is_instanceof < 0) { @@ -4636,7 +4641,7 @@ static void zend_func_return_info(const zend_op_array *op_array, } if (opline->op1_type == IS_CONST) { - zval *zv = CRT_CONSTANT(opline->op1); + const zval *zv = CRT_CONSTANT(opline->op1); if (Z_TYPE_P(zv) == IS_LONG) { if (tmp_has_range < 0) { @@ -4739,7 +4744,7 @@ static zend_result zend_infer_types(const zend_op_array *op_array, const zend_sc return SUCCESS; } -static void zend_mark_cv_references(const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa) +static void zend_mark_cv_references(const zend_op_array *op_array, const zend_script *script, const zend_ssa *ssa) { int var, def; const zend_op *opline; @@ -5105,14 +5110,16 @@ ZEND_API bool zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op case ZEND_PRE_DEC: case ZEND_POST_DEC: return (t1 & (MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)); - case ZEND_BOOL_NOT: case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: - case ZEND_BOOL: case ZEND_JMP_SET: return (t1 & MAY_BE_OBJECT); + case ZEND_BOOL: + case ZEND_BOOL_NOT: + /* NAN Cast to bool will warn, but if we have a range it is fine */ + return (t1 & MAY_BE_OBJECT) || ((t1 & MAY_BE_DOUBLE) && !OP1_HAS_RANGE()); case ZEND_BOOL_XOR: return (t1 & MAY_BE_OBJECT) || (t2 & MAY_BE_OBJECT); case ZEND_IS_EQUAL: @@ -5246,7 +5253,7 @@ ZEND_API bool zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op case ZEND_INIT_ARRAY: return (opline->op2_type != IS_UNUSED) && (t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)); case ZEND_ADD_ARRAY_ELEMENT: - return (opline->op2_type == IS_UNUSED) || (t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)); + return (opline->op2_type == IS_UNUSED) || (t2 & (MAY_BE_NULL|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)); case ZEND_STRLEN: return (t1 & MAY_BE_ANY) != MAY_BE_STRING; case ZEND_COUNT: @@ -5279,6 +5286,7 @@ ZEND_API bool zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op case ZEND_CAST: switch (opline->extended_value) { case IS_LONG: + return (t1 & (MAY_BE_DOUBLE|MAY_BE_STRING|MAY_BE_OBJECT)); case IS_DOUBLE: return (t1 & MAY_BE_OBJECT); case IS_STRING: diff --git a/Zend/Optimizer/zend_inference.h b/Zend/Optimizer/zend_inference.h index 666abc586592e..1b626fa2ee227 100644 --- a/Zend/Optimizer/zend_inference.h +++ b/Zend/Optimizer/zend_inference.h @@ -217,11 +217,11 @@ static zend_always_inline bool zend_sub_will_overflow(zend_long a, zend_long b) BEGIN_EXTERN_C() -ZEND_API void zend_ssa_find_false_dependencies(const zend_op_array *op_array, zend_ssa *ssa); +ZEND_API void zend_ssa_find_false_dependencies(const zend_op_array *op_array, const zend_ssa *ssa); ZEND_API void zend_ssa_find_sccs(const zend_op_array *op_array, zend_ssa *ssa); ZEND_API zend_result zend_ssa_inference(zend_arena **raena, const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_long optimization_level); -ZEND_API uint32_t zend_array_element_type(uint32_t t1, uint8_t op_type, int write, int insert); +ZEND_API uint32_t zend_array_element_type(uint32_t t1, uint8_t op_type, bool write, bool insert); ZEND_API bool zend_inference_propagate_range(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op *opline, const zend_ssa_op* ssa_op, int var, zend_ssa_range *tmp); @@ -238,7 +238,7 @@ ZEND_API bool zend_may_throw(const zend_op *opline, const zend_ssa_op *ssa_op, c ZEND_API zend_result zend_update_type_info( const zend_op_array *op_array, zend_ssa *ssa, const zend_script *script, - zend_op *opline, zend_ssa_op *ssa_op, const zend_op **ssa_opcodes, + const zend_op *opline, zend_ssa_op *ssa_op, const zend_op **ssa_opcodes, zend_long optimization_level); END_EXTERN_C() diff --git a/Zend/Optimizer/zend_optimizer.c b/Zend/Optimizer/zend_optimizer.c index 1c58d6b7372fb..b57ad3ad4268e 100644 --- a/Zend/Optimizer/zend_optimizer.c +++ b/Zend/Optimizer/zend_optimizer.c @@ -41,7 +41,7 @@ struct { int last; } zend_optimizer_registered_passes = {{NULL}, 0}; -void zend_optimizer_collect_constant(zend_optimizer_ctx *ctx, zval *name, zval* value) +void zend_optimizer_collect_constant(zend_optimizer_ctx *ctx, const zval *name, zval* value) { if (!ctx->constants) { ctx->constants = zend_arena_alloc(&ctx->arena, sizeof(HashTable)); @@ -74,6 +74,9 @@ zend_result zend_optimizer_eval_unary_op(zval *result, uint8_t opcode, zval *op1 } return unary_op(result, op1); } else { /* ZEND_BOOL */ + if (Z_TYPE_P(op1) == IS_DOUBLE && zend_isnan(Z_DVAL_P(op1))) { + return FAILURE; + } ZVAL_BOOL(result, zend_is_true(op1)); return SUCCESS; } @@ -100,11 +103,11 @@ zend_result zend_optimizer_eval_strlen(zval *result, const zval *op1) /* {{{ */ /* }}} */ zend_result zend_optimizer_eval_special_func_call( - zval *result, zend_string *name, zend_string *arg) { + zval *result, const zend_string *name, zend_string *arg) { if (zend_string_equals_literal(name, "function_exists") || zend_string_equals_literal(name, "is_callable")) { zend_string *lc_name = zend_string_tolower(arg); - zend_internal_function *func = zend_hash_find_ptr(EG(function_table), lc_name); + const zend_internal_function *func = zend_hash_find_ptr(EG(function_table), lc_name); zend_string_release_ex(lc_name, 0); if (func && func->type == ZEND_INTERNAL_FUNCTION @@ -142,7 +145,7 @@ zend_result zend_optimizer_eval_special_func_call( return FAILURE; } if (zend_string_equals_literal(name, "constant")) { - return zend_optimizer_get_persistent_constant(arg, result, 1) ? SUCCESS : FAILURE; + return zend_optimizer_get_persistent_constant(arg, result, true) ? SUCCESS : FAILURE; } if (zend_string_equals_literal(name, "dirname")) { if (!IS_ABSOLUTE_PATH(ZSTR_VAL(arg), ZSTR_LEN(arg))) { @@ -177,18 +180,18 @@ zend_result zend_optimizer_eval_special_func_call( return FAILURE; } -bool zend_optimizer_get_collected_constant(HashTable *constants, zval *name, zval* value) +bool zend_optimizer_get_collected_constant(const HashTable *constants, const zval *name, zval* value) { zval *val; if ((val = zend_hash_find(constants, Z_STR_P(name))) != NULL) { ZVAL_COPY(value, val); - return 1; + return true; } - return 0; + return false; } -void zend_optimizer_convert_to_free_op1(zend_op_array *op_array, zend_op *opline) +void zend_optimizer_convert_to_free_op1(const zend_op_array *op_array, zend_op *opline) { if (opline->op1_type == IS_CV) { opline->opcode = ZEND_CHECK_VAR; @@ -207,9 +210,9 @@ void zend_optimizer_convert_to_free_op1(zend_op_array *op_array, zend_op *opline } } -int zend_optimizer_add_literal(zend_op_array *op_array, const zval *zv) +uint32_t zend_optimizer_add_literal(zend_op_array *op_array, const zval *zv) { - int i = op_array->last_literal; + uint32_t i = op_array->last_literal; op_array->last_literal++; op_array->literals = (zval*)erealloc(op_array->literals, op_array->last_literal * sizeof(zval)); ZVAL_COPY_VALUE(&op_array->literals[i], zv); @@ -217,7 +220,7 @@ int zend_optimizer_add_literal(zend_op_array *op_array, const zval *zv) return i; } -static inline int zend_optimizer_add_literal_string(zend_op_array *op_array, zend_string *str) { +static inline uint32_t zend_optimizer_add_literal_string(zend_op_array *op_array, zend_string *str) { zval zv; ZVAL_STR(&zv, str); zend_string_hash_val(str); @@ -260,7 +263,7 @@ bool zend_optimizer_update_op1_const(zend_op_array *op_array, switch ((opline-1)->opcode) { case ZEND_ASSIGN_OBJ_REF: case ZEND_ASSIGN_STATIC_PROP_REF: - return 0; + return false; } opline->op1.constant = zend_optimizer_add_literal(op_array, val); break; @@ -268,7 +271,7 @@ bool zend_optimizer_update_op1_const(zend_op_array *op_array, case ZEND_CHECK_VAR: MAKE_NOP(opline); zval_ptr_dtor_nogc(val); - return 1; + return true; case ZEND_SEND_VAR_EX: case ZEND_SEND_FUNC_ARG: case ZEND_FETCH_DIM_W: @@ -283,7 +286,7 @@ bool zend_optimizer_update_op1_const(zend_op_array *op_array, case ZEND_SEPARATE: case ZEND_SEND_VAR_NO_REF: case ZEND_SEND_VAR_NO_REF_EX: - return 0; + return false; case ZEND_CATCH: REQUIRES_STRING(val); drop_leading_backslash(val); @@ -365,10 +368,10 @@ bool zend_optimizer_update_op1_const(zend_op_array *op_array, case ZEND_VERIFY_RETURN_TYPE: /* This would require a non-local change. * zend_optimizer_replace_by_const() supports this. */ - return 0; + return false; case ZEND_COPY_TMP: case ZEND_FETCH_CLASS_NAME: - return 0; + return false; case ZEND_ECHO: { zval zv; @@ -379,7 +382,7 @@ bool zend_optimizer_update_op1_const(zend_op_array *op_array, opline->op1.constant = zend_optimizer_add_literal(op_array, val); if (Z_TYPE_P(val) == IS_STRING && Z_STRLEN_P(val) == 0) { MAKE_NOP(opline); - return 1; + return true; } /* TODO: In a subsequent pass, *after* this step and compacting nops, combine consecutive ZEND_ECHOs using the block information from ssa->cfg */ /* (e.g. for ext/opcache/tests/opt/sccp_010.phpt) */ @@ -409,7 +412,7 @@ bool zend_optimizer_update_op1_const(zend_op_array *op_array, if (Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) { zend_string_hash_val(Z_STR(ZEND_OP1_LITERAL(opline))); } - return 1; + return true; } bool zend_optimizer_update_op2_const(zend_op_array *op_array, @@ -421,7 +424,7 @@ bool zend_optimizer_update_op2_const(zend_op_array *op_array, switch (opline->opcode) { case ZEND_ASSIGN_REF: case ZEND_FAST_CALL: - return 0; + return false; case ZEND_FETCH_CLASS: case ZEND_INSTANCEOF: REQUIRES_STRING(val); @@ -475,13 +478,13 @@ bool zend_optimizer_update_op2_const(zend_op_array *op_array, case ZEND_INIT_DYNAMIC_CALL: if (Z_TYPE_P(val) == IS_STRING) { if (zend_memrchr(Z_STRVAL_P(val), ':', Z_STRLEN_P(val))) { - return 0; + return false; } if (zend_optimizer_classify_function(Z_STR_P(val), opline->extended_value)) { /* Dynamic call to various special functions must stay dynamic, * otherwise would drop a warning */ - return 0; + return false; } opline->opcode = ZEND_INIT_FCALL_BY_NAME; @@ -591,7 +594,7 @@ bool zend_optimizer_update_op2_const(zend_op_array *op_array, if (Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) { zend_string_hash_val(Z_STR(ZEND_OP2_LITERAL(opline))); } - return 1; + return true; } bool zend_optimizer_replace_by_const(zend_op_array *op_array, @@ -600,7 +603,7 @@ bool zend_optimizer_replace_by_const(zend_op_array *op_array, uint32_t var, zval *val) { - zend_op *end = op_array->opcodes + op_array->last; + const zend_op *end = op_array->opcodes + op_array->last; while (opline < end) { if (opline->op1_type == type && @@ -619,7 +622,7 @@ bool zend_optimizer_replace_by_const(zend_op_array *op_array, case ZEND_MATCH: case ZEND_MATCH_ERROR: case ZEND_JMP_NULL: { - zend_op *end = op_array->opcodes + op_array->last; + const zend_op *end = op_array->opcodes + op_array->last; while (opline < end) { if (opline->op1_type == type && opline->op1.var == var) { /* If this opcode doesn't keep the operand alive, we're done. Check @@ -638,7 +641,7 @@ bool zend_optimizer_replace_by_const(zend_op_array *op_array, Z_TRY_ADDREF_P(val); if (!zend_optimizer_update_op1_const(op_array, opline, val)) { zval_ptr_dtor(val); - return 0; + return false; } if (is_last) { break; @@ -647,13 +650,13 @@ bool zend_optimizer_replace_by_const(zend_op_array *op_array, opline++; } zval_ptr_dtor_nogc(val); - return 1; + return true; } case ZEND_VERIFY_RETURN_TYPE: { - zend_arg_info *ret_info = op_array->arg_info - 1; + const zend_arg_info *ret_info = op_array->arg_info - 1; if (!ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(val)) || (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE)) { - return 0; + return false; } MAKE_NOP(opline); @@ -678,11 +681,11 @@ bool zend_optimizer_replace_by_const(zend_op_array *op_array, opline++; } - return 1; + return true; } /* Update jump offsets after a jump was migrated to another opline */ -void zend_optimizer_migrate_jump(zend_op_array *op_array, zend_op *new_opline, zend_op *opline) { +void zend_optimizer_migrate_jump(const zend_op_array *op_array, zend_op *new_opline, zend_op *opline) { switch (new_opline->opcode) { case ZEND_JMP: case ZEND_FAST_CALL: @@ -715,7 +718,7 @@ void zend_optimizer_migrate_jump(zend_op_array *op_array, zend_op *new_opline, z case ZEND_SWITCH_STRING: case ZEND_MATCH: { - HashTable *jumptable = Z_ARRVAL(ZEND_OP2_LITERAL(opline)); + const HashTable *jumptable = Z_ARRVAL(ZEND_OP2_LITERAL(opline)); zval *zv; ZEND_HASH_FOREACH_VAL(jumptable, zv) { Z_LVAL_P(zv) = ZEND_OPLINE_NUM_TO_OFFSET(op_array, new_opline, ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(zv))); @@ -727,7 +730,7 @@ void zend_optimizer_migrate_jump(zend_op_array *op_array, zend_op *new_opline, z } /* Shift jump offsets based on shiftlist */ -void zend_optimizer_shift_jump(zend_op_array *op_array, zend_op *opline, uint32_t *shiftlist) { +void zend_optimizer_shift_jump(const zend_op_array *op_array, zend_op *opline, const uint32_t *shiftlist) { switch (opline->opcode) { case ZEND_JMP: case ZEND_FAST_CALL: @@ -760,7 +763,7 @@ void zend_optimizer_shift_jump(zend_op_array *op_array, zend_op *opline, uint32_ case ZEND_SWITCH_STRING: case ZEND_MATCH: { - HashTable *jumptable = Z_ARRVAL(ZEND_OP2_LITERAL(opline)); + const HashTable *jumptable = Z_ARRVAL(ZEND_OP2_LITERAL(opline)); zval *zv; ZEND_HASH_FOREACH_VAL(jumptable, zv) { Z_LVAL_P(zv) = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(zv)) - shiftlist[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(zv))]); @@ -771,12 +774,12 @@ void zend_optimizer_shift_jump(zend_op_array *op_array, zend_op *opline, uint32_ } } -static bool zend_optimizer_ignore_class(zval *ce_zv, zend_string *filename) +static bool zend_optimizer_ignore_class(zval *ce_zv, const zend_string *filename) { - zend_class_entry *ce = Z_PTR_P(ce_zv); + const zend_class_entry *ce = Z_PTR_P(ce_zv); if (ce->ce_flags & ZEND_ACC_PRELOADED) { - Bucket *ce_bucket = (Bucket*)((uintptr_t)ce_zv - XtOffsetOf(Bucket, val)); + const Bucket *ce_bucket = (const Bucket*)((uintptr_t)ce_zv - XtOffsetOf(Bucket, val)); size_t offset = ce_bucket - EG(class_table)->arData; if (offset < EG(persistent_classes_count)) { return false; @@ -786,15 +789,15 @@ static bool zend_optimizer_ignore_class(zval *ce_zv, zend_string *filename) && (!ce->info.user.filename || ce->info.user.filename != filename); } -static bool zend_optimizer_ignore_function(zval *fbc_zv, zend_string *filename) +static bool zend_optimizer_ignore_function(zval *fbc_zv, const zend_string *filename) { - zend_function *fbc = Z_PTR_P(fbc_zv); + const zend_function *fbc = Z_PTR_P(fbc_zv); if (fbc->type == ZEND_INTERNAL_FUNCTION) { return false; } else if (fbc->type == ZEND_USER_FUNCTION) { if (fbc->op_array.fn_flags & ZEND_ACC_PRELOADED) { - Bucket *fbc_bucket = (Bucket*)((uintptr_t)fbc_zv - XtOffsetOf(Bucket, val)); + const Bucket *fbc_bucket = (const Bucket*)((uintptr_t)fbc_zv - XtOffsetOf(Bucket, val)); size_t offset = fbc_bucket - EG(function_table)->arData; if (offset < EG(persistent_functions_count)) { return false; @@ -829,7 +832,7 @@ zend_class_entry *zend_optimizer_get_class_entry( zend_class_entry *zend_optimizer_get_class_entry_from_op1( const zend_script *script, const zend_op_array *op_array, const zend_op *opline) { if (opline->op1_type == IS_CONST) { - zval *op1 = CRT_CONSTANT(opline->op1); + const zval *op1 = CRT_CONSTANT(opline->op1); if (Z_TYPE_P(op1) == IS_STRING) { return zend_optimizer_get_class_entry(script, op_array, Z_STR_P(op1 + 1)); } @@ -852,7 +855,7 @@ const zend_class_constant *zend_fetch_class_const_info( return NULL; } if (opline->op1_type == IS_CONST) { - zval *op1 = CRT_CONSTANT(opline->op1); + const zval *op1 = CRT_CONSTANT(opline->op1); if (Z_TYPE_P(op1) == IS_STRING) { if (script) { ce = zend_optimizer_get_class_entry(script, op_array, Z_STR_P(op1 + 1)); @@ -866,7 +869,7 @@ const zend_class_constant *zend_fetch_class_const_info( } else if (opline->op1_type == IS_UNUSED && op_array->scope && !(op_array->scope->ce_flags & ZEND_ACC_TRAIT) && !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) { - int fetch_type = opline->op1.num & ZEND_FETCH_CLASS_MASK; + uint32_t fetch_type = opline->op1.num & ZEND_FETCH_CLASS_MASK; if (fetch_type == ZEND_FETCH_CLASS_SELF) { ce = op_array->scope; } else if (fetch_type == ZEND_FETCH_CLASS_STATIC) { @@ -896,9 +899,9 @@ const zend_class_constant *zend_fetch_class_const_info( } zend_function *zend_optimizer_get_called_func( - zend_script *script, zend_op_array *op_array, zend_op *opline, bool *is_prototype) + const zend_script *script, const zend_op_array *op_array, zend_op *opline, bool *is_prototype) { - *is_prototype = 0; + *is_prototype = false; switch (opline->opcode) { case ZEND_INIT_FCALL: { @@ -917,7 +920,7 @@ zend_function *zend_optimizer_get_called_func( case ZEND_INIT_FCALL_BY_NAME: case ZEND_INIT_NS_FCALL_BY_NAME: if (opline->op2_type == IS_CONST && Z_TYPE_P(CRT_CONSTANT(opline->op2)) == IS_STRING) { - zval *function_name = CRT_CONSTANT(opline->op2) + 1; + const zval *function_name = CRT_CONSTANT(opline->op2) + 1; zend_function *func; zval *func_zv; if (script && (func = zend_hash_find_ptr(&script->function_table, Z_STR_P(function_name)))) { @@ -931,7 +934,7 @@ zend_function *zend_optimizer_get_called_func( break; case ZEND_INIT_STATIC_METHOD_CALL: if (opline->op2_type == IS_CONST && Z_TYPE_P(CRT_CONSTANT(opline->op2)) == IS_STRING) { - zend_class_entry *ce = zend_optimizer_get_class_entry_from_op1( + const zend_class_entry *ce = zend_optimizer_get_class_entry_from_op1( script, op_array, opline); if (ce) { zend_string *func_name = Z_STR_P(CRT_CONSTANT(opline->op2) + 1); @@ -975,13 +978,13 @@ zend_function *zend_optimizer_get_called_func( } break; case ZEND_INIT_PARENT_PROPERTY_HOOK_CALL: { - zend_class_entry *scope = op_array->scope; + const zend_class_entry *scope = op_array->scope; ZEND_ASSERT(scope != NULL); if ((scope->ce_flags & ZEND_ACC_LINKED) && scope->parent) { - zend_class_entry *parent_scope = scope->parent; + const zend_class_entry *parent_scope = scope->parent; zend_string *prop_name = Z_STR_P(CRT_CONSTANT(opline->op1)); zend_property_hook_kind hook_kind = opline->op2.num; - zend_property_info *prop_info = zend_get_property_info(parent_scope, prop_name, /* silent */ true); + const zend_property_info *prop_info = zend_get_property_info(parent_scope, prop_name, /* silent */ true); if (prop_info && prop_info != ZEND_WRONG_PROPERTY_INFO @@ -998,7 +1001,7 @@ zend_function *zend_optimizer_get_called_func( } case ZEND_NEW: { - zend_class_entry *ce = zend_optimizer_get_class_entry_from_op1( + const zend_class_entry *ce = zend_optimizer_get_class_entry_from_op1( script, op_array, opline); if (ce && ce->type == ZEND_USER_CLASS) { return ce->constructor; @@ -1009,7 +1012,7 @@ zend_function *zend_optimizer_get_called_func( return NULL; } -uint32_t zend_optimizer_classify_function(zend_string *name, uint32_t num_args) { +uint32_t zend_optimizer_classify_function(const zend_string *name, uint32_t num_args) { if (zend_string_equals_literal(name, "extract")) { return ZEND_FUNC_INDIRECT_VAR_ACCESS; } else if (zend_string_equals_literal(name, "compact")) { @@ -1161,12 +1164,12 @@ static void zend_optimize(zend_op_array *op_array, static void zend_revert_pass_two(zend_op_array *op_array) { - zend_op *opline, *end; + zend_op *opline; ZEND_ASSERT((op_array->fn_flags & ZEND_ACC_DONE_PASS_TWO) != 0); opline = op_array->opcodes; - end = opline + op_array->last; + const zend_op *end = opline + op_array->last; while (opline < end) { if (opline->op1_type == IS_CONST) { ZEND_PASS_TWO_UNDO_CONSTANT(op_array, opline, opline->op1); @@ -1299,7 +1302,7 @@ static void zend_redo_pass_two(zend_op_array *op_array) op_array->fn_flags |= ZEND_ACC_DONE_PASS_TWO; } -static void zend_redo_pass_two_ex(zend_op_array *op_array, zend_ssa *ssa) +static void zend_redo_pass_two_ex(zend_op_array *op_array, const zend_ssa *ssa) { zend_op *opline, *end; #if ZEND_USE_ABS_JMP_ADDR && !ZEND_USE_ABS_CONST_ADDR @@ -1328,7 +1331,7 @@ static void zend_redo_pass_two_ex(zend_op_array *op_array, zend_ssa *ssa) opline = op_array->opcodes; end = opline + op_array->last; while (opline < end) { - zend_ssa_op *ssa_op = &ssa->ops[opline - op_array->opcodes]; + const zend_ssa_op *ssa_op = &ssa->ops[opline - op_array->opcodes]; uint32_t op1_info = opline->op1_type == IS_UNUSED ? 0 : (OP1_INFO() & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_KEY_ANY)); uint32_t op2_info = opline->op1_type == IS_UNUSED ? 0 : (OP2_INFO() & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_KEY_ANY)); uint32_t res_info = @@ -1458,13 +1461,13 @@ static void zend_optimize_op_array(zend_op_array *op_array, } } -static void zend_adjust_fcall_stack_size(zend_op_array *op_array, zend_optimizer_ctx *ctx) +static void zend_adjust_fcall_stack_size(const zend_op_array *op_array, const zend_optimizer_ctx *ctx) { zend_function *func; - zend_op *opline, *end; + zend_op *opline; opline = op_array->opcodes; - end = opline + op_array->last; + const zend_op* end = opline + op_array->last; while (opline < end) { if (opline->opcode == ZEND_INIT_FCALL) { func = zend_hash_find_ptr( @@ -1478,12 +1481,12 @@ static void zend_adjust_fcall_stack_size(zend_op_array *op_array, zend_optimizer } } -static void zend_adjust_fcall_stack_size_graph(zend_op_array *op_array) +static void zend_adjust_fcall_stack_size_graph(const zend_op_array *op_array) { - zend_func_info *func_info = ZEND_FUNC_INFO(op_array); + const zend_func_info *func_info = ZEND_FUNC_INFO(op_array); if (func_info) { - zend_call_info *call_info =func_info->callee_info; + const zend_call_info *call_info =func_info->callee_info; while (call_info) { zend_op *opline = call_info->caller_init_opline; @@ -1497,13 +1500,13 @@ static void zend_adjust_fcall_stack_size_graph(zend_op_array *op_array) } } -static bool needs_live_range(zend_op_array *op_array, zend_op *def_opline) { - zend_func_info *func_info = ZEND_FUNC_INFO(op_array); - zend_ssa_op *ssa_op = &func_info->ssa.ops[def_opline - op_array->opcodes]; +static bool needs_live_range(const zend_op_array *op_array, const zend_op *def_opline) { + const zend_func_info *func_info = ZEND_FUNC_INFO(op_array); + const zend_ssa_op *ssa_op = &func_info->ssa.ops[def_opline - op_array->opcodes]; int ssa_var = ssa_op->result_def; if (ssa_var < 0) { /* Be conservative. */ - return 1; + return true; } /* If the variable is used by a PHI, this may be the assignment of the final branch of a @@ -1540,7 +1543,7 @@ void zend_foreach_op_array(zend_script *script, zend_op_array_func_t func, void if (Z_TYPE_P(zv) == IS_ALIAS_PTR) { continue; } - zend_class_entry *ce = Z_CE_P(zv); + const zend_class_entry *ce = Z_CE_P(zv); ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) { if (op_array->scope == ce && op_array->type == ZEND_USER_FUNCTION @@ -1555,7 +1558,7 @@ void zend_foreach_op_array(zend_script *script, zend_op_array_func_t func, void zend_function **hooks = property->hooks; if (property->ce == ce && property->hooks) { for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) { - zend_function *hook = hooks[i]; + const zend_function *hook = hooks[i]; if (hook && hook->common.scope == ce && !(hooks[i]->op_array.fn_flags & ZEND_ACC_TRAIT_CLONE)) { zend_foreach_op_array_helper(&hooks[i]->op_array, func, context); } @@ -1606,7 +1609,7 @@ ZEND_API void zend_optimize_script(zend_script *script, zend_long optimization_l zend_call_graph call_graph; zend_build_call_graph(&ctx.arena, script, &call_graph); - int i; + uint32_t i; zend_func_info *func_info; for (i = 0; i < call_graph.op_arrays_count; i++) { @@ -1715,20 +1718,22 @@ ZEND_API void zend_optimize_script(zend_script *script, zend_long optimization_l if (Z_TYPE_P(zv) == IS_ALIAS_PTR) { continue; } - zend_class_entry *ce = Z_CE_P(zv); + const zend_class_entry *ce = Z_CE_P(zv); ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&ce->function_table, name, op_array) { if (op_array->scope != ce && op_array->type == ZEND_USER_FUNCTION) { - zend_op_array *orig_op_array = + const zend_op_array *orig_op_array = zend_hash_find_ptr(&op_array->scope->function_table, name); ZEND_ASSERT(orig_op_array != NULL); if (orig_op_array != op_array) { uint32_t fn_flags = op_array->fn_flags; + uint32_t fn_flags2 = op_array->fn_flags2; zend_function *prototype = op_array->prototype; HashTable *ht = op_array->static_variables; *op_array = *orig_op_array; op_array->fn_flags = fn_flags; + op_array->fn_flags2 = fn_flags2; op_array->prototype = prototype; op_array->static_variables = ht; } 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..869275811e3da 100644 --- a/Zend/Optimizer/zend_optimizer_internal.h +++ b/Zend/Optimizer/zend_optimizer_internal.h @@ -78,17 +78,17 @@ static inline bool zend_optimizer_is_loop_var_free(const zend_op *opline) { || (opline->opcode == ZEND_FREE && opline->extended_value == ZEND_FREE_SWITCH); } -void zend_optimizer_convert_to_free_op1(zend_op_array *op_array, zend_op *opline); -int zend_optimizer_add_literal(zend_op_array *op_array, const zval *zv); -bool zend_optimizer_get_persistent_constant(zend_string *name, zval *result, int copy); -void zend_optimizer_collect_constant(zend_optimizer_ctx *ctx, zval *name, zval* value); -bool zend_optimizer_get_collected_constant(HashTable *constants, zval *name, zval* value); +void zend_optimizer_convert_to_free_op1(const zend_op_array *op_array, zend_op *opline); +uint32_t zend_optimizer_add_literal(zend_op_array *op_array, const zval *zv); +bool zend_optimizer_get_persistent_constant(zend_string *name, zval *result, bool copy); +void zend_optimizer_collect_constant(zend_optimizer_ctx *ctx, const zval *name, zval* value); +bool zend_optimizer_get_collected_constant(const HashTable *constants, const zval *name, zval* value); zend_result zend_optimizer_eval_binary_op(zval *result, uint8_t opcode, zval *op1, zval *op2); zend_result zend_optimizer_eval_unary_op(zval *result, uint8_t opcode, zval *op1); zend_result zend_optimizer_eval_cast(zval *result, uint32_t type, zval *op1); zend_result zend_optimizer_eval_strlen(zval *result, const zval *op1); zend_result zend_optimizer_eval_special_func_call( - zval *result, zend_string *name, zend_string *arg); + zval *result, const zend_string *name, zend_string *arg); bool zend_optimizer_update_op1_const(zend_op_array *op_array, zend_op *opline, zval *val); @@ -120,15 +120,12 @@ void zend_optimizer_nop_removal(zend_op_array *op_array, zend_optimizer_ctx *ctx void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx *ctx); void zend_optimizer_compact_vars(zend_op_array *op_array); zend_function *zend_optimizer_get_called_func( - zend_script *script, zend_op_array *op_array, zend_op *opline, bool *is_prototype); -uint32_t zend_optimizer_classify_function(zend_string *name, uint32_t num_args); -void zend_optimizer_migrate_jump(zend_op_array *op_array, zend_op *new_opline, zend_op *opline); -void zend_optimizer_shift_jump(zend_op_array *op_array, zend_op *opline, uint32_t *shiftlist); -int sccp_optimize_op_array(zend_optimizer_ctx *ctx, zend_op_array *op_array, zend_ssa *ssa, zend_call_info **call_map); + const zend_script *script, const zend_op_array *op_array, zend_op *opline, bool *is_prototype); +uint32_t zend_optimizer_classify_function(const zend_string *name, uint32_t num_args); +void zend_optimizer_migrate_jump(const zend_op_array *op_array, zend_op *new_opline, zend_op *opline); +void zend_optimizer_shift_jump(const zend_op_array *op_array, zend_op *opline, const uint32_t *shiftlist); +uint32_t sccp_optimize_op_array(zend_optimizer_ctx *ctx, zend_op_array *op_array, zend_ssa *ssa, zend_call_info **call_map); 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..99978da9d7e80 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) { @@ -51,10 +52,10 @@ static bool will_rejoin( /* The other successor dominates this predecessor, * so we will get the original value from it. */ if (dominates(cfg->blocks, other_successor, predecessor)) { - return 1; + return true; } } - return 0; + return false; } static bool needs_pi(const zend_op_array *op_array, const zend_dfg *dfg, const zend_ssa *ssa, int from, int to, int var) /* {{{ */ @@ -64,7 +65,7 @@ static bool needs_pi(const zend_op_array *op_array, const zend_dfg *dfg, const z if (!DFG_ISSET(dfg->in, dfg->size, to, var)) { /* Variable is not live, certainly won't benefit from pi */ - return 0; + return false; } /* Make sure that both successors of the from block aren't the same. Pi nodes are associated @@ -72,13 +73,13 @@ static bool needs_pi(const zend_op_array *op_array, const zend_dfg *dfg, const z from_block = &ssa->cfg.blocks[from]; ZEND_ASSERT(from_block->successors_count == 2); if (from_block->successors[0] == from_block->successors[1]) { - return 0; + return false; } to_block = &ssa->cfg.blocks[to]; if (to_block->predecessors_count == 1) { /* Always place pi if one predecessor (an if branch) */ - return 1; + return true; } /* Check whether we will rejoin with the original value coming from the other successor, @@ -90,7 +91,7 @@ static bool needs_pi(const zend_op_array *op_array, const zend_dfg *dfg, const z /* }}} */ static zend_ssa_phi *add_pi( - zend_arena **arena, const zend_op_array *op_array, zend_dfg *dfg, zend_ssa *ssa, + zend_arena **arena, const zend_op_array *op_array, const zend_dfg *dfg, const zend_ssa *ssa, int from, int to, int var) /* {{{ */ { zend_ssa_phi *phi; @@ -130,7 +131,7 @@ static zend_ssa_phi *add_pi( static void pi_range( zend_ssa_phi *phi, int min_var, int max_var, zend_long min, zend_long max, - char underflow, char overflow, char negative) /* {{{ */ + bool underflow, bool overflow, bool negative) /* {{{ */ { zend_ssa_range_constraint *constraint = &phi->constraint.range; constraint->min_var = min_var; @@ -147,16 +148,16 @@ static void pi_range( /* }}} */ static inline void pi_range_equals(zend_ssa_phi *phi, int var, zend_long val) { - pi_range(phi, var, var, val, val, 0, 0, 0); + pi_range(phi, var, var, val, val, false, false, false); } static inline void pi_range_not_equals(zend_ssa_phi *phi, int var, zend_long val) { - pi_range(phi, var, var, val, val, 0, 0, 1); + pi_range(phi, var, var, val, val, false, false, true); } static inline void pi_range_min(zend_ssa_phi *phi, int var, zend_long val) { - pi_range(phi, var, -1, val, ZEND_LONG_MAX, 0, 1, 0); + pi_range(phi, var, -1, val, ZEND_LONG_MAX, false, true, false); } static inline void pi_range_max(zend_ssa_phi *phi, int var, zend_long val) { - pi_range(phi, -1, var, ZEND_LONG_MIN, val, 1, 0, 0); + pi_range(phi, -1, var, ZEND_LONG_MIN, val, true, false, false); } static void pi_type_mask(zend_ssa_phi *phi, uint32_t type_mask) { @@ -240,8 +241,8 @@ static int find_adjusted_tmp_var(const zend_op_array *op_array, uint32_t build_f */ static void place_essa_pis( zend_arena **arena, const zend_script *script, const zend_op_array *op_array, - uint32_t build_flags, zend_ssa *ssa, zend_dfg *dfg) /* {{{ */ { - zend_basic_block *blocks = ssa->cfg.blocks; + uint32_t build_flags, const zend_ssa *ssa, const zend_dfg *dfg) /* {{{ */ { + const zend_basic_block *blocks = ssa->cfg.blocks; int j, blocks_count = ssa->cfg.blocks_count; for (j = 0; j < blocks_count; j++) { zend_ssa_phi *pi; @@ -816,23 +817,14 @@ 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; + const zend_basic_block *blocks = ssa->cfg.blocks; + const zend_ssa_block *ssa_blocks = ssa->blocks; zend_ssa_op *ssa_ops = ssa->ops; 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; - } + const zend_op *opline, *end; if (ssa_blocks[n].phis) { zend_ssa_phi *phi = ssa_blocks[n].phis; @@ -857,7 +849,7 @@ static zend_result zend_ssa_rename(const zend_op_array *op_array, uint32_t build } } - zend_ssa_op *fe_fetch_ssa_op = blocks[n].len != 0 + const zend_ssa_op *fe_fetch_ssa_op = blocks[n].len != 0 && ((end-1)->opcode == ZEND_FE_FETCH_R || (end-1)->opcode == ZEND_FE_FETCH_RW) && (end-1)->op2_type == IS_CV ? &ssa_ops[blocks[n].start + blocks[n].len - 1] : NULL; @@ -916,26 +908,94 @@ 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) /* {{{ */ { - zend_basic_block *blocks = ssa->cfg.blocks; + const zend_basic_block *blocks = ssa->cfg.blocks; zend_ssa_block *ssa_blocks; int blocks_count = ssa->cfg.blocks_count; uint32_t set_size; @@ -1199,7 +1259,7 @@ ZEND_API void zend_ssa_compute_use_def_chains(zend_arena **arena, const zend_op_ } /* }}} */ -void zend_ssa_unlink_use_chain(zend_ssa *ssa, int op, int var) /* {{{ */ +void zend_ssa_unlink_use_chain(const zend_ssa *ssa, int op, int var) /* {{{ */ { if (ssa->vars[var].use_chain == op) { ssa->vars[var].use_chain = zend_ssa_next_use(ssa->ops, var, op); @@ -1238,7 +1298,7 @@ void zend_ssa_unlink_use_chain(zend_ssa *ssa, int op, int var) /* {{{ */ } /* }}} */ -void zend_ssa_replace_use_chain(zend_ssa *ssa, int op, int new_op, int var) /* {{{ */ +void zend_ssa_replace_use_chain(const zend_ssa *ssa, int op, int new_op, int var) /* {{{ */ { if (ssa->vars[var].use_chain == op) { ssa->vars[var].use_chain = new_op; @@ -1278,7 +1338,7 @@ void zend_ssa_replace_use_chain(zend_ssa *ssa, int op, int new_op, int var) /* { } /* }}} */ -void zend_ssa_remove_instr(zend_ssa *ssa, zend_op *opline, zend_ssa_op *ssa_op) /* {{{ */ +void zend_ssa_remove_instr(const zend_ssa *ssa, zend_op *opline, zend_ssa_op *ssa_op) /* {{{ */ { if (ssa_op->result_use >= 0) { zend_ssa_unlink_use_chain(ssa, ssa_op - ssa->ops, ssa_op->result_use); @@ -1309,7 +1369,7 @@ void zend_ssa_remove_instr(zend_ssa *ssa, zend_op *opline, zend_ssa_op *ssa_op) } /* }}} */ -static inline zend_ssa_phi **zend_ssa_next_use_phi_ptr(zend_ssa *ssa, int var, zend_ssa_phi *p) /* {{{ */ +static inline zend_ssa_phi **zend_ssa_next_use_phi_ptr(const zend_ssa *ssa, int var, zend_ssa_phi *p) /* {{{ */ { if (p->pi >= 0) { return &p->use_chains[0]; @@ -1328,7 +1388,7 @@ static inline zend_ssa_phi **zend_ssa_next_use_phi_ptr(zend_ssa *ssa, int var, z /* May be called even if source is not used in the phi (useful when removing uses in a phi * with multiple identical operands) */ -static inline void zend_ssa_remove_use_of_phi_source(zend_ssa *ssa, zend_ssa_phi *phi, int source, zend_ssa_phi *next_use_phi) /* {{{ */ +static inline void zend_ssa_remove_use_of_phi_source(const zend_ssa *ssa, const zend_ssa_phi *phi, int source, zend_ssa_phi *next_use_phi) /* {{{ */ { zend_ssa_phi **cur = &ssa->vars[source].phi_use_chain; while (*cur && *cur != phi) { @@ -1340,7 +1400,7 @@ static inline void zend_ssa_remove_use_of_phi_source(zend_ssa *ssa, zend_ssa_phi } /* }}} */ -static void zend_ssa_remove_uses_of_phi_sources(zend_ssa *ssa, zend_ssa_phi *phi) /* {{{ */ +static void zend_ssa_remove_uses_of_phi_sources(const zend_ssa *ssa, zend_ssa_phi *phi) /* {{{ */ { int source; FOREACH_PHI_SOURCE(phi, source) { @@ -1349,7 +1409,7 @@ static void zend_ssa_remove_uses_of_phi_sources(zend_ssa *ssa, zend_ssa_phi *phi } /* }}} */ -static void zend_ssa_remove_phi_from_block(zend_ssa *ssa, zend_ssa_phi *phi) /* {{{ */ +static void zend_ssa_remove_phi_from_block(const zend_ssa *ssa, const zend_ssa_phi *phi) /* {{{ */ { zend_ssa_block *block = &ssa->blocks[phi->block]; zend_ssa_phi **cur = &block->phis; @@ -1378,7 +1438,7 @@ void zend_ssa_remove_defs_of_instr(zend_ssa *ssa, zend_ssa_op *ssa_op) /* {{{ */ } /* }}} */ -static inline void zend_ssa_remove_phi_source(zend_ssa *ssa, zend_ssa_phi *phi, int pred_offset, int predecessors_count) /* {{{ */ +static inline void zend_ssa_remove_phi_source(const zend_ssa *ssa, const zend_ssa_phi *phi, int pred_offset, int predecessors_count) /* {{{ */ { int j, var_num = phi->sources[pred_offset]; zend_ssa_phi *next_phi = phi->use_chains[pred_offset]; @@ -1407,7 +1467,7 @@ static inline void zend_ssa_remove_phi_source(zend_ssa *ssa, zend_ssa_phi *phi, } /* }}} */ -void zend_ssa_remove_phi(zend_ssa *ssa, zend_ssa_phi *phi) /* {{{ */ +void zend_ssa_remove_phi(const zend_ssa *ssa, zend_ssa_phi *phi) /* {{{ */ { ZEND_ASSERT(phi->ssa_var >= 0); ZEND_ASSERT(ssa->vars[phi->ssa_var].use_chain < 0 @@ -1419,7 +1479,7 @@ void zend_ssa_remove_phi(zend_ssa *ssa, zend_ssa_phi *phi) /* {{{ */ } /* }}} */ -void zend_ssa_remove_uses_of_var(zend_ssa *ssa, int var_num) /* {{{ */ +void zend_ssa_remove_uses_of_var(const zend_ssa *ssa, int var_num) /* {{{ */ { zend_ssa_var *var = &ssa->vars[var_num]; zend_ssa_phi *phi; @@ -1455,7 +1515,7 @@ void zend_ssa_remove_uses_of_var(zend_ssa *ssa, int var_num) /* {{{ */ void zend_ssa_remove_predecessor(zend_ssa *ssa, int from, int to) /* {{{ */ { zend_basic_block *next_block = &ssa->cfg.blocks[to]; - zend_ssa_block *next_ssa_block = &ssa->blocks[to]; + const zend_ssa_block *next_ssa_block = &ssa->blocks[to]; zend_ssa_phi *phi; int j; @@ -1480,7 +1540,7 @@ void zend_ssa_remove_predecessor(zend_ssa *ssa, int from, int to) /* {{{ */ for (phi = next_ssa_block->phis; phi; phi = phi->next) { if (phi->pi >= 0) { if (phi->pi == from) { - zend_ssa_rename_var_uses(ssa, phi->ssa_var, phi->sources[0], /* update_types */ 0); + zend_ssa_rename_var_uses(ssa, phi->ssa_var, phi->sources[0], /* update_types */ false); zend_ssa_remove_phi(ssa, phi); } } else { @@ -1498,10 +1558,10 @@ void zend_ssa_remove_predecessor(zend_ssa *ssa, int from, int to) /* {{{ */ } /* }}} */ -void zend_ssa_remove_block(zend_op_array *op_array, zend_ssa *ssa, int i) /* {{{ */ +void zend_ssa_remove_block(const zend_op_array *op_array, zend_ssa *ssa, int i) /* {{{ */ { zend_basic_block *block = &ssa->cfg.blocks[i]; - zend_ssa_block *ssa_block = &ssa->blocks[i]; + const zend_ssa_block *ssa_block = &ssa->blocks[i]; zend_ssa_phi *phi; int j; @@ -1611,15 +1671,15 @@ void zend_ssa_rename_var_uses(zend_ssa *ssa, int old, int new, bool update_types /* If the op already uses the new var, don't add the op to the use * list again. Instead move the use_chain to the correct operand. */ - bool add_to_use_chain = 1; + bool add_to_use_chain = true; if (ssa_op->result_use == new) { - add_to_use_chain = 0; + add_to_use_chain = false; } else if (ssa_op->op1_use == new) { if (ssa_op->result_use == old) { ssa_op->res_use_chain = ssa_op->op1_use_chain; ssa_op->op1_use_chain = -1; } - add_to_use_chain = 0; + add_to_use_chain = false; } else if (ssa_op->op2_use == new) { if (ssa_op->result_use == old) { ssa_op->res_use_chain = ssa_op->op2_use_chain; @@ -1628,7 +1688,7 @@ void zend_ssa_rename_var_uses(zend_ssa *ssa, int old, int new, bool update_types ssa_op->op1_use_chain = ssa_op->op2_use_chain; ssa_op->op2_use_chain = -1; } - add_to_use_chain = 0; + add_to_use_chain = false; } /* Perform the actual renaming */ @@ -1663,7 +1723,7 @@ void zend_ssa_rename_var_uses(zend_ssa *ssa, int old, int new, bool update_types /* Update phi use chains */ FOREACH_PHI_USE(old_var, phi) { int j; - bool after_first_new_source = 0; + bool after_first_new_source = false; /* If the phi already uses the new var, find its use chain, as we may * need to move it to a different source operand. */ @@ -1677,7 +1737,7 @@ void zend_ssa_rename_var_uses(zend_ssa *ssa, int old, int new, bool update_types for (j = 0; j < ssa->cfg.blocks[phi->block].predecessors_count; j++) { if (phi->sources[j] == new) { - after_first_new_source = 1; + after_first_new_source = true; } else if (phi->sources[j] == old) { phi->sources[j] = new; @@ -1691,7 +1751,7 @@ void zend_ssa_rename_var_uses(zend_ssa *ssa, int old, int new, bool update_types phi->use_chains[j] = new_var->phi_use_chain; new_var->phi_use_chain = phi; } - after_first_new_source = 1; + after_first_new_source = true; } else { phi->use_chains[j] = NULL; } diff --git a/Zend/Optimizer/zend_ssa.h b/Zend/Optimizer/zend_ssa.h index 5995adcb14986..0696d2bba8671 100644 --- a/Zend/Optimizer/zend_ssa.h +++ b/Zend/Optimizer/zend_ssa.h @@ -147,15 +147,15 @@ BEGIN_EXTERN_C() 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); ZEND_API void zend_ssa_compute_use_def_chains(zend_arena **arena, const zend_op_array *op_array, zend_ssa *ssa); ZEND_API int zend_ssa_rename_op(const zend_op_array *op_array, const zend_op *opline, uint32_t k, uint32_t build_flags, int ssa_vars_count, zend_ssa_op *ssa_ops, int *var); -void zend_ssa_unlink_use_chain(zend_ssa *ssa, int op, int var); -void zend_ssa_replace_use_chain(zend_ssa *ssa, int op, int new_op, int var); +void zend_ssa_unlink_use_chain(const zend_ssa *ssa, int op, int var); +void zend_ssa_replace_use_chain(const zend_ssa *ssa, int op, int new_op, int var); void zend_ssa_remove_predecessor(zend_ssa *ssa, int from, int to); void zend_ssa_remove_defs_of_instr(zend_ssa *ssa, zend_ssa_op *ssa_op); -void zend_ssa_remove_instr(zend_ssa *ssa, zend_op *opline, zend_ssa_op *ssa_op); -void zend_ssa_remove_phi(zend_ssa *ssa, zend_ssa_phi *phi); -void zend_ssa_remove_uses_of_var(zend_ssa *ssa, int var_num); -void zend_ssa_remove_block(zend_op_array *op_array, zend_ssa *ssa, int b); +void zend_ssa_remove_instr(const zend_ssa *ssa, zend_op *opline, zend_ssa_op *ssa_op); +void zend_ssa_remove_phi(const zend_ssa *ssa, zend_ssa_phi *phi); +void zend_ssa_remove_uses_of_var(const zend_ssa *ssa, int var_num); +void zend_ssa_remove_block(const zend_op_array *op_array, zend_ssa *ssa, int b); void zend_ssa_rename_var_uses(zend_ssa *ssa, int old_var, int new_var, bool update_types); void zend_ssa_remove_block_from_cfg(zend_ssa *ssa, int b); @@ -240,21 +240,21 @@ static zend_always_inline void zend_ssa_rename_defs_of_instr(zend_ssa *ssa, zend /* Rename def to use if possible. Mark variable as not defined otherwise. */ if (ssa_op->op1_def >= 0) { if (ssa_op->op1_use >= 0) { - zend_ssa_rename_var_uses(ssa, ssa_op->op1_def, ssa_op->op1_use, 1); + zend_ssa_rename_var_uses(ssa, ssa_op->op1_def, ssa_op->op1_use, true); } ssa->vars[ssa_op->op1_def].definition = -1; ssa_op->op1_def = -1; } if (ssa_op->op2_def >= 0) { if (ssa_op->op2_use >= 0) { - zend_ssa_rename_var_uses(ssa, ssa_op->op2_def, ssa_op->op2_use, 1); + zend_ssa_rename_var_uses(ssa, ssa_op->op2_def, ssa_op->op2_use, true); } ssa->vars[ssa_op->op2_def].definition = -1; ssa_op->op2_def = -1; } if (ssa_op->result_def >= 0) { if (ssa_op->result_use >= 0) { - zend_ssa_rename_var_uses(ssa, ssa_op->result_def, ssa_op->result_use, 1); + zend_ssa_rename_var_uses(ssa, ssa_op->result_def, ssa_op->result_use, true); } ssa->vars[ssa_op->result_def].definition = -1; ssa_op->result_def = -1; diff --git a/Zend/Optimizer/zend_worklist.h b/Zend/Optimizer/zend_worklist.h index f47d01bd1579b..85e7b111d5c94 100644 --- a/Zend/Optimizer/zend_worklist.h +++ b/Zend/Optimizer/zend_worklist.h @@ -97,12 +97,12 @@ static inline bool zend_worklist_push(zend_worklist *worklist, int i) ZEND_ASSERT(i >= 0 && i < worklist->stack.capacity); if (zend_bitset_in(worklist->visited, i)) { - return 0; + return false; } zend_bitset_incl(worklist->visited, i); zend_worklist_stack_push(&worklist->stack, i); - return 1; + return true; } static inline int zend_worklist_peek(const zend_worklist *worklist) diff --git a/Zend/Zend.m4 b/Zend/Zend.m4 index 69a546afce491..33009e9909f5a 100644 --- a/Zend/Zend.m4 +++ b/Zend/Zend.m4 @@ -170,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]) @@ -193,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 @@ -471,3 +465,111 @@ 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_preserve_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" +#if defined(__APPLE__) + "call _fun\n" +#else + "call fun\n" +#endif + : "=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" +#if defined(__APPLE__) + "bl _fun\n" +#else + "bl fun\n" +#endif + "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/asm/jump_s390x_sysv_elf_gas.S b/Zend/asm/jump_s390x_sysv_elf_gas.S index c2a578b2663eb..fa71467756d21 100644 --- a/Zend/asm/jump_s390x_sysv_elf_gas.S +++ b/Zend/asm/jump_s390x_sysv_elf_gas.S @@ -49,11 +49,12 @@ .type jump_fcontext, @function #define ARG_OFFSET 0 -#define GR_OFFSET 16 -#define FP_OFFSET 96 -#define FPC_OFFSET 160 -#define PC_OFFSET 168 -#define CONTEXT_SIZE 176 +#define GR_OFFSET 16 +#define R14_OFFSET 88 +#define FP_OFFSET 96 +#define FPC_OFFSET 160 +#define PC_OFFSET 168 +#define CONTEXT_SIZE 176 #define REG_SAVE_AREA_SIZE 160 @@ -131,11 +132,14 @@ jump_fcontext: ltg %r2,GR_OFFSET(%r15) jnz use_return_slot - /* We restore a make_fcontext context. Use the function - argument slot in the context we just saved and allocate the - register save area for the target function. */ - la %r2,ARG_OFFSET(%r1) - aghi %r15,-REG_SAVE_AREA_SIZE + /* We're restoring a context created by make_fcontext. + This is going to be the argument of the entry point + of the fiber. We're placing it on top of the ABI + defined register save area of the fiber's own stack. */ + la %r2,REG_SAVE_AREA_SIZE(%r15) + + /* REG_SAVE_AREA_SIZE + sizeof(transfer_t) */ + aghi %r15,-(REG_SAVE_AREA_SIZE+16) use_return_slot: /* Save the two fields in transfer_t. When calling a diff --git a/Zend/asm/jump_sparc64_sysv_elf_gas.S b/Zend/asm/jump_sparc64_sysv_elf_gas.S index 727687aad804a..61101fb1f6297 100644 --- a/Zend/asm/jump_sparc64_sysv_elf_gas.S +++ b/Zend/asm/jump_sparc64_sysv_elf_gas.S @@ -6,12 +6,14 @@ */ /* - * typedef struct { - * void *handle; - * zend_fiber_transfer *transfer; - * } boost_context_data; + * typedef void* fcontext_t; * - * boost_context_data jump_fcontext(void *to, zend_fiber_transfer *transfer); + * struct transfer_t { + * fcontext_t fctx; + * void * data; + * }; + * + * transfer_t jump_fcontext(fcontext_t const to, void *vp); */ #define CC64FSZ 176 #define BIAS 2047 diff --git a/Zend/asm/jump_x86_64_ms_pe_gas.S b/Zend/asm/jump_x86_64_ms_pe_gas.S index 5ebc46f364030..ec4ecfe946d3e 100644 --- a/Zend/asm/jump_x86_64_ms_pe_gas.S +++ b/Zend/asm/jump_x86_64_ms_pe_gas.S @@ -89,6 +89,7 @@ .file "jump_x86_64_ms_pe_gas.asm" .text .p2align 4,,15 +.globl jump_fcontext .def jump_fcontext; .scl 2; .type 32; .endef .seh_proc jump_fcontext jump_fcontext: @@ -203,3 +204,6 @@ jump_fcontext: /* indirect jump to context */ jmp *%r10 .seh_endproc + +.section .drectve +.ascii " -export:\"jump_fcontext\"" diff --git a/Zend/asm/make_s390x_sysv_elf_gas.S b/Zend/asm/make_s390x_sysv_elf_gas.S index e7e2d5f6e0c9f..4dd423e2a44c2 100644 --- a/Zend/asm/make_s390x_sysv_elf_gas.S +++ b/Zend/asm/make_s390x_sysv_elf_gas.S @@ -49,12 +49,12 @@ .type make_fcontext, @function #define ARG_OFFSET 0 -#define GR_OFFSET 16 -#define R14_OFFSET 88 -#define FP_OFFSET 96 -#define FPC_OFFSET 160 -#define PC_OFFSET 168 -#define CONTEXT_SIZE 176 +#define GR_OFFSET 16 +#define R14_OFFSET 88 +#define FP_OFFSET 96 +#define FPC_OFFSET 160 +#define PC_OFFSET 168 +#define CONTEXT_SIZE 176 /* @@ -72,7 +72,7 @@ r4 - The address of the context function make_fcontext: .machine "z10" /* Align the stack to an 8 byte boundary. */ - nill %r2,0xfff0 + nill %r2,0xfff8 /* Allocate stack space for the context. */ aghi %r2,-CONTEXT_SIZE diff --git a/Zend/asm/make_sparc64_sysv_elf_gas.S b/Zend/asm/make_sparc64_sysv_elf_gas.S index 52ff70b996b66..3e7ee809c9187 100644 --- a/Zend/asm/make_sparc64_sysv_elf_gas.S +++ b/Zend/asm/make_sparc64_sysv_elf_gas.S @@ -6,7 +6,7 @@ */ /* - * void *make_fcontext(void *sp, size_t size, void (*fn)(boost_context_data)); + * fcontext_t *make_fcontext(void *sp, size_t size, void (*fn)(transfer_t)); */ #define CC64FSZ 176 #define BIAS 2047 @@ -56,7 +56,7 @@ make_fcontext: trampoline: ldx [%sp + BIAS + I7], %l0 - # no need to setup boost_context_data, already in %o0 and %o1 + # no need to setup transfer_t, already in %o0 and %o1 jmpl %l0, %o7 nop diff --git a/Zend/asm/make_x86_64_ms_pe_gas.S b/Zend/asm/make_x86_64_ms_pe_gas.S index 66a9bb3953567..958a2a7b6d0ea 100644 --- a/Zend/asm/make_x86_64_ms_pe_gas.S +++ b/Zend/asm/make_x86_64_ms_pe_gas.S @@ -89,6 +89,7 @@ .file "make_x86_64_ms_pe_gas.asm" .text .p2align 4,,15 +.globl make_fcontext .def make_fcontext; .scl 2; .type 32; .endef .seh_proc make_fcontext make_fcontext: @@ -168,3 +169,6 @@ finish: .seh_endproc .def _exit; .scl 2; .type 32; .endef /* standard C library function */ + +.section .drectve +.ascii " -export:\"make_fcontext\"" diff --git a/Zend/tests/002.phpt b/Zend/tests/002.phpt deleted file mode 100644 index 7c2ff7b4d389d..0000000000000 --- a/Zend/tests/002.phpt +++ /dev/null @@ -1,121 +0,0 @@ ---TEST-- -func_get_arg() tests ---FILE-- -getMessage() . \PHP_EOL; - } - - try { - var_dump(func_get_arg(0)); - } catch (\Error $e) { - echo $e->getMessage() . \PHP_EOL; - } - try { - var_dump(func_get_arg(1)); - } catch (\Error $e) { - echo $e->getMessage() . \PHP_EOL; - } -} - -function test2($a) { - try { - var_dump(func_get_arg(0)); - } catch (\Error $e) { - echo $e->getMessage() . \PHP_EOL; - } - try { - var_dump(func_get_arg(1)); - } catch (\Error $e) { - echo $e->getMessage() . \PHP_EOL; - } -} - -function test3($a, $b) { - try { - var_dump(func_get_arg(0)); - } catch (\Error $e) { - echo $e->getMessage() . \PHP_EOL; - } - try { - var_dump(func_get_arg(1)); - } catch (\Error $e) { - echo $e->getMessage() . \PHP_EOL; - } - try { - var_dump(func_get_arg(2)); - } catch (\Error $e) { - echo $e->getMessage() . \PHP_EOL; - } -} - -test1(); -test1(10); -test2(1); -try { - test2(); -} catch (Throwable $e) { - echo "Exception: " . $e->getMessage() . "\n"; -} -test3(1,2); - -call_user_func("test1"); -try { - call_user_func("test3", 1); -} catch (Throwable $e) { - echo "Exception: " . $e->getMessage() . "\n"; -} -call_user_func("test3", 1, 2); - -class test { - static function test1($a) { - try { - var_dump(func_get_arg(0)); - } catch (\Error $e) { - echo $e->getMessage() . \PHP_EOL; - } - try { - var_dump(func_get_arg(1)); - } catch (\Error $e) { - echo $e->getMessage() . \PHP_EOL; - } - } -} - -test::test1(1); -try { - var_dump(func_get_arg(1)); -} catch (\Error $e) { - echo $e->getMessage() . \PHP_EOL; -} - -echo "Done\n"; -?> ---EXPECTF-- -func_get_arg(): Argument #1 ($position) must be greater than or equal to 0 -func_get_arg(): Argument #1 ($position) must be less than the number of the arguments passed to the currently executed function -func_get_arg(): Argument #1 ($position) must be less than the number of the arguments passed to the currently executed function -func_get_arg(): Argument #1 ($position) must be greater than or equal to 0 -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 -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 -func_get_arg(): Argument #1 ($position) must be greater than or equal to 0 -func_get_arg(): Argument #1 ($position) must be less than the number of the arguments passed to the currently executed function -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 test3(), 1 passed in %s on line %d and exactly 2 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 -int(1) -func_get_arg(): Argument #1 ($position) must be less than the number of the arguments passed to the currently executed function -func_get_arg() cannot be called from the global scope -Done diff --git a/Zend/tests/003.phpt b/Zend/tests/003.phpt deleted file mode 100644 index 3931628e9a9ca..0000000000000 --- a/Zend/tests/003.phpt +++ /dev/null @@ -1,82 +0,0 @@ ---TEST-- -func_get_args() tests ---FILE-- -getMessage() . "\n"; -} -test3(1,2); - -call_user_func("test1"); -try { - call_user_func("test3", 1); -} catch (Throwable $e) { - echo "Exception: " . $e->getMessage() . "\n"; -} -call_user_func("test3", 1, 2); - -class test { - static function test1($a) { - var_dump(func_get_args()); - } -} - -test::test1(1); - -try { - var_dump(func_get_args()); -} catch (\Error $e) { - echo $e->getMessage() . \PHP_EOL; -} - -?> ---EXPECTF-- -array(0) { -} -array(1) { - [0]=> - int(10) -} -array(1) { - [0]=> - int(1) -} -Exception: Too few arguments to function test2(), 0 passed in %s003.php on line %d and exactly 1 expected -array(2) { - [0]=> - int(1) - [1]=> - int(2) -} -array(0) { -} -Exception: Too few arguments to function test3(), 1 passed in %s003.php on line %d and exactly 2 expected -array(2) { - [0]=> - int(1) - [1]=> - int(2) -} -array(1) { - [0]=> - int(1) -} -func_get_args() cannot be called from the global scope 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/014.phpt b/Zend/tests/014.phpt deleted file mode 100644 index c02fee93856f1..0000000000000 --- a/Zend/tests/014.phpt +++ /dev/null @@ -1,42 +0,0 @@ ---TEST-- -get_included_files() tests ---FILE-- - ---EXPECTF-- -array(1) { - [0]=> - string(%d) "%s" -} -array(2) { - [0]=> - string(%d) "%s" - [1]=> - string(%d) "%s" -} -array(2) { - [0]=> - string(%d) "%s" - [1]=> - string(%d) "%s" -} -array(2) { - [0]=> - string(%d) "%s" - [1]=> - string(%d) "%s" -} -Done diff --git a/Zend/tests/019.phpt b/Zend/tests/019.phpt deleted file mode 100644 index 4bc9d6be530cd..0000000000000 --- a/Zend/tests/019.phpt +++ /dev/null @@ -1,1321 +0,0 @@ ---TEST-- -Test unset(), empty() and isset() functions ---FILE-- - "One", 2 => "two"), - array("Name" => "Jack", "Age" => "30"), - array(1,2, "One" => "1", 2 => "two", ""=>"empty", "" => '') -); - -$outer_loop_counter = 1; -foreach ($array_variables as $array_var) { - echo "--- Outerloop Iteration $outer_loop_counter ---\n"; - - // check the isset and unset on non existing key - $var = 1; // a var which is defined - // try to unset the element which is non-existent - unset($array_var['non_existent']); - // check using isset() & empty() on a non_existent element in the array - var_dump( isset($array_var['non_existent']) ); - var_dump( isset($array_var['non_existent'], $var) ); - var_dump( isset($array_var['non_existent'], $array_var['none']) ); - var_dump( empty($array_var['non_existent']) ); - - // testing empty and isset on arrays - var_dump( empty($array_var) ); // expecting bool(false), except: array(), which is considered empty - var_dump( isset($array_var) ); // expecting bool(true), except: array(), which is not set - - // get the keys of the $array_var - $keys = array_keys($array_var); - // unset each element in the array and see the working of unset, isset & empty - $inner_loop_counter = 1; - foreach ($keys as $key_value) { - echo "-- Innerloop Iteration $inner_loop_counter of Outerloop Iteration $outer_loop_counter --\n"; - $inner_loop_counter++; - - // unset the element - unset($array_var[$key_value]); - // dump the array after element was unset - var_dump($array_var); - // check using isset for the element that was unset - var_dump( isset($array_var[$key_val]) ); // expected: bool(false) - // calling isset with more args - var_dump( isset($array_var[$key_val], $array_var) ); //expected: bool(false) - - // calling empty, expected bool(true) - var_dump( empty($array_var[$key_val]) ); - - // dump the array to see that that array did not get modified - // because of using isset, empty and unset on its element - var_dump($array_var); - } - - $outer_loop_counter++; - - // unset the whole array - unset($array_var); - // dump the array to see its unset - var_dump($array_var); - // use isset to see that array is not set - var_dump( isset($array_var) ); //expected: bool(false) - var_dump( isset($array_var, $array_var[$key_val]) ); // expected: bool(false) - - // empty() to see if the array is empty - var_dump( empty($array_var) ); // expected: bool(true) -} - -echo "\n*** Testing unset(), empty() & isset() with resource variables ***\n"; -$fp = fopen(__FILE__, "r"); -$dfp = opendir( __DIR__ ); -$resources = array ( - $fp, - $dfp -); -$loop_counter = 1; -foreach ($resources as $resource) { - $temp_var = 10; - echo "-- Iteration $loop_counter --\n"; $loop_counter++; - //dump the resource first - var_dump($resource); - - // check using isset() and empty() - var_dump( isset($resource) ); // expected: bool(true) - var_dump( empty($resource) ); // expected: bool(false) - // call isset() with two args, both set - var_dump( isset($resource, $temp_var) ); // expected: bool(true) - - // dump the resource to see using isset() and empty () had no effect on it - var_dump($resource); - - // unset the resource - unset($resource); - // check using isset() and empty() - var_dump( isset($resource) ); // expected: bool(false) - var_dump( empty($resource) ); // expected: bool(true) - // call isset() with two args, but one set - var_dump( isset($resource, $temp_var) ); // expected: bool(false) - // unset the temp_var - unset($temp_var); - // now the isset() with both the args as unset - var_dump( isset($resource, $temp_var) ); // expected: bool(false); - - // dump the resource to see if there any effect on it - var_dump($resource); -} -// unset and dump the array containing all the resources to see that -// unset works correctly -unset($resources); -var_dump($resources); -var_dump( isset($resources) ); //expected: bool(false) -var_dump( empty($resources) ); // expected: bool(true) - -echo "\n*** Testing unset(), empty() & isset() with objects ***\n"; -class Point -{ - var $x; - var $y; - var $lable; - - function __construct($x, $y) { - $this->x = $x; - $this->y = $y; - } - - function setLable($lable) { - $this->lable = $lable; - } - function testPoint() { - echo "\nPoint::testPoint() called\n"; - } -} -$point1 = new Point(30,40); - -// use unset/empty/isset to check the object -var_dump($point1); // dump the object - -// check the object and member that is not set -var_dump( isset($point1) ); // expected: bool(true) -var_dump( empty($point1) ); // expected: bool(false) -var_dump( isset($point1->$lable) ); //expected: bool(false) -var_dump( empty($point1->$lable) ); //expected: bool(true) - -//set the member variable lable and check -$point1->setLable("Point1"); -var_dump( isset($point1->$lable) ); //expected: bool(true) -var_dump( empty($point1->$lable) ); //expected: bool(false) - -// dump the object to see that obj was not harmed -// because of the usage of the isset & empty -var_dump($point1); - -//unset a member and check -unset($point1->x); -// dump the point to see that variable was unset -var_dump($point1); -var_dump( isset($point1->x) ); // expected: bool(false) -var_dump( empty($point1->x) ); // expected: bool(true) - -// unset all members and check -unset($point1->y); -unset($point1->lable); -// dump the object to check that all variables are unset -var_dump($point1); -var_dump( isset($point1) ); // expected: bool(ture) -var_dump( empty($point1) ); // expected: bool(false) - -//unset the object and check -unset($point1); -var_dump( isset($point1) ); // expected: bool(false) -var_dump( empty($point1) ); // expected: bool(true) -// dump to see that object is unset -var_dump($point1); - -// try isset/unset/empty on a member function -$point2 = new Point(5,6); -var_dump( isset($point2->testPoint) ); -var_dump( empty($point2->testPoint) ); -unset($point2->testPoint); -var_dump( isset($point2->testPoint) ); -var_dump( empty($point2->testPoint) ); - -// use get_class_methods to see effect if any -var_dump( get_class_methods($point2) ); -// dump the object to see the effect, none expected -var_dump($point2); - -/* testing variation in operation for isset(), empty() & unset(). -Note: Most of the variation for function unset() is testing by a - set of testcases named "Zend/tests/unset_cv??.phpt", only - variation not tested are attempted here */ - -echo "\n*** Testing possible variation in operation for isset(), empty() & unset() ***\n"; -/* unset() variation1: checking unset on static variable inside a function. - * unset() destroys the variable only in the context of the rest of a function - * Following calls will restore the previous value of a variable. - */ -echo "\n** Testing unset() variation 1: unset on static variable inside a function **\n"; -function test_unset1() { - static $static_var; - - // increment the value of the static. this change is in function context - $static_var ++; - - echo "value of static_var before unset: $static_var\n"; - // check using isset and empty - var_dump( isset($static_var) ); - var_dump( empty($static_var) ); - - // unset the static var - unset($static_var); - echo "value of static_var after unset: $static_var\n"; - // check using isset and empty - var_dump( isset($static_var) ); - var_dump( empty($static_var) ); - - // assign a value to static var - $static_var = 20; - echo "value of static_var after new assignment: $static_var\n"; -} -// call the function -test_unset1(); -test_unset1(); -test_unset1(); - - -echo "\n** Testing unset() variation 2: unset on a variable passed by ref. inside of a function **\n"; -/* unset() variation2: Pass by reference - * If a variable that is PASSED BY REFERENCE is unset() inside of a function, - * only the local variable is destroyed. The variable in the calling environment - * will retain the same value as before unset() was called. - */ -function test_unset2( &$ref_val ) { - // unset the variable passed - unset($ref_val); - // check using isset and empty to confirm - var_dump( isset($ref_val) ); - var_dump( empty($ref_val) ); - - // set the value ot a new one - $ref_val = "new value by ref"; -} - -$value = "value"; -var_dump($value); -test_unset2($value); -var_dump($value); - - -echo "\n** Testing unset() variation 3: unset on a global variable inside of a function **\n"; -/* unset() variation2: unset on a global variable inside a function - * If a globalized variable is unset() inside of a function, only the - * local variable is destroyed. The variable in the calling environment - * will retain the same value as before unset() was called. - */ -$global_var = 10; - -function test_unset3() { - global $global_var; - - // check the $global_var using isset and empty - var_dump( isset($global_var) ); - var_dump( empty($global_var) ); - - // unset the global var - unset($global_var); - - // check the $global_var using isset and empty - var_dump( isset($global_var) ); - var_dump( empty($global_var) ); -} - -var_dump($global_var); -test_unset3(); -var_dump($global_var); - -//Note: No error conditions relating to passing arguments can be tested -// because these are not functions but statements, it will result in syntax error. -?> ---EXPECTF-- -*** Testing unset(), empty() & isset() with scalar variables *** --- Iteration 1 -- -bool(true) -bool(true) -bool(true) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 2 -- -bool(true) -bool(true) -bool(false) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 3 -- -bool(true) -bool(true) -bool(true) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 4 -- -bool(true) -bool(true) -bool(false) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 5 -- -bool(true) -bool(true) -bool(false) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 6 -- -bool(true) -bool(true) -bool(false) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 7 -- -bool(true) -bool(true) -bool(false) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 8 -- -bool(true) -bool(true) -bool(true) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 9 -- -bool(true) -bool(true) -bool(false) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 10 -- -bool(true) -bool(true) -bool(false) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 11 -- -bool(true) -bool(true) -bool(false) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 12 -- -bool(true) -bool(true) -bool(false) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 13 -- -bool(true) -bool(true) -bool(true) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 14 -- -bool(true) -bool(true) -bool(true) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 15 -- -bool(true) -bool(true) -bool(false) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 16 -- -bool(true) -bool(true) -bool(false) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 17 -- -bool(true) -bool(true) -bool(false) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 18 -- -bool(true) -bool(true) -bool(false) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 19 -- -bool(true) -bool(true) -bool(true) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 20 -- -bool(true) -bool(true) -bool(false) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 21 -- -bool(true) -bool(true) -bool(false) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 22 -- -bool(true) -bool(true) -bool(false) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 23 -- -bool(true) -bool(true) -bool(false) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 24 -- -bool(true) -bool(true) -bool(false) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 25 -- -bool(true) -bool(true) -bool(true) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 26 -- -bool(true) -bool(true) -bool(false) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) --- Iteration 27 -- -bool(true) -bool(true) -bool(true) - -Warning: Undefined variable $scalar_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) -bool(false) -bool(false) - -*** Testing unset(), empty() & isset() with arrays *** ---- Outerloop Iteration 1 --- -bool(false) -bool(false) -bool(false) -bool(true) -bool(true) -bool(true) - -Warning: Undefined variable $array_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) ---- Outerloop Iteration 2 --- -bool(false) -bool(false) -bool(false) -bool(true) -bool(false) -bool(true) --- Innerloop Iteration 1 of Outerloop Iteration 2 -- -array(0) { -} - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) -array(0) { -} - -Warning: Undefined variable $array_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) ---- Outerloop Iteration 3 --- -bool(false) -bool(false) -bool(false) -bool(true) -bool(false) -bool(true) --- Innerloop Iteration 1 of Outerloop Iteration 3 -- -array(0) { -} - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) -array(0) { -} - -Warning: Undefined variable $array_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) ---- Outerloop Iteration 4 --- -bool(false) -bool(false) -bool(false) -bool(true) -bool(false) -bool(true) --- Innerloop Iteration 1 of Outerloop Iteration 4 -- -array(0) { -} - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) -array(0) { -} - -Warning: Undefined variable $array_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) ---- Outerloop Iteration 5 --- -bool(false) -bool(false) -bool(false) -bool(true) -bool(false) -bool(true) --- Innerloop Iteration 1 of Outerloop Iteration 5 -- -array(0) { -} - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) -array(0) { -} - -Warning: Undefined variable $array_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) ---- Outerloop Iteration 6 --- -bool(false) -bool(false) -bool(false) -bool(true) -bool(false) -bool(true) --- Innerloop Iteration 1 of Outerloop Iteration 6 -- -array(3) { - [1]=> - int(2) - [2]=> - int(3) - [3]=> - int(4) -} - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) -array(3) { - [1]=> - int(2) - [2]=> - int(3) - [3]=> - int(4) -} --- Innerloop Iteration 2 of Outerloop Iteration 6 -- -array(2) { - [2]=> - int(3) - [3]=> - int(4) -} - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) -array(2) { - [2]=> - int(3) - [3]=> - int(4) -} --- Innerloop Iteration 3 of Outerloop Iteration 6 -- -array(1) { - [3]=> - int(4) -} - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) -array(1) { - [3]=> - int(4) -} --- Innerloop Iteration 4 of Outerloop Iteration 6 -- -array(0) { -} - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) -array(0) { -} - -Warning: Undefined variable $array_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) ---- Outerloop Iteration 7 --- -bool(false) -bool(false) -bool(false) -bool(true) -bool(false) -bool(true) --- Innerloop Iteration 1 of Outerloop Iteration 7 -- -array(2) { - [1]=> - float(2.5) - [2]=> - float(5.6) -} - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) -array(2) { - [1]=> - float(2.5) - [2]=> - float(5.6) -} --- Innerloop Iteration 2 of Outerloop Iteration 7 -- -array(1) { - [2]=> - float(5.6) -} - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) -array(1) { - [2]=> - float(5.6) -} --- Innerloop Iteration 3 of Outerloop Iteration 7 -- -array(0) { -} - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) -array(0) { -} - -Warning: Undefined variable $array_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) ---- Outerloop Iteration 8 --- -bool(false) -bool(false) -bool(false) -bool(true) -bool(false) -bool(true) --- Innerloop Iteration 1 of Outerloop Iteration 8 -- -array(1) { - [2]=> - string(3) "two" -} - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) -array(1) { - [2]=> - string(3) "two" -} --- Innerloop Iteration 2 of Outerloop Iteration 8 -- -array(0) { -} - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) -array(0) { -} - -Warning: Undefined variable $array_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) ---- Outerloop Iteration 9 --- -bool(false) -bool(false) -bool(false) -bool(true) -bool(false) -bool(true) --- Innerloop Iteration 1 of Outerloop Iteration 9 -- -array(1) { - ["Age"]=> - string(2) "30" -} - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) -array(1) { - ["Age"]=> - string(2) "30" -} --- Innerloop Iteration 2 of Outerloop Iteration 9 -- -array(0) { -} - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) -array(0) { -} - -Warning: Undefined variable $array_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) ---- Outerloop Iteration 10 --- -bool(false) -bool(false) -bool(false) -bool(true) -bool(false) -bool(true) --- Innerloop Iteration 1 of Outerloop Iteration 10 -- -array(4) { - [1]=> - int(2) - ["One"]=> - string(1) "1" - [2]=> - string(3) "two" - [""]=> - string(0) "" -} - -Warning: Undefined variable $key_val in %s on line %d -bool(true) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) -array(4) { - [1]=> - int(2) - ["One"]=> - string(1) "1" - [2]=> - string(3) "two" - [""]=> - string(0) "" -} --- Innerloop Iteration 2 of Outerloop Iteration 10 -- -array(3) { - ["One"]=> - string(1) "1" - [2]=> - string(3) "two" - [""]=> - string(0) "" -} - -Warning: Undefined variable $key_val in %s on line %d -bool(true) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) -array(3) { - ["One"]=> - string(1) "1" - [2]=> - string(3) "two" - [""]=> - string(0) "" -} --- Innerloop Iteration 3 of Outerloop Iteration 10 -- -array(2) { - [2]=> - string(3) "two" - [""]=> - string(0) "" -} - -Warning: Undefined variable $key_val in %s on line %d -bool(true) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) -array(2) { - [2]=> - string(3) "two" - [""]=> - string(0) "" -} --- Innerloop Iteration 4 of Outerloop Iteration 10 -- -array(1) { - [""]=> - string(0) "" -} - -Warning: Undefined variable $key_val in %s on line %d -bool(true) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) -array(1) { - [""]=> - string(0) "" -} --- Innerloop Iteration 5 of Outerloop Iteration 10 -- -array(0) { -} - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(false) - -Warning: Undefined variable $key_val in %s on line %d -bool(true) -array(0) { -} - -Warning: Undefined variable $array_var in %s on line %d -NULL -bool(false) -bool(false) -bool(true) - -*** Testing unset(), empty() & isset() with resource variables *** --- Iteration 1 -- -resource(%d) of type (stream) -bool(true) -bool(false) -bool(true) -resource(%d) of type (stream) -bool(false) -bool(true) -bool(false) -bool(false) - -Warning: Undefined variable $resource in %s on line %d -NULL --- Iteration 2 -- -resource(%d) of type (stream) -bool(true) -bool(false) -bool(true) -resource(%d) of type (stream) -bool(false) -bool(true) -bool(false) -bool(false) - -Warning: Undefined variable $resource in %s on line %d -NULL - -Warning: Undefined variable $resources in %s on line %d -NULL -bool(false) -bool(true) - -*** Testing unset(), empty() & isset() with objects *** -object(Point)#%d (3) { - ["x"]=> - int(30) - ["y"]=> - int(40) - ["lable"]=> - NULL -} -bool(true) -bool(false) - -Warning: Undefined variable $lable in %s on line %d -bool(false) - -Warning: Undefined variable $lable in %s on line %d -bool(true) - -Warning: Undefined variable $lable in %s on line %d -bool(false) - -Warning: Undefined variable $lable in %s on line %d -bool(true) -object(Point)#%d (3) { - ["x"]=> - int(30) - ["y"]=> - int(40) - ["lable"]=> - string(6) "Point1" -} -object(Point)#%d (2) { - ["y"]=> - int(40) - ["lable"]=> - string(6) "Point1" -} -bool(false) -bool(true) -object(Point)#%d (0) { -} -bool(true) -bool(false) -bool(false) -bool(true) - -Warning: Undefined variable $point1 in %s on line %d -NULL -bool(false) -bool(true) -bool(false) -bool(true) -array(3) { - [0]=> - string(11) "__construct" - [1]=> - string(8) "setLable" - [2]=> - string(9) "testPoint" -} -object(Point)#%d (3) { - ["x"]=> - int(5) - ["y"]=> - int(6) - ["lable"]=> - NULL -} - -*** Testing possible variation in operation for isset(), empty() & unset() *** - -** Testing unset() variation 1: unset on static variable inside a function ** -value of static_var before unset: 1 -bool(true) -bool(false) - -Warning: Undefined variable $static_var in %s on line %d -value of static_var after unset: -bool(false) -bool(true) -value of static_var after new assignment: 20 -value of static_var before unset: 2 -bool(true) -bool(false) - -Warning: Undefined variable $static_var in %s on line %d -value of static_var after unset: -bool(false) -bool(true) -value of static_var after new assignment: 20 -value of static_var before unset: 3 -bool(true) -bool(false) - -Warning: Undefined variable $static_var in %s on line %d -value of static_var after unset: -bool(false) -bool(true) -value of static_var after new assignment: 20 - -** Testing unset() variation 2: unset on a variable passed by ref. inside of a function ** -string(5) "value" -bool(false) -bool(true) -string(5) "value" - -** Testing unset() variation 3: unset on a global variable inside of a function ** -int(10) -bool(true) -bool(false) -bool(false) -bool(true) -int(10) diff --git a/Zend/tests/027.phpt b/Zend/tests/027.phpt deleted file mode 100644 index a862d689e1a84..0000000000000 --- a/Zend/tests/027.phpt +++ /dev/null @@ -1,22 +0,0 @@ ---TEST-- -Testing dynamic calls using variable variables with curly syntax ---FILE-- - ---EXPECT-- -bool(true) -bool(true) 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/asymmetric_visibility/virtual_get_only.phpt b/Zend/tests/asymmetric_visibility/virtual_get_only.phpt index 3eaada70329d4..a3f6f980bdfe3 100644 --- a/Zend/tests/asymmetric_visibility/virtual_get_only.phpt +++ b/Zend/tests/asymmetric_visibility/virtual_get_only.phpt @@ -11,4 +11,4 @@ class Foo { ?> --EXPECTF-- -Fatal error: Read-only virtual property Foo::$bar must not specify asymmetric visibility in %s on line %d +Fatal error: get-only virtual property Foo::$bar must not specify asymmetric visibility in %s on line %d diff --git a/Zend/tests/asymmetric_visibility/virtual_set_only.phpt b/Zend/tests/asymmetric_visibility/virtual_set_only.phpt index 18abb7ac046a4..7d1d2bc7cb99f 100644 --- a/Zend/tests/asymmetric_visibility/virtual_set_only.phpt +++ b/Zend/tests/asymmetric_visibility/virtual_set_only.phpt @@ -11,4 +11,4 @@ class Foo { ?> --EXPECTF-- -Fatal error: Write-only virtual property Foo::$bar must not specify asymmetric visibility in %s on line %d +Fatal error: set-only virtual property Foo::$bar must not specify asymmetric visibility in %s on line %d 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/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/bitwise_not_precision_exception.phpt b/Zend/tests/bitwise_not_precision_exception.phpt index fa821100464e7..e28bf8f4e17b6 100644 --- a/Zend/tests/bitwise_not_precision_exception.phpt +++ b/Zend/tests/bitwise_not_precision_exception.phpt @@ -12,4 +12,4 @@ try { } ?> --EXPECT-- -Implicit conversion from float INF to int loses precision +The float INF is not representable as an int, cast occurred 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/bug41421.phpt b/Zend/tests/bug41421.phpt index 762c32b96df80..fdf86da443867 100644 --- a/Zend/tests/bug41421.phpt +++ b/Zend/tests/bug41421.phpt @@ -9,22 +9,19 @@ class wrapper { return true; } function stream_eof() { - throw new exception(); + throw new Exception('cannot eof'); } } stream_wrapper_register("wrap", "wrapper"); $fp = fopen("wrap://...", "r"); -feof($fp); -echo "Done\n"; -?> ---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/bug46701.phpt b/Zend/tests/bug46701.phpt index e7cc823d85c5e..620d5209443e5 100644 --- a/Zend/tests/bug46701.phpt +++ b/Zend/tests/bug46701.phpt @@ -27,11 +27,11 @@ new foo; ?> --EXPECTF-- -Deprecated: Implicit conversion from float 3428599296 to int loses precision in %s on line %d +Warning: The float 3428599296 is not representable as an int, cast occurred in %s on line %d -Deprecated: Implicit conversion from float 3459455488 to int loses precision in %s on line %d +Warning: The float 3459455488 is not representable as an int, cast occurred in %s on line %d -Deprecated: Implicit conversion from float 3459616768 to int loses precision in %s on line %d +Warning: The float 3459616768 is not representable as an int, cast occurred in %s on line %d array(3) { [-866368000]=> int(1) @@ -41,10 +41,10 @@ array(3) { int(3) } -Deprecated: Implicit conversion from float 3459455488 to int loses precision in %s on line %d +Warning: The float 3459455488 is not representable as an int, cast occurred in %s on line %d int(2) -Deprecated: Implicit conversion from float 3459616768 to int loses precision in %s on line %d +Warning: The float 3459616768 is not representable as an int, cast occurred in %s on line %d array(1) { [-835350528]=> int(3) 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/bug78340.phpt b/Zend/tests/bug78340.phpt index 4012e83af6acd..22ea0c19353e9 100644 --- a/Zend/tests/bug78340.phpt +++ b/Zend/tests/bug78340.phpt @@ -32,7 +32,7 @@ class lib { function stream_stat() { return [ - 'dev' => 3632233996, + 'dev' => PHP_INT_MAX, 'size' => strlen($this->bytes), 'ino' => $this->ino ]; 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-- '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_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/fcc-cache.phpt b/Zend/tests/closures/fcc-cache.phpt new file mode 100644 index 0000000000000..3b47a2410d143 --- /dev/null +++ b/Zend/tests/closures/fcc-cache.phpt @@ -0,0 +1,8 @@ +--TEST-- +FCCs are cached and shared +--FILE-- + +--EXPECT-- +bool(true) diff --git a/Zend/tests/closures/gh19653_1.phpt b/Zend/tests/closures/gh19653_1.phpt new file mode 100644 index 0000000000000..93b119eb57826 --- /dev/null +++ b/Zend/tests/closures/gh19653_1.phpt @@ -0,0 +1,27 @@ +--TEST-- +GH-19653 (Closure named argument unpacking between temporary closures can cause a crash) +--CREDITS-- +ivan-u7n +--FILE-- + +--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/closures/gh19653_3.phpt b/Zend/tests/closures/gh19653_3.phpt new file mode 100644 index 0000000000000..7a9ac589182c3 --- /dev/null +++ b/Zend/tests/closures/gh19653_3.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-19653 (Closure named argument unpacking between temporary closures can cause a crash) - temporary method variation +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Error: Unknown named parameter $tmpMethodParamName 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/concat_003.phpt b/Zend/tests/concat/concat_003.phpt index dc22bae1a7206..52594dffcfd29 100644 --- a/Zend/tests/concat/concat_003.phpt +++ b/Zend/tests/concat/concat_003.phpt @@ -11,7 +11,7 @@ if (getenv('SKIP_PERF_SENSITIVE')) die("skip performance sensitive test"); $time = microtime(TRUE); /* This might vary on Linux/Windows, so the worst case and also count in slow machines. */ -$t_max = 1.0; +$t_max = 2.0; $datas = array_fill(0, 220000, [ '000.000.000.000', 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/constexpr/constant_expressions_dynamic.phpt b/Zend/tests/constexpr/constant_expressions_dynamic.phpt index c5c67248df900..c2f8ded98d9b2 100644 --- a/Zend/tests/constexpr/constant_expressions_dynamic.phpt +++ b/Zend/tests/constexpr/constant_expressions_dynamic.phpt @@ -48,6 +48,8 @@ var_dump( Warning: A non-numeric value encountered in %s on line %d Deprecated: Implicit conversion from float 3.14 to int loses precision in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d int(3) string(4) "1foo" bool(false) diff --git a/Zend/tests/ctor_promotion/ctor_promotion_final.phpt b/Zend/tests/ctor_promotion/ctor_promotion_final.phpt new file mode 100644 index 0000000000000..abfb5b7088082 --- /dev/null +++ b/Zend/tests/ctor_promotion/ctor_promotion_final.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-20377: Constructor promotion with a final property without visibility set +--FILE-- + +--EXPECTF-- +object(Demo)#%d (2) { + ["foo"]=> + string(5) "first" + ["bar"]=> + string(6) "second" +} 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/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/dval_to_lval_32.phpt b/Zend/tests/dval_to_lval_32.phpt deleted file mode 100644 index 89acf9076ad75..0000000000000 --- a/Zend/tests/dval_to_lval_32.phpt +++ /dev/null @@ -1,32 +0,0 @@ ---TEST-- -zend_dval_to_lval preserves low bits (32 bit long) ---SKIPIF-- - ---FILE-- - ---EXPECT-- -int(-2056257536) -int(-2055733248) -int(-2055208960) -int(-2054684672) -int(-2054160384) -int(2147483647) diff --git a/Zend/tests/dval_to_lval_64.phpt b/Zend/tests/dval_to_lval_64.phpt deleted file mode 100644 index b54f861bf55cf..0000000000000 --- a/Zend/tests/dval_to_lval_64.phpt +++ /dev/null @@ -1,29 +0,0 @@ ---TEST-- -zend_dval_to_lval preserves low bits (64 bit long) ---SKIPIF-- - ---FILE-- - ---EXPECT-- -int(2943463994971652096) -int(2943463994972176384) -int(2943463994972700672) -int(2943463994973224960) -int(2943463994973749248) 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/dynamic_call/variable_variables_curly_syntax.phpt b/Zend/tests/dynamic_call/variable_variables_curly_syntax.phpt new file mode 100644 index 0000000000000..217ad5a3a304e --- /dev/null +++ b/Zend/tests/dynamic_call/variable_variables_curly_syntax.phpt @@ -0,0 +1,24 @@ +--TEST-- +Testing dynamic calls using variable variables with curly syntax +--FILE-- + +--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/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-- ---EXPECT-- +--EXPECTF-- string(4) "exit" string(3) "die" -object(Closure)#1 (2) { +object(Closure)#%d (2) { ["function"]=> string(4) "exit" ["parameter"]=> @@ -31,7 +31,7 @@ object(Closure)#1 (2) { string(10) "" } } -object(Closure)#2 (2) { +object(Closure)#%d (2) { ["function"]=> string(4) "exit" ["parameter"]=> diff --git a/Zend/tests/falsetoarray_003.phpt b/Zend/tests/falsetoarray_003.phpt index 11b32771e1fc1..117e443ef9584 100644 --- a/Zend/tests/falsetoarray_003.phpt +++ b/Zend/tests/falsetoarray_003.phpt @@ -11,6 +11,6 @@ $a=[]; ?> DONE --EXPECTF-- -Err: Implicit conversion from float %f to int loses precision +Err: The float %f is not representable as an int, cast occurred Err: Undefined array key %i DONE diff --git a/Zend/tests/fibers/gh20483.phpt b/Zend/tests/fibers/gh20483.phpt new file mode 100644 index 0000000000000..e06cf87258ea1 --- /dev/null +++ b/Zend/tests/fibers/gh20483.phpt @@ -0,0 +1,16 @@ +--TEST-- +GH-20483 (ASAN stack overflow with small fiber.stack_size INI value) +--INI-- +fiber.stack_size=1024 +--FILE-- +start(); +} catch (Exception $e) { + echo $e->getMessage() . "\n"; +} +?> +--EXPECTF-- +Fiber stack size is too small, it needs to be at least %d bytes diff --git a/Zend/tests/first_class_callable/constexpr/autoload.phpt b/Zend/tests/first_class_callable/constexpr/autoload.phpt index 2dd2561f9a369..c962b77f12b61 100644 --- a/Zend/tests/first_class_callable/constexpr/autoload.phpt +++ b/Zend/tests/first_class_callable/constexpr/autoload.phpt @@ -26,6 +26,6 @@ var_dump(Closure); Autoloading AutoloadedClass object(Closure)#%d (1) { ["function"]=> - 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/namespace_004.phpt b/Zend/tests/first_class_callable/constexpr/namespace_004.phpt index 0fc23422199d5..6fe99593bf95d 100644 --- a/Zend/tests/first_class_callable/constexpr/namespace_004.phpt +++ b/Zend/tests/first_class_callable/constexpr/namespace_004.phpt @@ -26,7 +26,7 @@ foo(); ?> --EXPECTF-- -object(Closure)#1 (2) { +object(Closure)#%d (2) { ["function"]=> string(6) "strrev" ["parameter"]=> @@ -36,7 +36,7 @@ object(Closure)#1 (2) { } } string(3) "cba" -object(Closure)#2 (2) { +object(Closure)#%d (2) { ["function"]=> string(6) "strrev" ["parameter"]=> @@ -46,7 +46,7 @@ object(Closure)#2 (2) { } } string(3) "cba" -object(Closure)#2 (2) { +object(Closure)#%d (2) { ["function"]=> string(6) "strrev" ["parameter"]=> @@ -56,7 +56,7 @@ object(Closure)#2 (2) { } } string(3) "cba" -object(Closure)#1 (2) { +object(Closure)#%d (2) { ["function"]=> string(6) "strrev" ["parameter"]=> 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/first_class_callable/first_class_callable_optimization.phpt b/Zend/tests/first_class_callable/first_class_callable_optimization.phpt index 707b6a7299a4a..169f6dfd62cc2 100644 --- a/Zend/tests/first_class_callable/first_class_callable_optimization.phpt +++ b/Zend/tests/first_class_callable/first_class_callable_optimization.phpt @@ -10,12 +10,12 @@ var_dump(test1(...)); var_dump(test2(...)); ?> ---EXPECT-- -object(Closure)#1 (1) { +--EXPECTF-- +object(Closure)#%d (1) { ["function"]=> string(5) "test1" } -object(Closure)#1 (1) { +object(Closure)#%d (1) { ["function"]=> string(5) "test2" } diff --git a/Zend/tests/float_to_int/explicit_casts_should_not_warn.phpt b/Zend/tests/float_to_int/explicit_casts_should_not_warn.phpt deleted file mode 100644 index 71c68e57574bf..0000000000000 --- a/Zend/tests/float_to_int/explicit_casts_should_not_warn.phpt +++ /dev/null @@ -1,38 +0,0 @@ ---TEST-- -Explicit (int) cast must not warn ---SKIPIF-- - ---FILE-- - ---EXPECT-- -int(3) -int(3) -int(0) -int(0) -int(0) -int(3) -int(3) -int(9223372036854775807) -int(9223372036854775807) -int(0) diff --git a/Zend/tests/float_to_int/explicit_casts_should_not_warn_32bit.phpt b/Zend/tests/float_to_int/explicit_casts_should_not_warn_32bit.phpt deleted file mode 100644 index fee011df06ea8..0000000000000 --- a/Zend/tests/float_to_int/explicit_casts_should_not_warn_32bit.phpt +++ /dev/null @@ -1,38 +0,0 @@ ---TEST-- -Explicit (int) cast must not warn 32bit variation ---SKIPIF-- - ---FILE-- - ---EXPECT-- -int(3) -int(3) -int(0) -int(0) -int(0) -int(3) -int(3) -int(2147483647) -int(2147483647) -int(0) diff --git a/Zend/tests/float_to_int/warning_float_does_not_fit_zend_long_arrays.phpt b/Zend/tests/float_to_int/warning_float_does_not_fit_zend_long_arrays.phpt deleted file mode 100644 index bb27d1bb49ddb..0000000000000 --- a/Zend/tests/float_to_int/warning_float_does_not_fit_zend_long_arrays.phpt +++ /dev/null @@ -1,55 +0,0 @@ ---TEST-- -Implicit float to int conversions when float too large should warn, array variant ---FILE-- - 'Large float', (string) 10e120 => 'String large float']; -$arrayDynamic = [$float => 'Large float', $string_float => 'String large float']; - -var_dump($arrayConstant); -var_dump($arrayDynamic); - -$array = ['0', '1', '2']; -var_dump($array[10e120]); -var_dump($array[(string) 10e120]); -var_dump($array[$float]); -var_dump($array[$string_float]); - -?> ---EXPECTF-- -int(0) -bool(true) - -Deprecated: Implicit conversion from float 1.0E+121 to int loses precision in %s on line %d - -Deprecated: Implicit conversion from float 1.0E+121 to int loses precision in %s on line %d -array(2) { - [0]=> - string(11) "Large float" - ["1.0E+121"]=> - string(18) "String large float" -} -array(2) { - [0]=> - string(11) "Large float" - ["1.0E+121"]=> - string(18) "String large float" -} - -Deprecated: Implicit conversion from float 1.0E+121 to int loses precision in %s on line %d -string(1) "0" - -Warning: Undefined array key "1.0E+121" in %s on line %d -NULL - -Deprecated: Implicit conversion from float 1.0E+121 to int loses precision in %s on line %d -string(1) "0" - -Warning: Undefined array key "1.0E+121" in %s on line %d -NULL 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/func_get_arg_basic.phpt b/Zend/tests/func_get_arg_basic.phpt new file mode 100644 index 0000000000000..ec06a5c20f4df --- /dev/null +++ b/Zend/tests/func_get_arg_basic.phpt @@ -0,0 +1,121 @@ +--TEST-- +func_get_arg() tests +--FILE-- +getMessage() . \PHP_EOL; + } + + try { + var_dump(func_get_arg(0)); + } catch (\Error $e) { + echo $e->getMessage() . \PHP_EOL; + } + try { + var_dump(func_get_arg(1)); + } catch (\Error $e) { + echo $e->getMessage() . \PHP_EOL; + } +} + +function test2($a) { + try { + var_dump(func_get_arg(0)); + } catch (\Error $e) { + echo $e->getMessage() . \PHP_EOL; + } + try { + var_dump(func_get_arg(1)); + } catch (\Error $e) { + echo $e->getMessage() . \PHP_EOL; + } +} + +function test3($a, $b) { + try { + var_dump(func_get_arg(0)); + } catch (\Error $e) { + echo $e->getMessage() . \PHP_EOL; + } + try { + var_dump(func_get_arg(1)); + } catch (\Error $e) { + echo $e->getMessage() . \PHP_EOL; + } + try { + var_dump(func_get_arg(2)); + } catch (\Error $e) { + echo $e->getMessage() . \PHP_EOL; + } +} + +test1(); +test1(10); +test2(1); +try { + test2(); +} catch (Throwable $e) { + echo "Exception: " . $e->getMessage() . "\n"; +} +test3(1,2); + +call_user_func("test1"); +try { + call_user_func("test3", 1); +} catch (Throwable $e) { + echo "Exception: " . $e->getMessage() . "\n"; +} +call_user_func("test3", 1, 2); + +class test { + static function test1($a) { + try { + var_dump(func_get_arg(0)); + } catch (\Error $e) { + echo $e->getMessage() . \PHP_EOL; + } + try { + var_dump(func_get_arg(1)); + } catch (\Error $e) { + echo $e->getMessage() . \PHP_EOL; + } + } +} + +test::test1(1); +try { + var_dump(func_get_arg(1)); +} catch (\Error $e) { + echo $e->getMessage() . \PHP_EOL; +} + +echo "Done\n"; +?> +--EXPECTF-- +func_get_arg(): Argument #1 ($position) must be greater than or equal to 0 +func_get_arg(): Argument #1 ($position) must be less than the number of the arguments passed to the currently executed function +func_get_arg(): Argument #1 ($position) must be less than the number of the arguments passed to the currently executed function +func_get_arg(): Argument #1 ($position) must be greater than or equal to 0 +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 %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 +func_get_arg(): Argument #1 ($position) must be greater than or equal to 0 +func_get_arg(): Argument #1 ($position) must be less than the number of the arguments passed to the currently executed function +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 test3(), 1 passed in %s on line %d and exactly 2 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 +int(1) +func_get_arg(): Argument #1 ($position) must be less than the number of the arguments passed to the currently executed function +func_get_arg() cannot be called from the global scope +Done 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/func_get_args_basic.phpt b/Zend/tests/func_get_args_basic.phpt new file mode 100644 index 0000000000000..54ddf1b40c921 --- /dev/null +++ b/Zend/tests/func_get_args_basic.phpt @@ -0,0 +1,82 @@ +--TEST-- +func_get_args() tests +--FILE-- +getMessage() . "\n"; +} +test3(1,2); + +call_user_func("test1"); +try { + call_user_func("test3", 1); +} catch (Throwable $e) { + echo "Exception: " . $e->getMessage() . "\n"; +} +call_user_func("test3", 1, 2); + +class test { + static function test1($a) { + var_dump(func_get_args()); + } +} + +test::test1(1); + +try { + var_dump(func_get_args()); +} catch (\Error $e) { + echo $e->getMessage() . \PHP_EOL; +} + +?> +--EXPECTF-- +array(0) { +} +array(1) { + [0]=> + int(10) +} +array(1) { + [0]=> + int(1) +} +Exception: Too few arguments to function test2(), 0 passed in %s on line %d and exactly 1 expected +array(2) { + [0]=> + int(1) + [1]=> + int(2) +} +array(0) { +} +Exception: Too few arguments to function test3(), 1 passed in %s on line %d and exactly 2 expected +array(2) { + [0]=> + int(1) + [1]=> + int(2) +} +array(1) { + [0]=> + int(1) +} +func_get_args() cannot be called from the global scope 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/function_arguments/gh20435.phpt b/Zend/tests/function_arguments/gh20435.phpt new file mode 100644 index 0000000000000..e360b873d3ced --- /dev/null +++ b/Zend/tests/function_arguments/gh20435.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-20435 (SensitiveParameter doesn't work for named argument passing to variadic parameter) +--FILE-- + +--EXPECTF-- +#0 %s(%d): test(2, b: Object(SensitiveParameterValue), c: Object(SensitiveParameterValue)) diff --git a/Zend/tests/function_arguments/gh20435_2.phpt b/Zend/tests/function_arguments/gh20435_2.phpt new file mode 100644 index 0000000000000..a58c4d6be1ca5 --- /dev/null +++ b/Zend/tests/function_arguments/gh20435_2.phpt @@ -0,0 +1,38 @@ +--TEST-- +GH-20435: ZEND_CALL_HAS_EXTRA_NAMED_PARAMS & magic methods in debug_backtrace_get_args() +--FILE-- +__toString(), "\n\n"; + } + public function __call($name, $args) { + echo (new Exception())->__toString(), "\n\n"; + } + public function __invoke(...$args) { + echo (new Exception())->__toString(), "\n"; + } +} + +$c = new C(); +$c->foo(bar: 'bar'); +C::foo(bar: 'bar'); +$c(bar: 'bar'); + +?> +--EXPECTF-- +Exception in %s:%d +Stack trace: +#0 %s(%d): C->__call('foo', Array) +#1 {main} + +Exception in %s:%d +Stack trace: +#0 %s(%d): C::__callStatic('foo', Array) +#1 {main} + +Exception in %s:%d +Stack trace: +#0 %s(%d): C->__invoke(bar: 'bar') +#1 {main} 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/functions/zend_call_function_deprecated_frame.phpt b/Zend/tests/functions/zend_call_function_deprecated_frame.phpt new file mode 100644 index 0000000000000..ce2943a876e2b --- /dev/null +++ b/Zend/tests/functions/zend_call_function_deprecated_frame.phpt @@ -0,0 +1,25 @@ +--TEST-- +Deprecated function notice promoted to exception within zend_call_function() +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Exception: Function foo() is deprecated in %s:%d +Stack trace: +#0 [internal function]: {closure:%s:%d}(16384, 'Function foo() ...', '%s', %d) +#1 %s(%d): array_map(Object(Closure), Array) +#2 {main} + thrown in %s on line %d 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/get_included_files_basic.phpt b/Zend/tests/get_included_files_basic.phpt new file mode 100644 index 0000000000000..be595a592621a --- /dev/null +++ b/Zend/tests/get_included_files_basic.phpt @@ -0,0 +1,42 @@ +--TEST-- +get_included_files() tests +--FILE-- + +--EXPECTF-- +array(1) { + [0]=> + string(%d) "%s" +} +array(2) { + [0]=> + string(%d) "%s" + [1]=> + string(%d) "%s" +} +array(2) { + [0]=> + string(%d) "%s" + [1]=> + string(%d) "%s" +} +array(2) { + [0]=> + string(%d) "%s" + [1]=> + string(%d) "%s" +} +Done 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/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/gh19719.phpt b/Zend/tests/gh19719.phpt new file mode 100644 index 0000000000000..715e847846fe1 --- /dev/null +++ b/Zend/tests/gh19719.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-19719: Allow empty expressions before declare(strict_types) +--FILE-- + +getMessage(), "\n"; +} + +?> +--EXPECTF-- +takesInt(): Argument #1 ($x) must be of type int, string given, called in %s on line %d diff --git a/Zend/tests/gh19839.phpt b/Zend/tests/gh19839.phpt new file mode 100644 index 0000000000000..cc589ce0605f1 --- /dev/null +++ b/Zend/tests/gh19839.phpt @@ -0,0 +1,18 @@ +--TEST-- +GH-19839: Incorrect HASH_FLAG_HAS_EMPTY_IND flag on userland array +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/gh19844.phpt b/Zend/tests/gh19844.phpt new file mode 100644 index 0000000000000..2978640735357 --- /dev/null +++ b/Zend/tests/gh19844.phpt @@ -0,0 +1,46 @@ +--TEST-- +GH-19844: Bail from stream_close() in zend_shutdown_executor_values() +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Fatal error: Bail in %s on line %d + +Fatal error: Bail in %s on line %d + +Fatal error: Bail in %s on line %d diff --git a/Zend/tests/gh20113.phpt b/Zend/tests/gh20113.phpt new file mode 100644 index 0000000000000..64e029a6cec17 --- /dev/null +++ b/Zend/tests/gh20113.phpt @@ -0,0 +1,8 @@ +--TEST-- +GH-20113: new Foo(...) error in constant expressions +--FILE-- + +--EXPECTF-- +Fatal error: Cannot create Closure for new expression in %s on line %d diff --git a/Zend/tests/gh20177.phpt b/Zend/tests/gh20177.phpt new file mode 100644 index 0000000000000..fd69460067f97 --- /dev/null +++ b/Zend/tests/gh20177.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-20177: Access overridden private property in get_object_vars() +--FILE-- + +--EXPECT-- +array(1) { + ["prop"]=> + string(8) "A::$prop" +} diff --git a/Zend/tests/gh20183_001.phpt b/Zend/tests/gh20183_001.phpt new file mode 100644 index 0000000000000..9468bcaea5673 --- /dev/null +++ b/Zend/tests/gh20183_001.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-20183: Stale EG(opline_before_exception) pointer through eval +--CREDITS-- +Viet Hoang Luu (@vi3tL0u1s) +--FILE-- + +--EXPECTF-- +#0 %s(10): A->__destruct() + +Fatal error: Uncaught Error: Class "B" not found in %s:10 +Stack trace: +#0 {main} + thrown in %s on line 10 diff --git a/Zend/tests/gh20183_002.phpt b/Zend/tests/gh20183_002.phpt new file mode 100644 index 0000000000000..ec4d62d0960dc --- /dev/null +++ b/Zend/tests/gh20183_002.phpt @@ -0,0 +1,34 @@ +--TEST-- +GH-20183: Stale EG(opline_before_exception) pointer through eval +--CREDITS-- +Arnaud Le Blanc +--FILE-- +gen = gen(); + $this->gen->rewind(); + } +} + +B::$a = new A(); + +?> +--EXPECTF-- +#0 %s(20): gen() + +Fatal error: Uncaught Error: Class "B" not found in %s:20 +Stack trace: +#0 {main} + thrown in %s on line 20 diff --git a/Zend/tests/gh20714.phpt b/Zend/tests/gh20714.phpt new file mode 100644 index 0000000000000..10ffde555f896 --- /dev/null +++ b/Zend/tests/gh20714.phpt @@ -0,0 +1,29 @@ +--TEST-- +GH-20714: Uncatchable exception thrown in generator +--CREDITS-- +Grégoire Paris (greg0ire) +--FILE-- + +--EXPECT-- +Caught 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/argument_restriction_001.phpt b/Zend/tests/inheritance/argument_restriction_001.phpt index 2c54636a58178..6eb3ff8d27062 100644 --- a/Zend/tests/inheritance/argument_restriction_001.phpt +++ b/Zend/tests/inheritance/argument_restriction_001.phpt @@ -13,4 +13,4 @@ class Sub extends Base { } ?> --EXPECTF-- -Fatal error: Declaration of & Sub::test() must be compatible with & Base::test($foo, array $bar, $option = null, $extra = 'llllllllll...') in %s on line %d +Fatal error: Declaration of &Sub::test() must be compatible with &Base::test($foo, array $bar, $option = null, $extra = 'llllllllll...') in %s on line %d 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/int_overflow_32bit.phpt b/Zend/tests/int_overflow_32bit.phpt index 15dce6eea7dcf..e337932bcd554 100644 --- a/Zend/tests/int_overflow_32bit.phpt +++ b/Zend/tests/int_overflow_32bit.phpt @@ -20,10 +20,19 @@ foreach ($doubles as $d) { echo "Done\n"; ?> ---EXPECT-- +--EXPECTF-- +Warning: The float 2147483648 is not representable as an int, cast occurred in %s on line %d int(-2147483648) + +Warning: The float 2147483649 is not representable as an int, cast occurred in %s on line %d int(-2147483647) + +Warning: The float 2147483658 is not representable as an int, cast occurred in %s on line %d int(-2147483638) + +Warning: The float 2147483748 is not representable as an int, cast occurred in %s on line %d int(-2147483548) + +Warning: The float 2147484648 is not representable as an int, cast occurred in %s on line %d int(-2147482648) Done diff --git a/Zend/tests/int_overflow_64bit.phpt b/Zend/tests/int_overflow_64bit.phpt index 7c541250205c8..cc14e14949ca8 100644 --- a/Zend/tests/int_overflow_64bit.phpt +++ b/Zend/tests/int_overflow_64bit.phpt @@ -22,10 +22,16 @@ foreach ($doubles as $d) { echo "Done\n"; ?> ---EXPECT-- +--EXPECTF-- int(9223372036854775807) + +Warning: The float %f is not representable as an int, cast occurred in %s on line %d int(-9223372036854775808) + +Warning: The float %f is not representable as an int, cast occurred in %s on line %d int(-9223372036854775808) + +Warning: The float %f is not representable as an int, cast occurred in %s on line %d int(0) int(-9223372036854775808) int(-9223372036854775808) diff --git a/Zend/tests/int_special_values.phpt b/Zend/tests/int_special_values.phpt deleted file mode 100644 index eedb9ab2c02ac..0000000000000 --- a/Zend/tests/int_special_values.phpt +++ /dev/null @@ -1,37 +0,0 @@ ---TEST-- -Conversion of special float values to int ---FILE-- - ---EXPECT-- -float(0) -int(0) - -float(INF) -int(0) - -float(-INF) -int(0) - -float(0) -int(0) - -float(-0) -int(0) - -float(NAN) -int(0) diff --git a/Zend/tests/int_underflow_32bit.phpt b/Zend/tests/int_underflow_32bit.phpt index 71464a758aeea..88c0e79834b4b 100644 --- a/Zend/tests/int_underflow_32bit.phpt +++ b/Zend/tests/int_underflow_32bit.phpt @@ -20,10 +20,18 @@ foreach ($doubles as $d) { echo "Done\n"; ?> ---EXPECT-- +--EXPECTF-- int(-2147483648) + +Warning: The float -2147483649 is not representable as an int, cast occurred in %s on line %d int(2147483647) + +Warning: The float -2147483658 is not representable as an int, cast occurred in %s on line %d int(2147483638) + +Warning: The float -2147483748 is not representable as an int, cast occurred in %s on line %d int(2147483548) + +Warning: The float -2147484648 is not representable as an int, cast occurred in %s on line %d int(2147482648) Done 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/gh20085.phpt b/Zend/tests/lazy_objects/gh20085.phpt new file mode 100644 index 0000000000000..5624f71ea8b47 --- /dev/null +++ b/Zend/tests/lazy_objects/gh20085.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-20085 (Assertion failure when combining lazy object get_properties exception with foreach loop) +--FILE-- +a = 1; + } +} +$obj = new C; +$reflector = new ReflectionClass(C::class); +foreach ($obj as &$value) { + $obj = $reflector->newLazyGhost(function ($obj) { + throw new Error; + }); +} +echo !obj; +?> +--EXPECTF-- +Fatal error: Uncaught Error in %s:%d +Stack trace: +#0 %s(%d): {closure:%s:%d}(Object(C)) +#1 {main} + thrown in %s on line %d 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/magic_methods/trampoline_closure_named_arguments.phpt b/Zend/tests/magic_methods/trampoline_closure_named_arguments.phpt index e4ccaf16e63a6..3be14f6145ace 100644 --- a/Zend/tests/magic_methods/trampoline_closure_named_arguments.phpt +++ b/Zend/tests/magic_methods/trampoline_closure_named_arguments.phpt @@ -42,7 +42,7 @@ var_dump($type); var_dump($type->getName()); ?> ---EXPECT-- +--EXPECTF-- -- Non-static cases -- string(4) "test" array(3) { @@ -69,7 +69,7 @@ array(4) { ["a"]=> int(123) ["b"]=> - object(Test)#1 (0) { + object(Test)#%d (0) { } } string(4) "test" @@ -77,7 +77,7 @@ array(2) { ["a"]=> int(123) ["b"]=> - object(Test)#1 (0) { + object(Test)#%d (0) { } } string(4) "test" @@ -114,7 +114,7 @@ array(4) { ["a"]=> int(123) ["b"]=> - object(Test)#1 (0) { + object(Test)#%d (0) { } } string(10) "testStatic" @@ -122,7 +122,7 @@ array(2) { ["a"]=> int(123) ["b"]=> - object(Test)#1 (0) { + object(Test)#%d (0) { } } string(10) "testStatic" @@ -136,12 +136,12 @@ array(1) { -- Reflection tests -- array(1) { [0]=> - object(ReflectionParameter)#4 (1) { + object(ReflectionParameter)#%d (1) { ["name"]=> string(9) "arguments" } } bool(true) -object(ReflectionNamedType)#5 (0) { +object(ReflectionNamedType)#%d (0) { } string(5) "mixed" 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/objects/objects_005.phpt b/Zend/tests/objects/objects_005.phpt index 9b9a41465f95b..7749a39d986fb 100644 --- a/Zend/tests/objects/objects_005.phpt +++ b/Zend/tests/objects/objects_005.phpt @@ -19,4 +19,4 @@ class test3 extends test { ?> --EXPECTF-- -Fatal error: Declaration of test3::foo() must be compatible with & test::foo() in %s on line %d +Fatal error: Declaration of test3::foo() must be compatible with &test::foo() in %s on line %d 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-- --EXPECT-- -Err: Implicit conversion from float 1.0E+20 to int loses precision +Err: The float 1.0E+20 is not representable as an int, cast occurred array(0) { } diff --git a/Zend/tests/offsets/false_container_offset_behaviour.phpt b/Zend/tests/offsets/false_container_offset_behaviour.phpt index 8a6cd93b72609..0647400baee0a 100644 --- a/Zend/tests/offsets/false_container_offset_behaviour.phpt +++ b/Zend/tests/offsets/false_container_offset_behaviour.phpt @@ -135,6 +135,176 @@ OUTPUT; $EXPECTED_OUTPUT_FLOAT_OFFSETS_REGEX = '/^' . expectf_to_regex(EXPECTF_OUTPUT_FLOAT_OFFSETS) . '$/s'; +const EXPECTF_OUTPUT_FLOAT_OOB_OFFSETS = << 1]; + +echo $a[null]; + +?> +--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 +1 diff --git a/Zend/tests/offsets/null_container_offset_behaviour.phpt b/Zend/tests/offsets/null_container_offset_behaviour.phpt index 0fe02556d3e09..2ac51937a0fe7 100644 --- a/Zend/tests/offsets/null_container_offset_behaviour.phpt +++ b/Zend/tests/offsets/null_container_offset_behaviour.phpt @@ -131,6 +131,172 @@ OUTPUT; $EXPECTED_OUTPUT_FLOAT_OFFSETS_REGEX = '/^' . expectf_to_regex(EXPECTF_OUTPUT_FLOAT_OFFSETS) . '$/s'; +const EXPECTF_OUTPUT_FLOAT_OOB_OFFSETS = << 'bar', null => new stdClass]; +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +?> +--EXPECT-- +Exception: Using null as an array offset is deprecated, use an empty string instead diff --git a/Zend/tests/offsets/null_offset_no_uaf.phpt b/Zend/tests/offsets/null_offset_no_uaf.phpt new file mode 100644 index 0000000000000..38a1b98683455 --- /dev/null +++ b/Zend/tests/offsets/null_offset_no_uaf.phpt @@ -0,0 +1,17 @@ +--TEST-- +No UAF on null offset +--FILE-- + +--EXPECTF-- +Using null as an array offset is deprecated, use an empty string instead +Success diff --git a/Zend/tests/offsets/null_offset_unset_via_error_handler.phpt b/Zend/tests/offsets/null_offset_unset_via_error_handler.phpt new file mode 100644 index 0000000000000..cfaa2b3b20d98 --- /dev/null +++ b/Zend/tests/offsets/null_offset_unset_via_error_handler.phpt @@ -0,0 +1,19 @@ +--TEST-- +No UAF on null offset deprecation with unset value +--FILE-- + $a]; + +echo "\nSuccess\n"; +?> +--EXPECTF-- +string(72) "Using null as an array offset is deprecated, use an empty string instead" + +Success diff --git a/Zend/tests/offsets/string_container_offset_behaviour.phpt b/Zend/tests/offsets/string_container_offset_behaviour.phpt index dc4c95e5d9ec5..9c752ebddd819 100644 --- a/Zend/tests/offsets/string_container_offset_behaviour.phpt +++ b/Zend/tests/offsets/string_container_offset_behaviour.phpt @@ -280,7 +280,7 @@ OUTPUT; $EXPECTED_OUTPUT_STRING_CAST_OFFSETS_OUT_OF_RANGE_REGEX = '/^' . expectf_to_regex(EXPECTED_OUTPUT_STRING_CAST_OFFSETS_OUT_OF_RANGE) . '$/s'; -const EXPECTF_OUTPUT_FLOAT_OFFSETS_OUT_OF_RANGE = << '\d+', '%x' => '[0-9a-fA-F]+', '%f' => '[+-]?(?:\d+|(?=\.\d))(?:\.\d+)?(?:[Ee][+-]?\d+)?', - '%F' => '([+-]?(?:\d+|(?=\.\d))(?:\.\d+)?(?:[Ee][+-]?\d+)?)|(NAN)|(INF)', + '%F' => '([+-]?(?:\d+|(?=\.\d))(?:\.\d+)?(?:[Ee][+-]?\d+)?)|(NAN)|(INF)|([+-]?\d+)', '%c' => '.', '%0' => '\x00', ]); 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/optimizer/nan_warning_switch.phpt b/Zend/tests/optimizer/nan_warning_switch.phpt new file mode 100644 index 0000000000000..1b7b404201f44 --- /dev/null +++ b/Zend/tests/optimizer/nan_warning_switch.phpt @@ -0,0 +1,17 @@ +--TEST-- +Checking NAN in a switch statement with true/false +--FILE-- + +--EXPECT-- +true diff --git a/Zend/tests/oss-fuzz-465488618.phpt b/Zend/tests/oss-fuzz-465488618.phpt new file mode 100644 index 0000000000000..517c481b33e0a --- /dev/null +++ b/Zend/tests/oss-fuzz-465488618.phpt @@ -0,0 +1,16 @@ +--TEST-- +OSS-Fuzz #465488618: Dump function signature with dynamic class const lookup default argument +--FILE-- + +--EXPECTF-- +Fatal error: Declaration of B::test(string $x = ) must be compatible with A::test(int $x) in %s on line %d 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/oss_fuzz_447521098.phpt b/Zend/tests/oss_fuzz_447521098.phpt new file mode 100644 index 0000000000000..09967ce0ae3ac --- /dev/null +++ b/Zend/tests/oss_fuzz_447521098.phpt @@ -0,0 +1,13 @@ +--TEST-- +OSS-Fuzz #447521098: Fatal error during sccp shift eval +--FILE-- +> $y; +} +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/oss_fuzz_454273637.phpt b/Zend/tests/oss_fuzz_454273637.phpt new file mode 100644 index 0000000000000..fbcdb57ed2a16 --- /dev/null +++ b/Zend/tests/oss_fuzz_454273637.phpt @@ -0,0 +1,8 @@ +--TEST-- +OSS-Fuzz #454273637 (UAF with printf optimization and const output) +--FILE-- + +--EXPECT-- +% diff --git a/Zend/tests/oss_fuzz_456317305.phpt b/Zend/tests/oss_fuzz_456317305.phpt new file mode 100644 index 0000000000000..37e7c59e46515 --- /dev/null +++ b/Zend/tests/oss_fuzz_456317305.phpt @@ -0,0 +1,25 @@ +--TEST-- +OSS-Fuzz #456317305: EG(current_execute_data) NULL pointer violation +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Exception in %s:%d +Stack trace: +#0 [internal function]: C->__destruct() +#1 {main} + thrown in %s on line %d 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_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/bug001.phpt b/Zend/tests/property_hooks/bug001.phpt index 5328506d476cb..62291019b3338 100644 --- a/Zend/tests/property_hooks/bug001.phpt +++ b/Zend/tests/property_hooks/bug001.phpt @@ -27,4 +27,4 @@ try { ?> --EXPECT-- bool(true) -Property C::$x is read-only +Cannot write to get-only virtual property C::$x diff --git a/Zend/tests/property_hooks/bug008.phpt b/Zend/tests/property_hooks/bug008.phpt index 9c321cfe16e14..38fe709a38a3f 100644 --- a/Zend/tests/property_hooks/bug008.phpt +++ b/Zend/tests/property_hooks/bug008.phpt @@ -18,7 +18,7 @@ $foo->bar = 'bar'; ?> --EXPECTF-- -Fatal error: Uncaught Error: Property Foo::$bar is read-only in %s:%d +Fatal error: Uncaught Error: Cannot write to get-only virtual property Foo::$bar in %s:%d Stack trace: #0 {main} thrown in %s on line %d 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/get.phpt b/Zend/tests/property_hooks/get.phpt index 0cb0a6b7c76be..6d4b005843eaf 100644 --- a/Zend/tests/property_hooks/get.phpt +++ b/Zend/tests/property_hooks/get.phpt @@ -21,4 +21,4 @@ try { ?> --EXPECT-- int(42) -Property Test::$prop is read-only +Cannot write to get-only virtual property Test::$prop diff --git a/Zend/tests/property_hooks/get_by_ref_implemented_by_val.phpt b/Zend/tests/property_hooks/get_by_ref_implemented_by_val.phpt index 84eb968263546..2c507d862be6f 100644 --- a/Zend/tests/property_hooks/get_by_ref_implemented_by_val.phpt +++ b/Zend/tests/property_hooks/get_by_ref_implemented_by_val.phpt @@ -15,4 +15,4 @@ class A implements I { ?> --EXPECTF-- -Fatal error: Declaration of A::$prop::get() must be compatible with & I::$prop::get() in %s on line %d +Fatal error: Declaration of A::$prop::get() must be compatible with &I::$prop::get() in %s on line %d 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/property_hooks/gh20270.phpt b/Zend/tests/property_hooks/gh20270.phpt new file mode 100644 index 0000000000000..173d21990e556 --- /dev/null +++ b/Zend/tests/property_hooks/gh20270.phpt @@ -0,0 +1,51 @@ +--TEST-- +GH-20270: Parent hook call with named arguments +--CREDITS-- +Viet Hoang Luu (@vi3tL0u1s) +--FILE-- + $custom; + } +} + +class B extends A { + public mixed $prop1 { + set { + parent::$prop1::set(value: 42); + parent::$prop1::set(unknown: 43); + } + } + public mixed $prop2 { + set { + parent::$prop2::set(custom: 42); + parent::$prop2::set(value: 43); + } + } +} + +$b = new B(); + +try { + $b->prop1 = 0; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +var_dump($b->prop1); + +try { + $b->prop2 = 0; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +var_dump($b->prop2); + +?> +--EXPECT-- +Unknown named parameter $unknown +int(42) +Unknown named parameter $value +int(42) diff --git a/Zend/tests/property_hooks/override_add_get.phpt b/Zend/tests/property_hooks/override_add_get.phpt index 28dbd047c0718..df2739e6086c3 100644 --- a/Zend/tests/property_hooks/override_add_get.phpt +++ b/Zend/tests/property_hooks/override_add_get.phpt @@ -31,7 +31,7 @@ var_dump($b->prop); ?> --EXPECT-- A::A::$prop::set -Property A::$prop is write-only +Cannot read from set-only virtual property A::$prop B::B::$prop::set B::B::$prop::get int(42) diff --git a/Zend/tests/property_hooks/override_add_set.phpt b/Zend/tests/property_hooks/override_add_set.phpt index 6b490d4d87f94..e13de15f0b822 100644 --- a/Zend/tests/property_hooks/override_add_set.phpt +++ b/Zend/tests/property_hooks/override_add_set.phpt @@ -30,7 +30,7 @@ var_dump($b->prop); ?> --EXPECT-- -Property A::$prop is read-only +Cannot write to get-only virtual property A::$prop A::A::$prop::get int(42) B::B::$prop::set diff --git a/Zend/tests/property_hooks/set.phpt b/Zend/tests/property_hooks/set.phpt index 04e36ae85411f..2928aee6cedee 100644 --- a/Zend/tests/property_hooks/set.phpt +++ b/Zend/tests/property_hooks/set.phpt @@ -28,5 +28,5 @@ try { ?> --EXPECT-- int(42) -Property Test::$prop is write-only -Property Test::$prop is write-only +Cannot read from set-only virtual property Test::$prop +Cannot read from set-only virtual property Test::$prop diff --git a/Zend/tests/property_hooks/type_compatibility.phpt b/Zend/tests/property_hooks/type_compatibility.phpt index 8bfb7b0cadd59..def1fc77dc9ce 100644 --- a/Zend/tests/property_hooks/type_compatibility.phpt +++ b/Zend/tests/property_hooks/type_compatibility.phpt @@ -1,5 +1,5 @@ --TEST-- -Relaxed type compatibility for read-only and write-only properties +Relaxed type compatibility for get-only and set-only properties --FILE-- --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/runtime_compile_time_binary_operands.phpt b/Zend/tests/runtime_compile_time_binary_operands.phpt index e18134283e83d..948246f73b403 100644 --- a/Zend/tests/runtime_compile_time_binary_operands.phpt +++ b/Zend/tests/runtime_compile_time_binary_operands.phpt @@ -8,7 +8,7 @@ if (getenv("SKIP_SLOW_TESTS")) die('skip slow test'); ?> --FILE-- +--FILE-- + +--EXPECTF-- +Warning: The float -4.000000000000001E+21 is not representable as an int, cast occurred in %s on line %d +int(-2056257536) + +Warning: The float -4.0000000000000005E+21 is not representable as an int, cast occurred in %s on line %d +int(-2055733248) + +Warning: The float -4.0E+21 is not representable as an int, cast occurred in %s on line %d +int(-2055208960) + +Warning: The float -3.9999999999999995E+21 is not representable as an int, cast occurred in %s on line %d +int(-2054684672) + +Warning: The float -3.999999999999999E+21 is not representable as an int, cast occurred in %s on line %d +int(-2054160384) + +Warning: The float -2147483649.8 is not representable as an int, cast occurred in %s on line %d +int(2147483647) diff --git a/Zend/tests/type_coercion/float_to_int/dval_to_lval_64.phpt b/Zend/tests/type_coercion/float_to_int/dval_to_lval_64.phpt new file mode 100644 index 0000000000000..993950534fc17 --- /dev/null +++ b/Zend/tests/type_coercion/float_to_int/dval_to_lval_64.phpt @@ -0,0 +1,38 @@ +--TEST-- +zend_dval_to_lval preserves low bits (64 bit long) +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Warning: The float -4.000000000000001E+21 is not representable as an int, cast occurred in %s on line %d +int(2943463994971652096) + +Warning: The float -4.0000000000000005E+21 is not representable as an int, cast occurred in %s on line %d +int(2943463994972176384) + +Warning: The float -4.0E+21 is not representable as an int, cast occurred in %s on line %d +int(2943463994972700672) + +Warning: The float -3.9999999999999995E+21 is not representable as an int, cast occurred in %s on line %d +int(2943463994973224960) + +Warning: The float -3.999999999999999E+21 is not representable as an int, cast occurred in %s on line %d +int(2943463994973749248) diff --git a/Zend/tests/type_coercion/float_to_int/explicit_casts_should_not_warn.phpt b/Zend/tests/type_coercion/float_to_int/explicit_casts_should_not_warn.phpt new file mode 100644 index 0000000000000..4ef1215461885 --- /dev/null +++ b/Zend/tests/type_coercion/float_to_int/explicit_casts_should_not_warn.phpt @@ -0,0 +1,49 @@ +--TEST-- +Explicit (int) cast must not warn if value is representable +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Warning: unexpected NAN value was coerced to string in %s on line %d +int(3) +int(3) + +Warning: The float 1.0E+121 is not representable as an int, cast occurred in %s on line %d +int(0) + +Warning: The float 1.0E+301 is not representable as an int, cast occurred in %s on line %d +int(0) + +Warning: The float NAN is not representable as an int, cast occurred in %s on line %d +int(0) +int(3) +int(3) + +Warning: The float-string "1.0E+121" is not representable as an int, cast occurred in %s on line %d +int(9223372036854775807) + +Warning: The float-string "1.0E+301" is not representable as an int, cast occurred in %s on line %d +int(9223372036854775807) +int(0) diff --git a/Zend/tests/type_coercion/float_to_int/explicit_casts_should_not_warn_32bit.phpt b/Zend/tests/type_coercion/float_to_int/explicit_casts_should_not_warn_32bit.phpt new file mode 100644 index 0000000000000..3165d653d0478 --- /dev/null +++ b/Zend/tests/type_coercion/float_to_int/explicit_casts_should_not_warn_32bit.phpt @@ -0,0 +1,49 @@ +--TEST-- +Explicit (int) cast must not warn if value is representable 32bit variation +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Warning: unexpected NAN value was coerced to string in %s on line %d +int(3) +int(3) + +Warning: The float 1.0E+121 is not representable as an int, cast occurred in %s on line %d +int(0) + +Warning: The float 1.0E+301 is not representable as an int, cast occurred in %s on line %d +int(0) + +Warning: The float NAN is not representable as an int, cast occurred in %s on line %d +int(0) +int(3) +int(3) + +Warning: The float-string "1.0E+121" is not representable as an int, cast occurred in %s on line %d +int(2147483647) + +Warning: The float-string "1.0E+301" is not representable as an int, cast occurred in %s on line %d +int(2147483647) +int(0) diff --git a/Zend/tests/float_to_int/negative_zero_check.phpt b/Zend/tests/type_coercion/float_to_int/negative_zero_check.phpt similarity index 100% rename from Zend/tests/float_to_int/negative_zero_check.phpt rename to Zend/tests/type_coercion/float_to_int/negative_zero_check.phpt diff --git a/Zend/tests/float_to_int/no_warning_compatible_float_literals.phpt b/Zend/tests/type_coercion/float_to_int/no_warning_compatible_float_literals.phpt similarity index 100% rename from Zend/tests/float_to_int/no_warning_compatible_float_literals.phpt rename to Zend/tests/type_coercion/float_to_int/no_warning_compatible_float_literals.phpt diff --git a/Zend/tests/float_to_int/no_warning_compatible_string_float_literals.phpt b/Zend/tests/type_coercion/float_to_int/no_warning_compatible_string_float_literals.phpt similarity index 100% rename from Zend/tests/float_to_int/no_warning_compatible_string_float_literals.phpt rename to Zend/tests/type_coercion/float_to_int/no_warning_compatible_string_float_literals.phpt diff --git a/Zend/tests/float_to_int/no_warnings_compatible_float_literals_assignment_ops.phpt b/Zend/tests/type_coercion/float_to_int/no_warnings_compatible_float_literals_assignment_ops.phpt similarity index 100% rename from Zend/tests/float_to_int/no_warnings_compatible_float_literals_assignment_ops.phpt rename to Zend/tests/type_coercion/float_to_int/no_warnings_compatible_float_literals_assignment_ops.phpt diff --git a/Zend/tests/float_to_int/no_warnings_compatible_float_vars.phpt b/Zend/tests/type_coercion/float_to_int/no_warnings_compatible_float_vars.phpt similarity index 100% rename from Zend/tests/float_to_int/no_warnings_compatible_float_vars.phpt rename to Zend/tests/type_coercion/float_to_int/no_warnings_compatible_float_vars.phpt diff --git a/Zend/tests/float_to_int/no_warnings_compatible_string_float_vars.phpt b/Zend/tests/type_coercion/float_to_int/no_warnings_compatible_string_float_vars.phpt similarity index 100% rename from Zend/tests/float_to_int/no_warnings_compatible_string_float_vars.phpt rename to Zend/tests/type_coercion/float_to_int/no_warnings_compatible_string_float_vars.phpt diff --git a/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra1.phpt b/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra1.phpt new file mode 100644 index 0000000000000..aacf0dc855190 --- /dev/null +++ b/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra1.phpt @@ -0,0 +1,19 @@ +--TEST-- +Non rep float string to int conversions should not crash when modified +--FILE-- + +--EXPECTF-- +The float-string "1.0E+4%d" is not representable as an int, cast occurred +Implicit conversion from float-string "1.0E+4%d" to int loses precision +int(%d) diff --git a/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra2.phpt b/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra2.phpt new file mode 100644 index 0000000000000..0e96acfd182d2 --- /dev/null +++ b/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra2.phpt @@ -0,0 +1,17 @@ +--TEST-- +Non rep float string to int conversions should not crash when modified +--FILE-- + +--EXPECT-- +The float 1.0E+42 is not representable as an int, cast occurred diff --git a/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra3.phpt b/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra3.phpt new file mode 100644 index 0000000000000..0bfbeb01a2d00 --- /dev/null +++ b/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra3.phpt @@ -0,0 +1,18 @@ +--TEST-- +Non rep float string to int conversions should not crash when modified +--FILE-- + +--EXPECT-- +The float 1.0E+42 is not representable as an int, cast occurred +bool(false) diff --git a/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra4.phpt b/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra4.phpt new file mode 100644 index 0000000000000..8134ce08d2eed --- /dev/null +++ b/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra4.phpt @@ -0,0 +1,18 @@ +--TEST-- +Non rep float string to int conversions should not crash when modified +--FILE-- + +--EXPECT-- +The float 1.0E+42 is not representable as an int, cast occurred +bool(false) diff --git a/Zend/tests/float_to_int/union_int_string_type_arg.phpt b/Zend/tests/type_coercion/float_to_int/union_int_string_type_arg.phpt similarity index 85% rename from Zend/tests/float_to_int/union_int_string_type_arg.phpt rename to Zend/tests/type_coercion/float_to_int/union_int_string_type_arg.phpt index 3208b44e1ad29..9b1f057b7484f 100644 --- a/Zend/tests/float_to_int/union_int_string_type_arg.phpt +++ b/Zend/tests/type_coercion/float_to_int/union_int_string_type_arg.phpt @@ -23,6 +23,8 @@ int(1) Deprecated: Implicit conversion from float 1.5 to int loses precision in %s on line %d int(1) + +Warning: unexpected NAN value was coerced to string in %s on line %d string(3) "NAN" string(8) "1.0E+121" string(3) "INF" diff --git a/Zend/tests/float_to_int/union_int_string_type_arg_promote_exception.phpt b/Zend/tests/type_coercion/float_to_int/union_int_string_type_arg_promote_exception.phpt similarity index 100% rename from Zend/tests/float_to_int/union_int_string_type_arg_promote_exception.phpt rename to Zend/tests/type_coercion/float_to_int/union_int_string_type_arg_promote_exception.phpt diff --git a/Zend/tests/type_coercion/float_to_int/warning_float_does_not_fit_zend_long_arrays.phpt b/Zend/tests/type_coercion/float_to_int/warning_float_does_not_fit_zend_long_arrays.phpt new file mode 100644 index 0000000000000..779e103e6f821 --- /dev/null +++ b/Zend/tests/type_coercion/float_to_int/warning_float_does_not_fit_zend_long_arrays.phpt @@ -0,0 +1,58 @@ +--TEST-- +Implicit float to int conversions when float too large should warn, array variant +--FILE-- + 'Large float', (string) 10e120 => 'String large float']; +$arrayDynamic = [$float => 'Large float', $string_float => 'String large float']; + +var_dump($arrayConstant); +var_dump($arrayDynamic); + +$array = ['0', '1', '2']; +var_dump($array[10e120]); +var_dump($array[(string) 10e120]); +var_dump($array[$float]); +var_dump($array[$string_float]); + +?> +--EXPECTF-- +Warning: The float 1.0E+121 is not representable as an int, cast occurred in %s on line %d +int(0) + +Warning: The float-string "1.0E+121" is not representable as an int, cast occurred in %s on line %d +bool(true) + +Warning: The float 1.0E+121 is not representable as an int, cast occurred in %s on line %d + +Warning: The float 1.0E+121 is not representable as an int, cast occurred in %s on line %d +array(2) { + [0]=> + string(11) "Large float" + ["1.0E+121"]=> + string(18) "String large float" +} +array(2) { + [0]=> + string(11) "Large float" + ["1.0E+121"]=> + string(18) "String large float" +} + +Warning: The float 1.0E+121 is not representable as an int, cast occurred in %s on line %d +string(1) "0" + +Warning: Undefined array key "1.0E+121" in %s on line %d +NULL + +Warning: The float 1.0E+121 is not representable as an int, cast occurred in %s on line %d +string(1) "0" + +Warning: Undefined array key "1.0E+121" in %s on line %d +NULL diff --git a/Zend/tests/float_to_int/warning_float_does_not_fit_zend_long_strings.phpt b/Zend/tests/type_coercion/float_to_int/warning_float_does_not_fit_zend_long_strings.phpt similarity index 92% rename from Zend/tests/float_to_int/warning_float_does_not_fit_zend_long_strings.phpt rename to Zend/tests/type_coercion/float_to_int/warning_float_does_not_fit_zend_long_strings.phpt index 0c63cba1f5bc0..b4651d28ac4b3 100644 --- a/Zend/tests/float_to_int/warning_float_does_not_fit_zend_long_strings.phpt +++ b/Zend/tests/type_coercion/float_to_int/warning_float_does_not_fit_zend_long_strings.phpt @@ -75,7 +75,10 @@ var_dump($string); ?> --EXPECTF-- +Warning: The float 1.0E+121 is not representable as an int, cast occurred in %s on line %d int(0) + +Warning: The float-string "1.0E+121" is not representable as an int, cast occurred in %s on line %d int(9223372036854775807) Attempt to read Float diff --git a/Zend/tests/float_to_int/warning_float_does_not_fit_zend_long_strings_32bit.phpt b/Zend/tests/type_coercion/float_to_int/warning_float_does_not_fit_zend_long_strings_32bit.phpt similarity index 92% rename from Zend/tests/float_to_int/warning_float_does_not_fit_zend_long_strings_32bit.phpt rename to Zend/tests/type_coercion/float_to_int/warning_float_does_not_fit_zend_long_strings_32bit.phpt index cf2e396c311ba..3ec2c62cacdd4 100644 --- a/Zend/tests/float_to_int/warning_float_does_not_fit_zend_long_strings_32bit.phpt +++ b/Zend/tests/type_coercion/float_to_int/warning_float_does_not_fit_zend_long_strings_32bit.phpt @@ -75,7 +75,10 @@ var_dump($string); ?> --EXPECTF-- +Warning: The float 1.0E+121 is not representable as an int, cast occurred in %s on line %d int(0) + +Warning: The float-string "1.0E+121" is not representable as an int, cast occurred in %s on line %d int(2147483647) Attempt to read Float diff --git a/Zend/tests/float_to_int/warnings_float_literals.phpt b/Zend/tests/type_coercion/float_to_int/warnings_float_literals.phpt similarity index 100% rename from Zend/tests/float_to_int/warnings_float_literals.phpt rename to Zend/tests/type_coercion/float_to_int/warnings_float_literals.phpt diff --git a/Zend/tests/float_to_int/warnings_float_literals_assignment_ops.phpt b/Zend/tests/type_coercion/float_to_int/warnings_float_literals_assignment_ops.phpt similarity index 100% rename from Zend/tests/float_to_int/warnings_float_literals_assignment_ops.phpt rename to Zend/tests/type_coercion/float_to_int/warnings_float_literals_assignment_ops.phpt diff --git a/Zend/tests/float_to_int/warnings_float_vars.phpt b/Zend/tests/type_coercion/float_to_int/warnings_float_vars.phpt similarity index 100% rename from Zend/tests/float_to_int/warnings_float_vars.phpt rename to Zend/tests/type_coercion/float_to_int/warnings_float_vars.phpt diff --git a/Zend/tests/float_to_int/warnings_string_float_literals.phpt b/Zend/tests/type_coercion/float_to_int/warnings_string_float_literals.phpt similarity index 100% rename from Zend/tests/float_to_int/warnings_string_float_literals.phpt rename to Zend/tests/type_coercion/float_to_int/warnings_string_float_literals.phpt diff --git a/Zend/tests/float_to_int/warnings_string_float_literals_assignment_ops.phpt b/Zend/tests/type_coercion/float_to_int/warnings_string_float_literals_assignment_ops.phpt similarity index 100% rename from Zend/tests/float_to_int/warnings_string_float_literals_assignment_ops.phpt rename to Zend/tests/type_coercion/float_to_int/warnings_string_float_literals_assignment_ops.phpt diff --git a/Zend/tests/float_to_int/warnings_string_float_vars.phpt b/Zend/tests/type_coercion/float_to_int/warnings_string_float_vars.phpt similarity index 100% rename from Zend/tests/float_to_int/warnings_string_float_vars.phpt rename to Zend/tests/type_coercion/float_to_int/warnings_string_float_vars.phpt diff --git a/Zend/tests/type_coercion/int_special_values.phpt b/Zend/tests/type_coercion/int_special_values.phpt new file mode 100644 index 0000000000000..e536ff988e0ae --- /dev/null +++ b/Zend/tests/type_coercion/int_special_values.phpt @@ -0,0 +1,43 @@ +--TEST-- +Conversion of special float values to int +--FILE-- + +--EXPECTF-- +float(0) +int(0) + +float(INF) + +Warning: The float INF is not representable as an int, cast occurred in %s on line %d +int(0) + +float(-INF) + +Warning: The float -INF is not representable as an int, cast occurred in %s on line %d +int(0) + +float(0) +int(0) + +float(-0) +int(0) + +float(NAN) + +Warning: The float NAN is not representable as an int, cast occurred in %s on line %d +int(0) diff --git a/Zend/tests/type_coercion/nan_comp_op.phpt b/Zend/tests/type_coercion/nan_comp_op.phpt new file mode 100644 index 0000000000000..0be33cbb26ab6 --- /dev/null +++ b/Zend/tests/type_coercion/nan_comp_op.phpt @@ -0,0 +1,106 @@ +--TEST-- +NAN coerced to other types +--FILE-- + $right); + var_dump($nan >= $right); + var_dump($nan <=> $right); +} + +?> +--EXPECT-- +float(NAN) +Using 0 as right op +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(false) +bool(false) +bool(false) +int(1) +Using NULL as right op +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(false) +bool(true) +bool(true) +int(1) +Using false as right op +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(false) +bool(true) +bool(true) +int(1) +Using true as right op +bool(true) +bool(false) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +int(0) +Using '' as right op +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(false) +bool(false) +bool(false) +int(1) +Using array ( +) as right op +bool(false) +bool(true) +bool(false) +bool(true) +bool(true) +bool(true) +bool(false) +bool(false) +int(-1) +Using NAN as right op +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(false) +bool(false) +bool(false) +int(1) diff --git a/Zend/tests/type_coercion/nan_to_other.phpt b/Zend/tests/type_coercion/nan_to_other.phpt new file mode 100644 index 0000000000000..2918d1a8ccf4f --- /dev/null +++ b/Zend/tests/type_coercion/nan_to_other.phpt @@ -0,0 +1,93 @@ +--TEST-- +NAN coerced to other types +--FILE-- + +--EXPECTF-- +float(NAN) + +Warning: unexpected NAN value was coerced to bool in %s on line %d +bool(true) + +Warning: unexpected NAN value was coerced to string in %s on line %d +string(3) "NAN" + +Warning: The float NAN is not representable as an int, cast occurred in %s on line %d +int(0) + +Warning: unexpected NAN value was coerced to bool in %s on line %d +bool(true) + +Warning: unexpected NAN value was coerced to string in %s on line %d +string(3) "NAN" + +Warning: unexpected NAN value was coerced to array in %s on line %d +array(1) { + [0]=> + float(NAN) +} + +Warning: unexpected NAN value was coerced to object in %s on line %d +object(stdClass)#%d (1) { + ["scalar"]=> + float(NAN) +} + +Warning: unexpected NAN value was coerced to null in %s on line %d +NULL + +Warning: unexpected NAN value was coerced to bool in %s on line %d +bool(true) + +Warning: The float NAN is not representable as an int, cast occurred in %s on line %d +int(0) + +Warning: unexpected NAN value was coerced to string in %s on line %d +string(3) "NAN" + +Warning: unexpected NAN value was coerced to array in %s on line %d +array(1) { + [0]=> + float(NAN) +} + +Warning: unexpected NAN value was coerced to object in %s on line %d +object(stdClass)#%d (1) { + ["scalar"]=> + float(NAN) +} diff --git a/Zend/tests/settype/settype_array.phpt b/Zend/tests/type_coercion/settype/settype_array.phpt similarity index 100% rename from Zend/tests/settype/settype_array.phpt rename to Zend/tests/type_coercion/settype/settype_array.phpt diff --git a/Zend/tests/type_coercion/settype/settype_array_nan_with_error_handler.phpt b/Zend/tests/type_coercion/settype/settype_array_nan_with_error_handler.phpt new file mode 100644 index 0000000000000..b07d975d7b2fa --- /dev/null +++ b/Zend/tests/type_coercion/settype/settype_array_nan_with_error_handler.phpt @@ -0,0 +1,24 @@ +--TEST-- +Error handler dtor NAN value, set to array +--FILE-- + +--EXPECT-- +float(NAN) +unexpected NAN value was coerced to array +array(1) { + [0]=> + NULL +} diff --git a/Zend/tests/type_coercion/settype/settype_array_nan_with_error_handler2.phpt b/Zend/tests/type_coercion/settype/settype_array_nan_with_error_handler2.phpt new file mode 100644 index 0000000000000..681b015593026 --- /dev/null +++ b/Zend/tests/type_coercion/settype/settype_array_nan_with_error_handler2.phpt @@ -0,0 +1,24 @@ +--TEST-- +Error handler dtor NAN value, set to array 2 +--FILE-- + +--EXPECT-- +float(NAN) +unexpected NAN value was coerced to array +array(1) { + [0]=> + float(NAN) +} diff --git a/Zend/tests/type_coercion/settype/settype_array_nan_with_error_handler3.phpt b/Zend/tests/type_coercion/settype/settype_array_nan_with_error_handler3.phpt new file mode 100644 index 0000000000000..1dae45a6ebec5 --- /dev/null +++ b/Zend/tests/type_coercion/settype/settype_array_nan_with_error_handler3.phpt @@ -0,0 +1,24 @@ +--TEST-- +Error handler dtor NAN value, set to array 3 +--FILE-- + +--EXPECTF-- +float(NAN) +unexpected NAN value was coerced to array +array(1) { + [0]=> + string(8) "%s" +} diff --git a/Zend/tests/settype/settype_bool.phpt b/Zend/tests/type_coercion/settype/settype_bool.phpt similarity index 100% rename from Zend/tests/settype/settype_bool.phpt rename to Zend/tests/type_coercion/settype/settype_bool.phpt diff --git a/Zend/tests/type_coercion/settype/settype_bool_nan_with_error_handler.phpt b/Zend/tests/type_coercion/settype/settype_bool_nan_with_error_handler.phpt new file mode 100644 index 0000000000000..5f854c54ddbdd --- /dev/null +++ b/Zend/tests/type_coercion/settype/settype_bool_nan_with_error_handler.phpt @@ -0,0 +1,21 @@ +--TEST-- +Error handler dtor NAN value, set to bool +--FILE-- + +--EXPECT-- +float(NAN) +unexpected NAN value was coerced to bool +bool(true) diff --git a/Zend/tests/type_coercion/settype/settype_bool_nan_with_error_handler2.phpt b/Zend/tests/type_coercion/settype/settype_bool_nan_with_error_handler2.phpt new file mode 100644 index 0000000000000..1377228a9da64 --- /dev/null +++ b/Zend/tests/type_coercion/settype/settype_bool_nan_with_error_handler2.phpt @@ -0,0 +1,21 @@ +--TEST-- +Error handler dtor NAN value, set to bool 2 +--FILE-- + +--EXPECT-- +float(NAN) +unexpected NAN value was coerced to bool +bool(true) diff --git a/Zend/tests/type_coercion/settype/settype_bool_nan_with_error_handler3.phpt b/Zend/tests/type_coercion/settype/settype_bool_nan_with_error_handler3.phpt new file mode 100644 index 0000000000000..ceb17da96408f --- /dev/null +++ b/Zend/tests/type_coercion/settype/settype_bool_nan_with_error_handler3.phpt @@ -0,0 +1,21 @@ +--TEST-- +Error handler dtor NAN value, set to bool 3 +--FILE-- + +--EXPECT-- +float(NAN) +unexpected NAN value was coerced to bool +bool(true) diff --git a/Zend/tests/settype/settype_double.phpt b/Zend/tests/type_coercion/settype/settype_double.phpt similarity index 100% rename from Zend/tests/settype/settype_double.phpt rename to Zend/tests/type_coercion/settype/settype_double.phpt diff --git a/Zend/tests/settype/settype_int.phpt b/Zend/tests/type_coercion/settype/settype_int.phpt similarity index 100% rename from Zend/tests/settype/settype_int.phpt rename to Zend/tests/type_coercion/settype/settype_int.phpt diff --git a/Zend/tests/type_coercion/settype/settype_int_nan_with_error_handler.phpt b/Zend/tests/type_coercion/settype/settype_int_nan_with_error_handler.phpt new file mode 100644 index 0000000000000..4f00f51331e0d --- /dev/null +++ b/Zend/tests/type_coercion/settype/settype_int_nan_with_error_handler.phpt @@ -0,0 +1,21 @@ +--TEST-- +Error handler dtor NAN value, set to int +--FILE-- + +--EXPECT-- +float(NAN) +The float NAN is not representable as an int, cast occurred +int(0) diff --git a/Zend/tests/type_coercion/settype/settype_int_nan_with_error_handler2.phpt b/Zend/tests/type_coercion/settype/settype_int_nan_with_error_handler2.phpt new file mode 100644 index 0000000000000..65c048158f8a5 --- /dev/null +++ b/Zend/tests/type_coercion/settype/settype_int_nan_with_error_handler2.phpt @@ -0,0 +1,21 @@ +--TEST-- +Error handler dtor NAN value, set to int 2 +--FILE-- + +--EXPECT-- +float(NAN) +The float NAN is not representable as an int, cast occurred +int(0) diff --git a/Zend/tests/type_coercion/settype/settype_int_nan_with_error_handler3.phpt b/Zend/tests/type_coercion/settype/settype_int_nan_with_error_handler3.phpt new file mode 100644 index 0000000000000..4e715bdcca1bd --- /dev/null +++ b/Zend/tests/type_coercion/settype/settype_int_nan_with_error_handler3.phpt @@ -0,0 +1,21 @@ +--TEST-- +Error handler dtor NAN value, set to int 3 +--FILE-- + +--EXPECT-- +float(NAN) +The float NAN is not representable as an int, cast occurred +int(0) diff --git a/Zend/tests/settype/settype_null.phpt b/Zend/tests/type_coercion/settype/settype_null.phpt similarity index 100% rename from Zend/tests/settype/settype_null.phpt rename to Zend/tests/type_coercion/settype/settype_null.phpt diff --git a/Zend/tests/type_coercion/settype/settype_null_nan_with_error_handler.phpt b/Zend/tests/type_coercion/settype/settype_null_nan_with_error_handler.phpt new file mode 100644 index 0000000000000..d89cb55443241 --- /dev/null +++ b/Zend/tests/type_coercion/settype/settype_null_nan_with_error_handler.phpt @@ -0,0 +1,21 @@ +--TEST-- +Error handler dtor NAN value, set to null +--FILE-- + +--EXPECT-- +float(NAN) +unexpected NAN value was coerced to null +NULL diff --git a/Zend/tests/type_coercion/settype/settype_null_nan_with_error_handler2.phpt b/Zend/tests/type_coercion/settype/settype_null_nan_with_error_handler2.phpt new file mode 100644 index 0000000000000..41c095ff3f0b2 --- /dev/null +++ b/Zend/tests/type_coercion/settype/settype_null_nan_with_error_handler2.phpt @@ -0,0 +1,21 @@ +--TEST-- +Error handler dtor NAN value, set to null 2 +--FILE-- + +--EXPECT-- +float(NAN) +unexpected NAN value was coerced to null +NULL diff --git a/Zend/tests/type_coercion/settype/settype_null_nan_with_error_handler3.phpt b/Zend/tests/type_coercion/settype/settype_null_nan_with_error_handler3.phpt new file mode 100644 index 0000000000000..9a289b4151aa2 --- /dev/null +++ b/Zend/tests/type_coercion/settype/settype_null_nan_with_error_handler3.phpt @@ -0,0 +1,21 @@ +--TEST-- +Error handler dtor NAN value, set to null 3 +--FILE-- + +--EXPECT-- +float(NAN) +unexpected NAN value was coerced to null +NULL diff --git a/Zend/tests/settype/settype_object.phpt b/Zend/tests/type_coercion/settype/settype_object.phpt similarity index 100% rename from Zend/tests/settype/settype_object.phpt rename to Zend/tests/type_coercion/settype/settype_object.phpt diff --git a/Zend/tests/type_coercion/settype/settype_object_nan_with_error_handler.phpt b/Zend/tests/type_coercion/settype/settype_object_nan_with_error_handler.phpt new file mode 100644 index 0000000000000..19e36fa3d4fcd --- /dev/null +++ b/Zend/tests/type_coercion/settype/settype_object_nan_with_error_handler.phpt @@ -0,0 +1,24 @@ +--TEST-- +Error handler dtor NAN value, set to object +--FILE-- + +--EXPECT-- +float(NAN) +unexpected NAN value was coerced to object +object(stdClass)#2 (1) { + ["scalar"]=> + NULL +} diff --git a/Zend/tests/type_coercion/settype/settype_object_nan_with_error_handler2.phpt b/Zend/tests/type_coercion/settype/settype_object_nan_with_error_handler2.phpt new file mode 100644 index 0000000000000..b605d0ff9e7e5 --- /dev/null +++ b/Zend/tests/type_coercion/settype/settype_object_nan_with_error_handler2.phpt @@ -0,0 +1,24 @@ +--TEST-- +Error handler dtor NAN value, set to object 2 +--FILE-- + +--EXPECT-- +float(NAN) +unexpected NAN value was coerced to object +object(stdClass)#2 (1) { + ["scalar"]=> + float(NAN) +} diff --git a/Zend/tests/type_coercion/settype/settype_object_nan_with_error_handler3.phpt b/Zend/tests/type_coercion/settype/settype_object_nan_with_error_handler3.phpt new file mode 100644 index 0000000000000..b3789f2a9c572 --- /dev/null +++ b/Zend/tests/type_coercion/settype/settype_object_nan_with_error_handler3.phpt @@ -0,0 +1,24 @@ +--TEST-- +Error handler dtor NAN value, set to object 3 +--FILE-- + +--EXPECTF-- +float(NAN) +unexpected NAN value was coerced to object +object(stdClass)#2 (1) { + ["scalar"]=> + string(8) "%s" +} diff --git a/Zend/tests/settype/settype_resource.phpt b/Zend/tests/type_coercion/settype/settype_resource.phpt similarity index 100% rename from Zend/tests/settype/settype_resource.phpt rename to Zend/tests/type_coercion/settype/settype_resource.phpt diff --git a/Zend/tests/settype/settype_string.phpt b/Zend/tests/type_coercion/settype/settype_string.phpt similarity index 100% rename from Zend/tests/settype/settype_string.phpt rename to Zend/tests/type_coercion/settype/settype_string.phpt diff --git a/Zend/tests/type_coercion/settype/settype_string_nan_with_error_handler.phpt b/Zend/tests/type_coercion/settype/settype_string_nan_with_error_handler.phpt new file mode 100644 index 0000000000000..d3a52996f4ddb --- /dev/null +++ b/Zend/tests/type_coercion/settype/settype_string_nan_with_error_handler.phpt @@ -0,0 +1,21 @@ +--TEST-- +Error handler dtor NAN value, set to string +--FILE-- + +--EXPECT-- +float(NAN) +unexpected NAN value was coerced to string +string(3) "NAN" diff --git a/Zend/tests/type_coercion/settype/settype_string_nan_with_error_handler2.phpt b/Zend/tests/type_coercion/settype/settype_string_nan_with_error_handler2.phpt new file mode 100644 index 0000000000000..17921e5ae5308 --- /dev/null +++ b/Zend/tests/type_coercion/settype/settype_string_nan_with_error_handler2.phpt @@ -0,0 +1,21 @@ +--TEST-- +Error handler dtor NAN value, set to string 2 +--FILE-- + +--EXPECT-- +float(NAN) +unexpected NAN value was coerced to string +string(3) "NAN" \ No newline at end of file diff --git a/Zend/tests/type_coercion/settype/settype_string_nan_with_error_handler3.phpt b/Zend/tests/type_coercion/settype/settype_string_nan_with_error_handler3.phpt new file mode 100644 index 0000000000000..0a8718780abd2 --- /dev/null +++ b/Zend/tests/type_coercion/settype/settype_string_nan_with_error_handler3.phpt @@ -0,0 +1,21 @@ +--TEST-- +Error handler dtor NAN value, set to string 3 +--FILE-- + +--EXPECT-- +float(NAN) +unexpected NAN value was coerced to string +string(3) "NAN" diff --git a/Zend/tests/type_casts/cast_to_array.phpt b/Zend/tests/type_coercion/type_casts/cast_to_array.phpt similarity index 100% rename from Zend/tests/type_casts/cast_to_array.phpt rename to Zend/tests/type_coercion/type_casts/cast_to_array.phpt diff --git a/Zend/tests/type_casts/cast_to_bool.phpt b/Zend/tests/type_coercion/type_casts/cast_to_bool.phpt similarity index 100% rename from Zend/tests/type_casts/cast_to_bool.phpt rename to Zend/tests/type_coercion/type_casts/cast_to_bool.phpt diff --git a/Zend/tests/type_casts/cast_to_double.phpt b/Zend/tests/type_coercion/type_casts/cast_to_double.phpt similarity index 90% rename from Zend/tests/type_casts/cast_to_double.phpt rename to Zend/tests/type_coercion/type_casts/cast_to_double.phpt index 2972fbbe8027a..69a625b09de88 100644 --- a/Zend/tests/type_casts/cast_to_double.phpt +++ b/Zend/tests/type_coercion/type_casts/cast_to_double.phpt @@ -1,5 +1,5 @@ --TEST-- -casting different variables to double +casting different variables to float --INI-- precision=14 --FILE-- @@ -32,7 +32,7 @@ $vars = array( ); foreach ($vars as $var) { - $tmp = (double)$var; + $tmp = (float)$var; var_dump($tmp); } diff --git a/Zend/tests/type_casts/cast_to_int.phpt b/Zend/tests/type_coercion/type_casts/cast_to_int.phpt similarity index 100% rename from Zend/tests/type_casts/cast_to_int.phpt rename to Zend/tests/type_coercion/type_casts/cast_to_int.phpt diff --git a/Zend/tests/type_casts/cast_to_object.phpt b/Zend/tests/type_coercion/type_casts/cast_to_object.phpt similarity index 100% rename from Zend/tests/type_casts/cast_to_object.phpt rename to Zend/tests/type_coercion/type_casts/cast_to_object.phpt diff --git a/Zend/tests/type_casts/cast_to_string.phpt b/Zend/tests/type_coercion/type_casts/cast_to_string.phpt similarity index 100% rename from Zend/tests/type_casts/cast_to_string.phpt rename to Zend/tests/type_coercion/type_casts/cast_to_string.phpt diff --git a/Zend/tests/type_casts/cast_to_void.phpt b/Zend/tests/type_coercion/type_casts/cast_to_void.phpt similarity index 100% rename from Zend/tests/type_casts/cast_to_void.phpt rename to Zend/tests/type_coercion/type_casts/cast_to_void.phpt diff --git a/Zend/tests/type_casts/cast_to_void_ast.phpt b/Zend/tests/type_coercion/type_casts/cast_to_void_ast.phpt similarity index 100% rename from Zend/tests/type_casts/cast_to_void_ast.phpt rename to Zend/tests/type_coercion/type_casts/cast_to_void_ast.phpt diff --git a/Zend/tests/type_casts/cast_to_void_destructor.phpt b/Zend/tests/type_coercion/type_casts/cast_to_void_destructor.phpt similarity index 100% rename from Zend/tests/type_casts/cast_to_void_destructor.phpt rename to Zend/tests/type_coercion/type_casts/cast_to_void_destructor.phpt diff --git a/Zend/tests/type_casts/cast_to_void_statement.phpt b/Zend/tests/type_coercion/type_casts/cast_to_void_statement.phpt similarity index 100% rename from Zend/tests/type_casts/cast_to_void_statement.phpt rename to Zend/tests/type_coercion/type_casts/cast_to_void_statement.phpt diff --git a/Zend/tests/type_casts/gh18301_cast_to_void_for.phpt b/Zend/tests/type_coercion/type_casts/gh18301_cast_to_void_for.phpt similarity index 100% rename from Zend/tests/type_casts/gh18301_cast_to_void_for.phpt rename to Zend/tests/type_coercion/type_casts/gh18301_cast_to_void_for.phpt diff --git a/Zend/tests/type_casts/gh18301_cast_to_void_statement_for_condition.phpt b/Zend/tests/type_coercion/type_casts/gh18301_cast_to_void_statement_for_condition.phpt similarity index 100% rename from Zend/tests/type_casts/gh18301_cast_to_void_statement_for_condition.phpt rename to Zend/tests/type_coercion/type_casts/gh18301_cast_to_void_statement_for_condition.phpt diff --git a/Zend/tests/type_coercion/type_casts/non_canonical_binary_cast.phpt b/Zend/tests/type_coercion/type_casts/non_canonical_binary_cast.phpt new file mode 100644 index 0000000000000..fc7aa59ac9084 --- /dev/null +++ b/Zend/tests/type_coercion/type_casts/non_canonical_binary_cast.phpt @@ -0,0 +1,11 @@ +--TEST-- +Non canonical (binary) cast +--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/scalar_basic.phpt b/Zend/tests/type_declarations/scalar_basic.phpt index 6b2cf736edbf9..352c48f8a9e07 100644 --- a/Zend/tests/type_declarations/scalar_basic.phpt +++ b/Zend/tests/type_declarations/scalar_basic.phpt @@ -194,6 +194,7 @@ string(0) "" string(%d) "%d" *** Trying float(NAN) +E_WARNING: unexpected NAN value was coerced to string on line %d string(3) "NAN" *** Trying bool(true) @@ -247,6 +248,7 @@ bool(false) bool(true) *** Trying float(NAN) +E_WARNING: unexpected NAN value was coerced to bool on line %d bool(true) *** Trying bool(true) diff --git a/Zend/tests/type_declarations/scalar_return_basic.phpt b/Zend/tests/type_declarations/scalar_return_basic.phpt index 8f827600328ed..67af304ec2c69 100644 --- a/Zend/tests/type_declarations/scalar_return_basic.phpt +++ b/Zend/tests/type_declarations/scalar_return_basic.phpt @@ -156,6 +156,7 @@ string(0) "" *** Trying int(2147483647) string(10) "2147483647" *** Trying float(NAN) +E_WARNING: unexpected NAN value was coerced to string on line %d string(3) "NAN" *** Trying bool(true) string(1) "1" @@ -193,6 +194,7 @@ bool(false) *** Trying int(2147483647) bool(true) *** Trying float(NAN) +E_WARNING: unexpected NAN value was coerced to bool on line %d bool(true) *** Trying bool(true) bool(true) diff --git a/Zend/tests/type_declarations/scalar_return_basic_64bit.phpt b/Zend/tests/type_declarations/scalar_return_basic_64bit.phpt index 0a32dd3f16f23..498092e8ac543 100644 --- a/Zend/tests/type_declarations/scalar_return_basic_64bit.phpt +++ b/Zend/tests/type_declarations/scalar_return_basic_64bit.phpt @@ -156,6 +156,7 @@ string(0) "" *** Trying int(9223372036854775807) string(19) "9223372036854775807" *** Trying float(NAN) +E_WARNING: unexpected NAN value was coerced to string on line %d string(3) "NAN" *** Trying bool(true) string(1) "1" @@ -193,6 +194,7 @@ bool(false) *** Trying int(9223372036854775807) bool(true) *** Trying float(NAN) +E_WARNING: unexpected NAN value was coerced to bool on line %d bool(true) *** Trying bool(true) bool(true) 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/unified_arg_infos_001.phpt b/Zend/tests/unified_arg_infos_001.phpt new file mode 100644 index 0000000000000..d6699aa8d8cb5 --- /dev/null +++ b/Zend/tests/unified_arg_infos_001.phpt @@ -0,0 +1,21 @@ +--TEST-- +Declaring non persistent method with arg info +--EXTENSIONS-- +zend_test +--FILE-- +testTmpMethodWithArgInfo(null); + +echo new ReflectionFunction($o->testTmpMethodWithArgInfo(...)); + +?> +--EXPECT-- +Closure [ public method testTmpMethodWithArgInfo ] { + + - Parameters [2] { + Parameter #0 [ Foo|Bar|null $tmpMethodParamName = null ] + Parameter #1 [ string $tmpMethodParamWithStringDefaultValue = "tmpMethodParamWithStringDefaultValue" ] + } +} diff --git a/Zend/tests/unset_empty_isset_comprehensive.phpt b/Zend/tests/unset_empty_isset_comprehensive.phpt new file mode 100644 index 0000000000000..9a1aad99aa694 --- /dev/null +++ b/Zend/tests/unset_empty_isset_comprehensive.phpt @@ -0,0 +1,1441 @@ +--TEST-- +Test unset(), empty() and isset() functions +--FILE-- + "One", 2 => "two"), + array("Name" => "Jack", "Age" => "30"), + array(1,2, "One" => "1", 2 => "two", ""=>"empty", "" => '') +); + +$outer_loop_counter = 1; +foreach ($array_variables as $array_var) { + echo "--- Outerloop Iteration $outer_loop_counter ---\n"; + + // check the isset and unset on non existing key + $var = 1; // a var which is defined + // try to unset the element which is non-existent + unset($array_var['non_existent']); + // check using isset() & empty() on a non_existent element in the array + var_dump( isset($array_var['non_existent']) ); + var_dump( isset($array_var['non_existent'], $var) ); + var_dump( isset($array_var['non_existent'], $array_var['none']) ); + var_dump( empty($array_var['non_existent']) ); + + // testing empty and isset on arrays + var_dump( empty($array_var) ); // expecting bool(false), except: array(), which is considered empty + var_dump( isset($array_var) ); // expecting bool(true), except: array(), which is not set + + // get the keys of the $array_var + $keys = array_keys($array_var); + // unset each element in the array and see the working of unset, isset & empty + $inner_loop_counter = 1; + foreach ($keys as $key_value) { + echo "-- Innerloop Iteration $inner_loop_counter of Outerloop Iteration $outer_loop_counter --\n"; + $inner_loop_counter++; + + // unset the element + unset($array_var[$key_value]); + // dump the array after element was unset + var_dump($array_var); + // check using isset for the element that was unset + var_dump( isset($array_var[$key_val]) ); // expected: bool(false) + // calling isset with more args + var_dump( isset($array_var[$key_val], $array_var) ); //expected: bool(false) + + // calling empty, expected bool(true) + var_dump( empty($array_var[$key_val]) ); + + // dump the array to see that that array did not get modified + // because of using isset, empty and unset on its element + var_dump($array_var); + } + + $outer_loop_counter++; + + // unset the whole array + unset($array_var); + // dump the array to see its unset + var_dump($array_var); + // use isset to see that array is not set + var_dump( isset($array_var) ); //expected: bool(false) + var_dump( isset($array_var, $array_var[$key_val]) ); // expected: bool(false) + + // empty() to see if the array is empty + var_dump( empty($array_var) ); // expected: bool(true) +} + +echo "\n*** Testing unset(), empty() & isset() with resource variables ***\n"; +$fp = fopen(__FILE__, "r"); +$dfp = opendir( __DIR__ ); +$resources = array ( + $fp, + $dfp +); +$loop_counter = 1; +foreach ($resources as $resource) { + $temp_var = 10; + echo "-- Iteration $loop_counter --\n"; $loop_counter++; + //dump the resource first + var_dump($resource); + + // check using isset() and empty() + var_dump( isset($resource) ); // expected: bool(true) + var_dump( empty($resource) ); // expected: bool(false) + // call isset() with two args, both set + var_dump( isset($resource, $temp_var) ); // expected: bool(true) + + // dump the resource to see using isset() and empty () had no effect on it + var_dump($resource); + + // unset the resource + unset($resource); + // check using isset() and empty() + var_dump( isset($resource) ); // expected: bool(false) + var_dump( empty($resource) ); // expected: bool(true) + // call isset() with two args, but one set + var_dump( isset($resource, $temp_var) ); // expected: bool(false) + // unset the temp_var + unset($temp_var); + // now the isset() with both the args as unset + var_dump( isset($resource, $temp_var) ); // expected: bool(false); + + // dump the resource to see if there any effect on it + var_dump($resource); +} +// unset and dump the array containing all the resources to see that +// unset works correctly +unset($resources); +var_dump($resources); +var_dump( isset($resources) ); //expected: bool(false) +var_dump( empty($resources) ); // expected: bool(true) + +echo "\n*** Testing unset(), empty() & isset() with objects ***\n"; +class Point +{ + var $x; + var $y; + var $lable; + + function __construct($x, $y) { + $this->x = $x; + $this->y = $y; + } + + function setLable($lable) { + $this->lable = $lable; + } + function testPoint() { + echo "\nPoint::testPoint() called\n"; + } +} +$point1 = new Point(30,40); + +// use unset/empty/isset to check the object +var_dump($point1); // dump the object + +// check the object and member that is not set +var_dump( isset($point1) ); // expected: bool(true) +var_dump( empty($point1) ); // expected: bool(false) +var_dump( isset($point1->$lable) ); //expected: bool(false) +var_dump( empty($point1->$lable) ); //expected: bool(true) + +//set the member variable lable and check +$point1->setLable("Point1"); +var_dump( isset($point1->$lable) ); //expected: bool(true) +var_dump( empty($point1->$lable) ); //expected: bool(false) + +// dump the object to see that obj was not harmed +// because of the usage of the isset & empty +var_dump($point1); + +//unset a member and check +unset($point1->x); +// dump the point to see that variable was unset +var_dump($point1); +var_dump( isset($point1->x) ); // expected: bool(false) +var_dump( empty($point1->x) ); // expected: bool(true) + +// unset all members and check +unset($point1->y); +unset($point1->lable); +// dump the object to check that all variables are unset +var_dump($point1); +var_dump( isset($point1) ); // expected: bool(ture) +var_dump( empty($point1) ); // expected: bool(false) + +//unset the object and check +unset($point1); +var_dump( isset($point1) ); // expected: bool(false) +var_dump( empty($point1) ); // expected: bool(true) +// dump to see that object is unset +var_dump($point1); + +// try isset/unset/empty on a member function +$point2 = new Point(5,6); +var_dump( isset($point2->testPoint) ); +var_dump( empty($point2->testPoint) ); +unset($point2->testPoint); +var_dump( isset($point2->testPoint) ); +var_dump( empty($point2->testPoint) ); + +// use get_class_methods to see effect if any +var_dump( get_class_methods($point2) ); +// dump the object to see the effect, none expected +var_dump($point2); + +/* testing variation in operation for isset(), empty() & unset(). +Note: Most of the variation for function unset() is testing by a + set of testcases named "Zend/tests/unset_cv??.phpt", only + variation not tested are attempted here */ + +echo "\n*** Testing possible variation in operation for isset(), empty() & unset() ***\n"; +/* unset() variation1: checking unset on static variable inside a function. + * unset() destroys the variable only in the context of the rest of a function + * Following calls will restore the previous value of a variable. + */ +echo "\n** Testing unset() variation 1: unset on static variable inside a function **\n"; +function test_unset1() { + static $static_var; + + // increment the value of the static. this change is in function context + $static_var ++; + + echo "value of static_var before unset: $static_var\n"; + // check using isset and empty + var_dump( isset($static_var) ); + var_dump( empty($static_var) ); + + // unset the static var + unset($static_var); + echo "value of static_var after unset: $static_var\n"; + // check using isset and empty + var_dump( isset($static_var) ); + var_dump( empty($static_var) ); + + // assign a value to static var + $static_var = 20; + echo "value of static_var after new assignment: $static_var\n"; +} +// call the function +test_unset1(); +test_unset1(); +test_unset1(); + + +echo "\n** Testing unset() variation 2: unset on a variable passed by ref. inside of a function **\n"; +/* unset() variation2: Pass by reference + * If a variable that is PASSED BY REFERENCE is unset() inside of a function, + * only the local variable is destroyed. The variable in the calling environment + * will retain the same value as before unset() was called. + */ +function test_unset2( &$ref_val ) { + // unset the variable passed + unset($ref_val); + // check using isset and empty to confirm + var_dump( isset($ref_val) ); + var_dump( empty($ref_val) ); + + // set the value ot a new one + $ref_val = "new value by ref"; +} + +$value = "value"; +var_dump($value); +test_unset2($value); +var_dump($value); + + +echo "\n** Testing unset() variation 3: unset on a global variable inside of a function **\n"; +/* unset() variation2: unset on a global variable inside a function + * If a globalized variable is unset() inside of a function, only the + * local variable is destroyed. The variable in the calling environment + * will retain the same value as before unset() was called. + */ +$global_var = 10; + +function test_unset3() { + global $global_var; + + // check the $global_var using isset and empty + var_dump( isset($global_var) ); + var_dump( empty($global_var) ); + + // unset the global var + unset($global_var); + + // check the $global_var using isset and empty + var_dump( isset($global_var) ); + var_dump( empty($global_var) ); +} + +var_dump($global_var); +test_unset3(); +var_dump($global_var); + +//Note: No error conditions relating to passing arguments can be tested +// because these are not functions but statements, it will result in syntax error. +?> +--EXPECTF-- +*** Testing unset(), empty() & isset() with scalar variables *** +-- Iteration 1 -- +bool(true) +bool(true) +bool(true) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 2 -- +bool(true) +bool(true) +bool(false) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 3 -- +bool(true) +bool(true) +bool(true) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 4 -- +bool(true) +bool(true) +bool(false) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 5 -- +bool(true) +bool(true) +bool(false) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 6 -- +bool(true) +bool(true) +bool(false) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 7 -- +bool(true) +bool(true) +bool(false) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 8 -- +bool(true) +bool(true) +bool(true) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 9 -- +bool(true) +bool(true) +bool(false) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 10 -- +bool(true) +bool(true) +bool(false) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 11 -- +bool(true) +bool(true) +bool(false) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 12 -- +bool(true) +bool(true) +bool(false) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 13 -- +bool(true) +bool(true) +bool(true) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 14 -- +bool(true) +bool(true) +bool(true) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 15 -- +bool(true) +bool(true) +bool(false) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 16 -- +bool(true) +bool(true) +bool(false) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 17 -- +bool(true) +bool(true) +bool(false) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 18 -- +bool(true) +bool(true) +bool(false) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 19 -- +bool(true) +bool(true) +bool(true) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 20 -- +bool(true) +bool(true) +bool(false) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 21 -- +bool(true) +bool(true) +bool(false) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 22 -- +bool(true) +bool(true) +bool(false) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 23 -- +bool(true) +bool(true) +bool(false) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 24 -- +bool(true) +bool(true) +bool(false) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 25 -- +bool(true) +bool(true) +bool(true) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 26 -- +bool(true) +bool(true) +bool(false) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +-- Iteration 27 -- +bool(true) +bool(true) +bool(true) + +Warning: Undefined variable $scalar_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) + +*** Testing unset(), empty() & isset() with arrays *** +--- Outerloop Iteration 1 --- +bool(false) +bool(false) +bool(false) +bool(true) +bool(true) +bool(true) + +Warning: Undefined variable $array_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +--- Outerloop Iteration 2 --- +bool(false) +bool(false) +bool(false) +bool(true) +bool(false) +bool(true) +-- Innerloop Iteration 1 of Outerloop Iteration 2 -- +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) { +} + +Warning: Undefined variable $array_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +--- Outerloop Iteration 3 --- +bool(false) +bool(false) +bool(false) +bool(true) +bool(false) +bool(true) +-- Innerloop Iteration 1 of Outerloop Iteration 3 -- +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) { +} + +Warning: Undefined variable $array_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +--- Outerloop Iteration 4 --- +bool(false) +bool(false) +bool(false) +bool(true) +bool(false) +bool(true) +-- Innerloop Iteration 1 of Outerloop Iteration 4 -- +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) { +} + +Warning: Undefined variable $array_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +--- Outerloop Iteration 5 --- +bool(false) +bool(false) +bool(false) +bool(true) +bool(false) +bool(true) +-- Innerloop Iteration 1 of Outerloop Iteration 5 -- +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) { +} + +Warning: Undefined variable $array_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +--- Outerloop Iteration 6 --- +bool(false) +bool(false) +bool(false) +bool(true) +bool(false) +bool(true) +-- Innerloop Iteration 1 of Outerloop Iteration 6 -- +array(3) { + [1]=> + int(2) + [2]=> + int(3) + [3]=> + int(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(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]=> + int(2) + [2]=> + int(3) + [3]=> + int(4) +} +-- Innerloop Iteration 2 of Outerloop Iteration 6 -- +array(2) { + [2]=> + int(3) + [3]=> + int(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(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]=> + int(3) + [3]=> + int(4) +} +-- Innerloop Iteration 3 of Outerloop Iteration 6 -- +array(1) { + [3]=> + int(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(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]=> + int(4) +} +-- Innerloop Iteration 4 of Outerloop Iteration 6 -- +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) { +} + +Warning: Undefined variable $array_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +--- Outerloop Iteration 7 --- +bool(false) +bool(false) +bool(false) +bool(true) +bool(false) +bool(true) +-- Innerloop Iteration 1 of Outerloop Iteration 7 -- +array(2) { + [1]=> + float(2.5) + [2]=> + float(5.6) +} + +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]=> + float(2.5) + [2]=> + float(5.6) +} +-- Innerloop Iteration 2 of Outerloop Iteration 7 -- +array(1) { + [2]=> + float(5.6) +} + +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]=> + float(5.6) +} +-- Innerloop Iteration 3 of Outerloop Iteration 7 -- +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) { +} + +Warning: Undefined variable $array_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +--- Outerloop Iteration 8 --- +bool(false) +bool(false) +bool(false) +bool(true) +bool(false) +bool(true) +-- Innerloop Iteration 1 of Outerloop Iteration 8 -- +array(1) { + [2]=> + string(3) "two" +} + +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]=> + string(3) "two" +} +-- Innerloop Iteration 2 of Outerloop Iteration 8 -- +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) { +} + +Warning: Undefined variable $array_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +--- Outerloop Iteration 9 --- +bool(false) +bool(false) +bool(false) +bool(true) +bool(false) +bool(true) +-- Innerloop Iteration 1 of Outerloop Iteration 9 -- +array(1) { + ["Age"]=> + string(2) "30" +} + +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"]=> + string(2) "30" +} +-- Innerloop Iteration 2 of Outerloop Iteration 9 -- +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) { +} + +Warning: Undefined variable $array_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) +--- Outerloop Iteration 10 --- +bool(false) +bool(false) +bool(false) +bool(true) +bool(false) +bool(true) +-- Innerloop Iteration 1 of Outerloop Iteration 10 -- +array(4) { + [1]=> + int(2) + ["One"]=> + string(1) "1" + [2]=> + string(3) "two" + [""]=> + string(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(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]=> + int(2) + ["One"]=> + string(1) "1" + [2]=> + string(3) "two" + [""]=> + string(0) "" +} +-- Innerloop Iteration 2 of Outerloop Iteration 10 -- +array(3) { + ["One"]=> + string(1) "1" + [2]=> + string(3) "two" + [""]=> + string(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(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"]=> + string(1) "1" + [2]=> + string(3) "two" + [""]=> + string(0) "" +} +-- Innerloop Iteration 3 of Outerloop Iteration 10 -- +array(2) { + [2]=> + string(3) "two" + [""]=> + string(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(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]=> + string(3) "two" + [""]=> + string(0) "" +} +-- Innerloop Iteration 4 of Outerloop Iteration 10 -- +array(1) { + [""]=> + string(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(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) { + [""]=> + string(0) "" +} +-- Innerloop Iteration 5 of Outerloop Iteration 10 -- +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) { +} + +Warning: Undefined variable $array_var in %s on line %d +NULL +bool(false) +bool(false) +bool(true) + +*** Testing unset(), empty() & isset() with resource variables *** +-- Iteration 1 -- +resource(5) of type (stream) +bool(true) +bool(false) +bool(true) +resource(5) of type (stream) +bool(false) +bool(true) +bool(false) +bool(false) + +Warning: Undefined variable $resource in %s on line %d +NULL +-- Iteration 2 -- +resource(6) of type (stream) +bool(true) +bool(false) +bool(true) +resource(6) of type (stream) +bool(false) +bool(true) +bool(false) +bool(false) + +Warning: Undefined variable $resource in %s on line %d +NULL + +Warning: Undefined variable $resources in %s on line %d +NULL +bool(false) +bool(true) + +*** Testing unset(), empty() & isset() with objects *** +object(Point)#1 (3) { + ["x"]=> + int(30) + ["y"]=> + int(40) + ["lable"]=> + NULL +} +bool(true) +bool(false) + +Warning: Undefined variable $lable in %s on line %d +bool(false) + +Warning: Undefined variable $lable in %s on line %d +bool(true) + +Warning: Undefined variable $lable in %s on line %d +bool(false) + +Warning: Undefined variable $lable in %s on line %d +bool(true) +object(Point)#1 (3) { + ["x"]=> + int(30) + ["y"]=> + int(40) + ["lable"]=> + string(6) "Point1" +} +object(Point)#1 (2) { + ["y"]=> + int(40) + ["lable"]=> + string(6) "Point1" +} +bool(false) +bool(true) +object(Point)#1 (0) { +} +bool(true) +bool(false) +bool(false) +bool(true) + +Warning: Undefined variable $point1 in %s on line %d +NULL +bool(false) +bool(true) +bool(false) +bool(true) +array(3) { + [0]=> + string(11) "__construct" + [1]=> + string(8) "setLable" + [2]=> + string(9) "testPoint" +} +object(Point)#1 (3) { + ["x"]=> + int(5) + ["y"]=> + int(6) + ["lable"]=> + NULL +} + +*** Testing possible variation in operation for isset(), empty() & unset() *** + +** Testing unset() variation 1: unset on static variable inside a function ** +value of static_var before unset: 1 +bool(true) +bool(false) + +Warning: Undefined variable $static_var in %s on line %d +value of static_var after unset: +bool(false) +bool(true) +value of static_var after new assignment: 20 +value of static_var before unset: 2 +bool(true) +bool(false) + +Warning: Undefined variable $static_var in %s on line %d +value of static_var after unset: +bool(false) +bool(true) +value of static_var after new assignment: 20 +value of static_var before unset: 3 +bool(true) +bool(false) + +Warning: Undefined variable $static_var in %s on line %d +value of static_var after unset: +bool(false) +bool(true) +value of static_var after new assignment: 20 + +** Testing unset() variation 2: unset on a variable passed by ref. inside of a function ** +string(5) "value" +bool(false) +bool(true) +string(5) "value" + +** Testing unset() variation 3: unset on a global variable inside of a function ** +int(10) +bool(true) +bool(false) +bool(false) +bool(true) +int(10) diff --git a/Zend/tests/weakrefs/gh20073.phpt b/Zend/tests/weakrefs/gh20073.phpt new file mode 100644 index 0000000000000..b64c1a68d3cc0 --- /dev/null +++ b/Zend/tests/weakrefs/gh20073.phpt @@ -0,0 +1,15 @@ +--TEST-- +GH-20073 (Assertion failure in WeakMap offset operations on reference) +--FILE-- +offsetGet($obj)); +?> +--EXPECT-- +int(2) +int(2) diff --git a/Zend/tests/weakrefs/weakmap_by_ref_dimension_assign.phpt b/Zend/tests/weakrefs/weakmap_by_ref_dimension_assign.phpt new file mode 100644 index 0000000000000..6444de7eea6ba --- /dev/null +++ b/Zend/tests/weakrefs/weakmap_by_ref_dimension_assign.phpt @@ -0,0 +1,13 @@ +--TEST-- +By-ref assign of WeakMap dimension +--FILE-- + +--EXPECT-- +int(1) diff --git a/Zend/zend.c b/Zend/zend.c index 2d8a0f455f8b4..c46c8e9ada86c 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -38,6 +38,8 @@ #include "zend_call_stack.h" #include "zend_max_execution_timer.h" #include "zend_hrtime.h" +#include "zend_enum.h" +#include "zend_closures.h" #include "Optimizer/zend_optimizer.h" #include "php.h" #include "php_globals.h" @@ -553,7 +555,7 @@ static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent) /* } GC_PROTECT_RECURSION(Z_ARRVAL_P(expr)); } - print_hash(buf, Z_ARRVAL_P(expr), indent, 0); + print_hash(buf, Z_ARRVAL_P(expr), indent, false); GC_TRY_UNPROTECT_RECURSION(Z_ARRVAL_P(expr)); break; case IS_OBJECT: @@ -583,12 +585,12 @@ static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent) /* } if ((properties = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_DEBUG)) == NULL) { - print_hash(buf, (HashTable*) &zend_empty_array, indent, 1); + print_hash(buf, (HashTable*) &zend_empty_array, indent, true); break; } ZEND_GUARD_OR_GC_PROTECT_RECURSION(guard, DEBUG, zobj); - print_hash(buf, properties, indent, 1); + print_hash(buf, properties, indent, true); ZEND_GUARD_OR_GC_UNPROTECT_RECURSION(guard, DEBUG, zobj); zend_release_properties(properties); @@ -641,7 +643,7 @@ static FILE *zend_fopen_wrapper(zend_string *filename, zend_string **opened_path /* }}} */ #ifdef ZTS -static bool short_tags_default = 1; +static bool short_tags_default = true; static uint32_t compiler_options_default = ZEND_COMPILE_DEFAULT; #else # define short_tags_default 1 @@ -817,7 +819,7 @@ static void executor_globals_ctor(zend_executor_globals *executor_globals) /* {{ executor_globals->saved_fpu_cw = 0; #endif executor_globals->saved_fpu_cw_ptr = NULL; - executor_globals->active = 0; + executor_globals->active = false; executor_globals->bailout = NULL; executor_globals->error_handling = EH_NORMAL; executor_globals->exception_class = NULL; @@ -910,7 +912,7 @@ static bool php_auto_globals_create_globals(zend_string *name) /* {{{ */ { /* While we keep registering $GLOBALS as an auto-global, we do not create an * actual variable for it. Access to it handled specially by the compiler. */ - return 0; + return false; } /* }}} */ @@ -1026,7 +1028,7 @@ void zend_startup(zend_utility_functions *utility_functions) /* {{{ */ executor_globals = ts_resource(executor_globals_id); compiler_globals_dtor(compiler_globals); - compiler_globals->in_compilation = 0; + compiler_globals->in_compilation = false; compiler_globals->function_table = (HashTable *) malloc(sizeof(HashTable)); compiler_globals->class_table = (HashTable *) malloc(sizeof(HashTable)); @@ -1054,6 +1056,7 @@ void zend_startup(zend_utility_functions *utility_functions) /* {{{ */ ZVAL_UNDEF(&EG(last_fatal_error_backtrace)); zend_interned_strings_init(); + zend_object_handlers_startup(); zend_startup_builtin_functions(); zend_register_standard_constants(); zend_register_auto_global(zend_string_init_interned("GLOBALS", sizeof("GLOBALS") - 1, 1), 1, php_auto_globals_create_globals); @@ -1077,6 +1080,9 @@ void zend_startup(zend_utility_functions *utility_functions) /* {{{ */ tsrm_set_new_thread_end_handler(zend_new_thread_end_handler); tsrm_set_shutdown_handler(zend_interned_strings_dtor); #endif + + zend_enum_startup(); + zend_closure_startup(); } /* }}} */ @@ -1275,9 +1281,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 +1459,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 +1494,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. @@ -1472,12 +1507,10 @@ ZEND_API ZEND_COLD void zend_error_zstr_at( /* Report about uncaught exception in case of fatal errors */ if (EG(exception)) { - zend_execute_data *ex; - const zend_op *opline; - if (type & E_FATAL_ERRORS) { - ex = EG(current_execute_data); - opline = NULL; + zend_execute_data *ex = EG(current_execute_data); + const zend_op *opline = NULL; + while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) { ex = ex->prev_execute_data; } @@ -1752,15 +1785,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..8957241ccfb37 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.5.0-dev" +#define ZEND_VERSION "4.6.0-dev" #define ZEND_ENGINE_3 @@ -152,11 +152,12 @@ struct _zend_class_entry { zend_class_entry *parent; zend_string *parent_name; }; - int refcount; + uint32_t refcount; uint32_t ce_flags; + uint32_t ce_flags2; int default_properties_count; - int default_static_members_count; + uint32_t default_static_members_count; zval *default_properties_table; zval *default_static_members_table; ZEND_MAP_PTR_DEF(zval *, static_members_table); @@ -441,9 +442,10 @@ typedef struct { BEGIN_EXTERN_C() ZEND_API void zend_save_error_handling(zend_error_handling *current); ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current); -ZEND_API void zend_restore_error_handling(zend_error_handling *saved); +ZEND_API void zend_restore_error_handling(const 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 5262cc0b6c95f..0881a169dfa7d 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -20,6 +20,7 @@ */ #include "zend.h" +#include "zend_compile.h" #include "zend_execute.h" #include "zend_API.h" #include "zend_hash.h" @@ -76,28 +77,6 @@ ZEND_API zend_result zend_get_parameters_array_ex(uint32_t param_count, zval *ar } /* }}} */ -ZEND_API zend_result zend_copy_parameters_array(uint32_t param_count, zval *argument_array) /* {{{ */ -{ - zval *param_ptr; - uint32_t arg_count; - - param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1); - arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data)); - - if (param_count>arg_count) { - return FAILURE; - } - - while (param_count-->0) { - Z_TRY_ADDREF_P(param_ptr); - zend_hash_next_index_insert_new(Z_ARRVAL_P(argument_array), param_ptr); - param_ptr++; - } - - return SUCCESS; -} -/* }}} */ - ZEND_API ZEND_COLD void zend_wrong_param_count(void) /* {{{ */ { const char *space; @@ -107,7 +86,7 @@ ZEND_API ZEND_COLD void zend_wrong_param_count(void) /* {{{ */ } /* }}} */ -ZEND_API ZEND_COLD void zend_wrong_property_read(zval *object, zval *property) +ZEND_API ZEND_COLD void zend_wrong_property_read(const zval *object, zval *property) { zend_string *tmp_property_name; zend_string *property_name = zval_get_tmp_string(property, &tmp_property_name); @@ -247,7 +226,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_error(uint32_t } /* }}} */ -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_error(int error_code, uint32_t num, char *name, zend_expected_type expected_type, zval *arg) /* {{{ */ +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_error(int error_code, uint32_t num, char *name, zend_expected_type expected_type, const zval *arg) /* {{{ */ { switch (error_code) { case ZPP_ERROR_WRONG_CALLBACK: @@ -288,7 +267,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_error(int error_code, } /* }}} */ -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_error(uint32_t num, zend_expected_type expected_type, zval *arg) /* {{{ */ +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_error(uint32_t num, zend_expected_type expected_type, const zval *arg) /* {{{ */ { static const char * const expected_error[] = { Z_EXPECTED_TYPES(Z_EXPECTED_TYPE_STR) @@ -309,7 +288,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_error(uint32_t n } /* }}} */ -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(uint32_t num, const char *name, zval *arg) /* {{{ */ +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(uint32_t num, const char *name, const zval *arg) /* {{{ */ { if (EG(exception)) { return; @@ -319,7 +298,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(uint32_t } /* }}} */ -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_null_error(uint32_t num, const char *name, zval *arg) /* {{{ */ +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_null_error(uint32_t num, const char *name, const zval *arg) /* {{{ */ { if (EG(exception)) { return; @@ -329,7 +308,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_null_error(u } /* }}} */ -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_long_error(uint32_t num, const char *name, zval *arg) /* {{{ */ +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_long_error(uint32_t num, const char *name, const zval *arg) /* {{{ */ { if (EG(exception)) { return; @@ -339,7 +318,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_long_error(u } /* }}} */ -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_long_or_null_error(uint32_t num, const char *name, zval *arg) /* {{{ */ +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_long_or_null_error(uint32_t num, const char *name, const zval *arg) /* {{{ */ { if (EG(exception)) { return; @@ -349,7 +328,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_long_or_null } /* }}} */ -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_string_error(uint32_t num, const char *name, zval *arg) /* {{{ */ +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_string_error(uint32_t num, const char *name, const zval *arg) /* {{{ */ { if (EG(exception)) { return; @@ -359,7 +338,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_string_error } /* }}} */ -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_string_or_null_error(uint32_t num, const char *name, zval *arg) /* {{{ */ +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_string_or_null_error(uint32_t num, const char *name, const zval *arg) /* {{{ */ { if (EG(exception)) { return; @@ -452,7 +431,7 @@ ZEND_API ZEND_COLD void zend_argument_must_not_be_empty_error(uint32_t arg_num) zend_argument_value_error(arg_num, "must not be empty"); } -ZEND_API ZEND_COLD void zend_class_redeclaration_error_ex(int type, zend_string *new_name, zend_class_entry *old_ce) +ZEND_API ZEND_COLD void zend_class_redeclaration_error_ex(int type, zend_string *new_name, const zend_class_entry *old_ce) { if (old_ce->type == ZEND_INTERNAL_CLASS) { zend_error(type, "Cannot redeclare %s %s", @@ -467,7 +446,7 @@ ZEND_API ZEND_COLD void zend_class_redeclaration_error_ex(int type, zend_string } } -ZEND_API ZEND_COLD void zend_class_redeclaration_error(int type, zend_class_entry *old_ce) +ZEND_API ZEND_COLD void zend_class_redeclaration_error(int type, const zend_class_entry *old_ce) { zend_class_redeclaration_error_ex(type, old_ce->name, old_ce); } @@ -502,7 +481,7 @@ ZEND_API bool ZEND_FASTCALL zend_parse_arg_class(zval *arg, zend_class_entry **p /* }}} */ static ZEND_COLD bool zend_null_arg_deprecated(const char *fallback_type, uint32_t arg_num) { - zend_function *func = zend_active_function(); + const zend_function *func = zend_active_function(); ZEND_ASSERT(arg_num > 0); uint32_t arg_offset = arg_num - 1; if (arg_offset >= func->common.num_args) { @@ -510,7 +489,7 @@ static ZEND_COLD bool zend_null_arg_deprecated(const char *fallback_type, uint32 arg_offset = func->common.num_args; } - zend_arg_info *arg_info = &func->common.arg_info[arg_offset]; + const zend_arg_info *arg_info = &func->common.arg_info[arg_offset]; zend_string *func_name = get_active_function_or_method_name(); const char *arg_name = get_active_function_arg_name(arg_num); @@ -614,9 +593,6 @@ ZEND_API bool ZEND_FASTCALL zend_parse_arg_long_weak(const zval *arg, zend_long return 0; } } - if (UNEXPECTED(EG(exception))) { - return 0; - } } else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) { if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("int", arg_num)) { return 0; @@ -663,9 +639,6 @@ ZEND_API bool ZEND_FASTCALL zend_parse_arg_double_weak(const zval *arg, double * return 0; } } - if (UNEXPECTED(EG(exception))) { - return 0; - } } else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) { if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("float", arg_num)) { return 0; @@ -818,8 +791,8 @@ static const char *zend_parse_arg_impl(zval *arg, va_list *va, const char **spec { const char *spec_walk = *spec; char c = *spec_walk++; - bool check_null = 0; - bool separate = 0; + bool check_null = false; + bool separate = false; zval *real_arg = arg; /* scan through modifiers */ @@ -828,9 +801,9 @@ static const char *zend_parse_arg_impl(zval *arg, va_list *va, const char **spec if (*spec_walk == '/') { SEPARATE_ZVAL_NOREF(arg); real_arg = arg; - separate = 1; + separate = true; } else if (*spec_walk == '!') { - check_null = 1; + check_null = true; } else { break; } @@ -1140,7 +1113,7 @@ ZEND_API zend_result zend_parse_parameter(int flags, uint32_t arg_num, zval *arg } static ZEND_COLD void zend_parse_parameters_debug_error(const char *msg) { - zend_function *active_function = EG(current_execute_data)->func; + const zend_function *active_function = EG(current_execute_data)->func; const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : ""; zend_error_noreturn(E_CORE_ERROR, "%s%s%s(): %s", @@ -1157,8 +1130,8 @@ static zend_result zend_parse_va_args(uint32_t num_args, const char *type_spec, uint32_t max_num_args = 0; uint32_t post_varargs = 0; zval *arg; - bool have_varargs = 0; - bool have_optional_args = 0; + bool have_varargs = false; + bool have_optional_args = false; zval **varargs = NULL; uint32_t *n_varargs = NULL; @@ -1180,7 +1153,7 @@ static zend_result zend_parse_va_args(uint32_t num_args, const char *type_spec, case '|': min_num_args = max_num_args; - have_optional_args = 1; + have_optional_args = true; break; case '/': @@ -1195,7 +1168,7 @@ static zend_result zend_parse_va_args(uint32_t num_args, const char *type_spec, "only one varargs specifier (* or +) is permitted"); return FAILURE; } - have_varargs = 1; + have_varargs = true; /* we expect at least one parameter in varargs */ if (c == '+') { max_num_args++; @@ -1396,7 +1369,7 @@ ZEND_API zend_result zend_parse_method_parameters_ex(int flags, uint32_t num_arg /* This function should be called after the constructor has been called * because it may call __set from the uninitialized object otherwise. */ -ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */ +ZEND_API void zend_merge_properties(const zval *obj, const HashTable *properties) /* {{{ */ { zend_object *zobj = Z_OBJ_P(obj); zend_object_write_property_t write_property = zobj->handlers->write_property; @@ -1418,7 +1391,7 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */ } /* }}} */ -static zend_class_mutable_data *zend_allocate_mutable_data(zend_class_entry *class_type) /* {{{ */ +static zend_class_mutable_data *zend_allocate_mutable_data(const zend_class_entry *class_type) /* {{{ */ { zend_class_mutable_data *mutable_data; @@ -1434,7 +1407,7 @@ static zend_class_mutable_data *zend_allocate_mutable_data(zend_class_entry *cla } /* }}} */ -ZEND_API HashTable *zend_separate_class_constants_table(zend_class_entry *class_type) /* {{{ */ +ZEND_API HashTable *zend_separate_class_constants_table(const zend_class_entry *class_type) /* {{{ */ { zend_class_mutable_data *mutable_data; HashTable *constants_table; @@ -1474,7 +1447,7 @@ ZEND_API HashTable *zend_separate_class_constants_table(zend_class_entry *class_ return constants_table; } -static zend_result update_property(zval *val, zend_property_info *prop_info) { +static zend_result update_property(zval *val, const zend_property_info *prop_info) { if (ZEND_TYPE_IS_SET(prop_info->type)) { zval tmp; @@ -1520,6 +1493,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; } @@ -1706,10 +1682,9 @@ ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properti if (object->ce->default_properties_count) { zval *prop; zend_string *key; - zend_property_info *property_info; ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(properties, key, prop) { - property_info = zend_get_property_info(object->ce, key, 1); + const zend_property_info *property_info = zend_get_property_info(object->ce, key, 1); if (property_info != ZEND_WRONG_PROPERTY_INFO && property_info && (property_info->flags & ZEND_ACC_STATIC) == 0) { @@ -1733,12 +1708,12 @@ ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properti } /* }}} */ -ZEND_API void object_properties_load(zend_object *object, HashTable *properties) /* {{{ */ +ZEND_API void object_properties_load(zend_object *object, const HashTable *properties) /* {{{ */ { zval *prop, tmp; zend_string *key; zend_long h; - zend_property_info *property_info; + const zend_property_info *property_info; ZEND_HASH_FOREACH_KEY_VAL(properties, h, key, prop) { if (key) { @@ -1766,6 +1741,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); @@ -2244,9 +2227,6 @@ ZEND_API zend_result array_set_zval_key(HashTable *ht, zval *key, zval *value) / case IS_STRING: result = zend_symtable_update(ht, Z_STR_P(key), value); break; - case IS_NULL: - result = zend_hash_update(ht, ZSTR_EMPTY_ALLOC(), value); - break; case IS_RESOURCE: zend_use_resource_as_offset(key); result = zend_hash_index_update(ht, Z_RES_HANDLE_P(key), value); @@ -2263,6 +2243,13 @@ ZEND_API zend_result array_set_zval_key(HashTable *ht, zval *key, zval *value) / case IS_DOUBLE: result = zend_hash_index_update(ht, zend_dval_to_lval_safe(Z_DVAL_P(key)), value); break; + case IS_NULL: + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (UNEXPECTED(EG(exception))) { + return FAILURE; + } + result = zend_hash_update(ht, ZSTR_EMPTY_ALLOC(), value); + break; default: zend_illegal_container_offset(ZSTR_KNOWN(ZEND_STR_ARRAY), key, BP_VAR_W); result = NULL; @@ -2777,7 +2764,7 @@ static void zend_check_magic_method_no_return_type( } } -ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, const zend_function *fptr, zend_string *lcname, int error_type) /* {{{ */ +ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, const zend_function *fptr, const zend_string *lcname, int error_type) /* {{{ */ { if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') { @@ -2874,7 +2861,7 @@ ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, } /* }}} */ -ZEND_API void zend_add_magic_method(zend_class_entry *ce, zend_function *fptr, zend_string *lcname) +ZEND_API void zend_add_magic_method(zend_class_entry *ce, zend_function *fptr, const zend_string *lcname) { if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') { /* pass */ @@ -2941,6 +2928,80 @@ static zend_always_inline void zend_normalize_internal_type(zend_type *type) { } ZEND_TYPE_FOREACH_END(); } +static void zend_convert_internal_arg_info_type(zend_type *type, bool persistent) +{ + if (ZEND_TYPE_HAS_LITERAL_NAME(*type)) { + // gen_stubs.php does not support codegen for compound types. As a + // temporary workaround, we support union types by splitting + // the type name on `|` characters if necessary. + const char *class_name = ZEND_TYPE_LITERAL_NAME(*type); + type->type_mask &= ~_ZEND_TYPE_LITERAL_NAME_BIT; + + size_t num_types = 1; + const char *p = class_name; + while ((p = strchr(p, '|'))) { + num_types++; + p++; + } + + if (num_types == 1) { + /* Simple class type */ + zend_string *str = zend_string_init_interned(class_name, strlen(class_name), persistent); + zend_alloc_ce_cache(str); + ZEND_TYPE_SET_PTR(*type, str); + type->type_mask |= _ZEND_TYPE_NAME_BIT; + } else { + /* Union type */ + zend_type_list *list = pemalloc(ZEND_TYPE_LIST_SIZE(num_types), persistent); + list->num_types = num_types; + ZEND_TYPE_SET_LIST(*type, list); + ZEND_TYPE_FULL_MASK(*type) |= _ZEND_TYPE_UNION_BIT; + + const char *start = class_name; + uint32_t j = 0; + while (true) { + const char *end = strchr(start, '|'); + zend_string *str = zend_string_init_interned(start, end ? end - start : strlen(start), persistent); + zend_alloc_ce_cache(str); + list->types[j] = (zend_type) ZEND_TYPE_INIT_CLASS(str, 0, 0); + if (!end) { + break; + } + start = end + 1; + j++; + } + } + } + if (ZEND_TYPE_IS_ITERABLE_FALLBACK(*type)) { + /* Warning generated an extension load warning which is emitted for every test + zend_error(E_CORE_WARNING, "iterable type is now a compile time alias for array|Traversable," + " regenerate the argument info via the php-src gen_stub build script"); + */ + zend_type legacy_iterable = ZEND_TYPE_INIT_CLASS_MASK( + ZSTR_KNOWN(ZEND_STR_TRAVERSABLE), + (type->type_mask | MAY_BE_ARRAY) + ); + *type = legacy_iterable; + } +} + +ZEND_API void zend_convert_internal_arg_info(zend_arg_info *new_arg_info, const zend_internal_arg_info *arg_info, bool is_return_info, bool persistent) +{ + if (!is_return_info) { + new_arg_info->name = zend_string_init_interned(arg_info->name, strlen(arg_info->name), persistent); + if (arg_info->default_value) { + new_arg_info->default_value = zend_string_init_interned(arg_info->default_value, strlen(arg_info->default_value), persistent); + } else { + new_arg_info->default_value = NULL; + } + } else { + new_arg_info->name = NULL; + new_arg_info->default_value = NULL; + } + new_arg_info->type = arg_info->type; + zend_convert_internal_arg_info_type(&new_arg_info->type, persistent); +} + /* registers all functions in *library_functions in the function hash */ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type) /* {{{ */ { @@ -2952,6 +3013,7 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend int error_type; zend_string *lowercase_name; size_t fname_len; + const zend_internal_arg_info *internal_arg_info; if (type==MODULE_PERSISTENT) { error_type = E_CORE_WARNING; @@ -3008,7 +3070,7 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend if (ptr->arg_info) { zend_internal_function_info *info = (zend_internal_function_info*)ptr->arg_info; - internal_function->arg_info = (zend_internal_arg_info*)ptr->arg_info+1; + internal_arg_info = ptr->arg_info+1; internal_function->num_args = ptr->num_args; /* Currently you cannot denote that the function can accept less arguments than num_args */ if (info->required_num_args == (uintptr_t)-1) { @@ -3038,7 +3100,7 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend zend_error(E_CORE_WARNING, "Missing arginfo for %s%s%s()", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname); - internal_function->arg_info = NULL; + internal_arg_info = NULL; internal_function->num_args = 0; internal_function->required_num_args = 0; } @@ -3049,13 +3111,11 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend !(internal_function->fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) { zend_error(E_CORE_WARNING, "%s::__toString() implemented without string return type", ZSTR_VAL(scope->name)); - internal_function->arg_info = (zend_internal_arg_info *) arg_info_toString + 1; + internal_arg_info = (zend_internal_arg_info *) arg_info_toString + 1; internal_function->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE; internal_function->num_args = internal_function->required_num_args = 0; } - - zend_set_function_arg_flags((zend_function*)internal_function); if (ptr->flags & ZEND_ACC_ABSTRACT) { if (scope) { /* This is a class that must be abstract itself. Here we set the check info. */ @@ -3120,17 +3180,17 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend } /* If types of arguments have to be checked */ - if (reg_function->arg_info && num_args) { + if (internal_arg_info && num_args) { uint32_t i; for (i = 0; i < num_args; i++) { - zend_internal_arg_info *arg_info = ®_function->arg_info[i]; + const zend_internal_arg_info *arg_info = &internal_arg_info[i]; ZEND_ASSERT(arg_info->name && "Parameter must have a name"); if (ZEND_TYPE_IS_SET(arg_info->type)) { reg_function->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS; } #if ZEND_DEBUG for (uint32_t j = 0; j < i; j++) { - if (!strcmp(arg_info->name, reg_function->arg_info[j].name)) { + if (!strcmp(arg_info->name, internal_arg_info[j].name)) { zend_error_noreturn(E_CORE_ERROR, "Duplicate parameter name $%s for function %s%s%s()", arg_info->name, scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname); @@ -3140,78 +3200,24 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend } } - /* Rebuild arginfos if parameter/property types and/or a return type are used */ - if (reg_function->arg_info && - (reg_function->fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS))) { - /* convert "const char*" class type names into "zend_string*" */ + /* Convert zend_internal_arg_info to zend_arg_info */ + if (internal_arg_info) { uint32_t i; - zend_internal_arg_info *arg_info = reg_function->arg_info - 1; - zend_internal_arg_info *new_arg_info; + const zend_internal_arg_info *arg_info = internal_arg_info - 1; + zend_arg_info *new_arg_info; /* Treat return type as an extra argument */ num_args++; - new_arg_info = malloc(sizeof(zend_internal_arg_info) * num_args); - memcpy(new_arg_info, arg_info, sizeof(zend_internal_arg_info) * num_args); + new_arg_info = malloc(sizeof(zend_arg_info) * num_args); reg_function->arg_info = new_arg_info + 1; for (i = 0; i < num_args; i++) { - if (ZEND_TYPE_HAS_LITERAL_NAME(new_arg_info[i].type)) { - // gen_stubs.php does not support codegen for DNF types in arg infos. - // As a temporary workaround, we split the type name on `|` characters, - // converting it to an union type if necessary. - const char *class_name = ZEND_TYPE_LITERAL_NAME(new_arg_info[i].type); - new_arg_info[i].type.type_mask &= ~_ZEND_TYPE_LITERAL_NAME_BIT; - - size_t num_types = 1; - const char *p = class_name; - while ((p = strchr(p, '|'))) { - num_types++; - p++; - } - - if (num_types == 1) { - /* Simple class type */ - zend_string *str = zend_string_init_interned(class_name, strlen(class_name), 1); - zend_alloc_ce_cache(str); - ZEND_TYPE_SET_PTR(new_arg_info[i].type, str); - new_arg_info[i].type.type_mask |= _ZEND_TYPE_NAME_BIT; - } else { - /* Union type */ - zend_type_list *list = malloc(ZEND_TYPE_LIST_SIZE(num_types)); - list->num_types = num_types; - ZEND_TYPE_SET_LIST(new_arg_info[i].type, list); - ZEND_TYPE_FULL_MASK(new_arg_info[i].type) |= _ZEND_TYPE_UNION_BIT; - - const char *start = class_name; - uint32_t j = 0; - while (true) { - const char *end = strchr(start, '|'); - zend_string *str = zend_string_init_interned(start, end ? end - start : strlen(start), 1); - zend_alloc_ce_cache(str); - list->types[j] = (zend_type) ZEND_TYPE_INIT_CLASS(str, 0, 0); - if (!end) { - break; - } - start = end + 1; - j++; - } - } - } - if (ZEND_TYPE_IS_ITERABLE_FALLBACK(new_arg_info[i].type)) { - /* Warning generated an extension load warning which is emitted for every test - zend_error(E_CORE_WARNING, "iterable type is now a compile time alias for array|Traversable," - " regenerate the argument info via the php-src gen_stub build script"); - */ - zend_type legacy_iterable = ZEND_TYPE_INIT_CLASS_MASK( - ZSTR_KNOWN(ZEND_STR_TRAVERSABLE), - (new_arg_info[i].type.type_mask | MAY_BE_ARRAY) - ); - new_arg_info[i].type = legacy_iterable; - } - - zend_normalize_internal_type(&new_arg_info[i].type); + zend_convert_internal_arg_info(&new_arg_info[i], &arg_info[i], + i == 0, true); } } + zend_set_function_arg_flags((zend_function*)reg_function); + if (scope) { zend_check_magic_method_implementation( scope, (zend_function *)reg_function, lowercase_name, E_CORE_ERROR); @@ -3291,7 +3297,7 @@ static void clean_module_classes(int module_number) /* {{{ */ /* Child classes may reuse structures from parent classes, so destroy in reverse order. */ Bucket *bucket; ZEND_HASH_REVERSE_FOREACH_BUCKET(EG(class_table), bucket) { - zend_class_entry *ce = Z_CE(bucket->val); + const zend_class_entry *ce = Z_CE(bucket->val); if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module->module_number == module_number) { zend_hash_del_bucket(EG(class_table), bucket); } @@ -3302,8 +3308,8 @@ static void clean_module_classes(int module_number) /* {{{ */ static int clean_module_function(zval *el, void *arg) /* {{{ */ { - zend_function *fe = (zend_function *) Z_PTR_P(el); - zend_module_entry *module = (zend_module_entry *) arg; + const zend_function *fe = (zend_function *) Z_PTR_P(el); + const zend_module_entry *module = arg; if (fe->common.type == ZEND_INTERNAL_FUNCTION && fe->internal_function.module == module) { return ZEND_HASH_APPLY_REMOVE; } else { @@ -3391,7 +3397,7 @@ ZEND_API void zend_activate_modules(void) /* {{{ */ zend_module_entry **p = module_request_startup_handlers; while (*p) { - zend_module_entry *module = *p; + const zend_module_entry *module = *p; if (module->request_startup_func(module->type, module->module_number)==FAILURE) { zend_error(E_WARNING, "request_startup() for %s module failed", module->name); @@ -3420,7 +3426,7 @@ ZEND_API void zend_deactivate_modules(void) /* {{{ */ zend_module_entry **p = module_request_shutdown_handlers; while (*p) { - zend_module_entry *module = *p; + const zend_module_entry *module = *p; zend_try { module->request_shutdown_func(module->type, module->module_number); } zend_end_try(); @@ -3469,7 +3475,7 @@ ZEND_API void zend_post_deactivate_modules(void) /* {{{ */ zend_module_entry **p = module_post_deactivate_handlers; while (*p) { - zend_module_entry *module = *p; + const zend_module_entry *module = *p; module->post_deactivate_func(); p++; @@ -3485,7 +3491,7 @@ ZEND_API int zend_next_free_module(void) /* {{{ */ } /* }}} */ -static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, uint32_t ce_flags) /* {{{ */ +static zend_class_entry *do_register_internal_class(const zend_class_entry *orig_class_entry, uint32_t ce_flags) /* {{{ */ { zend_class_entry *class_entry = malloc(sizeof(zend_class_entry)); zend_string *lowercase_name; @@ -3521,14 +3527,14 @@ static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class * If both parent_ce and parent_name are NULL it does a regular class registration * If parent_name is specified but not found NULL is returned */ -ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce) /* {{{ */ +ZEND_API zend_class_entry *zend_register_internal_class_ex(const zend_class_entry *class_entry, zend_class_entry *parent_ce) /* {{{ */ { return zend_register_internal_class_with_flags(class_entry, parent_ce, 0); } /* }}} */ ZEND_API zend_class_entry *zend_register_internal_class_with_flags( - zend_class_entry *class_entry, + const zend_class_entry *class_entry, zend_class_entry *parent_ce, uint32_t ce_flags ) { @@ -3566,13 +3572,13 @@ ZEND_API void zend_class_implements(zend_class_entry *class_entry, int num_inter /* A class that contains at least one abstract method automatically becomes an abstract class. */ -ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_class_entry) /* {{{ */ +ZEND_API zend_class_entry *zend_register_internal_class(const zend_class_entry *orig_class_entry) /* {{{ */ { return do_register_internal_class(orig_class_entry, 0); } /* }}} */ -ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *orig_class_entry) /* {{{ */ +ZEND_API zend_class_entry *zend_register_internal_interface(const zend_class_entry *orig_class_entry) /* {{{ */ { return do_register_internal_class(orig_class_entry, ZEND_ACC_INTERFACE); } @@ -3585,7 +3591,7 @@ ZEND_API zend_result zend_register_class_alias_ex(const char *name, size_t name_ /* TODO: Move this out of here in 7.4. */ if (persistent && EG(current_module) && EG(current_module)->type == MODULE_TEMPORARY) { - persistent = 0; + persistent = false; } if (name[0] == '\\') { @@ -3619,29 +3625,6 @@ ZEND_API zend_result zend_register_class_alias_ex(const char *name, size_t name_ } /* }}} */ -// TODO num_symbol_tables as unsigned int? -ZEND_API zend_result zend_set_hash_symbol(zval *symbol, const char *name, size_t name_length, bool is_ref, int num_symbol_tables, ...) /* {{{ */ -{ - HashTable *symbol_table; - va_list symbol_table_list; - - if (num_symbol_tables <= 0) return FAILURE; - - if (is_ref) { - ZVAL_MAKE_REF(symbol); - } - - va_start(symbol_table_list, num_symbol_tables); - while (num_symbol_tables-- > 0) { - symbol_table = va_arg(symbol_table_list, HashTable *); - zend_hash_str_update(symbol_table, name, name_length, symbol); - Z_TRY_ADDREF_P(symbol); - } - va_end(symbol_table_list); - return SUCCESS; -} -/* }}} */ - /* Disabled functions support */ static void zend_disable_function(const char *function_name, size_t function_name_length) @@ -3692,85 +3675,14 @@ 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) +static zend_always_inline zend_class_entry *get_scope(const zend_execute_data *frame) { return frame && frame->func ? frame->func->common.scope : NULL; } -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) /* {{{ */ +static bool zend_is_callable_check_class(zend_string *name, zend_class_entry *scope, const 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; @@ -3779,7 +3691,7 @@ static bool zend_is_callable_check_class(zend_string *name, zend_class_entry *sc ZSTR_ALLOCA_ALLOC(lcname, name_len, use_heap); zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(name), name_len); - *strict_class = 0; + *strict_class = false; if (zend_string_equals(lcname, ZSTR_KNOWN(ZEND_STR_SELF))) { if (!scope) { if (error) *error = estrdup("cannot access \"self\" when no class scope is active"); @@ -3795,7 +3707,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,8 +3726,8 @@ static bool zend_is_callable_check_class(zend_string *name, zend_class_entry *sc if (!fcc->object) { fcc->object = zend_get_this_object(frame); } - *strict_class = 1; - ret = 1; + *strict_class = true; + ret = true; } } else if (zend_string_equals(lcname, ZSTR_KNOWN(ZEND_STR_STATIC))) { zend_class_entry *called_scope = zend_get_called_scope(frame); @@ -3831,18 +3743,18 @@ static bool zend_is_callable_check_class(zend_string *name, zend_class_entry *sc if (!fcc->object) { fcc->object = zend_get_this_object(frame); } - *strict_class = 1; - ret = 1; + *strict_class = true; + ret = true; } } else if ((ce = zend_lookup_class(name)) != NULL) { - zend_class_entry *scope = get_scope(frame); + const zend_class_entry *frame_scope = get_scope(frame); fcc->calling_scope = ce; - if (scope && !fcc->object) { + if (frame_scope && !fcc->object) { zend_object *object = zend_get_this_object(frame); if (object && - instanceof_function(object->ce, scope) && - instanceof_function(scope, ce)) { + instanceof_function(object->ce, frame_scope) && + instanceof_function(frame_scope, ce)) { fcc->object = object; fcc->called_scope = object->ce; } else { @@ -3851,8 +3763,8 @@ static bool zend_is_callable_check_class(zend_string *name, zend_class_entry *sc } else { fcc->called_scope = fcc->object ? fcc->object->ce : ce; } - *strict_class = 1; - ret = 1; + *strict_class = true; + ret = true; } else { if (error) zend_spprintf(error, 0, "class \"%.*s\" not found", (int)name_len, ZSTR_VAL(name)); } @@ -3872,10 +3784,10 @@ ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc) { } } -static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_execute_data *frame, zend_fcall_info_cache *fcc, bool strict_class, char **error, bool suppress_deprecation) /* {{{ */ +static zend_always_inline bool zend_is_callable_check_func(const zval *callable, const zend_execute_data *frame, zend_fcall_info_cache *fcc, bool strict_class, char **error, bool suppress_deprecation) /* {{{ */ { zend_class_entry *ce_org = fcc->calling_scope; - bool retval = 0; + bool retval = false; zend_string *mname, *cname; zend_string *lmname; const char *colon; @@ -3957,7 +3869,7 @@ static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_ } else { fcc->called_scope = fcc->object ? fcc->object->ce : fcc->calling_scope; } - strict_class = 1; + strict_class = true; } else if (!zend_is_callable_check_class(cname, scope, frame, fcc, &strict_class, error, suppress_deprecation || ce_org != NULL)) { zend_string_release_ex(cname, 0); return 0; @@ -3995,11 +3907,11 @@ static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_ zend_string_equals_literal(lmname, ZEND_CONSTRUCTOR_FUNC_NAME)) { fcc->function_handler = fcc->calling_scope->constructor; if (fcc->function_handler) { - retval = 1; + retval = true; } } else if ((zv = zend_hash_find(ftable, lmname)) != NULL) { fcc->function_handler = Z_PTR_P(zv); - retval = 1; + retval = true; if ((fcc->function_handler->op_array.fn_flags & ZEND_ACC_CHANGED) && !strict_class) { scope = get_scope(frame); @@ -4024,7 +3936,7 @@ static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_ scope = get_scope(frame); ZEND_ASSERT(!(fcc->function_handler->common.fn_flags & ZEND_ACC_PUBLIC)); if (!zend_check_method_accessible(fcc->function_handler, scope)) { - retval = 0; + retval = false; fcc->function_handler = NULL; goto get_function_via_handler; } @@ -4033,9 +3945,9 @@ static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_ get_function_via_handler: if (fcc->object && fcc->calling_scope == ce_org) { if (strict_class && ce_org->__call) { - fcc->function_handler = zend_get_call_trampoline_func(ce_org, mname, 0); + fcc->function_handler = zend_get_call_trampoline_func(ce_org->__call, mname); call_via_handler = 1; - retval = 1; + retval = true; } else { fcc->function_handler = fcc->object->handlers->get_method(&fcc->object, mname, NULL); if (fcc->function_handler) { @@ -4044,7 +3956,7 @@ static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_ !instanceof_function(ce_org, fcc->function_handler->common.scope))) { zend_release_fcall_info_cache(fcc); } else { - retval = 1; + retval = true; call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0; } } @@ -4056,7 +3968,7 @@ static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_ fcc->function_handler = zend_std_get_static_method(fcc->calling_scope, mname, NULL); } if (fcc->function_handler) { - retval = 1; + retval = true; call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0; if (call_via_handler && !fcc->object) { zend_object *object = zend_get_this_object(frame); @@ -4072,12 +3984,12 @@ static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_ if (retval) { if (fcc->calling_scope && !call_via_handler) { if (fcc->function_handler->common.fn_flags & ZEND_ACC_ABSTRACT) { - retval = 0; + retval = false; if (error) { zend_spprintf(error, 0, "cannot call abstract method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name)); } } else if (!fcc->object && !(fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) { - retval = 0; + retval = false; if (error) { zend_spprintf(error, 0, "non-static method %s::%s() cannot be called statically", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name)); } @@ -4093,7 +4005,7 @@ static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_ } 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; + retval = false; } } } @@ -4118,7 +4030,7 @@ static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_ } /* }}} */ -ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, zend_object *object) /* {{{ */ +ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, const zend_object *object) /* {{{ */ { try_again: switch (Z_TYPE_P(callable)) { @@ -4130,8 +4042,8 @@ ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, zend_object *obj case IS_ARRAY: { - zval *method = NULL; - zval *obj = NULL; + const zval *method = NULL; + const zval *obj = NULL; if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) { obj = zend_hash_index_find_deref(Z_ARRVAL_P(callable), 0); @@ -4152,7 +4064,7 @@ ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, zend_object *obj } case IS_OBJECT: { - zend_class_entry *ce = Z_OBJCE_P(callable); + const zend_class_entry *ce = Z_OBJCE_P(callable); if (ce == zend_ce_closure) { const zend_function *fn = zend_get_closure_method_def(Z_OBJ_P(callable)); @@ -4183,12 +4095,12 @@ ZEND_API zend_string *zend_get_callable_name(zval *callable) /* {{{ */ /* }}} */ ZEND_API bool zend_is_callable_at_frame( - zval *callable, zend_object *object, zend_execute_data *frame, + const zval *callable, zend_object *object, const zend_execute_data *frame, uint32_t check_flags, zend_fcall_info_cache *fcc, char **error) /* {{{ */ { bool ret; zend_fcall_info_cache fcc_local; - bool strict_class = 0; + bool strict_class = false; if (fcc == NULL) { fcc = &fcc_local; @@ -4296,7 +4208,7 @@ ZEND_API bool zend_is_callable_at_frame( ZEND_API bool zend_is_callable_ex(zval *callable, zend_object *object, uint32_t check_flags, zend_string **callable_name, zend_fcall_info_cache *fcc, char **error) /* {{{ */ { /* Determine callability at the first parent user frame. */ - zend_execute_data *frame = EG(current_execute_data); + const zend_execute_data *frame = EG(current_execute_data); while (frame && (!frame->func || !ZEND_USER_CODE(frame->func->type))) { frame = frame->prev_execute_data; } @@ -4314,24 +4226,6 @@ ZEND_API bool zend_is_callable(zval *callable, uint32_t check_flags, zend_string } /* }}} */ -ZEND_API bool zend_make_callable(zval *callable, zend_string **callable_name) /* {{{ */ -{ - zend_fcall_info_cache fcc; - - if (zend_is_callable_ex(callable, NULL, IS_CALLABLE_SUPPRESS_DEPRECATIONS, callable_name, &fcc, NULL)) { - if (Z_TYPE_P(callable) == IS_STRING && fcc.calling_scope) { - zval_ptr_dtor_str(callable); - array_init(callable); - add_next_index_str(callable, zend_string_copy(fcc.calling_scope->name)); - add_next_index_str(callable, zend_string_copy(fcc.function_handler->common.function_name)); - } - zend_release_fcall_info_cache(&fcc); - return 1; - } - return 0; -} -/* }}} */ - ZEND_API zend_result zend_fcall_info_init(zval *callable, uint32_t check_flags, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string **callable_name, char **error) /* {{{ */ { if (!zend_is_callable_ex(callable, NULL, check_flags, callable_name, fcc, error)) { @@ -4380,7 +4274,7 @@ ZEND_API void zend_fcall_info_args_save(zend_fcall_info *fci, uint32_t *param_co ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, uint32_t param_count, zval *params) /* {{{ */ { - zend_fcall_info_args_clear(fci, 1); + zend_fcall_info_args_clear(fci, true); fci->param_count = param_count; fci->params = params; } @@ -4510,19 +4404,13 @@ ZEND_API void zend_get_callable_zval_from_fcc(const zend_fcall_info_cache *fcc, ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */ { - zend_string *lname; size_t name_len = strlen(module_name); - zend_module_entry *module; - - lname = zend_string_alloc(name_len, 0); - zend_str_tolower_copy(ZSTR_VAL(lname), module_name, name_len); - module = zend_hash_find_ptr(&module_registry, lname); - zend_string_efree(lname); + zend_module_entry *module = zend_hash_str_find_ptr_lc(&module_registry, module_name, name_len); return module ? module->version : NULL; } /* }}} */ -static zend_always_inline bool is_persistent_class(zend_class_entry *ce) { +static zend_always_inline bool is_persistent_class(const zend_class_entry *ce) { return (ce->type & ZEND_INTERNAL_CLASS) && ce->info.internal.module->type == MODULE_PERSISTENT; } @@ -5000,7 +4888,7 @@ 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) /* {{{ */ { const zend_class_entry *old_scope = EG(fake_scope); @@ -5012,7 +4900,7 @@ 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; const zend_class_entry *old_scope = EG(fake_scope); @@ -5027,7 +4915,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; @@ -5036,7 +4924,7 @@ 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; const zend_class_entry *old_scope = EG(fake_scope); @@ -5051,7 +4939,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; @@ -5060,7 +4948,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; @@ -5069,7 +4957,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; @@ -5078,7 +4966,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; @@ -5087,7 +4975,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; @@ -5097,7 +4985,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; @@ -5208,7 +5096,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) /* {{{ */ +ZEND_API zval *zend_read_property_ex(const zend_class_entry *scope, zend_object *object, zend_string *name, bool silent, zval *rv) /* {{{ */ { zval *value; const zend_class_entry *old_scope = EG(fake_scope); @@ -5222,7 +5110,7 @@ ZEND_API zval *zend_read_property_ex(zend_class_entry *scope, zend_object *objec } /* }}} */ -ZEND_API zval *zend_read_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, bool silent, zval *rv) /* {{{ */ +ZEND_API zval *zend_read_property(const zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, bool silent, zval *rv) /* {{{ */ { zval *value; zend_string *str; @@ -5274,7 +5162,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_restore_error_handling(const zend_error_handling *saved) /* {{{ */ { EG(error_handling) = saved->handling; EG(exception_class) = saved->exception; @@ -5374,48 +5262,43 @@ static zend_string *try_parse_string(const char *str, size_t len, char quote) { } ZEND_API zend_result zend_get_default_from_internal_arg_info( - zval *default_value_zval, zend_internal_arg_info *arg_info) + zval *default_value_zval, const zend_arg_info *arg_info) { - const char *default_value = arg_info->default_value; + const zend_string *default_value = arg_info->default_value; if (!default_value) { return FAILURE; } /* Avoid going through the full AST machinery for some simple and common cases. */ - size_t default_value_len = strlen(default_value); zend_ulong lval; - if (default_value_len == sizeof("null")-1 - && !memcmp(default_value, "null", sizeof("null")-1)) { + if (zend_string_equals_literal(default_value, "null")) { ZVAL_NULL(default_value_zval); return SUCCESS; - } else if (default_value_len == sizeof("true")-1 - && !memcmp(default_value, "true", sizeof("true")-1)) { + } else if (zend_string_equals_literal(default_value, "true")) { ZVAL_TRUE(default_value_zval); return SUCCESS; - } else if (default_value_len == sizeof("false")-1 - && !memcmp(default_value, "false", sizeof("false")-1)) { + } else if (zend_string_equals_literal(default_value, "false")) { ZVAL_FALSE(default_value_zval); return SUCCESS; - } else if (default_value_len >= 2 - && (default_value[0] == '\'' || default_value[0] == '"') - && default_value[default_value_len - 1] == default_value[0]) { + } else if (ZSTR_LEN(default_value) >= 2 + && (ZSTR_VAL(default_value)[0] == '\'' || ZSTR_VAL(default_value)[0] == '"') + && ZSTR_VAL(default_value)[ZSTR_LEN(default_value) - 1] == ZSTR_VAL(default_value)[0]) { zend_string *str = try_parse_string( - default_value + 1, default_value_len - 2, default_value[0]); + ZSTR_VAL(default_value) + 1, ZSTR_LEN(default_value) - 2, ZSTR_VAL(default_value)[0]); if (str) { ZVAL_STR(default_value_zval, str); return SUCCESS; } - } else if (default_value_len == sizeof("[]")-1 - && !memcmp(default_value, "[]", sizeof("[]")-1)) { + } else if (zend_string_equals_literal(default_value, "[]")) { ZVAL_EMPTY_ARRAY(default_value_zval); return SUCCESS; - } else if (ZEND_HANDLE_NUMERIC_STR(default_value, default_value_len, lval)) { + } else if (ZEND_HANDLE_NUMERIC(default_value, lval)) { ZVAL_LONG(default_value_zval, lval); return SUCCESS; } #if 0 - fprintf(stderr, "Evaluating %s via AST\n", default_value); + fprintf(stderr, "Evaluating %s via AST\n", ZSTR_VAL(default_value)); #endif - return get_default_via_ast(default_value_zval, default_value); + return get_default_via_ast(default_value_zval, ZSTR_VAL(default_value)); } diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 25a96f8cc9e52..c1ccbf13666a5 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -347,9 +347,6 @@ ZEND_API void zend_set_dl_use_deepbind(bool use_deepbind); ZEND_API zend_result zend_get_parameters_array_ex(uint32_t param_count, zval *argument_array); -/* internal function to efficiently copy parameters when executing __call() */ -ZEND_API zend_result zend_copy_parameters_array(uint32_t param_count, zval *argument_array); - #define zend_get_parameters_array(ht, param_count, argument_array) \ zend_get_parameters_array_ex(param_count, argument_array) #define zend_parse_parameters_none() \ @@ -387,13 +384,13 @@ ZEND_API void zend_startup_modules(void); ZEND_API void zend_collect_module_handlers(void); ZEND_API void zend_destroy_modules(void); ZEND_API void zend_check_magic_method_implementation( - const zend_class_entry *ce, const zend_function *fptr, zend_string *lcname, int error_type); -ZEND_API void zend_add_magic_method(zend_class_entry *ce, zend_function *fptr, zend_string *lcname); + const zend_class_entry *ce, const zend_function *fptr, const zend_string *lcname, int error_type); +ZEND_API void zend_add_magic_method(zend_class_entry *ce, zend_function *fptr, const zend_string *lcname); -ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *class_entry); -ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce); -ZEND_API zend_class_entry *zend_register_internal_class_with_flags(zend_class_entry *class_entry, zend_class_entry *parent_ce, uint32_t flags); -ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *orig_class_entry); +ZEND_API zend_class_entry *zend_register_internal_class(const zend_class_entry *class_entry); +ZEND_API zend_class_entry *zend_register_internal_class_ex(const zend_class_entry *class_entry, zend_class_entry *parent_ce); +ZEND_API zend_class_entry *zend_register_internal_class_with_flags(const zend_class_entry *class_entry, zend_class_entry *parent_ce, uint32_t flags); +ZEND_API zend_class_entry *zend_register_internal_interface(const zend_class_entry *orig_class_entry); ZEND_API void zend_class_implements(zend_class_entry *class_entry, int num_interfaces, ...); ZEND_API zend_result zend_register_class_alias_ex(const char *name, size_t name_len, zend_class_entry *ce, bool persistent); @@ -405,23 +402,21 @@ 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); +ZEND_API ZEND_COLD void zend_wrong_property_read(const zval *object, zval *property); #define IS_CALLABLE_CHECK_SYNTAX_ONLY (1<<0) #define IS_CALLABLE_SUPPRESS_DEPRECATIONS (1<<1) ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc); -ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, zend_object *object); +ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, const zend_object *object); ZEND_API zend_string *zend_get_callable_name(zval *callable); ZEND_API bool zend_is_callable_at_frame( - zval *callable, zend_object *object, zend_execute_data *frame, + const zval *callable, zend_object *object, const zend_execute_data *frame, uint32_t check_flags, zend_fcall_info_cache *fcc, char **error); ZEND_API bool zend_is_callable_ex(zval *callable, zend_object *object, uint32_t check_flags, zend_string **callable_name, zend_fcall_info_cache *fcc, char **error); ZEND_API bool zend_is_callable(zval *callable, uint32_t check_flags, zend_string **callable_name); -ZEND_API bool zend_make_callable(zval *callable, zend_string **callable_name); ZEND_API const char *zend_get_module_version(const char *module_name); ZEND_API zend_result zend_get_module_started(const char *module_name); @@ -448,7 +443,7 @@ ZEND_API void zend_declare_class_constant_string(zend_class_entry *ce, const cha ZEND_API zend_result zend_update_class_constant(zend_class_constant *c, const zend_string *name, zend_class_entry *scope); ZEND_API zend_result zend_update_class_constants(zend_class_entry *class_type); -ZEND_API HashTable *zend_separate_class_constants_table(zend_class_entry *class_type); +ZEND_API HashTable *zend_separate_class_constants_table(const zend_class_entry *class_type); static zend_always_inline HashTable *zend_class_constants_table(zend_class_entry *ce) { if ((ce->ce_flags & ZEND_ACC_HAS_AST_CONSTANTS) && ZEND_MAP_PTR(ce->mutable_data)) { @@ -494,16 +489,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); @@ -514,8 +509,8 @@ ZEND_API zend_result zend_update_static_property_double(zend_class_entry *scope, ZEND_API zend_result zend_update_static_property_string(zend_class_entry *scope, const char *name, size_t name_length, const char *value); ZEND_API zend_result zend_update_static_property_stringl(zend_class_entry *scope, const char *name, size_t name_length, const char *value, size_t value_length); -ZEND_API zval *zend_read_property_ex(zend_class_entry *scope, zend_object *object, zend_string *name, bool silent, zval *rv); -ZEND_API zval *zend_read_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, bool silent, zval *rv); +ZEND_API zval *zend_read_property_ex(const zend_class_entry *scope, zend_object *object, zend_string *name, bool silent, zval *rv); +ZEND_API zval *zend_read_property(const zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, bool silent, zval *rv); ZEND_API zval *zend_read_static_property_ex(zend_class_entry *scope, zend_string *name, bool silent); ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, size_t name_length, bool silent); @@ -528,9 +523,7 @@ ZEND_API const char *zend_get_type_by_const(int type); #define getThis() (hasThis() ? ZEND_THIS : NULL) #define ZEND_IS_METHOD_CALL() (EX(func)->common.scope != NULL) -#define WRONG_PARAM_COUNT ZEND_WRONG_PARAM_COUNT() #define ZEND_NUM_ARGS() EX_NUM_ARGS() -#define ZEND_WRONG_PARAM_COUNT() { zend_wrong_param_count(); return; } #ifndef ZEND_WIN32 #define DLEXPORT @@ -544,9 +537,9 @@ ZEND_API zend_result object_init_with_constructor(zval *arg, zend_class_entry *c ZEND_API zend_result object_and_properties_init(zval *arg, zend_class_entry *ce, HashTable *properties); ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type); ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properties); -ZEND_API void object_properties_load(zend_object *object, HashTable *properties); +ZEND_API void object_properties_load(zend_object *object, const HashTable *properties); -ZEND_API void zend_merge_properties(zval *obj, HashTable *properties); +ZEND_API void zend_merge_properties(const zval *obj, const HashTable *properties); ZEND_API void add_assoc_long_ex(zval *arg, const char *key, size_t key_len, zend_long n); ZEND_API void add_assoc_null_ex(zval *arg, const char *key, size_t key_len); @@ -889,8 +882,6 @@ 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_API zend_result zend_set_hash_symbol(zval *symbol, const char *name, size_t name_length, bool is_ref, int num_symbol_tables, ...); - ZEND_API zend_result zend_delete_global_variable(zend_string *name); ZEND_API zend_array *zend_rebuild_symbol_table(void); @@ -901,7 +892,7 @@ ZEND_API zend_result zend_set_local_var_str(const char *name, size_t len, zval * static zend_always_inline zend_result zend_forbid_dynamic_call(void) { - zend_execute_data *ex = EG(current_execute_data); + const zend_execute_data *ex = EG(current_execute_data); ZEND_ASSERT(ex != NULL && ex->func != NULL); if (ZEND_CALL_INFO(ex) & ZEND_CALL_DYNAMIC) { @@ -931,8 +922,12 @@ ZEND_API bool zend_is_iterable(const zval *iterable); ZEND_API bool zend_is_countable(const zval *countable); +ZEND_API void zend_convert_internal_arg_info(zend_arg_info *new_arg_info, + const zend_internal_arg_info *arg_info, bool is_return_info, + bool permanent); + ZEND_API zend_result zend_get_default_from_internal_arg_info( - zval *default_value_zval, zend_internal_arg_info *arg_info); + zval *default_value_zval, const zend_arg_info *arg_info); END_EXTERN_C() @@ -952,10 +947,6 @@ static zend_always_inline bool zend_char_has_nul_byte(const char *s, size_t know return known_length != strlen(s); } -/* Compatibility with PHP 8.1 and below */ -#define CHECK_ZVAL_NULL_PATH(p) zend_str_has_nul_byte(Z_STR_P(p)) -#define CHECK_NULL_PATH(p, l) zend_char_has_nul_byte(p, l) - #define ZVAL_STRINGL(z, s, l) do { \ ZVAL_NEW_STR(z, zend_string_init(s, l, 0)); \ } while (0) @@ -1067,7 +1058,6 @@ static zend_always_inline bool zend_char_has_nul_byte(const char *s, size_t know #define RETURN_THROWS() do { ZEND_ASSERT(EG(exception)); (void) return_value; return; } while (0) #define HASH_OF(p) (Z_TYPE_P(p)==IS_ARRAY ? Z_ARRVAL_P(p) : ((Z_TYPE_P(p)==IS_OBJECT ? Z_OBJ_HT_P(p)->get_properties(Z_OBJ_P(p)) : NULL))) -#define ZVAL_IS_NULL(z) (Z_TYPE_P(z) == IS_NULL) /* For compatibility */ #define ZEND_MINIT ZEND_MODULE_STARTUP_N @@ -1365,6 +1355,7 @@ ZEND_API zend_result zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval #define ZEND_TRY_ASSIGN_REF_ARR(zv, arr) do { \ ZEND_ASSERT(Z_ISREF_P(zv)); \ + ZEND_ASSERT(!(GC_FLAGS(arr) & GC_IMMUTABLE)); \ _ZEND_TRY_ASSIGN_ARR(zv, arr, 1); \ } while (0) @@ -1557,14 +1548,14 @@ typedef enum _zend_expected_type { ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_none_error(void); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_error(uint32_t min_num_args, uint32_t max_num_args); -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_error(int error_code, uint32_t num, char *name, zend_expected_type expected_type, zval *arg); -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_error(uint32_t num, zend_expected_type expected_type, zval *arg); -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(uint32_t num, const char *name, zval *arg); -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_null_error(uint32_t num, const char *name, zval *arg); -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_long_error(uint32_t num, const char *name, zval *arg); -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_long_or_null_error(uint32_t num, const char *name, zval *arg); -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_string_error(uint32_t num, const char *name, zval *arg); -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_string_or_null_error(uint32_t num, const char *name, zval *arg); +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_error(int error_code, uint32_t num, char *name, zend_expected_type expected_type, const zval *arg); +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_error(uint32_t num, zend_expected_type expected_type, const zval *arg); +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(uint32_t num, const char *name, const zval *arg); +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_null_error(uint32_t num, const char *name, const zval *arg); +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_long_error(uint32_t num, const char *name, const zval *arg); +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_long_or_null_error(uint32_t num, const char *name, const zval *arg); +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_string_error(uint32_t num, const char *name, const zval *arg); +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_string_or_null_error(uint32_t num, const char *name, const zval *arg); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(uint32_t num, char *error); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_or_null_error(uint32_t num, char *error); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_unexpected_extra_named_error(void); @@ -1573,8 +1564,8 @@ ZEND_API ZEND_COLD void zend_argument_error(zend_class_entry *error_ce, uint32_t ZEND_API ZEND_COLD void zend_argument_type_error(uint32_t arg_num, const char *format, ...); ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format, ...); ZEND_API ZEND_COLD void zend_argument_must_not_be_empty_error(uint32_t arg_num); -ZEND_API ZEND_COLD void zend_class_redeclaration_error(int type, zend_class_entry *old_ce); -ZEND_API ZEND_COLD void zend_class_redeclaration_error_ex(int type, zend_string *new_name, zend_class_entry *old_ce); +ZEND_API ZEND_COLD void zend_class_redeclaration_error(int type, const zend_class_entry *old_ce); +ZEND_API ZEND_COLD void zend_class_redeclaration_error_ex(int type, zend_string *new_name, const zend_class_entry *old_ce); #define ZPP_ERROR_OK 0 #define ZPP_ERROR_FAILURE 1 @@ -2326,7 +2317,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..1157dc98fa615 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); } } @@ -2609,7 +2627,7 @@ ZEND_API bool is_zend_mm(void) #if ZEND_MM_CUSTOM return !AG(mm_heap)->use_custom_heap; #else - return 1; + return true; #endif } @@ -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 0e403329264c4..30bd4a9c05dd0 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; @@ -558,7 +558,7 @@ static zend_class_entry *zend_ast_fetch_class(zend_ast *ast, zend_class_entry *s return zend_fetch_class_with_scope(zend_ast_get_str(ast), (ast->attr >> ZEND_CONST_EXPR_NEW_FETCH_TYPE_SHIFT) | ZEND_FETCH_CLASS_EXCEPTION, scope); } -ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner( +static zend_result ZEND_FASTCALL zend_ast_evaluate_inner( zval *result, zend_ast *ast, zend_class_entry *scope, @@ -589,7 +589,7 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_ex( return r; } -ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner( +static zend_result ZEND_FASTCALL zend_ast_evaluate_inner( zval *result, zend_ast *ast, zend_class_entry *scope, @@ -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,13 +1087,15 @@ 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); @@ -1120,12 +1124,12 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner( if (!(fptr->common.fn_flags & ZEND_ACC_STATIC)) { zend_non_static_method_call(fptr); - + return FAILURE; } if ((fptr->common.fn_flags & ZEND_ACC_ABSTRACT)) { zend_abstract_method_call(fptr); - + return FAILURE; } else if (fptr->common.scope->ce_flags & ZEND_ACC_TRAIT) { zend_error(E_DEPRECATED, @@ -1144,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; } @@ -1242,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++) { @@ -1283,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; @@ -1300,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; @@ -1309,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; @@ -1370,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; @@ -1385,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); @@ -1464,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; @@ -1479,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; @@ -1535,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)); @@ -1548,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) { @@ -1571,9 +1575,9 @@ static ZEND_COLD bool zend_ast_valid_var_char(char ch) (c < '0' || c > '9') && (c < 'A' || c > 'Z') && (c < 'a' || c > 'z')) { - return 0; + return false; } - return 1; + return true; } static ZEND_COLD bool zend_ast_valid_var_name(const char *s, size_t len) @@ -1582,13 +1586,13 @@ static ZEND_COLD bool zend_ast_valid_var_name(const char *s, size_t len) size_t i; if (len == 0) { - return 0; + return false; } c = (unsigned char)s[0]; if (c != '_' && c < 127 && (c < 'A' || c > 'Z') && (c < 'a' || c > 'z')) { - return 0; + return false; } for (i = 1; i < len; i++) { c = (unsigned char)s[i]; @@ -1596,10 +1600,10 @@ static ZEND_COLD bool zend_ast_valid_var_name(const char *s, size_t len) (c < '0' || c > '9') && (c < 'A' || c > 'Z') && (c < 'a' || c > 'z')) { - return 0; + return false; } } - return 1; + return true; } static ZEND_COLD bool zend_ast_var_needs_braces(char ch) @@ -1627,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; @@ -1641,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; @@ -1654,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)); @@ -1675,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; @@ -1691,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; @@ -1716,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) { @@ -1743,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, ';'); } @@ -1758,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; @@ -1782,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"); @@ -1795,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)) { @@ -1852,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); @@ -1868,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, ", "); @@ -1886,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++) { @@ -1925,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, '|'); @@ -1935,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, '&'); @@ -1950,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'); @@ -1958,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 "); @@ -2032,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; @@ -2068,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); @@ -2112,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; } @@ -2127,9 +2137,9 @@ 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); + zend_ast_export_attributes(str, decl->child[3], indent, true); } if (decl->flags & ZEND_ACC_INTERFACE) { smart_str_appends(str, "interface "); @@ -2163,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), true, 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), true, 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: @@ -2180,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), false, 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: { @@ -2197,7 +2207,7 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio zend_ast *prop_ast = ast->child[1]; if (ast->child[2]) { - zend_ast_export_attributes(str, ast->child[2], indent, 1); + zend_ast_export_attributes(str, ast->child[2], indent, true); } zend_ast_export_visibility(str, ast->attr, ZEND_MODIFIER_TARGET_PROPERTY); @@ -2226,13 +2236,13 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio str, ast_list->child[ast_list->children - 1], indent, - 1 + true ); /* So that the list printing doesn't try to print the attributes, * use zend_ast_export_list_ex() to override the number of children * to print. */ smart_str_appends(str, "const "); - zend_ast_export_list_ex(str, ast_list, 1, 20, indent, ast_list->children - 1); + zend_ast_export_list_ex(str, ast_list, true, 20, indent, ast_list->children - 1); break; } smart_str_appends(str, "const "); @@ -2240,7 +2250,7 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio } case ZEND_AST_CLASS_CONST_GROUP: if (ast->child[1]) { - zend_ast_export_attributes(str, ast->child[1], indent, 1); + zend_ast_export_attributes(str, ast->child[1], indent, true); } zend_ast_export_visibility(str, ast->attr, ZEND_MODIFIER_TARGET_CONSTANT); @@ -2254,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 "); @@ -2309,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); @@ -2328,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); @@ -2522,9 +2532,9 @@ 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); + zend_ast_export_attributes(str, decl->child[3], indent, false); } smart_str_appends(str, "class"); if (!zend_ast_is_list(ast->child[1]) @@ -2625,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]), true, 0, indent); smart_str_appends(str, " => "); } else { smart_str_appends(str, "default => "); @@ -2636,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]), true, 0, indent); smart_str_appendc(str, ')'); if (ast->child[1]) { smart_str_appends(str, " {\n"); @@ -2783,7 +2793,7 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio break; case ZEND_AST_PARAM: if (ast->child[3]) { - zend_ast_export_attributes(str, ast->child[3], indent, 0); + zend_ast_export_attributes(str, ast->child[3], indent, false); } zend_ast_export_visibility(str, ast->attr, ZEND_MODIFIER_TARGET_CPP); if (ast->attr & ZEND_ACC_FINAL) { @@ -2811,7 +2821,7 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio break; case ZEND_AST_ENUM_CASE: if (ast->child[3]) { - zend_ast_export_attributes(str, ast->child[3], indent, 1); + zend_ast_export_attributes(str, ast->child[3], indent, true); } smart_str_appends(str, "case "); zend_ast_export_name(str, ast->child[0], 0, indent); @@ -2949,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..cba95810ba496 100644 --- a/Zend/zend_attributes.c +++ b/Zend/zend_attributes.c @@ -32,12 +32,13 @@ 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; static HashTable internal_attributes; -uint32_t zend_attribute_attribute_get_flags(zend_attribute *attr, zend_class_entry *scope) +uint32_t zend_attribute_attribute_get_flags(const zend_attribute *attr, zend_class_entry *scope) { // TODO: More proper signature validation: Too many args, incorrect arg names. if (attr->argc > 0) { @@ -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; @@ -217,7 +265,7 @@ ZEND_METHOD(NoDiscard, __construct) } } -static zend_attribute *get_attribute(HashTable *attributes, zend_string *lcname, uint32_t offset) +static zend_attribute *get_attribute(const HashTable *attributes, const zend_string *lcname, uint32_t offset) { if (attributes) { zend_attribute *attr; @@ -232,7 +280,7 @@ static zend_attribute *get_attribute(HashTable *attributes, zend_string *lcname, return NULL; } -static zend_attribute *get_attribute_str(HashTable *attributes, const char *str, size_t len, uint32_t offset) +static zend_attribute *get_attribute_str(const HashTable *attributes, const char *str, size_t len, uint32_t offset) { if (attributes) { zend_attribute *attr; @@ -247,27 +295,27 @@ static zend_attribute *get_attribute_str(HashTable *attributes, const char *str, return NULL; } -ZEND_API zend_attribute *zend_get_attribute(HashTable *attributes, zend_string *lcname) +ZEND_API zend_attribute *zend_get_attribute(const HashTable *attributes, const zend_string *lcname) { return get_attribute(attributes, lcname, 0); } -ZEND_API zend_attribute *zend_get_attribute_str(HashTable *attributes, const char *str, size_t len) +ZEND_API zend_attribute *zend_get_attribute_str(const HashTable *attributes, const char *str, size_t len) { return get_attribute_str(attributes, str, len, 0); } -ZEND_API zend_attribute *zend_get_parameter_attribute(HashTable *attributes, zend_string *lcname, uint32_t offset) +ZEND_API zend_attribute *zend_get_parameter_attribute(const HashTable *attributes, const zend_string *lcname, uint32_t offset) { return get_attribute(attributes, lcname, offset + 1); } -ZEND_API zend_attribute *zend_get_parameter_attribute_str(HashTable *attributes, const char *str, size_t len, uint32_t offset) +ZEND_API zend_attribute *zend_get_parameter_attribute_str(const HashTable *attributes, const char *str, size_t len, uint32_t offset) { return get_attribute_str(attributes, str, len, offset + 1); } -ZEND_API zend_result zend_get_attribute_value(zval *ret, zend_attribute *attr, uint32_t i, zend_class_entry *scope) +ZEND_API zend_result zend_get_attribute_value(zval *ret, const zend_attribute *attr, uint32_t i, zend_class_entry *scope) { if (i >= attr->argc) { return FAILURE; @@ -399,7 +447,7 @@ ZEND_API zend_string *zend_get_attribute_target_names(uint32_t flags) return smart_str_extract(&str); } -ZEND_API bool zend_is_attribute_repeated(HashTable *attributes, zend_attribute *attr) +ZEND_API bool zend_is_attribute_repeated(const HashTable *attributes, const zend_attribute *attr) { zend_attribute *other; @@ -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..f8b61ac9d1666 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,20 +74,20 @@ 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); -ZEND_API zend_attribute *zend_get_attribute_str(HashTable *attributes, const char *str, size_t len); +ZEND_API zend_attribute *zend_get_attribute(const HashTable *attributes, const zend_string *lcname); +ZEND_API zend_attribute *zend_get_attribute_str(const HashTable *attributes, const char *str, size_t len); -ZEND_API zend_attribute *zend_get_parameter_attribute(HashTable *attributes, zend_string *lcname, uint32_t offset); -ZEND_API zend_attribute *zend_get_parameter_attribute_str(HashTable *attributes, const char *str, size_t len, uint32_t offset); +ZEND_API zend_attribute *zend_get_parameter_attribute(const HashTable *attributes, const zend_string *lcname, uint32_t offset); +ZEND_API zend_attribute *zend_get_parameter_attribute_str(const HashTable *attributes, const char *str, size_t len, uint32_t offset); -ZEND_API zend_result zend_get_attribute_value(zval *ret, zend_attribute *attr, uint32_t i, zend_class_entry *scope); +ZEND_API zend_result zend_get_attribute_value(zval *ret, const zend_attribute *attr, uint32_t i, zend_class_entry *scope); ZEND_API zend_result zend_get_attribute_object(zval *out, zend_class_entry *attribute_ce, zend_attribute *attribute_data, zend_class_entry *scope, zend_string *filename); ZEND_API zend_string *zend_get_attribute_target_names(uint32_t targets); -ZEND_API bool zend_is_attribute_repeated(HashTable *attributes, zend_attribute *attr); +ZEND_API bool zend_is_attribute_repeated(const HashTable *attributes, const zend_attribute *attr); ZEND_API zend_internal_attribute *zend_mark_internal_attribute(zend_class_entry *ce); ZEND_API zend_internal_attribute *zend_internal_attribute_register(zend_class_entry *ce, uint32_t flags); @@ -93,7 +97,7 @@ ZEND_API zend_attribute *zend_add_attribute( HashTable **attributes, zend_string *name, uint32_t argc, uint32_t flags, uint32_t offset, uint32_t lineno); -uint32_t zend_attribute_attribute_get_flags(zend_attribute *attr, zend_class_entry *scope); +uint32_t zend_attribute_attribute_get_flags(const zend_attribute *attr, zend_class_entry *scope); END_EXTERN_C() @@ -115,13 +119,13 @@ static zend_always_inline zend_attribute *zend_add_parameter_attribute(zend_func return zend_add_attribute(&func->common.attributes, name, argc, flags, offset + 1, 0); } -static zend_always_inline zend_attribute *zend_add_property_attribute(zend_class_entry *ce, zend_property_info *info, zend_string *name, uint32_t argc) +static zend_always_inline zend_attribute *zend_add_property_attribute(const zend_class_entry *ce, zend_property_info *info, zend_string *name, uint32_t argc) { uint32_t flags = ce->type != ZEND_USER_CLASS ? ZEND_ATTRIBUTE_PERSISTENT : 0; return zend_add_attribute(&info->attributes, name, argc, flags, 0, 0); } -static zend_always_inline zend_attribute *zend_add_class_constant_attribute(zend_class_entry *ce, zend_class_constant *c, zend_string *name, uint32_t argc) +static zend_always_inline zend_attribute *zend_add_class_constant_attribute(const zend_class_entry *ce, zend_class_constant *c, zend_string *name, uint32_t argc) { uint32_t flags = ce->type != ZEND_USER_CLASS ? ZEND_ATTRIBUTE_PERSISTENT : 0; return zend_add_attribute(&c->attributes, name, argc, flags, 0, 0); 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..ec8d8de4ee508 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") @@ -95,70 +95,68 @@ static zend_class_entry *register_class_Attribute(void) zval const_TARGET_CLASS_value; ZVAL_LONG(&const_TARGET_CLASS_value, ZEND_ATTRIBUTE_TARGET_CLASS); - zend_string *const_TARGET_CLASS_name = zend_string_init_interned("TARGET_CLASS", sizeof("TARGET_CLASS") - 1, 1); + zend_string *const_TARGET_CLASS_name = zend_string_init_interned("TARGET_CLASS", sizeof("TARGET_CLASS") - 1, true); zend_declare_typed_class_constant(class_entry, const_TARGET_CLASS_name, &const_TARGET_CLASS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TARGET_CLASS_name); + zend_string_release_ex(const_TARGET_CLASS_name, true); zval const_TARGET_FUNCTION_value; ZVAL_LONG(&const_TARGET_FUNCTION_value, ZEND_ATTRIBUTE_TARGET_FUNCTION); - zend_string *const_TARGET_FUNCTION_name = zend_string_init_interned("TARGET_FUNCTION", sizeof("TARGET_FUNCTION") - 1, 1); + zend_string *const_TARGET_FUNCTION_name = zend_string_init_interned("TARGET_FUNCTION", sizeof("TARGET_FUNCTION") - 1, true); zend_declare_typed_class_constant(class_entry, const_TARGET_FUNCTION_name, &const_TARGET_FUNCTION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TARGET_FUNCTION_name); + zend_string_release_ex(const_TARGET_FUNCTION_name, true); zval const_TARGET_METHOD_value; ZVAL_LONG(&const_TARGET_METHOD_value, ZEND_ATTRIBUTE_TARGET_METHOD); - zend_string *const_TARGET_METHOD_name = zend_string_init_interned("TARGET_METHOD", sizeof("TARGET_METHOD") - 1, 1); + zend_string *const_TARGET_METHOD_name = zend_string_init_interned("TARGET_METHOD", sizeof("TARGET_METHOD") - 1, true); zend_declare_typed_class_constant(class_entry, const_TARGET_METHOD_name, &const_TARGET_METHOD_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TARGET_METHOD_name); + zend_string_release_ex(const_TARGET_METHOD_name, true); zval const_TARGET_PROPERTY_value; ZVAL_LONG(&const_TARGET_PROPERTY_value, ZEND_ATTRIBUTE_TARGET_PROPERTY); - zend_string *const_TARGET_PROPERTY_name = zend_string_init_interned("TARGET_PROPERTY", sizeof("TARGET_PROPERTY") - 1, 1); + zend_string *const_TARGET_PROPERTY_name = zend_string_init_interned("TARGET_PROPERTY", sizeof("TARGET_PROPERTY") - 1, true); zend_declare_typed_class_constant(class_entry, const_TARGET_PROPERTY_name, &const_TARGET_PROPERTY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TARGET_PROPERTY_name); + zend_string_release_ex(const_TARGET_PROPERTY_name, true); zval const_TARGET_CLASS_CONSTANT_value; ZVAL_LONG(&const_TARGET_CLASS_CONSTANT_value, ZEND_ATTRIBUTE_TARGET_CLASS_CONST); - zend_string *const_TARGET_CLASS_CONSTANT_name = zend_string_init_interned("TARGET_CLASS_CONSTANT", sizeof("TARGET_CLASS_CONSTANT") - 1, 1); + zend_string *const_TARGET_CLASS_CONSTANT_name = zend_string_init_interned("TARGET_CLASS_CONSTANT", sizeof("TARGET_CLASS_CONSTANT") - 1, true); zend_declare_typed_class_constant(class_entry, const_TARGET_CLASS_CONSTANT_name, &const_TARGET_CLASS_CONSTANT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TARGET_CLASS_CONSTANT_name); + zend_string_release_ex(const_TARGET_CLASS_CONSTANT_name, true); zval const_TARGET_PARAMETER_value; ZVAL_LONG(&const_TARGET_PARAMETER_value, ZEND_ATTRIBUTE_TARGET_PARAMETER); - zend_string *const_TARGET_PARAMETER_name = zend_string_init_interned("TARGET_PARAMETER", sizeof("TARGET_PARAMETER") - 1, 1); + zend_string *const_TARGET_PARAMETER_name = zend_string_init_interned("TARGET_PARAMETER", sizeof("TARGET_PARAMETER") - 1, true); zend_declare_typed_class_constant(class_entry, const_TARGET_PARAMETER_name, &const_TARGET_PARAMETER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TARGET_PARAMETER_name); + zend_string_release_ex(const_TARGET_PARAMETER_name, true); zval const_TARGET_CONSTANT_value; ZVAL_LONG(&const_TARGET_CONSTANT_value, ZEND_ATTRIBUTE_TARGET_CONST); - zend_string *const_TARGET_CONSTANT_name = zend_string_init_interned("TARGET_CONSTANT", sizeof("TARGET_CONSTANT") - 1, 1); + zend_string *const_TARGET_CONSTANT_name = zend_string_init_interned("TARGET_CONSTANT", sizeof("TARGET_CONSTANT") - 1, true); zend_declare_typed_class_constant(class_entry, const_TARGET_CONSTANT_name, &const_TARGET_CONSTANT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TARGET_CONSTANT_name); + zend_string_release_ex(const_TARGET_CONSTANT_name, true); zval const_TARGET_ALL_value; ZVAL_LONG(&const_TARGET_ALL_value, ZEND_ATTRIBUTE_TARGET_ALL); - zend_string *const_TARGET_ALL_name = zend_string_init_interned("TARGET_ALL", sizeof("TARGET_ALL") - 1, 1); + zend_string *const_TARGET_ALL_name = zend_string_init_interned("TARGET_ALL", sizeof("TARGET_ALL") - 1, true); zend_declare_typed_class_constant(class_entry, const_TARGET_ALL_name, &const_TARGET_ALL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TARGET_ALL_name); + zend_string_release_ex(const_TARGET_ALL_name, true); zval const_IS_REPEATABLE_value; ZVAL_LONG(&const_IS_REPEATABLE_value, ZEND_ATTRIBUTE_IS_REPEATABLE); - zend_string *const_IS_REPEATABLE_name = zend_string_init_interned("IS_REPEATABLE", sizeof("IS_REPEATABLE") - 1, 1); + zend_string *const_IS_REPEATABLE_name = zend_string_init_interned("IS_REPEATABLE", sizeof("IS_REPEATABLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_REPEATABLE_name, &const_IS_REPEATABLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_REPEATABLE_name); + zend_string_release_ex(const_IS_REPEATABLE_name, true); zval property_flags_default_value; ZVAL_UNDEF(&property_flags_default_value); - zend_string *property_flags_name = zend_string_init("flags", sizeof("flags") - 1, 1); + zend_string *property_flags_name = zend_string_init("flags", sizeof("flags") - 1, true); zend_declare_typed_property(class_entry, property_flags_name, &property_flags_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_flags_name); + zend_string_release_ex(property_flags_name, true); - zend_string *attribute_name_Attribute_class_Attribute_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_string *attribute_name_Attribute_class_Attribute_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, true); 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); + zend_string_release_ex(attribute_name_Attribute_class_Attribute_0, true); + ZVAL_LONG(&attribute_Attribute_class_Attribute_0->args[0].value, ZEND_ATTRIBUTE_TARGET_CLASS); return class_entry; } @@ -170,12 +168,10 @@ static zend_class_entry *register_class_ReturnTypeWillChange(void) INIT_CLASS_ENTRY(ce, "ReturnTypeWillChange", class_ReturnTypeWillChange_methods); class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL); - zend_string *attribute_name_Attribute_class_ReturnTypeWillChange_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_string *attribute_name_Attribute_class_ReturnTypeWillChange_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, true); 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); + zend_string_release_ex(attribute_name_Attribute_class_ReturnTypeWillChange_0, true); + ZVAL_LONG(&attribute_Attribute_class_ReturnTypeWillChange_0->args[0].value, ZEND_ATTRIBUTE_TARGET_METHOD); return class_entry; } @@ -187,12 +183,10 @@ static zend_class_entry *register_class_AllowDynamicProperties(void) INIT_CLASS_ENTRY(ce, "AllowDynamicProperties", class_AllowDynamicProperties_methods); class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL); - zend_string *attribute_name_Attribute_class_AllowDynamicProperties_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_string *attribute_name_Attribute_class_AllowDynamicProperties_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, true); 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); + zend_string_release_ex(attribute_name_Attribute_class_AllowDynamicProperties_0, true); + ZVAL_LONG(&attribute_Attribute_class_AllowDynamicProperties_0->args[0].value, ZEND_ATTRIBUTE_TARGET_CLASS); return class_entry; } @@ -204,12 +198,10 @@ static zend_class_entry *register_class_SensitiveParameter(void) INIT_CLASS_ENTRY(ce, "SensitiveParameter", class_SensitiveParameter_methods); class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES); - zend_string *attribute_name_Attribute_class_SensitiveParameter_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_string *attribute_name_Attribute_class_SensitiveParameter_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, true); 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); + zend_string_release_ex(attribute_name_Attribute_class_SensitiveParameter_0, true); + ZVAL_LONG(&attribute_Attribute_class_SensitiveParameter_0->args[0].value, ZEND_ATTRIBUTE_TARGET_PARAMETER); return class_entry; } @@ -235,12 +227,10 @@ static zend_class_entry *register_class_Override(void) INIT_CLASS_ENTRY(ce, "Override", class_Override_methods); class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES); - zend_string *attribute_name_Attribute_class_Override_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_string *attribute_name_Attribute_class_Override_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, true); 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); + zend_string_release_ex(attribute_name_Attribute_class_Override_0, true); + ZVAL_LONG(&attribute_Attribute_class_Override_0->args[0].value, ZEND_ATTRIBUTE_TARGET_METHOD | ZEND_ATTRIBUTE_TARGET_PROPERTY); return class_entry; } @@ -260,12 +250,10 @@ static zend_class_entry *register_class_Deprecated(void) ZVAL_UNDEF(&property_since_default_value); zend_declare_typed_property(class_entry, ZSTR_KNOWN(ZEND_STR_SINCE), &property_since_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string *attribute_name_Attribute_class_Deprecated_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_string *attribute_name_Attribute_class_Deprecated_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, true); 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); + zend_string_release_ex(attribute_name_Attribute_class_Deprecated_0, true); + 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; } @@ -281,12 +269,25 @@ static zend_class_entry *register_class_NoDiscard(void) ZVAL_UNDEF(&property_message_default_value); zend_declare_typed_property(class_entry, ZSTR_KNOWN(ZEND_STR_MESSAGE), &property_message_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string *attribute_name_Attribute_class_NoDiscard_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_string *attribute_name_Attribute_class_NoDiscard_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, true); 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); + zend_string_release_ex(attribute_name_Attribute_class_NoDiscard_0, true); + 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, true); + zend_attribute *attribute_Attribute_class_DelayedTargetValidation_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_DelayedTargetValidation_0, 1); + zend_string_release_ex(attribute_name_Attribute_class_DelayedTargetValidation_0, true); + 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 256f08e05d6a6..a4ece3061d5d0 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. */ @@ -95,7 +98,16 @@ ZEND_FUNCTION(clone) } 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)) { @@ -491,7 +503,7 @@ ZEND_FUNCTION(error_reporting) static bool validate_constant_array_argument(HashTable *ht, int argument_number) /* {{{ */ { - bool ret = 1; + bool ret = true; zval *val; GC_PROTECT_RECURSION(ht); @@ -500,10 +512,10 @@ static bool validate_constant_array_argument(HashTable *ht, int argument_number) if (Z_TYPE_P(val) == IS_ARRAY && Z_REFCOUNTED_P(val)) { if (Z_IS_RECURSIVE_P(val)) { zend_argument_value_error(argument_number, "cannot be a recursive array"); - ret = 0; + ret = false; break; } else if (!validate_constant_array_argument(Z_ARRVAL_P(val), argument_number)) { - ret = 0; + ret = false; break; } } @@ -543,7 +555,7 @@ static void copy_constant_array(zval *dst, zval *src) /* {{{ */ ZEND_FUNCTION(define) { zend_string *name; - zval *val, val_free; + zval *val; bool non_cs = 0; zend_constant c; @@ -563,23 +575,16 @@ ZEND_FUNCTION(define) zend_error(E_WARNING, "define(): Argument #3 ($case_insensitive) is ignored since declaration of case-insensitive constants is no longer supported"); } - ZVAL_UNDEF(&val_free); - - if (Z_TYPE_P(val) == IS_ARRAY) { - if (Z_REFCOUNTED_P(val)) { - if (!validate_constant_array_argument(Z_ARRVAL_P(val), 2)) { - RETURN_THROWS(); - } else { - copy_constant_array(&c.value, val); - goto register_constant; - } + if (Z_TYPE_P(val) == IS_ARRAY && Z_REFCOUNTED_P(val)) { + if (!validate_constant_array_argument(Z_ARRVAL_P(val), 2)) { + RETURN_THROWS(); + } else { + copy_constant_array(&c.value, val); } + } else { + ZVAL_COPY(&c.value, val); } - ZVAL_COPY(&c.value, val); - zval_ptr_dtor(&val_free); - -register_constant: /* non persistent */ ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT); c.name = zend_string_copy(name); @@ -812,8 +817,8 @@ ZEND_FUNCTION(get_class_vars) } scope = zend_get_executed_scope(); - add_class_vars(scope, ce, 0, return_value); - add_class_vars(scope, ce, 1, return_value); + add_class_vars(scope, ce, false, return_value); + add_class_vars(scope, ce, true, return_value); } /* }}} */ @@ -1471,15 +1476,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); @@ -1619,7 +1624,7 @@ static void add_zendext_info(zend_extension *ext, void *arg) /* {{{ */ /* {{{ Return an array containing names of loaded extensions */ ZEND_FUNCTION(get_loaded_extensions) { - bool zendext = 0; + bool zendext = false; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &zendext) == FAILURE) { RETURN_THROWS(); @@ -1642,7 +1647,7 @@ ZEND_FUNCTION(get_loaded_extensions) /* {{{ Return an array containing the names and values of all defined constants */ ZEND_FUNCTION(get_defined_constants) { - bool categorize = 0; + bool categorize = false; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &categorize) == FAILURE) { RETURN_THROWS(); @@ -1710,6 +1715,18 @@ ZEND_FUNCTION(get_defined_constants) } /* }}} */ +static bool backtrace_is_arg_sensitive(const zend_execute_data *call, uint32_t offset) +{ + zend_attribute *attribute = zend_get_parameter_attribute_str( + call->func->common.attributes, + "sensitiveparameter", + sizeof("sensitiveparameter") - 1, + offset + ); + + return attribute != NULL; +} + static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) /* {{{ */ { uint32_t num_args = ZEND_CALL_NUM_ARGS(call); @@ -1733,14 +1750,7 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) / zend_string *arg_name = call->func->op_array.vars[i]; zval original_arg; zval *arg = zend_hash_find_ex_ind(call->symbol_table, arg_name, 1); - zend_attribute *attribute = zend_get_parameter_attribute_str( - call->func->common.attributes, - "sensitiveparameter", - sizeof("sensitiveparameter") - 1, - i - ); - - bool is_sensitive = attribute != NULL; + bool is_sensitive = backtrace_is_arg_sensitive(call, i); if (arg) { ZVAL_DEREF(arg); @@ -1751,8 +1761,7 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) / if (is_sensitive) { zval redacted_arg; - object_init_ex(&redacted_arg, zend_ce_sensitive_parameter_value); - zend_call_known_function(Z_OBJCE_P(&redacted_arg)->constructor, Z_OBJ_P(&redacted_arg), Z_OBJCE_P(&redacted_arg), NULL, 1, &original_arg, NULL); + object_init_with_constructor(&redacted_arg, zend_ce_sensitive_parameter_value, 1, &original_arg, NULL); ZEND_HASH_FILL_SET(&redacted_arg); } else { Z_TRY_ADDREF_P(&original_arg); @@ -1765,13 +1774,7 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) / } else { while (i < first_extra_arg) { zval original_arg; - zend_attribute *attribute = zend_get_parameter_attribute_str( - call->func->common.attributes, - "sensitiveparameter", - sizeof("sensitiveparameter") - 1, - i - ); - bool is_sensitive = attribute != NULL; + bool is_sensitive = backtrace_is_arg_sensitive(call, i); if (EXPECTED(Z_TYPE_INFO_P(p) != IS_UNDEF)) { zval *arg = p; @@ -1783,8 +1786,7 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) / if (is_sensitive) { zval redacted_arg; - object_init_ex(&redacted_arg, zend_ce_sensitive_parameter_value); - zend_call_known_function(Z_OBJCE_P(&redacted_arg)->constructor, Z_OBJ_P(&redacted_arg), Z_OBJCE_P(&redacted_arg), NULL, 1, &original_arg, NULL); + object_init_with_constructor(&redacted_arg, zend_ce_sensitive_parameter_value, 1, &original_arg, NULL); ZEND_HASH_FILL_SET(&redacted_arg); } else { Z_TRY_ADDREF_P(&original_arg); @@ -1804,13 +1806,7 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) / bool is_sensitive = 0; if (i < call->func->common.num_args || call->func->common.fn_flags & ZEND_ACC_VARIADIC) { - zend_attribute *attribute = zend_get_parameter_attribute_str( - call->func->common.attributes, - "sensitiveparameter", - sizeof("sensitiveparameter") - 1, - MIN(i, call->func->common.num_args) - ); - is_sensitive = attribute != NULL; + is_sensitive = backtrace_is_arg_sensitive(call, MIN(i, call->func->common.num_args)); } if (EXPECTED(Z_TYPE_INFO_P(p) != IS_UNDEF)) { @@ -1823,8 +1819,7 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) / if (is_sensitive) { zval redacted_arg; - object_init_ex(&redacted_arg, zend_ce_sensitive_parameter_value); - zend_call_known_function(Z_OBJCE_P(&redacted_arg)->constructor, Z_OBJ_P(&redacted_arg), Z_OBJCE_P(&redacted_arg), NULL, 1, &original_arg, NULL); + object_init_with_constructor(&redacted_arg, zend_ce_sensitive_parameter_value, 1, &original_arg, NULL); ZEND_HASH_FILL_SET(&redacted_arg); } else { Z_TRY_ADDREF_P(&original_arg); @@ -1841,14 +1836,27 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) / ZVAL_EMPTY_ARRAY(arg_array); } - if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) { + if ((ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) + /* __call and __callStatic are non-variadic, potentially with + * HAS_EXTRA_NAMED_PARAMS set. Don't add extra args, as they're already + * contained in the 2nd param. */ + && (call->func->common.fn_flags & ZEND_ACC_VARIADIC)) { zend_string *name; zval *arg; + + bool is_sensitive = backtrace_is_arg_sensitive(call, call->func->common.num_args); + SEPARATE_ARRAY(arg_array); ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(call->extra_named_params, name, arg) { ZVAL_DEREF(arg); - Z_TRY_ADDREF_P(arg); - zend_hash_add_new(Z_ARRVAL_P(arg_array), name, arg); + if (is_sensitive) { + zval redacted_arg; + object_init_with_constructor(&redacted_arg, zend_ce_sensitive_parameter_value, 1, arg, NULL); + zend_hash_add_new(Z_ARRVAL_P(arg_array), name, &redacted_arg); + } else { + Z_TRY_ADDREF_P(arg); + zend_hash_add_new(Z_ARRVAL_P(arg_array), name, arg); + } } ZEND_HASH_FOREACH_END(); } } @@ -1880,7 +1888,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int { zend_execute_data *call, *last_call = NULL; zend_object *object; - bool fake_frame = 0; + bool fake_frame = false; int lineno, frameno = 0; zend_function *func; zend_string *filename; @@ -1979,8 +1987,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)) { @@ -2117,7 +2124,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int } } else { /* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */ - bool build_filename_arg = 1; + bool build_filename_arg = true; zend_string *pseudo_function_name; uint32_t include_kind = 0; if (prev && prev->func && ZEND_USER_CODE(prev->func->common.type) && prev->opline->opcode == ZEND_INCLUDE_OR_EVAL) { @@ -2127,7 +2134,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int switch (include_kind) { case ZEND_EVAL: pseudo_function_name = ZSTR_KNOWN(ZEND_STR_EVAL); - build_filename_arg = 0; + build_filename_arg = false; break; case ZEND_INCLUDE: pseudo_function_name = ZSTR_KNOWN(ZEND_STR_INCLUDE); @@ -2149,7 +2156,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int } pseudo_function_name = ZSTR_KNOWN(ZEND_STR_UNKNOWN); - build_filename_arg = 0; + build_filename_arg = false; break; } @@ -2183,9 +2190,9 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int && prev->func && ZEND_USER_CODE(prev->func->common.type) && prev->opline->opcode == ZEND_INCLUDE_OR_EVAL) { - fake_frame = 1; + fake_frame = true; } else { - fake_frame = 0; + fake_frame = false; include_filename = filename; last_call = call; call = prev; @@ -2255,9 +2262,9 @@ ZEND_FUNCTION(get_extension_funcs) if (module->functions) { /* avoid BC break, if functions list is empty, will return an empty array */ array_init(return_value); - array = 1; + array = true; } else { - array = 0; + array = false; } ZEND_HASH_MAP_FOREACH_PTR(CG(function_table), zif) { @@ -2265,7 +2272,7 @@ ZEND_FUNCTION(get_extension_funcs) && zif->internal_function.module == module) { if (!array) { array_init(return_value); - array = 1; + array = true; } add_next_index_str(return_value, zend_string_copy(zif->common.function_name)); } 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..17484eb03f253 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) @@ -386,9 +387,9 @@ static zend_class_entry *register_class_stdClass(void) INIT_CLASS_ENTRY(ce, "stdClass", NULL); class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES); - zend_string *attribute_name_AllowDynamicProperties_class_stdClass_0 = zend_string_init_interned("AllowDynamicProperties", sizeof("AllowDynamicProperties") - 1, 1); + zend_string *attribute_name_AllowDynamicProperties_class_stdClass_0 = zend_string_init_interned("AllowDynamicProperties", sizeof("AllowDynamicProperties") - 1, true); zend_add_class_attribute(class_entry, attribute_name_AllowDynamicProperties_class_stdClass_0, 0); - zend_string_release(attribute_name_AllowDynamicProperties_class_stdClass_0); + zend_string_release_ex(attribute_name_AllowDynamicProperties_class_stdClass_0, true); return class_entry; } diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 5777e1a34a2b8..05b6862044816 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -81,46 +81,46 @@ 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"); - return 0; + zend_error(E_WARNING, "Cannot bind an instance to a static closure, this will be an error in PHP 9"); + return false; } 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)); - return 0; + return false; } } else if (is_fake_closure && func->common.scope && !(func->common.fn_flags & ZEND_ACC_STATIC)) { - zend_error(E_WARNING, "Cannot unbind $this of method"); - return 0; + zend_error(E_WARNING, "Cannot unbind $this of method, this will be an error in PHP 9"); + return false; } 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"); - return 0; + zend_error(E_WARNING, "Cannot unbind $this of closure using $this, this will be an error in PHP 9"); + return false; } 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; + return false; } 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; + return false; } - return 1; + return true; } /* }}} */ @@ -287,6 +287,19 @@ ZEND_METHOD(Closure, bindTo) do_closure_bind(return_value, ZEND_THIS, newthis, scope_obj, scope_str); } +static void zend_copy_parameters_array(const uint32_t param_count, HashTable *argument_array) /* {{{ */ +{ + zval *param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1); + + ZEND_ASSERT(param_count <= ZEND_CALL_NUM_ARGS(EG(current_execute_data))); + + for (uint32_t i = 0; i < param_count; i++) { + Z_TRY_ADDREF_P(param_ptr); + zend_hash_next_index_insert_new(argument_array, param_ptr); + param_ptr++; + } +} + static ZEND_NAMED_FUNCTION(zend_closure_call_magic) /* {{{ */ { zend_fcall_info fci; zend_fcall_info_cache fcc; @@ -310,14 +323,14 @@ static ZEND_NAMED_FUNCTION(zend_closure_call_magic) /* {{{ */ { array_init_size(&fci.params[1], ZEND_NUM_ARGS() + zend_hash_num_elements(EX(extra_named_params))); /* Avoid conversion from packed to mixed later. */ zend_hash_real_init_mixed(Z_ARRVAL(fci.params[1])); - zend_copy_parameters_array(ZEND_NUM_ARGS(), &fci.params[1]); + zend_copy_parameters_array(ZEND_NUM_ARGS(), Z_ARRVAL(fci.params[1])); ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, named_param_zval) { Z_TRY_ADDREF_P(named_param_zval); zend_hash_add_new(Z_ARRVAL(fci.params[1]), name, named_param_zval); } ZEND_HASH_FOREACH_END(); } else if (ZEND_NUM_ARGS()) { array_init_size(&fci.params[1], ZEND_NUM_ARGS()); - zend_copy_parameters_array(ZEND_NUM_ARGS(), &fci.params[1]); + zend_copy_parameters_array(ZEND_NUM_ARGS(), Z_ARRVAL(fci.params[1])); } else { ZVAL_EMPTY_ARRAY(&fci.params[1]); } @@ -418,6 +431,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"); @@ -480,7 +510,7 @@ ZEND_API zend_function *zend_get_closure_invoke_method(zend_object *object) /* { * ZEND_ACC_USER_ARG_INFO flag to prevent invalid usage by Reflection */ invoke->type = ZEND_INTERNAL_FUNCTION; invoke->internal_function.fn_flags = - ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER | (closure->func.common.fn_flags & keep_flags); + ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER | ZEND_ACC_NEVER_CACHE | (closure->func.common.fn_flags & keep_flags); if (closure->func.type != ZEND_INTERNAL_FUNCTION || (closure->func.common.fn_flags & ZEND_ACC_USER_ARG_INFO)) { invoke->internal_function.fn_flags |= ZEND_ACC_USER_ARG_INFO; @@ -588,7 +618,6 @@ static HashTable *zend_closure_get_debug_info(zend_object *object, int *is_temp) zval val; struct _zend_arg_info *arg_info = closure->func.common.arg_info; HashTable *debug_info; - bool zstr_args = (closure->func.type == ZEND_USER_FUNCTION) || (closure->func.common.fn_flags & ZEND_ACC_USER_ARG_INFO); *is_temp = 1; @@ -664,15 +693,9 @@ static HashTable *zend_closure_get_debug_info(zend_object *object, int *is_temp) zend_string *name; zval info; ZEND_ASSERT(arg_info->name && "Argument should have name"); - if (zstr_args) { - name = zend_strpprintf(0, "%s$%s", - ZEND_ARG_SEND_MODE(arg_info) ? "&" : "", - ZSTR_VAL(arg_info->name)); - } else { - name = zend_strpprintf(0, "%s$%s", - ZEND_ARG_SEND_MODE(arg_info) ? "&" : "", - ((zend_internal_arg_info*)arg_info)->name); - } + name = zend_strpprintf(0, "%s$%s", + ZEND_ARG_SEND_MODE(arg_info) ? "&" : "", + ZSTR_VAL(arg_info->name)); ZVAL_NEW_STR(&info, zend_strpprintf(0, "%s", i >= required ? "" : "")); zend_hash_update(Z_ARRVAL(val), name, &info); zend_string_release_ex(name, 0); @@ -849,13 +872,15 @@ ZEND_API void zend_create_fake_closure(zval *res, zend_function *func, zend_clas closure = (zend_closure *)Z_OBJ_P(res); closure->func.common.fn_flags |= ZEND_ACC_FAKE_CLOSURE; + if (Z_TYPE(closure->this_ptr) != IS_OBJECT) { + GC_ADD_FLAGS(&closure->std, GC_NOT_COLLECTABLE); + } } /* }}} */ -/* __call and __callStatic name the arguments "$arguments" in the docs. */ -static zend_internal_arg_info trampoline_arg_info[] = {ZEND_ARG_VARIADIC_TYPE_INFO(false, arguments, IS_MIXED, false)}; +static zend_arg_info trampoline_arg_info[1]; -void zend_closure_from_frame(zval *return_value, zend_execute_data *call) { /* {{{ */ +void zend_closure_from_frame(zval *return_value, const zend_execute_data *call) { /* {{{ */ zval instance; zend_internal_function trampoline; zend_function *mptr = call->func; @@ -918,3 +943,11 @@ void zend_closure_bind_var_ex(zval *closure_zv, uint32_t offset, zval *val) /* { ZVAL_COPY_VALUE(var, val); } /* }}} */ + +void zend_closure_startup(void) +{ + /* __call and __callStatic name the arguments "$arguments" in the docs. */ + trampoline_arg_info[0].name = zend_string_init_interned("arguments", strlen("arguments"), true); + trampoline_arg_info[0].type = (zend_type)ZEND_TYPE_INIT_CODE(IS_MIXED, false, _ZEND_ARG_INFO_FLAGS(false, 1, 0)); + trampoline_arg_info[0].default_value = NULL; +} diff --git a/Zend/zend_closures.h b/Zend/zend_closures.h index ced1b5ba48c15..a118044c6e248 100644 --- a/Zend/zend_closures.h +++ b/Zend/zend_closures.h @@ -28,10 +28,11 @@ BEGIN_EXTERN_C() #define ZEND_CLOSURE_OBJECT(op_array) \ ((zend_object*)((char*)(op_array) - sizeof(zend_object))) +void zend_closure_startup(void); void zend_register_closure_ce(void); void zend_closure_bind_var(zval *closure_zv, zend_string *var_name, zval *var); void zend_closure_bind_var_ex(zval *closure_zv, uint32_t offset, zval *val); -void zend_closure_from_frame(zval *closure_zv, zend_execute_data *frame); +void zend_closure_from_frame(zval *closure_zv, const zend_execute_data *frame); extern ZEND_API zend_class_entry *zend_ce_closure; 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 4fe06dbea52c4..5eba2ec1366fa 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -28,6 +28,7 @@ #include "zend_API.h" #include "zend_exceptions.h" #include "zend_interfaces.h" +#include "zend_types.h" #include "zend_virtual_cwd.h" #include "zend_multibyte.h" #include "zend_language_scanner.h" @@ -339,6 +340,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; @@ -347,7 +349,7 @@ void zend_oparray_context_begin(zend_oparray_context *prev_context, zend_op_arra } /* }}} */ -void zend_oparray_context_end(zend_oparray_context *prev_context) /* {{{ */ +void zend_oparray_context_end(const zend_oparray_context *prev_context) /* {{{ */ { if (CG(context).brk_cont_array) { efree(CG(context).brk_cont_array); @@ -410,7 +412,7 @@ void zend_file_context_begin(zend_file_context *prev_context) /* {{{ */ } /* }}} */ -void zend_file_context_end(zend_file_context *prev_context) /* {{{ */ +void zend_file_context_end(const zend_file_context *prev_context) /* {{{ */ { zend_end_namespace(); zend_hash_destroy(&FC(seen_symbols)); @@ -445,7 +447,7 @@ static void zend_register_seen_symbol(zend_string *name, uint32_t kind) { } static bool zend_have_seen_symbol(zend_string *name, uint32_t kind) { - zval *zv = zend_hash_find(&FC(seen_symbols), name); + const zval *zv = zend_hash_find(&FC(seen_symbols), name); return zv && (Z_LVAL_P(zv) & kind) != 0; } @@ -517,7 +519,7 @@ ZEND_API zend_string *zend_get_compiled_filename(void) /* {{{ */ } /* }}} */ -ZEND_API int zend_get_compiled_lineno(void) /* {{{ */ +ZEND_API uint32_t zend_get_compiled_lineno(void) /* {{{ */ { return CG(zend_lineno); } @@ -535,7 +537,7 @@ static zend_always_inline uint32_t get_temporary_variable(void) /* {{{ */ } /* }}} */ -static int lookup_cv(zend_string *name) /* {{{ */{ +static uint32_t lookup_cv(zend_string *name) /* {{{ */{ zend_op_array *op_array = CG(active_op_array); int i = 0; zend_ulong hash_value = zend_string_hash_val(name); @@ -570,7 +572,7 @@ zend_string *zval_make_interned_string(zval *zv) } /* Common part of zend_add_literal and zend_append_individual_literal */ -static inline void zend_insert_literal(zend_op_array *op_array, zval *zv, int literal_position) /* {{{ */ +static inline void zend_insert_literal(const zend_op_array *op_array, zval *zv, int literal_position) /* {{{ */ { zval *lit = CT_CONSTANT_EX(op_array, literal_position); if (Z_TYPE_P(zv) == IS_STRING) { @@ -587,7 +589,7 @@ static inline void zend_insert_literal(zend_op_array *op_array, zval *zv, int li static int zend_add_literal(zval *zv) /* {{{ */ { zend_op_array *op_array = CG(active_op_array); - int i = op_array->last_literal; + uint32_t i = op_array->last_literal; op_array->last_literal++; if (i >= CG(context).literals_size) { while (i >= CG(context).literals_size) { @@ -821,7 +823,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); @@ -949,7 +952,7 @@ uint32_t zend_modifier_token_to_flag(zend_modifier_target target, uint32_t token uint32_t zend_modifier_list_to_flags(zend_modifier_target target, zend_ast *modifiers) { uint32_t flags = 0; - zend_ast_list *modifier_list = zend_ast_get_list(modifiers); + const zend_ast_list *modifier_list = zend_ast_get_list(modifiers); for (uint32_t i = 0; i < modifier_list->children; i++) { uint32_t token = (uint32_t) Z_LVAL_P(zend_ast_get_zval(modifier_list->child[i])); @@ -1048,20 +1051,20 @@ uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag, zend_modifi } /* }}} */ -ZEND_API zend_string *zend_create_member_string(zend_string *class_name, zend_string *member_name) { +ZEND_API zend_string *zend_create_member_string(const zend_string *class_name, const zend_string *member_name) { return zend_string_concat3( ZSTR_VAL(class_name), ZSTR_LEN(class_name), "::", sizeof("::") - 1, ZSTR_VAL(member_name), ZSTR_LEN(member_name)); } -static zend_string *zend_concat_names(char *name1, size_t name1_len, char *name2, size_t name2_len) { +static zend_string *zend_concat_names(const char *name1, size_t name1_len, const char *name2, size_t name2_len) { return zend_string_concat3(name1, name1_len, "\\", 1, name2, name2_len); } static zend_string *zend_prefix_with_ns(zend_string *name) { if (FC(current_namespace)) { - zend_string *ns = FC(current_namespace); + const zend_string *ns = FC(current_namespace); return zend_concat_names(ZSTR_VAL(ns), ZSTR_LEN(ns), ZSTR_VAL(name), ZSTR_LEN(name)); } else { return zend_string_copy(name); @@ -1070,24 +1073,24 @@ static zend_string *zend_prefix_with_ns(zend_string *name) { static zend_string *zend_resolve_non_class_name( zend_string *name, uint32_t type, bool *is_fully_qualified, - bool case_sensitive, HashTable *current_import_sub + bool case_sensitive, const HashTable *current_import_sub ) { - char *compound; - *is_fully_qualified = 0; + const char *compound; + *is_fully_qualified = false; if (ZSTR_VAL(name)[0] == '\\') { /* Remove \ prefix (only relevant if this is a string rather than a label) */ - *is_fully_qualified = 1; + *is_fully_qualified = true; return zend_string_init(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1, 0); } if (type == ZEND_NAME_FQ) { - *is_fully_qualified = 1; + *is_fully_qualified = true; return zend_string_copy(name); } if (type == ZEND_NAME_RELATIVE) { - *is_fully_qualified = 1; + *is_fully_qualified = true; return zend_prefix_with_ns(name); } @@ -1101,20 +1104,20 @@ static zend_string *zend_resolve_non_class_name( } if (import_name) { - *is_fully_qualified = 1; + *is_fully_qualified = true; return zend_string_copy(import_name); } } compound = memchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name)); if (compound) { - *is_fully_qualified = 1; + *is_fully_qualified = true; } if (compound && FC(imports)) { /* If the first part of a qualified name is an alias, substitute it. */ size_t len = compound - ZSTR_VAL(name); - zend_string *import_name = zend_hash_str_find_ptr_lc(FC(imports), ZSTR_VAL(name), len); + const zend_string *import_name = zend_hash_str_find_ptr_lc(FC(imports), ZSTR_VAL(name), len); if (import_name) { return zend_concat_names( @@ -1129,18 +1132,18 @@ static zend_string *zend_resolve_non_class_name( static zend_string *zend_resolve_function_name(zend_string *name, uint32_t type, bool *is_fully_qualified) { return zend_resolve_non_class_name( - name, type, is_fully_qualified, 0, FC(imports_function)); + name, type, is_fully_qualified, false, FC(imports_function)); } static zend_string *zend_resolve_const_name(zend_string *name, uint32_t type, bool *is_fully_qualified) { return zend_resolve_non_class_name( - name, type, is_fully_qualified, 1, FC(imports_const)); + name, type, is_fully_qualified, true, FC(imports_const)); } static zend_string *zend_resolve_class_name(zend_string *name, uint32_t type) /* {{{ */ { - char *compound; + const char *compound; if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) { if (type == ZEND_NAME_FQ) { @@ -1178,7 +1181,7 @@ static zend_string *zend_resolve_class_name(zend_string *name, uint32_t type) /* if (compound) { /* If the first part of a qualified name is an alias, substitute it. */ size_t len = compound - ZSTR_VAL(name); - zend_string *import_name = + const zend_string *import_name = zend_hash_str_find_ptr_lc(FC(imports), ZSTR_VAL(name), len); if (import_name) { @@ -1203,7 +1206,7 @@ static zend_string *zend_resolve_class_name(zend_string *name, uint32_t type) /* static zend_string *zend_resolve_class_name_ast(zend_ast *ast) /* {{{ */ { - zval *class_name = zend_ast_get_zval(ast); + const zval *class_name = zend_ast_get_zval(ast); if (Z_TYPE_P(class_name) != IS_STRING) { zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name"); } @@ -1222,8 +1225,6 @@ static void str_dtor(zval *zv) /* {{{ */ { } /* }}} */ -static bool zend_is_call(zend_ast *ast); - static uint32_t zend_add_try_element(uint32_t try_op) /* {{{ */ { zend_op_array *op_array = CG(active_op_array); @@ -1261,14 +1262,14 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */ } /* }}} */ -static zend_never_inline ZEND_COLD ZEND_NORETURN void do_bind_function_error(zend_string *lcname, zend_op_array *op_array, bool compile_time) /* {{{ */ +static zend_never_inline ZEND_COLD ZEND_NORETURN void do_bind_function_error(const zend_string *lcname, const zend_op_array *op_array, bool compile_time) /* {{{ */ { - zval *zv = zend_hash_find_known_hash(compile_time ? CG(function_table) : EG(function_table), lcname); + const zval *zv = zend_hash_find_known_hash(compile_time ? CG(function_table) : EG(function_table), lcname); int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR; - zend_function *old_function; + const zend_function *old_function; ZEND_ASSERT(zv != NULL); - old_function = (zend_function*)Z_PTR_P(zv); + old_function = Z_PTR_P(zv); if (old_function->type == ZEND_USER_FUNCTION && old_function->op_array.last > 0) { zend_error_noreturn(error_level, "Cannot redeclare function %s() (previously declared in %s:%d)", @@ -1281,11 +1282,11 @@ static zend_never_inline ZEND_COLD ZEND_NORETURN void do_bind_function_error(zen } } -ZEND_API zend_result do_bind_function(zend_function *func, zval *lcname) /* {{{ */ +ZEND_API zend_result do_bind_function(zend_function *func, const zval *lcname) /* {{{ */ { zend_function *added_func = zend_hash_add_ptr(EG(function_table), Z_STR_P(lcname), func); if (UNEXPECTED(!added_func)) { - do_bind_function_error(Z_STR_P(lcname), &func->op_array, 0); + do_bind_function_error(Z_STR_P(lcname), &func->op_array, false); return FAILURE; } @@ -1301,7 +1302,7 @@ ZEND_API zend_result do_bind_function(zend_function *func, zval *lcname) /* {{{ /* }}} */ ZEND_API zend_class_entry *zend_bind_class_in_slot( - zval *class_table_slot, zval *lcname, zend_string *lc_parent_name) + zval *class_table_slot, const zval *lcname, zend_string *lc_parent_name) { zend_class_entry *ce = Z_PTR_P(class_table_slot); bool is_preloaded = @@ -1327,7 +1328,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; } @@ -1344,7 +1344,6 @@ ZEND_API zend_class_entry *zend_bind_class_in_slot( ZEND_API zend_result do_bind_class(zval *lcname, zend_string *lc_parent_name) /* {{{ */ { - zend_class_entry *ce; zval *rtd_key, *zv; rtd_key = lcname + 1; @@ -1352,7 +1351,7 @@ ZEND_API zend_result do_bind_class(zval *lcname, zend_string *lc_parent_name) /* zv = zend_hash_find_known_hash(EG(class_table), Z_STR_P(rtd_key)); if (UNEXPECTED(!zv)) { - ce = zend_hash_find_ptr(EG(class_table), Z_STR_P(lcname)); + const zend_class_entry *ce = zend_hash_find_ptr(EG(class_table), Z_STR_P(lcname)); ZEND_ASSERT(ce); zend_class_redeclaration_error(E_COMPILE_ERROR, ce); return FAILURE; @@ -1381,7 +1380,7 @@ static zend_string *add_type_string(zend_string *type, zend_string *new_type, bo return result; } -static zend_string *resolve_class_name(zend_string *name, zend_class_entry *scope) { +static zend_string *resolve_class_name(zend_string *name, const zend_class_entry *scope) { if (scope) { if (zend_string_equals_ci(name, ZSTR_KNOWN(ZEND_STR_SELF))) { name = scope->name; @@ -1394,7 +1393,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); @@ -1464,7 +1462,7 @@ zend_string *zend_type_to_string_resolved(const zend_type type, zend_class_entry zend_string *name = ZSTR_KNOWN(ZEND_STR_STATIC); // During compilation of eval'd code the called scope refers to the scope calling the eval if (scope && !zend_is_compiling()) { - zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data)); + const zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data)); if (called_scope) { name = called_scope->name; } @@ -1542,7 +1540,7 @@ static void zend_mark_function_as_generator(void) /* {{{ */ ZEND_TYPE_FOREACH(return_type, single_type) { if (ZEND_TYPE_HAS_NAME(*single_type) && is_generator_compatible_class_type(ZEND_TYPE_NAME(*single_type))) { - valid_type = 1; + valid_type = true; break; } } ZEND_TYPE_FOREACH_END(); @@ -1618,7 +1616,7 @@ ZEND_API zend_result zend_unmangle_property_name_ex(const zend_string *name, con } /* }}} */ -static bool array_is_const_ex(zend_array *array, uint32_t *max_checks) +static bool array_is_const_ex(const zend_array *array, uint32_t *max_checks) { if (zend_hash_num_elements(array) > *max_checks) { return false; @@ -1641,13 +1639,13 @@ static bool array_is_const_ex(zend_array *array, uint32_t *max_checks) return true; } -static bool array_is_const(zend_array *array) +static bool array_is_const(const zend_array *array) { uint32_t max_checks = 50; return array_is_const_ex(array, &max_checks); } -static bool can_ct_eval_const(zend_constant *c) { +static bool can_ct_eval_const(const zend_constant *c) { if (ZEND_CONSTANT_FLAGS(c) & CONST_DEPRECATED) { return 0; } @@ -1716,7 +1714,7 @@ static inline bool zend_is_scope_known(void) /* {{{ */ } /* }}} */ -static inline bool class_name_refers_to_active_ce(zend_string *class_name, uint32_t fetch_type) /* {{{ */ +static inline bool class_name_refers_to_active_ce(const zend_string *class_name, uint32_t fetch_type) /* {{{ */ { if (!CG(active_class_entry)) { return 0; @@ -1784,7 +1782,7 @@ static void zend_ensure_valid_class_fetch_type(uint32_t fetch_type) /* {{{ */ static bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_ast *class_ast) /* {{{ */ { uint32_t fetch_type; - zval *class_name; + const zval *class_name; if (class_ast->kind != ZEND_AST_ZVAL) { return 0; @@ -1824,7 +1822,7 @@ static bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_ast *c /* }}} */ /* We don't use zend_verify_const_access because we need to deal with unlinked classes. */ -static bool zend_verify_ct_const_access(zend_class_constant *c, zend_class_entry *scope) +static bool zend_verify_ct_const_access(const zend_class_constant *c, const zend_class_entry *scope) { if (ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED) { return 0; @@ -1869,7 +1867,7 @@ static bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name, zend if (class_name_refers_to_active_ce(class_name, fetch_type)) { cc = zend_hash_find_ptr(&CG(active_class_entry)->constants_table, name); } else if (fetch_type == ZEND_FETCH_CLASS_DEFAULT && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) { - zend_class_entry *ce = zend_hash_find_ptr_lc(CG(class_table), class_name); + const zend_class_entry *ce = zend_hash_find_ptr_lc(CG(class_table), class_name); if (ce) { cc = zend_hash_find_ptr(&ce->constants_table, name); } else { @@ -1922,7 +1920,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 +1931,9 @@ static void zend_do_extended_stmt(void) /* {{{ */ opline = get_next_op(); opline->opcode = ZEND_EXT_STMT; + if (result) { + SET_NODE(opline->op1, result); + } } /* }}} */ @@ -2011,12 +2012,12 @@ ZEND_API void zend_activate_auto_globals(void) /* {{{ */ zend_auto_global *auto_global; ZEND_HASH_MAP_FOREACH_PTR(CG(auto_globals), auto_global) { - if (auto_global->jit) { - auto_global->armed = 1; - } else if (auto_global->auto_global_callback) { + auto_global->armed = auto_global->jit || auto_global->auto_global_callback; + } ZEND_HASH_FOREACH_END(); + + ZEND_HASH_MAP_FOREACH_PTR(CG(auto_globals), auto_global) { + if (auto_global->armed && !auto_global->jit) { auto_global->armed = auto_global->auto_global_callback(auto_global->name); - } else { - auto_global->armed = 0; } } ZEND_HASH_FOREACH_END(); } @@ -2045,6 +2046,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, bool nullify_hand ce->refcount = 1; ce->ce_flags = ZEND_ACC_CONSTANTS_UPDATED; + ce->ce_flags2 = 0; if (CG(compiler_options) & ZEND_COMPILE_GUARDS) { ce->ce_flags |= ZEND_ACC_USE_GUARDS; @@ -2537,7 +2539,7 @@ static uint32_t zend_short_circuiting_checkpoint(void) return zend_stack_count(&CG(short_circuiting_opnums)); } -static void zend_short_circuiting_commit(uint32_t checkpoint, znode *result, zend_ast *ast) +static void zend_short_circuiting_commit(uint32_t checkpoint, znode *result, const zend_ast *ast) { bool is_short_circuited = zend_ast_kind_is_short_circuited(ast->kind) || ast->kind == ZEND_AST_ISSET || ast->kind == ZEND_AST_EMPTY; @@ -2603,7 +2605,7 @@ static void zend_compile_memoized_expr(znode *result, zend_ast *expr) /* {{{ */ zend_hash_index_update_mem( CG(memoized_exprs), (uintptr_t) expr, &memoized_result, sizeof(znode)); } else if (memoize_mode == ZEND_MEMOIZE_FETCH) { - znode *memoized_result = zend_hash_index_find_ptr(CG(memoized_exprs), (uintptr_t) expr); + const znode *memoized_result = zend_hash_index_find_ptr(CG(memoized_exprs), (uintptr_t) expr); *result = *memoized_result; if (result->op_type == IS_CONST) { Z_TRY_ADDREF(result->u.constant); @@ -2615,7 +2617,7 @@ static void zend_compile_memoized_expr(znode *result, zend_ast *expr) /* {{{ */ /* }}} */ static void zend_emit_return_type_check( - znode *expr, zend_arg_info *return_info, bool implicit) /* {{{ */ + znode *expr, const zend_arg_info *return_info, bool implicit) /* {{{ */ { zend_type type = return_info->type; if (ZEND_TYPE_IS_SET(type)) { @@ -2694,7 +2696,7 @@ void zend_emit_final_return(bool return_one) /* {{{ */ return; } - zend_emit_return_type_check(NULL, return_info, 1); + zend_emit_return_type_check(NULL, return_info, true); } zn.op_type = IS_CONST; @@ -2709,7 +2711,7 @@ void zend_emit_final_return(bool return_one) /* {{{ */ } /* }}} */ -static inline bool zend_is_variable(zend_ast *ast) /* {{{ */ +static inline bool zend_is_variable(const zend_ast *ast) /* {{{ */ { return ast->kind == ZEND_AST_VAR || ast->kind == ZEND_AST_DIM @@ -2719,22 +2721,23 @@ static inline bool zend_is_variable(zend_ast *ast) /* {{{ */ } /* }}} */ -static inline bool zend_is_call(zend_ast *ast) /* {{{ */ +static inline bool zend_is_call(const 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; } /* }}} */ -static inline bool zend_is_variable_or_call(zend_ast *ast) /* {{{ */ +static inline bool zend_is_variable_or_call(const zend_ast *ast) /* {{{ */ { return zend_is_variable(ast) || zend_is_call(ast); } /* }}} */ -static inline bool zend_is_unticked_stmt(zend_ast *ast) /* {{{ */ +static inline bool zend_is_unticked_stmt(const zend_ast *ast) /* {{{ */ { return ast->kind == ZEND_AST_STMT_LIST || ast->kind == ZEND_AST_LABEL || ast->kind == ZEND_AST_PROP_DECL || ast->kind == ZEND_AST_CLASS_CONST_GROUP @@ -2742,7 +2745,7 @@ static inline bool zend_is_unticked_stmt(zend_ast *ast) /* {{{ */ } /* }}} */ -static inline bool zend_can_write_to_variable(zend_ast *ast) /* {{{ */ +static inline bool zend_can_write_to_variable(const zend_ast *ast) /* {{{ */ { while ( ast->kind == ZEND_AST_DIM @@ -2778,7 +2781,7 @@ static inline void zend_handle_numeric_op(znode *node) /* {{{ */ } /* }}} */ -static inline void zend_handle_numeric_dim(zend_op *opline, znode *dim_node) /* {{{ */ +static inline void zend_handle_numeric_dim(const zend_op *opline, znode *dim_node) /* {{{ */ { if (Z_TYPE(dim_node->u.constant) == IS_STRING) { zend_ulong index; @@ -2864,7 +2867,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, const zend_ast *ast, uint32_t type) /* {{{ */ { zend_ast *name_ast = ast->child[0]; if (name_ast->kind == ZEND_AST_ZVAL) { @@ -2881,6 +2884,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); @@ -2895,7 +2908,7 @@ static zend_result zend_try_compile_cv(znode *result, zend_ast *ast) /* {{{ */ } /* }}} */ -static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint32_t type, bool delayed) /* {{{ */ +static zend_op *zend_compile_simple_var_no_cv(znode *result, const zend_ast *ast, uint32_t type, bool delayed) /* {{{ */ { zend_ast *name_ast = ast->child[0]; znode name_node; @@ -2917,6 +2930,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; } @@ -2925,10 +2946,10 @@ static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint } /* }}} */ -static bool is_this_fetch(zend_ast *ast) /* {{{ */ +static bool is_this_fetch(const zend_ast *ast) /* {{{ */ { if (ast->kind == ZEND_AST_VAR && ast->child[0]->kind == ZEND_AST_ZVAL) { - zval *name = zend_ast_get_zval(ast->child[0]); + const zval *name = zend_ast_get_zval(ast->child[0]); return Z_TYPE_P(name) == IS_STRING && zend_string_equals(Z_STR_P(name), ZSTR_KNOWN(ZEND_STR_THIS)); } @@ -2939,25 +2960,25 @@ static bool is_this_fetch(zend_ast *ast) /* {{{ */ static bool is_globals_fetch(const zend_ast *ast) { if (ast->kind == ZEND_AST_VAR && ast->child[0]->kind == ZEND_AST_ZVAL) { - zval *name = zend_ast_get_zval(ast->child[0]); + const zval *name = zend_ast_get_zval(ast->child[0]); return Z_TYPE_P(name) == IS_STRING && zend_string_equals_literal(Z_STR_P(name), "GLOBALS"); } return 0; } -static bool is_global_var_fetch(zend_ast *ast) +static bool is_global_var_fetch(const zend_ast *ast) { return ast->kind == ZEND_AST_DIM && is_globals_fetch(ast->child[0]); } static bool this_guaranteed_exists(void) /* {{{ */ { - zend_oparray_context *ctx = &CG(context); + const zend_oparray_context *ctx = &CG(context); while (ctx) { /* Instance methods always have a $this. * This also includes closures that have a scope and use $this. */ - zend_op_array *op_array = ctx->op_array; + const zend_op_array *op_array = ctx->op_array; if (op_array->fn_flags & ZEND_ACC_STATIC) { return false; } else if (op_array->scope) { @@ -2971,7 +2992,7 @@ static bool this_guaranteed_exists(void) /* {{{ */ } /* }}} */ -static zend_op *zend_compile_simple_var(znode *result, zend_ast *ast, uint32_t type, bool delayed) /* {{{ */ +static zend_op *zend_compile_simple_var(znode *result, const zend_ast *ast, uint32_t type, bool delayed) /* {{{ */ { if (is_this_fetch(ast)) { zend_op *opline = zend_emit_op(result, ZEND_FETCH_THIS, NULL, NULL); @@ -2988,14 +3009,14 @@ 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; } /* }}} */ -static void zend_separate_if_call_and_write(znode *node, zend_ast *ast, uint32_t type) /* {{{ */ +static void zend_separate_if_call_and_write(znode *node, const zend_ast *ast, uint32_t type) /* {{{ */ { if (type != BP_VAR_R && type != BP_VAR_IS @@ -3013,7 +3034,7 @@ static void zend_separate_if_call_and_write(znode *node, zend_ast *ast, uint32_t } /* }}} */ -static inline void zend_emit_assign_znode(zend_ast *var_ast, znode *value_node) /* {{{ */ +static inline void zend_emit_assign_znode(zend_ast *var_ast, const znode *value_node) /* {{{ */ { znode dummy_node; zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN, var_ast, @@ -3047,7 +3068,7 @@ static zend_op *zend_delayed_compile_dim(znode *result, zend_ast *ast, uint32_t return opline; } else { zend_short_circuiting_mark_inner(var_ast); - opline = zend_delayed_compile_var(&var_node, var_ast, type, 0); + opline = zend_delayed_compile_var(&var_node, var_ast, type, false); if (opline) { if (type == BP_VAR_W && (opline->opcode == ZEND_FETCH_STATIC_PROP_W || opline->opcode == ZEND_FETCH_OBJ_W)) { opline->extended_value |= ZEND_FETCH_DIM_WRITE; @@ -3115,7 +3136,7 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t * check for a nullsafe access. */ } else { zend_short_circuiting_mark_inner(obj_ast); - opline = zend_delayed_compile_var(&obj_node, obj_ast, type, 0); + opline = zend_delayed_compile_var(&obj_node, obj_ast, type, false); if (opline && (opline->opcode == ZEND_FETCH_DIM_W || opline->opcode == ZEND_FETCH_DIM_RW || opline->opcode == ZEND_FETCH_DIM_FUNC_ARG @@ -3221,7 +3242,7 @@ static zend_op *zend_compile_static_prop(znode *result, zend_ast *ast, uint32_t } /* }}} */ -static void zend_verify_list_assign_target(zend_ast *var_ast, zend_ast_attr array_style) /* {{{ */ { +static void zend_verify_list_assign_target(const zend_ast *var_ast, zend_ast_attr array_style) /* {{{ */ { if (var_ast->kind == ZEND_AST_ARRAY) { if (var_ast->attr == ZEND_ARRAY_SYNTAX_LONG) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot assign to array(), use [] instead"); @@ -3235,12 +3256,12 @@ static void zend_verify_list_assign_target(zend_ast *var_ast, zend_ast_attr arra } /* }}} */ -static inline void zend_emit_assign_ref_znode(zend_ast *var_ast, znode *value_node); +static inline void zend_emit_assign_ref_znode(zend_ast *var_ast, const znode *value_node); /* Propagate refs used on leaf elements to the surrounding list() structures. */ static bool zend_propagate_list_refs(zend_ast *ast) { /* {{{ */ - zend_ast_list *list = zend_ast_get_list(ast); - bool has_refs = 0; + const zend_ast_list *list = zend_ast_get_list(ast); + bool has_refs = false; uint32_t i; for (i = 0; i < list->children; ++i) { @@ -3259,10 +3280,10 @@ static bool zend_propagate_list_refs(zend_ast *ast) { /* {{{ */ } /* }}} */ -static bool list_is_keyed(zend_ast_list *list) +static bool list_is_keyed(const zend_ast_list *list) { for (uint32_t i = 0; i < list->children; i++) { - zend_ast *child = list->child[i]; + const zend_ast *child = list->child[i]; if (child) { return child->kind == ZEND_AST_ARRAY_ELEM && child->child[1] != NULL; } @@ -3275,7 +3296,7 @@ static void zend_compile_list_assign( { zend_ast_list *list = zend_ast_get_list(ast); uint32_t i; - bool has_elems = 0; + bool has_elems = false; bool is_keyed = list_is_keyed(list); if (list->children && expr_node->op_type == IS_CONST && Z_TYPE(expr_node->u.constant) == IS_STRING) { @@ -3304,7 +3325,7 @@ static void zend_compile_list_assign( var_ast = elem_ast->child[0]; key_ast = elem_ast->child[1]; - has_elems = 1; + has_elems = true; if (is_keyed) { if (key_ast == NULL) { @@ -3362,7 +3383,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 ( @@ -3383,7 +3404,7 @@ static void zend_ensure_writable_variable(const zend_ast *ast) /* {{{ */ /* }}} */ /* Detects $a... = $a pattern */ -static bool zend_is_assign_to_self(zend_ast *var_ast, zend_ast *expr_ast) /* {{{ */ +static bool zend_is_assign_to_self(const zend_ast *var_ast, const zend_ast *expr_ast) /* {{{ */ { if (expr_ast->kind != ZEND_AST_VAR || expr_ast->child[0]->kind != ZEND_AST_ZVAL) { return 0; @@ -3409,13 +3430,13 @@ static bool zend_is_assign_to_self(zend_ast *var_ast, zend_ast *expr_ast) /* {{{ /* }}} */ static void zend_compile_expr_with_potential_assign_to_self( - znode *expr_node, zend_ast *expr_ast, zend_ast *var_ast) { + znode *expr_node, zend_ast *expr_ast, const zend_ast *var_ast) { if (zend_is_assign_to_self(var_ast, expr_ast) && !is_this_fetch(expr_ast)) { /* $a[0] = $a should evaluate the right $a first */ znode cv_node; - if (zend_try_compile_cv(&cv_node, expr_ast) == FAILURE) { - zend_compile_simple_var_no_cv(expr_node, expr_ast, BP_VAR_R, 0); + 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, false); } else { zend_emit_op_tmp(expr_node, ZEND_QM_ASSIGN, &cv_node, NULL); } @@ -3443,7 +3464,7 @@ static void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */ switch (kind) { case ZEND_AST_VAR: offset = zend_delayed_compile_begin(); - zend_delayed_compile_var(&var_node, var_ast, BP_VAR_W, 0); + zend_delayed_compile_var(&var_node, var_ast, BP_VAR_W, false); zend_compile_expr(&expr_node, expr_ast); zend_delayed_compile_end(offset); CG(zend_lineno) = zend_ast_get_lineno(var_ast); @@ -3451,7 +3472,7 @@ static void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */ return; case ZEND_AST_STATIC_PROP: offset = zend_delayed_compile_begin(); - zend_delayed_compile_var(result, var_ast, BP_VAR_W, 0); + zend_delayed_compile_var(result, var_ast, BP_VAR_W, false); zend_compile_expr(&expr_node, expr_ast); opline = zend_delayed_compile_end(offset); @@ -3495,7 +3516,7 @@ static void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */ zend_assert_not_short_circuited(expr_ast); } - zend_compile_var(&expr_node, expr_ast, BP_VAR_W, 1); + zend_compile_var(&expr_node, expr_ast, BP_VAR_W, true); /* MAKE_REF is usually not necessary for CVs. However, if there are * self-assignments, this forces the RHS to evaluate first. */ zend_emit_op(&expr_node, ZEND_MAKE_REF, &expr_node, NULL); @@ -3504,8 +3525,8 @@ 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) { - zend_compile_simple_var_no_cv(&expr_node, expr_ast, BP_VAR_R, 0); + 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, false); } else { zend_emit_op_tmp(&expr_node, ZEND_QM_ASSIGN, &cv_node, NULL); } @@ -3540,8 +3561,8 @@ static void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */ } offset = zend_delayed_compile_begin(); - zend_delayed_compile_var(&target_node, target_ast, BP_VAR_W, 1); - zend_compile_var(&source_node, source_ast, BP_VAR_W, 1); + zend_delayed_compile_var(&target_node, target_ast, BP_VAR_W, true); + zend_compile_var(&source_node, source_ast, BP_VAR_W, true); if ((target_ast->kind != ZEND_AST_VAR || target_ast->child[0]->kind != ZEND_AST_ZVAL) @@ -3583,7 +3604,7 @@ static void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */ } /* }}} */ -static inline void zend_emit_assign_ref_znode(zend_ast *var_ast, znode *value_node) /* {{{ */ +static inline void zend_emit_assign_ref_znode(zend_ast *var_ast, const znode *value_node) /* {{{ */ { znode dummy_node; zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN_REF, var_ast, @@ -3610,7 +3631,7 @@ static void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */ switch (kind) { case ZEND_AST_VAR: offset = zend_delayed_compile_begin(); - zend_delayed_compile_var(&var_node, var_ast, BP_VAR_RW, 0); + zend_delayed_compile_var(&var_node, var_ast, BP_VAR_RW, false); zend_compile_expr(&expr_node, expr_ast); zend_delayed_compile_end(offset); opline = zend_emit_op_tmp(result, ZEND_ASSIGN_OP, &var_node, &expr_node); @@ -3618,7 +3639,7 @@ static void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */ return; case ZEND_AST_STATIC_PROP: offset = zend_delayed_compile_begin(); - zend_delayed_compile_var(result, var_ast, BP_VAR_RW, 0); + zend_delayed_compile_var(result, var_ast, BP_VAR_RW, false); zend_compile_expr(&expr_node, expr_ast); opline = zend_delayed_compile_end(offset); @@ -3665,23 +3686,12 @@ static void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */ } /* }}} */ -static uint32_t zend_get_arg_num(zend_function *fn, zend_string *arg_name) { +static uint32_t zend_get_arg_num(const zend_function *fn, const zend_string *arg_name) { // TODO: Caching? - if (fn->type == ZEND_USER_FUNCTION) { - for (uint32_t i = 0; i < fn->common.num_args; i++) { - zend_arg_info *arg_info = &fn->op_array.arg_info[i]; - if (zend_string_equals(arg_info->name, arg_name)) { - return i + 1; - } - } - } else { - ZEND_ASSERT(fn->common.num_args == 0 || fn->internal_function.arg_info); - for (uint32_t i = 0; i < fn->common.num_args; i++) { - zend_internal_arg_info *arg_info = &fn->internal_function.arg_info[i]; - size_t len = strlen(arg_info->name); - if (zend_string_equals_cstr(arg_name, arg_info->name, len)) { - return i + 1; - } + for (uint32_t i = 0; i < fn->common.num_args; i++) { + zend_arg_info *arg_info = &fn->op_array.arg_info[i]; + if (zend_string_equals(arg_info->name, arg_name)) { + return i + 1; } } @@ -3690,20 +3700,20 @@ static uint32_t zend_get_arg_num(zend_function *fn, zend_string *arg_name) { } static uint32_t zend_compile_args( - zend_ast *ast, zend_function *fbc, bool *may_have_extra_named_args) /* {{{ */ + zend_ast *ast, const zend_function *fbc, bool *may_have_extra_named_args) /* {{{ */ { - zend_ast_list *args = zend_ast_get_list(ast); + const zend_ast_list *args = zend_ast_get_list(ast); uint32_t i; - bool uses_arg_unpack = 0; + bool uses_arg_unpack = false; uint32_t arg_count = 0; /* number of arguments not including unpacks */ /* Whether named arguments are used syntactically, to enforce language level limitations. * May not actually use named argument passing. */ - bool uses_named_args = 0; + bool uses_named_args = false; /* Whether there may be any undef arguments due to the use of named arguments. */ - bool may_have_undef = 0; + bool may_have_undef = false; /* Whether there may be any extra named arguments collected into a variadic. */ - *may_have_extra_named_args = 0; + *may_have_extra_named_args = false; for (i = 0; i < args->children; ++i) { zend_ast *arg = args->child[i]; @@ -3721,12 +3731,12 @@ static uint32_t zend_compile_args( } /* Unpack may contain named arguments. */ - may_have_undef = 1; + may_have_undef = true; if (!fbc || (fbc->common.fn_flags & ZEND_ACC_VARIADIC)) { - *may_have_extra_named_args = 1; + *may_have_extra_named_args = true; } - uses_arg_unpack = 1; + uses_arg_unpack = true; fbc = NULL; zend_compile_expr(&arg_node, arg->child[0]); @@ -3738,7 +3748,7 @@ static uint32_t zend_compile_args( } if (arg->kind == ZEND_AST_NAMED_ARG) { - uses_named_args = 1; + uses_named_args = true; arg_name = zval_make_interned_string(zend_ast_get_zval(arg->child[0])); arg = arg->child[1]; @@ -3750,15 +3760,15 @@ static uint32_t zend_compile_args( arg_count++; } else { // TODO: We could track which arguments were passed, even if out of order. - may_have_undef = 1; + may_have_undef = true; if (arg_num == (uint32_t) -1 && (fbc->common.fn_flags & ZEND_ACC_VARIADIC)) { - *may_have_extra_named_args = 1; + *may_have_extra_named_args = true; } } } else { arg_num = (uint32_t) -1; - may_have_undef = 1; - *may_have_extra_named_args = 1; + may_have_undef = true; + *may_have_extra_named_args = true; } } else { if (uses_arg_unpack) { @@ -3777,7 +3787,7 @@ static uint32_t zend_compile_args( /* Treat passing of $GLOBALS the same as passing a call. * This will error at runtime if the argument is by-ref. */ if (zend_is_call(arg) || is_globals_fetch(arg)) { - zend_compile_var(&arg_node, arg, BP_VAR_R, 0); + zend_compile_var(&arg_node, arg, BP_VAR_R, false); if (arg_node.op_type & (IS_CONST|IS_TMP_VAR)) { /* Function call was converted into builtin instruction */ if (!fbc || ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) { @@ -3804,10 +3814,10 @@ static uint32_t zend_compile_args( } else if (zend_is_variable(arg) && !zend_ast_is_short_circuited(arg)) { if (fbc && arg_num != (uint32_t) -1) { if (ARG_SHOULD_BE_SENT_BY_REF(fbc, arg_num)) { - zend_compile_var(&arg_node, arg, BP_VAR_W, 1); + zend_compile_var(&arg_node, arg, BP_VAR_W, true); opcode = ZEND_SEND_REF; } else { - zend_compile_var(&arg_node, arg, BP_VAR_R, 0); + zend_compile_var(&arg_node, arg, BP_VAR_R, false); opcode = (arg_node.op_type == IS_TMP_VAR) ? ZEND_SEND_VAL : ZEND_SEND_VAR; } } else { @@ -3819,7 +3829,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; } @@ -3833,7 +3843,7 @@ static uint32_t zend_compile_args( } else { opline->op2.num = arg_num; } - zend_compile_var(&arg_node, arg, BP_VAR_FUNC_ARG, 1); + zend_compile_var(&arg_node, arg, BP_VAR_FUNC_ARG, true); opcode = ZEND_SEND_FUNC_ARG; } while (0); } @@ -3892,7 +3902,7 @@ static uint32_t zend_compile_args( } /* }}} */ -ZEND_API uint8_t zend_get_call_op(const zend_op *init_op, zend_function *fbc, bool result_used) /* {{{ */ +ZEND_API uint8_t zend_get_call_op(const zend_op *init_op, const zend_function *fbc, bool result_used) /* {{{ */ { uint32_t no_discard = result_used ? 0 : ZEND_ACC_NODISCARD; @@ -3925,7 +3935,7 @@ ZEND_API uint8_t zend_get_call_op(const zend_op *init_op, zend_function *fbc, bo } /* }}} */ -static bool zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *fbc, uint32_t lineno) /* {{{ */ +static bool zend_compile_call_common(znode *result, zend_ast *args_ast, const zend_function *fbc, uint32_t lineno) /* {{{ */ { zend_op *opline; uint32_t opnum_init = get_next_op_number() - 1; @@ -3933,16 +3943,25 @@ static bool zend_compile_call_common(znode *result, zend_ast *args_ast, zend_fun if (args_ast->kind == ZEND_AST_CALLABLE_CONVERT) { opline = &CG(active_op_array)->opcodes[opnum_init]; opline->extended_value = 0; + /* opcode array may be reallocated, so don't access opcode field after zend_emit_op_tmp(). */ + uint8_t opcode = opline->opcode; - if (opline->opcode == ZEND_NEW) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot create Closure for new expression"); + if (opcode == ZEND_NEW) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot create Closure for new expression"); } - if (opline->opcode == ZEND_INIT_FCALL) { + if (opcode == ZEND_INIT_FCALL) { opline->op1.num = zend_vm_calc_used_stack(0, fbc); } - zend_emit_op_tmp(result, ZEND_CALLABLE_CONVERT, NULL, NULL); + zend_op *callable_convert_op = zend_emit_op_tmp(result, ZEND_CALLABLE_CONVERT, NULL, NULL); + if (opcode == ZEND_INIT_FCALL + || opcode == ZEND_INIT_FCALL_BY_NAME + || opcode == ZEND_INIT_NS_FCALL_BY_NAME) { + callable_convert_op->extended_value = zend_alloc_cache_slot(); + } else { + callable_convert_op->extended_value = (uint32_t)-1; + } return true; } @@ -4024,11 +4043,11 @@ static void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast } /* }}} */ -static inline bool zend_args_contain_unpack_or_named(zend_ast_list *args) /* {{{ */ +static inline bool zend_args_contain_unpack_or_named(const zend_ast_list *args) /* {{{ */ { uint32_t i; for (i = 0; i < args->children; ++i) { - zend_ast *arg = args->child[i]; + const zend_ast *arg = args->child[i]; if (arg->kind == ZEND_AST_UNPACK || arg->kind == ZEND_AST_NAMED_ARG) { return 1; } @@ -4037,7 +4056,7 @@ static inline bool zend_args_contain_unpack_or_named(zend_ast_list *args) /* {{{ } /* }}} */ -static zend_result zend_compile_func_strlen(znode *result, zend_ast_list *args) /* {{{ */ +static zend_result zend_compile_func_strlen(znode *result, const zend_ast_list *args) /* {{{ */ { znode arg_node; @@ -4057,7 +4076,7 @@ static zend_result zend_compile_func_strlen(znode *result, zend_ast_list *args) } /* }}} */ -static zend_result zend_compile_func_typecheck(znode *result, zend_ast_list *args, uint32_t type) /* {{{ */ +static zend_result zend_compile_func_typecheck(znode *result, const zend_ast_list *args, uint32_t type) /* {{{ */ { znode arg_node; zend_op *opline; @@ -4077,7 +4096,7 @@ static zend_result zend_compile_func_typecheck(znode *result, zend_ast_list *arg } /* }}} */ -static zend_result zend_compile_func_is_scalar(znode *result, zend_ast_list *args) /* {{{ */ +static zend_result zend_compile_func_is_scalar(znode *result, const zend_ast_list *args) /* {{{ */ { znode arg_node; zend_op *opline; @@ -4092,7 +4111,7 @@ static zend_result zend_compile_func_is_scalar(znode *result, zend_ast_list *arg return SUCCESS; } -static zend_result zend_compile_func_cast(znode *result, zend_ast_list *args, uint32_t type) /* {{{ */ +static zend_result zend_compile_func_cast(znode *result, const zend_ast_list *args, uint32_t type) /* {{{ */ { znode arg_node; zend_op *opline; @@ -4112,7 +4131,7 @@ static zend_result zend_compile_func_cast(znode *result, zend_ast_list *args, ui } /* }}} */ -static zend_result zend_compile_func_defined(znode *result, zend_ast_list *args) /* {{{ */ +static zend_result zend_compile_func_defined(znode *result, const zend_ast_list *args) /* {{{ */ { zend_string *name; zend_op *opline; @@ -4127,7 +4146,7 @@ static zend_result zend_compile_func_defined(znode *result, zend_ast_list *args) return FAILURE; } - if (zend_try_ct_eval_const(&result->u.constant, name, 0)) { + if (zend_try_ct_eval_const(&result->u.constant, name, false)) { zend_string_release_ex(name, 0); zval_ptr_dtor(&result->u.constant); ZVAL_TRUE(&result->u.constant); @@ -4144,17 +4163,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 +4183,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; @@ -4180,11 +4205,11 @@ static zend_result zend_compile_func_ord(znode *result, zend_ast_list *args) /* /* We can only calculate the stack size for functions that have been fully compiled, otherwise * additional CV or TMP slots may still be added. This prevents the use of INIT_FCALL for * directly or indirectly recursive function calls. */ -static bool fbc_is_finalized(zend_function *fbc) { +static bool fbc_is_finalized(const zend_function *fbc) { return !ZEND_USER_CODE(fbc->type) || (fbc->common.fn_flags & ZEND_ACC_DONE_PASS_TWO); } -static bool zend_compile_ignore_class(zend_class_entry *ce, zend_string *filename) +static bool zend_compile_ignore_class(const zend_class_entry *ce, const zend_string *filename) { if (ce->type == ZEND_INTERNAL_CLASS) { return CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES; @@ -4194,7 +4219,7 @@ static bool zend_compile_ignore_class(zend_class_entry *ce, zend_string *filenam } } -static bool zend_compile_ignore_function(zend_function *fbc, zend_string *filename) +static bool zend_compile_ignore_function(const zend_function *fbc, const zend_string *filename) { if (fbc->type == ZEND_INTERNAL_FUNCTION) { return CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS; @@ -4309,7 +4334,7 @@ static zend_result zend_compile_func_cufa(znode *result, zend_ast_list *args, ze /* }}} */ /* cuf = call_user_func */ -static zend_result zend_compile_func_cuf(znode *result, zend_ast_list *args, zend_string *lcname) /* {{{ */ +static zend_result zend_compile_func_cuf(znode *result, const zend_ast_list *args, zend_string *lcname) /* {{{ */ { uint32_t i; @@ -4335,7 +4360,7 @@ static zend_result zend_compile_func_cuf(znode *result, zend_ast_list *args, zen } /* }}} */ -static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string *name, zend_function *fbc, uint32_t lineno) /* {{{ */ +static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string *name, const zend_function *fbc, uint32_t lineno) /* {{{ */ { if (EG(assertions) >= 0) { znode name_node; @@ -4367,7 +4392,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); @@ -4387,7 +4412,7 @@ static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string static zend_result zend_compile_func_in_array(znode *result, zend_ast_list *args) /* {{{ */ { - bool strict = 0; + bool strict = false; znode array, needly; zend_op *opline; @@ -4422,7 +4447,7 @@ static zend_result zend_compile_func_in_array(znode *result, zend_ast_list *args } if (zend_hash_num_elements(Z_ARRVAL(array.u.constant)) > 0) { - bool ok = 1; + bool ok = true; zval *val, tmp; HashTable *src = Z_ARRVAL(array.u.constant); HashTable *dst = zend_new_array(zend_hash_num_elements(src)); @@ -4437,7 +4462,7 @@ static zend_result zend_compile_func_in_array(znode *result, zend_ast_list *args zend_hash_index_add(dst, Z_LVAL_P(val), &tmp); } else { zend_array_destroy(dst); - ok = 0; + ok = false; break; } } ZEND_HASH_FOREACH_END(); @@ -4446,7 +4471,7 @@ static zend_result zend_compile_func_in_array(znode *result, zend_ast_list *args if (Z_TYPE_P(val) != IS_STRING || is_numeric_string(Z_STRVAL_P(val), Z_STRLEN_P(val), NULL, NULL, 0)) { zend_array_destroy(dst); - ok = 0; + ok = false; break; } zend_hash_add(dst, Z_STR_P(val), &tmp); @@ -4470,7 +4495,7 @@ static zend_result zend_compile_func_in_array(znode *result, zend_ast_list *args } /* }}} */ -static zend_result zend_compile_func_count(znode *result, zend_ast_list *args, zend_string *lcname) /* {{{ */ +static zend_result zend_compile_func_count(znode *result, const zend_ast_list *args, const zend_string *lcname) /* {{{ */ { znode arg_node; zend_op *opline; @@ -4487,7 +4512,7 @@ static zend_result zend_compile_func_count(znode *result, zend_ast_list *args, z } /* }}} */ -static zend_result zend_compile_func_get_class(znode *result, zend_ast_list *args) /* {{{ */ +static zend_result zend_compile_func_get_class(znode *result, const zend_ast_list *args) /* {{{ */ { if (args->children == 0) { zend_emit_op_tmp(result, ZEND_GET_CLASS, NULL, NULL); @@ -4505,7 +4530,7 @@ static zend_result zend_compile_func_get_class(znode *result, zend_ast_list *arg } /* }}} */ -static zend_result zend_compile_func_get_called_class(znode *result, zend_ast_list *args) /* {{{ */ +static zend_result zend_compile_func_get_called_class(znode *result, const zend_ast_list *args) /* {{{ */ { if (args->children != 0) { return FAILURE; @@ -4516,7 +4541,7 @@ static zend_result zend_compile_func_get_called_class(znode *result, zend_ast_li } /* }}} */ -static zend_result zend_compile_func_gettype(znode *result, zend_ast_list *args) /* {{{ */ +static zend_result zend_compile_func_gettype(znode *result, const zend_ast_list *args) /* {{{ */ { znode arg_node; @@ -4530,7 +4555,7 @@ static zend_result zend_compile_func_gettype(znode *result, zend_ast_list *args) } /* }}} */ -static zend_result zend_compile_func_num_args(znode *result, zend_ast_list *args) /* {{{ */ +static zend_result zend_compile_func_num_args(znode *result, const zend_ast_list *args) /* {{{ */ { if (CG(active_op_array)->function_name && args->children == 0) { zend_emit_op_tmp(result, ZEND_FUNC_NUM_ARGS, NULL, NULL); @@ -4541,7 +4566,7 @@ static zend_result zend_compile_func_num_args(znode *result, zend_ast_list *args } /* }}} */ -static zend_result zend_compile_func_get_args(znode *result, zend_ast_list *args) /* {{{ */ +static zend_result zend_compile_func_get_args(znode *result, const zend_ast_list *args) /* {{{ */ { if (CG(active_op_array)->function_name && args->children == 0) { zend_emit_op_tmp(result, ZEND_FUNC_GET_ARGS, NULL, NULL); @@ -4552,7 +4577,7 @@ static zend_result zend_compile_func_get_args(znode *result, zend_ast_list *args } /* }}} */ -static zend_result zend_compile_func_array_key_exists(znode *result, zend_ast_list *args) /* {{{ */ +static zend_result zend_compile_func_array_key_exists(znode *result, const zend_ast_list *args) /* {{{ */ { znode subject, needle; @@ -4568,7 +4593,7 @@ static zend_result zend_compile_func_array_key_exists(znode *result, zend_ast_li } /* }}} */ -static zend_result zend_compile_func_array_slice(znode *result, zend_ast_list *args) /* {{{ */ +static zend_result zend_compile_func_array_slice(znode *result, const zend_ast_list *args) /* {{{ */ { if (CG(active_op_array)->function_name && args->children == 2 @@ -4581,8 +4606,8 @@ static zend_result zend_compile_func_array_slice(znode *result, zend_ast_list *a zend_string *orig_name = zend_ast_get_str(args->child[0]->child[0]); bool is_fully_qualified; zend_string *name = zend_resolve_function_name(orig_name, args->child[0]->child[0]->attr, &is_fully_qualified); - zend_ast_list *list = zend_ast_get_list(args->child[0]->child[1]); - zval *zv = zend_ast_get_zval(args->child[1]); + const zend_ast_list *list = zend_ast_get_list(args->child[0]->child[1]); + const zval *zv = zend_ast_get_zval(args->child[1]); znode first; if (zend_string_equals_literal_ci(name, "func_get_args") @@ -4601,7 +4626,7 @@ static zend_result zend_compile_func_array_slice(znode *result, zend_ast_list *a } /* }}} */ -static uint32_t find_frameless_function_offset(uint32_t arity, void *handler) +static uint32_t find_frameless_function_offset(uint32_t arity, const void *handler) { void **handlers = zend_flf_handlers; void **current = handlers; @@ -4615,7 +4640,7 @@ static uint32_t find_frameless_function_offset(uint32_t arity, void *handler) return (uint32_t)-1; } -static const zend_frameless_function_info *find_frameless_function_info(zend_ast_list *args, zend_function *fbc, uint32_t type) +static const zend_frameless_function_info *find_frameless_function_info(const zend_ast_list *args, const zend_function *fbc, uint32_t type) { if (zend_execute_internal) { return NULL; @@ -4656,9 +4681,9 @@ static const zend_frameless_function_info *find_frameless_function_info(zend_ast return NULL; } -static uint32_t zend_compile_frameless_icall_ex(znode *result, zend_ast_list *args, zend_function *fbc, const zend_frameless_function_info *frameless_function_info, uint32_t type) +static uint32_t zend_compile_frameless_icall_ex(znode *result, const zend_ast_list *args, const zend_function *fbc, const zend_frameless_function_info *frameless_function_info, uint32_t type) { - int lineno = CG(zend_lineno); + uint32_t lineno = CG(zend_lineno); uint32_t num_args = frameless_function_info->num_args; uint32_t offset = find_frameless_function_offset(num_args, frameless_function_info->handler); znode arg_zvs[3]; @@ -4666,7 +4691,7 @@ static uint32_t zend_compile_frameless_icall_ex(znode *result, zend_ast_list *ar if (i < args->children) { zend_compile_expr(&arg_zvs[i], args->child[i]); } else { - zend_internal_arg_info *arg_info = (zend_internal_arg_info *)&fbc->common.arg_info[i]; + const zend_arg_info *arg_info = &fbc->common.arg_info[i]; arg_zvs[i].op_type = IS_CONST; if (zend_get_default_from_internal_arg_info(&arg_zvs[i].u.constant, arg_info) == FAILURE) { ZEND_UNREACHABLE(); @@ -4690,7 +4715,7 @@ static uint32_t zend_compile_frameless_icall_ex(znode *result, zend_ast_list *ar return opnum; } -static uint32_t zend_compile_frameless_icall(znode *result, zend_ast_list *args, zend_function *fbc, uint32_t type) +static uint32_t zend_compile_frameless_icall(znode *result, const zend_ast_list *args, const zend_function *fbc, uint32_t type) { const zend_frameless_function_info *frameless_function_info = find_frameless_function_info(args, fbc, type); if (!frameless_function_info) { @@ -4700,12 +4725,12 @@ static uint32_t zend_compile_frameless_icall(znode *result, zend_ast_list *args, return zend_compile_frameless_icall_ex(result, args, fbc, frameless_function_info, type); } -static void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast, uint32_t lineno, uint32_t type) /* {{{ */ +static void zend_compile_ns_call(znode *result, const znode *name_node, zend_ast *args_ast, uint32_t lineno, uint32_t type) /* {{{ */ { int name_constants = zend_add_ns_func_name_literal(Z_STR(name_node->u.constant)); /* Find frameless function with same name. */ - zend_function *frameless_function = NULL; + const zend_function *frameless_function = NULL; if (args_ast->kind != ZEND_AST_CALLABLE_CONVERT && !zend_args_contain_unpack_or_named(zend_ast_get_list(args_ast)) /* Avoid blowing up op count with nested frameless branches. */ @@ -4930,7 +4955,62 @@ static zend_result zend_compile_func_sprintf(znode *result, zend_ast_list *args) return SUCCESS; } -static zend_result zend_compile_func_clone(znode *result, zend_ast_list *args) +static zend_result zend_compile_func_printf(znode *result, zend_ast_list *args) /* {{{ */ +{ + /* Special case: printf with a single constant string argument and no format specifiers. + * In this case, just emit ECHO and return the string length if needed. */ + if (args->children == 1) { + zend_eval_const_expr(&args->child[0]); + if (args->child[0]->kind != ZEND_AST_ZVAL) { + return FAILURE; + } + zval *format_string = zend_ast_get_zval(args->child[0]); + if (Z_TYPE_P(format_string) != IS_STRING) { + return FAILURE; + } + /* Check if there are any format specifiers */ + if (!memchr(Z_STRVAL_P(format_string), '%', Z_STRLEN_P(format_string))) { + /* No format specifiers - just emit ECHO and return string length */ + znode format_node; + zend_compile_expr(&format_node, args->child[0]); + zend_emit_op(NULL, ZEND_ECHO, &format_node, NULL); + + /* Return the string length as a constant if the result is used */ + result->op_type = IS_CONST; + ZVAL_LONG(&result->u.constant, Z_STRLEN_P(format_string)); + return SUCCESS; + } + } + + /* Fall back to sprintf optimization for format strings with specifiers */ + znode rope_result; + if (zend_compile_func_sprintf(&rope_result, args) != SUCCESS) { + return FAILURE; + } + + /* printf() returns the amount of bytes written, so just an ECHO of the + * resulting sprintf() optimisation might not be enough. At this early + * stage we can't detect if the result is actually used, so we just emit + * the opcodes and let them be cleaned up by the dead code elimination + * pass in the Zend Optimizer if the result of the printf() is in fact + * unused */ + znode copy; + if (rope_result.op_type != IS_CONST) { + /* Note: ZEND_COPY_TMP is only valid for TMPVAR. */ + ZEND_ASSERT(rope_result.op_type == IS_TMP_VAR); + zend_emit_op_tmp(©, ZEND_COPY_TMP, &rope_result, NULL); + zend_emit_op(NULL, ZEND_ECHO, &rope_result, NULL); + zend_emit_op_tmp(result, ZEND_STRLEN, ©, NULL); + } else { + zend_emit_op(NULL, ZEND_ECHO, &rope_result, NULL); + result->op_type = IS_CONST; + ZVAL_LONG(&result->u.constant, Z_STRLEN(rope_result.u.constant)); + } + + return SUCCESS; +} + +static zend_result zend_compile_func_clone(znode *result, const zend_ast_list *args) { znode arg_node; @@ -4944,7 +5024,7 @@ static zend_result zend_compile_func_clone(znode *result, zend_ast_list *args) return SUCCESS; } -static zend_result zend_try_compile_special_func_ex(znode *result, zend_string *lcname, zend_ast_list *args, zend_function *fbc, uint32_t type) /* {{{ */ +static zend_result zend_try_compile_special_func_ex(znode *result, zend_string *lcname, zend_ast_list *args, uint32_t type) /* {{{ */ { if (zend_string_equals_literal(lcname, "strlen")) { return zend_compile_func_strlen(result, args); @@ -5012,6 +5092,8 @@ static zend_result zend_try_compile_special_func_ex(znode *result, zend_string * return zend_compile_func_array_key_exists(result, args); } else if (zend_string_equals_literal(lcname, "sprintf")) { return zend_compile_func_sprintf(result, args); + } else if (zend_string_equals_literal(lcname, "printf")) { + return zend_compile_func_printf(result, args); } else if (zend_string_equals(lcname, ZSTR_KNOWN(ZEND_STR_CLONE))) { return zend_compile_func_clone(result, args); } else { @@ -5019,7 +5101,7 @@ static zend_result zend_try_compile_special_func_ex(znode *result, zend_string * } } -static zend_result zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_list *args, zend_function *fbc, uint32_t type) /* {{{ */ +static zend_result zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_list *args, const zend_function *fbc, uint32_t type) /* {{{ */ { if (CG(compiler_options) & ZEND_COMPILE_NO_BUILTINS) { return FAILURE; @@ -5035,7 +5117,7 @@ static zend_result zend_try_compile_special_func(znode *result, zend_string *lcn return FAILURE; } - if (zend_try_compile_special_func_ex(result, lcname, args, fbc, type) == SUCCESS) { + if (zend_try_compile_special_func_ex(result, lcname, args, type) == SUCCESS) { return SUCCESS; } @@ -5062,11 +5144,11 @@ static zend_string *zend_copy_unmangled_prop_name(zend_string *prop_name) } } -static bool zend_compile_parent_property_hook_call(znode *result, zend_ast *ast, uint32_t type) +static bool zend_compile_parent_property_hook_call(znode *result, const zend_ast *ast, uint32_t type) { ZEND_ASSERT(ast->kind == ZEND_AST_STATIC_CALL); - zend_ast *class_ast = ast->child[0]; + const zend_ast *class_ast = ast->child[0]; zend_ast *method_ast = ast->child[1]; /* Recognize parent::$prop::get() pattern. */ @@ -5121,13 +5203,12 @@ static bool zend_compile_parent_property_hook_call(znode *result, zend_ast *ast, opline->op1.constant = zend_add_literal_string(&property_name); opline->op2.num = hook_kind; - zend_function *fbc = NULL; - zend_compile_call_common(result, args_ast, fbc, zend_ast_get_lineno(method_ast)); + zend_compile_call_common(result, args_ast, NULL, zend_ast_get_lineno(method_ast)); return true; } -static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ +static void zend_compile_call(znode *result, const zend_ast *ast, uint32_t type) /* {{{ */ { zend_ast *name_ast = ast->child[0]; zend_ast *args_ast = ast->child[1]; @@ -5155,14 +5236,11 @@ static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{ } { - zval *name = &name_node.u.constant; - zend_string *lcname; - zend_function *fbc; - zend_op *opline; - - lcname = zend_string_tolower(Z_STR_P(name)); + const zval *name = &name_node.u.constant; + zend_string *lcname = zend_string_tolower(Z_STR_P(name)); zval *fbc_zv = zend_hash_find(CG(function_table), lcname); - fbc = fbc_zv ? Z_PTR_P(fbc_zv) : NULL; + const zend_function *fbc = fbc_zv ? Z_PTR_P(fbc_zv) : NULL; + zend_op *opline; /* Special assert() handling should apply independently of compiler flags. */ if (fbc && zend_string_equals_literal(lcname, "assert") && !is_callable_convert) { @@ -5197,7 +5275,7 @@ static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{ /* Store offset to function from symbol table in op2.extra. */ if (fbc->type == ZEND_INTERNAL_FUNCTION) { - Bucket *fbc_bucket = (Bucket*)((uintptr_t)fbc_zv - XtOffsetOf(Bucket, val)); + const Bucket *fbc_bucket = (const Bucket*)((uintptr_t)fbc_zv - XtOffsetOf(Bucket, val)); Z_EXTRA_P(CT_CONSTANT(opline->op2)) = fbc_bucket - CG(function_table)->arData; } @@ -5214,7 +5292,7 @@ static void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type znode obj_node, method_node; zend_op *opline; - zend_function *fbc = NULL; + const zend_function *fbc = NULL; bool nullsafe = ast->kind == ZEND_AST_NULLSAFE_METHOD_CALL; uint32_t short_circuiting_checkpoint = zend_short_circuiting_checkpoint(); @@ -5274,23 +5352,33 @@ static void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type } /* }}} */ -static bool zend_is_constructor(zend_string *name) /* {{{ */ +static bool zend_is_constructor(const zend_string *name) /* {{{ */ { return zend_string_equals_literal_ci(name, ZEND_CONSTRUCTOR_FUNC_NAME); } /* }}} */ -static zend_function *zend_get_compatible_func_or_null(zend_class_entry *ce, zend_string *lcname) /* {{{ */ +static bool is_func_accessible(const zend_function *fbc) { - zend_function *fbc = zend_hash_find_ptr(&ce->function_table, lcname); - if (!fbc || (fbc->common.fn_flags & ZEND_ACC_PUBLIC) || ce == CG(active_class_entry)) { - return fbc; + if ((fbc->common.fn_flags & ZEND_ACC_PUBLIC) || fbc->common.scope == CG(active_class_entry)) { + return true; } if (!(fbc->common.fn_flags & ZEND_ACC_PRIVATE) && (fbc->common.scope->ce_flags & ZEND_ACC_LINKED) && (!CG(active_class_entry) || (CG(active_class_entry)->ce_flags & ZEND_ACC_LINKED)) && zend_check_protected(zend_get_function_root_class(fbc), CG(active_class_entry))) { + return true; + } + + return false; +} + +static const zend_function *zend_get_compatible_func_or_null(const zend_class_entry *ce, zend_string *lcname) /* {{{ */ +{ + const zend_function *fbc = zend_hash_find_ptr(&ce->function_table, lcname); + + if (!fbc || is_func_accessible(fbc)) { return fbc; } @@ -5306,7 +5394,7 @@ static void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type znode class_node, method_node; zend_op *opline; - zend_function *fbc = NULL; + const zend_function *fbc = NULL; if (zend_compile_parent_property_hook_call(result, ast, type)) { return; @@ -5374,7 +5462,7 @@ static void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type } /* }}} */ -static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel); +static void zend_compile_class_decl(znode *result, const zend_ast *ast, bool toplevel); static void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */ { @@ -5386,23 +5474,47 @@ static void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */ if (class_ast->kind == ZEND_AST_CLASS) { /* anon class declaration */ - zend_compile_class_decl(&class_node, class_ast, 0); + zend_compile_class_decl(&class_node, class_ast, false); } else { zend_compile_class_ref(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION); } opline = zend_emit_op(result, ZEND_NEW, NULL, NULL); - if (class_node.op_type == IS_CONST) { - opline->op1_type = IS_CONST; - opline->op1.constant = zend_add_class_name_literal( - Z_STR(class_node.u.constant)); + zend_set_class_name_op1(opline, &class_node); + + if (opline->op1_type == IS_CONST) { opline->op2.num = zend_alloc_cache_slot(); - } else { - SET_NODE(opline->op1, &class_node); } - zend_compile_call_common(&ctor_result, args_ast, NULL, ast->lineno); + zend_class_entry *ce = NULL; + if (opline->op1_type == IS_CONST) { + zend_string *lcname = Z_STR_P(CT_CONSTANT(opline->op1) + 1); + ce = zend_hash_find_ptr(CG(class_table), lcname); + if (ce) { + if (zend_compile_ignore_class(ce, CG(active_op_array)->filename)) { + ce = NULL; + } + } else if (CG(active_class_entry) + && zend_string_equals_ci(CG(active_class_entry)->name, lcname)) { + ce = CG(active_class_entry); + } + } else if (opline->op1_type == IS_UNUSED + && (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF + && zend_is_scope_known()) { + ce = CG(active_class_entry); + } + + + const zend_function *fbc = NULL; + if (ce + && ce->default_object_handlers->get_constructor == zend_std_get_constructor + && ce->constructor + && is_func_accessible(ce->constructor)) { + fbc = ce->constructor; + } + + zend_compile_call_common(&ctor_result, args_ast, fbc, ast->lineno); zend_do_free(&ctor_result); } /* }}} */ @@ -5422,7 +5534,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 { @@ -5521,7 +5633,7 @@ static void zend_compile_static_var(zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_unset(zend_ast *ast) /* {{{ */ +static void zend_compile_unset(const zend_ast *ast) /* {{{ */ { zend_ast *var_ast = ast->child[0]; znode var_node; @@ -5548,10 +5660,10 @@ 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); + opline = zend_compile_simple_var_no_cv(NULL, var_ast, BP_VAR_UNSET, false); opline->opcode = ZEND_UNSET_VAR; } return; @@ -5561,11 +5673,11 @@ static void zend_compile_unset(zend_ast *ast) /* {{{ */ return; case ZEND_AST_PROP: case ZEND_AST_NULLSAFE_PROP: - opline = zend_compile_prop(NULL, var_ast, BP_VAR_UNSET, 0); + opline = zend_compile_prop(NULL, var_ast, BP_VAR_UNSET, false); opline->opcode = ZEND_UNSET_OBJ; return; case ZEND_AST_STATIC_PROP: - opline = zend_compile_static_prop(NULL, var_ast, BP_VAR_UNSET, 0, 0); + opline = zend_compile_static_prop(NULL, var_ast, BP_VAR_UNSET, false, false); opline->opcode = ZEND_UNSET_STATIC_PROP; return; EMPTY_SWITCH_DEFAULT_CASE() @@ -5575,7 +5687,7 @@ static void zend_compile_unset(zend_ast *ast) /* {{{ */ static bool zend_handle_loops_and_finally_ex(zend_long depth, znode *return_value) /* {{{ */ { - zend_loop_var *base; + const zend_loop_var *base; zend_loop_var *loop_var = zend_stack_top(&CG(loop_var_stack)); if (!loop_var) { @@ -5630,7 +5742,7 @@ static bool zend_handle_loops_and_finally(znode *return_value) /* {{{ */ static bool zend_has_finally_ex(zend_long depth) /* {{{ */ { - zend_loop_var *base; + const zend_loop_var *base; zend_loop_var *loop_var = zend_stack_top(&CG(loop_var_stack)); if (!loop_var) { @@ -5660,7 +5772,7 @@ static bool zend_has_finally(void) /* {{{ */ } /* }}} */ -static void zend_compile_return(zend_ast *ast) /* {{{ */ +static void zend_compile_return(const zend_ast *ast) /* {{{ */ { zend_ast *expr_ast = ast->child[0]; bool is_generator = (CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0; @@ -5671,7 +5783,7 @@ static void zend_compile_return(zend_ast *ast) /* {{{ */ if (is_generator) { /* For generators the by-ref flag refers to yields, not returns */ - by_ref = 0; + by_ref = false; } if (!expr_ast) { @@ -5679,7 +5791,7 @@ static void zend_compile_return(zend_ast *ast) /* {{{ */ ZVAL_NULL(&expr_node.u.constant); } else if (by_ref && zend_is_variable(expr_ast)) { zend_assert_not_short_circuited(expr_ast); - zend_compile_var(&expr_node, expr_ast, BP_VAR_W, 1); + zend_compile_var(&expr_node, expr_ast, BP_VAR_W, true); } else { zend_compile_expr(&expr_node, expr_ast); } @@ -5698,11 +5810,23 @@ static void zend_compile_return(zend_ast *ast) /* {{{ */ /* Generator return types are handled separately */ if (!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); + expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1, false); } + 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, false); + } + opline = zend_emit_op(NULL, by_ref ? ZEND_RETURN_BY_REF : ZEND_RETURN, &expr_node, NULL); @@ -5716,7 +5840,7 @@ static void zend_compile_return(zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_void_cast(znode *result, zend_ast *ast) +static void zend_compile_void_cast(znode *result, const zend_ast *ast) { zend_ast *expr_ast = ast->child[0]; znode expr_node; @@ -5736,7 +5860,7 @@ static void zend_compile_void_cast(znode *result, zend_ast *ast) } } -static void zend_compile_echo(zend_ast *ast) /* {{{ */ +static void zend_compile_echo(const zend_ast *ast) /* {{{ */ { zend_op *opline; zend_ast *expr_ast = ast->child[0]; @@ -5749,7 +5873,7 @@ static void zend_compile_echo(zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_throw(znode *result, zend_ast *ast) /* {{{ */ +static void zend_compile_throw(znode *result, const zend_ast *ast) /* {{{ */ { zend_ast *expr_ast = ast->child[0]; @@ -5766,7 +5890,7 @@ static void zend_compile_throw(znode *result, zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_break_continue(zend_ast *ast) /* {{{ */ +static void zend_compile_break_continue(const zend_ast *ast) /* {{{ */ { zend_ast *depth_ast = ast->child[0]; @@ -5776,7 +5900,7 @@ static void zend_compile_break_continue(zend_ast *ast) /* {{{ */ ZEND_ASSERT(ast->kind == ZEND_AST_BREAK || ast->kind == ZEND_AST_CONTINUE); if (depth_ast) { - zval *depth_zv; + const zval *depth_zv; if (depth_ast->kind != ZEND_AST_ZVAL) { zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator with non-integer operand " "is no longer supported", ast->kind == ZEND_AST_BREAK ? "break" : "continue"); @@ -5846,7 +5970,7 @@ static void zend_compile_break_continue(zend_ast *ast) /* {{{ */ void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline) /* {{{ */ { zend_label *dest; - int current, remove_oplines = opline->op1.num; + int remove_oplines = opline->op1.num; zval *label; uint32_t opnum = opline - op_array->opcodes; @@ -5863,7 +5987,7 @@ void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline) /* {{{ */ zval_ptr_dtor_str(label); ZVAL_NULL(label); - current = opline->extended_value; + uint32_t current = opline->extended_value; for (; current != dest->brk_cont; current = CG(context).brk_cont_array[current].parent) { if (current == -1) { CG(in_compilation) = 1; @@ -5877,7 +6001,7 @@ void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline) /* {{{ */ } for (current = 0; current < op_array->last_try_catch; ++current) { - zend_try_catch_element *elem = &op_array->try_catch_array[current]; + const zend_try_catch_element *elem = &op_array->try_catch_array[current]; if (elem->try_op > opnum) { break; } @@ -5904,7 +6028,7 @@ void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline) /* {{{ */ } /* }}} */ -static void zend_compile_goto(zend_ast *ast) /* {{{ */ +static void zend_compile_goto(const zend_ast *ast) /* {{{ */ { zend_ast *label_ast = ast->child[0]; znode label_node; @@ -5921,7 +6045,7 @@ static void zend_compile_goto(zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_label(zend_ast *ast) /* {{{ */ +static void zend_compile_label(const zend_ast *ast) /* {{{ */ { zend_string *label = zend_ast_get_str(ast->child[0]); zend_label dest; @@ -5940,7 +6064,7 @@ static void zend_compile_label(zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_while(zend_ast *ast) /* {{{ */ +static void zend_compile_while(const zend_ast *ast) /* {{{ */ { zend_ast *cond_ast = ast->child[0]; zend_ast *stmt_ast = ast->child[1]; @@ -5949,7 +6073,7 @@ static void zend_compile_while(zend_ast *ast) /* {{{ */ opnum_jmp = zend_emit_jump(0); - zend_begin_loop(ZEND_NOP, NULL, 0); + zend_begin_loop(ZEND_NOP, NULL, false); opnum_start = get_next_op_number(); zend_compile_stmt(stmt_ast); @@ -5964,7 +6088,7 @@ static void zend_compile_while(zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_do_while(zend_ast *ast) /* {{{ */ +static void zend_compile_do_while(const zend_ast *ast) /* {{{ */ { zend_ast *stmt_ast = ast->child[0]; zend_ast *cond_ast = ast->child[1]; @@ -5972,7 +6096,7 @@ static void zend_compile_do_while(zend_ast *ast) /* {{{ */ znode cond_node; uint32_t opnum_start, opnum_cond; - zend_begin_loop(ZEND_NOP, NULL, 0); + zend_begin_loop(ZEND_NOP, NULL, false); opnum_start = get_next_op_number(); zend_compile_stmt(stmt_ast); @@ -5988,7 +6112,7 @@ static void zend_compile_do_while(zend_ast *ast) /* {{{ */ static void zend_compile_for_expr_list(znode *result, zend_ast *ast) /* {{{ */ { - zend_ast_list *list; + const zend_ast_list *list; uint32_t i; result->op_type = IS_CONST; @@ -6014,7 +6138,7 @@ static void zend_compile_for_expr_list(znode *result, zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_for(zend_ast *ast) /* {{{ */ +static void zend_compile_for(const zend_ast *ast) /* {{{ */ { zend_ast *init_ast = ast->child[0]; zend_ast *cond_ast = ast->child[1]; @@ -6029,7 +6153,7 @@ static void zend_compile_for(zend_ast *ast) /* {{{ */ opnum_jmp = zend_emit_jump(0); - zend_begin_loop(ZEND_NOP, NULL, 0); + zend_begin_loop(ZEND_NOP, NULL, false); opnum_start = get_next_op_number(); zend_compile_stmt(stmt_ast); @@ -6040,7 +6164,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); @@ -6075,11 +6199,11 @@ static void zend_compile_foreach(zend_ast *ast) /* {{{ */ } if (value_ast->kind == ZEND_AST_ARRAY && zend_propagate_list_refs(value_ast)) { - by_ref = 1; + by_ref = true; } if (by_ref && is_variable) { - zend_compile_var(&expr_node, expr_ast, BP_VAR_W, 1); + zend_compile_var(&expr_node, expr_ast, BP_VAR_W, true); } else { zend_compile_expr(&expr_node, expr_ast); } @@ -6091,7 +6215,7 @@ static void zend_compile_foreach(zend_ast *ast) /* {{{ */ opnum_reset = get_next_op_number(); opline = zend_emit_op(&reset_node, by_ref ? ZEND_FE_RESET_RW : ZEND_FE_RESET_R, &expr_node, NULL); - zend_begin_loop(ZEND_FE_FREE, &reset_node, 0); + zend_begin_loop(ZEND_FE_FREE, &reset_node, false); opnum_fetch = get_next_op_number(); opline = zend_emit_op(NULL, by_ref ? ZEND_FE_FETCH_RW : ZEND_FE_FETCH_R, &reset_node, NULL); @@ -6099,7 +6223,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; @@ -6142,7 +6266,7 @@ static void zend_compile_foreach(zend_ast *ast) /* {{{ */ static void zend_compile_if(zend_ast *ast) /* {{{ */ { - zend_ast_list *list = zend_ast_get_list(ast); + const zend_ast_list *list = zend_ast_get_list(ast); uint32_t i; uint32_t *jmp_opnums = NULL; @@ -6151,7 +6275,7 @@ static void zend_compile_if(zend_ast *ast) /* {{{ */ } for (i = 0; i < list->children; ++i) { - zend_ast *elem_ast = list->child[i]; + const zend_ast *elem_ast = list->child[i]; zend_ast *cond_ast = elem_ast->child[0]; zend_ast *stmt_ast = elem_ast->child[1]; @@ -6161,7 +6285,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); @@ -6192,13 +6316,13 @@ static void zend_compile_if(zend_ast *ast) /* {{{ */ } /* }}} */ -static uint8_t determine_switch_jumptable_type(zend_ast_list *cases) { +static uint8_t determine_switch_jumptable_type(const zend_ast_list *cases) { uint32_t i; uint8_t common_type = IS_UNDEF; for (i = 0; i < cases->children; i++) { zend_ast *case_ast = cases->child[i]; zend_ast **cond_ast = &case_ast->child[0]; - zval *cond_zv; + const zval *cond_zv; if (!case_ast->child[0]) { /* Skip default clause */ continue; @@ -6233,7 +6357,7 @@ static uint8_t determine_switch_jumptable_type(zend_ast_list *cases) { return common_type; } -static bool should_use_jumptable(zend_ast_list *cases, uint8_t jumptable_type) { +static bool should_use_jumptable(const zend_ast_list *cases, uint8_t jumptable_type) { if (CG(compiler_options) & ZEND_COMPILE_NO_JUMPTABLES) { return 0; } @@ -6254,7 +6378,7 @@ static void zend_compile_switch(zend_ast *ast) /* {{{ */ zend_ast_list *cases = zend_ast_get_list(ast->child[1]); uint32_t i; - bool has_default_case = 0; + bool has_default_case = false; znode expr_node, case_node; zend_op *opline; @@ -6264,7 +6388,7 @@ static void zend_compile_switch(zend_ast *ast) /* {{{ */ zend_compile_expr(&expr_node, expr_ast); - zend_begin_loop(ZEND_FREE, &expr_node, 1); + zend_begin_loop(ZEND_FREE, &expr_node, true); case_node.op_type = IS_TMP_VAR; case_node.u.op.var = get_temporary_variable(); @@ -6293,13 +6417,18 @@ static void zend_compile_switch(zend_ast *ast) /* {{{ */ zend_ast *cond_ast = case_ast->child[0]; znode cond_node; + 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"); + } + if (!cond_ast) { if (has_default_case) { CG(zend_lineno) = case_ast->lineno; zend_error_noreturn(E_COMPILE_ERROR, "Switch statements may only contain one default clause"); } - has_default_case = 1; + has_default_case = true; continue; } @@ -6382,26 +6511,26 @@ static void zend_compile_switch(zend_ast *ast) /* {{{ */ } /* }}} */ -static uint32_t count_match_conds(zend_ast_list *arms) +static uint32_t count_match_conds(const zend_ast_list *arms) { uint32_t num_conds = 0; for (uint32_t i = 0; i < arms->children; i++) { - zend_ast *arm_ast = arms->child[i]; + const zend_ast *arm_ast = arms->child[i]; if (arm_ast->child[0] == NULL) { continue; } - zend_ast_list *conds = zend_ast_get_list(arm_ast->child[0]); + const zend_ast_list *conds = zend_ast_get_list(arm_ast->child[0]); num_conds += conds->children; } return num_conds; } -static bool can_match_use_jumptable(zend_ast_list *arms) { +static bool can_match_use_jumptable(const zend_ast_list *arms) { for (uint32_t i = 0; i < arms->children; i++) { - zend_ast *arm_ast = arms->child[i]; + const zend_ast *arm_ast = arms->child[i]; if (!arm_ast->child[0]) { /* Skip default arm */ continue; @@ -6416,7 +6545,7 @@ static bool can_match_use_jumptable(zend_ast_list *arms) { return 0; } - zval *cond_zv = zend_ast_get_zval(*cond_ast); + const zval *cond_zv = zend_ast_get_zval(*cond_ast); if (Z_TYPE_P(cond_zv) != IS_LONG && Z_TYPE_P(cond_zv) != IS_STRING) { return 0; } @@ -6433,8 +6562,7 @@ static bool zend_is_pipe_optimizable_callable_name(zend_ast *ast) * 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 !zend_string_equals_literal_ci(zend_ast_get_str(ast), "assert"); } return true; @@ -6445,6 +6573,10 @@ 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); @@ -6489,6 +6621,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); } @@ -6496,7 +6630,7 @@ static void zend_compile_match(znode *result, zend_ast *ast) { zend_ast *expr_ast = ast->child[0]; zend_ast_list *arms = zend_ast_get_list(ast->child[1]); - bool has_default_arm = 0; + bool has_default_arm = false; uint32_t opnum_match = (uint32_t)-1; znode expr_node; @@ -6521,7 +6655,7 @@ static void zend_compile_match(znode *result, zend_ast *ast) zend_error_noreturn(E_COMPILE_ERROR, "Match expressions may only contain one default arm"); } - has_default_arm = 1; + has_default_arm = true; } } @@ -6574,7 +6708,7 @@ static void zend_compile_match(znode *result, zend_ast *ast) opnum_default_jmp = zend_emit_jump(0); } - bool is_first_case = 1; + bool is_first_case = true; uint32_t cond_count = 0; uint32_t *jmp_end_opnums = safe_emalloc(sizeof(uint32_t), arms->children, 0); @@ -6646,7 +6780,7 @@ static void zend_compile_match(znode *result, zend_ast *ast) if (is_first_case) { zend_emit_op_tmp(result, ZEND_QM_ASSIGN, &body_node, NULL); - is_first_case = 0; + is_first_case = false; } else { zend_op *opline_qm_assign = zend_emit_op(NULL, ZEND_QM_ASSIGN, &body_node, NULL); SET_NODE(opline_qm_assign->result, result); @@ -6678,10 +6812,10 @@ static void zend_compile_match(znode *result, zend_ast *ast) efree(jmp_end_opnums); } -static void zend_compile_try(zend_ast *ast) /* {{{ */ +static void zend_compile_try(const zend_ast *ast) /* {{{ */ { zend_ast *try_ast = ast->child[0]; - zend_ast_list *catches = zend_ast_get_list(ast->child[1]); + const zend_ast_list *catches = zend_ast_get_list(ast->child[1]); zend_ast *finally_ast = ast->child[2]; uint32_t i, j; @@ -6732,8 +6866,8 @@ static void zend_compile_try(zend_ast *ast) /* {{{ */ } for (i = 0; i < catches->children; ++i) { - zend_ast *catch_ast = catches->child[i]; - zend_ast_list *classes = zend_ast_get_list(catch_ast->child[0]); + const zend_ast *catch_ast = catches->child[i]; + const zend_ast_list *classes = zend_ast_get_list(catch_ast->child[0]); zend_ast *var_ast = catch_ast->child[1]; zend_ast *stmt_ast = catch_ast->child[2]; zend_string *var_name = var_ast ? zval_make_interned_string(zend_ast_get_zval(var_ast)) : NULL; @@ -6855,13 +6989,13 @@ static void zend_compile_try(zend_ast *ast) /* {{{ */ /* Encoding declarations must already be handled during parsing */ bool zend_handle_encoding_declaration(zend_ast *ast) /* {{{ */ { - zend_ast_list *declares = zend_ast_get_list(ast); + const zend_ast_list *declares = zend_ast_get_list(ast); uint32_t i; for (i = 0; i < declares->children; ++i) { - zend_ast *declare_ast = declares->child[i]; + const zend_ast *declare_ast = declares->child[i]; zend_ast *name_ast = declare_ast->child[0]; zend_ast *value_ast = declare_ast->child[1]; - zend_string *name = zend_ast_get_str(name_ast); + const zend_string *name = zend_ast_get_str(name_ast); if (zend_string_equals_literal_ci(name, "encoding")) { if (value_ast->kind != ZEND_AST_ZVAL) { @@ -6905,10 +7039,10 @@ bool zend_handle_encoding_declaration(zend_ast *ast) /* {{{ */ /* }}} */ /* Check whether this is the first statement, not counting declares. */ -static zend_result zend_is_first_statement(zend_ast *ast, bool allow_nop) /* {{{ */ +static zend_result zend_is_first_statement(const zend_ast *ast, bool allow_nop) /* {{{ */ { uint32_t i = 0; - zend_ast_list *file_ast = zend_ast_get_list(CG(ast)); + const zend_ast_list *file_ast = zend_ast_get_list(CG(ast)); while (i < file_ast->children) { if (file_ast->child[i] == ast) { @@ -6926,9 +7060,9 @@ static zend_result zend_is_first_statement(zend_ast *ast, bool allow_nop) /* {{{ } /* }}} */ -static void zend_compile_declare(zend_ast *ast) /* {{{ */ +static void zend_compile_declare(const zend_ast *ast) /* {{{ */ { - zend_ast_list *declares = zend_ast_get_list(ast->child[0]); + const zend_ast_list *declares = zend_ast_get_list(ast->child[0]); zend_ast *stmt_ast = ast->child[1]; zend_declarables orig_declarables = FC(declarables); uint32_t i; @@ -6950,14 +7084,14 @@ static void zend_compile_declare(zend_ast *ast) /* {{{ */ zval_ptr_dtor_nogc(&value_zv); } else if (zend_string_equals_literal_ci(name, "encoding")) { - if (FAILURE == zend_is_first_statement(ast, /* allow_nop */ 0)) { + if (FAILURE == zend_is_first_statement(ast, /* allow_nop */ false)) { zend_error_noreturn(E_COMPILE_ERROR, "Encoding declaration pragma must be " "the very first statement in the script"); } } else if (zend_string_equals_literal_ci(name, "strict_types")) { zval value_zv; - if (FAILURE == zend_is_first_statement(ast, /* allow_nop */ 0)) { + if (FAILURE == zend_is_first_statement(ast, /* allow_nop */ true)) { zend_error_noreturn(E_COMPILE_ERROR, "strict_types declaration must be " "the very first statement in the script"); } @@ -6992,7 +7126,7 @@ static void zend_compile_declare(zend_ast *ast) /* {{{ */ static void zend_compile_stmt_list(zend_ast *ast) /* {{{ */ { - 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) { zend_compile_stmt(list->child[i]); @@ -7067,16 +7201,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"); } @@ -7114,9 +7252,9 @@ static void zend_are_intersection_types_redundant(const zend_type left_type, con { ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(left_type)); ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(right_type)); - zend_type_list *l_type_list = ZEND_TYPE_LIST(left_type); - zend_type_list *r_type_list = ZEND_TYPE_LIST(right_type); - zend_type_list *smaller_type_list, *larger_type_list; + const zend_type_list *l_type_list = ZEND_TYPE_LIST(left_type); + const zend_type_list *r_type_list = ZEND_TYPE_LIST(right_type); + const zend_type_list *smaller_type_list, *larger_type_list; bool flipped = false; if (r_type_list->num_types < l_type_list->num_types) { @@ -7206,7 +7344,7 @@ static zend_type zend_compile_typename_ex( } 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); zend_type_list *type_list; bool is_composite = false; bool has_only_iterable_class = true; @@ -7322,7 +7460,7 @@ static zend_type zend_compile_typename_ex( ZSTR_VAL(type_str)); } } else 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); zend_type_list *type_list; /* Allocate the type list directly on the arena as it must be a type @@ -7452,20 +7590,20 @@ static void zend_compile_attributes( zend_attribute *attr; zend_internal_attribute *config; - zend_ast_list *list = zend_ast_get_list(ast); + const zend_ast_list *list = zend_ast_get_list(ast); uint32_t g, i, j; ZEND_ASSERT(ast->kind == ZEND_AST_ATTRIBUTE_LIST); for (g = 0; g < list->children; g++) { - zend_ast_list *group = zend_ast_get_list(list->child[g]); + const zend_ast_list *group = zend_ast_get_list(list->child[g]); ZEND_ASSERT(group->kind == ZEND_AST_ATTRIBUTE_GROUP); for (i = 0; i < group->children; i++) { ZEND_ASSERT(group->child[i]->kind == ZEND_AST_ATTRIBUTE); - zend_ast *el = group->child[i]; + const zend_ast *el = group->child[i]; if (el->child[1] && el->child[1]->kind == ZEND_AST_CALLABLE_CONVERT) { @@ -7498,7 +7636,7 @@ static void zend_compile_attributes( if (args) { ZEND_ASSERT(args->kind == ZEND_AST_ARG_LIST); - bool uses_named_args = 0; + bool uses_named_args = false; for (j = 0; j < args->children; j++) { zend_ast **arg_ast_ptr = &args->child[j]; zend_ast *arg_ast = *arg_ast_ptr; @@ -7511,7 +7649,7 @@ static void zend_compile_attributes( if (arg_ast->kind == ZEND_AST_NAMED_ARG) { attr->args[j].name = zend_string_copy(zend_ast_get_str(arg_ast->child[0])); arg_ast_ptr = &arg_ast->child[1]; - uses_named_args = 1; + uses_named_args = true; for (uint32_t k = 0; k < j; k++) { if (attr->args[k].name && @@ -7533,19 +7671,41 @@ static void zend_compile_attributes( } if (*attributes != NULL) { + /* Allow delaying target validation for forward compatibility. */ + const 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)) { @@ -7554,8 +7714,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(); } @@ -7564,10 +7733,10 @@ static void zend_compile_attributes( static void zend_compile_property_hooks( zend_property_info *prop_info, zend_string *prop_name, - zend_ast *prop_type_ast, zend_ast_list *hooks); + zend_ast *prop_type_ast, const zend_ast_list *hooks); typedef struct { - zend_string *property_name; + const zend_string *property_name; bool uses_property; } find_property_usage_context; @@ -7579,14 +7748,14 @@ static void zend_property_hook_find_property_usage(zend_ast **ast_ptr, void *_co if (ast == NULL) { return; } else if (ast->kind == ZEND_AST_PROP || ast->kind == ZEND_AST_NULLSAFE_PROP) { - zend_ast *object_ast = ast->child[0]; + const zend_ast *object_ast = ast->child[0]; zend_ast *property_ast = ast->child[1]; if (object_ast->kind == ZEND_AST_VAR && object_ast->child[0]->kind == ZEND_AST_ZVAL && property_ast->kind == ZEND_AST_ZVAL) { - zval *object = zend_ast_get_zval(object_ast->child[0]); - zval *property = zend_ast_get_zval(property_ast); + const zval *object = zend_ast_get_zval(object_ast->child[0]); + const zval *property = zend_ast_get_zval(property_ast); if (Z_TYPE_P(object) == IS_STRING && Z_TYPE_P(property) == IS_STRING && zend_string_equals_literal(Z_STR_P(object), "this") @@ -7604,7 +7773,7 @@ static void zend_property_hook_find_property_usage(zend_ast **ast_ptr, void *_co } } -static bool zend_property_hook_uses_property(zend_string *property_name, zend_string *hook_name, zend_ast *hook_ast) +static bool zend_property_hook_uses_property(const zend_string *property_name, const zend_string *hook_name, zend_ast *hook_ast) { if (zend_string_equals_literal_ci(hook_name, "set") && hook_ast->kind == ZEND_AST_PROPERTY_HOOK_SHORT_BODY) { @@ -7616,7 +7785,7 @@ static bool zend_property_hook_uses_property(zend_string *property_name, zend_st return context.uses_property; } -static bool zend_property_is_virtual(zend_class_entry *ce, zend_string *property_name, zend_ast *hooks_ast, uint32_t flags) +static bool zend_property_is_virtual(const zend_class_entry *ce, const zend_string *property_name, zend_ast *hooks_ast, uint32_t flags) { if (ce->ce_flags & ZEND_ACC_INTERFACE) { return true; @@ -7627,9 +7796,9 @@ static bool zend_property_is_virtual(zend_class_entry *ce, zend_string *property bool is_virtual = true; - zend_ast_list *hooks = zend_ast_get_list(hooks_ast); + const zend_ast_list *hooks = zend_ast_get_list(hooks_ast); for (uint32_t i = 0; i < hooks->children; i++) { - zend_ast_decl *hook = (zend_ast_decl *) hooks->child[i]; + const zend_ast_decl *hook = (const zend_ast_decl *) hooks->child[i]; zend_ast *body = hook->child[2]; if (body && zend_property_hook_uses_property(property_name, hook->name, body)) { is_virtual = false; @@ -7684,6 +7853,7 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32 } } + const uint32_t promotion_flags = ZEND_ACC_PPP_MASK | ZEND_ACC_PPP_SET_MASK | ZEND_ACC_READONLY | ZEND_ACC_FINAL; for (i = 0; i < list->children; ++i) { zend_ast *param_ast = list->child[i]; zend_ast *type_ast = param_ast->child[0]; @@ -7695,7 +7865,7 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32 zend_string *name = zval_make_interned_string(zend_ast_get_zval(var_ast)); bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0; bool is_variadic = (param_ast->attr & ZEND_PARAM_VARIADIC) != 0; - uint32_t property_flags = param_ast->attr & (ZEND_ACC_PPP_MASK | ZEND_ACC_PPP_SET_MASK | ZEND_ACC_READONLY | ZEND_ACC_FINAL); + uint32_t property_flags = param_ast->attr & promotion_flags; bool is_promoted = property_flags || hooks_ast; CG(zend_lineno) = param_ast->lineno; @@ -7718,6 +7888,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) { @@ -7751,6 +7923,7 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32 arg_info = &arg_infos[i]; arg_info->name = zend_string_copy(name); arg_info->type = (zend_type) ZEND_TYPE_INIT_NONE(0); + arg_info->default_value = NULL; if (attributes_ast) { zend_compile_attributes( @@ -7827,16 +8000,16 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32 } if (is_promoted) { - zend_op_array *op_array = CG(active_op_array); - zend_class_entry *scope = op_array->scope; + const zend_op_array *active_op_array = CG(active_op_array); + zend_class_entry *scope = active_op_array->scope; bool is_ctor = - scope && zend_is_constructor(op_array->function_name); + scope && zend_is_constructor(active_op_array->function_name); if (!is_ctor) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare promoted property outside a constructor"); } - if ((op_array->fn_flags & ZEND_ACC_ABSTRACT) + if ((active_op_array->fn_flags & ZEND_ACC_ABSTRACT) || (scope->ce_flags & ZEND_ACC_INTERFACE)) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare promoted property in an abstract constructor"); @@ -7891,12 +8064,17 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32 property_flags | (zend_property_is_virtual(scope, name, hooks_ast, property_flags) ? ZEND_ACC_VIRTUAL : 0) | ZEND_ACC_PROMOTED, doc_comment, type); if (hooks_ast) { - zend_ast_list *hooks = zend_ast_get_list(hooks_ast); + const zend_ast_list *hooks = zend_ast_get_list(hooks_ast); zend_compile_property_hooks(prop, name, type_ast, hooks); } 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; + } } } } @@ -7915,7 +8093,7 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32 zend_ast *param_ast = list->child[i]; zend_ast *hooks_ast = param_ast->child[5]; bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0; - uint32_t flags = param_ast->attr & (ZEND_ACC_PPP_MASK | ZEND_ACC_PPP_SET_MASK | ZEND_ACC_READONLY); + uint32_t flags = param_ast->attr & promotion_flags; bool is_promoted = flags || hooks_ast; if (!is_promoted) { continue; @@ -7941,7 +8119,7 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32 static void zend_compile_closure_binding(znode *closure, zend_op_array *op_array, zend_ast *uses_ast) /* {{{ */ { - zend_ast_list *list = zend_ast_get_list(uses_ast); + const zend_ast_list *list = zend_ast_get_list(uses_ast); uint32_t i; if (!list->children) { @@ -7989,6 +8167,8 @@ typedef struct { bool varvars_used; } closure_info; +static void find_implicit_binds(closure_info *info, zend_ast *params_ast, zend_ast *stmt_ast); + static void find_implicit_binds_recursively(closure_info *info, zend_ast *ast) { if (!ast) { return; @@ -8010,21 +8190,21 @@ static void find_implicit_binds_recursively(closure_info *info, zend_ast *ast) { zend_hash_add_empty_element(&info->uses, name); } else { - info->varvars_used = 1; + info->varvars_used = true; find_implicit_binds_recursively(info, name_ast); } } 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); uint32_t i; for (i = 0; i < list->children; i++) { find_implicit_binds_recursively(info, list->child[i]); } } else if (ast->kind == ZEND_AST_CLOSURE) { /* For normal closures add the use() list. */ - zend_ast_decl *closure_ast = (zend_ast_decl *) ast; + const zend_ast_decl *closure_ast = (const zend_ast_decl *) ast; zend_ast *uses_ast = closure_ast->child[1]; if (uses_ast) { - zend_ast_list *uses_list = zend_ast_get_list(uses_ast); + const zend_ast_list *uses_list = zend_ast_get_list(uses_ast); uint32_t i; for (i = 0; i < uses_list->children; i++) { zend_hash_add_empty_element(&info->uses, zend_ast_get_str(uses_list->child[i])); @@ -8032,8 +8212,16 @@ static void find_implicit_binds_recursively(closure_info *info, zend_ast *ast) { } } else if (ast->kind == ZEND_AST_ARROW_FUNC) { /* For arrow functions recursively check the expression. */ - zend_ast_decl *closure_ast = (zend_ast_decl *) ast; - find_implicit_binds_recursively(info, closure_ast->child[2]); + const zend_ast_decl *closure_ast = (const zend_ast_decl *) ast; + closure_info inner_info; + find_implicit_binds(&inner_info, closure_ast->child[0], closure_ast->child[2]); + if (inner_info.varvars_used) { + info->varvars_used = true; + } + if (zend_hash_num_elements(&inner_info.uses)) { + zend_hash_copy(&info->uses, &inner_info.uses, NULL); + } + zend_hash_destroy(&inner_info.uses); } else if (!zend_ast_is_special(ast)) { uint32_t i, children = zend_ast_get_num_children(ast); for (i = 0; i < children; i++) { @@ -8044,22 +8232,23 @@ static void find_implicit_binds_recursively(closure_info *info, zend_ast *ast) { static void find_implicit_binds(closure_info *info, zend_ast *params_ast, zend_ast *stmt_ast) { - zend_ast_list *param_list = zend_ast_get_list(params_ast); + const zend_ast_list *param_list = zend_ast_get_list(params_ast); uint32_t i; zend_hash_init(&info->uses, param_list->children, NULL, NULL, 0); + info->varvars_used = false; find_implicit_binds_recursively(info, stmt_ast); /* Remove variables that are parameters */ for (i = 0; i < param_list->children; i++) { - zend_ast *param_ast = param_list->child[i]; + const zend_ast *param_ast = param_list->child[i]; zend_hash_del(&info->uses, zend_ast_get_str(param_ast->child[1])); } } static void compile_implicit_lexical_binds( - closure_info *info, znode *closure, zend_op_array *op_array) + const closure_info *info, znode *closure, zend_op_array *op_array) { zend_string *var_name; zend_op *opline; @@ -8087,8 +8276,8 @@ static void compile_implicit_lexical_binds( static void zend_compile_closure_uses(zend_ast *ast) /* {{{ */ { - zend_op_array *op_array = CG(active_op_array); - zend_ast_list *list = zend_ast_get_list(ast); + const zend_op_array *op_array = CG(active_op_array); + const zend_ast_list *list = zend_ast_get_list(ast); uint32_t i; for (i = 0; i < list->children; ++i) { @@ -8119,7 +8308,7 @@ static void zend_compile_closure_uses(zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_implicit_closure_uses(closure_info *info) +static void zend_compile_implicit_closure_uses(const closure_info *info) { zend_string *var_name; ZEND_HASH_MAP_FOREACH_STR_KEY(&info->uses, var_name) @@ -8244,7 +8433,7 @@ enum func_decl_level { FUNC_DECL_LEVEL_CONSTEXPR, }; -static zend_string *zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_ast_decl *decl, enum func_decl_level level) /* {{{ */ +static zend_string *zend_begin_func_decl(znode *result, zend_op_array *op_array, const zend_ast_decl *decl, enum func_decl_level level) /* {{{ */ { zend_string *unqualified_name, *name, *lcname; zend_op *opline; @@ -8256,7 +8445,7 @@ static zend_string *zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_string *class = zend_empty_string; zend_string *separator = zend_empty_string; zend_string *function = filename; - char *parens = ""; + const char *parens = ""; if (CG(active_op_array) && CG(active_op_array)->function_name) { if (CG(active_op_array)->fn_flags & ZEND_ACC_CLOSURE) { @@ -8294,7 +8483,7 @@ static zend_string *zend_begin_func_decl(znode *result, zend_op_array *op_array, lcname = zend_string_tolower(name); if (FC(imports_function)) { - zend_string *import_name = + const zend_string *import_name = zend_hash_find_ptr_lc(FC(imports_function), unqualified_name); if (import_name && !zend_string_equals_ci(lcname, import_name)) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare function %s() (previously declared as local import)", @@ -8357,7 +8546,6 @@ static zend_op_array *zend_compile_func_decl_ex( zend_op_array *op_array = zend_arena_alloc(&CG(arena), sizeof(zend_op_array)); zend_oparray_context orig_oparray_context; closure_info info; - memset(&info, 0, sizeof(closure_info)); init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE); @@ -8396,6 +8584,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; @@ -8405,7 +8597,7 @@ static zend_op_array *zend_compile_func_decl_ex( zend_compile_attributes(&op_array->attributes, decl->child[4], 0, target, 0); - zend_attribute *override_attribute = zend_get_attribute_str( + const zend_attribute *override_attribute = zend_get_attribute_str( op_array->attributes, "override", sizeof("override")-1 @@ -8415,7 +8607,7 @@ static zend_op_array *zend_compile_func_decl_ex( op_array->fn_flags |= ZEND_ACC_OVERRIDE; } - zend_attribute *deprecated_attribute = zend_get_attribute_str( + const zend_attribute *deprecated_attribute = zend_get_attribute_str( op_array->attributes, "deprecated", sizeof("deprecated")-1 @@ -8425,15 +8617,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 @@ -8447,10 +8631,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; @@ -8475,7 +8655,7 @@ static zend_op_array *zend_compile_func_decl_ex( if (ast->kind == ZEND_AST_ARROW_FUNC && decl->child[2]->kind != ZEND_AST_RETURN) { bool needs_return = true; if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { - zend_arg_info *return_info = CG(active_op_array)->arg_info - 1; + const zend_arg_info *return_info = CG(active_op_array)->arg_info - 1; needs_return = !ZEND_TYPE_CONTAINS_CODE(return_info->type, IS_NEVER); } if (needs_return) { @@ -8485,12 +8665,15 @@ 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; + const zend_arg_info *return_info = CG(active_op_array)->arg_info - 1; if (ZEND_TYPE_CONTAINS_CODE(return_info->type, IS_VOID)) { zend_error_noreturn(E_COMPILE_ERROR, "A void %s does not return a value, but #[\\NoDiscard] requires a return value", @@ -8522,8 +8705,8 @@ 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_emit_final_return(0); + zend_do_extended_stmt(NULL); + zend_emit_final_return(false); pass_two(CG(active_op_array)); zend_oparray_context_end(&orig_oparray_context); @@ -8550,7 +8733,7 @@ static zend_op_array *zend_compile_func_decl(znode *result, zend_ast *ast, enum return zend_compile_func_decl_ex(result, ast, level, /* property_info */ NULL, (zend_property_hook_kind)-1); } -zend_property_hook_kind zend_get_property_hook_kind_from_name(zend_string *name) { +zend_property_hook_kind zend_get_property_hook_kind_from_name(const zend_string *name) { if (zend_string_equals_literal_ci(name, "get")) { return ZEND_PROPERTY_HOOK_GET; } else if (zend_string_equals_literal_ci(name, "set")) { @@ -8562,7 +8745,7 @@ zend_property_hook_kind zend_get_property_hook_kind_from_name(zend_string *name) static void zend_compile_property_hooks( zend_property_info *prop_info, zend_string *prop_name, - zend_ast *prop_type_ast, zend_ast_list *hooks) + zend_ast *prop_type_ast, const zend_ast_list *hooks) { zend_class_entry *ce = CG(active_class_entry); @@ -8646,12 +8829,12 @@ static void zend_compile_property_hooks( *return_type_ast_ptr = prop_type_ast; } else if (hook_kind == ZEND_PROPERTY_HOOK_SET) { if (hook->child[0]) { - zend_ast_list *param_list = zend_ast_get_list(hook->child[0]); + const zend_ast_list *param_list = zend_ast_get_list(hook->child[0]); if (param_list->children != 1) { zend_error_noreturn(E_COMPILE_ERROR, "%s hook of property %s::$%s must accept exactly one parameters", ZSTR_VAL(name), ZSTR_VAL(ce->name), ZSTR_VAL(prop_name)); } - zend_ast *value_param_ast = param_list->child[0]; + const zend_ast *value_param_ast = param_list->child[0]; if (value_param_ast->attr & ZEND_PARAM_REF) { zend_error_noreturn(E_COMPILE_ERROR, "Parameter $%s of %s hook %s::$%s must not be pass-by-reference", ZSTR_VAL(zend_ast_get_str(value_param_ast->child[1])), ZSTR_VAL(name), ZSTR_VAL(ce->name), ZSTR_VAL(prop_name)); @@ -8742,7 +8925,7 @@ static void zend_compile_property_hooks( static void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t flags, zend_ast *attr_ast) /* {{{ */ { - zend_ast_list *list = zend_ast_get_list(ast); + const zend_ast_list *list = zend_ast_get_list(ast); zend_class_entry *ce = CG(active_class_entry); uint32_t i, children = list->children; @@ -8876,6 +9059,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); + + const 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; @@ -8883,7 +9071,7 @@ static void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t f } /* }}} */ -static void zend_compile_prop_group(zend_ast *ast) /* {{{ */ +static void zend_compile_prop_group(const zend_ast *ast) /* {{{ */ { zend_ast *type_ast = ast->child[0]; zend_ast *prop_ast = ast->child[1]; @@ -8905,7 +9093,7 @@ static void zend_check_trait_alias_modifiers(uint32_t attr) /* {{{ */ static void zend_compile_class_const_decl(zend_ast *ast, uint32_t flags, zend_ast *attr_ast, zend_ast *type_ast) { - zend_ast_list *list = zend_ast_get_list(ast); + const zend_ast_list *list = zend_ast_get_list(ast); zend_class_entry *ce = CG(active_class_entry); uint32_t i, children = list->children; @@ -8954,7 +9142,7 @@ static void zend_compile_class_const_decl(zend_ast *ast, uint32_t flags, zend_as if (attr_ast) { zend_compile_attributes(&c->attributes, attr_ast, 0, ZEND_ATTRIBUTE_TARGET_CLASS_CONST, 0); - zend_attribute *deprecated = zend_get_attribute_str(c->attributes, "deprecated", sizeof("deprecated")-1); + const zend_attribute *deprecated = zend_get_attribute_str(c->attributes, "deprecated", sizeof("deprecated")-1); if (deprecated) { ZEND_CLASS_CONST_FLAGS(c) |= ZEND_ACC_DEPRECATED; @@ -8967,7 +9155,7 @@ static void zend_compile_class_const_decl(zend_ast *ast, uint32_t flags, zend_as } } -static void zend_compile_class_const_group(zend_ast *ast) /* {{{ */ +static void zend_compile_class_const_group(const zend_ast *ast) /* {{{ */ { zend_ast *const_ast = ast->child[0]; zend_ast *attr_ast = ast->child[1]; @@ -8977,7 +9165,7 @@ static void zend_compile_class_const_group(zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_method_ref(zend_ast *ast, zend_trait_method_reference *method_ref) /* {{{ */ +static void zend_compile_method_ref(const zend_ast *ast, zend_trait_method_reference *method_ref) /* {{{ */ { zend_ast *class_ast = ast->child[0]; zend_ast *method_ast = ast->child[1]; @@ -8992,11 +9180,11 @@ static void zend_compile_method_ref(zend_ast *ast, zend_trait_method_reference * } /* }}} */ -static void zend_compile_trait_precedence(zend_ast *ast) /* {{{ */ +static void zend_compile_trait_precedence(const zend_ast *ast) /* {{{ */ { - zend_ast *method_ref_ast = ast->child[0]; + const zend_ast *method_ref_ast = ast->child[0]; zend_ast *insteadof_ast = ast->child[1]; - zend_ast_list *insteadof_list = zend_ast_get_list(insteadof_ast); + const zend_ast_list *insteadof_list = zend_ast_get_list(insteadof_ast); uint32_t i; zend_trait_precedence *precedence = emalloc(sizeof(zend_trait_precedence) + (insteadof_list->children - 1) * sizeof(zend_string*)); @@ -9013,9 +9201,9 @@ static void zend_compile_trait_precedence(zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_trait_alias(zend_ast *ast) /* {{{ */ +static void zend_compile_trait_alias(const zend_ast *ast) /* {{{ */ { - zend_ast *method_ref_ast = ast->child[0]; + const zend_ast *method_ref_ast = ast->child[0]; zend_ast *alias_ast = ast->child[1]; uint32_t modifiers = ast->attr; @@ -9037,9 +9225,9 @@ static void zend_compile_trait_alias(zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_use_trait(zend_ast *ast) /* {{{ */ +static void zend_compile_use_trait(const zend_ast *ast) /* {{{ */ { - zend_ast_list *traits = zend_ast_get_list(ast->child[0]); + const zend_ast_list *traits = zend_ast_get_list(ast->child[0]); zend_ast_list *adaptations = ast->child[1] ? zend_ast_get_list(ast->child[1]) : NULL; zend_class_entry *ce = CG(active_class_entry); uint32_t i; @@ -9066,7 +9254,7 @@ static void zend_compile_use_trait(zend_ast *ast) /* {{{ */ } for (i = 0; i < adaptations->children; ++i) { - zend_ast *adaptation_ast = adaptations->child[i]; + const zend_ast *adaptation_ast = adaptations->child[i]; switch (adaptation_ast->kind) { case ZEND_AST_TRAIT_PRECEDENCE: zend_compile_trait_precedence(adaptation_ast); @@ -9082,7 +9270,7 @@ static void zend_compile_use_trait(zend_ast *ast) /* {{{ */ static void zend_compile_implements(zend_ast *ast) /* {{{ */ { - zend_ast_list *list = zend_ast_get_list(ast); + const zend_ast_list *list = zend_ast_get_list(ast); zend_class_entry *ce = CG(active_class_entry); zend_class_name *interface_names; uint32_t i; @@ -9101,7 +9289,7 @@ static void zend_compile_implements(zend_ast *ast) /* {{{ */ } /* }}} */ -static zend_string *zend_generate_anon_class_name(zend_ast_decl *decl) +static zend_string *zend_generate_anon_class_name(const zend_ast_decl *decl) { zend_string *filename = CG(active_op_array)->filename; uint32_t start_lineno = decl->start_lineno; @@ -9111,7 +9299,7 @@ static zend_string *zend_generate_anon_class_name(zend_ast_decl *decl) if (decl->child[0]) { prefix = zend_resolve_const_class_name_reference(decl->child[0], "class name"); } else if (decl->child[1]) { - zend_ast_list *list = zend_ast_get_list(decl->child[1]); + const zend_ast_list *list = zend_ast_get_list(decl->child[1]); prefix = zend_resolve_const_class_name_reference(list->child[0], "interface name"); } @@ -9141,9 +9329,9 @@ static void zend_compile_enum_backing_type(zend_class_entry *ce, zend_ast *enum_ zend_type_release(type, 0); } -static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel) /* {{{ */ +static void zend_compile_class_decl(znode *result, const zend_ast *ast, bool toplevel) /* {{{ */ { - zend_ast_decl *decl = (zend_ast_decl *) ast; + const zend_ast_decl *decl = (const zend_ast_decl *) ast; zend_ast *extends_ast = decl->child[0]; zend_ast *implements_ast = decl->child[1]; zend_ast *stmt_ast = decl->child[2]; @@ -9199,7 +9387,7 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel) ce->type = ZEND_USER_CLASS; ce->name = name; - zend_initialize_class_data(ce, 1); + zend_initialize_class_data(ce, true); if (!(decl->flags & ZEND_ACC_ANON_CLASS)) { zend_alloc_ce_cache(ce->name); } @@ -9463,7 +9651,7 @@ static char *zend_get_use_type_str(uint32_t type) /* {{{ */ } /* }}} */ -static void zend_check_already_in_use(uint32_t type, zend_string *old_name, zend_string *new_name, zend_string *check_name) /* {{{ */ +static void zend_check_already_in_use(uint32_t type, const zend_string *old_name, const zend_string *new_name, const zend_string *check_name) /* {{{ */ { if (zend_string_equals_ci(old_name, check_name)) { return; @@ -9476,7 +9664,7 @@ static void zend_check_already_in_use(uint32_t type, zend_string *old_name, zend static void zend_compile_use(zend_ast *ast) /* {{{ */ { - zend_ast_list *list = zend_ast_get_list(ast); + const zend_ast_list *list = zend_ast_get_list(ast); uint32_t i; zend_string *current_ns = FC(current_namespace); uint32_t type = ast->attr; @@ -9484,7 +9672,7 @@ static void zend_compile_use(zend_ast *ast) /* {{{ */ bool case_sensitive = type == ZEND_SYMBOL_CONST; for (i = 0; i < list->children; ++i) { - zend_ast *use_ast = list->child[i]; + const zend_ast *use_ast = list->child[i]; zend_ast *old_name_ast = use_ast->child[0]; zend_ast *new_name_ast = use_ast->child[1]; zend_string *old_name = zend_ast_get_str(old_name_ast); @@ -9547,11 +9735,11 @@ static void zend_compile_use(zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_group_use(zend_ast *ast) /* {{{ */ +static void zend_compile_group_use(const zend_ast *ast) /* {{{ */ { uint32_t i; - zend_string *ns = zend_ast_get_str(ast->child[0]); - zend_ast_list *list = zend_ast_get_list(ast->child[1]); + const zend_string *ns = zend_ast_get_str(ast->child[0]); + const zend_ast_list *list = zend_ast_get_list(ast->child[1]); for (i = 0; i < list->children; i++) { zend_ast *inline_use, *use = list->child[i]; @@ -9641,7 +9829,7 @@ static void zend_compile_const_decl(zend_ast *ast) /* {{{ */ } /* }}}*/ -static void zend_compile_namespace(zend_ast *ast) /* {{{ */ +static void zend_compile_namespace(const zend_ast *ast) /* {{{ */ { zend_ast *name_ast = ast->child[0]; zend_ast *stmt_ast = ast->child[1]; @@ -9669,7 +9857,7 @@ static void zend_compile_namespace(zend_ast *ast) /* {{{ */ bool is_first_namespace = (!with_bracket && !FC(current_namespace)) || (with_bracket && !FC(has_bracketed_namespaces)); - if (is_first_namespace && FAILURE == zend_is_first_statement(ast, /* allow_nop */ 1)) { + if (is_first_namespace && FAILURE == zend_is_first_statement(ast, /* allow_nop */ true)) { zend_error_noreturn(E_COMPILE_ERROR, "Namespace declaration statement has to be " "the very first statement or after any declare call in the script"); } @@ -9704,12 +9892,11 @@ static void zend_compile_namespace(zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_halt_compiler(zend_ast *ast) /* {{{ */ +static void zend_compile_halt_compiler(const zend_ast *ast) /* {{{ */ { zend_ast *offset_ast = ast->child[0]; zend_long offset = Z_LVAL_P(zend_ast_get_zval(offset_ast)); - zend_string *filename, *name; const char const_name[] = "__COMPILER_HALT_OFFSET__"; if (FC(has_bracketed_namespaces) && FC(in_namespace)) { @@ -9717,19 +9904,23 @@ static void zend_compile_halt_compiler(zend_ast *ast) /* {{{ */ "__HALT_COMPILER() can only be used from the outermost scope"); } - filename = zend_get_compiled_filename(); - name = zend_mangle_property_name(const_name, sizeof(const_name) - 1, - ZSTR_VAL(filename), ZSTR_LEN(filename), 0); + const zend_string *filename = zend_get_compiled_filename(); + zend_string *name = zend_mangle_property_name(const_name, sizeof(const_name) - 1, + ZSTR_VAL(filename), ZSTR_LEN(filename), false); - 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); } /* }}} */ -static bool zend_try_ct_eval_magic_const(zval *zv, zend_ast *ast) /* {{{ */ +static bool zend_try_ct_eval_magic_const(zval *zv, const zend_ast *ast) /* {{{ */ { - zend_op_array *op_array = CG(active_op_array); - zend_class_entry *ce = CG(active_class_entry); + const zend_op_array *op_array = CG(active_op_array); + const zend_class_entry *ce = CG(active_class_entry); switch (ast->attr) { case T_LINE: @@ -9740,7 +9931,7 @@ static bool zend_try_ct_eval_magic_const(zval *zv, zend_ast *ast) /* {{{ */ break; case T_DIR: { - zend_string *filename = CG(compiled_filename); + const zend_string *filename = CG(compiled_filename); zend_string *dirname = zend_string_init(ZSTR_VAL(filename), ZSTR_LEN(filename), 0); #ifdef ZEND_WIN32 ZSTR_LEN(dirname) = php_win32_ioutil_dirname(ZSTR_VAL(dirname), ZSTR_LEN(dirname)); @@ -9833,14 +10024,14 @@ ZEND_API bool zend_is_op_long_compatible(const zval *op) } if (Z_TYPE_P(op) == IS_DOUBLE - && !zend_is_long_compatible(Z_DVAL_P(op), zend_dval_to_lval(Z_DVAL_P(op)))) { + && !zend_is_long_compatible(Z_DVAL_P(op), zend_dval_to_lval_silent(Z_DVAL_P(op)))) { return false; } if (Z_TYPE_P(op) == IS_STRING) { double dval = 0; uint8_t is_num = is_numeric_str_function(Z_STR_P(op), NULL, &dval); - if (is_num == 0 || (is_num == IS_DOUBLE && !zend_is_long_compatible(dval, zend_dval_to_lval(dval)))) { + if (is_num == 0 || (is_num == IS_DOUBLE && !zend_is_long_compatible(dval, zend_dval_to_lval_silent(dval)))) { return false; } } @@ -9889,11 +10080,27 @@ ZEND_API bool zend_binary_op_produces_error(uint32_t opcode, const zval *op1, co return 1; } - if ((opcode == ZEND_MOD && zval_get_long(op2) == 0) - || (opcode == ZEND_DIV && zval_get_double(op2) == 0.0)) { + /* Operation which cast float/float-strings to integers might produce incompatible float to int errors */ + if (opcode == ZEND_SL || opcode == ZEND_SR || opcode == ZEND_BW_OR + || opcode == ZEND_BW_AND || opcode == ZEND_BW_XOR) { + if (!zend_is_op_long_compatible(op1) || !zend_is_op_long_compatible(op2)) { + return 1; + } + } + + if (opcode == ZEND_DIV && zval_get_double(op2) == 0.0) { /* Division by zero throws an error. */ return 1; } + + /* Mod is an operation that will cast float/float-strings to integers which might + produce float to int incompatible errors, and also cannot be divided by 0 */ + if (opcode == ZEND_MOD) { + if (!zend_is_op_long_compatible(op1) || !zend_is_op_long_compatible(op2) || zval_get_long(op2) == 0) { + return 1; + } + } + if ((opcode == ZEND_POW) && zval_get_double(op1) == 0 && zval_get_double(op2) < 0) { /* 0 ** (<0) throws a division by zero error. */ return 1; @@ -9903,12 +10110,6 @@ ZEND_API bool zend_binary_op_produces_error(uint32_t opcode, const zval *op1, co return 1; } - /* Operation which cast float/float-strings to integers might produce incompatible float to int errors */ - if (opcode == ZEND_SL || opcode == ZEND_SR || opcode == ZEND_BW_OR - || opcode == ZEND_BW_AND || opcode == ZEND_BW_XOR || opcode == ZEND_MOD) { - return !zend_is_op_long_compatible(op1) || !zend_is_op_long_compatible(op2); - } - return 0; } /* }}} */ @@ -9919,7 +10120,7 @@ static inline bool zend_try_ct_eval_binary_op(zval *result, uint32_t opcode, zva return 0; } - binary_op_type fn = get_binary_op(opcode); + const binary_op_type fn = get_binary_op(opcode); fn(result, op1, op2); return 1; } @@ -9934,6 +10135,11 @@ ZEND_API bool zend_unary_op_produces_error(uint32_t opcode, const zval *op) } return Z_TYPE_P(op) <= IS_TRUE || !zend_is_op_long_compatible(op); } + /* Can happen when called from zend_optimizer_eval_unary_op() */ + if (opcode == ZEND_BOOL || opcode == ZEND_BOOL_NOT) { + /* ZEND_BOOL/ZEND_BOOL_NOT warns when casting NAN. */ + return Z_TYPE_P(op) == IS_DOUBLE; + } return 0; } @@ -9944,7 +10150,7 @@ static inline bool zend_try_ct_eval_unary_op(zval *result, uint32_t opcode, zval return 0; } - unary_op_type fn = get_unary_op(opcode); + const unary_op_type fn = get_unary_op(opcode); fn(result, op); return 1; } @@ -9960,7 +10166,7 @@ static inline bool zend_try_ct_eval_unary_pm(zval *result, zend_ast_kind kind, z static inline void zend_ct_eval_greater(zval *result, zend_ast_kind kind, zval *op1, zval *op2) /* {{{ */ { - binary_op_type fn = kind == ZEND_AST_GREATER + const binary_op_type fn = kind == ZEND_AST_GREATER ? is_smaller_function : is_smaller_or_equal_function; fn(result, op2, op1); } @@ -9968,10 +10174,10 @@ static inline void zend_ct_eval_greater(zval *result, zend_ast_kind kind, zval * static bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */ { - zend_ast_list *list = zend_ast_get_list(ast); + const zend_ast_list *list = zend_ast_get_list(ast); zend_ast *last_elem_ast = NULL; uint32_t i; - bool is_constant = 1; + bool is_constant = true; if (ast->attr == ZEND_ARRAY_SYNTAX_LIST) { zend_error(E_COMPILE_ERROR, "Cannot use list() as standalone expression"); @@ -9996,13 +10202,13 @@ static bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */ if (elem_ast->attr /* by_ref */ || elem_ast->child[0]->kind != ZEND_AST_ZVAL || (elem_ast->child[1] && elem_ast->child[1]->kind != ZEND_AST_ZVAL) ) { - is_constant = 0; + is_constant = false; } } else { zend_eval_const_expr(&elem_ast->child[0]); if (elem_ast->child[0]->kind != ZEND_AST_ZVAL) { - is_constant = 0; + is_constant = false; } } @@ -10020,14 +10226,14 @@ static bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */ array_init_size(result, list->children); for (i = 0; i < list->children; ++i) { - zend_ast *elem_ast = list->child[i]; + const zend_ast *elem_ast = list->child[i]; zend_ast *value_ast = elem_ast->child[0]; zend_ast *key_ast; zval *value = zend_ast_get_zval(value_ast); if (elem_ast->kind == ZEND_AST_UNPACK) { if (Z_TYPE_P(value) == IS_ARRAY) { - HashTable *ht = Z_ARRVAL_P(value); + const HashTable *ht = Z_ARRVAL_P(value); zval *val; zend_string *key; @@ -10051,7 +10257,7 @@ static bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */ key_ast = elem_ast->child[1]; if (key_ast) { - zval *key = zend_ast_get_zval(key_ast); + const zval *key = zend_ast_get_zval(key_ast); switch (Z_TYPE_P(key)) { case IS_LONG: zend_hash_index_update(Z_ARRVAL_P(result), Z_LVAL_P(key), value); @@ -10060,12 +10266,10 @@ static bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */ zend_symtable_update(Z_ARRVAL_P(result), Z_STR_P(key), value); break; case IS_DOUBLE: { - zend_long lval = zend_dval_to_lval(Z_DVAL_P(key)); + zend_long lval = zend_dval_to_lval_silent(Z_DVAL_P(key)); /* Incompatible float will generate an error, leave this to run-time */ if (!zend_is_long_compatible(Z_DVAL_P(key), lval)) { - zval_ptr_dtor_nogc(value); - zval_ptr_dtor(result); - return 0; + goto fail; } zend_hash_index_update(Z_ARRVAL_P(result), lval, value); break; @@ -10077,13 +10281,14 @@ static bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */ zend_hash_index_update(Z_ARRVAL_P(result), 1, value); break; case IS_NULL: - zend_hash_update(Z_ARRVAL_P(result), ZSTR_EMPTY_ALLOC(), value); - break; + /* Null key will generate a warning at run-time. */ + goto fail; default: zend_error_noreturn(E_COMPILE_ERROR, "Illegal offset type"); break; } } else if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), value)) { +fail: zval_ptr_dtor_nogc(value); zval_ptr_dtor(result); return 0; @@ -10117,29 +10322,7 @@ static void zend_compile_binary_op(znode *result, zend_ast *ast) /* {{{ */ } do { - if (opcode == ZEND_IS_EQUAL || opcode == ZEND_IS_NOT_EQUAL) { - if (left_node.op_type == IS_CONST) { - if (Z_TYPE(left_node.u.constant) == IS_FALSE) { - opcode = (opcode == ZEND_IS_NOT_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT; - zend_emit_op_tmp(result, opcode, &right_node, NULL); - break; - } else if (Z_TYPE(left_node.u.constant) == IS_TRUE) { - opcode = (opcode == ZEND_IS_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT; - zend_emit_op_tmp(result, opcode, &right_node, NULL); - break; - } - } else if (right_node.op_type == IS_CONST) { - if (Z_TYPE(right_node.u.constant) == IS_FALSE) { - opcode = (opcode == ZEND_IS_NOT_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT; - zend_emit_op_tmp(result, opcode, &left_node, NULL); - break; - } else if (Z_TYPE(right_node.u.constant) == IS_TRUE) { - opcode = (opcode == ZEND_IS_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT; - zend_emit_op_tmp(result, opcode, &left_node, NULL); - break; - } - } - } else if (opcode == ZEND_IS_IDENTICAL || opcode == ZEND_IS_NOT_IDENTICAL) { + if (opcode == ZEND_IS_IDENTICAL || opcode == ZEND_IS_NOT_IDENTICAL) { /* convert $x === null to is_null($x) (i.e. ZEND_TYPE_CHECK opcode). Do the same thing for false/true. (covers IS_NULL, IS_FALSE, and IS_TRUE) */ if (left_node.op_type == IS_CONST) { if (Z_TYPE(left_node.u.constant) <= IS_TRUE && Z_TYPE(left_node.u.constant) >= IS_NULL) { @@ -10213,7 +10396,7 @@ static void zend_compile_greater(znode *result, zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_unary_op(znode *result, zend_ast *ast) /* {{{ */ +static void zend_compile_unary_op(znode *result, const zend_ast *ast) /* {{{ */ { zend_ast *expr_ast = ast->child[0]; uint32_t opcode = ast->attr; @@ -10309,7 +10492,7 @@ static void zend_compile_short_circuiting(znode *result, zend_ast *ast) /* {{{ * } /* }}} */ -static void zend_compile_post_incdec(znode *result, zend_ast *ast) /* {{{ */ +static void zend_compile_post_incdec(znode *result, const zend_ast *ast) /* {{{ */ { zend_ast *var_ast = ast->child[0]; ZEND_ASSERT(ast->kind == ZEND_AST_POST_INC || ast->kind == ZEND_AST_POST_DEC); @@ -10317,16 +10500,16 @@ static void zend_compile_post_incdec(znode *result, zend_ast *ast) /* {{{ */ zend_ensure_writable_variable(var_ast); if (var_ast->kind == ZEND_AST_PROP || var_ast->kind == ZEND_AST_NULLSAFE_PROP) { - zend_op *opline = zend_compile_prop(NULL, var_ast, BP_VAR_RW, 0); + zend_op *opline = zend_compile_prop(NULL, var_ast, BP_VAR_RW, false); opline->opcode = ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC_OBJ : ZEND_POST_DEC_OBJ; zend_make_tmp_result(result, opline); } else if (var_ast->kind == ZEND_AST_STATIC_PROP) { - zend_op *opline = zend_compile_static_prop(NULL, var_ast, BP_VAR_RW, 0, 0); + zend_op *opline = zend_compile_static_prop(NULL, var_ast, BP_VAR_RW, false, false); opline->opcode = ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC_STATIC_PROP : ZEND_POST_DEC_STATIC_PROP; zend_make_tmp_result(result, opline); } else { znode var_node; - zend_op *opline = zend_compile_var(&var_node, var_ast, BP_VAR_RW, 0); + zend_op *opline = zend_compile_var(&var_node, var_ast, BP_VAR_RW, false); if (opline && opline->opcode == ZEND_FETCH_DIM_RW) { opline->extended_value = ZEND_FETCH_DIM_INCDEC; } @@ -10336,7 +10519,7 @@ static void zend_compile_post_incdec(znode *result, zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_pre_incdec(znode *result, zend_ast *ast) /* {{{ */ +static void zend_compile_pre_incdec(znode *result, const zend_ast *ast) /* {{{ */ { zend_ast *var_ast = ast->child[0]; ZEND_ASSERT(ast->kind == ZEND_AST_PRE_INC || ast->kind == ZEND_AST_PRE_DEC); @@ -10344,18 +10527,18 @@ static void zend_compile_pre_incdec(znode *result, zend_ast *ast) /* {{{ */ zend_ensure_writable_variable(var_ast); if (var_ast->kind == ZEND_AST_PROP || var_ast->kind == ZEND_AST_NULLSAFE_PROP) { - zend_op *opline = zend_compile_prop(result, var_ast, BP_VAR_RW, 0); + zend_op *opline = zend_compile_prop(result, var_ast, BP_VAR_RW, false); opline->opcode = ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC_OBJ : ZEND_PRE_DEC_OBJ; opline->result_type = IS_TMP_VAR; result->op_type = IS_TMP_VAR; } else if (var_ast->kind == ZEND_AST_STATIC_PROP) { - zend_op *opline = zend_compile_static_prop(result, var_ast, BP_VAR_RW, 0, 0); + zend_op *opline = zend_compile_static_prop(result, var_ast, BP_VAR_RW, false, false); opline->opcode = ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC_STATIC_PROP : ZEND_PRE_DEC_STATIC_PROP; opline->result_type = IS_TMP_VAR; result->op_type = IS_TMP_VAR; } else { znode var_node; - zend_op *opline = zend_compile_var(&var_node, var_ast, BP_VAR_RW, 0); + zend_op *opline = zend_compile_var(&var_node, var_ast, BP_VAR_RW, false); if (opline && opline->opcode == ZEND_FETCH_DIM_RW) { opline->extended_value = ZEND_FETCH_DIM_INCDEC; } @@ -10365,7 +10548,7 @@ static void zend_compile_pre_incdec(znode *result, zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_cast(znode *result, zend_ast *ast) /* {{{ */ +static void zend_compile_cast(znode *result, const zend_ast *ast) /* {{{ */ { zend_ast *expr_ast = ast->child[0]; znode expr_node; @@ -10478,7 +10661,7 @@ static void zend_compile_coalesce(znode *result, zend_ast *ast) /* {{{ */ zend_op *opline; uint32_t opnum; - zend_compile_var(&expr_node, expr_ast, BP_VAR_IS, 0); + zend_compile_var(&expr_node, expr_ast, BP_VAR_IS, false); opnum = get_next_op_number(); zend_emit_op_tmp(result, ZEND_COALESCE, &expr_node, NULL); @@ -10509,7 +10692,7 @@ static void zend_compile_assign_coalesce(znode *result, zend_ast *ast) /* {{{ */ znode var_node_is, var_node_w, default_node, assign_node, *node; zend_op *opline; uint32_t coalesce_opnum; - bool need_frees = 0; + bool need_frees = false; /* Remember expressions compiled during the initial BP_VAR_IS lookup, * to avoid double-evaluation when we compile again with BP_VAR_W. */ @@ -10525,7 +10708,7 @@ static void zend_compile_assign_coalesce(znode *result, zend_ast *ast) /* {{{ */ zend_hash_init(CG(memoized_exprs), 0, NULL, znode_dtor, 0); CG(memoize_mode) = ZEND_MEMOIZE_COMPILE; - zend_compile_var(&var_node_is, var_ast, BP_VAR_IS, 0); + zend_compile_var(&var_node_is, var_ast, BP_VAR_IS, false); coalesce_opnum = get_next_op_number(); zend_emit_op_tmp(result, ZEND_COALESCE, &var_node_is, NULL); @@ -10538,7 +10721,7 @@ static void zend_compile_assign_coalesce(znode *result, zend_ast *ast) /* {{{ */ } CG(memoize_mode) = ZEND_MEMOIZE_FETCH; - zend_compile_var(&var_node_w, var_ast, BP_VAR_W, 0); + zend_compile_var(&var_node_w, var_ast, BP_VAR_W, false); /* Reproduce some of the zend_compile_assign() opcode fixup logic here. */ opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1]; @@ -10578,7 +10761,7 @@ static void zend_compile_assign_coalesce(znode *result, zend_ast *ast) /* {{{ */ ZEND_HASH_FOREACH_PTR(CG(memoized_exprs), node) { if (node->op_type == IS_TMP_VAR || node->op_type == IS_VAR) { - need_frees = 1; + need_frees = true; break; } } ZEND_HASH_FOREACH_END(); @@ -10604,7 +10787,7 @@ static void zend_compile_assign_coalesce(znode *result, zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_print(znode *result, zend_ast *ast) /* {{{ */ +static void zend_compile_print(znode *result, const zend_ast *ast) /* {{{ */ { zend_op *opline; zend_ast *expr_ast = ast->child[0]; @@ -10640,7 +10823,7 @@ static void zend_compile_yield(znode *result, zend_ast *ast) /* {{{ */ if (value_ast) { if (returns_by_ref && zend_is_variable(value_ast)) { zend_assert_not_short_circuited(value_ast); - zend_compile_var(&value_node, value_ast, BP_VAR_W, 1); + zend_compile_var(&value_node, value_ast, BP_VAR_W, true); } else { zend_compile_expr(&value_node, value_ast); } @@ -10655,7 +10838,7 @@ static void zend_compile_yield(znode *result, zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_yield_from(znode *result, zend_ast *ast) /* {{{ */ +static void zend_compile_yield_from(znode *result, const zend_ast *ast) /* {{{ */ { zend_ast *expr_ast = ast->child[0]; znode expr_node; @@ -10704,7 +10887,7 @@ static void zend_compile_instanceof(znode *result, zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_include_or_eval(znode *result, zend_ast *ast) /* {{{ */ +static void zend_compile_include_or_eval(znode *result, const zend_ast *ast) /* {{{ */ { zend_ast *expr_ast = ast->child[0]; znode expr_node; @@ -10720,7 +10903,7 @@ static void zend_compile_include_or_eval(znode *result, zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */ +static void zend_compile_isset_or_empty(znode *result, const zend_ast *ast) /* {{{ */ { zend_ast *var_ast = ast->child[0]; @@ -10770,10 +10953,10 @@ 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); + opline = zend_compile_simple_var_no_cv(result, var_ast, BP_VAR_IS, false); opline->opcode = ZEND_ISSET_ISEMPTY_VAR; } break; @@ -10783,11 +10966,11 @@ static void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */ break; case ZEND_AST_PROP: case ZEND_AST_NULLSAFE_PROP: - opline = zend_compile_prop(result, var_ast, BP_VAR_IS, 0); + opline = zend_compile_prop(result, var_ast, BP_VAR_IS, false); opline->opcode = ZEND_ISSET_ISEMPTY_PROP_OBJ; break; case ZEND_AST_STATIC_PROP: - opline = zend_compile_static_prop(result, var_ast, BP_VAR_IS, 0, 0); + opline = zend_compile_static_prop(result, var_ast, BP_VAR_IS, false, false); opline->opcode = ZEND_ISSET_ISEMPTY_STATIC_PROP; break; EMPTY_SWITCH_DEFAULT_CASE() @@ -10800,7 +10983,7 @@ static void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */ +static void zend_compile_silence(znode *result, const zend_ast *ast) /* {{{ */ { zend_ast *expr_ast = ast->child[0]; znode silence_node; @@ -10810,7 +10993,7 @@ static void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */ if (expr_ast->kind == ZEND_AST_VAR) { /* For @$var we need to force a FETCH instruction, otherwise the CV access will * happen outside the silenced section. */ - zend_compile_simple_var_no_cv(result, expr_ast, BP_VAR_R, 0 ); + zend_compile_simple_var_no_cv(result, expr_ast, BP_VAR_R, false ); } else { zend_compile_expr(result, expr_ast); } @@ -10819,13 +11002,15 @@ static void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_shell_exec(znode *result, zend_ast *ast) /* {{{ */ +static void zend_compile_shell_exec(znode *result, const zend_ast *ast) /* {{{ */ { zend_ast *expr_ast = ast->child[0]; 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); @@ -10842,7 +11027,7 @@ static void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */ zend_ast_list *list = zend_ast_get_list(ast); zend_op *opline; uint32_t i, opnum_init = -1; - bool packed = 1; + bool packed = true; if (zend_try_ct_eval_array(&result->u.constant, ast)) { result->op_type = IS_CONST; @@ -10886,7 +11071,7 @@ static void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */ if (by_ref) { zend_ensure_writable_variable(value_ast); - zend_compile_var(&value_node, value_ast, BP_VAR_W, 1); + zend_compile_var(&value_node, value_ast, BP_VAR_W, true); } else { zend_compile_expr(&value_node, value_ast); } @@ -10903,7 +11088,7 @@ static void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */ opline->extended_value |= by_ref; if (key_ast && key_node.op_type == IS_CONST && Z_TYPE(key_node.u.constant) == IS_STRING) { - packed = 0; + packed = false; } } @@ -10916,7 +11101,7 @@ static void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_const(znode *result, zend_ast *ast) /* {{{ */ +static void zend_compile_const(znode *result, const zend_ast *ast) /* {{{ */ { zend_ast *name_ast = ast->child[0]; @@ -10930,7 +11115,7 @@ static void zend_compile_const(znode *result, zend_ast *ast) /* {{{ */ zend_ast *last = CG(ast); while (last && last->kind == ZEND_AST_STMT_LIST) { - zend_ast_list *list = zend_ast_get_list(last); + const zend_ast_list *list = zend_ast_get_list(last); if (list->children == 0) { break; } @@ -10956,11 +11141,11 @@ static void zend_compile_const(znode *result, zend_ast *ast) /* {{{ */ if (is_fully_qualified || !FC(current_namespace)) { opline->op1.num = 0; opline->op2.constant = zend_add_const_name_literal( - resolved_name, 0); + resolved_name, false); } else { opline->op1.num = IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE; opline->op2.constant = zend_add_const_name_literal( - resolved_name, 1); + resolved_name, true); } opline->extended_value = zend_alloc_cache_slot(); } @@ -11007,7 +11192,7 @@ static void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_class_name(znode *result, zend_ast *ast) /* {{{ */ +static void zend_compile_class_name(znode *result, const zend_ast *ast) /* {{{ */ { zend_ast *class_ast = ast->child[0]; @@ -11202,7 +11387,7 @@ static void zend_compile_encaps_list(znode *result, zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_magic_const(znode *result, zend_ast *ast) /* {{{ */ +static void zend_compile_magic_const(znode *result, const zend_ast *ast) /* {{{ */ { zend_op *opline; @@ -11376,12 +11561,17 @@ static void zend_compile_const_expr_new(zend_ast **ast_ptr) { zend_ast *class_ast = (*ast_ptr)->child[0]; zend_compile_const_expr_class_reference(class_ast); + + const zend_ast *args_ast = (*ast_ptr)->child[1]; + if (args_ast->kind == ZEND_AST_CALLABLE_CONVERT) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot create Closure for new expression"); + } } static void zend_compile_const_expr_closure(zend_ast **ast_ptr) { zend_ast_decl *closure_ast = (zend_ast_decl *) *ast_ptr; - zend_ast *uses_ast = closure_ast->child[1]; + const zend_ast *uses_ast = closure_ast->child[1]; if (!(closure_ast->flags & ZEND_ACC_STATIC)) { zend_error_noreturn(E_COMPILE_ERROR, "Closures in constant expressions must be static"); @@ -11455,7 +11645,7 @@ static void zend_compile_const_expr_args(zend_ast **ast_ptr) zend_ast_list *list = zend_ast_get_list(*ast_ptr); bool uses_named_args = false; for (uint32_t i = 0; i < list->children; i++) { - zend_ast *arg = list->child[i]; + const zend_ast *arg = list->child[i]; if (arg->kind == ZEND_AST_UNPACK) { zend_error_noreturn(E_COMPILE_ERROR, "Argument unpacking in constant expressions is not supported"); @@ -11479,7 +11669,7 @@ typedef struct { static void zend_compile_const_expr(zend_ast **ast_ptr, void *context) /* {{{ */ { - const_expr_context *ctx = (const_expr_context *) context; + const const_expr_context *ctx = context; zend_ast *ast = *ast_ptr; if (ast == NULL || ast->kind == ZEND_AST_ZVAL) { return; @@ -11558,7 +11748,7 @@ void zend_compile_top_stmt(zend_ast *ast) /* {{{ */ } if (ast->kind == ZEND_AST_STMT_LIST) { - 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) { zend_compile_top_stmt(list->child[i]); @@ -11572,7 +11762,7 @@ void zend_compile_top_stmt(zend_ast *ast) /* {{{ */ CG(zend_lineno) = ((zend_ast_decl *) ast)->end_lineno; } else if (ast->kind == ZEND_AST_CLASS) { CG(zend_lineno) = ast->lineno; - zend_compile_class_decl(NULL, ast, 1); + zend_compile_class_decl(NULL, ast, true); CG(zend_lineno) = ((zend_ast_decl *) ast)->end_lineno; } else { zend_compile_stmt(ast); @@ -11592,7 +11782,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) { @@ -11665,7 +11855,7 @@ static void zend_compile_stmt(zend_ast *ast) /* {{{ */ zend_compile_use_trait(ast); break; case ZEND_AST_CLASS: - zend_compile_class_decl(NULL, ast, 0); + zend_compile_class_decl(NULL, ast, false); break; case ZEND_AST_GROUP_USE: zend_compile_group_use(ast); @@ -11730,7 +11920,7 @@ static void zend_compile_expr_inner(znode *result, zend_ast *ast) /* {{{ */ case ZEND_AST_NULLSAFE_METHOD_CALL: case ZEND_AST_STATIC_CALL: case ZEND_AST_PARENT_PROPERTY_HOOK_CALL: - zend_compile_var(result, ast, BP_VAR_R, 0); + zend_compile_var(result, ast, BP_VAR_R, false); return; case ZEND_AST_ASSIGN: zend_compile_assign(result, ast); @@ -11871,14 +12061,14 @@ static zend_op *zend_compile_var_inner(znode *result, zend_ast *ast, uint32_t ty switch (ast->kind) { case ZEND_AST_VAR: - return zend_compile_simple_var(result, ast, type, 0); + return zend_compile_simple_var(result, ast, type, false); case ZEND_AST_DIM: return zend_compile_dim(result, ast, type, by_ref); case ZEND_AST_PROP: case ZEND_AST_NULLSAFE_PROP: return zend_compile_prop(result, ast, type, by_ref); case ZEND_AST_STATIC_PROP: - return zend_compile_static_prop(result, ast, type, by_ref, 0); + return zend_compile_static_prop(result, ast, type, by_ref, false); case ZEND_AST_CALL: zend_compile_call(result, ast, type); return NULL; @@ -11922,7 +12112,7 @@ static zend_op *zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t switch (ast->kind) { case ZEND_AST_VAR: - return zend_compile_simple_var(result, ast, type, 1); + return zend_compile_simple_var(result, ast, type, true); case ZEND_AST_DIM: return zend_delayed_compile_dim(result, ast, type, by_ref); case ZEND_AST_PROP: @@ -11935,20 +12125,27 @@ static zend_op *zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t return opline; } case ZEND_AST_STATIC_PROP: - return zend_compile_static_prop(result, ast, type, by_ref, 1); + return zend_compile_static_prop(result, ast, type, by_ref, true); default: - return zend_compile_var(result, ast, type, 0); + return zend_compile_var(result, ast, type, false); } } /* }}} */ bool zend_try_ct_eval_cast(zval *result, uint32_t type, zval *op1) { + /* NAN warns when casting */ + if (UNEXPECTED(Z_TYPE_P(op1) == IS_DOUBLE && zend_isnan(Z_DVAL_P(op1)))) { + return false; + } switch (type) { case _IS_BOOL: - ZVAL_BOOL(result, zval_is_true(op1)); + ZVAL_BOOL(result, zend_is_true(op1)); return true; case IS_LONG: + if (Z_TYPE_P(op1) == IS_DOUBLE && !ZEND_DOUBLE_FITS_LONG(Z_DVAL_P((op1)))) { + return false; + } ZVAL_LONG(result, zval_get_long(op1)); return true; case IS_DOUBLE: @@ -12106,7 +12303,7 @@ static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */ case ZEND_AST_DIM: { /* constant expression should be always read context ... */ - zval *container, *dim; + const zval *container, *dim; if (ast->child[1] == NULL) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading"); diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 7ac0a2b8b2c44..d2a3b47bf92f4 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; @@ -196,8 +197,8 @@ typedef struct _zend_oparray_context { struct _zend_oparray_context *prev; zend_op_array *op_array; uint32_t opcodes_size; - int vars_size; - int literals_size; + uint32_t vars_size; + uint32_t literals_size; uint32_t fast_call_var; uint32_t try_catch_offset; int current_brk_cont; @@ -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 | | | */ @@ -333,12 +341,14 @@ typedef struct _zend_oparray_context { /* Class cannot be serialized or unserialized | | | */ #define ZEND_ACC_NOT_SERIALIZABLE (1 << 29) /* X | | | */ /* | | | */ +/* Class Flags 2 (ce_flags2) (unused: 0-31) | | | */ +/* ========================= | | | */ +/* | | | */ +/* #define ZEND_ACC2_EXAMPLE (1 << 0) X | | | */ +/* | | | */ /* 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 +402,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 | | | */ @@ -405,6 +412,11 @@ typedef struct _zend_oparray_context { /* | | | */ /* op_array uses strict mode types | | | */ #define ZEND_ACC_STRICT_TYPES (1U << 31) /* | X | | */ +/* | | | */ +/* Function Flags 2 (fn_flags2) (unused: 0-31) | | | */ +/* ============================ | | | */ +/* | | | */ +/* #define ZEND_ACC2_EXAMPLE (1 << 0) | X | | */ #define ZEND_ACC_PPP_MASK (ZEND_ACC_PUBLIC | ZEND_ACC_PROTECTED | ZEND_ACC_PRIVATE) #define ZEND_ACC_PPP_SET_MASK (ZEND_ACC_PUBLIC_SET | ZEND_ACC_PROTECTED_SET | ZEND_ACC_PRIVATE_SET) @@ -441,7 +453,7 @@ static zend_always_inline uint32_t zend_visibility_to_set_visibility(uint32_t vi // Must not clash with ZEND_SHORT_CIRCUITING_CHAIN_MASK #define ZEND_JMP_NULL_BP_VAR_IS 4 -char *zend_visibility_string(uint32_t fn_flags); +const char *zend_visibility_string(uint32_t fn_flags); #define ZEND_PROPERTY_HOOK_COUNT 2 #define ZEND_PROPERTY_HOOK_STRUCT_SIZE (sizeof(zend_function*) * ZEND_PROPERTY_HOOK_COUNT) @@ -449,7 +461,7 @@ char *zend_visibility_string(uint32_t fn_flags); /* Stored in zend_property_info.offset, not returned by zend_get_property_offset(). */ #define ZEND_VIRTUAL_PROPERTY_OFFSET ((uint32_t)-1) -zend_property_hook_kind zend_get_property_hook_kind_from_name(zend_string *name); +zend_property_hook_kind zend_get_property_hook_kind_from_name(const zend_string *name); typedef struct _zend_property_info { uint32_t offset; /* property offset for object properties or @@ -525,12 +537,13 @@ struct _zend_op_array { ZEND_MAP_PTR_DEF(void **, run_time_cache); zend_string *doc_comment; uint32_t T; /* number of temporary variables */ + uint32_t fn_flags2; const zend_property_info *prop_info; /* The corresponding prop_info if this is a hook. */ /* END of common elements */ - int cache_size; /* number of run_time_cache_slots * sizeof(void*) */ - int last_var; /* number of CV variables */ - uint32_t last; /* number of opcodes */ + uint32_t cache_size; /* number of run_time_cache_slots * sizeof(void*) */ + int last_var; /* number of CV variables */ + uint32_t last; /* number of opcodes */ zend_op *opcodes; ZEND_MAP_PTR_DEF(HashTable *, static_variables_ptr); @@ -539,8 +552,8 @@ struct _zend_op_array { uint32_t *refcount; - int last_live_range; - int last_try_catch; + uint32_t last_live_range; + uint32_t last_try_catch; zend_live_range *live_range; zend_try_catch_element *try_catch_array; @@ -548,7 +561,7 @@ struct _zend_op_array { uint32_t line_start; uint32_t line_end; - int last_literal; + uint32_t last_literal; uint32_t num_dynamic_func_defs; zval *literals; @@ -579,11 +592,12 @@ typedef struct _zend_internal_function { zend_function *prototype; uint32_t num_args; uint32_t required_num_args; - zend_internal_arg_info *arg_info; + zend_arg_info *arg_info; HashTable *attributes; ZEND_MAP_PTR_DEF(void **, run_time_cache); zend_string *doc_comment; uint32_t T; /* number of temporary variables */ + uint32_t fn_flags2; const zend_property_info *prop_info; /* The corresponding prop_info if this is a hook. */ /* END of common elements */ @@ -613,6 +627,7 @@ union _zend_function { ZEND_MAP_PTR_DEF(void **, run_time_cache); zend_string *doc_comment; uint32_t T; /* number of temporary variables */ + uint32_t fn_flags2; const zend_property_info *prop_info; /* The corresponding prop_info if this is a hook. */ } common; @@ -865,9 +880,9 @@ void shutdown_compiler(void); void zend_init_compiler_data_structures(void); void zend_oparray_context_begin(zend_oparray_context *prev_context, zend_op_array *op_array); -void zend_oparray_context_end(zend_oparray_context *prev_context); +void zend_oparray_context_end(const zend_oparray_context *prev_context); void zend_file_context_begin(zend_file_context *prev_context); -void zend_file_context_end(zend_file_context *prev_context); +void zend_file_context_end(const zend_file_context *prev_context); extern ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type); extern ZEND_API zend_op_array *(*zend_compile_string)(zend_string *source_string, const char *filename, zend_compile_position position); @@ -879,7 +894,7 @@ void shutdown_scanner(void); ZEND_API zend_string *zend_set_compiled_filename(zend_string *new_compiled_filename); ZEND_API void zend_restore_compiled_filename(zend_string *original_compiled_filename); ZEND_API zend_string *zend_get_compiled_filename(void); -ZEND_API int zend_get_compiled_lineno(void); +ZEND_API uint32_t zend_get_compiled_lineno(void); ZEND_API size_t zend_get_scanned_file_offset(void); ZEND_API zend_string *zend_get_compiled_variable_name(const zend_op_array *op_array, uint32_t var); @@ -918,8 +933,8 @@ uint32_t zend_modifier_list_to_flags(zend_modifier_target target, zend_ast *modi bool zend_handle_encoding_declaration(zend_ast *ast); ZEND_API zend_class_entry *zend_bind_class_in_slot( - zval *class_table_slot, zval *lcname, zend_string *lc_parent_name); -ZEND_API zend_result do_bind_function(zend_function *func, zval *lcname); + zval *class_table_slot, const zval *lcname, zend_string *lc_parent_name); +ZEND_API zend_result do_bind_function(zend_function *func, const zval *lcname); ZEND_API zend_result do_bind_class(zval *lcname, zend_string *lc_parent_name); void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline); @@ -948,7 +963,7 @@ ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle); ZEND_API void zend_cleanup_mutable_class_data(zend_class_entry *ce); ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce); ZEND_API void zend_type_release(zend_type type, bool persistent); -ZEND_API zend_string *zend_create_member_string(zend_string *class_name, zend_string *member_name); +ZEND_API zend_string *zend_create_member_string(const zend_string *class_name, const zend_string *member_name); ZEND_API ZEND_COLD void zend_user_exception_handler(void); @@ -961,7 +976,8 @@ ZEND_API ZEND_COLD void zend_user_exception_handler(void); } \ } while (0) -void zend_free_internal_arg_info(zend_internal_function *function); +ZEND_API void zend_free_internal_arg_info(zend_internal_function *function, + bool permanent); ZEND_API void destroy_zend_function(zend_function *function); ZEND_API void zend_function_dtor(zval *zv); ZEND_API void destroy_zend_class(zval *zv); @@ -981,7 +997,7 @@ static zend_always_inline const char *zend_get_unmangled_property_name(const zen #define ZEND_FUNCTION_DTOR zend_function_dtor #define ZEND_CLASS_DTOR destroy_zend_class -typedef bool (*zend_needs_live_range_cb)(zend_op_array *op_array, zend_op *opline); +typedef bool (*zend_needs_live_range_cb)(const zend_op_array *op_array, const zend_op *opline); ZEND_API void zend_recalc_live_ranges( zend_op_array *op_array, zend_needs_live_range_cb needs_live_range); @@ -990,7 +1006,7 @@ ZEND_API bool zend_is_compiling(void); ZEND_API char *zend_make_compiled_string_description(const char *name); ZEND_API void zend_initialize_class_data(zend_class_entry *ce, bool nullify_handlers); uint32_t zend_get_class_fetch_type(const zend_string *name); -ZEND_API uint8_t zend_get_call_op(const zend_op *init_op, zend_function *fbc, bool result_used); +ZEND_API uint8_t zend_get_call_op(const zend_op *init_op, const zend_function *fbc, bool result_used); ZEND_API bool zend_is_smart_branch(const zend_op *opline); typedef bool (*zend_auto_global_callback)(zend_string *name); @@ -1126,6 +1142,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 */ @@ -1205,6 +1222,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 cdab1bfced40b..a18c393be7f98 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -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; @@ -541,7 +544,7 @@ ZEND_API zend_constant *zend_register_constant(zend_constant *c) || (!persistent && zend_get_special_const(ZSTR_VAL(name), ZSTR_LEN(name))) || (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); 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 3edb91265f4df..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) { @@ -23,6 +23,7 @@ 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); @@ -31,9 +32,7 @@ static void register_zend_constants_symbols(int module_number) zend_attribute *attribute_Deprecated_const_E_STRICT_0 = zend_add_global_constant_attribute(const_E_STRICT, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); 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_cpuinfo.c b/Zend/zend_cpuinfo.c index 6264031ceba42..9f8f1354be061 100644 --- a/Zend/zend_cpuinfo.c +++ b/Zend/zend_cpuinfo.c @@ -93,21 +93,21 @@ static unsigned get_xcr0_eax(void) { static bool is_avx_supported(void) { if (!(cpuinfo.ecx & ZEND_CPU_FEATURE_AVX)) { /* No support for AVX */ - return 0; + return false; } if (!(cpuinfo.ecx & ZEND_CPU_FEATURE_OSXSAVE)) { /* The operating system does not support XSAVE. */ - return 0; + return false; } if ((get_xcr0_eax() & 0x6) != 0x6) { /* XCR0 SSE and AVX bits must be set. */ - return 0; + return false; } - return 1; + return true; } #else static bool is_avx_supported(void) { - return 0; + return false; } #endif diff --git a/Zend/zend_enum.c b/Zend/zend_enum.c index 6baa34cc50125..00fbab22a056e 100644 --- a/Zend/zend_enum.c +++ b/Zend/zend_enum.c @@ -36,9 +36,14 @@ ZEND_API zend_class_entry *zend_ce_unit_enum; ZEND_API zend_class_entry *zend_ce_backed_enum; ZEND_API zend_object_handlers zend_enum_object_handlers; +static zend_arg_info zarginfo_class_UnitEnum_cases[sizeof(arginfo_class_UnitEnum_cases)/sizeof(zend_internal_arg_info)]; +static zend_arg_info zarginfo_class_BackedEnum_from[sizeof(arginfo_class_BackedEnum_from)/sizeof(zend_internal_arg_info)]; +static zend_arg_info zarginfo_class_BackedEnum_tryFrom[sizeof(arginfo_class_BackedEnum_tryFrom)/sizeof(zend_internal_arg_info)]; + zend_object *zend_enum_new(zval *result, zend_class_entry *ce, zend_string *case_name, zval *backing_value_zv) { zend_object *zobj = zend_objects_new(ce); + GC_ADD_FLAGS(zobj, GC_NOT_COLLECTABLE); ZVAL_OBJ(result, zobj); zval *zname = OBJ_PROP_NUM(zobj, 0); @@ -445,7 +450,7 @@ void zend_enum_register_funcs(zend_class_entry *ce) cases_function->function_name = ZSTR_KNOWN(ZEND_STR_CASES); cases_function->fn_flags = fn_flags; cases_function->doc_comment = NULL; - cases_function->arg_info = (zend_internal_arg_info *) (arginfo_class_UnitEnum_cases + 1); + cases_function->arg_info = zarginfo_class_UnitEnum_cases + 1; zend_enum_register_func(ce, ZEND_STR_CASES, cases_function); if (ce->enum_backing_type != IS_UNDEF) { @@ -456,7 +461,7 @@ void zend_enum_register_funcs(zend_class_entry *ce) from_function->doc_comment = NULL; from_function->num_args = 1; from_function->required_num_args = 1; - from_function->arg_info = (zend_internal_arg_info *) (arginfo_class_BackedEnum_from + 1); + from_function->arg_info = zarginfo_class_BackedEnum_from + 1; zend_enum_register_func(ce, ZEND_STR_FROM, from_function); zend_internal_function *try_from_function = zend_arena_calloc(&CG(arena), sizeof(zend_internal_function), 1); @@ -466,7 +471,7 @@ void zend_enum_register_funcs(zend_class_entry *ce) try_from_function->doc_comment = NULL; try_from_function->num_args = 1; try_from_function->required_num_args = 1; - try_from_function->arg_info = (zend_internal_arg_info *) (arginfo_class_BackedEnum_tryFrom + 1); + try_from_function->arg_info = zarginfo_class_BackedEnum_tryFrom + 1; zend_enum_register_func(ce, ZEND_STR_TRYFROM_LOWERCASE, try_from_function); } } @@ -632,3 +637,16 @@ ZEND_API zend_object *zend_enum_get_case_cstr(zend_class_entry *ce, const char * zend_class_constant *c = zend_hash_str_find_ptr(CE_CONSTANTS_TABLE(ce), name, strlen(name)); return zend_enum_case_from_class_constant(c); } + +void zend_enum_startup(void) +{ + for (size_t i = 0; i < sizeof(zarginfo_class_UnitEnum_cases)/sizeof(zend_arg_info); i++) { + zend_convert_internal_arg_info(&zarginfo_class_UnitEnum_cases[i], &arginfo_class_UnitEnum_cases[i], i == 0, true); + } + for (size_t i = 0; i < sizeof(zarginfo_class_BackedEnum_from)/sizeof(zend_arg_info); i++) { + zend_convert_internal_arg_info(&zarginfo_class_BackedEnum_from[i], &arginfo_class_BackedEnum_from[i], i == 0, true); + } + for (size_t i = 0; i < sizeof(zarginfo_class_BackedEnum_tryFrom)/sizeof(zend_arg_info); i++) { + zend_convert_internal_arg_info(&zarginfo_class_BackedEnum_tryFrom[i], &arginfo_class_BackedEnum_tryFrom[i], i == 0, true); + } +} diff --git a/Zend/zend_enum.h b/Zend/zend_enum.h index 7b3b0184b4eb5..d6c820189475a 100644 --- a/Zend/zend_enum.h +++ b/Zend/zend_enum.h @@ -30,6 +30,7 @@ extern ZEND_API zend_class_entry *zend_ce_unit_enum; extern ZEND_API zend_class_entry *zend_ce_backed_enum; extern ZEND_API zend_object_handlers zend_enum_object_handlers; +void zend_enum_startup(void); void zend_register_enum_ce(void); void zend_enum_add_interfaces(zend_class_entry *ce); zend_result zend_enum_build_backed_enum_table(zend_class_entry *ce); diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index 99c4a48a9482f..191d8f7fe6aec 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -36,7 +36,6 @@ #define ZEND_EXCEPTION_LINE_OFF 4 #define ZEND_EXCEPTION_TRACE_OFF 5 #define ZEND_EXCEPTION_PREVIOUS_OFF 6 -#define ZEND_EXCEPTION_SEVERITY_OFF 7 ZEND_API zend_class_entry *zend_ce_throwable; ZEND_API zend_class_entry *zend_ce_exception; @@ -67,7 +66,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 +88,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 +191,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); @@ -401,7 +400,7 @@ ZEND_METHOD(ErrorException, __construct) { zend_string *message = NULL, *filename = NULL; zend_long code = 0, severity = E_ERROR, lineno; - bool lineno_is_null = 1; + bool lineno_is_null = true; zval tmp, *object, *previous = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|SllS!l!O!", &message, &code, &severity, &filename, &lineno, &lineno_is_null, &previous, zend_ce_throwable) == FAILURE) { @@ -415,7 +414,7 @@ ZEND_METHOD(ErrorException, __construct) } ZVAL_LONG(&tmp, severity); - zend_update_property_num_checked(NULL, Z_OBJ_P(object), ZEND_EXCEPTION_SEVERITY_OFF, ZSTR_KNOWN(ZEND_STR_SEVERITY), &tmp); + zend_update_property_ex(zend_ce_exception, Z_OBJ_P(object), ZSTR_KNOWN(ZEND_STR_SEVERITY), &tmp); if (UNEXPECTED(EG(exception))) { RETURN_THROWS(); } @@ -695,16 +694,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 +728,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 +775,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 +789,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); } diff --git a/Zend/zend_exceptions.h b/Zend/zend_exceptions.h index 5df49dcd6a3a6..24d9f4efd80a3 100644 --- a/Zend/zend_exceptions.h +++ b/Zend/zend_exceptions.h @@ -48,7 +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); +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 734494d252da0..518cbb98fc0f8 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -136,8 +136,7 @@ static ZEND_FUNCTION(pass) { } -ZEND_BEGIN_ARG_INFO_EX(zend_pass_function_arg_info, 0, 0, 0) -ZEND_END_ARG_INFO() +static zend_arg_info zend_pass_function_arg_info[1] = {0}; ZEND_API const zend_internal_function zend_pass_function = { ZEND_INTERNAL_FUNCTION, /* type */ @@ -148,11 +147,12 @@ ZEND_API const zend_internal_function zend_pass_function = { NULL, /* prototype */ 0, /* num_args */ 0, /* required_num_args */ - (zend_internal_arg_info *) zend_pass_function_arg_info + 1, /* arg_info */ + zend_pass_function_arg_info + 1, /* arg_info */ NULL, /* attributes */ NULL, /* run_time_cache */ NULL, /* doc_comment */ 0, /* T */ + 0, /* fn_flags2 */ NULL, /* prop_info */ ZEND_FN(pass), /* handler */ NULL, /* module */ @@ -746,36 +746,36 @@ static bool zend_verify_weak_scalar_type_hint(uint32_t type_mask, zval *arg) if (type == IS_LONG) { zend_string_release(Z_STR_P(arg)); ZVAL_LONG(arg, lval); - return 1; + return true; } if (type == IS_DOUBLE) { zend_string_release(Z_STR_P(arg)); ZVAL_DOUBLE(arg, dval); - return 1; + return true; } } else if (zend_parse_arg_long_weak(arg, &lval, 0)) { zval_ptr_dtor(arg); ZVAL_LONG(arg, lval); - return 1; + return true; } else if (UNEXPECTED(EG(exception))) { - return 0; + return false; } } if ((type_mask & MAY_BE_DOUBLE) && zend_parse_arg_double_weak(arg, &dval, 0)) { zval_ptr_dtor(arg); ZVAL_DOUBLE(arg, dval); - return 1; + return true; } if ((type_mask & MAY_BE_STRING) && zend_parse_arg_str_weak(arg, &str, 0)) { /* on success "arg" is converted to IS_STRING */ - return 1; + return true; } if ((type_mask & MAY_BE_BOOL) == MAY_BE_BOOL && zend_parse_arg_bool_weak(arg, &bval, 0)) { zval_ptr_dtor(arg); ZVAL_BOOL(arg, bval); - return 1; + return true; } - return 0; + return false; } #if ZEND_DEBUG @@ -800,18 +800,18 @@ static bool zend_verify_weak_scalar_type_hint_no_sideeffect(uint32_t type_mask, /* Pass (uint32_t)-1 as arg_num to indicate to ZPP not to emit any deprecation notice, * this is needed because the version with side effects also uses 0 (e.g. for typed properties) */ if ((type_mask & MAY_BE_LONG) && zend_parse_arg_long_weak(arg, &lval, (uint32_t)-1)) { - return 1; + return true; } if ((type_mask & MAY_BE_DOUBLE) && zend_parse_arg_double_weak(arg, &dval, (uint32_t)-1)) { - return 1; + return true; } if ((type_mask & MAY_BE_STRING) && can_convert_to_string(arg)) { - return 1; + return true; } if ((type_mask & MAY_BE_BOOL) == MAY_BE_BOOL && zend_parse_arg_bool_weak(arg, &bval, (uint32_t)-1)) { - return 1; + return true; } - return 0; + return false; } #endif @@ -1051,7 +1051,7 @@ static zend_always_inline bool i_zend_check_property_type(const zend_property_in uint32_t type_mask = ZEND_TYPE_FULL_MASK(info->type); ZEND_ASSERT(!(type_mask & (MAY_BE_CALLABLE|MAY_BE_STATIC|MAY_BE_NEVER|MAY_BE_VOID))); - return zend_verify_scalar_type_hint(type_mask, property, strict, 0); + return zend_verify_scalar_type_hint(type_mask, property, strict, false); } static zend_always_inline bool i_zend_verify_property_type(const zend_property_info *info, zval *property, bool strict) @@ -1246,7 +1246,7 @@ static zend_always_inline bool zend_verify_recv_arg_type(const zend_function *zf cur_arg_info = &zf->common.arg_info[arg_num-1]; if (ZEND_TYPE_IS_SET(cur_arg_info->type) - && UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, zf->common.scope, 0, 0))) { + && UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, zf->common.scope, false, false))) { zend_verify_arg_error(zf, cur_arg_info, arg_num, arg); return 0; } @@ -1258,7 +1258,7 @@ static zend_always_inline bool zend_verify_variadic_arg_type( const zend_function *zf, const zend_arg_info *arg_info, uint32_t arg_num, zval *arg) { ZEND_ASSERT(ZEND_TYPE_IS_SET(arg_info->type)); - if (UNEXPECTED(!zend_check_type(&arg_info->type, arg, zf->common.scope, 0, 0))) { + if (UNEXPECTED(!zend_check_type(&arg_info->type, arg, zf->common.scope, false, false))) { zend_verify_arg_error(zf, arg_info, arg_num, arg); return 0; } @@ -1283,7 +1283,7 @@ static zend_never_inline ZEND_ATTRIBUTE_UNUSED bool zend_verify_internal_arg_typ } if (ZEND_TYPE_IS_SET(cur_arg_info->type) - && UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, fbc->common.scope, 0, /* is_internal */ 1))) { + && UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, fbc->common.scope, false, /* is_internal */ true))) { return 0; } arg++; @@ -1479,7 +1479,7 @@ static ZEND_COLD void zend_verify_void_return_error(const zend_function *zf, con ZEND_API bool zend_verify_internal_return_type(const zend_function *zf, zval *ret) { - const zend_internal_arg_info *ret_info = zf->internal_function.arg_info - 1; + const zend_arg_info *ret_info = zf->internal_function.arg_info - 1; if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_VOID) { if (UNEXPECTED(Z_TYPE_P(ret) != IS_NULL)) { @@ -1489,7 +1489,7 @@ ZEND_API bool zend_verify_internal_return_type(const zend_function *zf, zval *re return 1; } - if (UNEXPECTED(!zend_check_type(&ret_info->type, ret, NULL, 1, /* is_internal */ 1))) { + if (UNEXPECTED(!zend_check_type(&ret_info->type, ret, NULL, true, /* is_internal */ true))) { zend_verify_internal_return_error(zf, ret); return 0; } @@ -1732,10 +1732,13 @@ static zend_never_inline zend_long zend_check_string_offset(zval *dim, int type zend_illegal_string_offset(dim, type); return 0; } + case IS_DOUBLE: + /* Suppress potential double warning */ + zend_error(E_WARNING, "String offset cast occurred"); + return zend_dval_to_lval_silent(Z_DVAL_P(dim)); case IS_UNDEF: ZVAL_UNDEFINED_OP2(); ZEND_FALLTHROUGH; - case IS_DOUBLE: case IS_NULL: case IS_FALSE: case IS_TRUE: @@ -2006,6 +2009,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,24 +2653,36 @@ 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: - value->lval = zend_dval_to_lval(Z_DVAL_P(dim)); - if (!zend_is_long_compatible(Z_DVAL_P(dim), value->lval)) { - /* The array may be destroyed while throwing the notice. - * Temporarily increase the refcount to detect this situation. */ - if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { - GC_ADDREF(ht); - } - zend_incompatible_double_to_long_error(Z_DVAL_P(dim)); - if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { - zend_array_destroy(ht); - return IS_NULL; - } - if (EG(exception)) { - return IS_NULL; - } + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value->lval = zend_dval_to_lval_safe(Z_DVAL_P(dim)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + return IS_NULL; + } + if (EG(exception)) { + return IS_NULL; } return IS_LONG; case IS_RESOURCE: @@ -2699,26 +2735,38 @@ 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: - value->lval = zend_dval_to_lval(Z_DVAL_P(dim)); - if (!zend_is_long_compatible(Z_DVAL_P(dim), value->lval)) { - /* The array may be destroyed while throwing the notice. - * Temporarily increase the refcount to detect this situation. */ - if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { - GC_ADDREF(ht); - } - zend_incompatible_double_to_long_error(Z_DVAL_P(dim)); - 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; + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value->lval = zend_dval_to_lval_safe(Z_DVAL_P(dim)); + 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; } return IS_LONG; case IS_RESOURCE: @@ -3005,7 +3053,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; @@ -3078,6 +3126,11 @@ static zend_always_inline void zend_fetch_dimension_address_read(zval *result, z return; } } + /* To prevent double warning */ + if (Z_TYPE_P(dim) == IS_DOUBLE) { + offset = zend_dval_to_lval_silent(Z_DVAL_P(dim)); + goto out; + } break; case IS_REFERENCE: dim = Z_REFVAL_P(dim); @@ -3143,6 +3196,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)); @@ -3185,11 +3241,36 @@ static zend_never_inline zval* ZEND_FASTCALL zend_find_array_dim_slow(HashTable zend_ulong hval; if (Z_TYPE_P(offset) == IS_DOUBLE) { + /* The array may be destroyed while throwing a warning in case the float is not representable as an int. + * Temporarily increase the refcount to detect this situation. */ + GC_TRY_ADDREF(ht); hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + return NULL; + } + if (EG(exception)) { + return NULL; + } 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 +3284,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; @@ -3309,7 +3390,17 @@ static zend_never_inline bool ZEND_FASTCALL zend_array_key_exists_fast(HashTable key = Z_REFVAL_P(key); goto try_again; } else if (Z_TYPE_P(key) == IS_DOUBLE) { + /* The array may be destroyed while throwing a warning in case the float is not representable as an int. + * Temporarily increase the refcount to detect this situation. */ + GC_TRY_ADDREF(ht); hval = zend_dval_to_lval_safe(Z_DVAL_P(key)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + return false; + } + if (EG(exception)) { + return false; + } goto num_key; } else if (Z_TYPE_P(key) == IS_FALSE) { hval = 0; @@ -3324,6 +3415,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; @@ -4251,7 +4345,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_fcall_interrupt(zend_execute_data *ca */ static zend_never_inline void zend_copy_extra_args(EXECUTE_DATA_D) { - zend_op_array *op_array = &EX(func)->op_array; + const zend_op_array *op_array = &EX(func)->op_array; uint32_t first_extra_arg = op_array->num_args; uint32_t num_args = EX_NUM_ARGS(); zval *src; @@ -4831,7 +4925,7 @@ static void cleanup_live_vars(zend_execute_data *execute_data, uint32_t op_num, zval_ptr_dtor_nogc(var); } else if (kind == ZEND_LIVE_ROPE) { zend_string **rope = (zend_string **)var; - zend_op *last = EX(func)->op_array.opcodes + op_num; + const zend_op *last = EX(func)->op_array.opcodes + op_num; while ((last->opcode != ZEND_ROPE_ADD && last->opcode != ZEND_ROPE_INIT) || last->result.var != var_num) { ZEND_ASSERT(last >= EX(func)->op_array.opcodes); @@ -4840,7 +4934,7 @@ static void cleanup_live_vars(zend_execute_data *execute_data, uint32_t op_num, if (last->opcode == ZEND_ROPE_INIT) { zend_string_release_ex(*rope, 0); } else { - int j = last->extended_value; + uint32_t j = last->extended_value; do { zend_string_release_ex(rope[j], 0); } while (j--); @@ -4887,7 +4981,7 @@ ZEND_API HashTable *zend_unfinished_execution_gc_ex(zend_execute_data *execute_d return NULL; } - zend_op_array *op_array = &EX(func)->op_array; + const zend_op_array *op_array = &EX(func)->op_array; if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) { uint32_t i, num_cvs = EX(func)->op_array.last_var; @@ -4898,7 +4992,7 @@ ZEND_API HashTable *zend_unfinished_execution_gc_ex(zend_execute_data *execute_d if (EX_CALL_INFO() & ZEND_CALL_FREE_EXTRA_ARGS) { zval *zv = EX_VAR_NUM(op_array->last_var + op_array->T); - zval *end = zv + (EX_NUM_ARGS() - op_array->num_args); + const zval *end = zv + (EX_NUM_ARGS() - op_array->num_args); while (zv != end) { zend_get_gc_buffer_add_zval(gc_buffer, zv++); } @@ -5211,7 +5305,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, @@ -5245,7 +5339,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, @@ -5367,39 +5461,40 @@ 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)) { + const zend_function *fbc, const zend_string *arg_name, void **cache_slot) { + /* 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); } // TODO: Use a hash table? uint32_t num_args = fbc->common.num_args; - if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) - || EXPECTED(fbc->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) { - 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; - return i; - } - } - } else { - ZEND_ASSERT(num_args == 0 || fbc->internal_function.arg_info); - for (uint32_t i = 0; i < num_args; i++) { - 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; + for (uint32_t i = 0; i < num_args; i++) { + const zend_arg_info *arg_info = &fbc->common.arg_info[i]; + if (zend_string_equals(arg_name, arg_info->name)) { + if ((fbc->type == ZEND_USER_FUNCTION + && (!fbc->op_array.refcount || !(fbc->op_array.fn_flags & ZEND_ACC_CLOSURE))) + || (fbc->type == ZEND_INTERNAL_FUNCTION + && !(fbc->common.fn_flags & ZEND_ACC_NEVER_CACHE))) { + *cache_slot = unique_id; *(uintptr_t *)(cache_slot + 1) = i; - return i; } + return i; } } if (fbc->common.fn_flags & ZEND_ACC_VARIADIC) { - *cache_slot = fbc; - *(uintptr_t *)(cache_slot + 1) = fbc->common.num_args; + if ((fbc->type == ZEND_USER_FUNCTION + && (!fbc->op_array.refcount || !(fbc->op_array.fn_flags & ZEND_ACC_CLOSURE))) + || (fbc->type == ZEND_INTERNAL_FUNCTION + && !(fbc->common.fn_flags & ZEND_ACC_NEVER_CACHE))) { + *cache_slot = unique_id; + *(uintptr_t *)(cache_slot + 1) = fbc->common.num_args; + } return fbc->common.num_args; } @@ -5410,7 +5505,7 @@ zval * ZEND_FASTCALL zend_handle_named_arg( zend_execute_data **call_ptr, zend_string *arg_name, uint32_t *arg_num_ptr, void **cache_slot) { zend_execute_data *call = *call_ptr; - zend_function *fbc = call->func; + const zend_function *fbc = call->func; uint32_t arg_offset = zend_get_arg_offset_by_name(fbc, arg_name, cache_slot); if (UNEXPECTED(arg_offset == (uint32_t) -1)) { zend_throw_error(NULL, "Unknown named parameter $%s", ZSTR_VAL(arg_name)); @@ -5496,7 +5591,7 @@ ZEND_API zend_result ZEND_FASTCALL zend_handle_undef_args(zend_execute_data *cal continue; } - zend_op *opline = &op_array->opcodes[i]; + const zend_op *opline = &op_array->opcodes[i]; if (EXPECTED(opline->opcode == ZEND_RECV_INIT)) { zval *default_value = RT_CONSTANT(opline, opline->op2); if (Z_OPT_TYPE_P(default_value) == IS_CONSTANT_AST) { @@ -5554,7 +5649,7 @@ ZEND_API zend_result ZEND_FASTCALL zend_handle_undef_args(zend_execute_data *cal continue; } - zend_internal_arg_info *arg_info = &fbc->internal_function.arg_info[i]; + zend_arg_info *arg_info = &fbc->internal_function.arg_info[i]; if (i < fbc->common.required_num_args) { zend_execute_data *old = start_fake_frame(call, NULL); zend_argument_error(zend_ce_argument_count_error, i + 1, "not passed"); diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index cf15c9e3b2db5..8858f9fce96ae 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -48,11 +48,11 @@ ZEND_API void zend_init_code_execute_data(zend_execute_data *execute_data, zend_ ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value); ZEND_API void execute_ex(zend_execute_data *execute_data); ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value); -ZEND_API bool zend_is_valid_class_name(zend_string *name); +ZEND_API bool zend_is_valid_class_name(const zend_string *name); ZEND_API zend_class_entry *zend_lookup_class(zend_string *name); ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *lcname, uint32_t flags); -ZEND_API zend_class_entry *zend_get_called_scope(zend_execute_data *ex); -ZEND_API zend_object *zend_get_this_object(zend_execute_data *ex); +ZEND_API zend_class_entry *zend_get_called_scope(const zend_execute_data *ex); +ZEND_API zend_object *zend_get_this_object(const zend_execute_data *ex); ZEND_API zend_result zend_eval_string(const char *str, zval *retval_ptr, const char *string_name); ZEND_API zend_result zend_eval_stringl(const char *str, size_t str_len, zval *retval_ptr, const char *string_name); ZEND_API zend_result zend_eval_string_ex(const char *str, zval *retval_ptr, const char *string_name, bool handle_exceptions); @@ -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); @@ -233,6 +234,9 @@ static zend_always_inline void zend_cast_zval_to_object(zval *result, zval *expr } Z_OBJ_P(result)->properties = ht; } else if (Z_TYPE_P(expr) != IS_NULL) { + if (UNEXPECTED(Z_TYPE_P(expr) == IS_DOUBLE && zend_isnan(Z_DVAL_P(expr)))) { + zend_nan_coerced_to_type_warning(IS_OBJECT); + } Z_OBJ_P(result)->properties = ht = zend_new_array(1); expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr); if (op1_type == IS_CONST) { @@ -247,6 +251,9 @@ static zend_always_inline void zend_cast_zval_to_array(zval *result, zval *expr, extern zend_class_entry *zend_ce_closure; if (op1_type == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) { if (Z_TYPE_P(expr) != IS_NULL) { + if (UNEXPECTED(Z_TYPE_P(expr) == IS_DOUBLE && zend_isnan(Z_DVAL_P(expr)))) { + zend_nan_coerced_to_type_warning(IS_ARRAY); + } ZVAL_ARR(result, zend_new_array(1)); expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr); if (op1_type == IS_CONST) { @@ -352,7 +359,7 @@ static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame_ex(ui } } -static zend_always_inline uint32_t zend_vm_calc_used_stack(uint32_t num_args, zend_function *func) +static zend_always_inline uint32_t zend_vm_calc_used_stack(uint32_t num_args, const zend_function *func) { uint32_t used_stack = ZEND_CALL_FRAME_SLOT + num_args + func->common.T; @@ -446,11 +453,11 @@ ZEND_API const char *get_active_class_name(const char **space); ZEND_API const char *get_active_function_name(void); ZEND_API const char *get_active_function_arg_name(uint32_t arg_num); ZEND_API const char *get_function_arg_name(const zend_function *func, uint32_t arg_num); -ZEND_API zend_function *zend_active_function_ex(zend_execute_data *execute_data); +ZEND_API const zend_function *zend_active_function_ex(const zend_execute_data *execute_data); -static zend_always_inline zend_function *zend_active_function(void) +static zend_always_inline const zend_function *zend_active_function(void) { - zend_function *func = EG(current_execute_data)->func; + const zend_function *func = EG(current_execute_data)->func; if (ZEND_USER_CODE(func->type)) { return zend_active_function_ex(EG(current_execute_data)); } else { diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 6d2a6195cd52c..e134d3d496b6d 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -88,7 +88,7 @@ static void zend_handle_sigsegv(void) /* {{{ */ /* }}} */ #endif -static void zend_extension_activator(zend_extension *extension) /* {{{ */ +static void zend_extension_activator(const zend_extension *extension) /* {{{ */ { if (extension->activate) { extension->activate(); @@ -96,7 +96,7 @@ static void zend_extension_activator(zend_extension *extension) /* {{{ */ } /* }}} */ -static void zend_extension_deactivator(zend_extension *extension) /* {{{ */ +static void zend_extension_deactivator(const zend_extension *extension) /* {{{ */ { if (extension->deactivate) { extension->deactivate(); @@ -113,14 +113,14 @@ static int clean_non_persistent_constant_full(zval *zv) /* {{{ */ static int clean_non_persistent_function_full(zval *zv) /* {{{ */ { - zend_function *function = Z_PTR_P(zv); + const zend_function *function = Z_PTR_P(zv); return (function->type == ZEND_INTERNAL_FUNCTION) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE; } /* }}} */ static int clean_non_persistent_class_full(zval *zv) /* {{{ */ { - zend_class_entry *ce = Z_PTR_P(zv); + const zend_class_entry *ce = Z_PTR_P(zv); return (ce->type == ZEND_INTERNAL_CLASS) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE; } /* }}} */ @@ -203,6 +203,8 @@ void init_executor(void) /* {{{ */ zend_fiber_init(); zend_weakrefs_init(); + zend_hash_init(&EG(callable_convert_cache), 8, NULL, ZVAL_PTR_DTOR, 0); + EG(active) = 1; } /* }}} */ @@ -229,7 +231,7 @@ static void zend_unclean_zval_ptr_dtor(zval *zv) /* {{{ */ } /* }}} */ -static ZEND_COLD void zend_throw_or_error(int fetch_type, zend_class_entry *exception_ce, const char *format, ...) /* {{{ */ +static ZEND_COLD void zend_throw_or_error(uint32_t fetch_type, zend_class_entry *exception_ce, const char *format, ...) /* {{{ */ { va_list va; char *message = NULL; @@ -270,24 +272,22 @@ void shutdown_destructors(void) /* {{{ */ /* Free values held by the executor. */ ZEND_API void zend_shutdown_executor_values(bool fast_shutdown) { - zend_string *key; - zval *zv; - EG(flags) |= EG_FLAGS_IN_RESOURCE_SHUTDOWN; - zend_try { - zend_close_rsrc_list(&EG(regular_list)); - } zend_end_try(); + zend_close_rsrc_list(&EG(regular_list)); /* No PHP callback functions should be called after this point. */ EG(active) = 0; if (!fast_shutdown) { + zval *zv; + zend_hash_graceful_reverse_destroy(&EG(symbol_table)); /* Constants may contain objects, destroy them before the object store. */ if (EG(full_tables_cleanup)) { zend_hash_reverse_apply(EG(zend_constants), clean_non_persistent_constant_full); } else { + zend_string *key; ZEND_HASH_MAP_REVERSE_FOREACH_STR_KEY_VAL(EG(zend_constants), key, zv) { zend_constant *c = Z_PTR_P(zv); if (_idx == EG(persistent_constants_count)) { @@ -420,6 +420,8 @@ ZEND_API void zend_shutdown_executor_values(bool fast_shutdown) zend_stack_clean(&EG(user_error_handlers), (void (*)(void *))ZVAL_PTR_DTOR, 1); zend_stack_clean(&EG(user_exception_handlers), (void (*)(void *))ZVAL_PTR_DTOR, 1); + zend_hash_clean(&EG(callable_convert_cache)); + #if ZEND_DEBUG if (!CG(unclean_shutdown)) { gc_collect_cycles(); @@ -434,8 +436,6 @@ ZEND_API void zend_shutdown_executor_values(bool fast_shutdown) void shutdown_executor(void) /* {{{ */ { - zend_string *key; - zval *zv; #if ZEND_DEBUG bool fast_shutdown = 0; #elif defined(__SANITIZE_ADDRESS__) @@ -477,6 +477,8 @@ void shutdown_executor(void) /* {{{ */ zend_hash_reverse_apply(EG(function_table), clean_non_persistent_function_full); zend_hash_reverse_apply(EG(class_table), clean_non_persistent_class_full); } else { + zend_string *key; + zval *zv; ZEND_HASH_MAP_REVERSE_FOREACH_STR_KEY_VAL(EG(function_table), key, zv) { zend_function *func = Z_PTR_P(zv); if (_idx == EG(persistent_functions_count)) { @@ -516,6 +518,8 @@ void shutdown_executor(void) /* {{{ */ if (EG(ht_iterators) != EG(ht_iterators_slots)) { efree(EG(ht_iterators)); } + + zend_hash_destroy(&EG(callable_convert_cache)); } #if ZEND_DEBUG @@ -536,7 +540,7 @@ void shutdown_executor(void) /* {{{ */ /* return class name and "::" or "". */ ZEND_API const char *get_active_class_name(const char **space) /* {{{ */ { - zend_function *func; + const zend_function *func; if (!zend_is_executing()) { if (space) { @@ -551,7 +555,7 @@ ZEND_API const char *get_active_class_name(const char **space) /* {{{ */ case ZEND_USER_FUNCTION: case ZEND_INTERNAL_FUNCTION: { - zend_class_entry *ce = func->common.scope; + const zend_class_entry *ce = func->common.scope; if (space) { *space = ce ? "::" : ""; @@ -569,7 +573,7 @@ ZEND_API const char *get_active_class_name(const char **space) /* {{{ */ ZEND_API const char *get_active_function_name(void) /* {{{ */ { - zend_function *func; + const zend_function *func; if (!zend_is_executing()) { return NULL; @@ -579,7 +583,7 @@ ZEND_API const char *get_active_function_name(void) /* {{{ */ switch (func->type) { case ZEND_USER_FUNCTION: { - zend_string *function_name = func->common.function_name; + const zend_string *function_name = func->common.function_name; if (function_name) { return ZSTR_VAL(function_name); @@ -597,9 +601,9 @@ ZEND_API const char *get_active_function_name(void) /* {{{ */ } /* }}} */ -ZEND_API zend_function *zend_active_function_ex(zend_execute_data *execute_data) +ZEND_API const zend_function *zend_active_function_ex(const zend_execute_data *execute_data) { - zend_function *func = EX(func); + const zend_function *func = EX(func); /* Resolve function if op is a frameless call. */ if (ZEND_USER_CODE(func->type)) { @@ -636,7 +640,7 @@ ZEND_API const char *get_active_function_arg_name(uint32_t arg_num) /* {{{ */ return NULL; } - zend_function *func = zend_active_function(); + const zend_function *func = zend_active_function(); return get_function_arg_name(func, arg_num); } @@ -648,17 +652,13 @@ ZEND_API const char *get_function_arg_name(const zend_function *func, uint32_t a return NULL; } - if (func->type == ZEND_USER_FUNCTION || (func->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) { - return ZSTR_VAL(func->common.arg_info[arg_num - 1].name); - } else { - return ((zend_internal_arg_info*) func->common.arg_info)[arg_num - 1].name; - } + return ZSTR_VAL(func->common.arg_info[arg_num - 1].name); } /* }}} */ ZEND_API const char *zend_get_executed_filename(void) /* {{{ */ { - zend_string *filename = zend_get_executed_filename_ex(); + const zend_string *filename = zend_get_executed_filename_ex(); return filename != NULL ? ZSTR_VAL(filename) : "[no active file]"; } /* }}} */ @@ -670,7 +670,7 @@ ZEND_API zend_string *zend_get_executed_filename_ex(void) /* {{{ */ return filename_override; } - zend_execute_data *ex = EG(current_execute_data); + const zend_execute_data *ex = EG(current_execute_data); while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) { ex = ex->prev_execute_data; @@ -690,7 +690,7 @@ ZEND_API uint32_t zend_get_executed_lineno(void) /* {{{ */ return lineno_override; } - zend_execute_data *ex = EG(current_execute_data); + const zend_execute_data *ex = EG(current_execute_data); while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) { ex = ex->prev_execute_data; @@ -713,7 +713,7 @@ ZEND_API uint32_t zend_get_executed_lineno(void) /* {{{ */ ZEND_API zend_class_entry *zend_get_executed_scope(void) /* {{{ */ { - zend_execute_data *ex = EG(current_execute_data); + const zend_execute_data *ex = EG(current_execute_data); while (1) { if (!ex) { @@ -739,7 +739,7 @@ ZEND_API zend_result ZEND_FASTCALL zval_update_constant_with_ctx(zval *p, zend_c if (ast->kind == ZEND_AST_CONSTANT) { zend_string *name = zend_ast_get_constant_name(ast); - zval *zv = zend_get_constant_ex(name, scope, ast->attr); + const zval *zv = zend_get_constant_ex(name, scope, ast->attr); if (UNEXPECTED(zv == NULL)) { return FAILURE; } @@ -808,7 +808,6 @@ zend_result _call_user_function_impl(zval *object, zval *function_name, zval *re zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /* {{{ */ { - uint32_t i; zend_execute_data *call; zend_fcall_info_cache fci_cache_local; zend_function *func; @@ -859,22 +858,21 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_ call_info = ZEND_CALL_TOP_FUNCTION | ZEND_CALL_DYNAMIC | ZEND_CALL_HAS_THIS; } - call = zend_vm_stack_push_call_frame(call_info, - func, fci->param_count, object_or_called_scope); - if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_DEPRECATED)) { zend_deprecated_function(func); if (UNEXPECTED(EG(exception))) { - zend_vm_stack_free_call_frame(call); return SUCCESS; } } - for (i=0; iparam_count; i++) { + call = zend_vm_stack_push_call_frame(call_info, + func, fci->param_count, object_or_called_scope); + + for (uint32_t i = 0; i < fci->param_count; i++) { zval *param = ZEND_CALL_ARG(call, i+1); zval *arg = &fci->params[i]; - bool must_wrap = 0; + bool must_wrap = false; if (UNEXPECTED(Z_ISUNDEF_P(arg))) { /* Allow forwarding undef slots. This is only used by Closure::__invoke(). */ ZVAL_UNDEF(param); @@ -888,7 +886,7 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_ /* By-value send is not allowed -- emit a warning, * and perform the call with the value wrapped in a reference. */ zend_param_must_be_ref(func, i + 1); - must_wrap = 1; + must_wrap = true; if (UNEXPECTED(EG(exception))) { ZEND_CALL_NUM_ARGS(call) = i; cleanup_args: @@ -922,13 +920,13 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_ zend_string *name; zval *arg; uint32_t arg_num = ZEND_CALL_NUM_ARGS(call) + 1; - bool have_named_params = 0; + bool have_named_params = false; ZEND_HASH_FOREACH_STR_KEY_VAL(fci->named_params, name, arg) { - bool must_wrap = 0; + bool must_wrap = false; zval *target; if (name) { void *cache_slot[2] = {NULL, NULL}; - have_named_params = 1; + have_named_params = true; target = zend_handle_named_arg(&call, name, &arg_num, cache_slot); if (!target) { goto cleanup_args; @@ -950,7 +948,7 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_ /* By-value send is not allowed -- emit a warning, * and perform the call with the value wrapped in a reference. */ zend_param_must_be_ref(func, arg_num); - must_wrap = 1; + must_wrap = true; if (UNEXPECTED(EG(exception))) { goto cleanup_args; } @@ -1130,22 +1128,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 */ @@ -1160,7 +1156,7 @@ static const uint32_t valid_chars[8] = { 0xffffffff, }; -ZEND_API bool zend_is_valid_class_name(zend_string *name) { +ZEND_API bool zend_is_valid_class_name(const zend_string *name) { for (size_t i = 0; i < ZSTR_LEN(name); i++) { unsigned char c = ZSTR_VAL(name)[i]; if (!ZEND_BIT_TEST(valid_chars, c)) { @@ -1300,7 +1296,7 @@ ZEND_API zend_class_entry *zend_lookup_class(zend_string *name) /* {{{ */ } /* }}} */ -ZEND_API zend_class_entry *zend_get_called_scope(zend_execute_data *ex) /* {{{ */ +ZEND_API zend_class_entry *zend_get_called_scope(const zend_execute_data *ex) /* {{{ */ { while (ex) { if (Z_TYPE(ex->This) == IS_OBJECT) { @@ -1318,7 +1314,7 @@ ZEND_API zend_class_entry *zend_get_called_scope(zend_execute_data *ex) /* {{{ * } /* }}} */ -ZEND_API zend_object *zend_get_this_object(zend_execute_data *ex) /* {{{ */ +ZEND_API zend_object *zend_get_this_object(const zend_execute_data *ex) /* {{{ */ { while (ex) { if (Z_TYPE(ex->This) == IS_OBJECT) { @@ -1432,14 +1428,14 @@ ZEND_API ZEND_NORETURN void ZEND_FASTCALL zend_timeout(void) /* {{{ */ function. */ if (EG(hard_timeout) > 0) { zend_atomic_bool_store_ex(&EG(timed_out), false); - zend_set_timeout_ex(EG(hard_timeout), 1); + zend_set_timeout_ex(EG(hard_timeout), true); /* XXX Abused, introduce an additional flag if the value needs to be kept. */ EG(hard_timeout) = 0; } # endif #else zend_atomic_bool_store_ex(&EG(timed_out), false); - zend_set_timeout_ex(0, 1); + zend_set_timeout_ex(0, true); #endif zend_error_noreturn(E_ERROR, "Maximum execution time of " ZEND_LONG_FMT " second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s"); @@ -1524,7 +1520,7 @@ static void zend_timeout_handler(int dummy) /* {{{ */ #ifndef ZTS if (EG(hard_timeout) > 0) { /* Set hard timeout */ - zend_set_timeout_ex(EG(hard_timeout), 1); + zend_set_timeout_ex(EG(hard_timeout), true); } #endif } @@ -1582,7 +1578,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; @@ -1669,7 +1667,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; @@ -1687,7 +1687,7 @@ void zend_unset_timeout(void) /* {{{ */ } /* }}} */ -static ZEND_COLD void report_class_fetch_error(zend_string *class_name, uint32_t fetch_type) +static ZEND_COLD void report_class_fetch_error(const zend_string *class_name, uint32_t fetch_type) { if (fetch_type & ZEND_FETCH_CLASS_SILENT) { return; @@ -1856,7 +1856,7 @@ ZEND_API zend_array *zend_rebuild_symbol_table(void) /* {{{ */ ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ */ { - zend_op_array *op_array = &execute_data->func->op_array; + const zend_op_array *op_array = &execute_data->func->op_array; HashTable *ht = execute_data->symbol_table; /* copy real values from symbol table into CV slots and create @@ -1871,7 +1871,7 @@ ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ * if (zv) { if (Z_TYPE_P(zv) == IS_INDIRECT) { - zval *val = Z_INDIRECT_P(zv); + const zval *val = Z_INDIRECT_P(zv); ZVAL_COPY_VALUE(var, val); } else { @@ -1891,7 +1891,7 @@ ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ * ZEND_API void zend_detach_symbol_table(zend_execute_data *execute_data) /* {{{ */ { - zend_op_array *op_array = &execute_data->func->op_array; + const zend_op_array *op_array = &execute_data->func->op_array; HashTable *ht = execute_data->symbol_table; /* copy real values from CV slots into symbol table */ @@ -1925,7 +1925,7 @@ ZEND_API zend_result zend_set_local_var(zend_string *name, zval *value, bool for if (execute_data) { if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) { zend_ulong h = zend_string_hash_val(name); - zend_op_array *op_array = &execute_data->func->op_array; + const zend_op_array *op_array = &execute_data->func->op_array; if (EXPECTED(op_array->last_var)) { zend_string **str = op_array->vars; @@ -1968,7 +1968,7 @@ ZEND_API zend_result zend_set_local_var_str(const char *name, size_t len, zval * if (execute_data) { if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) { zend_ulong h = zend_hash_func(name, len); - zend_op_array *op_array = &execute_data->func->op_array; + const zend_op_array *op_array = &execute_data->func->op_array; if (EXPECTED(op_array->last_var)) { zend_string **str = op_array->vars; zend_string **end = str + op_array->last_var; diff --git a/Zend/zend_extensions.h b/Zend/zend_extensions.h index becd53d7d08bd..4de8ad5414c2a 100644 --- a/Zend/zend_extensions.h +++ b/Zend/zend_extensions.h @@ -44,7 +44,7 @@ You can use the following macro to check the extension API version for compatibi /* The first number is the engine version and the rest is the date (YYYYMMDD). * This way engine 2/3 API no. is always greater than engine 1 API no.. */ -#define ZEND_EXTENSION_API_NO 420240925 +#define ZEND_EXTENSION_API_NO 420250926 typedef struct _zend_extension_version_info { int zend_extension_api_no; diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index 97b7cdcc911b7..d571a622e476b 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -207,7 +207,12 @@ static zend_fiber_stack *zend_fiber_stack_allocate(size_t size) { void *pointer; const size_t page_size = zend_fiber_get_page_size(); - const size_t minimum_stack_size = page_size + ZEND_FIBER_GUARD_PAGES * page_size; + const size_t minimum_stack_size = page_size + ZEND_FIBER_GUARD_PAGES * page_size +#ifdef __SANITIZE_ADDRESS__ + // necessary correction due to ASAN redzones + * 6 +#endif + ; if (size < minimum_stack_size) { zend_throw_exception_ex(NULL, 0, "Fiber stack size is too small, it needs to be at least %zu bytes", minimum_stack_size); diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c index 8da55fcd48f66..527ddd4b1931e 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); @@ -480,10 +512,10 @@ static void root_buffer_dtor(zend_gc_globals *gc_globals) static void gc_globals_ctor_ex(zend_gc_globals *gc_globals) { - gc_globals->gc_enabled = 0; - gc_globals->gc_active = 0; - gc_globals->gc_protected = 1; - gc_globals->gc_full = 0; + gc_globals->gc_enabled = false; + gc_globals->gc_active = false; + gc_globals->gc_protected = true; + gc_globals->gc_full = false; gc_globals->buf = NULL; gc_globals->unused = GC_INVALID; @@ -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,11 +1970,12 @@ 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; - bool should_rerun_gc = 0; - bool did_rerun_gc = 0; + bool should_rerun_gc = false; + bool did_rerun_gc = false; zend_hrtime_t start_time = zend_hrtime(); if (GC_G(num_roots) && !GC_G(gc_active)) { @@ -1968,7 +2029,7 @@ ZEND_API int zend_gc_collect_cycles(void) * modify any refcounts, so we have no real way to detect this situation * short of rerunning full GC tracing. What we do instead is to only run * destructors at this point and automatically re-run GC afterwards. */ - should_rerun_gc = 1; + should_rerun_gc = true; /* Mark all roots for which a dtor will be invoked as DTOR_GARBAGE. Additionally * color them purple. This serves a double purpose: First, they should be @@ -2094,7 +2155,7 @@ ZEND_API int zend_gc_collect_cycles(void) * up. We do this only once: If we encounter more destructors on the second run, we'll not * run GC another time. */ if (should_rerun_gc && !did_rerun_gc) { - did_rerun_gc = 1; + did_rerun_gc = true; goto rerun_gc; } diff --git a/Zend/zend_gdb.c b/Zend/zend_gdb.c index 102b0b3181999..5975d8c29c099 100644 --- a/Zend/zend_gdb.c +++ b/Zend/zend_gdb.c @@ -109,7 +109,7 @@ ZEND_API void zend_gdb_unregister_all(void) ZEND_API bool zend_gdb_present(void) { - bool ret = 0; + bool ret = false; #if defined(__linux__) /* netbsd while having this procfs part, does not hold the tracer pid */ int fd = open("/proc/self/status", O_RDONLY); @@ -133,7 +133,7 @@ ZEND_API bool zend_gdb_present(void) snprintf(buf, sizeof(buf), "/proc/%d/exe", (int)pid); if (readlink(buf, out, sizeof(out) - 1) > 0) { if (strstr(out, "gdb")) { - ret = 1; + ret = true; } } } diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index a6ea91a7425b9..d85c0f2da4a94 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -244,7 +244,6 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */ zend_generator *current_generator = zend_generator_get_current(generator); zend_execute_data *ex = generator->execute_data; uint32_t op_num, try_catch_offset; - int i; /* If current_generator is running in a fiber, there are 2 cases to consider: * - If generator is also marked with ZEND_GENERATOR_IN_FIBER, then the @@ -281,7 +280,7 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */ if (EXPECTED(!ex) || EXPECTED(!(ex->func->op_array.fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)) || CG(unclean_shutdown)) { - zend_generator_close(generator, 0); + zend_generator_close(generator, false); return; } @@ -289,7 +288,7 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */ try_catch_offset = -1; /* Find the innermost try/catch that we are inside of. */ - for (i = 0; i < ex->func->op_array.last_try_catch; i++) { + for (uint32_t 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 (op_num < try_catch->try_op) { break; @@ -309,9 +308,20 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */ ZEND_CALL_VAR(ex, ex->func->op_array.opcodes[try_catch->finally_end].op1.var); zend_generator_cleanup_unfinished_execution(generator, ex, try_catch->finally_op); - zend_object *old_exception = EG(exception); - const zend_op *old_opline_before_exception = EG(opline_before_exception); - EG(exception) = NULL; + + zend_object *old_exception = NULL; + const zend_op *old_opline_before_exception = NULL; + if (EG(exception)) { + if (EG(current_execute_data) + && EG(current_execute_data)->opline + && EG(current_execute_data)->opline->opcode == ZEND_HANDLE_EXCEPTION) { + EG(current_execute_data)->opline = EG(opline_before_exception); + old_opline_before_exception = EG(opline_before_exception); + } + old_exception = EG(exception); + EG(exception) = NULL; + } + Z_OBJ_P(fast_call) = NULL; Z_OPLINE_NUM_P(fast_call) = (uint32_t)-1; @@ -321,7 +331,10 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */ zend_generator_resume(generator); if (old_exception) { - EG(opline_before_exception) = old_opline_before_exception; + if (old_opline_before_exception) { + EG(current_execute_data)->opline = EG(exception_op); + EG(opline_before_exception) = old_opline_before_exception; + } if (EG(exception)) { zend_exception_set_previous(EG(exception), old_exception); } else { @@ -351,7 +364,7 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */ try_catch_offset--; } - zend_generator_close(generator, 0); + zend_generator_close(generator, false); } /* }}} */ @@ -359,7 +372,7 @@ static void zend_generator_free_storage(zend_object *object) /* {{{ */ { zend_generator *generator = (zend_generator*) object; - zend_generator_close(generator, 0); + zend_generator_close(generator, false); if (generator->func && (generator->func->common.fn_flags & ZEND_ACC_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(generator->func)); @@ -498,8 +511,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 +539,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 +807,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 +817,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 +840,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 { @@ -847,7 +869,7 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */ * its calling frame (see above in if (check_yield_from). */ if (UNEXPECTED(EG(exception) != NULL)) { if (generator == orig_generator) { - zend_generator_close(generator, 0); + zend_generator_close(generator, false); if (!EG(current_execute_data)) { zend_throw_exception_internal(NULL); } else if (EG(current_execute_data)->func && @@ -1025,7 +1047,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 b4e94ec1f9892..ef81ae5faaf25 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -88,7 +88,7 @@ struct _zend_compiler_globals { zend_string *compiled_filename; - int zend_lineno; + uint32_t zend_lineno; zend_op_array *active_op_array; @@ -204,7 +204,7 @@ struct _zend_executor_globals { zend_execute_data *current_observed_frame; - int ticks_count; + uint32_t ticks_count; zend_long precision; @@ -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; @@ -318,6 +319,8 @@ struct _zend_executor_globals { zend_strtod_state strtod_state; + HashTable callable_convert_cache; + void *reserved[ZEND_MAX_RESERVED_RESOURCES]; }; @@ -340,7 +343,7 @@ struct _zend_ini_scanner_globals { zend_stack state_stack; zend_string *filename; - int lineno; + uint32_t lineno; /* Modes are: ZEND_INI_SCANNER_NORMAL, ZEND_INI_SCANNER_RAW, ZEND_INI_SCANNER_TYPED */ int scanner_mode; diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 66cfb250d1fec..c00397e9fe9e3 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -281,14 +281,14 @@ ZEND_API void ZEND_FASTCALL _zend_hash_init(HashTable *ht, uint32_t nSize, dtor_ ZEND_API HashTable* ZEND_FASTCALL _zend_new_array_0(void) { HashTable *ht = emalloc(sizeof(HashTable)); - _zend_hash_init_int(ht, HT_MIN_SIZE, ZVAL_PTR_DTOR, 0); + _zend_hash_init_int(ht, HT_MIN_SIZE, ZVAL_PTR_DTOR, false); return ht; } ZEND_API HashTable* ZEND_FASTCALL _zend_new_array(uint32_t nSize) { HashTable *ht = emalloc(sizeof(HashTable)); - _zend_hash_init_int(ht, nSize, ZVAL_PTR_DTOR, 0); + _zend_hash_init_int(ht, nSize, ZVAL_PTR_DTOR, false); return ht; } @@ -296,7 +296,7 @@ ZEND_API HashTable* ZEND_FASTCALL zend_new_pair(const zval *val1, const zval *va { zval *zv; HashTable *ht = emalloc(sizeof(HashTable)); - _zend_hash_init_int(ht, HT_MIN_SIZE, ZVAL_PTR_DTOR, 0); + _zend_hash_init_int(ht, HT_MIN_SIZE, ZVAL_PTR_DTOR, false); ht->nNumUsed = ht->nNumOfElements = ht->nNextFreeElement = 2; zend_hash_real_init_packed_ex(ht); @@ -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); } @@ -1055,6 +1062,13 @@ ZEND_API zval* ZEND_FASTCALL zend_hash_str_add_new(HashTable *ht, const char *st return _zend_hash_str_add_or_update_i(ht, str, len, h, pData, HASH_ADD_NEW); } +ZEND_API zval* ZEND_FASTCALL zend_hash_str_lookup(HashTable *ht, const char *str, size_t len) +{ + zend_ulong h = zend_hash_func(str, len); + + return _zend_hash_str_add_or_update_i(ht, str, len, h, NULL, HASH_LOOKUP); +} + ZEND_API zval* ZEND_FASTCALL zend_hash_index_add_empty_element(HashTable *ht, zend_ulong h) { zval dummy; @@ -1378,7 +1392,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 +1411,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)) { @@ -2368,7 +2382,7 @@ static zend_always_inline void zend_array_dup_packed_elements(const HashTable *s const zval *end = p + source->nNumUsed; do { - if (!zend_array_dup_value(source, p, q, 1, with_holes)) { + if (!zend_array_dup_value(source, p, q, true, with_holes)) { if (with_holes) { ZVAL_UNDEF(q); } @@ -2393,13 +2407,13 @@ static zend_always_inline uint32_t zend_array_dup_elements(const HashTable *sour } do { - if (!zend_array_dup_element(source, target, idx, p, q, 0, static_keys, with_holes)) { + if (!zend_array_dup_element(source, target, idx, p, q, false, static_keys, with_holes)) { uint32_t target_idx = idx; idx++; p++; if (EXPECTED(!HT_HAS_ITERATORS(target))) { while (p != end) { - if (zend_array_dup_element(source, target, target_idx, p, q, 0, static_keys, with_holes)) { + if (zend_array_dup_element(source, target, target_idx, p, q, false, static_keys, with_holes)) { if (source->nInternalPointer == idx) { target->nInternalPointer = target_idx; } @@ -2412,7 +2426,7 @@ static zend_always_inline uint32_t zend_array_dup_elements(const HashTable *sour uint32_t iter_pos = zend_hash_iterators_lower_pos(target, idx); while (p != end) { - if (zend_array_dup_element(source, target, target_idx, p, q, 0, static_keys, with_holes)) { + if (zend_array_dup_element(source, target, target_idx, p, q, false, static_keys, with_holes)) { if (source->nInternalPointer == idx) { target->nInternalPointer = target_idx; } @@ -2457,6 +2471,7 @@ ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(const HashTable *source) target->nTableSize = HT_MIN_SIZE; HT_SET_DATA_ADDR(target, &uninitialized_bucket); } else if (GC_FLAGS(source) & IS_ARRAY_IMMUTABLE) { + ZEND_ASSERT(!(HT_FLAGS(source) & HASH_FLAG_HAS_EMPTY_IND)); HT_FLAGS(target) = HT_FLAGS(source) & HASH_FLAG_MASK; target->nTableMask = source->nTableMask; target->nNumUsed = source->nNumUsed; @@ -2473,6 +2488,7 @@ ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(const HashTable *source) memcpy(HT_GET_DATA_ADDR(target), HT_GET_DATA_ADDR(source), HT_USED_SIZE(source)); } } else if (HT_IS_PACKED(source)) { + ZEND_ASSERT(!(HT_FLAGS(source) & HASH_FLAG_HAS_EMPTY_IND)); HT_FLAGS(target) = HT_FLAGS(source) & HASH_FLAG_MASK; target->nTableMask = HT_MIN_MASK; target->nNumUsed = source->nNumUsed; @@ -2487,12 +2503,13 @@ ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(const HashTable *source) HT_HASH_RESET_PACKED(target); if (HT_IS_WITHOUT_HOLES(target)) { - zend_array_dup_packed_elements(source, target, 0); + zend_array_dup_packed_elements(source, target, false); } else { - zend_array_dup_packed_elements(source, target, 1); + zend_array_dup_packed_elements(source, target, true); } } else { - HT_FLAGS(target) = HT_FLAGS(source) & HASH_FLAG_MASK; + /* Indirects are removed during duplication, remove HASH_FLAG_HAS_EMPTY_IND accordingly. */ + HT_FLAGS(target) = HT_FLAGS(source) & (HASH_FLAG_MASK & ~HASH_FLAG_HAS_EMPTY_IND); target->nTableMask = source->nTableMask; target->nNextFreeElement = source->nNextFreeElement; target->nInternalPointer = @@ -2505,15 +2522,15 @@ ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(const HashTable *source) if (HT_HAS_STATIC_KEYS_ONLY(target)) { if (HT_IS_WITHOUT_HOLES(source)) { - idx = zend_array_dup_elements(source, target, 1, 0); + idx = zend_array_dup_elements(source, target, true, false); } else { - idx = zend_array_dup_elements(source, target, 1, 1); + idx = zend_array_dup_elements(source, target, true, true); } } else { if (HT_IS_WITHOUT_HOLES(source)) { - idx = zend_array_dup_elements(source, target, 0, 0); + idx = zend_array_dup_elements(source, target, false, false); } else { - idx = zend_array_dup_elements(source, target, 0, 1); + idx = zend_array_dup_elements(source, target, false, true); } } target->nNumUsed = idx; @@ -2841,8 +2858,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 +2905,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..70d9721cb7a17 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. */ @@ -216,6 +218,7 @@ static zend_always_inline zval *zend_hash_find_ex(const HashTable *ht, zend_stri /* Find or add NULL, if doesn't exist */ ZEND_API zval* ZEND_FASTCALL zend_hash_lookup(HashTable *ht, zend_string *key); ZEND_API zval* ZEND_FASTCALL zend_hash_index_lookup(HashTable *ht, zend_ulong h); +ZEND_API zval* ZEND_FASTCALL zend_hash_str_lookup(HashTable *ht, const char *str, size_t len); #define ZEND_HASH_INDEX_LOOKUP(_ht, _h, _ret) do { \ if (EXPECTED(HT_IS_PACKED(_ht))) { \ @@ -251,9 +254,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 +273,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) { @@ -471,6 +474,17 @@ static zend_always_inline bool zend_hash_str_exists_ind(const HashTable *ht, con Z_TYPE_P(Z_INDIRECT_P(zv)) != IS_UNDEF); } +static zend_always_inline zval *zend_symtable_add(HashTable *ht, zend_string *key, zval *pData) +{ + zend_ulong idx; + + if (ZEND_HANDLE_NUMERIC(key, idx)) { + return zend_hash_index_add(ht, idx, pData); + } else { + return zend_hash_add(ht, key, pData); + } +} + static zend_always_inline zval *zend_symtable_add_new(HashTable *ht, zend_string *key, zval *pData) { zend_ulong idx; @@ -1619,14 +1633,15 @@ static zend_always_inline bool zend_array_is_list(const zend_array *array) } -static zend_always_inline zval *_zend_hash_append_ex(HashTable *ht, zend_string *key, zval *zv, bool interned) +static zend_always_inline zval *_zend_hash_append_ex(HashTable *ht, zend_string *key, zval *zv, bool key_guaranteed_interned) { uint32_t idx = ht->nNumUsed++; uint32_t nIndex; Bucket *p = ht->arData + idx; ZVAL_COPY_VALUE(&p->val, zv); - if (!interned && !ZSTR_IS_INTERNED(key)) { + ZEND_ASSERT(!key_guaranteed_interned || ZSTR_IS_INTERNED(key)); + if (!key_guaranteed_interned && !ZSTR_IS_INTERNED(key)) { HT_FLAGS(ht) &= ~HASH_FLAG_STATIC_KEYS; zend_string_addref(key); zend_string_hash_val(key); @@ -1645,14 +1660,15 @@ static zend_always_inline zval *_zend_hash_append(HashTable *ht, zend_string *ke return _zend_hash_append_ex(ht, key, zv, 0); } -static zend_always_inline zval *_zend_hash_append_ptr_ex(HashTable *ht, zend_string *key, void *ptr, bool interned) +static zend_always_inline zval *_zend_hash_append_ptr_ex(HashTable *ht, zend_string *key, void *ptr, bool key_guaranteed_interned) { uint32_t idx = ht->nNumUsed++; uint32_t nIndex; Bucket *p = ht->arData + idx; ZVAL_PTR(&p->val, ptr); - if (!interned && !ZSTR_IS_INTERNED(key)) { + ZEND_ASSERT(!key_guaranteed_interned || ZSTR_IS_INTERNED(key)); + if (!key_guaranteed_interned && !ZSTR_IS_INTERNED(key)) { HT_FLAGS(ht) &= ~HASH_FLAG_STATIC_KEYS; zend_string_addref(key); zend_string_hash_val(key); diff --git a/Zend/zend_hrtime.c b/Zend/zend_hrtime.c index 7fa36b1b654f4..773e0525cadd9 100644 --- a/Zend/zend_hrtime.c +++ b/Zend/zend_hrtime.c @@ -27,6 +27,8 @@ # include # include +ZEND_API clockid_t zend_hrtime_posix_clock_id = CLOCK_MONOTONIC; + #elif ZEND_HRTIME_PLATFORM_WINDOWS # define WIN32_LEAN_AND_MEAN @@ -66,5 +68,24 @@ void zend_startup_hrtime(void) mach_timebase_info(&zend_hrtime_timerlib_info); +#elif ZEND_HRTIME_PLATFORM_POSIX + + struct timespec ts; + +#ifdef CLOCK_MONOTONIC_RAW + if (EXPECTED(0 == clock_gettime(CLOCK_MONOTONIC_RAW, &ts))) { + zend_hrtime_posix_clock_id = CLOCK_MONOTONIC_RAW; + return; + } +#endif + + if (EXPECTED(0 == clock_gettime(zend_hrtime_posix_clock_id, &ts))) { + return; + } + + // zend_error mechanism is not initialized at that point + fprintf(stderr, "No working CLOCK_MONOTONIC* found, this should never happen\n"); + abort(); + #endif } diff --git a/Zend/zend_hrtime.h b/Zend/zend_hrtime.h index 994dd6da169ed..f3bc4deeaf502 100644 --- a/Zend/zend_hrtime.h +++ b/Zend/zend_hrtime.h @@ -72,6 +72,10 @@ ZEND_API extern double zend_hrtime_timer_scale; # include ZEND_API extern mach_timebase_info_data_t zend_hrtime_timerlib_info; +#elif ZEND_HRTIME_PLATFORM_POSIX + +ZEND_API extern clockid_t zend_hrtime_posix_clock_id; + #endif #define ZEND_NANO_IN_SEC UINT64_C(1000000000) @@ -92,10 +96,8 @@ static zend_always_inline zend_hrtime_t zend_hrtime(void) return (zend_hrtime_t)mach_absolute_time() * zend_hrtime_timerlib_info.numer / zend_hrtime_timerlib_info.denom; #elif ZEND_HRTIME_PLATFORM_POSIX struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; - if (EXPECTED(0 == clock_gettime(CLOCK_MONOTONIC, &ts))) { - return ((zend_hrtime_t) ts.tv_sec * (zend_hrtime_t)ZEND_NANO_IN_SEC) + ts.tv_nsec; - } - return 0; + clock_gettime(zend_hrtime_posix_clock_id, &ts); + return ((zend_hrtime_t) ts.tv_sec * (zend_hrtime_t)ZEND_NANO_IN_SEC) + ts.tv_nsec; #elif ZEND_HRTIME_PLATFORM_HPUX return (zend_hrtime_t) gethrtime(); #elif ZEND_HRTIME_PLATFORM_AIX diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index d27cca5b76187..3c3931cdca164 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -200,7 +200,7 @@ static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */ } /* }}} */ -char *zend_visibility_string(uint32_t fn_flags) /* {{{ */ +const char *zend_visibility_string(uint32_t fn_flags) /* {{{ */ { if (fn_flags & ZEND_ACC_PUBLIC) { return "public"; @@ -312,7 +312,7 @@ static zend_class_entry *lookup_class(zend_class_entry *scope, zend_string *name /* Instanceof that's safe to use on unlinked classes. */ static bool unlinked_instanceof(const zend_class_entry *ce1, const zend_class_entry *ce2) { if (ce1 == ce2) { - return 1; + return true; } if (ce1->ce_flags & ZEND_ACC_LINKED) { @@ -331,7 +331,7 @@ static bool unlinked_instanceof(const zend_class_entry *ce1, const zend_class_en /* It's not sufficient to only check the parent chain itself, as need to do a full * recursive instanceof in case the parent interfaces haven't been copied yet. */ if (parent_ce && unlinked_instanceof(parent_ce, ce2)) { - return 1; + return true; } } @@ -342,7 +342,7 @@ static bool unlinked_instanceof(const zend_class_entry *ce1, const zend_class_en * check here, as the parent interfaces might not have been fully copied yet. */ for (i = 0; i < ce1->num_interfaces; i++) { if (unlinked_instanceof(ce1->interfaces[i], ce2)) { - return 1; + return true; } } } else { @@ -352,19 +352,19 @@ static bool unlinked_instanceof(const zend_class_entry *ce1, const zend_class_en ZEND_FETCH_CLASS_ALLOW_UNLINKED | ZEND_FETCH_CLASS_NO_AUTOLOAD); /* Avoid recursing if class implements itself. */ if (ce && ce != ce1 && unlinked_instanceof(ce, ce2)) { - return 1; + return true; } } } } - return 0; + return false; } static bool zend_type_permits_self( const zend_type type, const zend_class_entry *scope, zend_class_entry *self) { if (ZEND_TYPE_FULL_MASK(type) & MAY_BE_OBJECT) { - return 1; + return true; } /* Any types that may satisfy self must have already been loaded at this point @@ -376,11 +376,11 @@ static bool zend_type_permits_self( zend_string *name = resolve_class_name(scope, ZEND_TYPE_NAME(*single_type)); const zend_class_entry *ce = lookup_class(self, name); if (ce && unlinked_instanceof(self, ce)) { - return 1; + return true; } } } ZEND_TYPE_FOREACH_END(); - return 0; + return false; } static void track_class_dependency(zend_class_entry *ce, zend_string *class_name) @@ -475,7 +475,7 @@ static inheritance_status zend_is_class_subtype_of_type( zend_class_entry *fe_scope, zend_string *fe_class_name, zend_class_entry *proto_scope, const zend_type proto_type) { zend_class_entry *fe_ce = NULL; - bool have_unresolved = 0; + bool have_unresolved = false; /* If the parent has 'object' as a return type, any class satisfies the co-variant check */ if (ZEND_TYPE_FULL_MASK(proto_type) & MAY_BE_OBJECT) { @@ -484,7 +484,7 @@ static inheritance_status zend_is_class_subtype_of_type( * are not classes (such as typedefs). */ if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name); if (!fe_ce) { - have_unresolved = 1; + have_unresolved = true; } else { track_class_dependency(fe_ce, fe_class_name); return INHERITANCE_SUCCESS; @@ -495,7 +495,7 @@ static inheritance_status zend_is_class_subtype_of_type( if (ZEND_TYPE_FULL_MASK(proto_type) & MAY_BE_CALLABLE) { if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name); if (!fe_ce) { - have_unresolved = 1; + have_unresolved = true; } else if (fe_ce == zend_ce_closure) { track_class_dependency(fe_ce, fe_class_name); return INHERITANCE_SUCCESS; @@ -506,7 +506,7 @@ static inheritance_status zend_is_class_subtype_of_type( if ((ZEND_TYPE_FULL_MASK(proto_type) & MAY_BE_STATIC) && (fe_scope->ce_flags & ZEND_ACC_FINAL)) { if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name); if (!fe_ce) { - have_unresolved = 1; + have_unresolved = true; } else if (fe_ce == fe_scope) { track_class_dependency(fe_ce, fe_class_name); return INHERITANCE_SUCCESS; @@ -530,7 +530,7 @@ static inheritance_status zend_is_class_subtype_of_type( } continue; case INHERITANCE_UNRESOLVED: - have_unresolved = 1; + have_unresolved = true; continue; case INHERITANCE_SUCCESS: if (!is_intersection) { @@ -562,7 +562,7 @@ static inheritance_status zend_is_class_subtype_of_type( } if (!fe_ce || !proto_ce) { - have_unresolved = 1; + have_unresolved = true; continue; } if (unlinked_instanceof(fe_ce, proto_ce)) { @@ -916,7 +916,7 @@ static ZEND_COLD zend_string *zend_get_function_declaration( smart_str str = {0}; if (fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) { - smart_str_appends(&str, "& "); + smart_str_appendc(&str, '&'); } if (fptr->common.scope) { @@ -942,7 +942,7 @@ static ZEND_COLD zend_string *zend_get_function_declaration( num_args++; } for (uint32_t i = 0; i < num_args;) { - zend_append_type_hint(&str, scope, arg_info, 0); + zend_append_type_hint(&str, scope, arg_info, false); if (ZEND_ARG_SEND_MODE(arg_info)) { smart_str_appendc(&str, '&'); @@ -953,18 +953,14 @@ static ZEND_COLD zend_string *zend_get_function_declaration( } smart_str_appendc(&str, '$'); - if (fptr->type == ZEND_INTERNAL_FUNCTION) { - smart_str_appends(&str, ((zend_internal_arg_info*)arg_info)->name); - } else { - smart_str_appendl(&str, ZSTR_VAL(arg_info->name), ZSTR_LEN(arg_info->name)); - } + smart_str_append(&str, arg_info->name); if (i >= required && !ZEND_ARG_IS_VARIADIC(arg_info)) { smart_str_appends(&str, " = "); if (fptr->type == ZEND_INTERNAL_FUNCTION) { - if (((zend_internal_arg_info*)arg_info)->default_value) { - smart_str_appends(&str, ((zend_internal_arg_info*)arg_info)->default_value); + if (arg_info->default_value) { + smart_str_append(&str, arg_info->default_value); } else { smart_str_appends(&str, ""); } @@ -1011,7 +1007,9 @@ static ZEND_COLD zend_string *zend_get_function_declaration( zend_ast *ast = Z_ASTVAL_P(zv); if (ast->kind == ZEND_AST_CONSTANT) { smart_str_append(&str, zend_ast_get_constant_name(ast)); - } else if (ast->kind == ZEND_AST_CLASS_CONST) { + } else if (ast->kind == ZEND_AST_CLASS_CONST + && ast->child[1]->kind == ZEND_AST_ZVAL + && Z_TYPE_P(zend_ast_get_zval(ast->child[1])) == IS_STRING) { smart_str_append(&str, zend_ast_get_str(ast->child[0])); smart_str_appends(&str, "::"); smart_str_append(&str, zend_ast_get_str(ast->child[1])); @@ -1039,7 +1037,7 @@ static ZEND_COLD zend_string *zend_get_function_declaration( if (fptr->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { smart_str_appends(&str, ": "); - zend_append_type_hint(&str, scope, fptr->common.arg_info - 1, 1); + zend_append_type_hint(&str, scope, fptr->common.arg_info - 1, true); } smart_str_0(&str); @@ -1085,10 +1083,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 +1561,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 +1712,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(); @@ -1768,7 +1782,7 @@ ZEND_API void zend_verify_hooked_property(const zend_class_entry *ce, zend_prope && (prop_info->flags & ZEND_ACC_PPP_SET_MASK) && (!prop_info->hooks[ZEND_PROPERTY_HOOK_GET] || !prop_info->hooks[ZEND_PROPERTY_HOOK_SET])) { const char *prefix = !prop_info->hooks[ZEND_PROPERTY_HOOK_GET] - ? "Write-only" : "Read-only"; + ? "set-only" : "get-only"; zend_error_noreturn(E_COMPILE_ERROR, "%s virtual property %s::$%s must not specify asymmetric visibility", prefix, ZSTR_VAL(ce->name), ZSTR_VAL(prop_name)); @@ -2020,7 +2034,7 @@ ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *par } zend_function *func; ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&parent_ce->function_table, key, func) { - do_inherit_method(key, func, ce, 0, flags); + do_inherit_method(key, func, ce, false, flags); } ZEND_HASH_FOREACH_END(); } @@ -2173,7 +2187,7 @@ static void do_interface_implementation(zend_class_entry *ce, zend_class_entry * } ZEND_HASH_FOREACH_END(); ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&iface->function_table, key, func) { - do_inherit_method(key, func, ce, 1, flags); + do_inherit_method(key, func, ce, true, flags); } ZEND_HASH_FOREACH_END(); zend_hash_extend(&ce->properties_info, @@ -2303,13 +2317,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 +2332,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 +2352,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 +3522,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 +3568,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 +3579,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 +3784,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 +3945,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 +3972,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 +3996,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..8d26cd65579df 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; @@ -326,7 +332,7 @@ ZEND_API void zend_ini_refresh_caches(int stage) /* {{{ */ ZEND_API zend_result zend_alter_ini_entry(zend_string *name, zend_string *new_value, int modify_type, int stage) /* {{{ */ { - return zend_alter_ini_entry_ex(name, new_value, modify_type, stage, 0); + return zend_alter_ini_entry_ex(name, new_value, modify_type, stage, false); } /* }}} */ @@ -336,7 +342,7 @@ ZEND_API zend_result zend_alter_ini_entry_chars(zend_string *name, const char *v zend_string *new_value; new_value = zend_string_init(value, value_length, !(stage & ZEND_INI_STAGE_IN_REQUEST)); - ret = zend_alter_ini_entry_ex(name, new_value, modify_type, stage, 0); + ret = zend_alter_ini_entry_ex(name, new_value, modify_type, stage, false); zend_string_release(new_value); return ret; } @@ -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; @@ -503,7 +515,7 @@ ZEND_API zend_string *zend_ini_str_ex(const char *name, size_t name_length, bool ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length); if (ini_entry) { if (exists) { - *exists = 1; + *exists = true; } if (orig && ini_entry->modified) { @@ -513,7 +525,7 @@ ZEND_API zend_string *zend_ini_str_ex(const char *name, size_t name_length, bool } } else { if (exists) { - *exists = 0; + *exists = false; } return NULL; } @@ -522,7 +534,7 @@ ZEND_API zend_string *zend_ini_str_ex(const char *name, size_t name_length, bool ZEND_API zend_string *zend_ini_str(const char *name, size_t name_length, bool orig) /* {{{ */ { - bool exists = 1; + bool exists = true; zend_string *return_value; return_value = zend_ini_str_ex(name, name_length, orig, &exists); diff --git a/Zend/zend_ini_parser.y b/Zend/zend_ini_parser.y index 5f788f152fb6a..748ccd2235a6d 100644 --- a/Zend/zend_ini_parser.y +++ b/Zend/zend_ini_parser.y @@ -205,7 +205,7 @@ static ZEND_COLD void ini_error(const char *msg) error_buf_len = 128 + (int)strlen(msg) + (int)strlen(currently_parsed_filename); /* should be more than enough */ error_buf = (char *) emalloc(error_buf_len); - sprintf(error_buf, "%s in %s on line %d\n", msg, currently_parsed_filename, zend_ini_scanner_get_lineno()); + sprintf(error_buf, "%s in %s on line %" PRIu32 "\n", msg, currently_parsed_filename, zend_ini_scanner_get_lineno()); } else { error_buf = estrdup("Invalid configuration directive\n"); } diff --git a/Zend/zend_ini_scanner.h b/Zend/zend_ini_scanner.h index 62546413c7cb2..9a6c84fce4292 100644 --- a/Zend/zend_ini_scanner.h +++ b/Zend/zend_ini_scanner.h @@ -30,7 +30,7 @@ typedef struct _zend_file_handle zend_file_handle; #define ZEND_INI_SCANNER_TYPED 2 /* Typed mode. */ BEGIN_EXTERN_C() -ZEND_COLD int zend_ini_scanner_get_lineno(void); +ZEND_COLD uint32_t zend_ini_scanner_get_lineno(void); ZEND_COLD const char *zend_ini_scanner_get_filename(void); zend_result zend_ini_open_file_for_scanning(zend_file_handle *fh, int scanner_mode); zend_result zend_ini_prepare_string_for_scanning(const char *str, int scanner_mode); diff --git a/Zend/zend_ini_scanner.l b/Zend/zend_ini_scanner.l index b87f4e33cc8f8..5f9b77e6a3d8a 100644 --- a/Zend/zend_ini_scanner.l +++ b/Zend/zend_ini_scanner.l @@ -145,10 +145,10 @@ ZEND_API zend_ini_scanner_globals ini_scanner_globals; if (SCNG(scanner_mode) == ZEND_INI_SCANNER_TYPED && \ (YYSTATE == STATE(ST_VALUE) || YYSTATE == STATE(ST_RAW))) {\ zend_ini_copy_typed_value(ini_lval, type, str, len); \ - Z_EXTRA_P(ini_lval) = 0; \ } else { \ zend_ini_copy_value(ini_lval, str, len); \ } \ + Z_EXTRA_P(ini_lval) = 0; \ return type; \ } @@ -230,7 +230,7 @@ void shutdown_ini_scanner(void) /* }}} */ /* {{{ zend_ini_scanner_get_lineno() */ -ZEND_COLD int zend_ini_scanner_get_lineno(void) +ZEND_COLD uint32_t zend_ini_scanner_get_lineno(void) { return SCNG(lineno); } diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c index ce9cc00fdfb95..404dd9db893ea 100644 --- a/Zend/zend_interfaces.c +++ b/Zend/zend_interfaces.c @@ -496,7 +496,7 @@ static zend_object *zend_internal_iterator_create(zend_class_entry *ce) { zend_internal_iterator *intern = emalloc(sizeof(zend_internal_iterator)); zend_object_std_init(&intern->std, ce); intern->iter = NULL; - intern->rewind_called = 0; + intern->rewind_called = false; return &intern->std; } @@ -537,7 +537,7 @@ static zend_internal_iterator *zend_internal_iterator_fetch(zval *This) { static zend_result zend_internal_iterator_ensure_rewound(zend_internal_iterator *intern) { if (!intern->rewind_called) { zend_object_iterator *iter = intern->iter; - intern->rewind_called = 1; + intern->rewind_called = true; if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception))) { @@ -630,7 +630,7 @@ ZEND_METHOD(InternalIterator, rewind) { RETURN_THROWS(); } - intern->rewind_called = 1; + intern->rewind_called = true; if (!intern->iter->funcs->rewind) { /* Allow calling rewind() if no iteration has happened yet, * even if the iterator does not support rewinding. */ 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 07ea669ae8e6c..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)'" @@ -713,15 +713,14 @@ 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)); } ; @@ -1349,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.h b/Zend/zend_language_scanner.h index 612c845479272..c494564ba2349 100644 --- a/Zend/zend_language_scanner.h +++ b/Zend/zend_language_scanner.h @@ -20,6 +20,7 @@ #ifndef ZEND_SCANNER_H #define ZEND_SCANNER_H +/* The zend_php_scanner_event enum is declared in zend_globals and we don't want everything to include zend_language_scanner.h */ #include "zend_globals.h" typedef struct _zend_lex_state { @@ -71,7 +72,7 @@ typedef struct _zend_heredoc_label { /* Track locations of unclosed {, [, (, etc. for better syntax error reporting */ typedef struct _zend_nest_location { char text; - int lineno; + uint32_t lineno; } zend_nest_location; BEGIN_EXTERN_C() diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index 2bd21f7b4c2eb..1e26ddbd99199 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -30,6 +30,7 @@ #include "zend_language_scanner_defs.h" #include +#include #include "zend.h" #ifdef ZEND_WIN32 # include @@ -210,6 +211,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 +583,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; @@ -597,7 +601,7 @@ static zend_op_array *zend_compile(int type) CG(ast_arena) = zend_arena_create(1024 * 32); if (!zendparse()) { - int last_lineno = CG(zend_lineno); + uint32_t last_lineno = CG(zend_lineno); zend_file_context original_file_context; zend_oparray_context original_oparray_context; zend_op_array *original_active_op_array = CG(active_op_array); @@ -650,7 +654,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 +770,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 +927,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; @@ -1125,7 +1141,7 @@ skip_escape_conversion: unsigned char *str; // TODO: avoid realocation ??? s = Z_STRVAL_P(zendlval); - SCNG(output_filter)(&str, &sz, (unsigned char *)s, (size_t)Z_STRLEN_P(zendlval)); + SCNG(output_filter)(&str, &sz, (unsigned char *)s, Z_STRLEN_P(zendlval)); zval_ptr_dtor(zendlval); ZVAL_STRINGL(zendlval, (char *) str, sz); efree(str); @@ -1157,7 +1173,7 @@ static bool strip_multiline_string_indentation( const char *str = Z_STRVAL_P(zendlval), *end = str + Z_STRLEN_P(zendlval); char *copy = Z_STRVAL_P(zendlval); - int newline_count = 0; + uint32_t newline_count = 0; size_t newline_len; const char *nl; @@ -1238,7 +1254,7 @@ static void copy_heredoc_label_stack(void *void_heredoc_label) } /* Check that { }, [ ], ( ) are nested correctly */ -static void report_bad_nesting(char opening, int opening_lineno, char closing) +static void report_bad_nesting(char opening, uint32_t opening_lineno, char closing) { char buf[256]; size_t used = 0; @@ -1346,7 +1362,7 @@ int ZEND_FASTCALL lex_scan(zval *zendlval, zend_parser_stack_elem *elem) { int token; int offset; -int start_line = CG(zend_lineno); +uint32_t start_line = CG(zend_lineno); ZVAL_UNDEF(zendlval); restart: @@ -1619,11 +1635,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}("double"|"float"){TABS_AND_SPACES}")" { +"("{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}("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); } @@ -1635,7 +1671,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); } @@ -1647,7 +1693,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); } @@ -2444,7 +2500,7 @@ inline_char_handler: if (YYCURSOR < YYLIMIT) { YYCURSOR++; } else { - zend_throw_exception_ex(zend_ce_parse_error, 0, "Unterminated comment starting line %d", CG(zend_lineno)); + zend_throw_exception_ex(zend_ce_parse_error, 0, "Unterminated comment starting line %" PRIu32, CG(zend_lineno)); if (PARSER_MODE()) { RETURN_TOKEN(T_ERROR); } @@ -2561,7 +2617,7 @@ skip_escape_conversion: zend_string *new_str; s = Z_STRVAL_P(zendlval); // TODO: avoid reallocation ??? - SCNG(output_filter)((unsigned char **)&str, &sz, (unsigned char *)s, (size_t)Z_STRLEN_P(zendlval)); + SCNG(output_filter)((unsigned char **)&str, &sz, (unsigned char *)s, Z_STRLEN_P(zendlval)); new_str = zend_string_init(str, sz, 0); if (str != s) { efree(str); @@ -2703,6 +2759,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_list.c b/Zend/zend_list.c index bf599a2efca9b..10aa9174cfccb 100644 --- a/Zend/zend_list.c +++ b/Zend/zend_list.c @@ -214,18 +214,41 @@ void zend_init_rsrc_plist(void) void zend_close_rsrc_list(HashTable *ht) { - /* Reload ht->arData on each iteration, as it may be reallocated. */ uint32_t i = ht->nNumUsed; - - while (i-- > 0) { - zval *p = ZEND_HASH_ELEMENT(ht, i); - if (Z_TYPE_P(p) != IS_UNDEF) { - zend_resource *res = Z_PTR_P(p); - if (res->type >= 0) { - zend_resource_dtor(res); + uint32_t num = ht->nNumUsed; + +retry: + zend_try { + while (i-- > 0) { + /* Reload ht->arData on each iteration, as it may be reallocated. */ + zval *p = ZEND_HASH_ELEMENT(ht, i); + if (Z_TYPE_P(p) != IS_UNDEF) { + zend_resource *res = Z_PTR_P(p); + if (res->type >= 0) { + zend_resource_dtor(res); + + if (UNEXPECTED(ht->nNumUsed != num)) { + /* New resources were added, reloop from the start. + * We need to keep the top->down order to avoid freeing resources + * in use by the newly created resources. */ + i = num = ht->nNumUsed; + } + } } } - } + } zend_catch { + if (UNEXPECTED(ht->nNumUsed != num)) { + /* See above */ + i = num = ht->nNumUsed; + } + + /* If we have bailed, we probably executed user code (e.g. user stream + * API). Keep closing resources so they don't leak. User handlers must be + * called now so they aren't called in zend_deactivate() on + * zend_destroy_rsrc_list(&EG(regular_list)). At that point, the executor + * has already shut down and the process would crash. */ + goto retry; + } zend_end_try(); } diff --git a/Zend/zend_long.h b/Zend/zend_long.h index 3796f1c5ababb..fef237701f3bd 100644 --- a/Zend/zend_long.h +++ b/Zend/zend_long.h @@ -51,9 +51,6 @@ typedef int32_t zend_off_t; #endif -/* Conversion macros. */ -#define ZEND_LTOA_BUF_LEN 65 - #ifdef ZEND_ENABLE_ZVAL_LONG64 # define ZEND_LONG_FMT "%" PRId64 # define ZEND_ULONG_FMT "%" PRIu64 @@ -61,7 +58,6 @@ typedef int32_t zend_off_t; # define ZEND_LONG_FMT_SPEC PRId64 # define ZEND_ULONG_FMT_SPEC PRIu64 # ifdef ZEND_WIN32 -# define ZEND_LTOA(i, s, len) _i64toa_s((i), (s), (len), 10) # define ZEND_ATOL(s) _atoi64((s)) # define ZEND_STRTOL(s0, s1, base) _strtoi64((s0), (s1), (base)) # define ZEND_STRTOUL(s0, s1, base) _strtoui64((s0), (s1), (base)) @@ -69,11 +65,6 @@ typedef int32_t zend_off_t; # define ZEND_STRTOUL_PTR _strtoui64 # define ZEND_ABS _abs64 # else -# define ZEND_LTOA(i, s, len) \ - do { \ - int st = snprintf((s), (len), ZEND_LONG_FMT, (i)); \ - (s)[st] = '\0'; \ - } while (0) # define ZEND_ATOL(s) atoll((s)) # define ZEND_STRTOL(s0, s1, base) strtoll((s0), (s1), (base)) # define ZEND_STRTOUL(s0, s1, base) strtoull((s0), (s1), (base)) @@ -90,14 +81,8 @@ typedef int32_t zend_off_t; # define ZEND_LONG_FMT_SPEC PRId32 # define ZEND_ULONG_FMT_SPEC PRIu32 # ifdef ZEND_WIN32 -# define ZEND_LTOA(i, s, len) _ltoa_s((i), (s), (len), 10) # define ZEND_ATOL(s) atol((s)) # else -# define ZEND_LTOA(i, s, len) \ - do { \ - int st = snprintf((s), (len), ZEND_LONG_FMT, (i)); \ - (s)[st] = '\0'; \ - } while (0) # define ZEND_ATOL(s) atol((s)) # endif # define ZEND_STRTOL_PTR strtol diff --git a/Zend/zend_modules.h b/Zend/zend_modules.h index efc04a63bb363..a8076c0fb9058 100644 --- a/Zend/zend_modules.h +++ b/Zend/zend_modules.h @@ -31,7 +31,7 @@ #define ZEND_MODULE_INFO_FUNC_ARGS zend_module_entry *zend_module #define ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU zend_module -#define ZEND_MODULE_API_NO 20240925 +#define ZEND_MODULE_API_NO 20250926 #ifdef ZTS #define USING_ZTS 1 #else diff --git a/Zend/zend_multibyte.c b/Zend/zend_multibyte.c index 9459920b6332b..f61ed79fd1f7a 100644 --- a/Zend/zend_multibyte.c +++ b/Zend/zend_multibyte.c @@ -35,7 +35,7 @@ static const char *dummy_encoding_name_getter(const zend_encoding *encoding) static bool dummy_encoding_lexer_compatibility_checker(const zend_encoding *encoding) { - return 0; + return false; } static const zend_encoding *dummy_encoding_detector(const unsigned char *string, size_t length, const zend_encoding **list, size_t list_size) @@ -195,7 +195,7 @@ ZEND_API zend_result zend_multibyte_set_script_encoding_by_string(const char *ne return SUCCESS; } - if (FAILURE == zend_multibyte_parse_encoding_list(new_value, new_value_length, &list, &size, 1)) { + if (FAILURE == zend_multibyte_parse_encoding_list(new_value, new_value_length, &list, &size, true)) { return FAILURE; } 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 732b7e8f2bd96..88b7b1112d7b1 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -46,6 +46,9 @@ #define IN_ISSET ZEND_GUARD_PROPERTY_ISSET #define IN_HOOK ZEND_GUARD_PROPERTY_HOOK +static zend_arg_info zend_call_trampoline_arginfo[1] = {{0}}; +static zend_arg_info zend_property_hook_arginfo[1] = {{0}}; + static zend_always_inline bool zend_objects_check_stack_limit(void) { #ifdef ZEND_CHECK_STACK_LIMIT @@ -106,8 +109,7 @@ ZEND_API HashTable *rebuild_object_properties_internal(zend_object *zobj) /* {{{ /* Implements the fast path for array cast */ ZEND_API HashTable *zend_std_build_object_properties_array(zend_object *zobj) /* {{{ */ { - zend_property_info *prop_info; - zend_class_entry *ce = zobj->ce; + const zend_class_entry *ce = zobj->ce; HashTable *ht; zval* prop; int i; @@ -118,7 +120,7 @@ ZEND_API HashTable *zend_std_build_object_properties_array(zend_object *zobj) /* if (ce->default_properties_count) { zend_hash_real_init_mixed(ht); for (i = 0; i < ce->default_properties_count; i++) { - prop_info = ce->properties_info_table[i]; + const zend_property_info *prop_info = ce->properties_info_table[i]; if (!prop_info) { continue; @@ -192,7 +194,7 @@ ZEND_API HashTable *zend_std_get_gc(zend_object *zobj, zval **table, int *n) /* ZEND_API HashTable *zend_std_get_debug_info(zend_object *object, int *is_temp) /* {{{ */ { - zend_class_entry *ce = object->ce; + const zend_class_entry *ce = object->ce; zval retval; HashTable *ht; @@ -223,6 +225,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,7 +289,7 @@ 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)); } /* }}} */ @@ -332,7 +336,7 @@ static ZEND_COLD zend_never_inline bool zend_deprecated_dynamic_property( zend_error(E_DEPRECATED, "Creation of dynamic property %s::$%s is deprecated", ZSTR_VAL(obj->ce->name), ZSTR_VAL(member)); if (UNEXPECTED(GC_DELREF(obj) == 0)) { - zend_class_entry *ce = obj->ce; + const zend_class_entry *ce = obj->ce; zend_objects_store_del(obj); if (!EG(exception)) { /* We cannot continue execution and have to throw an exception */ @@ -345,7 +349,7 @@ static ZEND_COLD zend_never_inline bool zend_deprecated_dynamic_property( } static ZEND_COLD zend_never_inline void zend_readonly_property_unset_error( - zend_class_entry *ce, zend_string *member) { + const zend_class_entry *ce, const zend_string *member) { zend_throw_error(NULL, "Cannot unset readonly property %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(member)); } @@ -422,7 +426,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; } } @@ -517,7 +521,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; } } @@ -564,6 +568,11 @@ ZEND_API zend_result zend_check_property_access(const zend_object *zobj, zend_st return FAILURE; } } else { + /* We were looking for a protected property but found a private one + * belonging to the parent class. */ + if (property_info->flags & ZEND_ACC_PRIVATE) { + return FAILURE; + } ZEND_ASSERT(property_info->flags & ZEND_ACC_PROTECTED); } return SUCCESS; @@ -588,7 +597,7 @@ ZEND_API bool ZEND_FASTCALL zend_asymmetric_property_has_set_access(const zend_p 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) /* {{{ */ { @@ -673,7 +682,7 @@ static ZEND_FUNCTION(zend_parent_hook_set_trampoline); static bool zend_is_in_hook(const zend_property_info *prop_info) { - zend_execute_data *execute_data = EG(current_execute_data); + const zend_execute_data *execute_data = EG(current_execute_data); if (!execute_data || !EX(func) || !EX(func)->common.prop_info) { return false; } @@ -704,7 +713,7 @@ static bool zend_should_call_hook(const zend_property_info *prop_info, const zen return true; } -static ZEND_COLD void zend_throw_no_prop_backing_value_access(zend_string *class_name, zend_string *prop_name, bool is_read) +static ZEND_COLD void zend_throw_no_prop_backing_value_access(const zend_string *class_name, const zend_string *prop_name, bool is_read) { zend_throw_error(NULL, "Must not %s virtual property %s::$%s", is_read ? "read from" : "write to", @@ -712,7 +721,7 @@ static ZEND_COLD void zend_throw_no_prop_backing_value_access(zend_string *class } static bool zend_call_get_hook( - const zend_property_info *prop_info, zend_string *prop_name, + const zend_property_info *prop_info, const zend_string *prop_name, zend_function *get, zend_object *zobj, zval *rv) { if (!zend_should_call_hook(prop_info, zobj)) { @@ -807,7 +816,7 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int zend_function *get = prop_info->hooks[ZEND_PROPERTY_HOOK_GET]; if (!get) { if (prop_info->flags & ZEND_ACC_VIRTUAL) { - zend_throw_error(NULL, "Property %s::$%s is write-only", + zend_throw_error(NULL, "Cannot read from set-only virtual property %s::$%s", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name)); return &EG(uninitialized_zval); } @@ -835,7 +844,7 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int goto exit; } - zend_class_entry *ce = zobj->ce; + const zend_class_entry *ce = zobj->ce; if (!zend_call_get_hook(prop_info, name, get, zobj, rv)) { if (EG(exception)) { @@ -843,7 +852,7 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int } /* Reads from backing store can only occur in hooks, and hence will always remain simple. */ - zend_execute_data *execute_data = EG(current_execute_data); + const zend_execute_data *execute_data = EG(current_execute_data); if (cache_slot && EX(opline) && EX(opline)->opcode == ZEND_FETCH_OBJ_R && EX(opline)->op1_type == IS_UNUSED) { ZEND_SET_PROPERTY_HOOK_SIMPLE_READ(cache_slot); } @@ -989,7 +998,7 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int /* }}} */ static zend_always_inline bool property_uses_strict_types(void) { - zend_execute_data *execute_data = EG(current_execute_data); + const zend_execute_data *execute_data = EG(current_execute_data); return execute_data && execute_data->func && ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data)); @@ -1148,7 +1157,7 @@ found:; if (!set) { if (prop_info->flags & ZEND_ACC_VIRTUAL) { - zend_throw_error(NULL, "Property %s::$%s is read-only", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name)); + zend_throw_error(NULL, "Cannot write to get-only virtual property %s::$%s", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name)); variable_ptr = &EG(error_zval); goto exit; } @@ -1267,7 +1276,7 @@ found:; } /* }}} */ -static ZEND_COLD zend_never_inline void zend_bad_array_access(zend_class_entry *ce) /* {{{ */ +static ZEND_COLD zend_never_inline void zend_bad_array_access(const zend_class_entry *ce) /* {{{ */ { zend_throw_error(NULL, "Cannot use object of type %s as array", ZSTR_VAL(ce->name)); } @@ -1275,7 +1284,7 @@ static ZEND_COLD zend_never_inline void zend_bad_array_access(zend_class_entry * ZEND_API zval *zend_std_read_dimension(zend_object *object, zval *offset, int type, zval *rv) /* {{{ */ { - zend_class_entry *ce = object->ce; + const zend_class_entry *ce = object->ce; zval tmp_offset; /* arrayaccess_funcs_ptr is set if (and only if) the class implements zend_ce_arrayaccess */ @@ -1326,7 +1335,7 @@ ZEND_API zval *zend_std_read_dimension(zend_object *object, zval *offset, int ty ZEND_API void zend_std_write_dimension(zend_object *object, zval *offset, zval *value) /* {{{ */ { - zend_class_entry *ce = object->ce; + const zend_class_entry *ce = object->ce; zval tmp_offset; zend_class_arrayaccess_funcs *funcs = ce->arrayaccess_funcs_ptr; @@ -1349,7 +1358,7 @@ ZEND_API void zend_std_write_dimension(zend_object *object, zval *offset, zval * // todo: make zend_std_has_dimension return bool as well ZEND_API int zend_std_has_dimension(zend_object *object, zval *offset, int check_empty) /* {{{ */ { - zend_class_entry *ce = object->ce; + const zend_class_entry *ce = object->ce; zval retval, tmp_offset; bool result; @@ -1603,7 +1612,7 @@ ZEND_API void zend_std_unset_property(zend_object *zobj, zend_string *name, void ZEND_API void zend_std_unset_dimension(zend_object *object, zval *offset) /* {{{ */ { - zend_class_entry *ce = object->ce; + const zend_class_entry *ce = object->ce; zval tmp_offset; zend_class_arrayaccess_funcs *funcs = ce->arrayaccess_funcs_ptr; @@ -1619,7 +1628,7 @@ ZEND_API void zend_std_unset_dimension(zend_object *object, zval *offset) /* {{{ } /* }}} */ -static zend_never_inline zend_function *zend_get_parent_private_method(zend_class_entry *scope, zend_class_entry *ce, zend_string *function_name) /* {{{ */ +static zend_never_inline zend_function *zend_get_parent_private_method(const zend_class_entry *scope, const zend_class_entry *ce, zend_string *function_name) /* {{{ */ { zval *func; zend_function *fbc; @@ -1667,19 +1676,17 @@ ZEND_API bool zend_check_protected(const zend_class_entry *ce, const zend_class_ } /* }}} */ -ZEND_API zend_function *zend_get_call_trampoline_func(const zend_class_entry *ce, zend_string *method_name, bool is_static) /* {{{ */ +ZEND_API ZEND_ATTRIBUTE_NONNULL zend_function *zend_get_call_trampoline_func( + const zend_function *fbc, zend_string *method_name) /* {{{ */ { size_t mname_len; zend_op_array *func; - zend_function *fbc = is_static ? ce->__callstatic : ce->__call; /* We use non-NULL value to avoid useless run_time_cache allocation. * The low bit must be zero, to not be interpreted as a MAP_PTR offset. */ static const void *dummy = (void*)(intptr_t)2; static const zend_arg_info arg_info[1] = {{0}}; - ZEND_ASSERT(fbc); - if (EXPECTED(EG(trampoline).common.function_name == NULL)) { func = &EG(trampoline).op_array; } else { @@ -1693,12 +1700,10 @@ ZEND_API zend_function *zend_get_call_trampoline_func(const zend_class_entry *ce func->fn_flags = ZEND_ACC_CALL_VIA_TRAMPOLINE | ZEND_ACC_PUBLIC | ZEND_ACC_VARIADIC - | (fbc->common.fn_flags & (ZEND_ACC_RETURN_REFERENCE|ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED|ZEND_ACC_NODISCARD)); + | (fbc->common.fn_flags & (ZEND_ACC_RETURN_REFERENCE|ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED|ZEND_ACC_NODISCARD|ZEND_ACC_STATIC)); + func->fn_flags2 = 0; /* Attributes outlive the trampoline because they are created by the compiler. */ func->attributes = fbc->common.attributes; - if (is_static) { - func->fn_flags |= ZEND_ACC_STATIC; - } func->opcodes = &EG(call_trampoline_op); ZEND_MAP_PTR_INIT(func->run_time_cache, (void**)dummy); func->scope = fbc->common.scope; @@ -1744,7 +1749,7 @@ static ZEND_FUNCTION(zend_parent_hook_get_trampoline) } zval rv; - zval *retval = obj->handlers->read_property(obj, prop_name, BP_VAR_R, NULL, &rv); + const zval *retval = obj->handlers->read_property(obj, prop_name, BP_VAR_R, NULL, &rv); if (retval == &rv) { RETVAL_COPY_VALUE(retval); } else { @@ -1780,7 +1785,6 @@ ZEND_API zend_function *zend_get_property_hook_trampoline( const zend_property_info *prop_info, zend_property_hook_kind kind, zend_string *prop_name) { - static const zend_arg_info arg_info[1] = {{0}}; zend_function *func; if (EXPECTED(EG(trampoline).common.function_name == NULL)) { func = &EG(trampoline); @@ -1795,6 +1799,7 @@ ZEND_API zend_function *zend_get_property_hook_trampoline( func->common.arg_flags[1] = 0; func->common.arg_flags[2] = 0; func->common.fn_flags = ZEND_ACC_CALL_VIA_TRAMPOLINE; + func->common.fn_flags2 = 0; func->common.function_name = zend_string_concat3( "$", 1, ZSTR_VAL(prop_name), ZSTR_LEN(prop_name), kind == ZEND_PROPERTY_HOOK_GET ? "::get" : "::set", 5); @@ -1805,7 +1810,7 @@ ZEND_API zend_function *zend_get_property_hook_trampoline( func->common.scope = prop_info->ce; func->common.prototype = NULL; func->common.prop_info = prop_info; - func->common.arg_info = (zend_arg_info *) arg_info; + func->common.arg_info = zend_property_hook_arginfo; func->internal_function.handler = kind == ZEND_PROPERTY_HOOK_GET ? ZEND_FN(zend_parent_hook_get_trampoline) : ZEND_FN(zend_parent_hook_set_trampoline); @@ -1817,12 +1822,6 @@ ZEND_API zend_function *zend_get_property_hook_trampoline( return func; } -static zend_always_inline zend_function *zend_get_user_call_function(zend_class_entry *ce, zend_string *method_name) /* {{{ */ -{ - return zend_get_call_trampoline_func(ce, method_name, 0); -} -/* }}} */ - 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", @@ -1846,7 +1845,6 @@ ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string * zval *func; zend_function *fbc; zend_string *lc_method_name; - zend_class_entry *scope; ALLOCA_FLAG(use_heap); if (EXPECTED(key != NULL)) { @@ -1864,7 +1862,7 @@ ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string * ZSTR_ALLOCA_FREE(lc_method_name, use_heap); } if (zobj->ce->__call) { - return zend_get_user_call_function(zobj->ce, method_name); + return zend_get_call_trampoline_func(zobj->ce->__call, method_name); } else { return NULL; } @@ -1874,7 +1872,7 @@ ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string * /* Check access level */ if (fbc->op_array.fn_flags & (ZEND_ACC_CHANGED|ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) { - scope = zend_get_executed_scope(); + const zend_class_entry *scope = zend_get_executed_scope(); if (fbc->common.scope != scope) { if (fbc->op_array.fn_flags & ZEND_ACC_CHANGED) { @@ -1890,7 +1888,7 @@ ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string * if (UNEXPECTED(fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fbc), scope))) { if (zobj->ce->__call) { - fbc = zend_get_user_call_function(zobj->ce, method_name); + fbc = zend_get_call_trampoline_func(zobj->ce->__call, method_name); } else { zend_bad_method_call(fbc, method_name, scope); fbc = NULL; @@ -1911,14 +1909,8 @@ ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string * } /* }}} */ -static zend_always_inline zend_function *zend_get_user_callstatic_function(zend_class_entry *ce, zend_string *method_name) /* {{{ */ -{ - return zend_get_call_trampoline_func(ce, method_name, 1); -} -/* }}} */ - static zend_always_inline zend_function *get_static_method_fallback( - zend_class_entry *ce, zend_string *function_name) + const zend_class_entry *ce, zend_string *function_name) { zend_object *object; if (ce->__call && @@ -1928,15 +1920,15 @@ static zend_always_inline zend_function *get_static_method_fallback( * see: tests/classes/__call_004.phpt */ ZEND_ASSERT(object->ce->__call); - return zend_get_user_call_function(object->ce, function_name); + return zend_get_call_trampoline_func(object->ce->__call, function_name); } else if (ce->__callstatic) { - return zend_get_user_callstatic_function(ce, function_name); + return zend_get_call_trampoline_func(ce->__callstatic, function_name); } else { return NULL; } } -ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_string *function_name, const zval *key) /* {{{ */ +ZEND_API zend_function *zend_std_get_static_method(const zend_class_entry *ce, zend_string *function_name, const zval *key) /* {{{ */ { zend_string *lc_function_name; if (EXPECTED(key != NULL)) { @@ -1950,7 +1942,7 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st if (EXPECTED(func)) { fbc = Z_FUNC_P(func); if (!(fbc->common.fn_flags & ZEND_ACC_PUBLIC)) { - zend_class_entry *scope = zend_get_executed_scope(); + const zend_class_entry *scope = zend_get_executed_scope(); 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); @@ -1997,7 +1989,6 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st ZEND_API void zend_class_init_statics(zend_class_entry *class_type) /* {{{ */ { - int i; zval *p; if (class_type->default_static_members_count && !CE_STATIC_MEMBERS(class_type)) { @@ -2006,7 +1997,7 @@ ZEND_API void zend_class_init_statics(zend_class_entry *class_type) /* {{{ */ } ZEND_MAP_PTR_SET(class_type->static_members_table, emalloc(sizeof(zval) * class_type->default_static_members_count)); - for (i = 0; i < class_type->default_static_members_count; i++) { + for (uint32_t i = 0; i < class_type->default_static_members_count; i++) { p = &class_type->default_static_members_table[i]; if (Z_TYPE_P(p) == IS_INDIRECT) { zval *q = &CE_STATIC_MEMBERS(class_type->parent)[i]; @@ -2033,7 +2024,7 @@ ZEND_API zval *zend_std_get_static_property_with_info(zend_class_entry *ce, zend 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); } @@ -2204,6 +2195,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; @@ -2218,31 +2213,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; } } /* }}} */ @@ -2323,7 +2332,7 @@ ZEND_API int zend_std_has_property(zend_object *zobj, zend_string *name, int has if (!get) { if (prop_info->flags & ZEND_ACC_VIRTUAL) { - zend_throw_error(NULL, "Property %s::$%s is write-only", + zend_throw_error(NULL, "Cannot read from set-only virtual property %s::$%s", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name)); return 0; } else { @@ -2398,7 +2407,7 @@ ZEND_API int zend_std_has_property(zend_object *zobj, zend_string *name, int has if (!value || (Z_PROP_FLAG_P(value) & IS_PROP_LAZY)) { zobj = zend_lazy_object_init(zobj); if (!zobj) { - result = 0; + result = false; goto exit; } @@ -2416,7 +2425,7 @@ ZEND_API int zend_std_has_property(zend_object *zobj, zend_string *name, int has } } - result = 0; + result = false; goto exit; } /* }}} */ @@ -2431,7 +2440,7 @@ ZEND_API zend_result zend_std_cast_object_tostring(zend_object *readobj, zval *w { switch (type) { case IS_STRING: { - zend_class_entry *ce = readobj->ce; + const zend_class_entry *ce = readobj->ce; if (ce->__tostring) { zval retval; GC_ADDREF(readobj); @@ -2464,7 +2473,7 @@ ZEND_API zend_result zend_std_cast_object_tostring(zend_object *readobj, zval *w ZEND_API zend_result zend_std_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only) /* {{{ */ { zend_class_entry *ce = obj->ce; - zval *func = zend_hash_find_known_hash(&ce->function_table, ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE)); + const zval *func = zend_hash_find_known_hash(&ce->function_table, ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE)); if (func == NULL) { return FAILURE; @@ -2541,6 +2550,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 */ @@ -2564,3 +2574,8 @@ ZEND_API const zend_object_handlers std_object_handlers = { zend_std_compare_objects, /* compare */ NULL, /* get_properties_for */ }; + +void zend_object_handlers_startup(void) { + zend_call_trampoline_arginfo[0].name = ZSTR_KNOWN(ZEND_STR_ARGS); + zend_property_hook_arginfo[0].name = ZSTR_KNOWN(ZEND_STR_VALUE); +} diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index fb87695a2ed25..3e922343eb15a 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 */ @@ -246,7 +248,7 @@ extern const ZEND_API zend_object_handlers std_object_handlers; #define ZEND_PROPERTY_EXISTS 0x2 /* Property exists */ 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 zend_function *zend_std_get_static_method(const 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(const zend_class_entry *ce, const zend_string *property_name); @@ -310,9 +312,7 @@ ZEND_API bool zend_check_protected(const zend_class_entry *ce, const zend_class_ ZEND_API zend_result zend_check_property_access(const zend_object *zobj, zend_string *prop_info_name, bool is_dynamic); -ZEND_API zend_function *zend_get_call_trampoline_func(const zend_class_entry *ce, zend_string *method_name, bool is_static); - -ZEND_API uint32_t *zend_get_property_guard(zend_object *zobj, zend_string *member); +ZEND_API ZEND_ATTRIBUTE_NONNULL zend_function *zend_get_call_trampoline_func(const zend_function *fbc, zend_string *method_name); ZEND_API uint32_t *zend_get_property_guard(zend_object *zobj, zend_string *member); @@ -334,6 +334,8 @@ ZEND_API zend_function *zend_get_property_hook_trampoline( ZEND_API bool ZEND_FASTCALL zend_asymmetric_property_has_set_access(const zend_property_info *prop_info); +void zend_object_handlers_startup(void); + #define zend_release_properties(ht) do { \ if (ht) { \ zend_array_release(ht); \ diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c index 933c1161fe960..6f6a826389442 100644 --- a/Zend/zend_objects.c +++ b/Zend/zend_objects.c @@ -121,7 +121,7 @@ ZEND_API void zend_objects_destroy_object(zend_object *object) } zend_object *old_exception; - const zend_op *old_opline_before_exception; + const zend_op *old_opline_before_exception = NULL; if (destructor->common.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) { if (EG(current_execute_data)) { @@ -156,13 +156,15 @@ ZEND_API void zend_objects_destroy_object(zend_object *object) if (EG(exception) == object) { zend_error_noreturn(E_CORE_ERROR, "Attempt to destruct pending exception"); } else { - if (EG(current_execute_data) - && EG(current_execute_data)->func - && ZEND_USER_CODE(EG(current_execute_data)->func->common.type)) { - zend_rethrow_exception(EG(current_execute_data)); + if (EG(current_execute_data)) { + if (EG(current_execute_data)->func + && ZEND_USER_CODE(EG(current_execute_data)->func->common.type)) { + zend_rethrow_exception(EG(current_execute_data)); + } + EG(current_execute_data)->opline = EG(opline_before_exception); + old_opline_before_exception = EG(opline_before_exception); } old_exception = EG(exception); - old_opline_before_exception = EG(opline_before_exception); EG(exception) = NULL; } } @@ -170,7 +172,10 @@ ZEND_API void zend_objects_destroy_object(zend_object *object) zend_call_known_instance_method_with_0_params(destructor, object, NULL); if (old_exception) { - EG(opline_before_exception) = old_opline_before_exception; + if (EG(current_execute_data)) { + EG(current_execute_data)->opline = EG(exception_op); + EG(opline_before_exception) = old_opline_before_exception; + } if (EG(exception)) { zend_exception_set_previous(EG(exception), old_exception); } else { @@ -276,6 +281,52 @@ ZEND_API void ZEND_FASTCALL zend_objects_clone_members(zend_object *new_object, } } +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; + } + } + + 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) { zend_object *new_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_observer.c b/Zend/zend_observer.c index 15722eb6b2eb3..bee20bdbc20dc 100644 --- a/Zend/zend_observer.c +++ b/Zend/zend_observer.c @@ -115,8 +115,8 @@ ZEND_API void zend_observer_shutdown(void) static void zend_observer_fcall_install(zend_execute_data *execute_data) { - zend_llist *list = &zend_observers_fcall_list; - zend_function *function = execute_data->func; + const zend_llist *list = &zend_observers_fcall_list; + const zend_function *function = execute_data->func; ZEND_ASSERT(RUN_TIME_CACHE(&function->common)); zend_observer_fcall_begin_handler *begin_handlers = ZEND_OBSERVER_DATA(function), *begin_handlers_start = begin_handlers; @@ -126,7 +126,7 @@ static void zend_observer_fcall_install(zend_execute_data *execute_data) *end_handlers = ZEND_OBSERVER_NOT_OBSERVED; bool has_handlers = false; - for (zend_llist_element *element = list->head; element; element = element->next) { + for (const zend_llist_element *element = list->head; element; element = element->next) { zend_observer_fcall_init init; memcpy(&init, element->data, sizeof init); zend_observer_fcall_handlers handlers = init(execute_data); @@ -157,7 +157,7 @@ static void zend_observer_fcall_install(zend_execute_data *execute_data) * the previous next handler is now at the place where the current handler was. * Hence, the next handler executed will be the one after the next handler. * Callees must thus invoke the next handler themselves, with the same arguments they were passed. */ -static bool zend_observer_remove_handler(void **first_handler, void *old_handler, void **next_handler) { +static bool zend_observer_remove_handler(void **first_handler, const void *old_handler, void **next_handler) { size_t registered_observers = zend_observers_fcall_list.count; void **last_handler = first_handler + registered_observers - 1; @@ -179,7 +179,7 @@ static bool zend_observer_remove_handler(void **first_handler, void *old_handler return false; } -ZEND_API void zend_observer_add_begin_handler(zend_function *function, zend_observer_fcall_begin_handler begin) { +ZEND_API void zend_observer_add_begin_handler(const zend_function *function, zend_observer_fcall_begin_handler begin) { size_t registered_observers = zend_observers_fcall_list.count; zend_observer_fcall_begin_handler *first_handler = ZEND_OBSERVER_DATA(function), *last_handler = first_handler + registered_observers - 1; if (*first_handler == ZEND_OBSERVER_NOT_OBSERVED || *first_handler == ZEND_OBSERVER_NONE_OBSERVED) { @@ -196,7 +196,7 @@ ZEND_API void zend_observer_add_begin_handler(zend_function *function, zend_obse } } -ZEND_API bool zend_observer_remove_begin_handler(zend_function *function, zend_observer_fcall_begin_handler begin, zend_observer_fcall_begin_handler *next) { +ZEND_API bool zend_observer_remove_begin_handler(const zend_function *function, zend_observer_fcall_begin_handler begin, zend_observer_fcall_begin_handler *next) { void **begin_handlers = (void **)ZEND_OBSERVER_DATA(function); if (zend_observer_remove_handler(begin_handlers, begin, (void**)next)) { // Ensure invariant: ZEND_OBSERVER_NONE_OBSERVED in begin_handlers if both are not observed @@ -211,7 +211,7 @@ ZEND_API bool zend_observer_remove_begin_handler(zend_function *function, zend_o return false; } -ZEND_API void zend_observer_add_end_handler(zend_function *function, zend_observer_fcall_end_handler end) { +ZEND_API void zend_observer_add_end_handler(const zend_function *function, zend_observer_fcall_end_handler end) { size_t registered_observers = zend_observers_fcall_list.count; void **begin_handler = (void **)ZEND_OBSERVER_DATA(function); zend_observer_fcall_end_handler *end_handler = (zend_observer_fcall_end_handler *)begin_handler + registered_observers; @@ -226,7 +226,7 @@ ZEND_API void zend_observer_add_end_handler(zend_function *function, zend_observ *end_handler = end; } -ZEND_API bool zend_observer_remove_end_handler(zend_function *function, zend_observer_fcall_end_handler end, zend_observer_fcall_end_handler *next) { +ZEND_API bool zend_observer_remove_end_handler(const zend_function *function, zend_observer_fcall_end_handler end, zend_observer_fcall_end_handler *next) { size_t registered_observers = zend_observers_fcall_list.count; void **begin_handlers = (void **)ZEND_OBSERVER_DATA(function); void **end_handlers = begin_handlers + registered_observers; @@ -241,7 +241,7 @@ ZEND_API bool zend_observer_remove_end_handler(zend_function *function, zend_obs } static inline zend_execute_data **prev_observed_frame(zend_execute_data *execute_data) { - zend_function *func = EX(func); + const zend_function *func = EX(func); ZEND_ASSERT(func); return (zend_execute_data **)&Z_PTR_P(EX_VAR_NUM((ZEND_USER_CODE(func->type) ? func->op_array.last_var : ZEND_CALL_NUM_ARGS(execute_data)) + func->common.T - 1)); } @@ -256,7 +256,7 @@ static void ZEND_FASTCALL _zend_observe_fcall_begin(zend_execute_data *execute_d ZEND_API void ZEND_FASTCALL zend_observer_fcall_begin_prechecked(zend_execute_data *execute_data, zend_observer_fcall_begin_handler *handler) { - zend_observer_fcall_begin_handler *possible_handlers_end = handler + zend_observers_fcall_list.count; + const zend_observer_fcall_begin_handler *possible_handlers_end = handler + zend_observers_fcall_list.count; if (!*handler) { zend_observer_fcall_install(execute_data); @@ -265,7 +265,7 @@ ZEND_API void ZEND_FASTCALL zend_observer_fcall_begin_prechecked(zend_execute_da } } - zend_observer_fcall_end_handler *end_handler = (zend_observer_fcall_end_handler *)possible_handlers_end; + const zend_observer_fcall_end_handler *end_handler = (const zend_observer_fcall_end_handler *)possible_handlers_end; if (*end_handler != ZEND_OBSERVER_NOT_OBSERVED) { *prev_observed_frame(execute_data) = EG(current_observed_frame); EG(current_observed_frame) = execute_data; @@ -294,7 +294,7 @@ ZEND_API void ZEND_FASTCALL zend_observer_fcall_begin(zend_execute_data *execute } static inline void call_end_observers(zend_execute_data *execute_data, zval *return_value) { - zend_function *func = EX(func); + const zend_function *func = EX(func); ZEND_ASSERT(func); zend_observer_fcall_end_handler *handler = (zend_observer_fcall_end_handler *)ZEND_OBSERVER_DATA(func) + zend_observers_fcall_list.count; @@ -340,7 +340,7 @@ ZEND_API void ZEND_FASTCALL _zend_observer_function_declared_notify(zend_op_arra return; } - for (zend_llist_element *element = zend_observer_function_declared_callbacks.head; element; element = element->next) { + for (const zend_llist_element *element = zend_observer_function_declared_callbacks.head; element; element = element->next) { zend_observer_function_declared_cb callback = *(zend_observer_function_declared_cb *) (element->data); callback(op_array, name); } @@ -358,7 +358,7 @@ ZEND_API void ZEND_FASTCALL _zend_observer_class_linked_notify(zend_class_entry return; } - for (zend_llist_element *element = zend_observer_class_linked_callbacks.head; element; element = element->next) { + for (const zend_llist_element *element = zend_observer_class_linked_callbacks.head; element; element = element->next) { zend_observer_class_linked_cb callback = *(zend_observer_class_linked_cb *) (element->data); callback(ce, name); } @@ -372,7 +372,7 @@ ZEND_API void zend_observer_error_register(zend_observer_error_cb cb) ZEND_API void _zend_observer_error_notify(int type, zend_string *error_filename, uint32_t error_lineno, zend_string *message) { - for (zend_llist_element *element = zend_observer_error_callbacks.head; element; element = element->next) { + for (const zend_llist_element *element = zend_observer_error_callbacks.head; element; element = element->next) { zend_observer_error_cb callback = *(zend_observer_error_cb *) (element->data); callback(type, error_filename, error_lineno, message); } @@ -395,12 +395,11 @@ ZEND_API void zend_observer_fiber_destroy_register(zend_observer_fiber_destroy_h ZEND_API void ZEND_FASTCALL zend_observer_fiber_init_notify(zend_fiber_context *initializing) { - zend_llist_element *element; zend_observer_fiber_init_handler callback; initializing->top_observed_frame = NULL; - for (element = zend_observer_fiber_init.head; element; element = element->next) { + for (const zend_llist_element *element = zend_observer_fiber_init.head; element; element = element->next) { callback = *(zend_observer_fiber_init_handler *) element->data; callback(initializing); } @@ -408,14 +407,13 @@ ZEND_API void ZEND_FASTCALL zend_observer_fiber_init_notify(zend_fiber_context * ZEND_API void ZEND_FASTCALL zend_observer_fiber_switch_notify(zend_fiber_context *from, zend_fiber_context *to) { - zend_llist_element *element; zend_observer_fiber_switch_handler callback; if (from->status == ZEND_FIBER_STATUS_DEAD) { zend_observer_fcall_end_all(); // fiber is either finished (call will do nothing) or has bailed out } - for (element = zend_observer_fiber_switch.head; element; element = element->next) { + for (const zend_llist_element *element = zend_observer_fiber_switch.head; element; element = element->next) { callback = *(zend_observer_fiber_switch_handler *) element->data; callback(from, to); } @@ -426,10 +424,9 @@ ZEND_API void ZEND_FASTCALL zend_observer_fiber_switch_notify(zend_fiber_context ZEND_API void ZEND_FASTCALL zend_observer_fiber_destroy_notify(zend_fiber_context *destroying) { - zend_llist_element *element; zend_observer_fiber_destroy_handler callback; - for (element = zend_observer_fiber_destroy.head; element; element = element->next) { + for (const zend_llist_element *element = zend_observer_fiber_destroy.head; element; element = element->next) { callback = *(zend_observer_fiber_destroy_handler *) element->data; callback(destroying); } diff --git a/Zend/zend_observer.h b/Zend/zend_observer.h index bb8964692c370..cfec5200055af 100644 --- a/Zend/zend_observer.h +++ b/Zend/zend_observer.h @@ -74,10 +74,10 @@ ZEND_API void zend_observer_fcall_register(zend_observer_fcall_init); // Call during runtime, but only if you have used zend_observer_fcall_register. // You must not have more than one begin and one end handler active at the same time. Remove the old one first, if there is an existing one. -ZEND_API void zend_observer_add_begin_handler(zend_function *function, zend_observer_fcall_begin_handler begin); -ZEND_API bool zend_observer_remove_begin_handler(zend_function *function, zend_observer_fcall_begin_handler begin, zend_observer_fcall_begin_handler *next); -ZEND_API void zend_observer_add_end_handler(zend_function *function, zend_observer_fcall_end_handler end); -ZEND_API bool zend_observer_remove_end_handler(zend_function *function, zend_observer_fcall_end_handler end, zend_observer_fcall_end_handler *next); +ZEND_API void zend_observer_add_begin_handler(const zend_function *function, zend_observer_fcall_begin_handler begin); +ZEND_API bool zend_observer_remove_begin_handler(const zend_function *function, zend_observer_fcall_begin_handler begin, zend_observer_fcall_begin_handler *next); +ZEND_API void zend_observer_add_end_handler(const zend_function *function, zend_observer_fcall_end_handler end); +ZEND_API bool zend_observer_remove_end_handler(const zend_function *function, zend_observer_fcall_end_handler end, zend_observer_fcall_end_handler *next); ZEND_API void zend_observer_startup(void); // Called by engine before MINITs ZEND_API void zend_observer_post_startup(void); // Called by engine after MINITs @@ -88,13 +88,13 @@ ZEND_API void ZEND_FASTCALL zend_observer_fcall_begin(zend_execute_data *execute /* prechecked: the call is actually observed. */ ZEND_API void ZEND_FASTCALL zend_observer_fcall_begin_prechecked(zend_execute_data *execute_data, zend_observer_fcall_begin_handler *observer_data); -static zend_always_inline bool zend_observer_handler_is_unobserved(zend_observer_fcall_begin_handler *handler) { +static zend_always_inline bool zend_observer_handler_is_unobserved(const zend_observer_fcall_begin_handler *handler) { return *handler == ZEND_OBSERVER_NONE_OBSERVED; } /* Initial check for observers has not happened yet or no observers are installed. */ -static zend_always_inline bool zend_observer_fcall_has_no_observers(zend_execute_data *execute_data, bool allow_generator, zend_observer_fcall_begin_handler **handler) { - zend_function *function = EX(func); +static zend_always_inline bool zend_observer_fcall_has_no_observers(const zend_execute_data *execute_data, bool allow_generator, zend_observer_fcall_begin_handler **handler) { + const zend_function *function = EX(func); void *ZEND_MAP_PTR(runtime_cache) = ZEND_MAP_PTR(function->common.run_time_cache); if (function->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE | (allow_generator ? 0 : ZEND_ACC_GENERATOR))) { diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 01f6d924d28f6..5e9e7b20d869b 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -84,6 +84,7 @@ void init_op_array(zend_op_array *op_array, uint8_t type, int initial_ops_size) op_array->last_try_catch = 0; op_array->fn_flags = 0; + op_array->fn_flags2 = 0; op_array->last_literal = 0; op_array->literals = NULL; @@ -123,21 +124,32 @@ ZEND_API void zend_type_release(zend_type type, bool persistent) { } } -void zend_free_internal_arg_info(zend_internal_function *function) { - if ((function->fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) && - function->arg_info) { +ZEND_API void zend_free_internal_arg_info(zend_internal_function *function, + bool persistent) { + if (function->arg_info) { + ZEND_ASSERT((persistent || (function->fn_flags & ZEND_ACC_NEVER_CACHE)) + && "Functions with non-persistent arg_info must be flagged ZEND_ACC_NEVER_CACHE"); uint32_t i; uint32_t num_args = function->num_args + 1; - zend_internal_arg_info *arg_info = function->arg_info - 1; + zend_arg_info *arg_info = function->arg_info - 1; if (function->fn_flags & ZEND_ACC_VARIADIC) { num_args++; } for (i = 0 ; i < num_args; i++) { - zend_type_release(arg_info[i].type, /* persistent */ 1); + bool is_return_info = i == 0; + if (!is_return_info) { + zend_string_release_ex(arg_info[i].name, persistent); + if (arg_info[i].default_value) { + zend_string_release_ex(arg_info[i].default_value, + persistent); + } + } + zend_type_release(arg_info[i].type, persistent); } - free(arg_info); + + pefree(arg_info, persistent); } } @@ -156,7 +168,7 @@ ZEND_API void zend_function_dtor(zval *zv) /* For methods this will be called explicitly. */ if (!function->common.scope) { - zend_free_internal_arg_info(&function->internal_function); + zend_free_internal_arg_info(&function->internal_function, true); if (function->common.attributes) { zend_hash_release(function->common.attributes); @@ -396,7 +408,7 @@ ZEND_API void destroy_zend_class(zval *zv) if (prop_info->attributes) { zend_hash_release(prop_info->attributes); } - zend_type_release(prop_info->type, /* persistent */ 0); + zend_type_release(prop_info->type, /* persistent */ false); if (prop_info->hooks) { for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) { if (prop_info->hooks[i]) { @@ -463,7 +475,7 @@ ZEND_API void destroy_zend_class(zval *zv) ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop_info) { if (prop_info->ce == ce) { zend_string_release(prop_info->name); - zend_type_release(prop_info->type, /* persistent */ 1); + zend_type_release(prop_info->type, /* persistent */ true); if (prop_info->attributes) { zend_hash_release(prop_info->attributes); } @@ -473,12 +485,9 @@ ZEND_API void destroy_zend_class(zval *zv) zend_hash_destroy(&ce->properties_info); zend_string_release_ex(ce->name, 1); - /* TODO: eliminate this loop for classes without functions with arg_info / attributes */ ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, fn) { if (fn->common.scope == ce) { - if (fn->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) { - zend_free_internal_arg_info(&fn->internal_function); - } + zend_free_internal_arg_info(&fn->internal_function, true); if (fn->common.attributes) { zend_hash_release(fn->common.attributes); @@ -639,7 +648,7 @@ ZEND_API void destroy_op_array(zend_op_array *op_array) if (arg_info[i].name) { zend_string_release_ex(arg_info[i].name, 0); } - zend_type_release(arg_info[i].type, /* persistent */ 0); + zend_type_release(arg_info[i].type, /* persistent */ false); } efree(arg_info); } @@ -686,9 +695,7 @@ static void zend_extension_op_array_handler(zend_extension *extension, zend_op_a static void zend_check_finally_breakout(zend_op_array *op_array, uint32_t op_num, uint32_t dst_num) { - int i; - - for (i = 0; i < op_array->last_try_catch; i++) { + for (uint32_t i = 0; i < op_array->last_try_catch; i++) { if ((op_num < op_array->try_catch_array[i].finally_op || op_num >= op_array->try_catch_array[i].finally_end) && (dst_num >= op_array->try_catch_array[i].finally_op && @@ -903,15 +910,16 @@ 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) { - return 1; + || opline->opcode == ZEND_COPY_TMP + || opline->opcode == ZEND_EXT_STMT) { + return true; } ZEND_ASSERT(opline->opcode != ZEND_FE_FETCH_R && opline->opcode != ZEND_FE_FETCH_RW && opline->opcode != ZEND_VERIFY_RETURN_TYPE && opline->opcode != ZEND_BIND_LEXICAL && opline->opcode != ZEND_ROPE_ADD); - return 0; + return false; } /* Live ranges must be sorted by increasing start opline */ diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index bc115e1aa7866..2550fcbeb1cde 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -377,7 +377,7 @@ static zend_always_inline zend_result zendi_try_convert_scalar_to_number(zval *o static zend_never_inline zend_long ZEND_FASTCALL zendi_try_get_long(const zval *op, bool *failed) /* {{{ */ { - *failed = 0; + *failed = false; try_again: switch (Z_TYPE_P(op)) { case IS_NULL: @@ -387,12 +387,9 @@ static zend_never_inline zend_long ZEND_FASTCALL zendi_try_get_long(const zval * return 1; case IS_DOUBLE: { double dval = Z_DVAL_P(op); - zend_long lval = zend_dval_to_lval(dval); - if (!zend_is_long_compatible(dval, lval)) { - zend_incompatible_double_to_long_error(dval); - if (UNEXPECTED(EG(exception))) { - *failed = 1; - } + zend_long lval = zend_dval_to_lval_safe(dval); + if (UNEXPECTED(EG(exception))) { + *failed = true; } return lval; } @@ -408,7 +405,7 @@ static zend_never_inline zend_long ZEND_FASTCALL zendi_try_get_long(const zval * type = is_numeric_string_ex(Z_STRVAL_P(op), Z_STRLEN_P(op), &lval, &dval, /* allow errors */ true, NULL, &trailing_data); if (type == 0) { - *failed = 1; + *failed = true; return 0; } if (UNEXPECTED(trailing_data)) { @@ -417,7 +414,9 @@ static zend_never_inline zend_long ZEND_FASTCALL zendi_try_get_long(const zval * } zend_error(E_WARNING, "A non-numeric value encountered"); if (UNEXPECTED(EG(exception))) { - *failed = 1; + *failed = true; + zend_tmp_string_release(op_str); + return 0; } } if (EXPECTED(type == IS_LONG)) { @@ -428,14 +427,18 @@ static zend_never_inline zend_long ZEND_FASTCALL zendi_try_get_long(const zval * * We use use saturating conversion to emulate strtol()'s * behaviour. */ - lval = zend_dval_to_lval_cap(dval); + if (op_str == NULL) { + /* zend_dval_to_lval_cap() can emit a warning so always do the copy here */ + op_str = zend_string_copy(Z_STR_P(op)); + } + lval = zend_dval_to_lval_cap(dval, op_str); if (!zend_is_long_compatible(dval, lval)) { - zend_incompatible_string_to_long_error(op_str ? op_str : Z_STR_P(op)); + zend_incompatible_string_to_long_error(op_str); if (UNEXPECTED(EG(exception))) { - *failed = 1; + *failed = true; } } - zend_tmp_string_release(op_str); + zend_string_release(op_str); return lval; } } @@ -444,7 +447,7 @@ static zend_never_inline zend_long ZEND_FASTCALL zendi_try_get_long(const zval * zval dst; if (Z_OBJ_HT_P(op)->cast_object(Z_OBJ_P(op), &dst, IS_LONG) == FAILURE || EG(exception)) { - *failed = 1; + *failed = true; return 0; } ZEND_ASSERT(Z_TYPE(dst) == IS_LONG); @@ -452,7 +455,7 @@ static zend_never_inline zend_long ZEND_FASTCALL zendi_try_get_long(const zval * } case IS_RESOURCE: case IS_ARRAY: - *failed = 1; + *failed = true; return 0; case IS_REFERENCE: op = Z_REFVAL_P(op); @@ -571,9 +574,13 @@ ZEND_API void ZEND_FASTCALL convert_to_long(zval *op) /* {{{ */ break; case IS_LONG: break; - case IS_DOUBLE: - ZVAL_LONG(op, zend_dval_to_lval(Z_DVAL_P(op))); + case IS_DOUBLE: { + /* NAN might emit a warning */ + zend_long new_value = zend_dval_to_lval(Z_DVAL_P(op)); + zval_ptr_dtor(op); + ZVAL_LONG(op, new_value); break; + } case IS_STRING: { zend_string *str = Z_STR_P(op); @@ -669,6 +676,9 @@ ZEND_API void ZEND_FASTCALL convert_to_double(zval *op) /* {{{ */ ZEND_API void ZEND_FASTCALL convert_to_null(zval *op) /* {{{ */ { + if (UNEXPECTED(Z_TYPE_P(op) == IS_DOUBLE && zend_isnan(Z_DVAL_P(op)))) { + zend_nan_coerced_to_type_warning(IS_NULL); + } zval_ptr_dtor(op); ZVAL_NULL(op); } @@ -696,9 +706,16 @@ ZEND_API void ZEND_FASTCALL convert_to_boolean(zval *op) /* {{{ */ case IS_LONG: ZVAL_BOOL(op, Z_LVAL_P(op) ? 1 : 0); break; - case IS_DOUBLE: - ZVAL_BOOL(op, Z_DVAL_P(op) ? 1 : 0); + case IS_DOUBLE: { + /* We compute the new value before emitting the warning as the zval may change */ + bool new_value = Z_DVAL_P(op) ? true : false; + if (UNEXPECTED(zend_isnan(Z_DVAL_P(op)))) { + zend_nan_coerced_to_type_warning(_IS_BOOL); + zval_ptr_dtor(op); + } + ZVAL_BOOL(op, new_value); break; + } case IS_STRING: { zend_string *str = Z_STR_P(op); @@ -763,9 +780,13 @@ ZEND_API void ZEND_FASTCALL _convert_to_string(zval *op) /* {{{ */ case IS_LONG: ZVAL_STR(op, zend_long_to_str(Z_LVAL_P(op))); break; - case IS_DOUBLE: - ZVAL_NEW_STR(op, zend_double_to_str(Z_DVAL_P(op))); + case IS_DOUBLE: { + /* Casting NAN will cause a warning */ + zend_string *new_value = zend_double_to_str(Z_DVAL_P(op)); + zval_ptr_dtor(op); + ZVAL_NEW_STR(op, new_value); break; + } case IS_ARRAY: zend_error(E_WARNING, "Array to string conversion"); zval_ptr_dtor(op); @@ -810,6 +831,9 @@ ZEND_API bool ZEND_FASTCALL _try_convert_to_string(zval *op) /* {{{ */ static void convert_scalar_to_array(zval *op) /* {{{ */ { + if (UNEXPECTED(Z_TYPE_P(op) == IS_DOUBLE && zend_isnan(Z_DVAL_P(op)))) { + zend_nan_coerced_to_type_warning(IS_ARRAY); + } HashTable *ht = zend_new_array(1); zend_hash_index_add_new(ht, 0, op); ZVAL_ARR(op, ht); @@ -892,6 +916,11 @@ ZEND_API void ZEND_FASTCALL convert_to_object(zval *op) /* {{{ */ case IS_REFERENCE: zend_unwrap_reference(op); goto try_again; + case IS_DOUBLE: + if (UNEXPECTED(zend_isnan(Z_DVAL_P(op)))) { + zend_nan_coerced_to_type_warning(IS_OBJECT); + } + ZEND_FALLTHROUGH; default: { zval tmp; ZVAL_COPY_VALUE(&tmp, op); @@ -911,6 +940,19 @@ ZEND_API void ZEND_COLD zend_incompatible_string_to_long_error(const zend_string { zend_error(E_DEPRECATED, "Implicit conversion from float-string \"%s\" to int loses precision", ZSTR_VAL(s)); } +ZEND_API void ZEND_COLD zend_oob_double_to_long_error(double d) +{ + zend_error_unchecked(E_WARNING, "The float %.*H is not representable as an int, cast occurred", -1, d); +} +ZEND_API void ZEND_COLD zend_oob_string_to_long_error(const zend_string *s) +{ + zend_error_unchecked(E_WARNING, "The float-string \"%s\" is not representable as an int, cast occurred", ZSTR_VAL(s)); +} + +ZEND_API void ZEND_COLD zend_nan_coerced_to_type_warning(uint8_t type) +{ + zend_error(E_WARNING, "unexpected NAN value was coerced to %s", zend_get_type_by_const(type)); +} ZEND_API zend_long ZEND_FASTCALL zval_get_long_func(const zval *op, bool is_strict) /* {{{ */ { @@ -952,7 +994,7 @@ ZEND_API zend_long ZEND_FASTCALL zval_get_long_func(const zval *op, bool is_stri * behaviour. */ /* Most usages are expected to not be (int) casts */ - lval = zend_dval_to_lval_cap(dval); + lval = zend_dval_to_lval_cap(dval, Z_STR_P(op)); if (UNEXPECTED(is_strict)) { if (!zend_is_long_compatible(dval, lval)) { zend_incompatible_string_to_long_error(Z_STR_P(op)); @@ -1064,13 +1106,13 @@ static zend_always_inline zend_string* __zval_get_string_func(zval *op, bool try ZEND_API zend_string* ZEND_FASTCALL zval_get_string_func(zval *op) /* {{{ */ { - return __zval_get_string_func(op, 0); + return __zval_get_string_func(op, false); } /* }}} */ ZEND_API zend_string* ZEND_FASTCALL zval_try_get_string_func(zval *op) /* {{{ */ { - return __zval_get_string_func(op, 1); + return __zval_get_string_func(op, true); } /* }}} */ @@ -1551,7 +1593,7 @@ ZEND_API zend_result ZEND_FASTCALL boolean_xor_function(zval *result, zval *op1, } } ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BOOL_XOR); - op1_val = zval_is_true(op1); + op1_val = zend_is_true(op1); } } while (0); do { @@ -1571,7 +1613,7 @@ ZEND_API zend_result ZEND_FASTCALL boolean_xor_function(zval *result, zval *op1, } } ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BOOL_XOR); - op2_val = zval_is_true(op2); + op2_val = zend_is_true(op2); } } while (0); @@ -1599,7 +1641,7 @@ ZEND_API zend_result ZEND_FASTCALL boolean_not_function(zval *result, zval *op1) } ZEND_TRY_UNARY_OBJECT_OPERATION(ZEND_BOOL_NOT); - ZVAL_BOOL(result, !zval_is_true(op1)); + ZVAL_BOOL(result, !zend_is_true(op1)); } return SUCCESS; } @@ -1613,15 +1655,12 @@ ZEND_API zend_result ZEND_FASTCALL bitwise_not_function(zval *result, zval *op1) ZVAL_LONG(result, ~Z_LVAL_P(op1)); return SUCCESS; case IS_DOUBLE: { - zend_long lval = zend_dval_to_lval(Z_DVAL_P(op1)); - if (!zend_is_long_compatible(Z_DVAL_P(op1), lval)) { - zend_incompatible_double_to_long_error(Z_DVAL_P(op1)); - if (EG(exception)) { - if (result != op1) { - ZVAL_UNDEF(result); - } - return FAILURE; + zend_long lval = zend_dval_to_lval_safe(Z_DVAL_P(op1)); + if (EG(exception)) { + if (result != op1) { + ZVAL_UNDEF(result); } + return FAILURE; } ZVAL_LONG(result, ~lval); return SUCCESS; @@ -2246,6 +2285,8 @@ static int compare_double_to_string(double dval, zend_string *str) /* {{{ */ double str_dval; uint8_t type = is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), &str_lval, &str_dval, 0); + ZEND_ASSERT(!zend_isnan(dval)); + if (type == IS_LONG) { return ZEND_THREEWAY_COMPARE(dval, (double) str_lval); } @@ -2264,7 +2305,7 @@ static int compare_double_to_string(double dval, zend_string *str) /* {{{ */ ZEND_API int ZEND_FASTCALL zend_compare(zval *op1, zval *op2) /* {{{ */ { - int converted = 0; + bool converted = false; zval op1_copy, op2_copy; while (1) { @@ -2371,21 +2412,41 @@ ZEND_API int ZEND_FASTCALL zend_compare(zval *op1, zval *op2) /* {{{ */ } if (!converted) { - if (Z_TYPE_P(op1) < IS_TRUE) { - return zval_is_true(op2) ? -1 : 0; + /* Handle NAN */ + if (UNEXPECTED( + (Z_TYPE_P(op1) == IS_DOUBLE && zend_isnan(Z_DVAL_P(op1))) + || (Z_TYPE_P(op2) == IS_DOUBLE && zend_isnan(Z_DVAL_P(op2))) + )) { + // TODO: NAN should always be uncomparable + /* NAN used be cast to TRUE so handle this manually for the time being */ + if (Z_TYPE_P(op1) < IS_TRUE) { + return -1; + } else if (Z_TYPE_P(op1) == IS_TRUE || Z_TYPE_P(op2) == IS_TRUE) { + return 0; + } else if (Z_TYPE_P(op2) < IS_TRUE) { + return 1; + } else if (Z_TYPE_P(op1) != IS_DOUBLE) { + op1 = _zendi_convert_scalar_to_number_silent(op1, &op1_copy); + converted = true; + } else if (Z_TYPE_P(op2) != IS_DOUBLE) { + op2 = _zendi_convert_scalar_to_number_silent(op2, &op2_copy); + converted = true; + } + } else if (Z_TYPE_P(op1) < IS_TRUE) { + return zend_is_true(op2) ? -1 : 0; } else if (Z_TYPE_P(op1) == IS_TRUE) { - return zval_is_true(op2) ? 0 : 1; + return zend_is_true(op2) ? 0 : 1; } else if (Z_TYPE_P(op2) < IS_TRUE) { - return zval_is_true(op1) ? 1 : 0; + return zend_is_true(op1) ? 1 : 0; } else if (Z_TYPE_P(op2) == IS_TRUE) { - return zval_is_true(op1) ? 0 : -1; + return zend_is_true(op1) ? 0 : -1; } else { op1 = _zendi_convert_scalar_to_number_silent(op1, &op1_copy); op2 = _zendi_convert_scalar_to_number_silent(op2, &op2_copy); if (EG(exception)) { return 1; /* to stop comparison of arrays */ } - converted = 1; + converted = true; } } else if (Z_TYPE_P(op1)==IS_ARRAY) { return 1; @@ -2558,29 +2619,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; @@ -3422,7 +3477,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; } /* }}} */ @@ -3537,6 +3604,9 @@ ZEND_API zend_string* ZEND_FASTCALL zend_double_to_str(double num) int precision = (int) EG(precision); zend_gcvt(num, precision ? precision : 1, '.', 'E', buf); zend_string *str = zend_string_init(buf, strlen(buf), 0); + if (UNEXPECTED(zend_isnan(num))) { + zend_nan_coerced_to_type_warning(IS_STRING); + } GC_ADD_FLAGS(str, IS_STR_VALID_UTF8); return str; } diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index a7537d1b3ef33..ff31c84c41e5e 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -115,11 +115,29 @@ ZEND_API const char* ZEND_FASTCALL zend_memnrstr_ex(const char *haystack, const # define ZEND_DOUBLE_FITS_LONG(d) (!((d) >= (double)ZEND_LONG_MAX || (d) < (double)ZEND_LONG_MIN)) #endif +ZEND_API void zend_incompatible_double_to_long_error(double d); +ZEND_API void zend_incompatible_string_to_long_error(const zend_string *s); +ZEND_API void ZEND_COLD zend_oob_double_to_long_error(double d); +ZEND_API void ZEND_COLD zend_oob_string_to_long_error(const zend_string *s); +ZEND_API void ZEND_COLD zend_nan_coerced_to_type_warning(uint8_t type); + ZEND_API zend_long ZEND_FASTCALL zend_dval_to_lval_slow(double d); static zend_always_inline zend_long zend_dval_to_lval(double d) { - if (UNEXPECTED(!zend_finite(d)) || UNEXPECTED(zend_isnan(d))) { + if (UNEXPECTED(!zend_finite(d))) { + zend_oob_double_to_long_error(d); + return 0; + } else if (!ZEND_DOUBLE_FITS_LONG(d)) { + zend_oob_double_to_long_error(d); + return zend_dval_to_lval_slow(d); + } + return (zend_long)d; +} + +static zend_always_inline zend_long zend_dval_to_lval_silent(double d) +{ + if (UNEXPECTED(!zend_finite(d))) { return 0; } else if (!ZEND_DOUBLE_FITS_LONG(d)) { return zend_dval_to_lval_slow(d); @@ -128,11 +146,13 @@ static zend_always_inline zend_long zend_dval_to_lval(double d) } /* Used to convert a string float to integer during an (int) cast */ -static zend_always_inline zend_long zend_dval_to_lval_cap(double d) +static zend_always_inline zend_long zend_dval_to_lval_cap(double d, const zend_string *s) { - if (UNEXPECTED(!zend_finite(d)) || UNEXPECTED(zend_isnan(d))) { + if (UNEXPECTED(!zend_finite(d))) { + zend_oob_string_to_long_error(s); return 0; } else if (!ZEND_DOUBLE_FITS_LONG(d)) { + zend_oob_string_to_long_error(s); return (d > 0 ? ZEND_LONG_MAX : ZEND_LONG_MIN); } return (zend_long)d; @@ -143,13 +163,10 @@ static zend_always_inline bool zend_is_long_compatible(double d, zend_long l) { return (double)l == d; } -ZEND_API void zend_incompatible_double_to_long_error(double d); -ZEND_API void zend_incompatible_string_to_long_error(const zend_string *s); - static zend_always_inline zend_long zend_dval_to_lval_safe(double d) { zend_long l = zend_dval_to_lval(d); - if (!zend_is_long_compatible(d, l)) { + if (!zend_is_long_compatible(d, l) && ZEND_DOUBLE_FITS_LONG(d)) { zend_incompatible_double_to_long_error(d); } return l; @@ -215,7 +232,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 @@ -373,23 +390,12 @@ static zend_always_inline bool try_convert_to_string(zval *op) { return _try_convert_to_string(op); } -/* Compatibility macros for 7.2 and below */ -#define _zval_get_long(op) zval_get_long(op) -#define _zval_get_double(op) zval_get_double(op) -#define _zval_get_string(op) zval_get_string(op) -#define _zval_get_long_func(op) zval_get_long_func(op) -#define _zval_get_double_func(op) zval_get_double_func(op) -#define _zval_get_string_func(op) zval_get_string_func(op) - #define convert_to_string(op) if (Z_TYPE_P(op) != IS_STRING) { _convert_to_string((op)); } ZEND_API bool ZEND_FASTCALL zend_is_true(const zval *op); ZEND_API bool ZEND_FASTCALL zend_object_is_true(const zval *op); -#define zval_is_true(op) \ - zend_is_true(op) - static zend_always_inline bool i_zend_is_true(const zval *op) { bool result = 0; @@ -405,6 +411,9 @@ static zend_always_inline bool i_zend_is_true(const zval *op) } break; case IS_DOUBLE: + if (UNEXPECTED(zend_isnan(Z_DVAL_P(op)))) { + zend_nan_coerced_to_type_warning(_IS_BOOL); + } if (Z_DVAL_P(op)) { result = 1; } diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h index 1b28f21c39a87..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) @@ -248,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 @@ -321,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)) @@ -733,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) @@ -769,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 @@ -799,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_ptr_stack.c b/Zend/zend_ptr_stack.c index 80c77e11d73e6..fdabdeb61cef7 100644 --- a/Zend/zend_ptr_stack.c +++ b/Zend/zend_ptr_stack.c @@ -30,7 +30,7 @@ ZEND_API void zend_ptr_stack_init_ex(zend_ptr_stack *stack, bool persistent) ZEND_API void zend_ptr_stack_init(zend_ptr_stack *stack) { - zend_ptr_stack_init_ex(stack, 0); + zend_ptr_stack_init_ex(stack, false); } diff --git a/Zend/zend_simd.h b/Zend/zend_simd.h index 9bd16ce9e9afb..2f0df203733ca 100644 --- a/Zend/zend_simd.h +++ b/Zend/zend_simd.h @@ -1,17 +1,17 @@ /******************************************************************************** * MIT License * Copyright (c) 2025 Saki Takamachi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -22,389 +22,389 @@ *********************************************************************************/ - #ifndef XSSE_H - #define XSSE_H - - #define XSSE_VERSION 10000 - - #ifdef _MSC_VER - # define XSSE_FORCE_INLINE __forceinline - #elif defined(__GNUC__) || defined(__clang__) - # define XSSE_FORCE_INLINE inline __attribute__((always_inline)) - # define XSSE_HAS_MACRO_EXTENSION - #else - # define XSSE_FORCE_INLINE inline - #endif - - - #if defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) - #include - #define XSSE2 - - - #elif defined(__aarch64__) || defined(_M_ARM64) - #include - #define XSSE2 - - typedef int8x16_t __m128i; - - - /***************************************************************************** - * Load / Store * - *****************************************************************************/ - - #define _mm_set_epi8(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15) \ - ((int8x16_t) { \ - (int8_t) (x15), (int8_t) (x14), (int8_t) (x13), (int8_t) (x12), \ - (int8_t) (x11), (int8_t) (x10), (int8_t) (x9), (int8_t) (x8), \ - (int8_t) (x7), (int8_t) (x6), (int8_t) (x5), (int8_t) (x4), \ - (int8_t) (x3), (int8_t) (x2), (int8_t) (x1), (int8_t) (x0) }) - #define _mm_set_epi16(x0, x1, x2, x3, x4, x5, x6, x7) \ - (vreinterpretq_s8_s16((int16x8_t) { \ - (int16_t) (x7), (int16_t) (x6), (int16_t) (x5), (int16_t) (x4), \ - (int16_t) (x3), (int16_t) (x2), (int16_t) (x1), (int16_t) (x0) })) - #define _mm_set_epi32(x0, x1, x2, x3) \ - (vreinterpretq_s8_s32((int32x4_t) { (int32_t) (x3), (int32_t) (x2), (int32_t) (x1), (int32_t) (x0) })) - #define _mm_set_epi64x(x0, x1) (vreinterpretq_s8_s64((int64x2_t) { (int64_t) (x1), (int64_t) (x0) })) - #define _mm_set1_epi8(x) (vdupq_n_s8((int8_t) (x))) - #define _mm_set1_epi16(x) (vreinterpretq_s8_s16(vdupq_n_s16((int16_t) (x)))) - #define _mm_set1_epi32(x) (vreinterpretq_s8_s32(vdupq_n_s32((int32_t) (x)))) - #define _mm_set1_epi64x(x) (vreinterpretq_s8_s64(vdupq_n_s64((int64_t) (x)))) - - #define _mm_setr_epi8(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15) \ - ((int8x16_t) { \ - (int8_t) (x0), (int8_t) (x1), (int8_t) (x2), (int8_t) (x3), \ - (int8_t) (x4), (int8_t) (x5), (int8_t) (x6), (int8_t) (x7), \ - (int8_t) (x8), (int8_t) (x9), (int8_t) (x10), (int8_t) (x11), \ - (int8_t) (x12), (int8_t) (x13), (int8_t) (x14), (int8_t) (x15) }) - #define _mm_setr_epi16(x0, x1, x2, x3, x4, x5, x6, x7) \ - (vreinterpretq_s8_s16((int16x8_t) { \ - (int16_t) (x0), (int16_t) (x1), (int16_t) (x2), (int16_t) (x3), \ - (int16_t) (x4), (int16_t) (x5), (int16_t) (x6), (int16_t) (x7) })) - #define _mm_setr_epi32(x0, x1, x2, x3) \ - (vreinterpretq_s8_s32((int32x4_t) { (int32_t) (x0), (int32_t) (x1), (int32_t) (x2), (int32_t) (x3) })) - - #define _mm_setzero_si128() (vdupq_n_s8(0)) - - #define _mm_load_si128(x) (vld1q_s8((const int8_t *) (x))) - #define _mm_loadu_si128(x) _mm_load_si128(x) - - #define _mm_store_si128(to, x) (vst1q_s8((int8_t *) (to), x)) - #define _mm_storeu_si128(to, x) _mm_store_si128(to, x) - #define _mm_stream_si128(to, x) _mm_store_si128(to, x) - #define _mm_stream_si32(to, x) (*(volatile int32_t *)(to) = (int32_t)(x)) - - - /***************************************************************************** - * Bit shift / Bit wise * - *****************************************************************************/ - - #define _mm_or_si128(a, b) (vorrq_s8((a), (b))) - #define _mm_xor_si128(a, b) (veorq_s8((a), (b))) - #define _mm_and_si128(a, b) (vandq_s8((a), (b))) - #define _mm_andnot_si128(a, b) (vbicq_s8((b), (a))) - - #define _mm_slli_epi16(x, count) (vreinterpretq_s8_u16(vshlq_n_u16(vreinterpretq_u16_s8(x), (count)))) - #define _mm_slli_epi32(x, count) (vreinterpretq_s8_u32(vshlq_n_u32(vreinterpretq_u32_s8(x), (count)))) - #define _mm_slli_epi64(x, count) (vreinterpretq_s8_u64(vshlq_n_u64(vreinterpretq_u64_s8(x), (count)))) - static XSSE_FORCE_INLINE __m128i _mm_sll_epi16(__m128i x, __m128i count) - { - uint16_t shift = (uint16_t) (vgetq_lane_s64(vreinterpretq_s64_s8(count), 0) & 0xFFFF); - return vreinterpretq_s8_u16( - vshlq_u16(vreinterpretq_u16_s8(x), vdupq_n_s16((int16_t) shift)) - ); - } - static XSSE_FORCE_INLINE __m128i _mm_sll_epi32(__m128i x, __m128i count) - { - uint32_t shift = (uint32_t) (vgetq_lane_s64(vreinterpretq_s64_s8(count), 0) & 0xFFFFFFFF); - return vreinterpretq_s8_u32( - vshlq_u32(vreinterpretq_u32_s8(x), vdupq_n_s32((int32_t) shift)) - ); - } - static XSSE_FORCE_INLINE __m128i _mm_sll_epi64(__m128i x, __m128i count) - { - uint64_t shift = (uint64_t) vgetq_lane_s64(vreinterpretq_s64_s8(count), 0); - return vreinterpretq_s8_u64( - vshlq_u64(vreinterpretq_u64_s8(x), vdupq_n_s64((int64_t) shift)) - ); - } - - #define _mm_slli_si128(x, imm) \ - ((imm) >= 16 ? vdupq_n_s8(0) : vreinterpretq_s8_u8(vextq_u8(vdupq_n_u8(0), vreinterpretq_u8_s8(x), 16 - (imm)))) - - #define _mm_srai_epi16(x, count) (vreinterpretq_s8_s16(vshrq_n_s16(vreinterpretq_s16_s8(x), (count)))) - #define _mm_srai_epi32(x, count) (vreinterpretq_s8_s32(vshrq_n_s32(vreinterpretq_s32_s8(x), (count)))) - static inline __m128i _mm_sra_epi16(__m128i x, __m128i count) - { - uint16_t shift = (uint16_t) (vgetq_lane_s64(vreinterpretq_s64_s8(count), 0) & 0xFFFF); - return vreinterpretq_s8_s16( - vshlq_s16(vreinterpretq_s16_s8(x), vdupq_n_s16(-(int16_t) shift)) - ); - } - static inline __m128i _mm_sra_epi32(__m128i x, __m128i count) - { - uint32_t shift = (uint32_t) (vgetq_lane_s64(vreinterpretq_s64_s8(count), 0) & 0xFFFFFFFF); - return vreinterpretq_s8_s32( - vshlq_s32(vreinterpretq_s32_s8(x), vdupq_n_s32(-(int32_t) shift)) - ); - } - - #define _mm_srli_epi16(x, count) (vreinterpretq_s8_u16(vshrq_n_u16(vreinterpretq_u16_s8(x), (count)))) - #define _mm_srli_epi32(x, count) (vreinterpretq_s8_u32(vshrq_n_u32(vreinterpretq_u32_s8(x), (count)))) - #define _mm_srli_epi64(x, count) (vreinterpretq_s8_u64(vshrq_n_u64(vreinterpretq_u64_s8(x), (count)))) - static XSSE_FORCE_INLINE __m128i _mm_srl_epi16(__m128i x, __m128i count) - { - uint16_t shift = (uint16_t) (vgetq_lane_s64(vreinterpretq_s64_s8(count), 0) & 0xFFFF); - return vreinterpretq_s8_u16( - vshlq_u16(vreinterpretq_u16_s8(x), vdupq_n_s16(-(int16_t) shift)) - ); - } - static XSSE_FORCE_INLINE __m128i _mm_srl_epi32(__m128i x, __m128i count) - { - uint32_t shift = (uint32_t) (vgetq_lane_s64(vreinterpretq_s64_s8(count), 0) & 0xFFFFFFFF); - return vreinterpretq_s8_u32( - vshlq_u32(vreinterpretq_u32_s8(x), vdupq_n_s32(-(int32_t) shift)) - ); - } - static XSSE_FORCE_INLINE __m128i _mm_srl_epi64(__m128i x, __m128i count) - { - uint64_t shift = (uint64_t) vgetq_lane_s64(vreinterpretq_s64_s8(count), 0); - return vreinterpretq_s8_u64( - vshlq_u64(vreinterpretq_u64_s8(x), vdupq_n_s64(-(int64_t) shift)) - ); - } - - #define _mm_srli_si128(x, imm) \ - ((imm) >= 16 ? vdupq_n_s8(0) : vreinterpretq_s8_u8(vextq_u8(vreinterpretq_u8_s8(x), vdupq_n_u8(0), (imm)))) - - - /***************************************************************************** - * Integer Arithmetic Operations * - *****************************************************************************/ - - /** - * In practice, there is no problem, but a runtime error for signed integer overflow is triggered by UBSAN, - * so perform the calculation as unsigned. Since it is optimized at compile time, there are no unnecessary casts at runtime. - */ - #define _mm_add_epi8(a, b) (vreinterpretq_s8_u8(vaddq_u8(vreinterpretq_u8_s8(a), vreinterpretq_u8_s8(b)))) - #define _mm_add_epi16(a, b) (vreinterpretq_s8_u16(vaddq_u16(vreinterpretq_u16_s8(a), vreinterpretq_u16_s8(b)))) - #define _mm_add_epi32(a, b) (vreinterpretq_s8_u32(vaddq_u32(vreinterpretq_u32_s8(a), vreinterpretq_u32_s8(b)))) - #define _mm_add_epi64(a, b) (vreinterpretq_s8_u64(vaddq_u64(vreinterpretq_u64_s8(a), vreinterpretq_u64_s8(b)))) - - #define _mm_adds_epi8(a, b) (vqaddq_s8((a), (b))) - #define _mm_adds_epi16(a, b) (vreinterpretq_s8_s16(vqaddq_s16(vreinterpretq_s16_s8(a), vreinterpretq_s16_s8(b)))) - #define _mm_adds_epu8(a, b) (vreinterpretq_s8_u8(vqaddq_u8(vreinterpretq_u8_s8(a), vreinterpretq_u8_s8(b)))) - #define _mm_adds_epu16(a, b) (vreinterpretq_s8_u16(vqaddq_u16(vreinterpretq_u16_s8(a), vreinterpretq_u16_s8(b)))) - - #define _mm_avg_epu8(a, b) (vreinterpretq_s8_u8(vrhaddq_u8(vreinterpretq_u8_s8(a), vreinterpretq_u8_s8(b)))) - #define _mm_avg_epu16(a, b) (vreinterpretq_s8_u16(vrhaddq_u16(vreinterpretq_u16_s8(a), vreinterpretq_u16_s8(b)))) - - static XSSE_FORCE_INLINE __m128i _mm_madd_epi16(__m128i a, __m128i b) - { - int32x4_t mul_lo = vmull_s16(vget_low_s16(vreinterpretq_s16_s8(a)), vget_low_s16(vreinterpretq_s16_s8(b))); - int32x4_t mul_hi = vmull_s16(vget_high_s16(vreinterpretq_s16_s8(a)), vget_high_s16(vreinterpretq_s16_s8(b))); - - return vreinterpretq_s8_s32(vcombine_s32( - vpadd_s32(vget_low_s32(mul_lo), vget_high_s32(mul_lo)), - vpadd_s32(vget_low_s32(mul_hi), vget_high_s32(mul_hi)) - )); - } - - #define _mm_max_epu8(a, b) (vreinterpretq_s8_u8(vmaxq_u8(vreinterpretq_u8_s8(a), vreinterpretq_u8_s8(b)))) - #define _mm_max_epi16(a, b) (vreinterpretq_s8_s16(vmaxq_s16(vreinterpretq_s16_s8(a), vreinterpretq_s16_s8(b)))) - #define _mm_min_epu8(a, b) (vreinterpretq_s8_u8(vminq_u8(vreinterpretq_u8_s8(a), vreinterpretq_u8_s8(b)))) - #define _mm_min_epi16(a, b) (vreinterpretq_s8_s16(vminq_s16(vreinterpretq_s16_s8(a), vreinterpretq_s16_s8(b)))) - - static XSSE_FORCE_INLINE __m128i _mm_mulhi_epi16(__m128i a, __m128i b) - { - int32x4_t lo = vmull_s16(vget_low_s16(vreinterpretq_s16_s8(a)), vget_low_s16(vreinterpretq_s16_s8(b))); - int32x4_t hi = vmull_s16(vget_high_s16(vreinterpretq_s16_s8(a)), vget_high_s16(vreinterpretq_s16_s8(b))); - return vreinterpretq_s8_s16(vcombine_s16(vshrn_n_s32(lo, 16), vshrn_n_s32(hi, 16))); - } - static XSSE_FORCE_INLINE __m128i _mm_mulhi_epu16(__m128i a, __m128i b) - { - uint32x4_t lo = vmull_u16(vget_low_u16(vreinterpretq_u16_s8(a)), vget_low_u16(vreinterpretq_u16_s8(b))); - uint32x4_t hi = vmull_u16(vget_high_u16(vreinterpretq_u16_s8(a)), vget_high_u16(vreinterpretq_u16_s8(b))); - return vreinterpretq_s8_u16(vcombine_u16(vshrn_n_u32(lo, 16), vshrn_n_u32(hi, 16))); - } - static XSSE_FORCE_INLINE __m128i _mm_mullo_epi16(__m128i a, __m128i b) - { - int32x4_t lo = vmull_s16(vget_low_s16(vreinterpretq_s16_s8(a)), vget_low_s16(vreinterpretq_s16_s8(b))); - int32x4_t hi = vmull_s16(vget_high_s16(vreinterpretq_s16_s8(a)), vget_high_s16(vreinterpretq_s16_s8(b))); - return vreinterpretq_s8_s16(vcombine_s16(vmovn_s32(lo), vmovn_s32(hi))); - } - static XSSE_FORCE_INLINE __m128i _mm_mul_epu32(__m128i a, __m128i b) - { - uint32x4_t evens = vuzpq_u32(vreinterpretq_u32_s8(a), vreinterpretq_u32_s8(b)).val[0]; - return vreinterpretq_s8_u64(vmull_u32(vget_low_u32(evens), vget_high_u32(evens))); - } - static XSSE_FORCE_INLINE __m128i _mm_sad_epu8(__m128i a, __m128i b) - { - uint16x8_t abs_diffs_16 = vpaddlq_u8(vabdq_u8(vreinterpretq_u8_s8(a), vreinterpretq_u8_s8(b))); - uint32x4_t abs_diffs_32 = vpaddlq_u16(abs_diffs_16); - uint64x2_t abs_diffs_64 = vpaddlq_u32(abs_diffs_32); - - return vreinterpretq_s8_u16((uint16x8_t) { - (int16_t) vgetq_lane_u64(abs_diffs_64, 0), 0, 0, 0, - (int16_t) vgetq_lane_u64(abs_diffs_64, 1), 0, 0, 0 - }); - } - - #define _mm_sub_epi8(a, b) (vreinterpretq_s8_u8(vsubq_u8(vreinterpretq_u8_s8(a), vreinterpretq_u8_s8(b)))) - #define _mm_sub_epi16(a, b) (vreinterpretq_s8_u16(vsubq_u16(vreinterpretq_u16_s8(a), vreinterpretq_u16_s8(b)))) - #define _mm_sub_epi32(a, b) (vreinterpretq_s8_u32(vsubq_u32(vreinterpretq_u32_s8(a), vreinterpretq_u32_s8(b)))) - #define _mm_sub_epi64(a, b) (vreinterpretq_s8_u64(vsubq_u64(vreinterpretq_u64_s8(a), vreinterpretq_u64_s8(b)))) - - #define _mm_subs_epi8(a, b) (vqsubq_s8((a), (b))) - #define _mm_subs_epi16(a, b) (vreinterpretq_s8_s16(vqsubq_s16(vreinterpretq_s16_s8(a), vreinterpretq_s16_s8(b)))) - #define _mm_subs_epu8(a, b) (vreinterpretq_s8_u8(vqsubq_u8(vreinterpretq_u8_s8(a), vreinterpretq_u8_s8(b)))) - #define _mm_subs_epu16(a, b) (vreinterpretq_s8_u16(vqsubq_u16(vreinterpretq_u16_s8(a), vreinterpretq_u16_s8(b)))) - - - /***************************************************************************** - * Comparison * - *****************************************************************************/ - - #define _mm_cmpeq_epi8(a, b) (vreinterpretq_s8_u8(vceqq_s8((a), (b)))) - #define _mm_cmpeq_epi16(a, b) (vreinterpretq_s8_u16(vceqq_s16(vreinterpretq_s16_s8(a), vreinterpretq_s16_s8(b)))) - #define _mm_cmpeq_epi32(a, b) (vreinterpretq_s8_u32(vceqq_s32(vreinterpretq_s32_s8(a), vreinterpretq_s32_s8(b)))) - - #define _mm_cmplt_epi8(a, b) (vreinterpretq_s8_u8(vcltq_s8((a), (b)))) - #define _mm_cmplt_epi16(a, b) (vreinterpretq_s8_u16(vcltq_s16(vreinterpretq_s16_s8(a), vreinterpretq_s16_s8(b)))) - #define _mm_cmplt_epi32(a, b) (vreinterpretq_s8_u32(vcltq_s32(vreinterpretq_s32_s8(a), vreinterpretq_s32_s8(b)))) - - #define _mm_cmpgt_epi8(a, b) (vreinterpretq_s8_u8(vcgtq_s8((a), (b)))) - #define _mm_cmpgt_epi16(a, b) (vreinterpretq_s8_u16(vcgtq_s16(vreinterpretq_s16_s8(a), vreinterpretq_s16_s8(b)))) - #define _mm_cmpgt_epi32(a, b) (vreinterpretq_s8_u32(vcgtq_s32(vreinterpretq_s32_s8(a), vreinterpretq_s32_s8(b)))) - - - /***************************************************************************** - * Convert * - *****************************************************************************/ - - #define _mm_cvtsi32_si128(x) (vreinterpretq_s8_s32((int32x4_t) { (int32_t) (x), 0, 0, 0 })) - #define _mm_cvtsi64_si128(x) (vreinterpretq_s8_s64((int64x2_t) { (int64_t) (x), 0 })) - #define _mm_cvtsi128_si32(x) (vgetq_lane_s32(vreinterpretq_s32_s8(x), 0)) - #define _mm_cvtsi128_si64(x) (vgetq_lane_s64(vreinterpretq_s64_s8(x), 0)) - - - /***************************************************************************** - * Others * - *****************************************************************************/ - - #define _mm_packs_epi16(a, b) (vcombine_s8(vqmovn_s16(vreinterpretq_s16_s8(a)), vqmovn_s16(vreinterpretq_s16_s8(b)))) - #define _mm_packs_epi32(a, b) \ - (vreinterpretq_s8_s16(vcombine_s16(vqmovn_s32(vreinterpretq_s32_s8(a)), vqmovn_s32(vreinterpretq_s32_s8(b))))) - #define _mm_packus_epi16(a, b) \ - (vreinterpretq_s8_u8(vcombine_u8(vqmovun_s16(vreinterpretq_s16_s8(a)), vqmovun_s16(vreinterpretq_s16_s8(b))))) - - #define _mm_extract_epi16(x, imm) (vgetq_lane_s16(vreinterpretq_s16_s8(x), (imm))) - #define _mm_insert_epi16(x, val, imm) (vreinterpretq_s8_s16(vsetq_lane_s16((int16_t) (val), vreinterpretq_s16_s8(x), (imm)))) - - static XSSE_FORCE_INLINE int _mm_movemask_epi8(__m128i x) - { - /** - * based on code from - * https://community.arm.com/arm-community-blogs/b/servers-and-cloud-computing-blog/posts/porting-x86-vector-bitmask-optimizations-to-arm-neon - */ - uint16x8_t high_bits = vreinterpretq_u16_u8(vshrq_n_u8(vreinterpretq_u8_s8(x), 7)); - uint32x4_t paired16 = vreinterpretq_u32_u16(vsraq_n_u16(high_bits, high_bits, 7)); - uint64x2_t paired32 = vreinterpretq_u64_u32(vsraq_n_u32(paired16, paired16, 14)); - uint8x16_t paired64 = vreinterpretq_u8_u64(vsraq_n_u64(paired32, paired32, 28)); - return vgetq_lane_u8(paired64, 0) | ((int) vgetq_lane_u8(paired64, 8) << 8); - } - - #define _MM_SHUFFLE(a, b, c, d) (((a) << 6) | ((b) << 4) | ((c) << 2) | (d)) - #ifdef XSSE_HAS_MACRO_EXTENSION - #define _mm_shuffle_epi32(x, imm) __extension__({ \ - int32x4_t __xsse_tmp = vreinterpretq_s32_s8(x); \ - vreinterpretq_s8_s32((int32x4_t) { \ - (int32_t) vgetq_lane_s32(__xsse_tmp, ((imm) >> 0) & 0x3), \ - (int32_t) vgetq_lane_s32(__xsse_tmp, ((imm) >> 2) & 0x3), \ - (int32_t) vgetq_lane_s32(__xsse_tmp, ((imm) >> 4) & 0x3), \ - (int32_t) vgetq_lane_s32(__xsse_tmp, ((imm) >> 6) & 0x3) \ - }); \ - }) - #define _mm_shufflehi_epi16(x, imm) __extension__({ \ - int16x8_t __xsse_tmp = vreinterpretq_s16_s8(x); \ - vreinterpretq_s8_s16(vcombine_s16( \ - vget_low_s16(__xsse_tmp), \ - (int16x4_t) { \ - (int16_t) vgetq_lane_s16(__xsse_tmp, (((imm) >> 0) & 0x3) + 4), \ - (int16_t) vgetq_lane_s16(__xsse_tmp, (((imm) >> 2) & 0x3) + 4), \ - (int16_t) vgetq_lane_s16(__xsse_tmp, (((imm) >> 4) & 0x3) + 4), \ - (int16_t) vgetq_lane_s16(__xsse_tmp, (((imm) >> 6) & 0x3) + 4) \ - } \ - )); \ - }) - #define _mm_shufflelo_epi16(x, imm) __extension__({ \ - int16x8_t __xsse_tmp = vreinterpretq_s16_s8(x); \ - vreinterpretq_s8_s16(vcombine_s16( \ - (int16x4_t) { \ - (int16_t) vgetq_lane_s16(__xsse_tmp, (((imm) >> 0) & 0x3)), \ - (int16_t) vgetq_lane_s16(__xsse_tmp, (((imm) >> 2) & 0x3)), \ - (int16_t) vgetq_lane_s16(__xsse_tmp, (((imm) >> 4) & 0x3)), \ - (int16_t) vgetq_lane_s16(__xsse_tmp, (((imm) >> 6) & 0x3)) \ - }, \ - vget_high_s16(__xsse_tmp) \ - )); \ - }) - #else - static XSSE_FORCE_INLINE __m128i _mm_shuffle_epi32(__m128i x, int imm) - { - int32x4_t vec = vreinterpretq_s32_s8(x); - int32_t arr[4]; - vst1q_s32(arr, vec); - - return vreinterpretq_s8_s32((int32x4_t) { - arr[(imm >> 0) & 0x3], - arr[(imm >> 2) & 0x3], - arr[(imm >> 4) & 0x3], - arr[(imm >> 6) & 0x3] - }); - } - static XSSE_FORCE_INLINE __m128i _mm_shufflehi_epi16(__m128i x, int imm) - { - int16x8_t vec = vreinterpretq_s16_s8(x); - int16_t arr[8]; - vst1q_s16(arr, vec); - - return vreinterpretq_s8_s16((int16x8_t) { - arr[0], arr[1], arr[2], arr[3], - arr[((imm >> 0) & 0x3) + 4], - arr[((imm >> 2) & 0x3) + 4], - arr[((imm >> 4) & 0x3) + 4], - arr[((imm >> 6) & 0x3) + 4] - }); - } - static XSSE_FORCE_INLINE __m128i _mm_shufflelo_epi16(__m128i x, int imm) - { - int16x8_t vec = vreinterpretq_s16_s8(x); - int16_t arr[8]; - vst1q_s16(arr, vec); - - return vreinterpretq_s8_s16((int16x8_t) { - arr[((imm >> 0) & 0x3)], - arr[((imm >> 2) & 0x3)], - arr[((imm >> 4) & 0x3)], - arr[((imm >> 6) & 0x3)], - arr[4], arr[5], arr[6], arr[7] - }); - } - #endif - - #define _mm_unpackhi_epi8(a, b) (vzip2q_s8((a), (b))) - #define _mm_unpackhi_epi16(a, b) (vreinterpretq_s8_s16(vzip2q_s16(vreinterpretq_s16_s8(a), vreinterpretq_s16_s8(b)))) - #define _mm_unpackhi_epi32(a, b) (vreinterpretq_s8_s32(vzip2q_s32(vreinterpretq_s32_s8(a), vreinterpretq_s32_s8(b)))) - #define _mm_unpackhi_epi64(a, b) (vreinterpretq_s8_s64(vzip2q_s64(vreinterpretq_s64_s8(a), vreinterpretq_s64_s8(b)))) - - #define _mm_unpacklo_epi8(a, b) (vzip1q_s8((a), (b))) - #define _mm_unpacklo_epi16(a, b) (vreinterpretq_s8_s16(vzip1q_s16(vreinterpretq_s16_s8(a), vreinterpretq_s16_s8(b)))) - #define _mm_unpacklo_epi32(a, b) (vreinterpretq_s8_s32(vzip1q_s32(vreinterpretq_s32_s8(a), vreinterpretq_s32_s8(b)))) - #define _mm_unpacklo_epi64(a, b) (vreinterpretq_s8_s64(vzip1q_s64(vreinterpretq_s64_s8(a), vreinterpretq_s64_s8(b)))) - - #define _mm_move_epi64(x) (vreinterpretq_s8_s64((int64x2_t) { vgetq_lane_s64(vreinterpretq_s64_s8(x), 0), 0 })) - - #endif - - #endif /* XSSE_H */ +#ifndef XSSE_H +#define XSSE_H + +#define XSSE_VERSION 10000 + +#ifdef _MSC_VER +# define XSSE_FORCE_INLINE __forceinline +#elif defined(__GNUC__) || defined(__clang__) +# define XSSE_FORCE_INLINE inline __attribute__((always_inline)) +# define XSSE_HAS_MACRO_EXTENSION +#else +# define XSSE_FORCE_INLINE inline +#endif + + +#if defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) +#include +#define XSSE2 + + +#elif defined(__aarch64__) || defined(_M_ARM64) +#include +#define XSSE2 + +typedef int8x16_t __m128i; + + +/***************************************************************************** + * Load / Store * + *****************************************************************************/ + +#define _mm_set_epi8(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15) \ + ((int8x16_t) { \ + (int8_t) (x15), (int8_t) (x14), (int8_t) (x13), (int8_t) (x12), \ + (int8_t) (x11), (int8_t) (x10), (int8_t) (x9), (int8_t) (x8), \ + (int8_t) (x7), (int8_t) (x6), (int8_t) (x5), (int8_t) (x4), \ + (int8_t) (x3), (int8_t) (x2), (int8_t) (x1), (int8_t) (x0) }) +#define _mm_set_epi16(x0, x1, x2, x3, x4, x5, x6, x7) \ + (vreinterpretq_s8_s16((int16x8_t) { \ + (int16_t) (x7), (int16_t) (x6), (int16_t) (x5), (int16_t) (x4), \ + (int16_t) (x3), (int16_t) (x2), (int16_t) (x1), (int16_t) (x0) })) +#define _mm_set_epi32(x0, x1, x2, x3) \ + (vreinterpretq_s8_s32((int32x4_t) { (int32_t) (x3), (int32_t) (x2), (int32_t) (x1), (int32_t) (x0) })) +#define _mm_set_epi64x(x0, x1) (vreinterpretq_s8_s64((int64x2_t) { (int64_t) (x1), (int64_t) (x0) })) +#define _mm_set1_epi8(x) (vdupq_n_s8((int8_t) (x))) +#define _mm_set1_epi16(x) (vreinterpretq_s8_s16(vdupq_n_s16((int16_t) (x)))) +#define _mm_set1_epi32(x) (vreinterpretq_s8_s32(vdupq_n_s32((int32_t) (x)))) +#define _mm_set1_epi64x(x) (vreinterpretq_s8_s64(vdupq_n_s64((int64_t) (x)))) + +#define _mm_setr_epi8(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15) \ + ((int8x16_t) { \ + (int8_t) (x0), (int8_t) (x1), (int8_t) (x2), (int8_t) (x3), \ + (int8_t) (x4), (int8_t) (x5), (int8_t) (x6), (int8_t) (x7), \ + (int8_t) (x8), (int8_t) (x9), (int8_t) (x10), (int8_t) (x11), \ + (int8_t) (x12), (int8_t) (x13), (int8_t) (x14), (int8_t) (x15) }) +#define _mm_setr_epi16(x0, x1, x2, x3, x4, x5, x6, x7) \ + (vreinterpretq_s8_s16((int16x8_t) { \ + (int16_t) (x0), (int16_t) (x1), (int16_t) (x2), (int16_t) (x3), \ + (int16_t) (x4), (int16_t) (x5), (int16_t) (x6), (int16_t) (x7) })) +#define _mm_setr_epi32(x0, x1, x2, x3) \ + (vreinterpretq_s8_s32((int32x4_t) { (int32_t) (x0), (int32_t) (x1), (int32_t) (x2), (int32_t) (x3) })) + +#define _mm_setzero_si128() (vdupq_n_s8(0)) + +#define _mm_load_si128(x) (vld1q_s8((const int8_t *) (x))) +#define _mm_loadu_si128(x) _mm_load_si128(x) + +#define _mm_store_si128(to, x) (vst1q_s8((int8_t *) (to), x)) +#define _mm_storeu_si128(to, x) _mm_store_si128(to, x) +#define _mm_stream_si128(to, x) _mm_store_si128(to, x) +#define _mm_stream_si32(to, x) (*(volatile int32_t *)(to) = (int32_t)(x)) + + +/***************************************************************************** + * Bit shift / Bit wise * + *****************************************************************************/ + +#define _mm_or_si128(a, b) (vorrq_s8((a), (b))) +#define _mm_xor_si128(a, b) (veorq_s8((a), (b))) +#define _mm_and_si128(a, b) (vandq_s8((a), (b))) +#define _mm_andnot_si128(a, b) (vbicq_s8((b), (a))) + +#define _mm_slli_epi16(x, count) (vreinterpretq_s8_u16(vshlq_n_u16(vreinterpretq_u16_s8(x), (count)))) +#define _mm_slli_epi32(x, count) (vreinterpretq_s8_u32(vshlq_n_u32(vreinterpretq_u32_s8(x), (count)))) +#define _mm_slli_epi64(x, count) (vreinterpretq_s8_u64(vshlq_n_u64(vreinterpretq_u64_s8(x), (count)))) +static XSSE_FORCE_INLINE __m128i _mm_sll_epi16(__m128i x, __m128i count) +{ + uint16_t shift = (uint16_t) (vgetq_lane_s64(vreinterpretq_s64_s8(count), 0) & 0xFFFF); + return vreinterpretq_s8_u16( + vshlq_u16(vreinterpretq_u16_s8(x), vdupq_n_s16((int16_t) shift)) + ); +} +static XSSE_FORCE_INLINE __m128i _mm_sll_epi32(__m128i x, __m128i count) +{ + uint32_t shift = (uint32_t) (vgetq_lane_s64(vreinterpretq_s64_s8(count), 0) & 0xFFFFFFFF); + return vreinterpretq_s8_u32( + vshlq_u32(vreinterpretq_u32_s8(x), vdupq_n_s32((int32_t) shift)) + ); +} +static XSSE_FORCE_INLINE __m128i _mm_sll_epi64(__m128i x, __m128i count) +{ + uint64_t shift = (uint64_t) vgetq_lane_s64(vreinterpretq_s64_s8(count), 0); + return vreinterpretq_s8_u64( + vshlq_u64(vreinterpretq_u64_s8(x), vdupq_n_s64((int64_t) shift)) + ); +} + +#define _mm_slli_si128(x, imm) \ + ((imm) >= 16 ? vdupq_n_s8(0) : vreinterpretq_s8_u8(vextq_u8(vdupq_n_u8(0), vreinterpretq_u8_s8(x), 16 - (imm)))) + +#define _mm_srai_epi16(x, count) (vreinterpretq_s8_s16(vshrq_n_s16(vreinterpretq_s16_s8(x), (count)))) +#define _mm_srai_epi32(x, count) (vreinterpretq_s8_s32(vshrq_n_s32(vreinterpretq_s32_s8(x), (count)))) +static inline __m128i _mm_sra_epi16(__m128i x, __m128i count) +{ + uint16_t shift = (uint16_t) (vgetq_lane_s64(vreinterpretq_s64_s8(count), 0) & 0xFFFF); + return vreinterpretq_s8_s16( + vshlq_s16(vreinterpretq_s16_s8(x), vdupq_n_s16(-(int16_t) shift)) + ); +} +static inline __m128i _mm_sra_epi32(__m128i x, __m128i count) +{ + uint32_t shift = (uint32_t) (vgetq_lane_s64(vreinterpretq_s64_s8(count), 0) & 0xFFFFFFFF); + return vreinterpretq_s8_s32( + vshlq_s32(vreinterpretq_s32_s8(x), vdupq_n_s32(-(int32_t) shift)) + ); +} + +#define _mm_srli_epi16(x, count) (vreinterpretq_s8_u16(vshrq_n_u16(vreinterpretq_u16_s8(x), (count)))) +#define _mm_srli_epi32(x, count) (vreinterpretq_s8_u32(vshrq_n_u32(vreinterpretq_u32_s8(x), (count)))) +#define _mm_srli_epi64(x, count) (vreinterpretq_s8_u64(vshrq_n_u64(vreinterpretq_u64_s8(x), (count)))) +static XSSE_FORCE_INLINE __m128i _mm_srl_epi16(__m128i x, __m128i count) +{ + uint16_t shift = (uint16_t) (vgetq_lane_s64(vreinterpretq_s64_s8(count), 0) & 0xFFFF); + return vreinterpretq_s8_u16( + vshlq_u16(vreinterpretq_u16_s8(x), vdupq_n_s16(-(int16_t) shift)) + ); +} +static XSSE_FORCE_INLINE __m128i _mm_srl_epi32(__m128i x, __m128i count) +{ + uint32_t shift = (uint32_t) (vgetq_lane_s64(vreinterpretq_s64_s8(count), 0) & 0xFFFFFFFF); + return vreinterpretq_s8_u32( + vshlq_u32(vreinterpretq_u32_s8(x), vdupq_n_s32(-(int32_t) shift)) + ); +} +static XSSE_FORCE_INLINE __m128i _mm_srl_epi64(__m128i x, __m128i count) +{ + uint64_t shift = (uint64_t) vgetq_lane_s64(vreinterpretq_s64_s8(count), 0); + return vreinterpretq_s8_u64( + vshlq_u64(vreinterpretq_u64_s8(x), vdupq_n_s64(-(int64_t) shift)) + ); +} + +#define _mm_srli_si128(x, imm) \ + ((imm) >= 16 ? vdupq_n_s8(0) : vreinterpretq_s8_u8(vextq_u8(vreinterpretq_u8_s8(x), vdupq_n_u8(0), (imm)))) + + +/***************************************************************************** + * Integer Arithmetic Operations * + *****************************************************************************/ + +/** + * In practice, there is no problem, but a runtime error for signed integer overflow is triggered by UBSAN, + * so perform the calculation as unsigned. Since it is optimized at compile time, there are no unnecessary casts at runtime. + */ +#define _mm_add_epi8(a, b) (vreinterpretq_s8_u8(vaddq_u8(vreinterpretq_u8_s8(a), vreinterpretq_u8_s8(b)))) +#define _mm_add_epi16(a, b) (vreinterpretq_s8_u16(vaddq_u16(vreinterpretq_u16_s8(a), vreinterpretq_u16_s8(b)))) +#define _mm_add_epi32(a, b) (vreinterpretq_s8_u32(vaddq_u32(vreinterpretq_u32_s8(a), vreinterpretq_u32_s8(b)))) +#define _mm_add_epi64(a, b) (vreinterpretq_s8_u64(vaddq_u64(vreinterpretq_u64_s8(a), vreinterpretq_u64_s8(b)))) + +#define _mm_adds_epi8(a, b) (vqaddq_s8((a), (b))) +#define _mm_adds_epi16(a, b) (vreinterpretq_s8_s16(vqaddq_s16(vreinterpretq_s16_s8(a), vreinterpretq_s16_s8(b)))) +#define _mm_adds_epu8(a, b) (vreinterpretq_s8_u8(vqaddq_u8(vreinterpretq_u8_s8(a), vreinterpretq_u8_s8(b)))) +#define _mm_adds_epu16(a, b) (vreinterpretq_s8_u16(vqaddq_u16(vreinterpretq_u16_s8(a), vreinterpretq_u16_s8(b)))) + +#define _mm_avg_epu8(a, b) (vreinterpretq_s8_u8(vrhaddq_u8(vreinterpretq_u8_s8(a), vreinterpretq_u8_s8(b)))) +#define _mm_avg_epu16(a, b) (vreinterpretq_s8_u16(vrhaddq_u16(vreinterpretq_u16_s8(a), vreinterpretq_u16_s8(b)))) + +static XSSE_FORCE_INLINE __m128i _mm_madd_epi16(__m128i a, __m128i b) +{ + int32x4_t mul_lo = vmull_s16(vget_low_s16(vreinterpretq_s16_s8(a)), vget_low_s16(vreinterpretq_s16_s8(b))); + int32x4_t mul_hi = vmull_s16(vget_high_s16(vreinterpretq_s16_s8(a)), vget_high_s16(vreinterpretq_s16_s8(b))); + + return vreinterpretq_s8_s32(vcombine_s32( + vpadd_s32(vget_low_s32(mul_lo), vget_high_s32(mul_lo)), + vpadd_s32(vget_low_s32(mul_hi), vget_high_s32(mul_hi)) + )); +} + +#define _mm_max_epu8(a, b) (vreinterpretq_s8_u8(vmaxq_u8(vreinterpretq_u8_s8(a), vreinterpretq_u8_s8(b)))) +#define _mm_max_epi16(a, b) (vreinterpretq_s8_s16(vmaxq_s16(vreinterpretq_s16_s8(a), vreinterpretq_s16_s8(b)))) +#define _mm_min_epu8(a, b) (vreinterpretq_s8_u8(vminq_u8(vreinterpretq_u8_s8(a), vreinterpretq_u8_s8(b)))) +#define _mm_min_epi16(a, b) (vreinterpretq_s8_s16(vminq_s16(vreinterpretq_s16_s8(a), vreinterpretq_s16_s8(b)))) + +static XSSE_FORCE_INLINE __m128i _mm_mulhi_epi16(__m128i a, __m128i b) +{ + int32x4_t lo = vmull_s16(vget_low_s16(vreinterpretq_s16_s8(a)), vget_low_s16(vreinterpretq_s16_s8(b))); + int32x4_t hi = vmull_s16(vget_high_s16(vreinterpretq_s16_s8(a)), vget_high_s16(vreinterpretq_s16_s8(b))); + return vreinterpretq_s8_s16(vcombine_s16(vshrn_n_s32(lo, 16), vshrn_n_s32(hi, 16))); +} +static XSSE_FORCE_INLINE __m128i _mm_mulhi_epu16(__m128i a, __m128i b) +{ + uint32x4_t lo = vmull_u16(vget_low_u16(vreinterpretq_u16_s8(a)), vget_low_u16(vreinterpretq_u16_s8(b))); + uint32x4_t hi = vmull_u16(vget_high_u16(vreinterpretq_u16_s8(a)), vget_high_u16(vreinterpretq_u16_s8(b))); + return vreinterpretq_s8_u16(vcombine_u16(vshrn_n_u32(lo, 16), vshrn_n_u32(hi, 16))); +} +static XSSE_FORCE_INLINE __m128i _mm_mullo_epi16(__m128i a, __m128i b) +{ + int32x4_t lo = vmull_s16(vget_low_s16(vreinterpretq_s16_s8(a)), vget_low_s16(vreinterpretq_s16_s8(b))); + int32x4_t hi = vmull_s16(vget_high_s16(vreinterpretq_s16_s8(a)), vget_high_s16(vreinterpretq_s16_s8(b))); + return vreinterpretq_s8_s16(vcombine_s16(vmovn_s32(lo), vmovn_s32(hi))); +} +static XSSE_FORCE_INLINE __m128i _mm_mul_epu32(__m128i a, __m128i b) +{ + uint32x4_t evens = vuzpq_u32(vreinterpretq_u32_s8(a), vreinterpretq_u32_s8(b)).val[0]; + return vreinterpretq_s8_u64(vmull_u32(vget_low_u32(evens), vget_high_u32(evens))); +} +static XSSE_FORCE_INLINE __m128i _mm_sad_epu8(__m128i a, __m128i b) +{ + uint16x8_t abs_diffs_16 = vpaddlq_u8(vabdq_u8(vreinterpretq_u8_s8(a), vreinterpretq_u8_s8(b))); + uint32x4_t abs_diffs_32 = vpaddlq_u16(abs_diffs_16); + uint64x2_t abs_diffs_64 = vpaddlq_u32(abs_diffs_32); + + return vreinterpretq_s8_u16((uint16x8_t) { + (int16_t) vgetq_lane_u64(abs_diffs_64, 0), 0, 0, 0, + (int16_t) vgetq_lane_u64(abs_diffs_64, 1), 0, 0, 0 + }); +} + +#define _mm_sub_epi8(a, b) (vreinterpretq_s8_u8(vsubq_u8(vreinterpretq_u8_s8(a), vreinterpretq_u8_s8(b)))) +#define _mm_sub_epi16(a, b) (vreinterpretq_s8_u16(vsubq_u16(vreinterpretq_u16_s8(a), vreinterpretq_u16_s8(b)))) +#define _mm_sub_epi32(a, b) (vreinterpretq_s8_u32(vsubq_u32(vreinterpretq_u32_s8(a), vreinterpretq_u32_s8(b)))) +#define _mm_sub_epi64(a, b) (vreinterpretq_s8_u64(vsubq_u64(vreinterpretq_u64_s8(a), vreinterpretq_u64_s8(b)))) + +#define _mm_subs_epi8(a, b) (vqsubq_s8((a), (b))) +#define _mm_subs_epi16(a, b) (vreinterpretq_s8_s16(vqsubq_s16(vreinterpretq_s16_s8(a), vreinterpretq_s16_s8(b)))) +#define _mm_subs_epu8(a, b) (vreinterpretq_s8_u8(vqsubq_u8(vreinterpretq_u8_s8(a), vreinterpretq_u8_s8(b)))) +#define _mm_subs_epu16(a, b) (vreinterpretq_s8_u16(vqsubq_u16(vreinterpretq_u16_s8(a), vreinterpretq_u16_s8(b)))) + + +/***************************************************************************** + * Comparison * + *****************************************************************************/ + +#define _mm_cmpeq_epi8(a, b) (vreinterpretq_s8_u8(vceqq_s8((a), (b)))) +#define _mm_cmpeq_epi16(a, b) (vreinterpretq_s8_u16(vceqq_s16(vreinterpretq_s16_s8(a), vreinterpretq_s16_s8(b)))) +#define _mm_cmpeq_epi32(a, b) (vreinterpretq_s8_u32(vceqq_s32(vreinterpretq_s32_s8(a), vreinterpretq_s32_s8(b)))) + +#define _mm_cmplt_epi8(a, b) (vreinterpretq_s8_u8(vcltq_s8((a), (b)))) +#define _mm_cmplt_epi16(a, b) (vreinterpretq_s8_u16(vcltq_s16(vreinterpretq_s16_s8(a), vreinterpretq_s16_s8(b)))) +#define _mm_cmplt_epi32(a, b) (vreinterpretq_s8_u32(vcltq_s32(vreinterpretq_s32_s8(a), vreinterpretq_s32_s8(b)))) + +#define _mm_cmpgt_epi8(a, b) (vreinterpretq_s8_u8(vcgtq_s8((a), (b)))) +#define _mm_cmpgt_epi16(a, b) (vreinterpretq_s8_u16(vcgtq_s16(vreinterpretq_s16_s8(a), vreinterpretq_s16_s8(b)))) +#define _mm_cmpgt_epi32(a, b) (vreinterpretq_s8_u32(vcgtq_s32(vreinterpretq_s32_s8(a), vreinterpretq_s32_s8(b)))) + + +/***************************************************************************** + * Convert * + *****************************************************************************/ + +#define _mm_cvtsi32_si128(x) (vreinterpretq_s8_s32((int32x4_t) { (int32_t) (x), 0, 0, 0 })) +#define _mm_cvtsi64_si128(x) (vreinterpretq_s8_s64((int64x2_t) { (int64_t) (x), 0 })) +#define _mm_cvtsi128_si32(x) (vgetq_lane_s32(vreinterpretq_s32_s8(x), 0)) +#define _mm_cvtsi128_si64(x) (vgetq_lane_s64(vreinterpretq_s64_s8(x), 0)) + + +/***************************************************************************** + * Others * + *****************************************************************************/ + +#define _mm_packs_epi16(a, b) (vcombine_s8(vqmovn_s16(vreinterpretq_s16_s8(a)), vqmovn_s16(vreinterpretq_s16_s8(b)))) +#define _mm_packs_epi32(a, b) \ + (vreinterpretq_s8_s16(vcombine_s16(vqmovn_s32(vreinterpretq_s32_s8(a)), vqmovn_s32(vreinterpretq_s32_s8(b))))) +#define _mm_packus_epi16(a, b) \ + (vreinterpretq_s8_u8(vcombine_u8(vqmovun_s16(vreinterpretq_s16_s8(a)), vqmovun_s16(vreinterpretq_s16_s8(b))))) + +#define _mm_extract_epi16(x, imm) (vgetq_lane_s16(vreinterpretq_s16_s8(x), (imm))) +#define _mm_insert_epi16(x, val, imm) (vreinterpretq_s8_s16(vsetq_lane_s16((int16_t) (val), vreinterpretq_s16_s8(x), (imm)))) + +static XSSE_FORCE_INLINE int _mm_movemask_epi8(__m128i x) +{ + /** + * based on code from + * https://community.arm.com/arm-community-blogs/b/servers-and-cloud-computing-blog/posts/porting-x86-vector-bitmask-optimizations-to-arm-neon + */ + uint16x8_t high_bits = vreinterpretq_u16_u8(vshrq_n_u8(vreinterpretq_u8_s8(x), 7)); + uint32x4_t paired16 = vreinterpretq_u32_u16(vsraq_n_u16(high_bits, high_bits, 7)); + uint64x2_t paired32 = vreinterpretq_u64_u32(vsraq_n_u32(paired16, paired16, 14)); + uint8x16_t paired64 = vreinterpretq_u8_u64(vsraq_n_u64(paired32, paired32, 28)); + return vgetq_lane_u8(paired64, 0) | ((int) vgetq_lane_u8(paired64, 8) << 8); +} + +#define _MM_SHUFFLE(a, b, c, d) (((a) << 6) | ((b) << 4) | ((c) << 2) | (d)) +#ifdef XSSE_HAS_MACRO_EXTENSION +#define _mm_shuffle_epi32(x, imm) __extension__({ \ + int32x4_t __xsse_tmp = vreinterpretq_s32_s8(x); \ + vreinterpretq_s8_s32((int32x4_t) { \ + (int32_t) vgetq_lane_s32(__xsse_tmp, ((imm) >> 0) & 0x3), \ + (int32_t) vgetq_lane_s32(__xsse_tmp, ((imm) >> 2) & 0x3), \ + (int32_t) vgetq_lane_s32(__xsse_tmp, ((imm) >> 4) & 0x3), \ + (int32_t) vgetq_lane_s32(__xsse_tmp, ((imm) >> 6) & 0x3) \ + }); \ + }) +#define _mm_shufflehi_epi16(x, imm) __extension__({ \ + int16x8_t __xsse_tmp = vreinterpretq_s16_s8(x); \ + vreinterpretq_s8_s16(vcombine_s16( \ + vget_low_s16(__xsse_tmp), \ + (int16x4_t) { \ + (int16_t) vgetq_lane_s16(__xsse_tmp, (((imm) >> 0) & 0x3) + 4), \ + (int16_t) vgetq_lane_s16(__xsse_tmp, (((imm) >> 2) & 0x3) + 4), \ + (int16_t) vgetq_lane_s16(__xsse_tmp, (((imm) >> 4) & 0x3) + 4), \ + (int16_t) vgetq_lane_s16(__xsse_tmp, (((imm) >> 6) & 0x3) + 4) \ + } \ + )); \ + }) +#define _mm_shufflelo_epi16(x, imm) __extension__({ \ + int16x8_t __xsse_tmp = vreinterpretq_s16_s8(x); \ + vreinterpretq_s8_s16(vcombine_s16( \ + (int16x4_t) { \ + (int16_t) vgetq_lane_s16(__xsse_tmp, (((imm) >> 0) & 0x3)), \ + (int16_t) vgetq_lane_s16(__xsse_tmp, (((imm) >> 2) & 0x3)), \ + (int16_t) vgetq_lane_s16(__xsse_tmp, (((imm) >> 4) & 0x3)), \ + (int16_t) vgetq_lane_s16(__xsse_tmp, (((imm) >> 6) & 0x3)) \ + }, \ + vget_high_s16(__xsse_tmp) \ + )); \ + }) +#else +static XSSE_FORCE_INLINE __m128i _mm_shuffle_epi32(__m128i x, int imm) +{ + int32x4_t vec = vreinterpretq_s32_s8(x); + int32_t arr[4]; + vst1q_s32(arr, vec); + + return vreinterpretq_s8_s32((int32x4_t) { + arr[(imm >> 0) & 0x3], + arr[(imm >> 2) & 0x3], + arr[(imm >> 4) & 0x3], + arr[(imm >> 6) & 0x3] + }); +} +static XSSE_FORCE_INLINE __m128i _mm_shufflehi_epi16(__m128i x, int imm) +{ + int16x8_t vec = vreinterpretq_s16_s8(x); + int16_t arr[8]; + vst1q_s16(arr, vec); + + return vreinterpretq_s8_s16((int16x8_t) { + arr[0], arr[1], arr[2], arr[3], + arr[((imm >> 0) & 0x3) + 4], + arr[((imm >> 2) & 0x3) + 4], + arr[((imm >> 4) & 0x3) + 4], + arr[((imm >> 6) & 0x3) + 4] + }); +} +static XSSE_FORCE_INLINE __m128i _mm_shufflelo_epi16(__m128i x, int imm) +{ + int16x8_t vec = vreinterpretq_s16_s8(x); + int16_t arr[8]; + vst1q_s16(arr, vec); + + return vreinterpretq_s8_s16((int16x8_t) { + arr[((imm >> 0) & 0x3)], + arr[((imm >> 2) & 0x3)], + arr[((imm >> 4) & 0x3)], + arr[((imm >> 6) & 0x3)], + arr[4], arr[5], arr[6], arr[7] + }); +} +#endif + +#define _mm_unpackhi_epi8(a, b) (vzip2q_s8((a), (b))) +#define _mm_unpackhi_epi16(a, b) (vreinterpretq_s8_s16(vzip2q_s16(vreinterpretq_s16_s8(a), vreinterpretq_s16_s8(b)))) +#define _mm_unpackhi_epi32(a, b) (vreinterpretq_s8_s32(vzip2q_s32(vreinterpretq_s32_s8(a), vreinterpretq_s32_s8(b)))) +#define _mm_unpackhi_epi64(a, b) (vreinterpretq_s8_s64(vzip2q_s64(vreinterpretq_s64_s8(a), vreinterpretq_s64_s8(b)))) + +#define _mm_unpacklo_epi8(a, b) (vzip1q_s8((a), (b))) +#define _mm_unpacklo_epi16(a, b) (vreinterpretq_s8_s16(vzip1q_s16(vreinterpretq_s16_s8(a), vreinterpretq_s16_s8(b)))) +#define _mm_unpacklo_epi32(a, b) (vreinterpretq_s8_s32(vzip1q_s32(vreinterpretq_s32_s8(a), vreinterpretq_s32_s8(b)))) +#define _mm_unpacklo_epi64(a, b) (vreinterpretq_s8_s64(vzip1q_s64(vreinterpretq_s64_s8(a), vreinterpretq_s64_s8(b)))) + +#define _mm_move_epi64(x) (vreinterpretq_s8_s64((int64x2_t) { vgetq_lane_s64(vreinterpretq_s64_s8(x), 0), 0 })) + +#endif + +#endif /* XSSE_H */ diff --git a/Zend/zend_smart_str.c b/Zend/zend_smart_str.c index 501f6e6176c8b..c779ee5c97cab 100644 --- a/Zend/zend_smart_str.c +++ b/Zend/zend_smart_str.c @@ -208,8 +208,11 @@ ZEND_API void ZEND_FASTCALL smart_str_append_scalar(smart_str *dest, const zval break; case IS_TRUE: + smart_str_appendl(dest, "true", sizeof("true")-1); + break; + case IS_FALSE: - smart_str_appends(dest, Z_TYPE_P(value) == IS_TRUE ? "true" : "false"); + smart_str_appendl(dest, "false", sizeof("false")-1); break; case IS_DOUBLE: diff --git a/Zend/zend_string.c b/Zend/zend_string.c index c864a847af39f..ad4b9d2d6cde1 100644 --- a/Zend/zend_string.c +++ b/Zend/zend_string.c @@ -94,7 +94,7 @@ ZEND_API void zend_interned_strings_init(void) zend_empty_string = NULL; zend_known_strings = NULL; - zend_init_interned_strings_ht(&interned_strings_permanent, 1); + zend_init_interned_strings_ht(&interned_strings_permanent, true); zend_new_interned_string = zend_new_interned_string_permanent; zend_string_init_interned = zend_string_init_interned_permanent; @@ -345,7 +345,7 @@ static zend_string* ZEND_FASTCALL zend_string_init_existing_interned_request(con ZEND_API void zend_interned_strings_activate(void) { - zend_init_interned_strings_ht(&CG(interned_strings), 0); + zend_init_interned_strings_ht(&CG(interned_strings), false); } ZEND_API void zend_interned_strings_deactivate(void) @@ -500,8 +500,10 @@ ZEND_API zend_string *zend_string_concat3( return res; } -/* strlcpy and strlcat are not intercepted by msan, so we need to do it ourselves. */ -#if __has_feature(memory_sanitizer) +/* strlcpy and strlcat are not always intercepted by msan, so we need to do it + * ourselves. Apply a simple heuristic to determine the platforms that need it. + * See https://github.com/php/php-src/issues/20002. */ +#if __has_feature(memory_sanitizer) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__APPLE__) static size_t (*libc_strlcpy)(char *__restrict, const char *__restrict, size_t); size_t strlcpy(char *__restrict dest, const char *__restrict src, size_t n) { diff --git a/Zend/zend_string.h b/Zend/zend_string.h index 87f221125202c..fc7705ff78650 100644 --- a/Zend/zend_string.h +++ b/Zend/zend_string.h @@ -123,7 +123,7 @@ END_EXTERN_C() #define ZSTR_ALLOCA_FREE(str, use_heap) free_alloca(str, use_heap) -#define ZSTR_INIT_LITERAL(s, persistent) (zend_string_init((s), strlen(s), (persistent))) +#define ZSTR_INIT_LITERAL(s, persistent) (zend_string_init(("" s), sizeof(s) - 1, (persistent))) /*---*/ @@ -402,7 +402,7 @@ static zend_always_inline bool zend_string_starts_with(const zend_string *str, c } #define zend_string_starts_with_literal(str, prefix) \ - zend_string_starts_with_cstr(str, prefix, strlen(prefix)) + zend_string_starts_with_cstr(str, "" prefix, sizeof(prefix) - 1) static zend_always_inline bool zend_string_starts_with_cstr_ci(const zend_string *str, const char *prefix, size_t prefix_length) { @@ -415,7 +415,7 @@ static zend_always_inline bool zend_string_starts_with_ci(const zend_string *str } #define zend_string_starts_with_literal_ci(str, prefix) \ - zend_string_starts_with_cstr_ci(str, prefix, strlen(prefix)) + zend_string_starts_with_cstr_ci(str, "" prefix, sizeof(prefix) - 1) /* * DJBX33A (Daniel J. Bernstein, Times 33 with Addition) diff --git a/Zend/zend_strtod.c b/Zend/zend_strtod.c index 88b905ffeab40..f0a15a2f4f479 100644 --- a/Zend/zend_strtod.c +++ b/Zend/zend_strtod.c @@ -4535,10 +4535,10 @@ ZEND_API char *zend_gcvt(double value, int ndigit, char dec_point, char exponent if ((decpt >= 0 && decpt > ndigit) || decpt < -3) { /* use E-style */ /* exponential format (e.g. 1.2345e+13) */ if (--decpt < 0) { - sign = 1; + sign = true; decpt = -decpt; } else { - sign = 0; + sign = false; } src = digits; *dst++ = *src++; diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 4a6d00b9d73ea..43aa2aa86a00e 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -62,19 +62,8 @@ typedef enum { typedef ZEND_RESULT_CODE zend_result; -#ifdef ZEND_ENABLE_ZVAL_LONG64 -# ifdef ZEND_WIN32 -# define ZEND_SIZE_MAX _UI64_MAX -# else -# define ZEND_SIZE_MAX SIZE_MAX -# endif -#else -# if defined(ZEND_WIN32) -# define ZEND_SIZE_MAX _UI32_MAX -# else -# define ZEND_SIZE_MAX SIZE_MAX -# endif -#endif +/* This constant is deprecated, use SIZE_MAX instead */ +#define ZEND_SIZE_MAX SIZE_MAX #ifdef ZTS #define ZEND_TLS static TSRM_TLS @@ -753,6 +742,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_variables.h b/Zend/zend_variables.h index 1cb745ca1b1dc..d90ad9951782a 100644 --- a/Zend/zend_variables.h +++ b/Zend/zend_variables.h @@ -81,9 +81,6 @@ ZEND_API void zval_ptr_dtor(zval *zval_ptr); ZEND_API void zval_ptr_safe_dtor(zval *zval_ptr); ZEND_API void zval_internal_ptr_dtor(zval *zvalue); -/* Kept for compatibility */ -#define zval_dtor(zvalue) zval_ptr_dtor_nogc(zvalue) - ZEND_API void zval_add_ref(zval *p); END_EXTERN_C() diff --git a/Zend/zend_virtual_cwd.c b/Zend/zend_virtual_cwd.c index 366e13ce9b6ba..a9fbd5667cb8d 100644 --- a/Zend/zend_virtual_cwd.c +++ b/Zend/zend_virtual_cwd.c @@ -524,18 +524,18 @@ static size_t tsrm_realpath_r(char *path, size_t start, size_t len, int *ll, tim (i + 1 == len && path[i] == '.')) { /* remove double slashes and '.' */ len = EXPECTED(i > 0) ? i - 1 : 0; - is_dir = 1; + is_dir = true; continue; } else if (i + 2 == len && path[i] == '.' && path[i+1] == '.') { /* remove '..' and previous directory */ - is_dir = 1; + is_dir = true; if (link_is_dir) { *link_is_dir = 1; } if (i <= start + 1) { return start ? start : len; } - j = tsrm_realpath_r(path, start, i-1, ll, t, use_realpath, 1, NULL); + j = tsrm_realpath_r(path, start, i-1, ll, t, use_realpath, true, NULL); if (j > start && j != (size_t)-1) { j--; assert(i < MAXPATHLEN); @@ -948,7 +948,8 @@ static size_t tsrm_realpath_r(char *path, size_t start, size_t len, int *ll, tim j = start; } else { /* some leading directories may be inaccessible */ - j = tsrm_realpath_r(path, start, i-1, ll, t, save ? CWD_FILEPATH : use_realpath, 1, NULL); + j = tsrm_realpath_r(path, start, i-1, ll, t, save ? CWD_FILEPATH : use_realpath, true, + NULL); if (j > start && j != (size_t)-1) { path[j++] = DEFAULT_SLASH; } @@ -1138,7 +1139,7 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func add_slash = (use_realpath != CWD_REALPATH) && path_length > 0 && IS_SLASH(resolved_path[path_length-1]); t = CWDG(realpath_cache_ttl) ? 0 : -1; - path_length = tsrm_realpath_r(resolved_path, start, path_length, &ll, &t, use_realpath, 0, NULL); + path_length = tsrm_realpath_r(resolved_path, start, path_length, &ll, &t, use_realpath, false, NULL); if (path_length == (size_t)-1) { #ifdef ZEND_WIN32 diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index c0e05aef470ae..1b91f11662c7a 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 || @@ -6156,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); @@ -6269,7 +6278,21 @@ ZEND_VM_C_LABEL(num_index): } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { offset = Z_REFVAL_P(offset); ZEND_VM_C_GOTO(add_again); - } else if (Z_TYPE_P(offset) == IS_NULL) { + } else if (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } str = ZSTR_EMPTY_ALLOC(); ZEND_VM_C_GOTO(str_index); } else if (Z_TYPE_P(offset) == IS_DOUBLE) { @@ -6319,17 +6342,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; @@ -6737,7 +6765,17 @@ ZEND_VM_C_LABEL(num_index_dim): offset = Z_REFVAL_P(offset); ZEND_VM_C_GOTO(offset_again); } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + /* The array may be destroyed while throwing a warning in case the float is not representable as an int. + * Temporarily increase the refcount to detect this situation. */ + GC_TRY_ADDREF(ht); hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + break; + } + if (EG(exception)) { + break; + } ZEND_VM_C_GOTO(num_index_dim); } else if (Z_TYPE_P(offset) == IS_NULL) { key = ZSTR_EMPTY_ALLOC(); @@ -7283,7 +7321,7 @@ ZEND_VM_HANDLER(126, ZEND_FE_FETCH_RW, VAR, ANY, JMP_ADDR) while (1) { if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { /* reached end of iteration */ - ZEND_VM_C_GOTO(fe_fetch_w_exit); + ZEND_VM_C_GOTO(fe_fetch_w_exit_exc); } pos++; value = &p->val; @@ -7379,6 +7417,7 @@ ZEND_VM_HANDLER(126, ZEND_FE_FETCH_RW, VAR, ANY, JMP_ADDR) } } else { zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(array)); +ZEND_VM_C_LABEL(fe_fetch_w_exit_exc): if (UNEXPECTED(EG(exception))) { UNDEF_RESULT(); HANDLE_EXCEPTION(); @@ -7932,7 +7971,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(); } } @@ -7956,7 +7995,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(); } } @@ -7981,7 +8020,7 @@ ZEND_VM_HANDLER(105, ZEND_TICKS, ANY, ANY, NUM) { USE_OPLINE - if ((uint32_t)++EG(ticks_count) >= opline->extended_value) { + if (++EG(ticks_count) >= opline->extended_value) { EG(ticks_count) = 0; if (zend_ticks_function) { SAVE_OPLINE(); @@ -8140,7 +8179,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) } uint32_t throw_op_num = throw_op - EX(func)->op_array.opcodes; - int i, current_try_catch_offset = -1; + uint32_t 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) { @@ -8151,7 +8190,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) 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++) { + for (uint32_t 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 */ @@ -8167,7 +8206,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) } /* Find the innermost try/catch/finally the exception was thrown in */ - for (i = 0; i < EX(func)->op_array.last_try_catch; i++) { + for (uint32_t 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... */ @@ -9685,12 +9724,32 @@ ZEND_VM_HANDLER(167, ZEND_COPY_TMP, TMPVAR, UNUSED) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(202, ZEND_CALLABLE_CONVERT, UNUSED, UNUSED) +ZEND_VM_HANDLER(202, ZEND_CALLABLE_CONVERT, UNUSED, UNUSED, NUM|CACHE_SLOT) { USE_OPLINE zend_execute_data *call = EX(call); - zend_closure_from_frame(EX_VAR(opline->result.var), call); + if (opline->extended_value != (uint32_t)-1) { + zend_object *closure = CACHED_PTR(opline->extended_value); + if (closure) { + ZVAL_OBJ_COPY(EX_VAR(opline->result.var), closure); + } else { + /* Rotate the key for better hash distribution. */ + const int shift = sizeof(size_t) == 4 ? 6 : 7; + zend_ulong key = (zend_ulong)(uintptr_t)call->func; + key = (key >> shift) | (key << ((sizeof(key) * 8) - shift)); + zval *closure_zv = zend_hash_index_lookup(&EG(callable_convert_cache), key); + if (Z_TYPE_P(closure_zv) == IS_NULL) { + zend_closure_from_frame(closure_zv, call); + } + ZEND_ASSERT(Z_TYPE_P(closure_zv) == IS_OBJECT); + closure = Z_OBJ_P(closure_zv); + ZVAL_OBJ_COPY(EX_VAR(opline->result.var), closure); + CACHE_PTR(opline->extended_value, closure); + } + } else { + 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)); @@ -9741,7 +9800,7 @@ ZEND_VM_HANDLER(204, ZEND_FRAMELESS_ICALL_0, UNUSED, UNUSED, SPEC(OBSERVER)) #endif { zend_frameless_function_0 function = (zend_frameless_function_0)ZEND_FLF_HANDLER(opline); - function(EX_VAR(opline->result.var)); + function(result); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 387a05943dd19..801bf0ee69e0d 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 @@ -442,13 +441,17 @@ typedef ZEND_OPCODE_HANDLER_RET (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_H # define ZEND_VM_LEAVE() return (zend_op*)((uintptr_t)opline | ZEND_VM_ENTER_BIT) #endif #define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +#ifdef ZEND_VM_FP_GLOBAL_REG #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)); +#else +#define ZEND_VM_LOOP_INTERRUPT() opline = (zend_op*)((uintptr_t)zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU) & ~ZEND_VM_ENTER_BIT); +#endif +#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 +472,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 +493,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 +514,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 +524,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 +545,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 +566,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 +587,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 +609,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 +631,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 +653,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 +675,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 +696,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 +717,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 +738,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 +751,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 +761,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 +772,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 +827,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 +855,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 +918,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 +946,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 +969,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 +981,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 +993,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 +1003,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 +1020,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 +1057,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 +1094,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 +1106,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 +1116,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 +1133,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 +1181,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 +1323,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 +1351,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 +1367,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 +1396,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 +1417,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 +1433,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 +1462,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 +1527,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 +1548,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 +1574,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 +1604,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 +1646,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 +1665,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 +1681,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 +1717,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 +1759,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 +1778,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 +1794,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 +1830,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 +1941,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 +1988,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 +2016,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 +2037,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 +2071,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 +2118,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 +2146,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 +2167,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 +2201,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 +2327,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 +2405,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 +2417,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 +2554,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 +2635,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 +2786,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 +2796,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 +2808,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 +2820,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 +2839,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 +2855,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 +2978,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 +3030,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 +3148,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 +3168,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 +3202,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 +3214,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 +3226,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 +3238,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 +3253,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 +3263,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,11 +3274,11 @@ 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 - if ((uint32_t)++EG(ticks_count) >= opline->extended_value) { + if (++EG(ticks_count) >= opline->extended_value) { EG(ticks_count) = 0; if (zend_ticks_function) { SAVE_OPLINE(); @@ -3245,21 +3291,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,17 +3382,17 @@ 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; - int i, current_try_catch_offset = -1; + uint32_t 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) { @@ -3357,7 +3403,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER( 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++) { + for (uint32_t 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 */ @@ -3373,7 +3419,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER( } /* Find the innermost try/catch/finally the exception was thrown in */ - for (i = 0; i < EX(func)->op_array.last_try_catch; i++) { + for (uint32_t 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... */ @@ -3406,10 +3452,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 +3487,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 +3499,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 +3523,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 +3534,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 +3551,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 +3569,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 +3631,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 +3662,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 +3683,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 +3717,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 +3861,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 +3895,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 +3929,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 +3969,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 +4009,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 +4017,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 +4043,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 +4071,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 +4104,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 +4125,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 +4158,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 +4187,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 +4205,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 +4255,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 +4308,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 +4321,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 +4399,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 +4425,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 +4451,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 +4484,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 +4505,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 +4516,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 +4540,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 +4571,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 +4609,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 +4643,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 +4669,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 +4680,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 +4705,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 +4716,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 +4792,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 +4876,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 +4897,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 +4922,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 +4937,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 +5012,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 +5048,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 +5058,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 +5105,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 +5129,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 +5139,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 +5194,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 +5211,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 +5236,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 +5254,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 +5275,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,6 +5287,7 @@ 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(); } @@ -5221,6 +5298,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_ 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(); } @@ -5228,10 +5306,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_ 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; @@ -5264,6 +5343,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(); } @@ -5275,10 +5355,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; @@ -5289,6 +5370,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)); @@ -5338,8 +5420,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); @@ -5353,15 +5437,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; @@ -5444,7 +5530,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; @@ -5460,6 +5546,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); @@ -5469,6 +5556,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER( if (UNEXPECTED(EG(exception))) { UNDEF_RESULT(); + HANDLE_EXCEPTION(); } } @@ -5493,15 +5581,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) { @@ -5515,11 +5606,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; @@ -5555,6 +5647,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) { @@ -5565,6 +5658,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_ if (UNEXPECTED(EG(exception))) { UNDEF_RESULT(); + HANDLE_EXCEPTION(); } } @@ -5591,15 +5685,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) { @@ -5613,11 +5710,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; @@ -5638,6 +5736,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(); } @@ -5660,10 +5759,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; @@ -5704,7 +5804,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; @@ -5717,6 +5817,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; } } @@ -5748,7 +5849,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; @@ -5786,7 +5887,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 @@ -5795,7 +5896,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; @@ -5822,7 +5923,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); @@ -5834,6 +5935,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(); } @@ -5846,6 +5948,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) { @@ -5853,6 +5956,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); @@ -5876,6 +5980,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)); @@ -5902,6 +6007,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(); } @@ -5922,7 +6028,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; @@ -5942,6 +6048,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(); } } @@ -5981,10 +6088,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; @@ -6014,13 +6122,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; @@ -6043,7 +6152,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); @@ -6066,7 +6175,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; @@ -6076,7 +6185,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; @@ -6086,7 +6195,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; @@ -6096,7 +6205,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; @@ -6107,7 +6216,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; @@ -6115,14 +6224,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; @@ -6157,10 +6266,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; @@ -6195,10 +6304,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; @@ -6236,10 +6345,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; @@ -6250,10 +6359,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; @@ -6277,10 +6388,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; @@ -6298,10 +6409,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; @@ -6317,10 +6428,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; @@ -6331,10 +6442,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; @@ -6346,10 +6459,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; @@ -6361,10 +6476,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; @@ -6419,10 +6536,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; @@ -6477,10 +6594,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; @@ -6520,10 +6637,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; @@ -6567,10 +6684,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; @@ -6581,10 +6698,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; @@ -6599,10 +6718,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; @@ -6617,10 +6736,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; @@ -6635,10 +6754,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; @@ -6649,10 +6768,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; @@ -6684,10 +6805,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; @@ -6697,10 +6820,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 @@ -6719,7 +6844,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; @@ -6805,6 +6930,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. */ @@ -6884,10 +7011,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; @@ -7005,10 +7134,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 @@ -7025,7 +7156,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; @@ -7034,10 +7165,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; @@ -7159,10 +7291,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; @@ -7193,12 +7327,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); } @@ -7231,6 +7368,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(); } @@ -7241,6 +7379,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); @@ -7265,6 +7405,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); } @@ -7288,6 +7429,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; @@ -7317,7 +7459,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; @@ -7335,6 +7477,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) { @@ -7345,6 +7488,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 { @@ -7377,6 +7521,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); } @@ -7392,6 +7537,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 && @@ -7404,6 +7550,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)) { @@ -7450,7 +7597,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; @@ -7472,6 +7619,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(); } @@ -7494,6 +7642,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)); @@ -7510,6 +7659,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(); } @@ -7521,7 +7671,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; @@ -7533,6 +7683,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 { @@ -7549,7 +7700,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; @@ -7561,6 +7712,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 { @@ -7573,8 +7725,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); @@ -7586,7 +7738,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; @@ -7611,6 +7763,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); @@ -7620,6 +7773,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 { @@ -7637,6 +7791,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); @@ -7644,6 +7799,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 @@ -7657,6 +7813,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(); } @@ -7664,6 +7821,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(); } @@ -7681,6 +7839,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(); } } @@ -7691,6 +7850,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(); } } @@ -7698,6 +7858,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(); } } @@ -7709,16 +7870,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; @@ -7733,6 +7896,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) { @@ -7780,7 +7944,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C } 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) { + } else if (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } str = ZSTR_EMPTY_ALLOC(); goto str_index; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { @@ -7805,6 +7983,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(); @@ -7814,7 +7993,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; @@ -7836,7 +8015,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; @@ -7887,6 +8066,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 { @@ -7912,10 +8092,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; @@ -7962,10 +8144,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 @@ -7994,10 +8178,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 @@ -8008,7 +8194,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(); } } @@ -8017,7 +8203,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; @@ -8034,6 +8220,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST zval_ptr_dtor_nogc(&c.value); + + HANDLE_EXCEPTION(); } } @@ -8045,10 +8233,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST } + + 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; @@ -8065,6 +8255,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_ zval_ptr_dtor_nogc(&c.value); + + HANDLE_EXCEPTION(); } } @@ -8076,6 +8268,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_ if (registered == NULL) { + + /* two opcodes used, second one is the data with attributes */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -8085,11 +8279,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_ 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 @@ -8146,6 +8342,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); @@ -8161,6 +8358,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) { @@ -8181,6 +8379,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 ) { @@ -8208,7 +8407,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; @@ -8236,7 +8435,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; @@ -8269,7 +8468,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; @@ -8310,7 +8509,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; @@ -8337,10 +8536,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)) { @@ -8365,6 +8566,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); } } @@ -8374,15 +8576,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; @@ -8417,10 +8621,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; @@ -8455,10 +8659,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; @@ -8482,10 +8686,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; @@ -8503,10 +8707,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; @@ -8522,10 +8726,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; @@ -8565,10 +8769,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; @@ -8608,10 +8812,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; @@ -8651,10 +8855,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; @@ -8698,10 +8902,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; @@ -8745,10 +8949,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; @@ -8792,10 +8996,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; @@ -8928,7 +9132,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; @@ -8940,7 +9144,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; @@ -8952,7 +9156,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; @@ -8964,7 +9168,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; @@ -8976,7 +9180,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; @@ -8988,7 +9192,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; @@ -9000,7 +9204,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; @@ -9012,7 +9216,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; @@ -9024,7 +9228,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; @@ -9036,7 +9240,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; @@ -9048,7 +9252,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; @@ -9060,7 +9264,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; @@ -9072,7 +9276,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; @@ -9084,7 +9288,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; @@ -9096,7 +9300,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; @@ -9108,7 +9312,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; @@ -9125,6 +9329,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); @@ -9133,6 +9338,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(); @@ -9152,6 +9358,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(); } @@ -9160,10 +9367,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; @@ -9173,11 +9381,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; @@ -9187,11 +9396,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; @@ -9263,12 +9473,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; @@ -9278,11 +9489,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; @@ -9314,10 +9526,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; @@ -9327,10 +9540,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 @@ -9349,7 +9563,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; @@ -9435,6 +9649,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. */ @@ -9514,10 +9730,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; @@ -9635,10 +9852,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 @@ -9655,7 +9873,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; @@ -9667,7 +9885,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; @@ -9788,11 +10006,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; @@ -9823,12 +10042,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); } @@ -9871,6 +10092,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); @@ -9947,7 +10169,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; @@ -10080,7 +10302,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; @@ -10152,7 +10374,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; @@ -10167,6 +10389,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) { @@ -10214,7 +10437,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_T } 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) { + } else if (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } str = ZSTR_EMPTY_ALLOC(); goto str_index; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { @@ -10248,7 +10485,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; @@ -10270,7 +10507,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; @@ -10346,10 +10583,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; @@ -10396,10 +10634,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 @@ -10429,10 +10668,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 @@ -10489,6 +10729,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); @@ -10504,6 +10745,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) { @@ -10552,7 +10794,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; @@ -10576,6 +10818,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(); @@ -10638,6 +10881,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) { @@ -10653,41 +10897,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 @@ -10706,7 +10950,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; @@ -10724,6 +10968,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) { @@ -10734,6 +10979,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 { @@ -10766,6 +11012,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); } @@ -10781,6 +11028,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 && @@ -10793,6 +11041,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)) { @@ -10839,7 +11088,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(); @@ -10906,7 +11155,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; @@ -10918,6 +11167,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 { @@ -10934,7 +11184,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; @@ -10946,6 +11196,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 { @@ -10958,8 +11209,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); @@ -10971,7 +11222,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; @@ -10983,6 +11234,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 { @@ -10995,8 +11247,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); @@ -11008,7 +11260,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; @@ -11077,7 +11329,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; @@ -11092,6 +11344,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) { @@ -11139,7 +11392,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_U } 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) { + } else if (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } str = ZSTR_EMPTY_ALLOC(); goto str_index; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { @@ -11164,6 +11431,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(); @@ -11173,7 +11441,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; @@ -11195,7 +11463,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; @@ -11218,6 +11486,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(); } } @@ -11229,11 +11498,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; @@ -11257,6 +11527,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 { @@ -11277,7 +11548,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 @@ -11334,6 +11605,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); @@ -11349,6 +11621,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) { @@ -11369,6 +11642,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 ) { @@ -11396,7 +11670,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; @@ -11407,7 +11681,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; @@ -11459,10 +11733,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 @@ -11501,11 +11776,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; @@ -11520,10 +11796,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; @@ -11600,7 +11877,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(); @@ -11656,7 +11933,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; @@ -11667,10 +11944,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; @@ -11681,10 +11960,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; @@ -11757,11 +12038,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; @@ -11772,10 +12055,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; @@ -11807,10 +12092,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; @@ -11820,10 +12107,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 @@ -11842,7 +12131,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; @@ -11928,6 +12217,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. */ @@ -12007,10 +12298,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; @@ -12128,10 +12421,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 @@ -12148,7 +12443,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; @@ -12157,10 +12452,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; @@ -12282,10 +12578,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; @@ -12316,12 +12614,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); } @@ -12354,6 +12655,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(); } @@ -12364,6 +12666,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); @@ -12388,6 +12692,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); } @@ -12411,6 +12716,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; @@ -12440,7 +12746,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; @@ -12458,6 +12764,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) { @@ -12468,6 +12775,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 { @@ -12500,6 +12808,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); } @@ -12515,6 +12824,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 && @@ -12527,6 +12837,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)) { @@ -12573,7 +12884,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; @@ -12595,6 +12906,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(); } @@ -12617,6 +12929,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)); @@ -12633,6 +12946,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(); } @@ -12644,7 +12958,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; @@ -12659,6 +12973,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) { @@ -12706,7 +13021,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C } 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) { + } else if (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } str = ZSTR_EMPTY_ALLOC(); goto str_index; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { @@ -12731,6 +13060,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(); @@ -12740,7 +13070,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; @@ -12762,7 +13092,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; @@ -12813,6 +13143,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 { @@ -12838,10 +13169,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; @@ -12888,10 +13221,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 @@ -12920,10 +13255,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 @@ -12980,6 +13317,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); @@ -12995,6 +13333,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) { @@ -13015,6 +13354,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 ) { @@ -13042,7 +13382,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; @@ -13053,10 +13393,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; @@ -13066,7 +13406,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; @@ -13076,7 +13416,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; @@ -13086,7 +13426,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; @@ -13121,10 +13461,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; @@ -13159,10 +13499,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; @@ -13200,10 +13540,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; @@ -13227,10 +13567,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; @@ -13248,10 +13588,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; @@ -13267,10 +13607,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; @@ -13310,10 +13650,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; @@ -13353,10 +13693,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; @@ -13396,10 +13736,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; @@ -13443,10 +13783,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; @@ -13490,10 +13830,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; @@ -13537,10 +13877,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; @@ -13555,10 +13895,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; @@ -13573,10 +13913,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; @@ -13591,10 +13931,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; @@ -13603,10 +13943,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; @@ -13634,7 +13975,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; @@ -13667,7 +14008,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; @@ -13708,7 +14049,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; @@ -13720,7 +14061,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; @@ -13732,7 +14073,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; @@ -13744,7 +14085,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; @@ -13756,7 +14097,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; @@ -13768,7 +14109,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; @@ -13780,7 +14121,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; @@ -13792,7 +14133,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; @@ -13806,7 +14147,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; @@ -13818,7 +14159,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; @@ -13830,7 +14171,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; @@ -13842,7 +14183,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; @@ -13854,7 +14195,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; @@ -13866,7 +14207,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; @@ -13878,7 +14219,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; @@ -13890,7 +14231,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; @@ -13902,7 +14243,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; @@ -13914,7 +14255,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; @@ -13926,7 +14267,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; @@ -13938,7 +14279,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; @@ -13950,7 +14291,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; @@ -13962,7 +14303,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; @@ -13972,10 +14313,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; @@ -13985,10 +14327,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; @@ -13998,10 +14341,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; @@ -14011,10 +14355,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; @@ -14024,10 +14369,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; @@ -14037,10 +14383,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; @@ -14052,7 +14399,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; @@ -14064,7 +14411,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; @@ -14076,7 +14423,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; @@ -14088,7 +14435,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; @@ -14100,7 +14447,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; @@ -14112,7 +14459,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; @@ -14124,7 +14471,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; @@ -14136,7 +14483,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; @@ -14148,7 +14495,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; @@ -14160,7 +14507,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; @@ -14172,7 +14519,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; @@ -14184,7 +14531,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; @@ -14219,10 +14566,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; @@ -14257,10 +14604,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; @@ -14298,10 +14645,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; @@ -14325,10 +14672,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; @@ -14346,10 +14693,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; @@ -14365,10 +14712,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; @@ -14408,10 +14755,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; @@ -14451,10 +14798,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; @@ -14494,10 +14841,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; @@ -14541,10 +14888,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; @@ -14588,10 +14935,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; @@ -14635,10 +14982,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; @@ -14653,10 +15000,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; @@ -14671,10 +15018,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; @@ -14689,10 +15036,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; @@ -14704,7 +15051,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; @@ -14716,7 +15063,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; @@ -14728,7 +15075,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; @@ -14740,7 +15087,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; @@ -14752,7 +15099,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; @@ -14764,7 +15111,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; @@ -14776,7 +15123,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; @@ -14790,7 +15137,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; @@ -14802,7 +15149,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; @@ -14814,7 +15161,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; @@ -14826,7 +15173,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; @@ -14838,7 +15185,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; @@ -14850,7 +15197,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; @@ -14862,7 +15209,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; @@ -14874,7 +15221,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; @@ -14886,7 +15233,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; @@ -14898,7 +15245,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; @@ -14910,7 +15257,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; @@ -14922,7 +15269,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; @@ -14934,7 +15281,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; @@ -14946,7 +15293,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; @@ -14958,7 +15305,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; @@ -14970,7 +15317,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; @@ -14982,7 +15329,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; @@ -14994,7 +15341,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; @@ -15006,7 +15353,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; @@ -15018,7 +15365,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; @@ -15030,7 +15377,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; @@ -15042,7 +15389,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; @@ -15054,7 +15401,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; @@ -15066,7 +15413,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; @@ -15078,7 +15425,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; @@ -15090,7 +15437,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; @@ -15102,7 +15449,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; @@ -15113,7 +15460,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; @@ -15122,10 +15469,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; @@ -15151,7 +15499,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; @@ -15180,7 +15528,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; @@ -15214,7 +15562,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; @@ -15248,7 +15596,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; @@ -15284,7 +15632,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; @@ -15319,7 +15667,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 @@ -15328,7 +15676,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 @@ -15353,7 +15701,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; @@ -15389,7 +15737,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; @@ -15415,7 +15763,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; @@ -15427,7 +15775,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 || @@ -15479,7 +15828,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; @@ -15539,6 +15888,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(); @@ -15562,7 +15912,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); @@ -15664,7 +16014,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; @@ -15726,7 +16076,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; @@ -15762,7 +16112,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; @@ -15824,7 +16174,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; @@ -15835,10 +16185,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; @@ -15849,10 +16200,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; @@ -15925,11 +16277,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; @@ -15984,10 +16337,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; @@ -16042,10 +16395,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; @@ -16100,10 +16453,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; @@ -16158,10 +16511,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; @@ -16216,10 +16569,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; @@ -16274,10 +16627,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; @@ -16288,10 +16641,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; @@ -16302,10 +16656,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; @@ -16336,11 +16691,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; @@ -16349,11 +16705,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; @@ -16439,6 +16796,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. */ @@ -16517,11 +16876,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; @@ -16638,11 +16998,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; @@ -16764,10 +17125,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; @@ -16803,6 +17165,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); @@ -16836,6 +17199,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(); } @@ -16845,6 +17209,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(); } @@ -16870,6 +17235,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); } @@ -16893,6 +17259,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; @@ -16922,7 +17289,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; @@ -16950,7 +17317,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; @@ -16991,6 +17358,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 { @@ -16998,10 +17366,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; @@ -17052,6 +17420,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 { @@ -17076,11 +17445,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; @@ -17126,11 +17496,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 @@ -17158,11 +17529,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; @@ -17207,7 +17579,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; @@ -17262,7 +17634,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; @@ -17317,7 +17689,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; @@ -17331,7 +17703,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; @@ -17345,7 +17717,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; @@ -17422,7 +17794,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; @@ -17477,10 +17849,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; @@ -17535,10 +17907,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; @@ -17593,10 +17965,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; @@ -17651,10 +18023,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; @@ -17709,10 +18081,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; @@ -17767,10 +18139,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; @@ -17784,7 +18156,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; @@ -17798,7 +18170,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; @@ -17833,7 +18205,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; @@ -17846,7 +18218,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; @@ -17932,6 +18304,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. */ @@ -18014,7 +18388,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; @@ -18135,7 +18509,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; @@ -18260,7 +18634,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; @@ -18415,7 +18789,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; @@ -18463,10 +18837,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; @@ -18545,7 +18919,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; @@ -18595,7 +18969,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 @@ -18628,7 +19002,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; @@ -18673,7 +19047,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; @@ -18774,41 +19148,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; @@ -18836,7 +19210,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; @@ -18874,7 +19248,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; @@ -18919,7 +19293,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; @@ -18964,7 +19338,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; @@ -19019,7 +19393,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)); @@ -19034,7 +19408,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 @@ -19077,7 +19451,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); @@ -19086,7 +19460,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; @@ -19097,10 +19471,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; @@ -19111,10 +19486,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; @@ -19187,11 +19563,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; @@ -19202,10 +19579,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; @@ -19236,11 +19614,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; @@ -19249,11 +19628,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; @@ -19339,6 +19719,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. */ @@ -19417,11 +19799,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; @@ -19538,11 +19921,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; @@ -19664,10 +20048,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; @@ -19703,6 +20088,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); @@ -19736,6 +20122,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(); } @@ -19745,6 +20132,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(); } @@ -19770,6 +20158,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); } @@ -19793,6 +20182,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; @@ -19822,7 +20212,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; @@ -19863,6 +20253,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 { @@ -19870,10 +20261,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; @@ -19924,6 +20315,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 { @@ -19948,11 +20340,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; @@ -19998,11 +20391,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 @@ -20030,19 +20424,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(); @@ -20108,19 +20505,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)) { @@ -20172,10 +20574,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; @@ -20211,6 +20615,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 */ @@ -20220,7 +20625,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; @@ -20241,7 +20646,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; @@ -20274,6 +20679,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(); } @@ -20289,7 +20695,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; @@ -20305,6 +20711,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); @@ -20314,6 +20721,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZE if (UNEXPECTED(EG(exception))) { UNDEF_RESULT(); + HANDLE_EXCEPTION(); } } @@ -20338,11 +20746,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); @@ -20365,7 +20775,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; @@ -20401,6 +20811,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) { @@ -20411,6 +20822,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(Z if (UNEXPECTED(EG(exception))) { UNDEF_RESULT(); + HANDLE_EXCEPTION(); } } @@ -20437,11 +20849,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); @@ -20463,7 +20877,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 @@ -20474,7 +20888,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; @@ -20521,7 +20935,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; @@ -20562,7 +20976,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; @@ -20606,7 +21020,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; @@ -20644,7 +21058,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; @@ -20656,10 +21070,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; @@ -20670,10 +21085,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; @@ -20685,10 +21101,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 @@ -20707,7 +21124,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 @@ -20724,7 +21141,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; @@ -20753,13 +21170,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; @@ -20788,6 +21206,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); @@ -20819,7 +21238,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; @@ -20843,8 +21262,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); @@ -20856,7 +21275,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; @@ -20918,7 +21337,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CON } 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) { + } else if (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } str = ZSTR_EMPTY_ALLOC(); goto str_index; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { @@ -20943,6 +21376,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(); @@ -20952,7 +21386,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; @@ -20974,7 +21408,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 @@ -21047,6 +21481,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) { @@ -21067,6 +21502,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 ) { @@ -21094,7 +21530,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; @@ -21166,7 +21602,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 @@ -21185,7 +21621,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 @@ -21202,7 +21638,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; @@ -21237,7 +21673,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; @@ -21297,7 +21733,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; @@ -21359,7 +21795,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP } 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) { + } else if (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } str = ZSTR_EMPTY_ALLOC(); goto str_index; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { @@ -21393,7 +21843,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; @@ -21415,7 +21865,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 @@ -21488,6 +21938,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) { @@ -21536,7 +21987,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; @@ -21551,7 +22002,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; @@ -21565,7 +22016,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; @@ -21580,7 +22031,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; @@ -21594,7 +22045,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 @@ -21613,7 +22064,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(); @@ -21680,7 +22131,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; @@ -21704,8 +22155,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); @@ -21717,7 +22168,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; @@ -21741,8 +22192,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); @@ -21754,7 +22205,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; @@ -21816,7 +22267,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNU } 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) { + } else if (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } str = ZSTR_EMPTY_ALLOC(); goto str_index; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { @@ -21841,6 +22306,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(); @@ -21850,7 +22316,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; @@ -21872,7 +22338,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 @@ -21945,6 +22411,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) { @@ -21965,6 +22432,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 ) { @@ -21992,7 +22460,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; @@ -22010,7 +22478,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; @@ -22021,10 +22489,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 @@ -22043,7 +22512,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 @@ -22060,7 +22529,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; @@ -22089,13 +22558,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; @@ -22124,6 +22594,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); @@ -22155,7 +22626,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; @@ -22217,7 +22688,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_ } 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) { + } else if (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } str = ZSTR_EMPTY_ALLOC(); goto str_index; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { @@ -22242,6 +22727,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(); @@ -22251,7 +22737,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; @@ -22273,7 +22759,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 @@ -22346,6 +22832,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) { @@ -22366,6 +22853,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 ) { @@ -22393,7 +22881,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; @@ -22425,7 +22913,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; @@ -22458,7 +22946,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; @@ -22476,7 +22964,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; @@ -22494,7 +22982,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; @@ -22528,7 +23016,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; @@ -22546,7 +23034,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; @@ -22564,7 +23052,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; @@ -22596,7 +23084,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; @@ -22612,7 +23100,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; @@ -22644,7 +23132,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; @@ -22660,15 +23148,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(); @@ -22734,19 +23224,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)) { @@ -22798,10 +23293,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; @@ -22837,6 +23334,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 */ @@ -22846,7 +23344,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; @@ -22867,7 +23365,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; @@ -22916,7 +23414,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; @@ -22993,7 +23491,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; @@ -23092,7 +23590,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; @@ -23172,7 +23670,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; @@ -23245,7 +23743,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(Z while (1) { if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { /* reached end of iteration */ - goto fe_fetch_w_exit; + goto fe_fetch_w_exit_exc; } pos++; value = &p->val; @@ -23341,6 +23839,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(Z } } else { zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(array)); +fe_fetch_w_exit_exc: if (UNEXPECTED(EG(exception))) { UNDEF_RESULT(); HANDLE_EXCEPTION(); @@ -23374,7 +23873,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; @@ -23421,7 +23920,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; @@ -23462,7 +23961,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; @@ -23506,7 +24005,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; @@ -23544,7 +24043,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; @@ -23561,7 +24060,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; @@ -23573,10 +24072,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; @@ -23587,10 +24087,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; @@ -23602,10 +24103,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; @@ -23692,13 +24194,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; @@ -23794,11 +24297,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; @@ -23824,11 +24328,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; @@ -23888,11 +24393,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; @@ -23950,11 +24456,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; @@ -23963,13 +24470,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; @@ -23978,13 +24486,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 @@ -24003,7 +24512,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; @@ -24012,13 +24521,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; @@ -24033,13 +24543,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; @@ -24050,13 +24561,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 @@ -24073,7 +24585,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; @@ -24084,13 +24596,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; @@ -24109,10 +24622,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; @@ -24235,6 +24749,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; } @@ -24255,18 +24770,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; @@ -24414,13 +24931,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; @@ -24568,13 +25086,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; @@ -24697,6 +25216,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; } @@ -24717,18 +25237,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; @@ -24826,6 +25348,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); } @@ -24833,12 +25356,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) @@ -24846,6 +25371,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); @@ -24867,6 +25393,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)); } @@ -24874,13 +25401,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; @@ -25027,13 +25555,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; @@ -25180,13 +25709,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; @@ -25284,6 +25814,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); } @@ -25291,12 +25822,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) @@ -25304,6 +25837,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); @@ -25325,6 +25859,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)); } @@ -25332,13 +25867,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; @@ -25367,7 +25903,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; @@ -25396,7 +25932,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; @@ -25428,12 +25964,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; @@ -25466,11 +26003,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; @@ -25488,6 +26027,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) { @@ -25498,6 +26038,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 { @@ -25530,6 +26071,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); } @@ -25545,6 +26087,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 && @@ -25557,6 +26100,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)) { @@ -25603,7 +26147,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; @@ -25650,7 +26194,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; @@ -25681,7 +26225,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; @@ -25749,7 +26293,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; @@ -25779,7 +26323,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; @@ -25845,7 +26389,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; @@ -25896,7 +26440,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; @@ -25921,6 +26465,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); @@ -25930,6 +26475,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 { @@ -25947,6 +26493,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); @@ -25954,6 +26501,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 @@ -25967,6 +26515,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(); } @@ -25974,6 +26523,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(); } @@ -25991,6 +26541,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(); } } @@ -26001,6 +26552,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(); } } @@ -26008,6 +26560,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(); } } @@ -26019,16 +26572,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; @@ -26090,7 +26645,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CON } 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) { + } else if (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } str = ZSTR_EMPTY_ALLOC(); goto str_index; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { @@ -26115,6 +26684,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(); @@ -26124,7 +26694,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; @@ -26146,7 +26716,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; @@ -26184,7 +26754,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDL offset = Z_REFVAL_P(offset); goto offset_again; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + /* The array may be destroyed while throwing a warning in case the float is not representable as an int. + * Temporarily increase the refcount to detect this situation. */ + GC_TRY_ADDREF(ht); hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + break; + } + if (EG(exception)) { + break; + } goto num_index_dim; } else if (Z_TYPE_P(offset) == IS_NULL) { key = ZSTR_EMPTY_ALLOC(); @@ -26233,11 +26813,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; @@ -26277,11 +26858,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 @@ -26374,6 +26956,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 ) { @@ -26401,7 +26984,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; @@ -26473,7 +27056,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; @@ -26606,7 +27189,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; @@ -26699,7 +27282,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; @@ -26800,7 +27383,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; @@ -26831,7 +27414,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; @@ -26896,7 +27479,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; @@ -26959,7 +27542,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; @@ -26974,7 +27557,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; @@ -26989,7 +27572,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 @@ -27008,7 +27591,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; @@ -27023,7 +27606,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; @@ -27044,7 +27627,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; @@ -27061,7 +27644,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 @@ -27078,7 +27661,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; @@ -27095,7 +27678,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; @@ -27118,7 +27701,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; @@ -27241,6 +27824,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; } @@ -27261,6 +27845,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); @@ -27272,7 +27857,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; @@ -27426,7 +28011,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; @@ -27580,7 +28165,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; @@ -27703,6 +28288,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; } @@ -27723,6 +28309,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); @@ -27734,7 +28321,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; @@ -27832,6 +28419,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); } @@ -27839,12 +28427,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) @@ -27852,6 +28442,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); @@ -27873,6 +28464,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)); } @@ -27886,7 +28478,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; @@ -28039,7 +28631,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; @@ -28192,7 +28784,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; @@ -28290,6 +28882,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); } @@ -28297,12 +28890,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) @@ -28310,6 +28905,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); @@ -28331,6 +28927,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)); } @@ -28344,7 +28941,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; @@ -28381,7 +28978,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; @@ -28414,11 +29011,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; @@ -28551,7 +29149,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; @@ -28613,7 +29211,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP } 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) { + } else if (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } str = ZSTR_EMPTY_ALLOC(); goto str_index; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { @@ -28647,7 +29259,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; @@ -28669,7 +29281,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; @@ -28707,7 +29319,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HAND offset = Z_REFVAL_P(offset); goto offset_again; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + /* The array may be destroyed while throwing a warning in case the float is not representable as an int. + * Temporarily increase the refcount to detect this situation. */ + GC_TRY_ADDREF(ht); hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + break; + } + if (EG(exception)) { + break; + } goto num_index_dim; } else if (Z_TYPE_P(offset) == IS_NULL) { key = ZSTR_EMPTY_ALLOC(); @@ -28761,7 +29383,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; @@ -28806,7 +29428,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 @@ -28927,7 +29549,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; @@ -28942,7 +29564,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; @@ -28956,7 +29578,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; @@ -28971,7 +29593,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; @@ -29000,7 +29622,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; @@ -29029,7 +29651,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; @@ -29044,7 +29666,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; @@ -29058,7 +29680,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; @@ -29073,7 +29695,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; @@ -29102,7 +29724,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; @@ -29131,7 +29753,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; @@ -29170,7 +29792,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; @@ -29266,11 +29888,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; @@ -29279,13 +29902,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; @@ -29294,13 +29918,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 @@ -29319,7 +29944,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; @@ -29417,6 +30042,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); } @@ -29424,12 +30050,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) @@ -29437,6 +30065,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); @@ -29458,6 +30087,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)); } @@ -29465,13 +30095,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; @@ -29618,13 +30249,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; @@ -29771,13 +30403,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; @@ -29875,6 +30508,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); } @@ -29882,12 +30516,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) @@ -29895,6 +30531,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); @@ -29916,6 +30553,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)); } @@ -29923,13 +30561,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; @@ -29947,6 +30586,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) { @@ -29957,6 +30597,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 { @@ -29989,6 +30630,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); } @@ -30004,6 +30646,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 && @@ -30016,6 +30659,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)) { @@ -30062,7 +30706,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(); @@ -30129,7 +30773,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; @@ -30176,7 +30820,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; @@ -30207,7 +30851,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; @@ -30275,7 +30919,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; @@ -30343,7 +30987,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; @@ -30373,7 +31017,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; @@ -30439,7 +31083,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; @@ -30505,7 +31149,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; @@ -30556,7 +31200,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; @@ -30625,7 +31269,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; @@ -30687,7 +31331,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNU } 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) { + } else if (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } str = ZSTR_EMPTY_ALLOC(); goto str_index; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { @@ -30712,6 +31370,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(); @@ -30721,7 +31380,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; @@ -30743,7 +31402,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; @@ -30758,7 +31417,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 @@ -30851,6 +31510,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 ) { @@ -30878,7 +31538,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); @@ -30911,7 +31571,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; @@ -30929,7 +31589,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; @@ -30951,7 +31611,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; @@ -30962,10 +31622,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; @@ -31052,13 +31713,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; @@ -31154,11 +31816,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; @@ -31184,11 +31847,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; @@ -31248,11 +31912,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; @@ -31310,11 +31975,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; @@ -31323,13 +31989,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; @@ -31338,13 +32005,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 @@ -31363,7 +32031,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; @@ -31372,13 +32040,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; @@ -31393,13 +32062,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; @@ -31410,13 +32080,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 @@ -31433,7 +32104,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; @@ -31444,13 +32115,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; @@ -31469,10 +32141,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; @@ -31595,6 +32268,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; } @@ -31615,18 +32289,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; @@ -31774,13 +32450,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; @@ -31928,13 +32605,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; @@ -32057,6 +32735,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; } @@ -32077,18 +32756,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; @@ -32186,6 +32867,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); } @@ -32193,12 +32875,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) @@ -32206,6 +32890,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); @@ -32227,6 +32912,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)); } @@ -32234,13 +32920,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; @@ -32387,13 +33074,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; @@ -32540,13 +33228,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; @@ -32644,6 +33333,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); } @@ -32651,12 +33341,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) @@ -32664,6 +33356,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); @@ -32685,6 +33378,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)); } @@ -32692,13 +33386,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; @@ -32727,7 +33422,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; @@ -32756,7 +33451,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; @@ -32790,11 +33485,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; @@ -32826,12 +33522,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; @@ -32864,11 +33561,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; @@ -32886,6 +33585,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) { @@ -32896,6 +33596,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 { @@ -32928,6 +33629,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); } @@ -32943,6 +33645,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 && @@ -32955,6 +33658,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)) { @@ -33001,7 +33705,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; @@ -33063,7 +33767,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_ } 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) { + } else if (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } str = ZSTR_EMPTY_ALLOC(); goto str_index; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { @@ -33088,6 +33806,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(); @@ -33097,7 +33816,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; @@ -33119,7 +33838,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; @@ -33157,7 +33876,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER( offset = Z_REFVAL_P(offset); goto offset_again; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + /* The array may be destroyed while throwing a warning in case the float is not representable as an int. + * Temporarily increase the refcount to detect this situation. */ + GC_TRY_ADDREF(ht); hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + break; + } + if (EG(exception)) { + break; + } goto num_index_dim; } else if (Z_TYPE_P(offset) == IS_NULL) { key = ZSTR_EMPTY_ALLOC(); @@ -33206,11 +33935,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; @@ -33250,11 +33980,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 @@ -33347,6 +34078,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 ) { @@ -33374,7 +34106,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; @@ -33442,7 +34174,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; @@ -33510,7 +34242,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; @@ -33522,7 +34254,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 || @@ -33542,6 +34275,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); @@ -33553,6 +34287,7 @@ 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(); } @@ -33563,6 +34298,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND 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(); } @@ -33570,10 +34306,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND 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; @@ -33588,12 +34325,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(); } @@ -33635,7 +34374,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; @@ -33723,12 +34462,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; @@ -33789,10 +34530,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; @@ -33851,10 +34594,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; @@ -33940,6 +34685,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. */ @@ -34019,15 +34766,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; @@ -34042,13 +34791,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; @@ -34059,13 +34809,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; @@ -34183,10 +34934,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 @@ -34203,7 +34956,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; @@ -34214,13 +34967,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; @@ -34343,6 +35097,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; } @@ -34363,18 +35118,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; @@ -34523,12 +35281,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; @@ -34677,12 +35437,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; @@ -34805,6 +35567,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; } @@ -34825,18 +35588,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; @@ -34867,12 +35633,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; @@ -34904,11 +35672,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; @@ -34937,13 +35708,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 @@ -34982,10 +35754,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; @@ -35016,12 +35789,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); } @@ -35054,6 +35830,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(); } @@ -35064,6 +35841,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); @@ -35088,6 +35867,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); } @@ -35111,6 +35891,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; @@ -35140,7 +35921,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; @@ -35158,6 +35939,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) { @@ -35168,6 +35950,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 { @@ -35200,6 +35983,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); } @@ -35215,6 +35999,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 && @@ -35227,6 +36012,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)) { @@ -35273,7 +36059,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; @@ -35305,7 +36091,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; @@ -35321,7 +36107,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; @@ -35346,6 +36132,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); @@ -35355,6 +36142,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 { @@ -35372,6 +36160,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); @@ -35379,6 +36168,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 @@ -35392,6 +36182,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(); } @@ -35399,6 +36190,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(); } @@ -35416,6 +36208,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(); } } @@ -35426,6 +36219,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(); } } @@ -35433,6 +36227,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(); } } @@ -35444,16 +36239,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; @@ -35475,7 +36272,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; @@ -35516,10 +36313,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; @@ -35566,10 +36365,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 @@ -35626,6 +36427,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; @@ -35641,6 +36443,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) { @@ -35661,6 +36464,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 ) { @@ -35688,7 +36492,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; @@ -35821,7 +36625,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; @@ -35909,12 +36713,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; @@ -35976,10 +36781,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; @@ -36039,10 +36845,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; @@ -36128,6 +36935,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. */ @@ -36207,10 +37016,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; @@ -36231,7 +37041,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; @@ -36248,7 +37058,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; @@ -36366,10 +37176,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 @@ -36386,7 +37197,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; @@ -36403,7 +37214,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; @@ -36526,6 +37337,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; } @@ -36546,18 +37358,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; @@ -36706,12 +37520,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; @@ -36860,12 +37675,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; @@ -36988,6 +37804,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; } @@ -37008,18 +37825,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; @@ -37049,13 +37868,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; @@ -37085,13 +37905,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; @@ -37126,7 +37948,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 @@ -37169,7 +37991,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; @@ -37200,12 +38022,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); } @@ -37248,6 +38072,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); @@ -37324,7 +38149,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; @@ -37457,7 +38282,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; @@ -37479,7 +38304,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; @@ -37521,10 +38346,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; @@ -37571,10 +38397,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 @@ -37631,6 +38458,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; @@ -37646,6 +38474,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) { @@ -37694,7 +38523,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 @@ -37733,10 +38562,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; @@ -37754,6 +38584,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) { @@ -37764,6 +38595,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 { @@ -37796,6 +38628,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); } @@ -37811,6 +38644,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 && @@ -37823,6 +38657,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)) { @@ -37869,7 +38704,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(); @@ -37936,14 +38771,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; @@ -37975,7 +38810,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; @@ -38007,7 +38842,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 @@ -38021,7 +38856,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; @@ -38090,7 +38925,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; @@ -38112,7 +38947,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 @@ -38169,6 +39004,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; @@ -38184,6 +39020,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) { @@ -38204,6 +39041,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 ) { @@ -38231,7 +39069,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 @@ -38246,7 +39084,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 @@ -38256,7 +39094,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 @@ -38266,7 +39104,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 @@ -38305,11 +39143,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 @@ -38327,7 +39166,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 @@ -38335,7 +39174,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; @@ -38412,12 +39251,32 @@ 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); - zend_closure_from_frame(EX_VAR(opline->result.var), call); + if (opline->extended_value != (uint32_t)-1) { + zend_object *closure = CACHED_PTR(opline->extended_value); + if (closure) { + ZVAL_OBJ_COPY(EX_VAR(opline->result.var), closure); + } else { + /* Rotate the key for better hash distribution. */ + const int shift = sizeof(size_t) == 4 ? 6 : 7; + zend_ulong key = (zend_ulong)(uintptr_t)call->func; + key = (key >> shift) | (key << ((sizeof(key) * 8) - shift)); + zval *closure_zv = zend_hash_index_lookup(&EG(callable_convert_cache), key); + if (Z_TYPE_P(closure_zv) == IS_NULL) { + zend_closure_from_frame(closure_zv, call); + } + ZEND_ASSERT(Z_TYPE_P(closure_zv) == IS_OBJECT); + closure = Z_OBJ_P(closure_zv); + ZVAL_OBJ_COPY(EX_VAR(opline->result.var), closure); + CACHE_PTR(opline->extended_value, closure); + } + } else { + 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)); @@ -38430,7 +39289,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(); @@ -38445,12 +39304,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FRAMELESS_ICALL_0_SPEC_UNUSED_ #endif { zend_frameless_function_0 function = (zend_frameless_function_0)ZEND_FLF_HANDLER(opline); - function(EX_VAR(opline->result.var)); + function(result); } 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(); @@ -38465,12 +39324,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FRAMELESS_ICALL_0_SPEC_OBSERVE #endif { zend_frameless_function_0 function = (zend_frameless_function_0)ZEND_FLF_HANDLER(opline); - function(EX_VAR(opline->result.var)); + function(result); } 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; @@ -38558,12 +39417,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; @@ -38624,10 +39485,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; @@ -38686,10 +39549,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; @@ -38775,6 +39640,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. */ @@ -38854,10 +39721,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; @@ -38872,13 +39741,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; @@ -38889,13 +39759,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; @@ -39013,10 +39884,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 @@ -39033,7 +39906,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; @@ -39044,13 +39917,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; @@ -39173,6 +40047,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; } @@ -39193,18 +40068,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; @@ -39353,12 +40231,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; @@ -39507,12 +40387,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; @@ -39635,6 +40517,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; } @@ -39655,18 +40538,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; @@ -39697,12 +40583,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; @@ -39734,11 +40622,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; @@ -39767,13 +40658,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 @@ -39812,10 +40704,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; @@ -39846,12 +40739,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); } @@ -39884,6 +40780,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(); } @@ -39894,6 +40791,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); @@ -39918,6 +40817,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); } @@ -39941,6 +40841,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; @@ -39970,7 +40871,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; @@ -39988,6 +40889,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) { @@ -39998,6 +40900,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 { @@ -40030,6 +40933,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); } @@ -40045,6 +40949,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 && @@ -40057,6 +40962,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)) { @@ -40103,7 +41009,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; @@ -40125,7 +41031,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; @@ -40166,10 +41072,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; @@ -40216,10 +41124,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 @@ -40276,6 +41186,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; @@ -40291,6 +41202,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) { @@ -40311,6 +41223,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 ) { @@ -40338,7 +41251,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; @@ -40359,12 +41272,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; @@ -40393,10 +41307,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; @@ -40414,7 +41329,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; @@ -40432,7 +41347,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; @@ -40462,10 +41377,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; @@ -40483,7 +41399,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; @@ -40501,7 +41417,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; @@ -40529,10 +41445,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; @@ -40548,7 +41465,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; @@ -40576,10 +41493,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; @@ -40595,7 +41513,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; @@ -40620,10 +41538,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; @@ -40657,7 +41576,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; @@ -40691,7 +41610,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; @@ -40717,6 +41636,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++; @@ -40727,7 +41647,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; @@ -40752,6 +41672,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); @@ -40762,15 +41683,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(); @@ -40836,19 +41759,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)) { @@ -40858,6 +41786,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); @@ -40882,6 +41811,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER( ZVAL_NEW_REF(return_value, retval_ptr); } else { + } break; } @@ -40896,13 +41826,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; @@ -40938,6 +41871,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 */ @@ -40947,7 +41881,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; @@ -40971,6 +41905,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); @@ -40980,10 +41915,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; @@ -41000,10 +41936,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; @@ -41024,12 +41961,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; @@ -41041,7 +41979,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 || @@ -41061,6 +42000,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); @@ -41072,6 +42012,7 @@ 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(); } @@ -41082,6 +42023,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC 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(); } @@ -41089,10 +42031,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC 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; @@ -41125,6 +42068,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(); } @@ -41136,10 +42080,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; @@ -41150,6 +42095,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)); @@ -41199,8 +42145,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); @@ -41214,15 +42162,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; @@ -41238,6 +42188,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); @@ -41247,6 +42198,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEN if (UNEXPECTED(EG(exception))) { UNDEF_RESULT(); + HANDLE_EXCEPTION(); } } @@ -41271,15 +42223,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) { @@ -41293,11 +42248,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; @@ -41333,6 +42289,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) { @@ -41343,6 +42300,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZE if (UNEXPECTED(EG(exception))) { UNDEF_RESULT(); + HANDLE_EXCEPTION(); } } @@ -41369,15 +42327,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) { @@ -41391,11 +42352,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; @@ -41416,6 +42378,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(); } @@ -41438,10 +42401,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; @@ -41482,7 +42446,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; @@ -41495,6 +42459,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; } } @@ -41526,7 +42491,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; @@ -41564,7 +42529,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); @@ -41576,6 +42541,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(); } @@ -41588,6 +42554,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) { @@ -41595,6 +42562,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); @@ -41618,6 +42586,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)); @@ -41644,6 +42613,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(); } @@ -41664,7 +42634,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; @@ -41684,6 +42654,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(); } } @@ -41723,10 +42694,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; @@ -41756,13 +42728,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; @@ -41777,12 +42750,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(); } @@ -41824,7 +42799,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; @@ -41877,7 +42852,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; @@ -41905,7 +42880,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; @@ -41918,7 +42893,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; @@ -41931,7 +42906,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; @@ -41944,7 +42919,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; @@ -41957,7 +42932,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; @@ -41970,7 +42945,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; @@ -41983,7 +42958,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; @@ -41996,7 +42971,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; @@ -42009,7 +42984,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; @@ -42020,7 +42995,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; @@ -42031,7 +43006,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; @@ -42042,7 +43017,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; @@ -42053,7 +43028,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; @@ -42070,7 +43045,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; @@ -42081,10 +43056,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; @@ -42095,10 +43072,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; @@ -42171,11 +43150,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; @@ -42187,10 +43168,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; @@ -42202,10 +43185,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; @@ -42260,10 +43245,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; @@ -42318,10 +43303,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; @@ -42376,10 +43361,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; @@ -42434,10 +43419,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; @@ -42492,10 +43477,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; @@ -42550,10 +43535,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; @@ -42564,10 +43549,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; @@ -42578,10 +43565,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; @@ -42669,12 +43658,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; @@ -42771,10 +43762,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; @@ -42801,10 +43794,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; @@ -42865,10 +43860,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; @@ -42927,10 +43924,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; @@ -42962,10 +43961,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; @@ -42974,13 +43975,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; @@ -42989,13 +43991,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; @@ -43005,10 +44008,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 @@ -43027,7 +44032,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; @@ -43036,13 +44041,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; @@ -43128,6 +44134,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. */ @@ -43207,15 +44215,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; @@ -43230,13 +44240,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; @@ -43247,13 +44258,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; @@ -43371,10 +44383,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 @@ -43391,7 +44405,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; @@ -43402,13 +44416,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; @@ -43531,6 +44546,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; } @@ -43551,18 +44567,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; @@ -43711,12 +44730,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; @@ -43865,12 +44886,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; @@ -43993,6 +45016,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; } @@ -44013,18 +45037,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; @@ -44122,6 +45149,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); } @@ -44129,12 +45157,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) @@ -44142,6 +45172,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); @@ -44163,6 +45194,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)); } @@ -44170,13 +45202,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; @@ -44323,13 +45357,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; @@ -44476,13 +45512,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; @@ -44580,6 +45618,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); } @@ -44587,12 +45626,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) @@ -44600,6 +45641,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); @@ -44621,6 +45663,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)); } @@ -44628,13 +45671,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; @@ -44658,12 +45703,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; @@ -44687,12 +45733,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; @@ -44723,12 +45770,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; @@ -44760,11 +45809,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; @@ -44886,10 +45938,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; @@ -44920,12 +45974,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); } @@ -44958,6 +46015,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(); } @@ -44968,6 +46026,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); @@ -44992,6 +46052,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); } @@ -45015,6 +46076,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; @@ -45044,7 +46106,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; @@ -45056,6 +46118,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 { @@ -45091,7 +46154,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; @@ -45103,6 +46166,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 { @@ -45117,10 +46181,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; @@ -45132,6 +46197,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 { @@ -45153,6 +46219,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(); } @@ -45185,7 +46252,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; @@ -45200,6 +46267,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) { @@ -45247,7 +46315,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONS } 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) { + } else if (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } str = ZSTR_EMPTY_ALLOC(); goto str_index; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { @@ -45272,6 +46354,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(); @@ -45281,7 +46364,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; @@ -45303,7 +46386,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; @@ -45341,7 +46424,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLE offset = Z_REFVAL_P(offset); goto offset_again; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + /* The array may be destroyed while throwing a warning in case the float is not representable as an int. + * Temporarily increase the refcount to detect this situation. */ + GC_TRY_ADDREF(ht); hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + break; + } + if (EG(exception)) { + break; + } goto num_index_dim; } else if (Z_TYPE_P(offset) == IS_NULL) { key = ZSTR_EMPTY_ALLOC(); @@ -45391,10 +46484,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; @@ -45435,10 +46530,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; @@ -45489,6 +46586,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 { @@ -45514,10 +46612,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; @@ -45564,10 +46664,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 @@ -45596,10 +46698,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; @@ -45624,6 +46728,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(); } @@ -45641,10 +46746,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 @@ -45701,6 +46807,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); @@ -45716,6 +46823,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) { @@ -45736,6 +46844,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 ) { @@ -45763,7 +46872,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; @@ -45843,7 +46952,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; @@ -45870,10 +46979,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)) { @@ -45898,6 +47009,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); } } @@ -45907,15 +47019,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. */ @@ -45931,7 +47045,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; @@ -45944,7 +47058,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; @@ -45961,6 +47075,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); @@ -45969,6 +47084,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(); @@ -45988,6 +47104,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(); } @@ -45996,10 +47113,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; @@ -46016,6 +47134,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); @@ -46024,6 +47143,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(); @@ -46043,6 +47163,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(); } @@ -46051,10 +47172,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; @@ -46064,11 +47186,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; @@ -46078,11 +47201,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; @@ -46154,12 +47278,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; @@ -46214,10 +47339,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; @@ -46272,10 +47397,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; @@ -46330,10 +47455,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; @@ -46388,10 +47513,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; @@ -46446,10 +47571,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; @@ -46504,10 +47629,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; @@ -46517,11 +47642,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; @@ -46531,11 +47657,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; @@ -46623,12 +47750,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; @@ -46726,10 +47854,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; @@ -46757,10 +47886,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; @@ -46822,10 +47952,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; @@ -46885,10 +48016,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; @@ -46920,10 +48052,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; @@ -46938,7 +48071,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; @@ -46953,7 +48086,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; @@ -46963,10 +48096,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 @@ -46985,7 +48119,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; @@ -47000,7 +48134,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; @@ -47086,6 +48220,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. */ @@ -47165,10 +48301,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; @@ -47189,7 +48326,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; @@ -47206,7 +48343,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; @@ -47324,10 +48461,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 @@ -47344,7 +48482,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; @@ -47361,7 +48499,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; @@ -47484,6 +48622,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; } @@ -47504,18 +48643,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; @@ -47664,12 +48805,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; @@ -47818,12 +48960,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; @@ -47946,6 +49089,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; } @@ -47966,18 +49110,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; @@ -48075,6 +49221,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); } @@ -48082,12 +49229,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) @@ -48095,6 +49244,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); @@ -48116,6 +49266,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)); } @@ -48125,11 +49276,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; @@ -48278,11 +49430,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; @@ -48431,11 +49584,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; @@ -48533,6 +49687,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); } @@ -48540,12 +49695,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) @@ -48553,6 +49710,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); @@ -48574,6 +49732,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)); } @@ -48583,11 +49742,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; @@ -48617,13 +49777,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; @@ -48653,13 +49814,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; @@ -48780,11 +49943,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; @@ -48815,12 +49979,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); } @@ -48863,6 +50029,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); @@ -48939,7 +50106,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; @@ -48954,6 +50121,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) { @@ -49001,7 +50169,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPV } 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) { + } else if (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } str = ZSTR_EMPTY_ALLOC(); goto str_index; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { @@ -49035,7 +50217,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; @@ -49057,7 +50239,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; @@ -49095,7 +50277,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDL offset = Z_REFVAL_P(offset); goto offset_again; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + /* The array may be destroyed while throwing a warning in case the float is not representable as an int. + * Temporarily increase the refcount to detect this situation. */ + GC_TRY_ADDREF(ht); hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + break; + } + if (EG(exception)) { + break; + } goto num_index_dim; } else if (Z_TYPE_P(offset) == IS_NULL) { key = ZSTR_EMPTY_ALLOC(); @@ -49146,10 +50338,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; @@ -49191,10 +50384,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; @@ -49270,10 +50464,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; @@ -49320,10 +50515,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 @@ -49353,10 +50549,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 @@ -49413,6 +50610,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); @@ -49428,6 +50626,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) { @@ -49476,7 +50675,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; @@ -49487,11 +50686,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; @@ -49502,11 +50702,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; @@ -49530,12 +50731,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; @@ -49559,12 +50761,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; @@ -49575,11 +50778,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; @@ -49590,11 +50794,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; @@ -49618,12 +50823,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; @@ -49647,12 +50853,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; @@ -49688,10 +50895,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; @@ -49716,6 +50924,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(); } @@ -49733,10 +50942,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; @@ -49833,10 +51043,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; @@ -49860,6 +51072,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(); @@ -49922,6 +51135,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) { @@ -49937,41 +51151,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; @@ -49980,13 +51194,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; @@ -49995,13 +51210,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 @@ -50020,7 +51236,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; @@ -50118,6 +51334,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); } @@ -50125,12 +51342,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) @@ -50138,6 +51357,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); @@ -50159,6 +51379,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)); } @@ -50166,13 +51387,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; @@ -50319,13 +51542,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; @@ -50472,13 +51697,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; @@ -50576,6 +51803,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); } @@ -50583,12 +51811,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) @@ -50596,6 +51826,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); @@ -50617,6 +51848,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)); } @@ -50624,13 +51856,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(); @@ -50697,7 +51931,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; @@ -50709,6 +51943,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 { @@ -50744,7 +51979,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; @@ -50756,6 +51991,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 { @@ -50770,10 +52006,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; @@ -50785,6 +52022,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 { @@ -50806,6 +52044,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(); } @@ -50838,7 +52077,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; @@ -50850,6 +52089,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 { @@ -50871,6 +52111,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(); } @@ -50903,7 +52144,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; @@ -50918,6 +52159,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) { @@ -50965,7 +52207,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUS } 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) { + } else if (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } str = ZSTR_EMPTY_ALLOC(); goto str_index; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { @@ -50990,6 +52246,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(); @@ -50999,7 +52256,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; @@ -51021,7 +52278,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); @@ -51039,7 +52296,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; @@ -51062,6 +52319,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(); } } @@ -51073,11 +52331,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; @@ -51099,7 +52358,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; @@ -51121,7 +52380,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; @@ -51145,6 +52404,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 { @@ -51165,7 +52425,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; @@ -51190,6 +52450,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(); } @@ -51207,10 +52468,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 @@ -51267,6 +52529,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); @@ -51282,6 +52545,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) { @@ -51302,6 +52566,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 ) { @@ -51329,7 +52594,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); @@ -51342,7 +52607,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); @@ -51375,7 +52640,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; @@ -51427,10 +52692,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)); @@ -51445,7 +52711,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 @@ -51484,11 +52750,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; @@ -51503,10 +52770,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; @@ -51528,7 +52796,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; @@ -51539,10 +52807,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; @@ -51553,10 +52823,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; @@ -51629,11 +52901,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; @@ -51645,10 +52919,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; @@ -51660,10 +52936,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; @@ -51718,10 +52996,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; @@ -51776,10 +53054,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; @@ -51834,10 +53112,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; @@ -51892,10 +53170,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; @@ -51950,10 +53228,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; @@ -52008,10 +53286,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; @@ -52022,10 +53300,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; @@ -52036,10 +53316,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; @@ -52127,12 +53409,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; @@ -52229,10 +53513,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; @@ -52259,10 +53545,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; @@ -52323,10 +53611,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; @@ -52385,10 +53675,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; @@ -52420,10 +53712,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; @@ -52432,13 +53726,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; @@ -52447,13 +53742,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; @@ -52463,10 +53759,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 @@ -52485,7 +53783,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; @@ -52494,13 +53792,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; @@ -52586,6 +53885,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. */ @@ -52665,10 +53966,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; @@ -52683,13 +53986,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; @@ -52700,13 +54004,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; @@ -52824,10 +54129,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 @@ -52844,7 +54151,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; @@ -52855,13 +54162,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; @@ -52984,6 +54292,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; } @@ -53004,164 +54313,13 @@ 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) -{ - 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! */ @@ -53169,7 +54327,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } /* 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_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -53179,7 +54337,163 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + 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_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_VAR_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) { @@ -53318,12 +54632,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; @@ -53446,6 +54762,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; } @@ -53466,18 +54783,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; @@ -53575,6 +54895,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); } @@ -53582,12 +54903,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) @@ -53595,6 +54918,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); @@ -53616,6 +54940,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)); } @@ -53623,13 +54948,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; @@ -53776,13 +55103,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; @@ -53929,13 +55258,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; @@ -54033,6 +55364,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); } @@ -54040,12 +55372,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) @@ -54053,6 +55387,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); @@ -54074,6 +55409,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)); } @@ -54081,13 +55417,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; @@ -54111,12 +55449,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; @@ -54140,12 +55479,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; @@ -54180,10 +55520,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; @@ -54214,12 +55556,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; @@ -54251,11 +55595,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; @@ -54377,10 +55724,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; @@ -54411,12 +55760,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); } @@ -54449,6 +55801,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(); } @@ -54459,6 +55812,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); @@ -54483,6 +55838,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); } @@ -54506,6 +55862,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; @@ -54535,7 +55892,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; @@ -54550,6 +55907,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) { @@ -54597,7 +55955,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_H } 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) { + } else if (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } str = ZSTR_EMPTY_ALLOC(); goto str_index; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { @@ -54622,6 +55994,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(); @@ -54631,7 +56004,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; @@ -54653,7 +56026,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; @@ -54691,7 +56064,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(Z offset = Z_REFVAL_P(offset); goto offset_again; } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + /* The array may be destroyed while throwing a warning in case the float is not representable as an int. + * Temporarily increase the refcount to detect this situation. */ + GC_TRY_ADDREF(ht); hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + break; + } + if (EG(exception)) { + break; + } goto num_index_dim; } else if (Z_TYPE_P(offset) == IS_NULL) { key = ZSTR_EMPTY_ALLOC(); @@ -54741,10 +56124,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; @@ -54782,341 +56167,56473 @@ 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 (++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; + uint32_t 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 (uint32_t 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 (uint32_t 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 (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } + 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 (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } + 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 (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } + 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 (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } + 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 (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } + 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 (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } + 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 (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } + 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 (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } + 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_exc; + } + 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)); +fe_fetch_w_exit_exc: + 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 (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } + 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) { + /* The array may be destroyed while throwing a warning in case the float is not representable as an int. + * Temporarily increase the refcount to detect this situation. */ + GC_TRY_ADDREF(ht); + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + break; + } + if (EG(exception)) { + break; + } + 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 (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } + 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) { + /* The array may be destroyed while throwing a warning in case the float is not representable as an int. + * Temporarily increase the refcount to detect this situation. */ + GC_TRY_ADDREF(ht); + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + break; + } + if (EG(exception)) { + break; + } + 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 (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } + 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 (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } + 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) { + /* The array may be destroyed while throwing a warning in case the float is not representable as an int. + * Temporarily increase the refcount to detect this situation. */ + GC_TRY_ADDREF(ht); + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + break; + } + if (EG(exception)) { + break; + } + 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); + + if (opline->extended_value != (uint32_t)-1) { + zend_object *closure = CACHED_PTR(opline->extended_value); + if (closure) { + ZVAL_OBJ_COPY(EX_VAR(opline->result.var), closure); + } else { + /* Rotate the key for better hash distribution. */ + const int shift = sizeof(size_t) == 4 ? 6 : 7; + zend_ulong key = (zend_ulong)(uintptr_t)call->func; + key = (key >> shift) | (key << ((sizeof(key) * 8) - shift)); + zval *closure_zv = zend_hash_index_lookup(&EG(callable_convert_cache), key); + if (Z_TYPE_P(closure_zv) == IS_NULL) { + zend_closure_from_frame(closure_zv, call); + } + ZEND_ASSERT(Z_TYPE_P(closure_zv) == IS_OBJECT); + closure = Z_OBJ_P(closure_zv); + ZVAL_OBJ_COPY(EX_VAR(opline->result.var), closure); + CACHE_PTR(opline->extended_value, closure); + } + } else { + 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(result); + } + 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(result); + } + 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 (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } + 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) { + /* The array may be destroyed while throwing a warning in case the float is not representable as an int. + * Temporarily increase the refcount to detect this situation. */ + GC_TRY_ADDREF(ht); + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + break; + } + if (EG(exception)) { + break; + } + 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 (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } + 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) { + /* The array may be destroyed while throwing a warning in case the float is not representable as an int. + * Temporarily increase the refcount to detect this situation. */ + GC_TRY_ADDREF(ht); + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + break; + } + if (EG(exception)) { + break; + } + 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 (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } + 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 (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) { + zval tmp; + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_COPY(&tmp, expr_ptr); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + /* A userland error handler can do funky things to the expression, so reset it */ + zval_ptr_dtor(expr_ptr); + ZVAL_COPY_VALUE(expr_ptr, &tmp); + } + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(expr_ptr); + HANDLE_EXCEPTION(); + } + 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) { + /* The array may be destroyed while throwing a warning in case the float is not representable as an int. + * Temporarily increase the refcount to detect this situation. */ + GC_TRY_ADDREF(ht); + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + break; + } + if (EG(exception)) { + break; + } + 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 @@ -55161,7 +112678,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, @@ -58657,8 +116174,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 @@ -58689,10 +116206,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 */ @@ -58771,7 +116288,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); @@ -59218,9 +116738,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(); @@ -59286,6 +116808,9 @@ ZEND_API void execute_ex(zend_execute_data *ex) + + + goto zend_leave_helper_SPEC_LABEL; } @@ -61247,9 +118772,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(); @@ -61296,7 +118823,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); @@ -61315,367 +119211,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); - } - } - } @@ -63025,9 +120560,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(); @@ -63093,6 +120630,9 @@ ZEND_API void execute_ex(zend_execute_data *ex) + + + goto zend_leave_helper_SPEC_LABEL; } @@ -64389,7 +121929,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, @@ -67885,6 +125425,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, @@ -68143,13 +129185,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(); @@ -68191,7 +129237,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) @@ -68201,9 +129247,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) { @@ -68212,6 +129256,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 @@ -68276,15 +129322,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)]; @@ -68586,8 +129632,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; @@ -68604,11 +129650,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; @@ -68617,8 +129663,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 2417b858b5b18..53b1ac6baf0a3 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -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..4ecc44237500a 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"); @@ -1950,15 +2025,19 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"# define ZEND_VM_LEAVE() return (zend_op*)((uintptr_t)opline | ZEND_VM_ENTER_BIT)\n"); out($f,"#endif\n"); out($f,"#define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n"); + out($f,"#ifdef ZEND_VM_FP_GLOBAL_REG\n"); out($f,"#define ZEND_VM_LOOP_INTERRUPT() zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); + out($f,"#else\n"); + out($f,"#define ZEND_VM_LOOP_INTERRUPT() opline = (zend_op*)((uintptr_t)zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU) & ~ZEND_VM_ENTER_BIT);\n"); + out($f,"#endif\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 +2113,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 +2217,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 +2266,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 +2317,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 +2335,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 +2478,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 +2757,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 +2821,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 +2847,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 +2934,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 +3017,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 +3028,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 +3139,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 +3161,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 +3181,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 +3252,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 +3285,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.c b/Zend/zend_vm_opcodes.c index 00ad38baaafeb..936a96e55e41f 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -439,7 +439,7 @@ static uint32_t zend_vm_opcodes_flags[211] = { 0x00000101, 0x00000101, 0x00000101, - 0x00000101, + 0x01040101, 0x00002001, 0x00000101, 0x00000100, 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..8c1263885bf6c 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), true); 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), false); } 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) { @@ -224,7 +237,7 @@ static zend_object* zend_weakref_new(zend_class_entry *ce) { static zend_always_inline bool zend_weakref_find(zend_object *referent, zval *return_value) { void *tagged_ptr = zend_hash_index_find_ptr(&EG(weakrefs), zend_object_to_weakref_key(referent)); if (!tagged_ptr) { - return 0; + return false; } void *ptr = ZEND_WEAKREF_GET_PTR(tagged_ptr); @@ -234,7 +247,7 @@ static zend_always_inline bool zend_weakref_find(zend_object *referent, zval *re found_weakref: wr = ptr; RETVAL_OBJ_COPY(&wr->std); - return 1; + return true; } if (tag == ZEND_WEAKREF_TAG_HT) { @@ -246,7 +259,7 @@ static zend_always_inline bool zend_weakref_find(zend_object *referent, zval *re } ZEND_HASH_FOREACH_END(); } - return 0; + return false; } static zend_always_inline void zend_weakref_create(zend_object *referent, zval *return_value) { @@ -272,7 +285,7 @@ static void zend_weakref_free(zend_object *zo) { zend_weakref *wr = zend_weakref_from(zo); if (wr->referent) { - zend_weakref_unregister(wr->referent, ZEND_WEAKREF_ENCODE(wr, ZEND_WEAKREF_TAG_REF), 1); + zend_weakref_unregister(wr->referent, ZEND_WEAKREF_ENCODE(wr, ZEND_WEAKREF_TAG_REF), true); } zend_object_std_dtor(&wr->std); @@ -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); } @@ -364,18 +370,25 @@ static zval *zend_weakmap_read_dimension(zend_object *object, zval *offset, int zend_weakmap *wm = zend_weakmap_from(object); zend_object *obj_addr = Z_OBJ_P(offset); zval *zv = zend_hash_index_find(&wm->ht, zend_object_to_weakref_key(obj_addr)); - if (zv == NULL) { - if (type != BP_VAR_IS) { - zend_throw_error(NULL, - "Object %s#%d not contained in WeakMap", ZSTR_VAL(obj_addr->ce->name), obj_addr->handle); + if (type == BP_VAR_W || type == BP_VAR_RW) { + if (zv == NULL) { + zval value; + zend_weakref_register(obj_addr, ZEND_WEAKREF_ENCODE(&wm->ht, ZEND_WEAKREF_TAG_MAP)); + ZVAL_NULL(&value); + zv = zend_hash_index_add_new(&wm->ht, zend_object_to_weakref_key(obj_addr), &value); + } + ZVAL_MAKE_REF(zv); + } else { + if (zv == NULL) { + if (type != BP_VAR_IS) { + zend_throw_error(NULL, + "Object %s#%d not contained in WeakMap", ZSTR_VAL(obj_addr->ce->name), obj_addr->handle); + return NULL; + } return NULL; } - return NULL; } - if (type == BP_VAR_W || type == BP_VAR_RW) { - ZVAL_MAKE_REF(zv); - } return zv; } @@ -449,7 +462,7 @@ static void zend_weakmap_unset_dimension(zend_object *object, zval *offset) return; } - zend_weakref_unregister(obj_addr, ZEND_WEAKREF_ENCODE(&wm->ht, ZEND_WEAKREF_TAG_MAP), 1); + zend_weakref_unregister(obj_addr, ZEND_WEAKREF_ENCODE(&wm->ht, ZEND_WEAKREF_TAG_MAP), true); } static zend_result zend_weakmap_count_elements(zend_object *object, zend_long *count) @@ -547,6 +560,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 +572,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 +600,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 +610,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 +673,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; @@ -713,7 +738,7 @@ ZEND_METHOD(WeakMap, offsetGet) RETURN_THROWS(); } - ZVAL_COPY(return_value, zv); + RETURN_COPY_DEREF(zv); } ZEND_METHOD(WeakMap, offsetSet) @@ -751,9 +776,7 @@ ZEND_METHOD(WeakMap, offsetUnset) ZEND_METHOD(WeakMap, count) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); zend_long count; zend_weakmap_count_elements(Z_OBJ_P(ZEND_THIS), &count); @@ -762,9 +785,7 @@ ZEND_METHOD(WeakMap, count) ZEND_METHOD(WeakMap, getIterator) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); zend_create_internal_iterator_zval(return_value, ZEND_THIS); } 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 5f8af2a2a927f..acee1e6ca0981 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"; - } + $docComment = $this->exposedDocComment ? '"' . $this->exposedDocComment->escape() . '"' : "NULL"; + $framelessFuncInfosName = !empty($this->framelessFunctionInfos) ? $this->getFramelessFunctionInfosName() : "NULL"; - $php84AndAboveFlags = array_slice($flagsByPhpVersions, 5, null, true); - $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); @@ -2821,11 +2796,12 @@ 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; - $code .= "\tzend_string *const_{$constName}_name = zend_string_init_interned(\"$constName\", sizeof(\"$constName\") - 1, 1);\n"; + $code .= "\tzend_string *const_{$constName}_name = zend_string_init_interned(\"$constName\", sizeof(\"$constName\") - 1, true);\n"; $nameCode = "const_{$constName}_name"; if ($this->exposedDocComment) { @@ -2852,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 ); } @@ -2870,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 ); } @@ -2881,7 +2855,7 @@ private function getClassConstDeclaration(EvaluatedValue $value, array $allConst $code .= "#endif\n"; } - $code .= "\tzend_string_release(const_{$constName}_name);\n"; + $code .= "\tzend_string_release_ex(const_{$constName}_name, true);\n"; return $code; } @@ -2922,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; @@ -3087,13 +3058,13 @@ public static function getString( // 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", + "\tzend_string *$varName = $initFn(\"$content\", sizeof(\"$content\") - 1, true);\n", $varName, - "\tzend_string_release($varName);\n" + "\tzend_string_release_ex($varName, true);\n" ]; // For attribute values that are not freed if ($varName === '') { - $result[0] = "$initFn(\"$content\", sizeof(\"$content\") - 1, 1);\n"; + $result[0] = "$initFn(\"$content\", sizeof(\"$content\") - 1, true);\n"; } // If not set, use the current latest version $allVersions = ALL_PHP_VERSION_IDS; @@ -3250,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 ); @@ -3261,29 +3231,26 @@ public function getDeclaration(array $allConstInfos): string { return $code; } - /** - * @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; @@ -3349,8 +3316,12 @@ 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 { + /** + * @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, '\\', '_'); [$stringInit, $nameCode, $stringRelease] = StringBuilder::getString( "attribute_name_{$escapedAttributeName}_$nameSuffix", @@ -3374,13 +3345,21 @@ public function generateCode(string $invocation, string $nameSuffix, array $allC ); 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); - $zvalName = "attribute_{$escapedAttributeName}_{$nameSuffix}_arg$i"; - $code .= $value->initializeZval($zvalName); - $code .= "\tZVAL_COPY_VALUE(&attribute_{$escapedAttributeName}_{$nameSuffix}->args[$i].value, &$zvalName);\n"; + $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; } @@ -3529,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) { @@ -3553,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 { @@ -3564,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); + } } } @@ -3614,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"; @@ -3685,10 +3661,7 @@ function (Name $item) { return $code; } - /** - * @return array - */ - private function getFlagsByPhpVersion(): array + private function getFlagsByPhpVersion(): VersionFlags { $php70Flags = []; @@ -3708,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 { @@ -4357,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) { @@ -4535,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 { @@ -4894,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; @@ -5088,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 @@ -5227,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"; @@ -5253,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; @@ -5277,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); @@ -5297,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) { @@ -5317,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 ); } @@ -5332,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 ); } } @@ -5346,12 +5338,15 @@ 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) { @@ -5360,12 +5355,20 @@ function generateGlobalConstantAttributeInitialization( $code = generateCodeWithConditions( $constInfos, "", - static function (ConstInfo $constInfo) use ($allConstInfos, $isConditional) { + 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; @@ -5380,7 +5383,8 @@ static function (ConstInfo $constInfo) use ($allConstInfos, $isConditional) { "zend_add_global_constant_attribute($constVarName", $constVarName . "_$key", $allConstInfos, - PHP_85_VERSION_ID + PHP_85_VERSION_ID, + $useDeclared ); } @@ -5397,25 +5401,37 @@ static function (ConstInfo $constInfo) use ($allConstInfos, $isConditional) { /** * @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 ); } @@ -5428,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) { @@ -5441,7 +5460,8 @@ function generatePropertyAttributeInitialization( "zend_add_property_attribute(class_entry, property_" . $propertyInfo->name->getDeclarationName(), "property_" . $propertyInfo->name->getDeclarationName() . "_" . $key, $allConstInfos, - $phpVersionIdMinimumCompatibility + $phpVersionIdMinimumCompatibility, + $declaredStrings ); } } @@ -5464,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 @@ -6135,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); @@ -6429,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 db4265c66fc67..0a2169f6f510e 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 ]) @@ -1796,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 @@ -2488,3 +2502,43 @@ AC_DEFUN([PHP_REMOVE_OPTIMIZATION_FLAGS], [ CFLAGS=$(echo "$CFLAGS" | $SED -e "$sed_script") CXXFLAGS=$(echo "$CXXFLAGS" | $SED -e "$sed_script") ]) + +dnl +dnl PHP_C_STANDARD_LIBRARY +dnl +dnl Determine the C standard library used for the build. The uclibc is checked +dnl first because it also defines the __GLIBC__ and could otherwise be detected +dnl as glibc. Musl C library is determined heuristically. +dnl +AC_DEFUN([PHP_C_STANDARD_LIBRARY], +[AC_CACHE_CHECK([C standard library implementation], +[php_cv_c_standard_library], +[php_cv_c_standard_library=unknown +dnl Check if C standard library is uclibc. +AS_VAR_IF([php_cv_c_standard_library], [unknown], +[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ], +[#ifndef __UCLIBC__ + (void) __UCLIBC__; +#endif])], +[php_cv_c_standard_library=uclibc], +[php_cv_c_standard_library=unknown])]) +dnl Check if C standard library is GNU C. +AS_VAR_IF([php_cv_c_standard_library], [unknown], +[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ], +[#ifndef __GLIBC__ + (void) __GLIBC__; +#endif])], +[php_cv_c_standard_library=glibc], +[php_cv_c_standard_library=unknown])]) +dnl Check if C standard library is musl libc. +AS_VAR_IF([php_cv_c_standard_library], [unknown], +[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ], +[#ifndef __DEFINED_va_list + (void) __DEFINED_va_list; +#endif])], +[php_cv_c_standard_library=musl], +[AS_IF([command -v ldd >/dev/null && ldd --version 2>&1 | grep ^musl >/dev/null 2>&1], +[php_cv_c_standard_library=musl], +[php_cv_c_standard_library=unknown])])]) +]) +]) diff --git a/configure.ac b/configure.ac index 2bd6ae26ce625..77fc8c89cdf40 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.5.0-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.6.0-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER @@ -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" ;; @@ -234,15 +250,10 @@ case $host_alias in ;; esac -dnl Detect musl libc -AC_MSG_CHECKING([whether we are using musl libc]) -if command -v ldd >/dev/null && ldd --version 2>&1 | grep ^musl >/dev/null 2>&1 -then - AC_MSG_RESULT([yes]) - AC_DEFINE([__MUSL__], [1], [Define to 1 when using musl libc.]) -else - AC_MSG_RESULT([no]) -fi +dnl Detect C library. +PHP_C_STANDARD_LIBRARY +AS_VAR_IF([php_cv_c_standard_library], [musl], + [AC_DEFINE([__MUSL__], [1], [Define to 1 when using musl libc.])]) dnl Add _GNU_SOURCE compile definition because the php_config.h with definitions dnl by AC_USE_SYSTEM_EXTENSIONS might be included after the system headers which diff --git a/docs/release-process.md b/docs/release-process.md index 37cf04dd70593..e053728feb0aa 100644 --- a/docs/release-process.md +++ b/docs/release-process.md @@ -169,10 +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). @@ -219,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 @@ -227,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 @@ -500,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. + + * [Announce 8.5.0alpha1](https://github.com/derickr/toot-together/pull/42) + * [Announce 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 @@ -564,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 @@ -572,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 @@ -871,25 +878,37 @@ If you choose to create a patch-level release, follow these steps: mailinglist. -## 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. +## Soft feature freeze -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. +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. -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 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..395034afe8d5d 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 @@ -487,7 +489,7 @@ generated. You can include this file conditionally, such as: #endif When ``@generate-legacy-arginfo`` is passed the minimum PHP version ID that needs to be supported, -then only one arginfo file is going to be generated, and ``#if`` prepocessor directives will ensure +then only one arginfo file is going to be generated, and ``#if`` preprocessor directives will ensure compatibility with all the required PHP 8 versions. PHP Version IDs are as follows: ``80000`` for PHP 8.0, ``80100`` for PHP PHP 8.1, ``80200`` for PHP diff --git a/docs/source/miscellaneous/writing-tests.rst b/docs/source/miscellaneous/writing-tests.rst index fd09d80f1275e..4c46dad638b6c 100644 --- a/docs/source/miscellaneous/writing-tests.rst +++ b/docs/source/miscellaneous/writing-tests.rst @@ -132,7 +132,7 @@ below illustrates a minimal test. string(32) "# hello All, I sAid hi planet! #" As you can see the file is divided into several sections. The TEST section holds a one line title of -the phpt test, this should be a simple description and shouldn't ever excede one line, if you need +the phpt test, this should be a simple description and shouldn't ever exceed one line, if you need to write more explanation add comments in the body of the test case. The phpt files name is used when generating a .php file. The FILE section is used as the body of the .php file, so don't forget to open and close your php tags. The EXPECT section is the part used as a comparison to see if the @@ -580,7 +580,7 @@ Example 1 (snippet): .. code:: text --DESCRIPTION-- - This test covers both valid and invalid usages of filter_input() with INPUT_GET and INPUT_POST data and several differnet filter sanitizers. + This test covers both valid and invalid usages of filter_input() with INPUT_GET and INPUT_POST data and several different filter sanitizers. Example 1 (full): :ref:`sample001.phpt` @@ -1310,7 +1310,7 @@ Example 1 (full): :ref:`sample017.phpt` ``--FLAKY--`` ------------- -**Description:** This section identifies this test as one that occassionally fails. If the test +**Description:** This section identifies this test as one that occasionally fails. If the test actually fails, it will be retried one more time, and that result will be reported. The section should include a brief description of why the test is flaky. Reasons for this include tests that rely on relatively precise timing, or temporary disc states. Available as of PHP 8.1.22 and 8.2.9, @@ -1884,7 +1884,7 @@ sample001.phpt --DESCRIPTION-- This test covers both valid and invalid usages of filter_input() with INPUT_GET and INPUT_POST data - and several differnt filter sanitizers. + and several different filter sanitizers. --CREDITS-- Felipe Pena --INI-- diff --git a/ext/bcmath/bcmath_arginfo.h b/ext/bcmath/bcmath_arginfo.h index 9edfd5cd65760..15325603f211e 100644 --- a/ext/bcmath/bcmath_arginfo.h +++ b/ext/bcmath/bcmath_arginfo.h @@ -208,9 +208,9 @@ static zend_class_entry *register_class_BcMath_Number(zend_class_entry *class_en zval property_scale_default_value; ZVAL_UNDEF(&property_scale_default_value); - zend_string *property_scale_name = zend_string_init("scale", sizeof("scale") - 1, 1); + zend_string *property_scale_name = zend_string_init("scale", sizeof("scale") - 1, true); zend_declare_typed_property(class_entry, property_scale_name, &property_scale_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_scale_name); + zend_string_release_ex(property_scale_name, true); return class_entry; } diff --git a/ext/bcmath/libbcmath/src/raise.c b/ext/bcmath/libbcmath/src/raise.c index 5df8130c24219..959ba924e57fd 100644 --- a/ext/bcmath/libbcmath/src/raise.c +++ b/ext/bcmath/libbcmath/src/raise.c @@ -193,7 +193,12 @@ bc_raise_status bc_raise(bc_num base, long exponent, bc_num *result, size_t scal if (bc_is_zero(base)) { /* If the exponent is negative, it divides by 0 */ - return is_neg ? BC_RAISE_STATUS_DIVIDE_BY_ZERO : BC_RAISE_STATUS_OK; + if (is_neg) { + return BC_RAISE_STATUS_DIVIDE_BY_ZERO; + } + bc_free_num (result); + *result = bc_copy_num(BCG(_zero_)); + return BC_RAISE_STATUS_OK; } /* check overflow */ diff --git a/ext/bcmath/tests/gh20006.phpt b/ext/bcmath/tests/gh20006.phpt new file mode 100644 index 0000000000000..ab0db915152d3 --- /dev/null +++ b/ext/bcmath/tests/gh20006.phpt @@ -0,0 +1,16 @@ +--TEST-- +GH-20006 (Power of 0 of BcMath number causes crash) +--EXTENSIONS-- +bcmath +--FILE-- + +--EXPECTF-- +object(BcMath\Number)#%d (2) { + ["value"]=> + string(1) "0" + ["scale"]=> + int(0) +} diff --git a/ext/bz2/bz2.c b/ext/bz2/bz2.c index 9ed5342a7df8f..a8153d7d11938 100644 --- a/ext/bz2/bz2.c +++ b/ext/bz2/bz2.c @@ -352,7 +352,7 @@ PHP_FUNCTION(bzopen) RETURN_THROWS(); } - if (CHECK_ZVAL_NULL_PATH(file)) { + if (zend_str_has_nul_byte(Z_STR_P(file))) { zend_argument_type_error(1, "must not contain null bytes"); RETURN_THROWS(); } @@ -366,10 +366,23 @@ PHP_FUNCTION(bzopen) php_stream_from_zval(stream, file); stream_mode_len = strlen(stream->mode); - if (stream_mode_len != 1 && !(stream_mode_len == 2 && memchr(stream->mode, 'b', 2))) { - php_error_docref(NULL, E_WARNING, "Cannot use stream opened in mode '%s'", stream->mode); - RETURN_FALSE; - } else if (stream_mode_len == 1 && stream->mode[0] != 'r' && stream->mode[0] != 'w' && stream->mode[0] != 'a' && stream->mode[0] != 'x') { + char primary_stream_mode; + if (stream_mode_len == 1) { + primary_stream_mode = stream->mode[0]; + } else if (stream_mode_len == 2) { + char secondary_stream_mode = 0; + if (stream->mode[0] != 'b') { + primary_stream_mode = stream->mode[0]; + secondary_stream_mode = stream->mode[1]; + } else { + primary_stream_mode = stream->mode[1]; + secondary_stream_mode = stream->mode[0]; + } + if (secondary_stream_mode != 'b') { + goto unsupported_mode; + } + } else { +unsupported_mode: php_error_docref(NULL, E_WARNING, "Cannot use stream opened in mode '%s'", stream->mode); RETURN_FALSE; } @@ -377,16 +390,14 @@ PHP_FUNCTION(bzopen) switch(mode[0]) { case 'r': /* only "r" and "rb" are supported */ - if (stream->mode[0] != mode[0] && !(stream_mode_len == 2 && stream->mode[1] != mode[0])) { + if (primary_stream_mode != 'r') { php_error_docref(NULL, E_WARNING, "Cannot read from a stream opened in write only mode"); RETURN_FALSE; } break; case 'w': /* support only "w"(b), "a"(b), "x"(b) */ - if (stream->mode[0] != mode[0] && !(stream_mode_len == 2 && stream->mode[1] != mode[0]) - && stream->mode[0] != 'a' && !(stream_mode_len == 2 && stream->mode[1] != 'a') - && stream->mode[0] != 'x' && !(stream_mode_len == 2 && stream->mode[1] != 'x')) { + if (!strchr("wax", primary_stream_mode)) { php_error_docref(NULL, E_WARNING, "cannot write to a stream opened in read only mode"); RETURN_FALSE; } @@ -465,8 +476,15 @@ PHP_FUNCTION(bzcompress) + .01 x length of data + 600 which is the largest size the results of the compression could possibly be, at least that's what the libbz2 docs say (thanks to jeremy@nirvani.net for pointing this out). */ - // TODO Check source string length fits in unsigned int - dest_len = (unsigned int) (source_len + (0.01 * source_len) + 600); + size_t chunk_len = source_len + source_len / 100 + 600; + const size_t min = MIN(ZSTR_MAX_LEN, UINT_MAX); + + if (chunk_len < source_len || chunk_len > min) { + zend_argument_value_error(1, "must have a length less than or equal to %zu", min); + RETURN_THROWS(); + } + + dest_len = (unsigned int) chunk_len; /* Allocate the destination buffer */ dest = zend_string_alloc(dest_len, 0); @@ -493,11 +511,7 @@ PHP_FUNCTION(bzdecompress) size_t source_len; int error; bool small = 0; -#ifdef PHP_WIN32 - unsigned __int64 size = 0; -#else - unsigned long long size = 0; -#endif + uint64_t size = 0; bz_stream bzs; if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "s|b", &source, &source_len, &small)) { @@ -524,26 +538,22 @@ PHP_FUNCTION(bzdecompress) /* compression is better then 2:1, need to allocate more memory */ bzs.avail_out = source_len; size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32; -#ifndef ZEND_ENABLE_ZVAL_LONG64 - if (size > SIZE_MAX) { + if (UNEXPECTED(size > SIZE_MAX)) { /* no reason to continue if we're going to drop it anyway */ break; } -#endif + dest = zend_string_safe_realloc(dest, 1, bzs.avail_out+1, (size_t) size, 0); bzs.next_out = ZSTR_VAL(dest) + size; } if (error == BZ_STREAM_END || error == BZ_OK) { size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32; -#ifndef ZEND_ENABLE_ZVAL_LONG64 if (UNEXPECTED(size > SIZE_MAX)) { - php_error_docref(NULL, E_WARNING, "Decompressed size too big, max is %zd", SIZE_MAX); + php_error_docref(NULL, E_WARNING, "Decompressed size too big, max is %zu", SIZE_MAX); zend_string_efree(dest); RETVAL_LONG(BZ_MEM_ERROR); - } else -#endif - { + } else { dest = zend_string_safe_realloc(dest, 1, (size_t)size, 1, 0); ZSTR_LEN(dest) = (size_t)size; ZSTR_VAL(dest)[(size_t)size] = '\0'; diff --git a/ext/bz2/bz2_filter.c b/ext/bz2/bz2_filter.c index 2fbdf9452dad3..27059391dacb9 100644 --- a/ext/bz2/bz2_filter.c +++ b/ext/bz2/bz2_filter.c @@ -337,12 +337,14 @@ static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *fi zval *tmpzval = NULL; if (Z_TYPE_P(filterparams) == IS_ARRAY || Z_TYPE_P(filterparams) == IS_OBJECT) { - if ((tmpzval = zend_hash_str_find(HASH_OF(filterparams), "concatenated", sizeof("concatenated")-1))) { + HashTable *ht = HASH_OF(filterparams); + + if ((tmpzval = zend_hash_str_find_ind(ht, "concatenated", sizeof("concatenated")-1))) { data->expect_concatenated = zend_is_true(tmpzval); tmpzval = NULL; } - tmpzval = zend_hash_str_find(HASH_OF(filterparams), "small", sizeof("small")-1); + tmpzval = zend_hash_str_find_ind(ht, "small", sizeof("small")-1); } else { tmpzval = filterparams; } @@ -362,7 +364,9 @@ static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *fi zval *tmpzval; if (Z_TYPE_P(filterparams) == IS_ARRAY || Z_TYPE_P(filterparams) == IS_OBJECT) { - if ((tmpzval = zend_hash_str_find(HASH_OF(filterparams), "blocks", sizeof("blocks")-1))) { + HashTable *ht = HASH_OF(filterparams); + + if ((tmpzval = zend_hash_str_find_ind(ht, "blocks", sizeof("blocks")-1))) { /* How much memory to allocate (1 - 9) x 100kb */ zend_long blocks = zval_get_long(tmpzval); if (blocks < 1 || blocks > 9) { @@ -372,7 +376,7 @@ static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *fi } } - if ((tmpzval = zend_hash_str_find(HASH_OF(filterparams), "work", sizeof("work")-1))) { + if ((tmpzval = zend_hash_str_find_ind(ht, "work", sizeof("work")-1))) { /* Work Factor (0 - 250) */ zend_long work = zval_get_long(tmpzval); if (work < 0 || work > 250) { diff --git a/ext/bz2/tests/filter_broken_object_options.phpt b/ext/bz2/tests/filter_broken_object_options.phpt new file mode 100644 index 0000000000000..84e49a64ccb62 --- /dev/null +++ b/ext/bz2/tests/filter_broken_object_options.phpt @@ -0,0 +1,25 @@ +--TEST-- +bz2 filter assertion failure with non-dynamic properties in filter param object +--EXTENSIONS-- +bz2 +--FILE-- + +--EXPECT-- +Hello world, hopefully not broken diff --git a/ext/bz2/tests/gh19810.phpt b/ext/bz2/tests/gh19810.phpt new file mode 100644 index 0000000000000..a230fbb6ffeff --- /dev/null +++ b/ext/bz2/tests/gh19810.phpt @@ -0,0 +1,11 @@ +--TEST-- +GH-19810: bzopen() stream mode validation +--EXTENSIONS-- +bz2 +--FILE-- + +--EXPECTF-- +Warning: bzopen(): Cannot read from a stream opened in write only mode in %s on line %d +bool(false) diff --git a/ext/bz2/tests/gh20620.phpt b/ext/bz2/tests/gh20620.phpt new file mode 100644 index 0000000000000..351ba488b2bd6 --- /dev/null +++ b/ext/bz2/tests/gh20620.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug GH-20620 (bzcompress with large source) +--EXTENSIONS-- +bz2 +--SKIPIF-- + +--INI-- +memory_limit=-1 +--FILE-- +getMessage(), PHP_EOL; +} +?> +--EXPECTF-- +bzcompress(): Argument #1 ($data) must have a length less than or equal to %d diff --git a/ext/calendar/cal_unix.c b/ext/calendar/cal_unix.c index c3fe5557d244e..915da1c326ae1 100644 --- a/ext/calendar/cal_unix.c +++ b/ext/calendar/cal_unix.c @@ -28,7 +28,7 @@ PHP_FUNCTION(unixtojd) { time_t ts; zend_long tl = 0; - bool tl_is_null = 1; + bool tl_is_null = true; struct tm *ta, tmbuf; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &tl, &tl_is_null) == FAILURE) { diff --git a/ext/calendar/calendar.c b/ext/calendar/calendar.c index 4cb6a2fa9a08a..b90e461da49ce 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)); } /* }}} */ @@ -455,7 +480,7 @@ static char *heb_number_to_chars(int n, int fl, char **ret) PHP_FUNCTION(jdtojewish) { zend_long julday, fl = 0; - bool heb = 0; + bool heb = false; int year, month, day; char *dayp, *yearp; diff --git a/ext/calendar/easter.c b/ext/calendar/easter.c index 72c52e0fcff78..7fd8c0b33bb3e 100644 --- a/ext/calendar/easter.c +++ b/ext/calendar/easter.c @@ -34,7 +34,7 @@ static void _cal_easter(INTERNAL_FUNCTION_PARAMETERS, bool gm) zend_long year, golden, solar, lunar, pfm, dom, tmp, easter, result; zend_long method = CAL_EASTER_DEFAULT; const zend_long max_year = (zend_long)(ZEND_LONG_MAX / 5) * 4; - bool year_is_null = 1; + bool year_is_null = true; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!l", &year, &year_is_null, &method) == FAILURE) { 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_com.c b/ext/com_dotnet/com_com.c index cf44858c93b78..129db275a72ef 100644 --- a/ext/com_dotnet/com_com.c +++ b/ext/com_dotnet/com_com.c @@ -281,7 +281,7 @@ PHP_FUNCTION(com_get_active_object) char *module_name; size_t module_name_len; zend_long code_page; - bool code_page_is_null = 1; + bool code_page_is_null = true; IUnknown *unk = NULL; IDispatch *obj = NULL; HRESULT res; @@ -538,7 +538,7 @@ zend_result php_com_do_invoke_byref(php_com_dotnet_object *obj, zend_internal_fu } /* this will create an exception if needed */ - hr = php_com_invoke_helper(obj, dispid, flags, &disp_params, v, 0, 0); + hr = php_com_invoke_helper(obj, dispid, flags, &disp_params, v, false, false); /* release variants */ if (vargs) { @@ -649,7 +649,7 @@ zend_result php_com_do_invoke(php_com_dotnet_object *obj, zend_string *name, return FAILURE; } - return php_com_do_invoke_by_id(obj, dispid, flags, v, nargs, args, 0, allow_noarg); + return php_com_do_invoke_by_id(obj, dispid, flags, v, nargs, args, false, allow_noarg); } /* {{{ Generate a globally unique identifier (GUID) */ 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_misc.c b/ext/com_dotnet/com_misc.c index a5de6415b9a73..6c80bd2b9e24c 100644 --- a/ext/com_dotnet/com_misc.c +++ b/ext/com_dotnet/com_misc.c @@ -73,7 +73,7 @@ PHP_COM_DOTNET_API void php_com_wrap_variant(zval *z, VARIANT *v, VariantInit(&obj->v); VariantCopyInd(&obj->v, v); - obj->modified = 0; + obj->modified = false; if ((V_VT(&obj->v) == VT_DISPATCH) && (V_DISPATCH(&obj->v) != NULL)) { IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &obj->typeinfo); 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..ba5ea177c38a9 100644 --- a/ext/ctype/tests/lc_ctype_inheritance.phpt +++ b/ext/ctype/tests/lc_ctype_inheritance.phpt @@ -4,6 +4,9 @@ Do not inherit LC_CTYPE from environment ctype --SKIPIF-- =')) { + die('skip macOS 15 inherits LC_CTYPE into the thread locale'); +} if (setlocale(LC_ALL, 'invalid') === 'invalid') { die('skip setlocale() is broken /w musl'); } if (!setlocale(LC_CTYPE, "de_DE", "de-DE")) die("skip requires de_DE locale"); ?> diff --git a/ext/curl/curl.stub.php b/ext/curl/curl.stub.php index 7199583b90396..c9cda9c0d4b0c 100644 --- a/ext/curl/curl.stub.php +++ b/ext/curl/curl.stub.php @@ -3339,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 @@ -3733,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 */ @@ -3803,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 640eaa62f2f97..7e4a5789d599a 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: c2245ec496551980ca17ff4472cc1790653e41bd */ + * 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) @@ -891,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); @@ -981,13 +986,24 @@ static void register_curl_symbols(int module_number) 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); - zval attribute_Deprecated_const_CURLOPT_BINARYTRANSFER_0_arg1; 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_arg1, attribute_Deprecated_const_CURLOPT_BINARYTRANSFER_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_CURLOPT_BINARYTRANSFER_0->args[1].value, &attribute_Deprecated_const_CURLOPT_BINARYTRANSFER_0_arg1); + 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); } @@ -1030,9 +1046,9 @@ static zend_class_entry *register_class_CurlSharePersistentHandle(void) zval property_options_default_value; ZVAL_UNDEF(&property_options_default_value); - zend_string *property_options_name = zend_string_init("options", sizeof("options") - 1, 1); + zend_string *property_options_name = zend_string_init("options", sizeof("options") - 1, true); zend_declare_typed_property(class_entry, property_options_name, &property_options_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ARRAY)); - zend_string_release(property_options_name); + zend_string_release_ex(property_options_name, true); return class_entry; } diff --git a/ext/curl/curl_file_arginfo.h b/ext/curl/curl_file_arginfo.h index e409c6e772513..9ddd1f39d8986 100644 --- a/ext/curl/curl_file_arginfo.h +++ b/ext/curl/curl_file_arginfo.h @@ -64,15 +64,15 @@ static zend_class_entry *register_class_CURLFile(void) zval property_mime_default_value; ZVAL_EMPTY_STRING(&property_mime_default_value); - zend_string *property_mime_name = zend_string_init("mime", sizeof("mime") - 1, 1); + zend_string *property_mime_name = zend_string_init("mime", sizeof("mime") - 1, true); zend_declare_typed_property(class_entry, property_mime_name, &property_mime_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_mime_name); + zend_string_release_ex(property_mime_name, true); zval property_postname_default_value; ZVAL_EMPTY_STRING(&property_postname_default_value); - zend_string *property_postname_name = zend_string_init("postname", sizeof("postname") - 1, 1); + zend_string *property_postname_name = zend_string_init("postname", sizeof("postname") - 1, true); zend_declare_typed_property(class_entry, property_postname_name, &property_postname_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_postname_name); + zend_string_release_ex(property_postname_name, true); return class_entry; } @@ -86,21 +86,21 @@ static zend_class_entry *register_class_CURLStringFile(void) zval property_data_default_value; ZVAL_UNDEF(&property_data_default_value); - zend_string *property_data_name = zend_string_init("data", sizeof("data") - 1, 1); + zend_string *property_data_name = zend_string_init("data", sizeof("data") - 1, true); zend_declare_typed_property(class_entry, property_data_name, &property_data_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_data_name); + zend_string_release_ex(property_data_name, true); zval property_postname_default_value; ZVAL_UNDEF(&property_postname_default_value); - zend_string *property_postname_name = zend_string_init("postname", sizeof("postname") - 1, 1); + zend_string *property_postname_name = zend_string_init("postname", sizeof("postname") - 1, true); zend_declare_typed_property(class_entry, property_postname_name, &property_postname_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_postname_name); + zend_string_release_ex(property_postname_name, true); zval property_mime_default_value; ZVAL_UNDEF(&property_mime_default_value); - zend_string *property_mime_name = zend_string_init("mime", sizeof("mime") - 1, 1); + zend_string *property_mime_name = zend_string_init("mime", sizeof("mime") - 1, true); zend_declare_typed_property(class_entry, property_mime_name, &property_mime_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_mime_name); + zend_string_release_ex(property_mime_name, true); return class_entry; } diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 56286fc222e56..5f69beac8e936 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -423,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); @@ -600,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"); @@ -638,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"); @@ -1145,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); @@ -1154,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')) { @@ -1166,7 +1166,7 @@ static void _php_curl_set_default_options(php_curl *ch) } #ifdef ZTS - curl_easy_setopt(ch->cp, CURLOPT_NOSIGNAL, 1); + curl_easy_setopt(ch->cp, CURLOPT_NOSIGNAL, 1L); #endif } /* }}} */ @@ -1544,37 +1544,23 @@ static inline zend_result build_mime_structure_from_hash(php_curl *ch, zval *zpo /* {{{ Copy a cURL handle along with all of it's preferences */ PHP_FUNCTION(curl_copy_handle) { - php_curl *ch; - CURL *cp; zval *zid; - php_curl *dupch; - zval *postfields; ZEND_PARSE_PARAMETERS_START(1,1) Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) ZEND_PARSE_PARAMETERS_END(); - ch = Z_CURL_P(zid); - - cp = curl_easy_duphandle(ch->cp); - if (!cp) { + zend_object *new_object = Z_OBJ_P(zid)->handlers->clone_obj(Z_OBJ_P(zid)); + if (EG(exception)) { + if (new_object != NULL) { + OBJ_RELEASE(new_object); + } + zend_clear_exception(); php_error_docref(NULL, E_WARNING, "Cannot duplicate cURL handle"); RETURN_FALSE; } - dupch = init_curl_handle_into_zval(return_value); - dupch->cp = cp; - - _php_setup_easy_copy_handlers(dupch, ch); - - postfields = &ch->postfields; - if (Z_TYPE_P(postfields) != IS_UNDEF) { - if (build_mime_structure_from_hash(dupch, postfields) == FAILURE) { - zval_ptr_dtor(return_value); - php_error_docref(NULL, E_WARNING, "Cannot rebuild mime structure"); - RETURN_FALSE; - } - } + RETURN_OBJ(new_object); } /* }}} */ @@ -1655,7 +1641,7 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue lval = zval_get_long(zvalue); if (lval == 1) { php_error_docref(NULL, E_NOTICE, "CURLOPT_SSL_VERIFYHOST no longer accepts the value 1, value 2 will be used instead"); - error = curl_easy_setopt(ch->cp, option, 2); + error = curl_easy_setopt(ch->cp, option, 2L); break; } ZEND_FALLTHROUGH; @@ -1944,6 +1930,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); @@ -2166,7 +2155,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); } @@ -2200,7 +2189,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 @@ -2240,11 +2229,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; 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/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_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..601e09d1f71a4 100644 --- a/ext/curl/tests/curl_setopt_ssl.phpt +++ b/ext/curl/tests/curl_setopt_ssl.phpt @@ -18,9 +18,13 @@ if ($curl_version['version_number'] < 0x074700) { --FILE-- ---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..692136bbad2ac 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -714,7 +714,7 @@ static zend_string *date_format(const char *format, size_t format_len, const tim } for (i = 0; i < format_len; i++) { - rfc_colon = 0; + rfc_colon = false; switch (format[i]) { /* day */ case 'd': length = slprintf(buffer, sizeof(buffer), "%02d", (int) t->d); break; @@ -778,7 +778,7 @@ static zend_string *date_format(const char *format, size_t format_len, const tim break; } ZEND_FALLTHROUGH; - case 'P': rfc_colon = 1; ZEND_FALLTHROUGH; + case 'P': rfc_colon = true; ZEND_FALLTHROUGH; case 'O': length = slprintf(buffer, sizeof(buffer), "%c%02d%s%02d", localtime ? ((offset->offset < 0) ? '-' : '+') : '+', localtime ? abs(offset->offset / 3600) : 0, @@ -1486,7 +1486,8 @@ static void create_date_period_datetime(timelib_time *datetime, zend_class_entry if (datetime) { php_date_obj *date_obj; - object_init_ex(zv, ce); + zend_result result = object_init_ex(zv, ce); + ZEND_ASSERT(result == SUCCESS && "should succeed as it reuses an existing object's ce"); date_obj = Z_PHPDATE_P(zv); date_obj->time = timelib_time_clone(datetime); } else { @@ -1502,7 +1503,7 @@ static void create_date_period_interval(timelib_rel_time *interval, zval *zv) object_init_ex(zv, date_ce_interval); interval_obj = Z_PHPINTERVAL_P(zv); interval_obj->diff = timelib_rel_time_clone(interval); - interval_obj->initialized = 1; + interval_obj->initialized = true; } else { ZVAL_NULL(zv); } @@ -1898,7 +1899,7 @@ static void date_object_to_hash(php_date_obj *dateobj, HashTable *props) zval zv; /* first we add the date and time in ISO format */ - ZVAL_STR(&zv, date_format("x-m-d H:i:s.u", sizeof("x-m-d H:i:s.u")-1, dateobj->time, 1)); + ZVAL_STR(&zv, date_format("x-m-d H:i:s.u", sizeof("x-m-d H:i:s.u")-1, dateobj->time, true)); zend_hash_str_update(props, "date", sizeof("date")-1, &zv); /* then we add the timezone name (or similar) */ @@ -1978,7 +1979,7 @@ static zend_object *date_object_clone_timezone(zend_object *this_ptr) /* {{{ */ } new_obj->type = old_obj->type; - new_obj->initialized = 1; + new_obj->initialized = true; switch (new_obj->type) { case TIMELIB_ZONETYPE_ID: new_obj->tzi.tz = old_obj->tzi.tz; @@ -2318,6 +2319,7 @@ static void add_common_properties(HashTable *myht, zend_object *zobj) } /* Advanced Interface */ +/* TODO: remove this API because it is unsafe to use as-is, as it does not propagate the failure/success status. */ PHPAPI zval *php_date_instantiate(zend_class_entry *pce, zval *object) /* {{{ */ { object_init_ex(object, pce); @@ -2595,7 +2597,9 @@ PHP_FUNCTION(date_create_from_format) Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone) ZEND_PARSE_PARAMETERS_END(); - php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, return_value); + if (object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date) != SUCCESS) { + RETURN_THROWS(); + } if (!php_date_initialize(Z_PHPDATE_P(return_value), time_str, time_str_len, format_str, timezone_object, PHP_DATE_INIT_FORMAT)) { zval_ptr_dtor(return_value); RETURN_FALSE; @@ -2617,7 +2621,9 @@ PHP_FUNCTION(date_create_immutable_from_format) Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone) ZEND_PARSE_PARAMETERS_END(); - php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, return_value); + if (object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable) != SUCCESS) { + RETURN_THROWS(); + } if (!php_date_initialize(Z_PHPDATE_P(return_value), time_str, time_str_len, format_str, timezone_object, PHP_DATE_INIT_FORMAT)) { zval_ptr_dtor(return_value); RETURN_FALSE; @@ -2673,7 +2679,9 @@ PHP_METHOD(DateTime, createFromImmutable) old_obj = Z_PHPDATE_P(datetimeimmutable_object); DATE_CHECK_INITIALIZED(old_obj->time, Z_OBJCE_P(datetimeimmutable_object)); - php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, return_value); + if (object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date) != SUCCESS) { + RETURN_THROWS(); + } new_obj = Z_PHPDATE_P(return_value); new_obj->time = timelib_time_clone(old_obj->time); @@ -2694,7 +2702,9 @@ PHP_METHOD(DateTime, createFromInterface) old_obj = Z_PHPDATE_P(datetimeinterface_object); DATE_CHECK_INITIALIZED(old_obj->time, Z_OBJCE_P(datetimeinterface_object)); - php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, return_value); + if (object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date) != SUCCESS) { + RETURN_THROWS(); + } new_obj = Z_PHPDATE_P(return_value); new_obj->time = timelib_time_clone(old_obj->time); @@ -2712,7 +2722,9 @@ PHP_METHOD(DateTime, createFromTimestamp) Z_PARAM_NUMBER(value) ZEND_PARSE_PARAMETERS_END(); - php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, &new_object); + if (object_init_ex(&new_object, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date) != SUCCESS) { + RETURN_THROWS(); + } new_dateobj = Z_PHPDATE_P(&new_object); switch (Z_TYPE_P(value)) { @@ -2748,7 +2760,9 @@ PHP_METHOD(DateTimeImmutable, createFromMutable) old_obj = Z_PHPDATE_P(datetime_object); DATE_CHECK_INITIALIZED(old_obj->time, Z_OBJCE_P(datetime_object)); - php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, return_value); + if (object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable) != SUCCESS) { + RETURN_THROWS(); + } new_obj = Z_PHPDATE_P(return_value); new_obj->time = timelib_time_clone(old_obj->time); @@ -2769,7 +2783,9 @@ PHP_METHOD(DateTimeImmutable, createFromInterface) old_obj = Z_PHPDATE_P(datetimeinterface_object); DATE_CHECK_INITIALIZED(old_obj->time, Z_OBJCE_P(datetimeinterface_object)); - php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, return_value); + if (object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable) != SUCCESS) { + RETURN_THROWS(); + } new_obj = Z_PHPDATE_P(return_value); new_obj->time = timelib_time_clone(old_obj->time); @@ -2787,7 +2803,9 @@ PHP_METHOD(DateTimeImmutable, createFromTimestamp) Z_PARAM_NUMBER(value) ZEND_PARSE_PARAMETERS_END(); - php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, &new_object); + if (object_init_ex(&new_object, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable) != SUCCESS) { + RETURN_THROWS(); + } new_dateobj = Z_PHPDATE_P(&new_object); switch (Z_TYPE_P(value)) { @@ -2856,7 +2874,7 @@ static bool php_date_initialize_from_hash(php_date_obj **dateobj, const HashTabl tzobj = Z_PHPTIMEZONE_P(php_date_instantiate(date_ce_timezone, &tmp_obj)); tzobj->type = TIMELIB_ZONETYPE_ID; tzobj->tzi.tz = tzi; - tzobj->initialized = 1; + tzobj->initialized = true; ret = php_date_initialize(*dateobj, Z_STRVAL_P(z_date), Z_STRLEN_P(z_date), NULL, &tmp_obj, 0); zval_ptr_dtor(&tmp_obj); @@ -2957,9 +2975,9 @@ static bool date_time_is_internal_property(const zend_string *name) zend_string_equals_literal(name, "timezone_type") || zend_string_equals_literal(name, "timezone") ) { - return 1; + return true; } - return 0; + return false; } static void restore_custom_datetime_properties(zval *object, const HashTable *myht) @@ -3223,7 +3241,7 @@ static bool php_date_modify(zval *object, char *modify, size_t modify_len) /* {{ if (!(dateobj->time)) { date_throw_uninitialized_error(Z_OBJCE_P(object)); - return 0; + return false; } tmp_time = timelib_strtotime(modify, modify_len, &err, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); @@ -3238,7 +3256,7 @@ static bool php_date_modify(zval *object, char *modify, size_t modify_len) /* {{ err->error_messages[0].character ? err->error_messages[0].character : ' ', err->error_messages[0].message); timelib_time_dtor(tmp_time); - return 0; + return false; } memcpy(&dateobj->time->relative, &tmp_time->relative, sizeof(timelib_rel_time)); @@ -3291,7 +3309,7 @@ static bool php_date_modify(zval *object, char *modify, size_t modify_len) /* {{ dateobj->time->have_relative = 0; memset(&dateobj->time->relative, 0, sizeof(dateobj->time->relative)); - return 1; + return true; } /* }}} */ /* {{{ Alters the timestamp. */ @@ -3504,7 +3522,7 @@ static void set_timezone_from_timelib_time(php_timezone_obj *tzobj, const timeli } /* Set new values */ - tzobj->initialized = 1; + tzobj->initialized = true; tzobj->type = t->zone_type; switch (t->zone_type) { @@ -3947,7 +3965,7 @@ PHP_FUNCTION(date_diff) zval *object1, *object2; php_date_obj *dateobj1, *dateobj2; php_interval_obj *interval; - bool absolute = 0; + bool absolute = false; if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OO|b", &object1, date_ce_interface, &object2, date_ce_interface, &absolute) == FAILURE) { RETURN_THROWS(); @@ -3963,53 +3981,43 @@ PHP_FUNCTION(date_diff) if (absolute) { interval->diff->invert = 0; } - interval->initialized = 1; + interval->initialized = true; interval->civil_or_wall = PHP_DATE_CIVIL; } /* }}} */ -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 +4034,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 +4055,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 +4086,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); } /* }}} */ /* {{{ */ @@ -4146,9 +4157,9 @@ static bool date_timezone_is_internal_property(const zend_string *name) zend_string_equals_literal(name, "timezone_type") || zend_string_equals_literal(name, "timezone") ) { - return 1; + return true; } - return 0; + return false; } static void restore_custom_datetimezone_properties(zval *object, const HashTable *myht) @@ -4319,10 +4330,10 @@ PHP_FUNCTION(timezone_transitions_get) if (timestamp_begin == ZEND_LONG_MIN) { add_nominal(); begin = 0; - found = 1; + found = true; } else { begin = 0; - found = 0; + found = false; if (tzobj->tzi.tz->bit64.timecnt > 0) { do { if (tzobj->tzi.tz->trans[begin] > timestamp_begin) { @@ -4331,7 +4342,7 @@ PHP_FUNCTION(timezone_transitions_get) } else { add_nominal(); } - found = 1; + found = true; break; } begin++; @@ -4629,7 +4640,7 @@ static void php_date_interval_initialize_from_hash(zval **return_value, php_inte } (*intobj)->diff = timelib_rel_time_clone(&time->relative); - (*intobj)->initialized = 1; + (*intobj)->initialized = true; (*intobj)->civil_or_wall = PHP_DATE_CIVIL; (*intobj)->from_string = true; (*intobj)->date_string = zend_string_copy(Z_STR_P(date_str)); @@ -4726,7 +4737,7 @@ static void php_date_interval_initialize_from_hash(zval **return_value, php_inte } } - (*intobj)->initialized = 1; + (*intobj)->initialized = true; } /* }}} */ /* {{{ */ @@ -4780,9 +4791,9 @@ static bool date_interval_is_internal_property(const zend_string *name) zend_string_equals_literal(name, "invert") || zend_string_equals_literal(name, "days") ) { - return 1; + return true; } - return 0; + return false; } static void restore_custom_dateinterval_properties(zval *object, const HashTable *myht) @@ -4841,7 +4852,7 @@ static void date_interval_instantiate_from_time(zval *return_value, timelib_time php_date_instantiate(date_ce_interval, return_value); diobj = Z_PHPINTERVAL_P(return_value); diobj->diff = timelib_rel_time_clone(&time->relative); - diobj->initialized = 1; + diobj->initialized = true; diobj->civil_or_wall = PHP_DATE_CIVIL; diobj->from_string = true; diobj->date_string = zend_string_copy(time_str); @@ -5097,7 +5108,7 @@ static bool date_period_init_finish(php_period_obj *dpobj, zend_long options, ze dpobj->recurrences = (int)recurrences; - dpobj->initialized = 1; + dpobj->initialized = true; return true; } @@ -5115,7 +5126,9 @@ PHP_METHOD(DatePeriod, createFromISO8601String) Z_PARAM_LONG(options) ZEND_PARSE_PARAMETERS_END(); - object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_period); + if (object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_period) != SUCCESS) { + RETURN_THROWS(); + } dpobj = Z_PHPPERIOD_P(return_value); dpobj->current = NULL; @@ -5267,7 +5280,7 @@ PHP_METHOD(DatePeriod, getDateInterval) php_date_instantiate(date_ce_interval, return_value); diobj = Z_PHPINTERVAL_P(return_value); diobj->diff = timelib_rel_time_clone(dpobj->interval); - diobj->initialized = 1; + diobj->initialized = true; } /* }}} */ @@ -5297,18 +5310,18 @@ PHP_METHOD(DatePeriod, getIterator) static bool check_id_allowed(const char *id, zend_long what) /* {{{ */ { - if ((what & PHP_DATE_TIMEZONE_GROUP_AFRICA) && strncasecmp(id, "Africa/", 7) == 0) return 1; - if ((what & PHP_DATE_TIMEZONE_GROUP_AMERICA) && strncasecmp(id, "America/", 8) == 0) return 1; - if ((what & PHP_DATE_TIMEZONE_GROUP_ANTARCTICA) && strncasecmp(id, "Antarctica/", 11) == 0) return 1; - if ((what & PHP_DATE_TIMEZONE_GROUP_ARCTIC) && strncasecmp(id, "Arctic/", 7) == 0) return 1; - if ((what & PHP_DATE_TIMEZONE_GROUP_ASIA) && strncasecmp(id, "Asia/", 5) == 0) return 1; - if ((what & PHP_DATE_TIMEZONE_GROUP_ATLANTIC) && strncasecmp(id, "Atlantic/", 9) == 0) return 1; - if ((what & PHP_DATE_TIMEZONE_GROUP_AUSTRALIA) && strncasecmp(id, "Australia/", 10) == 0) return 1; - if ((what & PHP_DATE_TIMEZONE_GROUP_EUROPE) && strncasecmp(id, "Europe/", 7) == 0) return 1; - if ((what & PHP_DATE_TIMEZONE_GROUP_INDIAN) && strncasecmp(id, "Indian/", 7) == 0) return 1; - if ((what & PHP_DATE_TIMEZONE_GROUP_PACIFIC) && strncasecmp(id, "Pacific/", 8) == 0) return 1; - if ((what & PHP_DATE_TIMEZONE_GROUP_UTC) && strncasecmp(id, "UTC", 3) == 0) return 1; - return 0; + if ((what & PHP_DATE_TIMEZONE_GROUP_AFRICA) && strncasecmp(id, "Africa/", 7) == 0) return true; + if ((what & PHP_DATE_TIMEZONE_GROUP_AMERICA) && strncasecmp(id, "America/", 8) == 0) return true; + if ((what & PHP_DATE_TIMEZONE_GROUP_ANTARCTICA) && strncasecmp(id, "Antarctica/", 11) == 0) return true; + if ((what & PHP_DATE_TIMEZONE_GROUP_ARCTIC) && strncasecmp(id, "Arctic/", 7) == 0) return true; + if ((what & PHP_DATE_TIMEZONE_GROUP_ASIA) && strncasecmp(id, "Asia/", 5) == 0) return true; + if ((what & PHP_DATE_TIMEZONE_GROUP_ATLANTIC) && strncasecmp(id, "Atlantic/", 9) == 0) return true; + if ((what & PHP_DATE_TIMEZONE_GROUP_AUSTRALIA) && strncasecmp(id, "Australia/", 10) == 0) return true; + if ((what & PHP_DATE_TIMEZONE_GROUP_EUROPE) && strncasecmp(id, "Europe/", 7) == 0) return true; + if ((what & PHP_DATE_TIMEZONE_GROUP_INDIAN) && strncasecmp(id, "Indian/", 7) == 0) return true; + if ((what & PHP_DATE_TIMEZONE_GROUP_PACIFIC) && strncasecmp(id, "Pacific/", 8) == 0) return true; + if ((what & PHP_DATE_TIMEZONE_GROUP_UTC) && strncasecmp(id, "UTC", 3) == 0) return true; + return false; } /* }}} */ /* {{{ Returns numerically index array with all timezone identifiers. */ @@ -5500,7 +5513,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); @@ -5715,7 +5728,7 @@ static bool php_date_period_initialize_from_hash(php_period_obj *period_obj, con date_obj = Z_PHPDATE_P(ht_entry); if (!date_obj->time) { - return 0; + return false; } if (period_obj->start != NULL) { @@ -5724,10 +5737,10 @@ static bool php_date_period_initialize_from_hash(php_period_obj *period_obj, con period_obj->start = timelib_time_clone(date_obj->time); period_obj->start_ce = Z_OBJCE_P(ht_entry); } else if (Z_TYPE_P(ht_entry) != IS_NULL) { - return 0; + return false; } } else { - return 0; + return false; } ht_entry = zend_hash_str_find(myht, "end", sizeof("end")-1); @@ -5737,7 +5750,7 @@ static bool php_date_period_initialize_from_hash(php_period_obj *period_obj, con date_obj = Z_PHPDATE_P(ht_entry); if (!date_obj->time) { - return 0; + return false; } if (period_obj->end != NULL) { @@ -5745,10 +5758,10 @@ static bool php_date_period_initialize_from_hash(php_period_obj *period_obj, con } period_obj->end = timelib_time_clone(date_obj->time); } else if (Z_TYPE_P(ht_entry) != IS_NULL) { - return 0; + return false; } } else { - return 0; + return false; } ht_entry = zend_hash_str_find(myht, "current", sizeof("current")-1); @@ -5758,7 +5771,7 @@ static bool php_date_period_initialize_from_hash(php_period_obj *period_obj, con date_obj = Z_PHPDATE_P(ht_entry); if (!date_obj->time) { - return 0; + return false; } if (period_obj->current != NULL) { @@ -5766,10 +5779,10 @@ static bool php_date_period_initialize_from_hash(php_period_obj *period_obj, con } period_obj->current = timelib_time_clone(date_obj->time); } else if (Z_TYPE_P(ht_entry) != IS_NULL) { - return 0; + return false; } } else { - return 0; + return false; } ht_entry = zend_hash_str_find(myht, "interval", sizeof("interval")-1); @@ -5779,7 +5792,7 @@ static bool php_date_period_initialize_from_hash(php_period_obj *period_obj, con interval_obj = Z_PHPINTERVAL_P(ht_entry); if (!interval_obj->initialized) { - return 0; + return false; } if (period_obj->interval != NULL) { @@ -5787,10 +5800,10 @@ static bool php_date_period_initialize_from_hash(php_period_obj *period_obj, con } period_obj->interval = timelib_rel_time_clone(interval_obj->diff); } else { /* interval is required */ - return 0; + return false; } } else { - return 0; + return false; } ht_entry = zend_hash_str_find(myht, "recurrences", sizeof("recurrences")-1); @@ -5798,7 +5811,7 @@ static bool php_date_period_initialize_from_hash(php_period_obj *period_obj, con Z_TYPE_P(ht_entry) == IS_LONG && Z_LVAL_P(ht_entry) >= 0 && Z_LVAL_P(ht_entry) <= INT_MAX) { period_obj->recurrences = Z_LVAL_P(ht_entry); } else { - return 0; + return false; } ht_entry = zend_hash_str_find(myht, "include_start_date", sizeof("include_start_date")-1); @@ -5806,7 +5819,7 @@ static bool php_date_period_initialize_from_hash(php_period_obj *period_obj, con (Z_TYPE_P(ht_entry) == IS_FALSE || Z_TYPE_P(ht_entry) == IS_TRUE)) { period_obj->include_start_date = (Z_TYPE_P(ht_entry) == IS_TRUE); } else { - return 0; + return false; } ht_entry = zend_hash_str_find(myht, "include_end_date", sizeof("include_end_date")-1); @@ -5814,12 +5827,12 @@ static bool php_date_period_initialize_from_hash(php_period_obj *period_obj, con (Z_TYPE_P(ht_entry) == IS_FALSE || Z_TYPE_P(ht_entry) == IS_TRUE)) { period_obj->include_end_date = (Z_TYPE_P(ht_entry) == IS_TRUE); } else { - return 0; + return false; } - period_obj->initialized = 1; + period_obj->initialized = true; - return 1; + return true; } /* }}} */ /* {{{ */ @@ -5876,9 +5889,9 @@ static bool date_period_is_internal_property(const zend_string *name) zend_string_equals_literal(name, "include_start_date") || zend_string_equals_literal(name, "include_end_date") ) { - return 1; + return true; } - return 0; + return false; } /* }}} */ diff --git a/ext/date/php_date.stub.php b/ext/date/php_date.stub.php index 4f77fc9223e27..da2182dfb6fa7 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"; @@ -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; @@ -334,6 +323,7 @@ public function getMicrosecond(): int; public function diff(DateTimeInterface $targetObject, bool $absolute = false): DateInterval; /** @tentative-return-type */ + #[\Deprecated(since: '8.5', message: 'this method is obsolete, as serialization hooks are provided by __unserialize() and __serialize()')] public function __wakeup(): void; public function __serialize(): array; @@ -350,6 +340,7 @@ public function __serialize(): array {} public function __unserialize(array $data): void {} /** @tentative-return-type */ + #[\Deprecated(since: '8.5', message: 'this method is obsolete, as serialization hooks are provided by __unserialize() and __serialize()')] public function __wakeup(): void {} /** @tentative-return-type */ @@ -467,6 +458,7 @@ public function __serialize(): array {} public function __unserialize(array $data): void {} /** @tentative-return-type */ + #[\Deprecated(since: '8.5', message: 'this method is obsolete, as serialization hooks are provided by __unserialize() and __serialize()')] public function __wakeup(): void {} /** @tentative-return-type */ @@ -643,6 +635,7 @@ public function __serialize(): array {} public function __unserialize(array $data): void {} /** @tentative-return-type */ + #[\Deprecated(since: '8.5', message: 'this method is obsolete, as serialization hooks are provided by __unserialize() and __serialize()')] public function __wakeup(): void {} /** @tentative-return-type */ @@ -669,6 +662,7 @@ public function __serialize(): array; public function __unserialize(array $data): void; /** @tentative-return-type */ + #[\Deprecated(since: '8.5', message: 'this method is obsolete, as serialization hooks are provided by __unserialize() and __serialize()')] public function __wakeup(): void {} /** @tentative-return-type */ @@ -745,6 +739,7 @@ public function __serialize(): array; public function __unserialize(array $data): void; /** @tentative-return-type */ + #[\Deprecated(since: '8.5', message: 'this method is obsolete, as serialization hooks are provided by __unserialize() and __serialize()')] public function __wakeup(): void {} /** @tentative-return-type */ diff --git a/ext/date/php_date_arginfo.h b/ext/date/php_date_arginfo.h index a96d4cd4aa302..74541e13a5c19 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: c9dba59a68085579d18948963a979d63eecff204 */ + * Stub hash: 8556e1b5f05ae9f78200f05f01d9f8e815cba49d */ 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) @@ -675,7 +675,7 @@ static const zend_function_entry class_DateTimeInterface_methods[] = { ZEND_RAW_FENTRY("getTimestamp", NULL, arginfo_class_DateTimeInterface_getTimestamp, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT, NULL, NULL) ZEND_RAW_FENTRY("getMicrosecond", NULL, arginfo_class_DateTimeInterface_getMicrosecond, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT, NULL, NULL) ZEND_RAW_FENTRY("diff", NULL, arginfo_class_DateTimeInterface_diff, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT, NULL, NULL) - ZEND_RAW_FENTRY("__wakeup", NULL, arginfo_class_DateTimeInterface___wakeup, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT, NULL, NULL) + ZEND_RAW_FENTRY("__wakeup", NULL, arginfo_class_DateTimeInterface___wakeup, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED, NULL, NULL) ZEND_RAW_FENTRY("__serialize", NULL, arginfo_class_DateTimeInterface___serialize, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT, NULL, NULL) ZEND_RAW_FENTRY("__unserialize", NULL, arginfo_class_DateTimeInterface___unserialize, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT, NULL, NULL) ZEND_FE_END @@ -685,7 +685,7 @@ static const zend_function_entry class_DateTime_methods[] = { ZEND_ME(DateTime, __construct, arginfo_class_DateTime___construct, ZEND_ACC_PUBLIC) ZEND_ME(DateTime, __serialize, arginfo_class_DateTime___serialize, ZEND_ACC_PUBLIC) ZEND_ME(DateTime, __unserialize, arginfo_class_DateTime___unserialize, ZEND_ACC_PUBLIC) - ZEND_ME(DateTime, __wakeup, arginfo_class_DateTime___wakeup, ZEND_ACC_PUBLIC) + ZEND_ME(DateTime, __wakeup, arginfo_class_DateTime___wakeup, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED) ZEND_ME(DateTime, __set_state, arginfo_class_DateTime___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_ME(DateTime, createFromImmutable, arginfo_class_DateTime_createFromImmutable, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_ME(DateTime, createFromInterface, arginfo_class_DateTime_createFromInterface, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) @@ -714,7 +714,7 @@ static const zend_function_entry class_DateTimeImmutable_methods[] = { ZEND_ME(DateTimeImmutable, __construct, arginfo_class_DateTimeImmutable___construct, ZEND_ACC_PUBLIC) ZEND_ME(DateTimeImmutable, __serialize, arginfo_class_DateTimeImmutable___serialize, ZEND_ACC_PUBLIC) ZEND_ME(DateTimeImmutable, __unserialize, arginfo_class_DateTimeImmutable___unserialize, ZEND_ACC_PUBLIC) - ZEND_ME(DateTimeImmutable, __wakeup, arginfo_class_DateTimeImmutable___wakeup, ZEND_ACC_PUBLIC) + ZEND_ME(DateTimeImmutable, __wakeup, arginfo_class_DateTimeImmutable___wakeup, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED) ZEND_ME(DateTimeImmutable, __set_state, arginfo_class_DateTimeImmutable___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_RAW_FENTRY("createFromFormat", zif_date_create_immutable_from_format, arginfo_class_DateTimeImmutable_createFromFormat, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, NULL) ZEND_ME(DateTimeImmutable, createFromTimestamp, arginfo_class_DateTimeImmutable_createFromTimestamp, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) @@ -749,7 +749,7 @@ static const zend_function_entry class_DateTimeZone_methods[] = { ZEND_RAW_FENTRY("listIdentifiers", zif_timezone_identifiers_list, arginfo_class_DateTimeZone_listIdentifiers, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, NULL) ZEND_ME(DateTimeZone, __serialize, arginfo_class_DateTimeZone___serialize, ZEND_ACC_PUBLIC) ZEND_ME(DateTimeZone, __unserialize, arginfo_class_DateTimeZone___unserialize, ZEND_ACC_PUBLIC) - ZEND_ME(DateTimeZone, __wakeup, arginfo_class_DateTimeZone___wakeup, ZEND_ACC_PUBLIC) + ZEND_ME(DateTimeZone, __wakeup, arginfo_class_DateTimeZone___wakeup, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED) ZEND_ME(DateTimeZone, __set_state, arginfo_class_DateTimeZone___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_FE_END }; @@ -760,7 +760,7 @@ static const zend_function_entry class_DateInterval_methods[] = { ZEND_RAW_FENTRY("format", zif_date_interval_format, arginfo_class_DateInterval_format, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_ME(DateInterval, __serialize, arginfo_class_DateInterval___serialize, ZEND_ACC_PUBLIC) ZEND_ME(DateInterval, __unserialize, arginfo_class_DateInterval___unserialize, ZEND_ACC_PUBLIC) - ZEND_ME(DateInterval, __wakeup, arginfo_class_DateInterval___wakeup, ZEND_ACC_PUBLIC) + ZEND_ME(DateInterval, __wakeup, arginfo_class_DateInterval___wakeup, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED) ZEND_ME(DateInterval, __set_state, arginfo_class_DateInterval___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_FE_END }; @@ -774,7 +774,7 @@ static const zend_function_entry class_DatePeriod_methods[] = { ZEND_ME(DatePeriod, getRecurrences, arginfo_class_DatePeriod_getRecurrences, ZEND_ACC_PUBLIC) ZEND_ME(DatePeriod, __serialize, arginfo_class_DatePeriod___serialize, ZEND_ACC_PUBLIC) ZEND_ME(DatePeriod, __unserialize, arginfo_class_DatePeriod___unserialize, ZEND_ACC_PUBLIC) - ZEND_ME(DatePeriod, __wakeup, arginfo_class_DatePeriod___wakeup, ZEND_ACC_PUBLIC) + ZEND_ME(DatePeriod, __wakeup, arginfo_class_DatePeriod___wakeup, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED) ZEND_ME(DatePeriod, __set_state, arginfo_class_DatePeriod___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_ME(DatePeriod, getIterator, arginfo_class_DatePeriod_getIterator, ZEND_ACC_PUBLIC) ZEND_FE_END @@ -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); @@ -816,64 +816,53 @@ static void register_php_date_symbols(int module_number) 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_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_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_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_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); - zval attribute_Deprecated_const_SUNFUNCS_RET_TIMESTAMP_0_arg1; 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_arg1, attribute_Deprecated_const_SUNFUNCS_RET_TIMESTAMP_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_SUNFUNCS_RET_TIMESTAMP_0->args[1].value, &attribute_Deprecated_const_SUNFUNCS_RET_TIMESTAMP_0_arg1); + 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 attribute_Deprecated_const_SUNFUNCS_RET_STRING_0_arg1; - zend_string *attribute_Deprecated_const_SUNFUNCS_RET_STRING_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_STRING_0_arg1, attribute_Deprecated_const_SUNFUNCS_RET_STRING_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_SUNFUNCS_RET_STRING_0->args[1].value, &attribute_Deprecated_const_SUNFUNCS_RET_STRING_0_arg1); + 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 attribute_Deprecated_const_SUNFUNCS_RET_DOUBLE_0_arg1; - zend_string *attribute_Deprecated_const_SUNFUNCS_RET_DOUBLE_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_DOUBLE_0_arg1, attribute_Deprecated_const_SUNFUNCS_RET_DOUBLE_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_SUNFUNCS_RET_DOUBLE_0->args[1].value, &attribute_Deprecated_const_SUNFUNCS_RET_DOUBLE_0_arg1); + 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); } @@ -887,100 +876,116 @@ static zend_class_entry *register_class_DateTimeInterface(void) zval const_ATOM_value; zend_string *const_ATOM_value_str = zend_string_init(DATE_FORMAT_RFC3339, strlen(DATE_FORMAT_RFC3339), 1); ZVAL_STR(&const_ATOM_value, const_ATOM_value_str); - zend_string *const_ATOM_name = zend_string_init_interned("ATOM", sizeof("ATOM") - 1, 1); + zend_string *const_ATOM_name = zend_string_init_interned("ATOM", sizeof("ATOM") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATOM_name, &const_ATOM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(const_ATOM_name); + zend_string_release_ex(const_ATOM_name, true); zval const_COOKIE_value; zend_string *const_COOKIE_value_str = zend_string_init(DATE_FORMAT_COOKIE, strlen(DATE_FORMAT_COOKIE), 1); ZVAL_STR(&const_COOKIE_value, const_COOKIE_value_str); - zend_string *const_COOKIE_name = zend_string_init_interned("COOKIE", sizeof("COOKIE") - 1, 1); + zend_string *const_COOKIE_name = zend_string_init_interned("COOKIE", sizeof("COOKIE") - 1, true); zend_declare_typed_class_constant(class_entry, const_COOKIE_name, &const_COOKIE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(const_COOKIE_name); + zend_string_release_ex(const_COOKIE_name, true); zval const_ISO8601_value; zend_string *const_ISO8601_value_str = zend_string_init(DATE_FORMAT_ISO8601, strlen(DATE_FORMAT_ISO8601), 1); ZVAL_STR(&const_ISO8601_value, const_ISO8601_value_str); - zend_string *const_ISO8601_name = zend_string_init_interned("ISO8601", sizeof("ISO8601") - 1, 1); + zend_string *const_ISO8601_name = zend_string_init_interned("ISO8601", sizeof("ISO8601") - 1, true); zend_declare_typed_class_constant(class_entry, const_ISO8601_name, &const_ISO8601_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(const_ISO8601_name); + zend_string_release_ex(const_ISO8601_name, true); zval const_ISO8601_EXPANDED_value; zend_string *const_ISO8601_EXPANDED_value_str = zend_string_init(DATE_FORMAT_ISO8601_EXPANDED, strlen(DATE_FORMAT_ISO8601_EXPANDED), 1); ZVAL_STR(&const_ISO8601_EXPANDED_value, const_ISO8601_EXPANDED_value_str); - zend_string *const_ISO8601_EXPANDED_name = zend_string_init_interned("ISO8601_EXPANDED", sizeof("ISO8601_EXPANDED") - 1, 1); + zend_string *const_ISO8601_EXPANDED_name = zend_string_init_interned("ISO8601_EXPANDED", sizeof("ISO8601_EXPANDED") - 1, true); zend_declare_typed_class_constant(class_entry, const_ISO8601_EXPANDED_name, &const_ISO8601_EXPANDED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(const_ISO8601_EXPANDED_name); + zend_string_release_ex(const_ISO8601_EXPANDED_name, true); zval const_RFC822_value; zend_string *const_RFC822_value_str = zend_string_init(DATE_FORMAT_RFC822, strlen(DATE_FORMAT_RFC822), 1); ZVAL_STR(&const_RFC822_value, const_RFC822_value_str); - zend_string *const_RFC822_name = zend_string_init_interned("RFC822", sizeof("RFC822") - 1, 1); + zend_string *const_RFC822_name = zend_string_init_interned("RFC822", sizeof("RFC822") - 1, true); zend_declare_typed_class_constant(class_entry, const_RFC822_name, &const_RFC822_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(const_RFC822_name); + zend_string_release_ex(const_RFC822_name, true); zval const_RFC850_value; zend_string *const_RFC850_value_str = zend_string_init(DATE_FORMAT_RFC850, strlen(DATE_FORMAT_RFC850), 1); ZVAL_STR(&const_RFC850_value, const_RFC850_value_str); - zend_string *const_RFC850_name = zend_string_init_interned("RFC850", sizeof("RFC850") - 1, 1); + zend_string *const_RFC850_name = zend_string_init_interned("RFC850", sizeof("RFC850") - 1, true); zend_declare_typed_class_constant(class_entry, const_RFC850_name, &const_RFC850_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(const_RFC850_name); + zend_string_release_ex(const_RFC850_name, true); zval const_RFC1036_value; zend_string *const_RFC1036_value_str = zend_string_init(DATE_FORMAT_RFC1036, strlen(DATE_FORMAT_RFC1036), 1); ZVAL_STR(&const_RFC1036_value, const_RFC1036_value_str); - zend_string *const_RFC1036_name = zend_string_init_interned("RFC1036", sizeof("RFC1036") - 1, 1); + zend_string *const_RFC1036_name = zend_string_init_interned("RFC1036", sizeof("RFC1036") - 1, true); zend_declare_typed_class_constant(class_entry, const_RFC1036_name, &const_RFC1036_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(const_RFC1036_name); + zend_string_release_ex(const_RFC1036_name, true); zval const_RFC1123_value; zend_string *const_RFC1123_value_str = zend_string_init(DATE_FORMAT_RFC1123, strlen(DATE_FORMAT_RFC1123), 1); ZVAL_STR(&const_RFC1123_value, const_RFC1123_value_str); - zend_string *const_RFC1123_name = zend_string_init_interned("RFC1123", sizeof("RFC1123") - 1, 1); + zend_string *const_RFC1123_name = zend_string_init_interned("RFC1123", sizeof("RFC1123") - 1, true); zend_declare_typed_class_constant(class_entry, const_RFC1123_name, &const_RFC1123_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(const_RFC1123_name); + zend_string_release_ex(const_RFC1123_name, true); zval const_RFC7231_value; 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_string_release(const_RFC7231_name); + zend_string *const_RFC7231_name = zend_string_init_interned("RFC7231", sizeof("RFC7231") - 1, true); + 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_ex(const_RFC7231_name, true); zval const_RFC2822_value; zend_string *const_RFC2822_value_str = zend_string_init(DATE_FORMAT_RFC2822, strlen(DATE_FORMAT_RFC2822), 1); ZVAL_STR(&const_RFC2822_value, const_RFC2822_value_str); - zend_string *const_RFC2822_name = zend_string_init_interned("RFC2822", sizeof("RFC2822") - 1, 1); + zend_string *const_RFC2822_name = zend_string_init_interned("RFC2822", sizeof("RFC2822") - 1, true); zend_declare_typed_class_constant(class_entry, const_RFC2822_name, &const_RFC2822_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(const_RFC2822_name); + zend_string_release_ex(const_RFC2822_name, true); zval const_RFC3339_value; zend_string *const_RFC3339_value_str = zend_string_init(DATE_FORMAT_RFC3339, strlen(DATE_FORMAT_RFC3339), 1); ZVAL_STR(&const_RFC3339_value, const_RFC3339_value_str); - zend_string *const_RFC3339_name = zend_string_init_interned("RFC3339", sizeof("RFC3339") - 1, 1); + zend_string *const_RFC3339_name = zend_string_init_interned("RFC3339", sizeof("RFC3339") - 1, true); zend_declare_typed_class_constant(class_entry, const_RFC3339_name, &const_RFC3339_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(const_RFC3339_name); + zend_string_release_ex(const_RFC3339_name, true); zval const_RFC3339_EXTENDED_value; zend_string *const_RFC3339_EXTENDED_value_str = zend_string_init(DATE_FORMAT_RFC3339_EXTENDED, strlen(DATE_FORMAT_RFC3339_EXTENDED), 1); ZVAL_STR(&const_RFC3339_EXTENDED_value, const_RFC3339_EXTENDED_value_str); - zend_string *const_RFC3339_EXTENDED_name = zend_string_init_interned("RFC3339_EXTENDED", sizeof("RFC3339_EXTENDED") - 1, 1); + zend_string *const_RFC3339_EXTENDED_name = zend_string_init_interned("RFC3339_EXTENDED", sizeof("RFC3339_EXTENDED") - 1, true); zend_declare_typed_class_constant(class_entry, const_RFC3339_EXTENDED_name, &const_RFC3339_EXTENDED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(const_RFC3339_EXTENDED_name); + zend_string_release_ex(const_RFC3339_EXTENDED_name, true); zval const_RSS_value; zend_string *const_RSS_value_str = zend_string_init(DATE_FORMAT_RFC1123, strlen(DATE_FORMAT_RFC1123), 1); ZVAL_STR(&const_RSS_value, const_RSS_value_str); - zend_string *const_RSS_name = zend_string_init_interned("RSS", sizeof("RSS") - 1, 1); + zend_string *const_RSS_name = zend_string_init_interned("RSS", sizeof("RSS") - 1, true); zend_declare_typed_class_constant(class_entry, const_RSS_name, &const_RSS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(const_RSS_name); + zend_string_release_ex(const_RSS_name, true); zval const_W3C_value; zend_string *const_W3C_value_str = zend_string_init(DATE_FORMAT_RFC3339, strlen(DATE_FORMAT_RFC3339), 1); ZVAL_STR(&const_W3C_value, const_W3C_value_str); - zend_string *const_W3C_name = zend_string_init_interned("W3C", sizeof("W3C") - 1, 1); + zend_string *const_W3C_name = zend_string_init_interned("W3C", sizeof("W3C") - 1, true); 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_string_release_ex(const_W3C_name, true); + + + 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); + + + 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_STR(&attribute_Deprecated_func___wakeup_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_func___wakeup_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + 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->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; } @@ -993,6 +998,14 @@ static zend_class_entry *register_class_DateTime(zend_class_entry *class_entry_D class_entry = zend_register_internal_class_with_flags(&ce, NULL, 0); zend_class_implements(class_entry, 1, class_entry_DateTimeInterface); + + 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_STR(&attribute_Deprecated_func___wakeup_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_func___wakeup_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + 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->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; } @@ -1005,85 +1018,74 @@ static zend_class_entry *register_class_DateTimeImmutable(zend_class_entry *clas zend_class_implements(class_entry, 1, class_entry_DateTimeInterface); - zend_string *attribute_name_NoDiscard_func_modify_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); + 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_STR(&attribute_Deprecated_func___wakeup_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_func___wakeup_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + 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->args[1].value, attribute_Deprecated_func___wakeup_0_arg1_str); + attribute_Deprecated_func___wakeup_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_string *attribute_name_NoDiscard_func_modify_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, true); 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_release_ex(attribute_name_NoDiscard_func_modify_0, true); 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_string *attribute_name_NoDiscard_func_add_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, true); 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_release_ex(attribute_name_NoDiscard_func_add_0, true); 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_string *attribute_name_NoDiscard_func_sub_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, true); 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_release_ex(attribute_name_NoDiscard_func_sub_0, true); 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_string *attribute_name_NoDiscard_func_settimezone_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, true); 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_release_ex(attribute_name_NoDiscard_func_settimezone_0, true); 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_string *attribute_name_NoDiscard_func_settime_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, true); 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_release_ex(attribute_name_NoDiscard_func_settime_0, true); 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_string *attribute_name_NoDiscard_func_setdate_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, true); 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_release_ex(attribute_name_NoDiscard_func_setdate_0, true); 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_string *attribute_name_NoDiscard_func_setisodate_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, true); 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_release_ex(attribute_name_NoDiscard_func_setisodate_0, true); 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_string *attribute_name_NoDiscard_func_settimestamp_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, true); 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_release_ex(attribute_name_NoDiscard_func_settimestamp_0, true); 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_string *attribute_name_NoDiscard_func_setmicrosecond_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, true); 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_release_ex(attribute_name_NoDiscard_func_setmicrosecond_0, true); 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; @@ -1098,87 +1100,95 @@ static zend_class_entry *register_class_DateTimeZone(void) zval const_AFRICA_value; ZVAL_LONG(&const_AFRICA_value, PHP_DATE_TIMEZONE_GROUP_AFRICA); - zend_string *const_AFRICA_name = zend_string_init_interned("AFRICA", sizeof("AFRICA") - 1, 1); + zend_string *const_AFRICA_name = zend_string_init_interned("AFRICA", sizeof("AFRICA") - 1, true); zend_declare_typed_class_constant(class_entry, const_AFRICA_name, &const_AFRICA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_AFRICA_name); + zend_string_release_ex(const_AFRICA_name, true); zval const_AMERICA_value; ZVAL_LONG(&const_AMERICA_value, PHP_DATE_TIMEZONE_GROUP_AMERICA); - zend_string *const_AMERICA_name = zend_string_init_interned("AMERICA", sizeof("AMERICA") - 1, 1); + zend_string *const_AMERICA_name = zend_string_init_interned("AMERICA", sizeof("AMERICA") - 1, true); zend_declare_typed_class_constant(class_entry, const_AMERICA_name, &const_AMERICA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_AMERICA_name); + zend_string_release_ex(const_AMERICA_name, true); zval const_ANTARCTICA_value; ZVAL_LONG(&const_ANTARCTICA_value, PHP_DATE_TIMEZONE_GROUP_ANTARCTICA); - zend_string *const_ANTARCTICA_name = zend_string_init_interned("ANTARCTICA", sizeof("ANTARCTICA") - 1, 1); + zend_string *const_ANTARCTICA_name = zend_string_init_interned("ANTARCTICA", sizeof("ANTARCTICA") - 1, true); zend_declare_typed_class_constant(class_entry, const_ANTARCTICA_name, &const_ANTARCTICA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ANTARCTICA_name); + zend_string_release_ex(const_ANTARCTICA_name, true); zval const_ARCTIC_value; ZVAL_LONG(&const_ARCTIC_value, PHP_DATE_TIMEZONE_GROUP_ARCTIC); - zend_string *const_ARCTIC_name = zend_string_init_interned("ARCTIC", sizeof("ARCTIC") - 1, 1); + zend_string *const_ARCTIC_name = zend_string_init_interned("ARCTIC", sizeof("ARCTIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_ARCTIC_name, &const_ARCTIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ARCTIC_name); + zend_string_release_ex(const_ARCTIC_name, true); zval const_ASIA_value; ZVAL_LONG(&const_ASIA_value, PHP_DATE_TIMEZONE_GROUP_ASIA); - zend_string *const_ASIA_name = zend_string_init_interned("ASIA", sizeof("ASIA") - 1, 1); + zend_string *const_ASIA_name = zend_string_init_interned("ASIA", sizeof("ASIA") - 1, true); zend_declare_typed_class_constant(class_entry, const_ASIA_name, &const_ASIA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ASIA_name); + zend_string_release_ex(const_ASIA_name, true); zval const_ATLANTIC_value; ZVAL_LONG(&const_ATLANTIC_value, PHP_DATE_TIMEZONE_GROUP_ATLANTIC); - zend_string *const_ATLANTIC_name = zend_string_init_interned("ATLANTIC", sizeof("ATLANTIC") - 1, 1); + zend_string *const_ATLANTIC_name = zend_string_init_interned("ATLANTIC", sizeof("ATLANTIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATLANTIC_name, &const_ATLANTIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATLANTIC_name); + zend_string_release_ex(const_ATLANTIC_name, true); zval const_AUSTRALIA_value; ZVAL_LONG(&const_AUSTRALIA_value, PHP_DATE_TIMEZONE_GROUP_AUSTRALIA); - zend_string *const_AUSTRALIA_name = zend_string_init_interned("AUSTRALIA", sizeof("AUSTRALIA") - 1, 1); + zend_string *const_AUSTRALIA_name = zend_string_init_interned("AUSTRALIA", sizeof("AUSTRALIA") - 1, true); zend_declare_typed_class_constant(class_entry, const_AUSTRALIA_name, &const_AUSTRALIA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_AUSTRALIA_name); + zend_string_release_ex(const_AUSTRALIA_name, true); zval const_EUROPE_value; ZVAL_LONG(&const_EUROPE_value, PHP_DATE_TIMEZONE_GROUP_EUROPE); - zend_string *const_EUROPE_name = zend_string_init_interned("EUROPE", sizeof("EUROPE") - 1, 1); + zend_string *const_EUROPE_name = zend_string_init_interned("EUROPE", sizeof("EUROPE") - 1, true); zend_declare_typed_class_constant(class_entry, const_EUROPE_name, &const_EUROPE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EUROPE_name); + zend_string_release_ex(const_EUROPE_name, true); zval const_INDIAN_value; ZVAL_LONG(&const_INDIAN_value, PHP_DATE_TIMEZONE_GROUP_INDIAN); - zend_string *const_INDIAN_name = zend_string_init_interned("INDIAN", sizeof("INDIAN") - 1, 1); + zend_string *const_INDIAN_name = zend_string_init_interned("INDIAN", sizeof("INDIAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_INDIAN_name, &const_INDIAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_INDIAN_name); + zend_string_release_ex(const_INDIAN_name, true); zval const_PACIFIC_value; ZVAL_LONG(&const_PACIFIC_value, PHP_DATE_TIMEZONE_GROUP_PACIFIC); - zend_string *const_PACIFIC_name = zend_string_init_interned("PACIFIC", sizeof("PACIFIC") - 1, 1); + zend_string *const_PACIFIC_name = zend_string_init_interned("PACIFIC", sizeof("PACIFIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_PACIFIC_name, &const_PACIFIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PACIFIC_name); + zend_string_release_ex(const_PACIFIC_name, true); zval const_UTC_value; ZVAL_LONG(&const_UTC_value, PHP_DATE_TIMEZONE_GROUP_UTC); - zend_string *const_UTC_name = zend_string_init_interned("UTC", sizeof("UTC") - 1, 1); + zend_string *const_UTC_name = zend_string_init_interned("UTC", sizeof("UTC") - 1, true); zend_declare_typed_class_constant(class_entry, const_UTC_name, &const_UTC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_UTC_name); + zend_string_release_ex(const_UTC_name, true); zval const_ALL_value; ZVAL_LONG(&const_ALL_value, PHP_DATE_TIMEZONE_GROUP_ALL); - zend_string *const_ALL_name = zend_string_init_interned("ALL", sizeof("ALL") - 1, 1); + zend_string *const_ALL_name = zend_string_init_interned("ALL", sizeof("ALL") - 1, true); zend_declare_typed_class_constant(class_entry, const_ALL_name, &const_ALL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ALL_name); + zend_string_release_ex(const_ALL_name, true); zval const_ALL_WITH_BC_value; ZVAL_LONG(&const_ALL_WITH_BC_value, PHP_DATE_TIMEZONE_GROUP_ALL_W_BC); - zend_string *const_ALL_WITH_BC_name = zend_string_init_interned("ALL_WITH_BC", sizeof("ALL_WITH_BC") - 1, 1); + zend_string *const_ALL_WITH_BC_name = zend_string_init_interned("ALL_WITH_BC", sizeof("ALL_WITH_BC") - 1, true); zend_declare_typed_class_constant(class_entry, const_ALL_WITH_BC_name, &const_ALL_WITH_BC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ALL_WITH_BC_name); + zend_string_release_ex(const_ALL_WITH_BC_name, true); zval const_PER_COUNTRY_value; ZVAL_LONG(&const_PER_COUNTRY_value, PHP_DATE_TIMEZONE_PER_COUNTRY); - zend_string *const_PER_COUNTRY_name = zend_string_init_interned("PER_COUNTRY", sizeof("PER_COUNTRY") - 1, 1); + zend_string *const_PER_COUNTRY_name = zend_string_init_interned("PER_COUNTRY", sizeof("PER_COUNTRY") - 1, true); zend_declare_typed_class_constant(class_entry, const_PER_COUNTRY_name, &const_PER_COUNTRY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PER_COUNTRY_name); + zend_string_release_ex(const_PER_COUNTRY_name, true); + + + 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_STR(&attribute_Deprecated_func___wakeup_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_func___wakeup_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + 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->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; } @@ -1190,6 +1200,14 @@ static zend_class_entry *register_class_DateInterval(void) INIT_CLASS_ENTRY(ce, "DateInterval", class_DateInterval_methods); class_entry = zend_register_internal_class_with_flags(&ce, NULL, 0); + + 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_STR(&attribute_Deprecated_func___wakeup_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_func___wakeup_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + 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->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; } @@ -1203,61 +1221,69 @@ static zend_class_entry *register_class_DatePeriod(zend_class_entry *class_entry zval const_EXCLUDE_START_DATE_value; ZVAL_LONG(&const_EXCLUDE_START_DATE_value, PHP_DATE_PERIOD_EXCLUDE_START_DATE); - zend_string *const_EXCLUDE_START_DATE_name = zend_string_init_interned("EXCLUDE_START_DATE", sizeof("EXCLUDE_START_DATE") - 1, 1); + zend_string *const_EXCLUDE_START_DATE_name = zend_string_init_interned("EXCLUDE_START_DATE", sizeof("EXCLUDE_START_DATE") - 1, true); zend_declare_typed_class_constant(class_entry, const_EXCLUDE_START_DATE_name, &const_EXCLUDE_START_DATE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EXCLUDE_START_DATE_name); + zend_string_release_ex(const_EXCLUDE_START_DATE_name, true); zval const_INCLUDE_END_DATE_value; ZVAL_LONG(&const_INCLUDE_END_DATE_value, PHP_DATE_PERIOD_INCLUDE_END_DATE); - zend_string *const_INCLUDE_END_DATE_name = zend_string_init_interned("INCLUDE_END_DATE", sizeof("INCLUDE_END_DATE") - 1, 1); + zend_string *const_INCLUDE_END_DATE_name = zend_string_init_interned("INCLUDE_END_DATE", sizeof("INCLUDE_END_DATE") - 1, true); zend_declare_typed_class_constant(class_entry, const_INCLUDE_END_DATE_name, &const_INCLUDE_END_DATE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_INCLUDE_END_DATE_name); + zend_string_release_ex(const_INCLUDE_END_DATE_name, true); zval property_start_default_value; ZVAL_UNDEF(&property_start_default_value); - zend_string *property_start_name = zend_string_init("start", sizeof("start") - 1, 1); + zend_string *property_start_name = zend_string_init("start", sizeof("start") - 1, true); zend_string *property_start_class_DateTimeInterface = zend_string_init("DateTimeInterface", sizeof("DateTimeInterface")-1, 1); zend_declare_typed_property(class_entry, property_start_name, &property_start_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_start_class_DateTimeInterface, 0, MAY_BE_NULL)); - zend_string_release(property_start_name); + zend_string_release_ex(property_start_name, true); zval property_current_default_value; ZVAL_UNDEF(&property_current_default_value); - zend_string *property_current_name = zend_string_init("current", sizeof("current") - 1, 1); + zend_string *property_current_name = zend_string_init("current", sizeof("current") - 1, true); zend_string *property_current_class_DateTimeInterface = zend_string_init("DateTimeInterface", sizeof("DateTimeInterface")-1, 1); zend_declare_typed_property(class_entry, property_current_name, &property_current_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_current_class_DateTimeInterface, 0, MAY_BE_NULL)); - zend_string_release(property_current_name); + zend_string_release_ex(property_current_name, true); zval property_end_default_value; ZVAL_UNDEF(&property_end_default_value); - zend_string *property_end_name = zend_string_init("end", sizeof("end") - 1, 1); + zend_string *property_end_name = zend_string_init("end", sizeof("end") - 1, true); zend_string *property_end_class_DateTimeInterface = zend_string_init("DateTimeInterface", sizeof("DateTimeInterface")-1, 1); zend_declare_typed_property(class_entry, property_end_name, &property_end_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_end_class_DateTimeInterface, 0, MAY_BE_NULL)); - zend_string_release(property_end_name); + zend_string_release_ex(property_end_name, true); zval property_interval_default_value; ZVAL_UNDEF(&property_interval_default_value); - zend_string *property_interval_name = zend_string_init("interval", sizeof("interval") - 1, 1); + zend_string *property_interval_name = zend_string_init("interval", sizeof("interval") - 1, true); zend_string *property_interval_class_DateInterval = zend_string_init("DateInterval", sizeof("DateInterval")-1, 1); zend_declare_typed_property(class_entry, property_interval_name, &property_interval_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_interval_class_DateInterval, 0, MAY_BE_NULL)); - zend_string_release(property_interval_name); + zend_string_release_ex(property_interval_name, true); zval property_recurrences_default_value; ZVAL_UNDEF(&property_recurrences_default_value); - zend_string *property_recurrences_name = zend_string_init("recurrences", sizeof("recurrences") - 1, 1); + zend_string *property_recurrences_name = zend_string_init("recurrences", sizeof("recurrences") - 1, true); zend_declare_typed_property(class_entry, property_recurrences_name, &property_recurrences_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_recurrences_name); + zend_string_release_ex(property_recurrences_name, true); zval property_include_start_date_default_value; ZVAL_UNDEF(&property_include_start_date_default_value); - zend_string *property_include_start_date_name = zend_string_init("include_start_date", sizeof("include_start_date") - 1, 1); + zend_string *property_include_start_date_name = zend_string_init("include_start_date", sizeof("include_start_date") - 1, true); zend_declare_typed_property(class_entry, property_include_start_date_name, &property_include_start_date_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_include_start_date_name); + zend_string_release_ex(property_include_start_date_name, true); zval property_include_end_date_default_value; ZVAL_UNDEF(&property_include_end_date_default_value); - zend_string *property_include_end_date_name = zend_string_init("include_end_date", sizeof("include_end_date") - 1, 1); + zend_string *property_include_end_date_name = zend_string_init("include_end_date", sizeof("include_end_date") - 1, true); zend_declare_typed_property(class_entry, property_include_end_date_name, &property_include_end_date_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_include_end_date_name); + zend_string_release_ex(property_include_end_date_name, true); + + + 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_STR(&attribute_Deprecated_func___wakeup_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_func___wakeup_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + 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->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/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/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/bug79015.phpt b/ext/date/tests/bug79015.phpt index 99cb03f75d5cb..b2f1a63fa4c21 100644 --- a/ext/date/tests/bug79015.phpt +++ b/ext/date/tests/bug79015.phpt @@ -6,6 +6,7 @@ $payload = 'O:12:"DateInterval":9:{s:1:"y";i:1;s:1:"m";i:0;s:1:"d";i:4;s:1:"h";i var_dump(unserialize($payload)); ?> --EXPECTF-- +Warning: The float 9.99999999999E+18 is not representable as an int, cast occurred in %s on line %d object(DateInterval)#%d (%d) { ["y"]=> int(1) 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/instantiate_uninstantiable_classes.phpt b/ext/date/tests/instantiate_uninstantiable_classes.phpt new file mode 100644 index 0000000000000..634ed635b2d2d --- /dev/null +++ b/ext/date/tests/instantiate_uninstantiable_classes.phpt @@ -0,0 +1,82 @@ +--TEST-- +Instantiating uninstantiable classes via static constructors +--FILE-- +getMessage(), "\n"; +} + +try { + MyDateTime::createFromFormat('Y-m-d', '2025-01-01'); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + MyDateTime::createFromImmutable(new DateTimeImmutable()); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + MyDateTime::createFromInterface(new DateTimeImmutable()); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + MyDateTime::createFromTimestamp(0); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + MyDateTimeImmutable::createFromFormat('Y-m-d', '2025-01-01'); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + MyDateTimeImmutable::createFromMutable(new DateTime()); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + MyDateTimeImmutable::createFromInterface(new DateTime()); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + MyDateTimeImmutable::createFromTimestamp(0); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Cannot instantiate abstract class MyDatePeriod +Cannot instantiate abstract class MyDateTime +Cannot instantiate abstract class MyDateTime +Cannot instantiate abstract class MyDateTime +Cannot instantiate abstract class MyDateTime +Cannot instantiate abstract class MyDateTimeImmutable +Cannot instantiate abstract class MyDateTimeImmutable +Cannot instantiate abstract class MyDateTimeImmutable +Cannot instantiate abstract class MyDateTimeImmutable 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..8963230353299 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) { @@ -528,8 +539,8 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) int persistent_flag = persistent ? STREAM_OPEN_PERSISTENT : 0; char *lock_name; #ifdef PHP_WIN32 - bool restarted = 0; - bool need_creation = 0; + bool restarted = false; + bool need_creation = false; #endif zend_string *path; @@ -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 */ @@ -903,7 +923,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) lock_file_mode = "r+b"; - restarted = 1; + restarted = true; goto restart; #endif } @@ -949,14 +969,14 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) /* {{{ Opens path using the specified handler in mode persistently */ PHP_FUNCTION(dba_popen) { - php_dba_open(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); + php_dba_open(INTERNAL_FUNCTION_PARAM_PASSTHRU, true); } /* }}} */ /* {{{ Opens path using the specified handler in mode*/ PHP_FUNCTION(dba_open) { - php_dba_open(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + php_dba_open(INTERNAL_FUNCTION_PARAM_PASSTHRU, false); } /* }}} */ @@ -1042,6 +1062,11 @@ PHP_FUNCTION(dba_fetch) ZEND_PARSE_PARAMETERS_END(); } + if (ZEND_LONG_EXCEEDS_INT(skip)) { + zend_argument_value_error(3, "must be between %d and %d", INT_MIN, INT_MAX); + RETURN_THROWS(); + } + info = Z_DBA_INFO_P(id); CHECK_DBA_CONNECTION(info); @@ -1252,7 +1277,7 @@ PHP_FUNCTION(dba_sync) /* {{{ List configured database handlers */ PHP_FUNCTION(dba_handlers) { - bool full_info = 0; + bool full_info = false; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &full_info) == FAILURE) { RETURN_THROWS(); 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/dba_inifile.c b/ext/dba/dba_inifile.c index 00b99d55b0056..75a267055d96c 100644 --- a/ext/dba/dba_inifile.c +++ b/ext/dba/dba_inifile.c @@ -127,7 +127,7 @@ DBA_DELETE_FUNC(inifile) { inifile *dba = info->dbf; int res; - bool found = 0; + bool found = false; key_type ini_key; if (!key) { 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/dba/tests/gh19885.phpt b/ext/dba/tests/gh19885.phpt new file mode 100644 index 0000000000000..987aea4f175a2 --- /dev/null +++ b/ext/dba/tests/gh19885.phpt @@ -0,0 +1,35 @@ +--TEST-- +GH-19885 (dba_fetch() segfault on large skip values) +--EXTENSIONS-- +dba +--SKIPIF-- + +--FILE-- +getMessage(), PHP_EOL; +} + +try { + dba_fetch("http://github.com/1", $db, PHP_INT_MAX); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} +// negative skip needs to remain acceptable albeit corrected down the line +var_dump(dba_fetch("http://github.com/1", $db, -1000000)); +?> +--EXPECTF-- +dba_fetch(): Argument #3 ($skip) must be between -%d and %d +dba_fetch(): Argument #3 ($skip) must be between -%d and %d + +Notice: dba_fetch(): Handler cdb accepts only skip values greater than or equal to zero, using skip=0 in %s on line %d +string(1) "1" 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..0b246bd0df1ee 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() @@ -57,9 +57,9 @@ static zend_class_entry *register_class_DlTestSuperClass(void) zval property_a_default_value; ZVAL_UNDEF(&property_a_default_value); - zend_string *property_a_name = zend_string_init("a", sizeof("a") - 1, 1); + zend_string *property_a_name = zend_string_init("a", sizeof("a") - 1, true); zend_declare_typed_property(class_entry, property_a_name, &property_a_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_a_name); + zend_string_release_ex(property_a_name, true); return class_entry; } diff --git a/ext/dom/attr.c b/ext/dom/attr.c index dfe3abc1a885c..3107f5a21a2be 100644 --- a/ext/dom/attr.c +++ b/ext/dom/attr.c @@ -83,7 +83,7 @@ zend_result dom_attr_name_read(dom_object *obj, zval *retval) if (php_dom_follow_spec_intern(obj)) { zend_string *str = dom_node_get_node_name_attribute_or_element((xmlNodePtr) attrp, false); - ZVAL_NEW_STR(retval, str); + ZVAL_STR(retval, str); } else { ZVAL_STRING(retval, (char *) attrp->name); } @@ -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..b46722d854c5e 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -752,7 +752,7 @@ PHP_METHOD(DOMDocument, importNode) xmlDocPtr docp; xmlNodePtr nodep, retnodep; dom_object *intern, *nodeobj; - bool recursive = 0; + bool recursive = false; if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|b", &node, dom_node_class_entry, &recursive) == FAILURE) { RETURN_THROWS(); @@ -802,7 +802,7 @@ static void dom_modern_document_import_node(INTERNAL_FUNCTION_PARAMETERS, zend_c xmlDocPtr docp; xmlNodePtr nodep, retnodep; dom_object *intern, *nodeobj; - bool recursive = 0; + bool recursive = false; if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|b", &node, node_ce, &recursive) != SUCCESS) { RETURN_THROWS(); @@ -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); @@ -1266,7 +1282,7 @@ PHP_METHOD(DOMDocument, __construct) } if (encoding_len > 0) { - docp->encoding = (const xmlChar *) xmlStrdup(BAD_CAST encoding); + docp->encoding = xmlStrdup((const xmlChar *) encoding); } intern = Z_DOMOBJ_P(ZEND_THIS); @@ -1364,10 +1380,8 @@ xmlDocPtr dom_document_parser(zval *id, dom_load_mode mode, const char *source, substitute_ent = doc_props->substituteentities; recover = doc_props->recover || (options & XML_PARSE_RECOVER) == XML_PARSE_RECOVER; - xmlInitParser(); - if (mode == DOM_LOAD_FILE) { - if (CHECK_NULL_PATH(source, source_len)) { + if (zend_char_has_nul_byte(source, source_len)) { zend_argument_value_error(1, "must not contain any null bytes"); return NULL; } @@ -1416,24 +1430,28 @@ xmlDocPtr dom_document_parser(zval *id, dom_load_mode mode, const char *source, ctxt->sax->warning = php_libxml_ctx_warning; } - if (validate && ! (options & XML_PARSE_DTDVALID)) { + if (validate) { options |= XML_PARSE_DTDVALID; } - if (resolve_externals && ! (options & XML_PARSE_DTDATTR)) { + if (resolve_externals) { options |= XML_PARSE_DTDATTR; } - if (substitute_ent && ! (options & XML_PARSE_NOENT)) { + if (substitute_ent) { options |= XML_PARSE_NOENT; } - if (keep_blanks == 0 && ! (options & XML_PARSE_NOBLANKS)) { + if (keep_blanks == 0) { options |= XML_PARSE_NOBLANKS; } if (recover) { options |= XML_PARSE_RECOVER; } +#if LIBXML_VERSION >= 21300 + xmlCtxtSetOptions(ctxt, options); +#else php_libxml_sanitize_parse_ctxt_options(ctxt); xmlCtxtUseOptions(ctxt, options); +#endif if (recover) { old_error_reporting = EG(error_reporting); @@ -1579,12 +1597,16 @@ PHP_METHOD(DOMDocument, save) libxml_doc_props const* doc_props = dom_get_doc_props_read_only(intern->document); bool format = doc_props->formatoutput; if (options & LIBXML_SAVE_NOEMPTYTAG) { + ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations") saveempty = xmlSaveNoEmptyTags; xmlSaveNoEmptyTags = 1; + ZEND_DIAGNOSTIC_IGNORED_END } zend_long bytes = intern->document->handlers->dump_doc_to_file(file, docp, format, (const char *) docp->encoding); if (options & LIBXML_SAVE_NOEMPTYTAG) { + ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations") xmlSaveNoEmptyTags = saveempty; + ZEND_DIAGNOSTIC_IGNORED_END } if (bytes == -1) { RETURN_FALSE; @@ -1625,10 +1647,14 @@ static void dom_document_save_xml(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry /* Save libxml2 global, override its value, and restore after saving (don't move me or risk breaking the state * w.r.t. the implicit return in DOM_GET_OBJ). */ + ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations") old_xml_save_no_empty_tags = xmlSaveNoEmptyTags; xmlSaveNoEmptyTags = (options & LIBXML_SAVE_NOEMPTYTAG) ? 1 : 0; + ZEND_DIAGNOSTIC_IGNORED_END res = intern->document->handlers->dump_node_to_str(docp, node, format, (const char *) docp->encoding); + ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations") xmlSaveNoEmptyTags = old_xml_save_no_empty_tags; + ZEND_DIAGNOSTIC_IGNORED_END } else { int converted_options = XML_SAVE_AS_XML; if (options & XML_SAVE_NO_DECL) { @@ -1639,10 +1665,14 @@ static void dom_document_save_xml(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry } /* Save libxml2 global, override its value, and restore after saving. */ + ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations") old_xml_save_no_empty_tags = xmlSaveNoEmptyTags; xmlSaveNoEmptyTags = (options & LIBXML_SAVE_NOEMPTYTAG) ? 1 : 0; + ZEND_DIAGNOSTIC_IGNORED_END res = intern->document->handlers->dump_doc_to_str(docp, converted_options, (const char *) docp->encoding); + ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations") xmlSaveNoEmptyTags = old_xml_save_no_empty_tags; + ZEND_DIAGNOSTIC_IGNORED_END } if (!res) { @@ -1846,7 +1876,7 @@ static void dom_document_schema_validate(INTERNAL_FUNCTION_PARAMETERS, int type) switch (type) { case DOM_LOAD_FILE: - if (CHECK_NULL_PATH(source, source_len)) { + if (zend_char_has_nul_byte(source, source_len)) { PHP_LIBXML_RESTORE_GLOBALS(new_parser_ctxt); zend_argument_value_error(1, "must not contain any null bytes"); RETURN_THROWS(); @@ -1953,7 +1983,7 @@ static void dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAMETERS, int type switch (type) { case DOM_LOAD_FILE: - if (CHECK_NULL_PATH(source, source_len)) { + if (zend_char_has_nul_byte(source, source_len)) { zend_argument_value_error(1, "must not contain any null bytes"); RETURN_THROWS(); } @@ -2024,8 +2054,6 @@ PHP_METHOD(DOMDocument, relaxNGValidateSource) #endif -#ifdef LIBXML_HTML_ENABLED - static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */ { char *source; @@ -2048,7 +2076,7 @@ static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */ } if (mode == DOM_LOAD_FILE) { - if (CHECK_NULL_PATH(source, source_len)) { + if (zend_char_has_nul_byte(source, source_len)) { zend_argument_value_error(1, "must not contain any null bytes"); RETURN_THROWS(); } @@ -2072,10 +2100,16 @@ static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */ ctxt->sax->error = php_libxml_ctx_error; ctxt->sax->warning = php_libxml_ctx_warning; } +#if LIBXML_VERSION >= 21400 + if (options) { + htmlCtxtSetOptions(ctxt, (int)options); + } +#else php_libxml_sanitize_parse_ctxt_options(ctxt); if (options) { htmlCtxtUseOptions(ctxt, (int)options); } +#endif htmlParseDocument(ctxt); xmlDocPtr newdoc = ctxt->myDoc; htmlFreeParserCtxt(ctxt); @@ -2218,8 +2252,6 @@ PHP_METHOD(DOMDocument, saveHTML) } /* }}} end dom_document_save_html */ -#endif /* defined(LIBXML_HTML_ENABLED) */ - /* {{{ Register extended class used to create base node type */ static void dom_document_register_node_class(INTERNAL_FUNCTION_PARAMETERS, bool modern) { diff --git a/ext/dom/documenttype.c b/ext/dom/documenttype.c index 63da0306649a9..266c895effb27 100644 --- a/ext/dom/documenttype.c +++ b/ext/dom/documenttype.c @@ -34,7 +34,11 @@ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core- zend_result dom_documenttype_name_read(dom_object *obj, zval *retval) { DOM_PROP_NODE(xmlDtdPtr, dtdptr, obj); - ZVAL_STRING(retval, dtdptr->name ? (char *) (dtdptr->name) : ""); + if (dtdptr->name) { + ZVAL_STRING(retval, (const char *) dtdptr->name); + } else { + ZVAL_EMPTY_STRING(retval); + } return SUCCESS; } diff --git a/ext/dom/dom_iterators.c b/ext/dom/dom_iterators.c index 90e973723f6c6..9134b107925a2 100644 --- a/ext/dom/dom_iterators.c +++ b/ext/dom/dom_iterators.c @@ -127,9 +127,9 @@ static void php_dom_iterator_current_key(zend_object_iterator *iter, zval *key) if (intern->ptr != NULL) { xmlNodePtr curnode = ((php_libxml_node_ptr *)intern->ptr)->node; if (curnode->type == XML_ATTRIBUTE_NODE && php_dom_follow_spec_intern(intern)) { - ZVAL_NEW_STR(key, dom_node_get_node_name_attribute_or_element(curnode, false)); + ZVAL_STR(key, dom_node_get_node_name_attribute_or_element(curnode, false)); } else { - ZVAL_STRINGL(key, (const char *) curnode->name, xmlStrlen(curnode->name)); + ZVAL_STRINGL_FAST(key, (const char *) curnode->name, xmlStrlen(curnode->name)); } } else { ZVAL_NULL(key); diff --git a/ext/dom/element.c b/ext/dom/element.c index f0afcf07eb2fe..797f215e173d1 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) { @@ -122,7 +122,7 @@ zend_result dom_element_tag_name_read(dom_object *obj, zval *retval) bool uppercase = php_dom_follow_spec_intern(obj) && php_dom_ns_is_html_and_document_is_html(nodep); zend_string *result = dom_node_get_node_name_attribute_or_element((const xmlNode *) nodep, uppercase); - ZVAL_NEW_STR(retval, result); + ZVAL_STR(retval, result); return SUCCESS; } @@ -180,7 +180,7 @@ zend_result dom_element_class_name_write(dom_object *obj, zval *newval) zval *dom_get_prop_checked_offset(dom_object *obj, uint32_t offset, const char *name) { #if ZEND_DEBUG - zend_string *name_zstr = ZSTR_INIT_LITERAL(name, false); + zend_string *name_zstr = zend_string_init(name, strlen(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); @@ -375,7 +375,7 @@ PHP_METHOD(DOMElement, getAttributeNames) } for (xmlAttrPtr attr = nodep->properties; attr; attr = attr->next) { - ZVAL_NEW_STR(&tmp, dom_node_get_node_name_attribute_or_element((const xmlNode *) attr, false)); + ZVAL_STR(&tmp, dom_node_get_node_name_attribute_or_element((const xmlNode *) attr, false)); zend_hash_next_index_insert(ht, &tmp); } } @@ -1019,7 +1019,7 @@ static void dom_set_attribute_ns_legacy(dom_object *intern, xmlNodePtr elemp, ch name_valid = xmlValidateName(BAD_CAST localname, 0); if (name_valid != 0) { errorcode = INVALID_CHARACTER_ERR; - stricterror = 1; + stricterror = true; } else { attr = xmlHasProp(elemp, BAD_CAST localname); if (attr != NULL && attr->type != XML_ATTRIBUTE_DECL) { @@ -1210,19 +1210,17 @@ Since: DOM Level 2 */ PHP_METHOD(DOMElement, getAttributeNodeNS) { - zval *id; xmlNodePtr elemp; xmlAttrPtr attrp; dom_object *intern; size_t uri_len, name_len; char *uri, *name; - id = ZEND_THIS; if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!s", &uri, &uri_len, &name, &name_len) == FAILURE) { RETURN_THROWS(); } - DOM_GET_OBJ(elemp, id, xmlNodePtr, intern); + DOM_GET_OBJ(elemp, ZEND_THIS, xmlNodePtr, intern); bool follow_spec = php_dom_follow_spec_intern(intern); if (follow_spec && uri_len == 0) { @@ -1239,16 +1237,11 @@ PHP_METHOD(DOMElement, getAttributeNodeNS) /* Keep parent alive, because we're a fake child. */ GC_ADDREF(&intern->std); (void) php_dom_create_fake_namespace_decl(elemp, nsptr, return_value, intern); - } else { - RETURN_NULL(); } - } else { - RETURN_NULL(); } } else { DOM_RET_OBJ((xmlNodePtr) attrp, intern); } - } /* }}} end dom_element_get_attribute_node_ns */ diff --git a/ext/dom/html5_parser.c b/ext/dom/html5_parser.c index f1dc2db53b25b..d5fe3d5c2773d 100644 --- a/ext/dom/html5_parser.c +++ b/ext/dom/html5_parser.c @@ -268,7 +268,10 @@ static lexbor_libxml2_bridge_status lexbor_libxml2_bridge_convert( /* xmlIsID does some other stuff too that is irrelevant here. */ if (local_name_length == 2 && local_name[0] == 'i' && local_name[1] == 'd' && attr->node.ns == LXB_NS_HTML) { - xmlAddID(NULL, lxml_doc, value, lxml_attr); + if (xmlAddID(NULL, lxml_doc, value, lxml_attr) == 0) { + /* If the ID already exists, the ID attribute still needs to be marked as an ID. */ + lxml_attr->atype = XML_ATTRIBUTE_ID; + } } /* libxml2 doesn't support line numbers on this anyway, it derives them instead, so don't bother */ diff --git a/ext/dom/inner_outer_html_mixin.c b/ext/dom/inner_outer_html_mixin.c index eee525cc47a6e..85124d41689af 100644 --- a/ext/dom/inner_outer_html_mixin.c +++ b/ext/dom/inner_outer_html_mixin.c @@ -291,8 +291,12 @@ static xmlNodePtr dom_xml_fragment_parsing_algorithm(dom_object *obj, const xmlN } parser->dict = context_node->doc->dict; +#if LIBXML_VERSION >= 21300 + xmlCtxtSetOptions(parser, XML_PARSE_IGNORE_ENC | XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NO_XXE); +#else php_libxml_sanitize_parse_ctxt_options(parser); xmlCtxtUseOptions(parser, XML_PARSE_IGNORE_ENC | XML_PARSE_NOERROR | XML_PARSE_NOWARNING); +#endif xmlCharEncodingHandlerPtr encoding = xmlFindCharEncodingHandler("UTF-8"); (void) xmlSwitchToEncoding(parser, encoding); diff --git a/ext/dom/lexbor/selectors-adapted/selectors.c b/ext/dom/lexbor/selectors-adapted/selectors.c index e5348292f4372..0bb285b39e99b 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 @@ -13,7 +13,7 @@ #include #include -#include "ext/dom/lexbor/selectors-adapted/selectors.h" +#include "selectors.h" #include "../../namespace_compat.h" #include "../../domexception.h" #include "../../php_dom.h" @@ -35,12 +35,22 @@ 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) +static bool lxb_selectors_str_cmp_loright(const char *lhs, const char *rhs) { - return CMP_NODE_TYPE(node, XML_ELEMENT_NODE); + while (true) { + if (*rhs != zend_tolower_ascii(*lhs)) { + return false; + } + if (!*lhs) { + return true; + } + ++rhs; + ++lhs; + } } -static zend_always_inline bool lxb_selectors_adapted_cmp_local_name_literal(const xmlNode *node, const char *name) +/* `name` is lowercase */ +static zend_always_inline bool lxb_selectors_cmp_html_name_lit(const xmlNode *node, const char *name) { return strcmp((const char *) node->name, name) == 0; } @@ -53,14 +63,15 @@ static zend_always_inline bool lxb_selectors_adapted_cmp_ns(const xmlNode *a, co static zend_always_inline bool lxb_selectors_adapted_cmp_local_name_id(const xmlNode *node, const lxb_selectors_adapted_id *id) { - uintptr_t ptr = (uintptr_t) node->name; - if (id->interned && (ptr & (ZEND_MM_ALIGNMENT - 1)) != 0) { - /* It cannot be a heap-allocated string because the pointer is not properly aligned for a heap allocation. - * Therefore, it must be interned into the dictionary pool. */ - return node->name == id->name; + ZEND_ASSERT(node->doc != NULL); + if (php_dom_ns_is_html_and_document_is_html(node)) { + /* From https://html.spec.whatwg.org/#case-sensitivity-of-selectors: + * The element name must be compared case sensitively _after_ converting the selector to lowercase. + * E.g. selector "DIV" must match element "div" but not "Div". */ + return lxb_selectors_str_cmp_loright((const char *) id->name, (const char *) node->name); + } else { + return strcmp((const char *) node->name, (const char *) id->name) == 0; } - - return strcmp((const char *) node->name, (const char *) id->name) == 0; } static zend_always_inline const xmlAttr *lxb_selectors_adapted_attr(const xmlNode *node, const lxb_char_t *name) @@ -69,9 +80,8 @@ static zend_always_inline const xmlAttr *lxb_selectors_adapted_attr(const xmlNod ZEND_ASSERT(node->doc != NULL); if (php_dom_ns_is_html_and_document_is_html(node)) { /* No need to handle DTD entities as we're in HTML. */ - size_t name_bound = strlen((const char *) name) + 1; for (const xmlAttr *cur = node->properties; cur != NULL; cur = cur->next) { - if (lexbor_str_data_nlocmp_right(cur->name, name, name_bound)) { + if (lxb_selectors_str_cmp_loright((const char *) name, (const char *) cur->name)) { attr = cur; break; } @@ -159,18 +169,7 @@ static bool lxb_selectors_is_lowercased_html_attrib_name(const lxb_css_selector_ static void lxb_selectors_adapted_set_entry_id_ex(lxb_selectors_entry_t *entry, const lxb_css_selector_t *selector, const xmlNode *node) { entry->id.attr_case_insensitive = lxb_selectors_is_lowercased_html_attrib_name(selector); - - if (node->doc != NULL && node->doc->dict != NULL) { - const xmlChar *interned = xmlDictExists(node->doc->dict, selector->name.data, selector->name.length); - if (interned != NULL) { - entry->id.name = interned; - entry->id.interned = true; - return; - } - } - entry->id.name = selector->name.data; - entry->id.interned = false; } static zend_always_inline void lxb_selectors_adapted_set_entry_id(lxb_selectors_entry_t *entry, const lxb_css_selector_t *selector, const xmlNode *node) @@ -181,48 +180,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_pseudo_class_function(lxb_selectors_t *selectors, - lxb_selectors_entry_t *entry); +lxb_selectors_state_found_check_forward(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_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 const xmlNode * -lxb_selectors_state_has_relative(const xmlNode *node, - const lxb_css_selector_t *selector); +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_after_find_has(lxb_selectors_t *selectors, - lxb_selectors_entry_t *entry); +lxb_selectors_state_not_found_forward(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry); + +static lxb_selectors_entry_t * +lxb_selectors_next_list(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry); + +static lxb_selectors_entry_t * +lxb_selectors_next_list_forward(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry); + +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_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 +269,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 +306,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 +349,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 +460,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, selector, 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, node)) { return node; } @@ -353,12 +531,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 +544,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 +597,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 +637,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 +711,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 +776,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 +814,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 +841,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 +871,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 +1327,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 +1432,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; @@ -1505,8 +1690,8 @@ lxb_selectors_pseudo_class(const lxb_css_selector_t *selector, case LXB_CSS_SELECTOR_PSEUDO_CLASS_ANY_LINK: /* https://drafts.csswg.org/selectors/#the-any-link-pseudo */ if (php_dom_ns_is_fast(node, php_dom_ns_is_html_magic_token) - && (lxb_selectors_adapted_cmp_local_name_literal(node, "a") - || lxb_selectors_adapted_cmp_local_name_literal(node, "area"))) + && (lxb_selectors_cmp_html_name_lit(node, "a") + || lxb_selectors_cmp_html_name_lit(node, "area"))) { return lxb_selectors_adapted_has_attr(node, "href"); } @@ -1524,7 +1709,7 @@ lxb_selectors_pseudo_class(const lxb_css_selector_t *selector, if (!php_dom_ns_is_fast(node, php_dom_ns_is_html_magic_token)) { return false; } - if (lxb_selectors_adapted_cmp_local_name_literal(node, "input")) { + if (lxb_selectors_cmp_html_name_lit(node, "input")) { const xmlAttr *dom_attr = lxb_selectors_adapted_attr(node, (const lxb_char_t *) "type"); if (dom_attr == NULL) { return false; @@ -1548,7 +1733,7 @@ lxb_selectors_pseudo_class(const lxb_css_selector_t *selector, return res; } - else if(lxb_selectors_adapted_cmp_local_name_literal(node, "option")) { + else if(lxb_selectors_cmp_html_name_lit(node, "option")) { return lxb_selectors_adapted_has_attr(node, "selected"); } @@ -1621,8 +1806,8 @@ lxb_selectors_pseudo_class(const lxb_css_selector_t *selector, case LXB_CSS_SELECTOR_PSEUDO_CLASS_LINK: /* https://html.spec.whatwg.org/multipage/semantics-other.html#selector-link */ if (php_dom_ns_is_fast(node, php_dom_ns_is_html_magic_token) - && (lxb_selectors_adapted_cmp_local_name_literal(node, "a") - || lxb_selectors_adapted_cmp_local_name_literal(node, "area"))) + && (lxb_selectors_cmp_html_name_lit(node, "a") + || lxb_selectors_cmp_html_name_lit(node, "area"))) { return lxb_selectors_adapted_has_attr(node, "href"); } @@ -1642,9 +1827,9 @@ lxb_selectors_pseudo_class(const lxb_css_selector_t *selector, case LXB_CSS_SELECTOR_PSEUDO_CLASS_OPTIONAL: if (php_dom_ns_is_fast(node, php_dom_ns_is_html_magic_token) - && (lxb_selectors_adapted_cmp_local_name_literal(node, "input") - || lxb_selectors_adapted_cmp_local_name_literal(node, "select") - || lxb_selectors_adapted_cmp_local_name_literal(node, "textarea"))) + && (lxb_selectors_cmp_html_name_lit(node, "input") + || lxb_selectors_cmp_html_name_lit(node, "select") + || lxb_selectors_cmp_html_name_lit(node, "textarea"))) { return !lxb_selectors_adapted_has_attr(node, "required"); } @@ -1659,8 +1844,8 @@ lxb_selectors_pseudo_class(const lxb_css_selector_t *selector, case LXB_CSS_SELECTOR_PSEUDO_CLASS_PLACEHOLDER_SHOWN: if (php_dom_ns_is_fast(node, php_dom_ns_is_html_magic_token) - && (lxb_selectors_adapted_cmp_local_name_literal(node, "input") - || lxb_selectors_adapted_cmp_local_name_literal(node, "textarea"))) + && (lxb_selectors_cmp_html_name_lit(node, "input") + || lxb_selectors_cmp_html_name_lit(node, "textarea"))) { return lxb_selectors_adapted_has_attr(node, "placeholder"); } @@ -1675,9 +1860,9 @@ lxb_selectors_pseudo_class(const lxb_css_selector_t *selector, case LXB_CSS_SELECTOR_PSEUDO_CLASS_REQUIRED: if (php_dom_ns_is_fast(node, php_dom_ns_is_html_magic_token) - && (lxb_selectors_adapted_cmp_local_name_literal(node, "input") - || lxb_selectors_adapted_cmp_local_name_literal(node, "select") - || lxb_selectors_adapted_cmp_local_name_literal(node, "textarea"))) + && (lxb_selectors_cmp_html_name_lit(node, "input") + || lxb_selectors_cmp_html_name_lit(node, "select") + || lxb_selectors_cmp_html_name_lit(node, "textarea"))) { return lxb_selectors_adapted_has_attr(node, "required"); } @@ -1714,24 +1899,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 +2020,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 +2038,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 +2050,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 +2068,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 @@ -1829,24 +2108,24 @@ lxb_selectors_pseudo_class_disabled(const xmlNode *node) } if (lxb_selectors_adapted_has_attr(node, "disabled") - && (lxb_selectors_adapted_cmp_local_name_literal(node, "button") - || lxb_selectors_adapted_cmp_local_name_literal(node, "input") - || lxb_selectors_adapted_cmp_local_name_literal(node, "select") - || lxb_selectors_adapted_cmp_local_name_literal(node, "textarea") - || lxb_selectors_adapted_cmp_local_name_literal(node, "optgroup") - || lxb_selectors_adapted_cmp_local_name_literal(node, "fieldset"))) + && (lxb_selectors_cmp_html_name_lit(node, "button") + || lxb_selectors_cmp_html_name_lit(node, "input") + || lxb_selectors_cmp_html_name_lit(node, "select") + || lxb_selectors_cmp_html_name_lit(node, "textarea") + || lxb_selectors_cmp_html_name_lit(node, "optgroup") + || lxb_selectors_cmp_html_name_lit(node, "fieldset"))) { return true; } - if (lxb_selectors_adapted_cmp_local_name_literal(node, "fieldset")) { + if (lxb_selectors_cmp_html_name_lit(node, "fieldset")) { 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") + && lxb_selectors_cmp_html_name_lit(node, "fieldset") && lxb_selectors_adapted_has_attr(node, "disabled")) { /* Search first legend child and figure out if fieldset is a descendent from that. */ @@ -1854,7 +2133,7 @@ lxb_selectors_pseudo_class_disabled(const xmlNode *node) do { if (search_current->type == XML_ELEMENT_NODE && php_dom_ns_is_fast(search_current, php_dom_ns_is_html_magic_token) - && lxb_selectors_adapted_cmp_local_name_literal(search_current, "legend")) { + && lxb_selectors_cmp_html_name_lit(search_current, "legend")) { /* search_current is a legend element. */ const xmlNode *inner_search_current = fieldset; @@ -1887,7 +2166,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 +2184,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 +2203,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 +2221,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)) { @@ -1960,8 +2239,8 @@ static bool lxb_selectors_pseudo_class_read_write(const xmlNode *node) { if (php_dom_ns_is_fast(node, php_dom_ns_is_html_magic_token)) { - if (lxb_selectors_adapted_cmp_local_name_literal(node, "input") - || lxb_selectors_adapted_cmp_local_name_literal(node, "textarea")) { + if (lxb_selectors_cmp_html_name_lit(node, "input") + || lxb_selectors_cmp_html_name_lit(node, "textarea")) { return !lxb_selectors_adapted_has_attr(node, "readonly") && !lxb_selectors_adapted_has_attr(node, "disabled"); } else { const xmlAttr *attr = lxb_selectors_adapted_attr(node, (const lxb_char_t *) "contenteditable"); @@ -1997,7 +2276,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 +2287,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..b64a9e49ee262 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 @@ -77,7 +77,6 @@ typedef lxb_selectors_entry_t * typedef struct { const xmlChar *name; - bool interned; bool attr_case_insensitive; } lxb_selectors_adapted_id; @@ -100,11 +99,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 +114,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/node.c b/ext/dom/node.c index dba4bb8db87cd..de80dba202e99 100644 --- a/ext/dom/node.c +++ b/ext/dom/node.c @@ -52,6 +52,13 @@ zend_string *dom_node_get_node_name_attribute_or_element(const xmlNode *nodep, b if (nodep->ns != NULL && nodep->ns->prefix != NULL) { ret = dom_node_concatenated_name_helper(name_len, (const char *) nodep->name, strlen((const char *) nodep->ns->prefix), (const char *) nodep->ns->prefix); } else { + if (name_len == 1) { + if (uppercase) { + return ZSTR_CHAR(zend_toupper_ascii(*nodep->name)); + } else { + return ZSTR_CHAR((zend_uchar) *nodep->name); + } + } ret = zend_string_init((const char *) nodep->name, name_len, false); } if (uppercase) { @@ -89,7 +96,7 @@ zend_result dom_node_node_name_read(dom_object *obj, zval *retval) uppercase = php_dom_follow_spec_intern(obj) && php_dom_ns_is_html_and_document_is_html(nodep); ZEND_FALLTHROUGH; case XML_ATTRIBUTE_NODE: - ZVAL_NEW_STR(retval, dom_node_get_node_name_attribute_or_element(nodep, uppercase)); + ZVAL_STR(retval, dom_node_get_node_name_attribute_or_element(nodep, uppercase)); break; case XML_NAMESPACE_DECL: { xmlNsPtr ns = nodep->ns; @@ -635,7 +642,7 @@ zend_result dom_node_local_name_read(dom_object *obj, zval *retval) DOM_PROP_NODE(xmlNodePtr, nodep, obj); if (nodep->type == XML_ELEMENT_NODE || nodep->type == XML_ATTRIBUTE_NODE || nodep->type == XML_NAMESPACE_DECL) { - ZVAL_STRING(retval, (char *) (nodep->name)); + ZVAL_STRING_FAST(retval, (const char *) (nodep->name)); } else { ZVAL_NULL(retval); } @@ -1463,7 +1470,7 @@ PHP_METHOD(DOMNode, cloneNode) zval *id; xmlNode *n, *node; dom_object *intern; - bool recursive = 0; + bool recursive = false; id = ZEND_THIS; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &recursive) == FAILURE) { @@ -1871,8 +1878,7 @@ static void dom_node_lookup_prefix(INTERNAL_FUNCTION_PARAMETERS, bool modern) case XML_DOCUMENT_FRAG_NODE: case XML_DOCUMENT_TYPE_NODE: case XML_DTD_NODE: - RETURN_NULL(); - break; + return; default: lookupp = nodep->parent; } @@ -1891,8 +1897,6 @@ static void dom_node_lookup_prefix(INTERNAL_FUNCTION_PARAMETERS, bool modern) } } } - - RETURN_NULL(); } PHP_METHOD(DOMNode, lookupPrefix) @@ -2058,16 +2062,14 @@ PHP_METHOD(DOMNode, lookupNamespaceURI) prefix = NULL; } const char *ns_uri = dom_locate_a_namespace(nodep, prefix); - if (ns_uri == NULL) { - RETURN_NULL(); - } else { + if (ns_uri != NULL) { RETURN_STRING(ns_uri); } } else { if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) { nodep = xmlDocGetRootElement((xmlDocPtr) nodep); if (nodep == NULL) { - RETURN_NULL(); + return; } } @@ -2076,8 +2078,6 @@ PHP_METHOD(DOMNode, lookupNamespaceURI) RETURN_STRING((char *) nsptr->href); } } - - RETURN_NULL(); } /* }}} end dom_node_lookup_namespace_uri */ @@ -2126,7 +2126,7 @@ static void dom_canonicalization(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ } } else { if (zend_parse_parameters(ZEND_NUM_ARGS(), - "s|bba!a!", &file, &file_len, &exclusive, + "p|bba!a!", &file, &file_len, &exclusive, &with_comments, &xpath_array, &ns_prefixes) == FAILURE) { RETURN_THROWS(); } @@ -2287,13 +2287,12 @@ static void dom_node_get_node_path(INTERNAL_FUNCTION_PARAMETERS, bool throw) zval *id; xmlNode *nodep; dom_object *intern; - char *value; ZEND_PARSE_PARAMETERS_NONE(); DOM_GET_THIS_OBJ(nodep, id, xmlNodePtr, intern); - value = (char *) xmlGetNodePath(nodep); + char *value = (char *) xmlGetNodePath(nodep); if (value == NULL) { /* This is only possible when an invalid argument is passed (e.g. namespace declaration, but that's not the case for this call site), * or on allocation failure. So in other words, this only happens on allocation failure. */ @@ -2301,7 +2300,6 @@ static void dom_node_get_node_path(INTERNAL_FUNCTION_PARAMETERS, bool throw) php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true); RETURN_THROWS(); } - RETURN_NULL(); } else { RETVAL_STRING(value); xmlFree(value); diff --git a/ext/dom/notation.c b/ext/dom/notation.c index a15fae9ee9d8e..f83b31428e16c 100644 --- a/ext/dom/notation.c +++ b/ext/dom/notation.c @@ -31,8 +31,6 @@ * Since: */ -/* {{{ attribute protos, not implemented yet */ - /* {{{ publicId string readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-54F2B4D0 @@ -73,6 +71,4 @@ zend_result dom_notation_system_id_read(dom_object *obj, zval *retval) /* }}} */ -/* }}} */ - #endif diff --git a/ext/dom/obj_map.c b/ext/dom/obj_map.c index 9c017c4d11a6b..84fae3bad5721 100644 --- a/ext/dom/obj_map.c +++ b/ext/dom/obj_map.c @@ -515,11 +515,11 @@ static xmlNodePtr dom_map_get_ns_named_item_prop(dom_nnodemap_object *map, const { xmlNodePtr nodep = dom_object_get_node(map->baseobj); if (nodep) { - if (php_dom_follow_spec_intern(map->baseobj)) { - return (xmlNodePtr) php_dom_get_attribute_node(nodep, BAD_CAST ZSTR_VAL(named), ZSTR_LEN(named)); + if (ns) { + return (xmlNodePtr) xmlHasNsProp(nodep, BAD_CAST ZSTR_VAL(named), BAD_CAST ns); } else { - if (ns) { - return (xmlNodePtr) xmlHasNsProp(nodep, BAD_CAST ZSTR_VAL(named), BAD_CAST ns); + if (php_dom_follow_spec_intern(map->baseobj)) { + return (xmlNodePtr) php_dom_get_attribute_node(nodep, BAD_CAST ZSTR_VAL(named), ZSTR_LEN(named)); } else { return (xmlNodePtr) xmlHasProp(nodep, BAD_CAST ZSTR_VAL(named)); } diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index 32eaaf8c2b606..a39e5c1656e9e 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -488,6 +488,7 @@ static void dom_unset_property(zend_object *object, zend_string *member, void ** zend_std_unset_property(object, member, cache_slot); } +/* This custom handler is necessary to avoid a recursive construction of the entire subtree. */ static HashTable* dom_get_debug_info_helper(zend_object *object, int *is_temp) /* {{{ */ { dom_object *obj = php_dom_obj_from_obj(object); @@ -498,6 +499,11 @@ static HashTable* dom_get_debug_info_helper(zend_object *object, int *is_temp) / dom_prop_handler *entry; zend_string *object_str; + /* As we have a custom implementation, we must manually check for overrides. */ + if (object->ce->__debugInfo) { + return zend_std_get_debug_info(object, is_temp); + } + *is_temp = 1; std_props = zend_std_get_properties(object); @@ -708,15 +714,17 @@ static zend_object *dom_object_namespace_node_clone_obj(zend_object *zobject) zend_object *clone = dom_objects_namespace_node_new(intern->dom.std.ce); dom_object_namespace_node *clone_intern = php_dom_namespace_node_obj_from_obj(clone); - xmlNodePtr original_node = dom_object_get_node(&intern->dom); - ZEND_ASSERT(original_node->type == XML_NAMESPACE_DECL); - xmlNodePtr cloned_node = php_dom_create_fake_namespace_decl_node_ptr(original_node->parent, original_node->ns); - if (intern->parent_intern) { clone_intern->parent_intern = intern->parent_intern; GC_ADDREF(&clone_intern->parent_intern->std); } - dom_update_refcount_after_clone(&intern->dom, original_node, &clone_intern->dom, cloned_node); + + xmlNodePtr original_node = dom_object_get_node(&intern->dom); + if (original_node != NULL) { + ZEND_ASSERT(original_node->type == XML_NAMESPACE_DECL); + xmlNodePtr cloned_node = php_dom_create_fake_namespace_decl_node_ptr(original_node->parent, original_node->ns); + dom_update_refcount_after_clone(&intern->dom, original_node, &clone_intern->dom, cloned_node); + } zend_objects_clone_members(clone, &intern->dom.std); return clone; @@ -1369,9 +1377,7 @@ PHP_MINFO_FUNCTION(dom) php_info_print_table_row(2, "DOM/XML", "enabled"); php_info_print_table_row(2, "DOM/XML API Version", DOM_API_VERSION); php_info_print_table_row(2, "libxml Version", LIBXML_DOTTED_VERSION); -#ifdef LIBXML_HTML_ENABLED php_info_print_table_row(2, "HTML Support", "enabled"); -#endif #ifdef LIBXML_XPATH_ENABLED php_info_print_table_row(2, "XPath Support", "enabled"); #endif @@ -2261,7 +2267,7 @@ static bool dom_nodemap_or_nodelist_process_offset_as_named(zval *offset, zend_l if (0 == (is_numeric_string_type = is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), lval, &dval, true))) { return true; } else if (is_numeric_string_type == IS_DOUBLE) { - *lval = zend_dval_to_lval_cap(dval); + *lval = zend_dval_to_lval_cap(dval, Z_STR_P(offset)); } } else { *lval = zval_get_long(offset); @@ -2333,10 +2339,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; @@ -2709,20 +2715,10 @@ xmlChar *php_dom_libxml_fix_file_path(xmlChar *path) xmlDocPtr php_dom_create_html_doc(void) { -#ifdef LIBXML_HTML_ENABLED xmlDocPtr lxml_doc = htmlNewDocNoDtD(NULL, NULL); if (EXPECTED(lxml_doc)) { lxml_doc->dict = xmlDictCreate(); } -#else - /* If HTML support is not enabled, then htmlNewDocNoDtD() is not available. - * This code mimics the behaviour. */ - xmlDocPtr lxml_doc = xmlNewDoc((const xmlChar *) "1.0"); - if (EXPECTED(lxml_doc)) { - lxml_doc->type = XML_HTML_DOCUMENT_NODE; - lxml_doc->dict = xmlDictCreate(); - } -#endif return lxml_doc; } diff --git a/ext/dom/php_dom.h b/ext/dom/php_dom.h index 34cc4af85c568..e44f74eadeb37 100644 --- a/ext/dom/php_dom.h +++ b/ext/dom/php_dom.h @@ -34,10 +34,8 @@ extern zend_module_entry dom_module_entry; #include #include #include -#ifdef LIBXML_HTML_ENABLED #include #include -#endif #ifdef LIBXML_XPATH_ENABLED #include #include diff --git a/ext/dom/php_dom.stub.php b/ext/dom/php_dom.stub.php index 7236e80b4d247..37a1bea62b627 100644 --- a/ext/dom/php_dom.stub.php +++ b/ext/dom/php_dom.stub.php @@ -1013,7 +1013,6 @@ public function registerNodeClass(string $baseClass, ?string $extendedClass): tr /** @tentative-return-type */ public function save(string $filename, int $options = 0): int|false {} -#ifdef LIBXML_HTML_ENABLED /** @tentative-return-type */ public function loadHTML(string $source, int $options = 0): bool {} @@ -1025,7 +1024,6 @@ public function saveHTML(?DOMNode $node = null): string|false {} /** @tentative-return-type */ public function saveHTMLFile(string $filename): int|false {} -#endif /** @tentative-return-type */ public function saveXML(?DOMNode $node = null, int $options = 0): string|false {} diff --git a/ext/dom/php_dom_arginfo.h b/ext/dom/php_dom_arginfo.h index af2d3f2f00fdb..1f3f9fd0a8a24 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: 757889c0ca89cc8e9905ba465e0621fe89b6e716 */ + * Stub hash: e3495cb89e4466d9102abb10bf6461989b7c8ba9 */ 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) @@ -404,16 +404,9 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX(arginfo_class_DOMDocument_save ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_LONG, 0, "0") ZEND_END_ARG_INFO() -#if defined(LIBXML_HTML_ENABLED) -ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DOMDocument_loadHTML, 0, 1, _IS_BOOL, 0) - ZEND_ARG_TYPE_INFO(0, source, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_LONG, 0, "0") -ZEND_END_ARG_INFO() +#define arginfo_class_DOMDocument_loadHTML arginfo_class_DOMDocument_loadXML -ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DOMDocument_loadHTMLFile, 0, 1, _IS_BOOL, 0) - ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_LONG, 0, "0") -ZEND_END_ARG_INFO() +#define arginfo_class_DOMDocument_loadHTMLFile arginfo_class_DOMDocument_load ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX(arginfo_class_DOMDocument_saveHTML, 0, 0, MAY_BE_STRING|MAY_BE_FALSE) ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, node, DOMNode, 1, "null") @@ -422,7 +415,6 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX(arginfo_class_DOMDocument_saveHTMLFile, 0, 1, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0) ZEND_END_ARG_INFO() -#endif ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX(arginfo_class_DOMDocument_saveXML, 0, 0, MAY_BE_STRING|MAY_BE_FALSE) ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, node, DOMNode, 1, "null") @@ -1228,12 +1220,10 @@ ZEND_METHOD(DOMDocument, loadXML); ZEND_METHOD(DOMDocument, normalizeDocument); ZEND_METHOD(DOMDocument, registerNodeClass); ZEND_METHOD(DOMDocument, save); -#if defined(LIBXML_HTML_ENABLED) ZEND_METHOD(DOMDocument, loadHTML); ZEND_METHOD(DOMDocument, loadHTMLFile); ZEND_METHOD(DOMDocument, saveHTML); ZEND_METHOD(DOMDocument, saveHTMLFile); -#endif ZEND_METHOD(DOMDocument, saveXML); #if defined(LIBXML_SCHEMAS_ENABLED) ZEND_METHOD(DOMDocument, schemaValidate); @@ -1496,12 +1486,10 @@ static const zend_function_entry class_DOMDocument_methods[] = { ZEND_ME(DOMDocument, normalizeDocument, arginfo_class_DOMDocument_normalizeDocument, ZEND_ACC_PUBLIC) ZEND_ME(DOMDocument, registerNodeClass, arginfo_class_DOMDocument_registerNodeClass, ZEND_ACC_PUBLIC) ZEND_ME(DOMDocument, save, arginfo_class_DOMDocument_save, ZEND_ACC_PUBLIC) -#if defined(LIBXML_HTML_ENABLED) ZEND_ME(DOMDocument, loadHTML, arginfo_class_DOMDocument_loadHTML, ZEND_ACC_PUBLIC) ZEND_ME(DOMDocument, loadHTMLFile, arginfo_class_DOMDocument_loadHTMLFile, ZEND_ACC_PUBLIC) ZEND_ME(DOMDocument, saveHTML, arginfo_class_DOMDocument_saveHTML, ZEND_ACC_PUBLIC) ZEND_ME(DOMDocument, saveHTMLFile, arginfo_class_DOMDocument_saveHTMLFile, ZEND_ACC_PUBLIC) -#endif ZEND_ME(DOMDocument, saveXML, arginfo_class_DOMDocument_saveXML, ZEND_ACC_PUBLIC) #if defined(LIBXML_SCHEMAS_ENABLED) ZEND_ME(DOMDocument, schemaValidate, arginfo_class_DOMDocument_schemaValidate, ZEND_ACC_PUBLIC) @@ -1884,10 +1872,8 @@ static void register_php_dom_symbols(int module_number) 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); - zval attribute_Deprecated_const_DOM_PHP_ERR_0_arg1; 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_arg1, attribute_Deprecated_const_DOM_PHP_ERR_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_DOM_PHP_ERR_0->args[1].value, &attribute_Deprecated_const_DOM_PHP_ERR_0_arg1); + 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); } @@ -1904,35 +1890,35 @@ static zend_class_entry *register_class_DOMDocumentType(zend_class_entry *class_ zval property_entities_default_value; ZVAL_UNDEF(&property_entities_default_value); - zend_string *property_entities_name = zend_string_init("entities", sizeof("entities") - 1, 1); + zend_string *property_entities_name = zend_string_init("entities", sizeof("entities") - 1, true); zend_string *property_entities_class_DOMNamedNodeMap = zend_string_init("DOMNamedNodeMap", sizeof("DOMNamedNodeMap")-1, 1); zend_declare_typed_property(class_entry, property_entities_name, &property_entities_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_entities_class_DOMNamedNodeMap, 0, 0)); - zend_string_release(property_entities_name); + zend_string_release_ex(property_entities_name, true); zval property_notations_default_value; ZVAL_UNDEF(&property_notations_default_value); - zend_string *property_notations_name = zend_string_init("notations", sizeof("notations") - 1, 1); + zend_string *property_notations_name = zend_string_init("notations", sizeof("notations") - 1, true); zend_string *property_notations_class_DOMNamedNodeMap = zend_string_init("DOMNamedNodeMap", sizeof("DOMNamedNodeMap")-1, 1); zend_declare_typed_property(class_entry, property_notations_name, &property_notations_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_notations_class_DOMNamedNodeMap, 0, 0)); - zend_string_release(property_notations_name); + zend_string_release_ex(property_notations_name, true); zval property_publicId_default_value; ZVAL_UNDEF(&property_publicId_default_value); - zend_string *property_publicId_name = zend_string_init("publicId", sizeof("publicId") - 1, 1); + zend_string *property_publicId_name = zend_string_init("publicId", sizeof("publicId") - 1, true); zend_declare_typed_property(class_entry, property_publicId_name, &property_publicId_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_publicId_name); + zend_string_release_ex(property_publicId_name, true); zval property_systemId_default_value; ZVAL_UNDEF(&property_systemId_default_value); - zend_string *property_systemId_name = zend_string_init("systemId", sizeof("systemId") - 1, 1); + zend_string *property_systemId_name = zend_string_init("systemId", sizeof("systemId") - 1, true); zend_declare_typed_property(class_entry, property_systemId_name, &property_systemId_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_systemId_name); + zend_string_release_ex(property_systemId_name, true); zval property_internalSubset_default_value; ZVAL_UNDEF(&property_internalSubset_default_value); - zend_string *property_internalSubset_name = zend_string_init("internalSubset", sizeof("internalSubset") - 1, 1); + zend_string *property_internalSubset_name = zend_string_init("internalSubset", sizeof("internalSubset") - 1, true); zend_declare_typed_property(class_entry, property_internalSubset_name, &property_internalSubset_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_internalSubset_name); + zend_string_release_ex(property_internalSubset_name, true); return class_entry; } @@ -1986,156 +1972,156 @@ static zend_class_entry *register_class_DOMNode(void) zval const_DOCUMENT_POSITION_DISCONNECTED_value; ZVAL_LONG(&const_DOCUMENT_POSITION_DISCONNECTED_value, 0x1); - zend_string *const_DOCUMENT_POSITION_DISCONNECTED_name = zend_string_init_interned("DOCUMENT_POSITION_DISCONNECTED", sizeof("DOCUMENT_POSITION_DISCONNECTED") - 1, 1); + zend_string *const_DOCUMENT_POSITION_DISCONNECTED_name = zend_string_init_interned("DOCUMENT_POSITION_DISCONNECTED", sizeof("DOCUMENT_POSITION_DISCONNECTED") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOCUMENT_POSITION_DISCONNECTED_name, &const_DOCUMENT_POSITION_DISCONNECTED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOCUMENT_POSITION_DISCONNECTED_name); + zend_string_release_ex(const_DOCUMENT_POSITION_DISCONNECTED_name, true); zval const_DOCUMENT_POSITION_PRECEDING_value; ZVAL_LONG(&const_DOCUMENT_POSITION_PRECEDING_value, 0x2); - zend_string *const_DOCUMENT_POSITION_PRECEDING_name = zend_string_init_interned("DOCUMENT_POSITION_PRECEDING", sizeof("DOCUMENT_POSITION_PRECEDING") - 1, 1); + zend_string *const_DOCUMENT_POSITION_PRECEDING_name = zend_string_init_interned("DOCUMENT_POSITION_PRECEDING", sizeof("DOCUMENT_POSITION_PRECEDING") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOCUMENT_POSITION_PRECEDING_name, &const_DOCUMENT_POSITION_PRECEDING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOCUMENT_POSITION_PRECEDING_name); + zend_string_release_ex(const_DOCUMENT_POSITION_PRECEDING_name, true); zval const_DOCUMENT_POSITION_FOLLOWING_value; ZVAL_LONG(&const_DOCUMENT_POSITION_FOLLOWING_value, 0x4); - zend_string *const_DOCUMENT_POSITION_FOLLOWING_name = zend_string_init_interned("DOCUMENT_POSITION_FOLLOWING", sizeof("DOCUMENT_POSITION_FOLLOWING") - 1, 1); + zend_string *const_DOCUMENT_POSITION_FOLLOWING_name = zend_string_init_interned("DOCUMENT_POSITION_FOLLOWING", sizeof("DOCUMENT_POSITION_FOLLOWING") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOCUMENT_POSITION_FOLLOWING_name, &const_DOCUMENT_POSITION_FOLLOWING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOCUMENT_POSITION_FOLLOWING_name); + zend_string_release_ex(const_DOCUMENT_POSITION_FOLLOWING_name, true); zval const_DOCUMENT_POSITION_CONTAINS_value; ZVAL_LONG(&const_DOCUMENT_POSITION_CONTAINS_value, 0x8); - zend_string *const_DOCUMENT_POSITION_CONTAINS_name = zend_string_init_interned("DOCUMENT_POSITION_CONTAINS", sizeof("DOCUMENT_POSITION_CONTAINS") - 1, 1); + zend_string *const_DOCUMENT_POSITION_CONTAINS_name = zend_string_init_interned("DOCUMENT_POSITION_CONTAINS", sizeof("DOCUMENT_POSITION_CONTAINS") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOCUMENT_POSITION_CONTAINS_name, &const_DOCUMENT_POSITION_CONTAINS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOCUMENT_POSITION_CONTAINS_name); + zend_string_release_ex(const_DOCUMENT_POSITION_CONTAINS_name, true); zval const_DOCUMENT_POSITION_CONTAINED_BY_value; ZVAL_LONG(&const_DOCUMENT_POSITION_CONTAINED_BY_value, 0x10); - zend_string *const_DOCUMENT_POSITION_CONTAINED_BY_name = zend_string_init_interned("DOCUMENT_POSITION_CONTAINED_BY", sizeof("DOCUMENT_POSITION_CONTAINED_BY") - 1, 1); + zend_string *const_DOCUMENT_POSITION_CONTAINED_BY_name = zend_string_init_interned("DOCUMENT_POSITION_CONTAINED_BY", sizeof("DOCUMENT_POSITION_CONTAINED_BY") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOCUMENT_POSITION_CONTAINED_BY_name, &const_DOCUMENT_POSITION_CONTAINED_BY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOCUMENT_POSITION_CONTAINED_BY_name); + zend_string_release_ex(const_DOCUMENT_POSITION_CONTAINED_BY_name, true); zval const_DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC_value; ZVAL_LONG(&const_DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC_value, 0x20); - zend_string *const_DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC_name = zend_string_init_interned("DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC", sizeof("DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC") - 1, 1); + zend_string *const_DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC_name = zend_string_init_interned("DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC", sizeof("DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC_name, &const_DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC_name); + zend_string_release_ex(const_DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC_name, true); zval property_nodeName_default_value; ZVAL_UNDEF(&property_nodeName_default_value); - zend_string *property_nodeName_name = zend_string_init("nodeName", sizeof("nodeName") - 1, 1); + zend_string *property_nodeName_name = zend_string_init("nodeName", sizeof("nodeName") - 1, true); zend_declare_typed_property(class_entry, property_nodeName_name, &property_nodeName_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_nodeName_name); + zend_string_release_ex(property_nodeName_name, true); zval property_nodeValue_default_value; ZVAL_UNDEF(&property_nodeValue_default_value); - zend_string *property_nodeValue_name = zend_string_init("nodeValue", sizeof("nodeValue") - 1, 1); + zend_string *property_nodeValue_name = zend_string_init("nodeValue", sizeof("nodeValue") - 1, true); zend_declare_typed_property(class_entry, property_nodeValue_name, &property_nodeValue_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_nodeValue_name); + zend_string_release_ex(property_nodeValue_name, true); zval property_nodeType_default_value; ZVAL_UNDEF(&property_nodeType_default_value); - zend_string *property_nodeType_name = zend_string_init("nodeType", sizeof("nodeType") - 1, 1); + zend_string *property_nodeType_name = zend_string_init("nodeType", sizeof("nodeType") - 1, true); zend_declare_typed_property(class_entry, property_nodeType_name, &property_nodeType_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_nodeType_name); + zend_string_release_ex(property_nodeType_name, true); zval property_parentNode_default_value; ZVAL_UNDEF(&property_parentNode_default_value); - zend_string *property_parentNode_name = zend_string_init("parentNode", sizeof("parentNode") - 1, 1); + zend_string *property_parentNode_name = zend_string_init("parentNode", sizeof("parentNode") - 1, true); zend_string *property_parentNode_class_DOMNode = zend_string_init("DOMNode", sizeof("DOMNode")-1, 1); zend_declare_typed_property(class_entry, property_parentNode_name, &property_parentNode_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_parentNode_class_DOMNode, 0, MAY_BE_NULL)); - zend_string_release(property_parentNode_name); + zend_string_release_ex(property_parentNode_name, true); zval property_parentElement_default_value; ZVAL_UNDEF(&property_parentElement_default_value); - zend_string *property_parentElement_name = zend_string_init("parentElement", sizeof("parentElement") - 1, 1); + zend_string *property_parentElement_name = zend_string_init("parentElement", sizeof("parentElement") - 1, true); zend_string *property_parentElement_class_DOMElement = zend_string_init("DOMElement", sizeof("DOMElement")-1, 1); zend_declare_typed_property(class_entry, property_parentElement_name, &property_parentElement_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_parentElement_class_DOMElement, 0, MAY_BE_NULL)); - zend_string_release(property_parentElement_name); + zend_string_release_ex(property_parentElement_name, true); zval property_childNodes_default_value; ZVAL_UNDEF(&property_childNodes_default_value); - zend_string *property_childNodes_name = zend_string_init("childNodes", sizeof("childNodes") - 1, 1); + zend_string *property_childNodes_name = zend_string_init("childNodes", sizeof("childNodes") - 1, true); zend_string *property_childNodes_class_DOMNodeList = zend_string_init("DOMNodeList", sizeof("DOMNodeList")-1, 1); zend_declare_typed_property(class_entry, property_childNodes_name, &property_childNodes_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_childNodes_class_DOMNodeList, 0, 0)); - zend_string_release(property_childNodes_name); + zend_string_release_ex(property_childNodes_name, true); zval property_firstChild_default_value; ZVAL_UNDEF(&property_firstChild_default_value); - zend_string *property_firstChild_name = zend_string_init("firstChild", sizeof("firstChild") - 1, 1); + zend_string *property_firstChild_name = zend_string_init("firstChild", sizeof("firstChild") - 1, true); zend_string *property_firstChild_class_DOMNode = zend_string_init("DOMNode", sizeof("DOMNode")-1, 1); zend_declare_typed_property(class_entry, property_firstChild_name, &property_firstChild_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_firstChild_class_DOMNode, 0, MAY_BE_NULL)); - zend_string_release(property_firstChild_name); + zend_string_release_ex(property_firstChild_name, true); zval property_lastChild_default_value; ZVAL_UNDEF(&property_lastChild_default_value); - zend_string *property_lastChild_name = zend_string_init("lastChild", sizeof("lastChild") - 1, 1); + zend_string *property_lastChild_name = zend_string_init("lastChild", sizeof("lastChild") - 1, true); zend_string *property_lastChild_class_DOMNode = zend_string_init("DOMNode", sizeof("DOMNode")-1, 1); zend_declare_typed_property(class_entry, property_lastChild_name, &property_lastChild_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_lastChild_class_DOMNode, 0, MAY_BE_NULL)); - zend_string_release(property_lastChild_name); + zend_string_release_ex(property_lastChild_name, true); zval property_previousSibling_default_value; ZVAL_UNDEF(&property_previousSibling_default_value); - zend_string *property_previousSibling_name = zend_string_init("previousSibling", sizeof("previousSibling") - 1, 1); + zend_string *property_previousSibling_name = zend_string_init("previousSibling", sizeof("previousSibling") - 1, true); zend_string *property_previousSibling_class_DOMNode = zend_string_init("DOMNode", sizeof("DOMNode")-1, 1); zend_declare_typed_property(class_entry, property_previousSibling_name, &property_previousSibling_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_previousSibling_class_DOMNode, 0, MAY_BE_NULL)); - zend_string_release(property_previousSibling_name); + zend_string_release_ex(property_previousSibling_name, true); zval property_nextSibling_default_value; ZVAL_UNDEF(&property_nextSibling_default_value); - zend_string *property_nextSibling_name = zend_string_init("nextSibling", sizeof("nextSibling") - 1, 1); + zend_string *property_nextSibling_name = zend_string_init("nextSibling", sizeof("nextSibling") - 1, true); zend_string *property_nextSibling_class_DOMNode = zend_string_init("DOMNode", sizeof("DOMNode")-1, 1); zend_declare_typed_property(class_entry, property_nextSibling_name, &property_nextSibling_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_nextSibling_class_DOMNode, 0, MAY_BE_NULL)); - zend_string_release(property_nextSibling_name); + zend_string_release_ex(property_nextSibling_name, true); 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_name = zend_string_init("attributes", sizeof("attributes") - 1, true); zend_string *property_attributes_class_DOMNamedNodeMap = zend_string_init("DOMNamedNodeMap", sizeof("DOMNamedNodeMap")-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_DOMNamedNodeMap, 0, MAY_BE_NULL)); - zend_string_release(property_attributes_name); + zend_string_release_ex(property_attributes_name, true); zval property_isConnected_default_value; ZVAL_UNDEF(&property_isConnected_default_value); - zend_string *property_isConnected_name = zend_string_init("isConnected", sizeof("isConnected") - 1, 1); + zend_string *property_isConnected_name = zend_string_init("isConnected", sizeof("isConnected") - 1, true); zend_declare_typed_property(class_entry, property_isConnected_name, &property_isConnected_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_isConnected_name); + zend_string_release_ex(property_isConnected_name, true); zval property_ownerDocument_default_value; ZVAL_UNDEF(&property_ownerDocument_default_value); - zend_string *property_ownerDocument_name = zend_string_init("ownerDocument", sizeof("ownerDocument") - 1, 1); + zend_string *property_ownerDocument_name = zend_string_init("ownerDocument", sizeof("ownerDocument") - 1, true); zend_string *property_ownerDocument_class_DOMDocument = zend_string_init("DOMDocument", sizeof("DOMDocument")-1, 1); zend_declare_typed_property(class_entry, property_ownerDocument_name, &property_ownerDocument_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_ownerDocument_class_DOMDocument, 0, MAY_BE_NULL)); - zend_string_release(property_ownerDocument_name); + zend_string_release_ex(property_ownerDocument_name, true); zval property_namespaceURI_default_value; ZVAL_UNDEF(&property_namespaceURI_default_value); - zend_string *property_namespaceURI_name = zend_string_init("namespaceURI", sizeof("namespaceURI") - 1, 1); + zend_string *property_namespaceURI_name = zend_string_init("namespaceURI", sizeof("namespaceURI") - 1, true); zend_declare_typed_property(class_entry, property_namespaceURI_name, &property_namespaceURI_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_namespaceURI_name); + zend_string_release_ex(property_namespaceURI_name, true); zval property_prefix_default_value; ZVAL_UNDEF(&property_prefix_default_value); - zend_string *property_prefix_name = zend_string_init("prefix", sizeof("prefix") - 1, 1); + zend_string *property_prefix_name = zend_string_init("prefix", sizeof("prefix") - 1, true); zend_declare_typed_property(class_entry, property_prefix_name, &property_prefix_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_prefix_name); + zend_string_release_ex(property_prefix_name, true); zval property_localName_default_value; ZVAL_UNDEF(&property_localName_default_value); - zend_string *property_localName_name = zend_string_init("localName", sizeof("localName") - 1, 1); + zend_string *property_localName_name = zend_string_init("localName", sizeof("localName") - 1, true); zend_declare_typed_property(class_entry, property_localName_name, &property_localName_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_localName_name); + zend_string_release_ex(property_localName_name, true); zval property_baseURI_default_value; ZVAL_UNDEF(&property_baseURI_default_value); - zend_string *property_baseURI_name = zend_string_init("baseURI", sizeof("baseURI") - 1, 1); + zend_string *property_baseURI_name = zend_string_init("baseURI", sizeof("baseURI") - 1, true); zend_declare_typed_property(class_entry, property_baseURI_name, &property_baseURI_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_baseURI_name); + zend_string_release_ex(property_baseURI_name, true); zval property_textContent_default_value; ZVAL_UNDEF(&property_textContent_default_value); - zend_string *property_textContent_name = zend_string_init("textContent", sizeof("textContent") - 1, 1); + zend_string *property_textContent_name = zend_string_init("textContent", sizeof("textContent") - 1, true); zend_declare_typed_property(class_entry, property_textContent_name, &property_textContent_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_textContent_name); + zend_string_release_ex(property_textContent_name, true); return class_entry; } @@ -2149,66 +2135,66 @@ static zend_class_entry *register_class_DOMNameSpaceNode(void) zval property_nodeName_default_value; ZVAL_UNDEF(&property_nodeName_default_value); - zend_string *property_nodeName_name = zend_string_init("nodeName", sizeof("nodeName") - 1, 1); + zend_string *property_nodeName_name = zend_string_init("nodeName", sizeof("nodeName") - 1, true); zend_declare_typed_property(class_entry, property_nodeName_name, &property_nodeName_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_nodeName_name); + zend_string_release_ex(property_nodeName_name, true); zval property_nodeValue_default_value; ZVAL_UNDEF(&property_nodeValue_default_value); - zend_string *property_nodeValue_name = zend_string_init("nodeValue", sizeof("nodeValue") - 1, 1); + zend_string *property_nodeValue_name = zend_string_init("nodeValue", sizeof("nodeValue") - 1, true); zend_declare_typed_property(class_entry, property_nodeValue_name, &property_nodeValue_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_nodeValue_name); + zend_string_release_ex(property_nodeValue_name, true); zval property_nodeType_default_value; ZVAL_UNDEF(&property_nodeType_default_value); - zend_string *property_nodeType_name = zend_string_init("nodeType", sizeof("nodeType") - 1, 1); + zend_string *property_nodeType_name = zend_string_init("nodeType", sizeof("nodeType") - 1, true); zend_declare_typed_property(class_entry, property_nodeType_name, &property_nodeType_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_nodeType_name); + zend_string_release_ex(property_nodeType_name, true); zval property_prefix_default_value; ZVAL_UNDEF(&property_prefix_default_value); - zend_string *property_prefix_name = zend_string_init("prefix", sizeof("prefix") - 1, 1); + zend_string *property_prefix_name = zend_string_init("prefix", sizeof("prefix") - 1, true); zend_declare_typed_property(class_entry, property_prefix_name, &property_prefix_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_prefix_name); + zend_string_release_ex(property_prefix_name, true); zval property_localName_default_value; ZVAL_UNDEF(&property_localName_default_value); - zend_string *property_localName_name = zend_string_init("localName", sizeof("localName") - 1, 1); + zend_string *property_localName_name = zend_string_init("localName", sizeof("localName") - 1, true); zend_declare_typed_property(class_entry, property_localName_name, &property_localName_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_localName_name); + zend_string_release_ex(property_localName_name, true); zval property_namespaceURI_default_value; ZVAL_UNDEF(&property_namespaceURI_default_value); - zend_string *property_namespaceURI_name = zend_string_init("namespaceURI", sizeof("namespaceURI") - 1, 1); + zend_string *property_namespaceURI_name = zend_string_init("namespaceURI", sizeof("namespaceURI") - 1, true); zend_declare_typed_property(class_entry, property_namespaceURI_name, &property_namespaceURI_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_namespaceURI_name); + zend_string_release_ex(property_namespaceURI_name, true); zval property_isConnected_default_value; ZVAL_UNDEF(&property_isConnected_default_value); - zend_string *property_isConnected_name = zend_string_init("isConnected", sizeof("isConnected") - 1, 1); + zend_string *property_isConnected_name = zend_string_init("isConnected", sizeof("isConnected") - 1, true); zend_declare_typed_property(class_entry, property_isConnected_name, &property_isConnected_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_isConnected_name); + zend_string_release_ex(property_isConnected_name, true); zval property_ownerDocument_default_value; ZVAL_UNDEF(&property_ownerDocument_default_value); - zend_string *property_ownerDocument_name = zend_string_init("ownerDocument", sizeof("ownerDocument") - 1, 1); + zend_string *property_ownerDocument_name = zend_string_init("ownerDocument", sizeof("ownerDocument") - 1, true); zend_string *property_ownerDocument_class_DOMDocument = zend_string_init("DOMDocument", sizeof("DOMDocument")-1, 1); zend_declare_typed_property(class_entry, property_ownerDocument_name, &property_ownerDocument_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_ownerDocument_class_DOMDocument, 0, MAY_BE_NULL)); - zend_string_release(property_ownerDocument_name); + zend_string_release_ex(property_ownerDocument_name, true); zval property_parentNode_default_value; ZVAL_UNDEF(&property_parentNode_default_value); - zend_string *property_parentNode_name = zend_string_init("parentNode", sizeof("parentNode") - 1, 1); + zend_string *property_parentNode_name = zend_string_init("parentNode", sizeof("parentNode") - 1, true); zend_string *property_parentNode_class_DOMNode = zend_string_init("DOMNode", sizeof("DOMNode")-1, 1); zend_declare_typed_property(class_entry, property_parentNode_name, &property_parentNode_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_parentNode_class_DOMNode, 0, MAY_BE_NULL)); - zend_string_release(property_parentNode_name); + zend_string_release_ex(property_parentNode_name, true); zval property_parentElement_default_value; ZVAL_UNDEF(&property_parentElement_default_value); - zend_string *property_parentElement_name = zend_string_init("parentElement", sizeof("parentElement") - 1, 1); + zend_string *property_parentElement_name = zend_string_init("parentElement", sizeof("parentElement") - 1, true); zend_string *property_parentElement_class_DOMElement = zend_string_init("DOMElement", sizeof("DOMElement")-1, 1); zend_declare_typed_property(class_entry, property_parentElement_name, &property_parentElement_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_parentElement_class_DOMElement, 0, MAY_BE_NULL)); - zend_string_release(property_parentElement_name); + zend_string_release_ex(property_parentElement_name, true); return class_entry; } @@ -2233,23 +2219,23 @@ static zend_class_entry *register_class_DOMDocumentFragment(zend_class_entry *cl 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_name = zend_string_init("firstElementChild", sizeof("firstElementChild") - 1, true); zend_string *property_firstElementChild_class_DOMElement = zend_string_init("DOMElement", sizeof("DOMElement")-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_DOMElement, 0, MAY_BE_NULL)); - zend_string_release(property_firstElementChild_name); + zend_string_release_ex(property_firstElementChild_name, true); 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_name = zend_string_init("lastElementChild", sizeof("lastElementChild") - 1, true); zend_string *property_lastElementChild_class_DOMElement = zend_string_init("DOMElement", sizeof("DOMElement")-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_DOMElement, 0, MAY_BE_NULL)); - zend_string_release(property_lastElementChild_name); + zend_string_release_ex(property_lastElementChild_name, true); 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_string *property_childElementCount_name = zend_string_init("childElementCount", sizeof("childElementCount") - 1, true); 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); + zend_string_release_ex(property_childElementCount_name, true); return class_entry; } @@ -2264,9 +2250,9 @@ static zend_class_entry *register_class_DOMNodeList(zend_class_entry *class_entr zval property_length_default_value; ZVAL_UNDEF(&property_length_default_value); - zend_string *property_length_name = zend_string_init("length", sizeof("length") - 1, 1); + zend_string *property_length_name = zend_string_init("length", sizeof("length") - 1, true); zend_declare_typed_property(class_entry, property_length_name, &property_length_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_length_name); + zend_string_release_ex(property_length_name, true); return class_entry; } @@ -2281,29 +2267,29 @@ static zend_class_entry *register_class_DOMCharacterData(zend_class_entry *class zval property_data_default_value; ZVAL_UNDEF(&property_data_default_value); - zend_string *property_data_name = zend_string_init("data", sizeof("data") - 1, 1); + zend_string *property_data_name = zend_string_init("data", sizeof("data") - 1, true); zend_declare_typed_property(class_entry, property_data_name, &property_data_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_data_name); + zend_string_release_ex(property_data_name, true); zval property_length_default_value; ZVAL_UNDEF(&property_length_default_value); - zend_string *property_length_name = zend_string_init("length", sizeof("length") - 1, 1); + zend_string *property_length_name = zend_string_init("length", sizeof("length") - 1, true); zend_declare_typed_property(class_entry, property_length_name, &property_length_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_length_name); + zend_string_release_ex(property_length_name, true); zval property_previousElementSibling_default_value; ZVAL_UNDEF(&property_previousElementSibling_default_value); - zend_string *property_previousElementSibling_name = zend_string_init("previousElementSibling", sizeof("previousElementSibling") - 1, 1); + zend_string *property_previousElementSibling_name = zend_string_init("previousElementSibling", sizeof("previousElementSibling") - 1, true); zend_string *property_previousElementSibling_class_DOMElement = zend_string_init("DOMElement", sizeof("DOMElement")-1, 1); zend_declare_typed_property(class_entry, property_previousElementSibling_name, &property_previousElementSibling_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_previousElementSibling_class_DOMElement, 0, MAY_BE_NULL)); - zend_string_release(property_previousElementSibling_name); + zend_string_release_ex(property_previousElementSibling_name, true); zval property_nextElementSibling_default_value; ZVAL_UNDEF(&property_nextElementSibling_default_value); - zend_string *property_nextElementSibling_name = zend_string_init("nextElementSibling", sizeof("nextElementSibling") - 1, 1); + zend_string *property_nextElementSibling_name = zend_string_init("nextElementSibling", sizeof("nextElementSibling") - 1, true); zend_string *property_nextElementSibling_class_DOMElement = zend_string_init("DOMElement", sizeof("DOMElement")-1, 1); 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_DOMElement, 0, MAY_BE_NULL)); - zend_string_release(property_nextElementSibling_name); + zend_string_release_ex(property_nextElementSibling_name, true); return class_entry; } @@ -2321,9 +2307,9 @@ static zend_class_entry *register_class_DOMAttr(zend_class_entry *class_entry_DO zval property_specified_default_value; ZVAL_UNDEF(&property_specified_default_value); - zend_string *property_specified_name = zend_string_init("specified", sizeof("specified") - 1, 1); + zend_string *property_specified_name = zend_string_init("specified", sizeof("specified") - 1, true); zend_declare_typed_property(class_entry, property_specified_name, &property_specified_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_specified_name); + zend_string_release_ex(property_specified_name, true); zval property_value_default_value; ZVAL_UNDEF(&property_value_default_value); @@ -2331,16 +2317,16 @@ static zend_class_entry *register_class_DOMAttr(zend_class_entry *class_entry_DO zval property_ownerElement_default_value; ZVAL_UNDEF(&property_ownerElement_default_value); - zend_string *property_ownerElement_name = zend_string_init("ownerElement", sizeof("ownerElement") - 1, 1); + zend_string *property_ownerElement_name = zend_string_init("ownerElement", sizeof("ownerElement") - 1, true); zend_string *property_ownerElement_class_DOMElement = zend_string_init("DOMElement", sizeof("DOMElement")-1, 1); zend_declare_typed_property(class_entry, property_ownerElement_name, &property_ownerElement_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_ownerElement_class_DOMElement, 0, MAY_BE_NULL)); - zend_string_release(property_ownerElement_name); + zend_string_release_ex(property_ownerElement_name, true); zval property_schemaTypeInfo_default_value; ZVAL_UNDEF(&property_schemaTypeInfo_default_value); - zend_string *property_schemaTypeInfo_name = zend_string_init("schemaTypeInfo", sizeof("schemaTypeInfo") - 1, 1); + zend_string *property_schemaTypeInfo_name = zend_string_init("schemaTypeInfo", sizeof("schemaTypeInfo") - 1, true); zend_declare_typed_property(class_entry, property_schemaTypeInfo_name, &property_schemaTypeInfo_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ANY)); - zend_string_release(property_schemaTypeInfo_name); + zend_string_release_ex(property_schemaTypeInfo_name, true); return class_entry; } @@ -2355,61 +2341,61 @@ static zend_class_entry *register_class_DOMElement(zend_class_entry *class_entry zval property_tagName_default_value; ZVAL_UNDEF(&property_tagName_default_value); - zend_string *property_tagName_name = zend_string_init("tagName", sizeof("tagName") - 1, 1); + zend_string *property_tagName_name = zend_string_init("tagName", sizeof("tagName") - 1, true); 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); + zend_string_release_ex(property_tagName_name, true); 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_string *property_className_name = zend_string_init("className", sizeof("className") - 1, true); 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); + zend_string_release_ex(property_className_name, true); 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_string *property_id_name = zend_string_init("id", sizeof("id") - 1, true); 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); + zend_string_release_ex(property_id_name, true); zval property_schemaTypeInfo_default_value; ZVAL_UNDEF(&property_schemaTypeInfo_default_value); - zend_string *property_schemaTypeInfo_name = zend_string_init("schemaTypeInfo", sizeof("schemaTypeInfo") - 1, 1); + zend_string *property_schemaTypeInfo_name = zend_string_init("schemaTypeInfo", sizeof("schemaTypeInfo") - 1, true); zend_declare_typed_property(class_entry, property_schemaTypeInfo_name, &property_schemaTypeInfo_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ANY)); - zend_string_release(property_schemaTypeInfo_name); + zend_string_release_ex(property_schemaTypeInfo_name, true); 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_name = zend_string_init("firstElementChild", sizeof("firstElementChild") - 1, true); zend_string *property_firstElementChild_class_DOMElement = zend_string_init("DOMElement", sizeof("DOMElement")-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_DOMElement, 0, MAY_BE_NULL)); - zend_string_release(property_firstElementChild_name); + zend_string_release_ex(property_firstElementChild_name, true); 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_name = zend_string_init("lastElementChild", sizeof("lastElementChild") - 1, true); zend_string *property_lastElementChild_class_DOMElement = zend_string_init("DOMElement", sizeof("DOMElement")-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_DOMElement, 0, MAY_BE_NULL)); - zend_string_release(property_lastElementChild_name); + zend_string_release_ex(property_lastElementChild_name, true); 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_string *property_childElementCount_name = zend_string_init("childElementCount", sizeof("childElementCount") - 1, true); 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); + zend_string_release_ex(property_childElementCount_name, true); zval property_previousElementSibling_default_value; ZVAL_UNDEF(&property_previousElementSibling_default_value); - zend_string *property_previousElementSibling_name = zend_string_init("previousElementSibling", sizeof("previousElementSibling") - 1, 1); + zend_string *property_previousElementSibling_name = zend_string_init("previousElementSibling", sizeof("previousElementSibling") - 1, true); zend_string *property_previousElementSibling_class_DOMElement = zend_string_init("DOMElement", sizeof("DOMElement")-1, 1); zend_declare_typed_property(class_entry, property_previousElementSibling_name, &property_previousElementSibling_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_previousElementSibling_class_DOMElement, 0, MAY_BE_NULL)); - zend_string_release(property_previousElementSibling_name); + zend_string_release_ex(property_previousElementSibling_name, true); zval property_nextElementSibling_default_value; ZVAL_UNDEF(&property_nextElementSibling_default_value); - zend_string *property_nextElementSibling_name = zend_string_init("nextElementSibling", sizeof("nextElementSibling") - 1, 1); + zend_string *property_nextElementSibling_name = zend_string_init("nextElementSibling", sizeof("nextElementSibling") - 1, true); zend_string *property_nextElementSibling_class_DOMElement = zend_string_init("DOMElement", sizeof("DOMElement")-1, 1); 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_DOMElement, 0, MAY_BE_NULL)); - zend_string_release(property_nextElementSibling_name); + zend_string_release_ex(property_nextElementSibling_name, true); return class_entry; } @@ -2424,140 +2410,140 @@ static zend_class_entry *register_class_DOMDocument(zend_class_entry *class_entr zval property_doctype_default_value; ZVAL_UNDEF(&property_doctype_default_value); - zend_string *property_doctype_name = zend_string_init("doctype", sizeof("doctype") - 1, 1); + zend_string *property_doctype_name = zend_string_init("doctype", sizeof("doctype") - 1, true); zend_string *property_doctype_class_DOMDocumentType = zend_string_init("DOMDocumentType", sizeof("DOMDocumentType")-1, 1); zend_declare_typed_property(class_entry, property_doctype_name, &property_doctype_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_doctype_class_DOMDocumentType, 0, MAY_BE_NULL)); - zend_string_release(property_doctype_name); + zend_string_release_ex(property_doctype_name, true); zval property_implementation_default_value; ZVAL_UNDEF(&property_implementation_default_value); - zend_string *property_implementation_name = zend_string_init("implementation", sizeof("implementation") - 1, 1); + zend_string *property_implementation_name = zend_string_init("implementation", sizeof("implementation") - 1, true); zend_string *property_implementation_class_DOMImplementation = zend_string_init("DOMImplementation", sizeof("DOMImplementation")-1, 1); zend_declare_typed_property(class_entry, property_implementation_name, &property_implementation_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_implementation_class_DOMImplementation, 0, 0)); - zend_string_release(property_implementation_name); + zend_string_release_ex(property_implementation_name, true); zval property_documentElement_default_value; ZVAL_UNDEF(&property_documentElement_default_value); - zend_string *property_documentElement_name = zend_string_init("documentElement", sizeof("documentElement") - 1, 1); + zend_string *property_documentElement_name = zend_string_init("documentElement", sizeof("documentElement") - 1, true); zend_string *property_documentElement_class_DOMElement = zend_string_init("DOMElement", sizeof("DOMElement")-1, 1); 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_DOMElement, 0, MAY_BE_NULL)); - zend_string_release(property_documentElement_name); + zend_string_release_ex(property_documentElement_name, true); zval property_actualEncoding_default_value; ZVAL_UNDEF(&property_actualEncoding_default_value); - zend_string *property_actualEncoding_name = zend_string_init("actualEncoding", sizeof("actualEncoding") - 1, 1); + zend_string *property_actualEncoding_name = zend_string_init("actualEncoding", sizeof("actualEncoding") - 1, true); zend_declare_typed_property(class_entry, property_actualEncoding_name, &property_actualEncoding_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_actualEncoding_name); + zend_string_release_ex(property_actualEncoding_name, true); zval property_encoding_default_value; ZVAL_UNDEF(&property_encoding_default_value); - zend_string *property_encoding_name = zend_string_init("encoding", sizeof("encoding") - 1, 1); + zend_string *property_encoding_name = zend_string_init("encoding", sizeof("encoding") - 1, true); zend_declare_typed_property(class_entry, property_encoding_name, &property_encoding_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_encoding_name); + zend_string_release_ex(property_encoding_name, true); zval property_xmlEncoding_default_value; ZVAL_UNDEF(&property_xmlEncoding_default_value); - zend_string *property_xmlEncoding_name = zend_string_init("xmlEncoding", sizeof("xmlEncoding") - 1, 1); + zend_string *property_xmlEncoding_name = zend_string_init("xmlEncoding", sizeof("xmlEncoding") - 1, true); zend_declare_typed_property(class_entry, property_xmlEncoding_name, &property_xmlEncoding_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_xmlEncoding_name); + zend_string_release_ex(property_xmlEncoding_name, true); zval property_standalone_default_value; ZVAL_UNDEF(&property_standalone_default_value); - zend_string *property_standalone_name = zend_string_init("standalone", sizeof("standalone") - 1, 1); + zend_string *property_standalone_name = zend_string_init("standalone", sizeof("standalone") - 1, true); zend_declare_typed_property(class_entry, property_standalone_name, &property_standalone_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_standalone_name); + zend_string_release_ex(property_standalone_name, true); zval property_xmlStandalone_default_value; ZVAL_UNDEF(&property_xmlStandalone_default_value); - zend_string *property_xmlStandalone_name = zend_string_init("xmlStandalone", sizeof("xmlStandalone") - 1, 1); + zend_string *property_xmlStandalone_name = zend_string_init("xmlStandalone", sizeof("xmlStandalone") - 1, true); zend_declare_typed_property(class_entry, property_xmlStandalone_name, &property_xmlStandalone_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_xmlStandalone_name); + zend_string_release_ex(property_xmlStandalone_name, true); zval property_version_default_value; ZVAL_UNDEF(&property_version_default_value); - zend_string *property_version_name = zend_string_init("version", sizeof("version") - 1, 1); + zend_string *property_version_name = zend_string_init("version", sizeof("version") - 1, true); zend_declare_typed_property(class_entry, property_version_name, &property_version_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_version_name); + zend_string_release_ex(property_version_name, true); zval property_xmlVersion_default_value; ZVAL_UNDEF(&property_xmlVersion_default_value); - zend_string *property_xmlVersion_name = zend_string_init("xmlVersion", sizeof("xmlVersion") - 1, 1); + zend_string *property_xmlVersion_name = zend_string_init("xmlVersion", sizeof("xmlVersion") - 1, true); zend_declare_typed_property(class_entry, property_xmlVersion_name, &property_xmlVersion_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_xmlVersion_name); + zend_string_release_ex(property_xmlVersion_name, true); zval property_strictErrorChecking_default_value; ZVAL_UNDEF(&property_strictErrorChecking_default_value); - zend_string *property_strictErrorChecking_name = zend_string_init("strictErrorChecking", sizeof("strictErrorChecking") - 1, 1); + zend_string *property_strictErrorChecking_name = zend_string_init("strictErrorChecking", sizeof("strictErrorChecking") - 1, true); zend_declare_typed_property(class_entry, property_strictErrorChecking_name, &property_strictErrorChecking_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_strictErrorChecking_name); + zend_string_release_ex(property_strictErrorChecking_name, true); zval property_documentURI_default_value; ZVAL_UNDEF(&property_documentURI_default_value); - zend_string *property_documentURI_name = zend_string_init("documentURI", sizeof("documentURI") - 1, 1); + zend_string *property_documentURI_name = zend_string_init("documentURI", sizeof("documentURI") - 1, true); zend_declare_typed_property(class_entry, property_documentURI_name, &property_documentURI_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_documentURI_name); + zend_string_release_ex(property_documentURI_name, true); zval property_config_default_value; ZVAL_UNDEF(&property_config_default_value); - zend_string *property_config_name = zend_string_init("config", sizeof("config") - 1, 1); + zend_string *property_config_name = zend_string_init("config", sizeof("config") - 1, true); zend_declare_typed_property(class_entry, property_config_name, &property_config_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ANY)); - zend_string_release(property_config_name); + zend_string_release_ex(property_config_name, true); zval property_formatOutput_default_value; ZVAL_UNDEF(&property_formatOutput_default_value); - zend_string *property_formatOutput_name = zend_string_init("formatOutput", sizeof("formatOutput") - 1, 1); + zend_string *property_formatOutput_name = zend_string_init("formatOutput", sizeof("formatOutput") - 1, true); zend_declare_typed_property(class_entry, property_formatOutput_name, &property_formatOutput_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_formatOutput_name); + zend_string_release_ex(property_formatOutput_name, true); zval property_validateOnParse_default_value; ZVAL_UNDEF(&property_validateOnParse_default_value); - zend_string *property_validateOnParse_name = zend_string_init("validateOnParse", sizeof("validateOnParse") - 1, 1); + zend_string *property_validateOnParse_name = zend_string_init("validateOnParse", sizeof("validateOnParse") - 1, true); zend_declare_typed_property(class_entry, property_validateOnParse_name, &property_validateOnParse_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_validateOnParse_name); + zend_string_release_ex(property_validateOnParse_name, true); zval property_resolveExternals_default_value; ZVAL_UNDEF(&property_resolveExternals_default_value); - zend_string *property_resolveExternals_name = zend_string_init("resolveExternals", sizeof("resolveExternals") - 1, 1); + zend_string *property_resolveExternals_name = zend_string_init("resolveExternals", sizeof("resolveExternals") - 1, true); zend_declare_typed_property(class_entry, property_resolveExternals_name, &property_resolveExternals_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_resolveExternals_name); + zend_string_release_ex(property_resolveExternals_name, true); zval property_preserveWhiteSpace_default_value; ZVAL_UNDEF(&property_preserveWhiteSpace_default_value); - zend_string *property_preserveWhiteSpace_name = zend_string_init("preserveWhiteSpace", sizeof("preserveWhiteSpace") - 1, 1); + zend_string *property_preserveWhiteSpace_name = zend_string_init("preserveWhiteSpace", sizeof("preserveWhiteSpace") - 1, true); zend_declare_typed_property(class_entry, property_preserveWhiteSpace_name, &property_preserveWhiteSpace_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_preserveWhiteSpace_name); + zend_string_release_ex(property_preserveWhiteSpace_name, true); zval property_recover_default_value; ZVAL_UNDEF(&property_recover_default_value); - zend_string *property_recover_name = zend_string_init("recover", sizeof("recover") - 1, 1); + zend_string *property_recover_name = zend_string_init("recover", sizeof("recover") - 1, true); zend_declare_typed_property(class_entry, property_recover_name, &property_recover_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_recover_name); + zend_string_release_ex(property_recover_name, true); zval property_substituteEntities_default_value; ZVAL_UNDEF(&property_substituteEntities_default_value); - zend_string *property_substituteEntities_name = zend_string_init("substituteEntities", sizeof("substituteEntities") - 1, 1); + zend_string *property_substituteEntities_name = zend_string_init("substituteEntities", sizeof("substituteEntities") - 1, true); zend_declare_typed_property(class_entry, property_substituteEntities_name, &property_substituteEntities_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_substituteEntities_name); + zend_string_release_ex(property_substituteEntities_name, true); 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_name = zend_string_init("firstElementChild", sizeof("firstElementChild") - 1, true); zend_string *property_firstElementChild_class_DOMElement = zend_string_init("DOMElement", sizeof("DOMElement")-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_DOMElement, 0, MAY_BE_NULL)); - zend_string_release(property_firstElementChild_name); + zend_string_release_ex(property_firstElementChild_name, true); 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_name = zend_string_init("lastElementChild", sizeof("lastElementChild") - 1, true); zend_string *property_lastElementChild_class_DOMElement = zend_string_init("DOMElement", sizeof("DOMElement")-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_DOMElement, 0, MAY_BE_NULL)); - zend_string_release(property_lastElementChild_name); + zend_string_release_ex(property_lastElementChild_name, true); 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_string *property_childElementCount_name = zend_string_init("childElementCount", sizeof("childElementCount") - 1, true); 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); + zend_string_release_ex(property_childElementCount_name, true); return class_entry; } @@ -2586,9 +2572,9 @@ static zend_class_entry *register_class_DOMText(zend_class_entry *class_entry_DO zval property_wholeText_default_value; ZVAL_UNDEF(&property_wholeText_default_value); - zend_string *property_wholeText_name = zend_string_init("wholeText", sizeof("wholeText") - 1, 1); + zend_string *property_wholeText_name = zend_string_init("wholeText", sizeof("wholeText") - 1, true); zend_declare_typed_property(class_entry, property_wholeText_name, &property_wholeText_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_wholeText_name); + zend_string_release_ex(property_wholeText_name, true); return class_entry; } @@ -2603,9 +2589,9 @@ static zend_class_entry *register_class_DOMNamedNodeMap(zend_class_entry *class_ zval property_length_default_value; ZVAL_UNDEF(&property_length_default_value); - zend_string *property_length_name = zend_string_init("length", sizeof("length") - 1, 1); + zend_string *property_length_name = zend_string_init("length", sizeof("length") - 1, true); zend_declare_typed_property(class_entry, property_length_name, &property_length_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_length_name); + zend_string_release_ex(property_length_name, true); return class_entry; } @@ -2619,39 +2605,39 @@ static zend_class_entry *register_class_DOMEntity(zend_class_entry *class_entry_ zval property_publicId_default_value; ZVAL_UNDEF(&property_publicId_default_value); - zend_string *property_publicId_name = zend_string_init("publicId", sizeof("publicId") - 1, 1); + zend_string *property_publicId_name = zend_string_init("publicId", sizeof("publicId") - 1, true); zend_declare_typed_property(class_entry, property_publicId_name, &property_publicId_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_publicId_name); + zend_string_release_ex(property_publicId_name, true); zval property_systemId_default_value; ZVAL_UNDEF(&property_systemId_default_value); - zend_string *property_systemId_name = zend_string_init("systemId", sizeof("systemId") - 1, 1); + zend_string *property_systemId_name = zend_string_init("systemId", sizeof("systemId") - 1, true); zend_declare_typed_property(class_entry, property_systemId_name, &property_systemId_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_systemId_name); + zend_string_release_ex(property_systemId_name, true); zval property_notationName_default_value; ZVAL_UNDEF(&property_notationName_default_value); - zend_string *property_notationName_name = zend_string_init("notationName", sizeof("notationName") - 1, 1); + zend_string *property_notationName_name = zend_string_init("notationName", sizeof("notationName") - 1, true); zend_declare_typed_property(class_entry, property_notationName_name, &property_notationName_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_notationName_name); + zend_string_release_ex(property_notationName_name, true); zval property_actualEncoding_default_value; ZVAL_UNDEF(&property_actualEncoding_default_value); - zend_string *property_actualEncoding_name = zend_string_init("actualEncoding", sizeof("actualEncoding") - 1, 1); + zend_string *property_actualEncoding_name = zend_string_init("actualEncoding", sizeof("actualEncoding") - 1, true); zend_declare_typed_property(class_entry, property_actualEncoding_name, &property_actualEncoding_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_actualEncoding_name); + zend_string_release_ex(property_actualEncoding_name, true); zval property_encoding_default_value; ZVAL_UNDEF(&property_encoding_default_value); - zend_string *property_encoding_name = zend_string_init("encoding", sizeof("encoding") - 1, 1); + zend_string *property_encoding_name = zend_string_init("encoding", sizeof("encoding") - 1, true); zend_declare_typed_property(class_entry, property_encoding_name, &property_encoding_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_encoding_name); + zend_string_release_ex(property_encoding_name, true); zval property_version_default_value; ZVAL_UNDEF(&property_version_default_value); - zend_string *property_version_name = zend_string_init("version", sizeof("version") - 1, 1); + zend_string *property_version_name = zend_string_init("version", sizeof("version") - 1, true); zend_declare_typed_property(class_entry, property_version_name, &property_version_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_version_name); + zend_string_release_ex(property_version_name, true); return class_entry; } @@ -2675,15 +2661,15 @@ static zend_class_entry *register_class_DOMNotation(zend_class_entry *class_entr zval property_publicId_default_value; ZVAL_UNDEF(&property_publicId_default_value); - zend_string *property_publicId_name = zend_string_init("publicId", sizeof("publicId") - 1, 1); + zend_string *property_publicId_name = zend_string_init("publicId", sizeof("publicId") - 1, true); zend_declare_typed_property(class_entry, property_publicId_name, &property_publicId_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_publicId_name); + zend_string_release_ex(property_publicId_name, true); zval property_systemId_default_value; ZVAL_UNDEF(&property_systemId_default_value); - zend_string *property_systemId_name = zend_string_init("systemId", sizeof("systemId") - 1, 1); + zend_string *property_systemId_name = zend_string_init("systemId", sizeof("systemId") - 1, true); zend_declare_typed_property(class_entry, property_systemId_name, &property_systemId_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_systemId_name); + zend_string_release_ex(property_systemId_name, true); return class_entry; } @@ -2697,15 +2683,15 @@ static zend_class_entry *register_class_DOMProcessingInstruction(zend_class_entr zval property_target_default_value; ZVAL_UNDEF(&property_target_default_value); - zend_string *property_target_name = zend_string_init("target", sizeof("target") - 1, 1); + zend_string *property_target_name = zend_string_init("target", sizeof("target") - 1, true); zend_declare_typed_property(class_entry, property_target_name, &property_target_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_target_name); + zend_string_release_ex(property_target_name, true); zval property_data_default_value; ZVAL_UNDEF(&property_data_default_value); - zend_string *property_data_name = zend_string_init("data", sizeof("data") - 1, 1); + zend_string *property_data_name = zend_string_init("data", sizeof("data") - 1, true); zend_declare_typed_property(class_entry, property_data_name, &property_data_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_data_name); + zend_string_release_ex(property_data_name, true); return class_entry; } @@ -2720,16 +2706,16 @@ static zend_class_entry *register_class_DOMXPath(void) zval property_document_default_value; ZVAL_UNDEF(&property_document_default_value); - zend_string *property_document_name = zend_string_init("document", sizeof("document") - 1, 1); + zend_string *property_document_name = zend_string_init("document", sizeof("document") - 1, true); zend_string *property_document_class_DOMDocument = zend_string_init("DOMDocument", sizeof("DOMDocument")-1, 1); zend_declare_typed_property(class_entry, property_document_name, &property_document_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_document_class_DOMDocument, 0, 0)); - zend_string_release(property_document_name); + zend_string_release_ex(property_document_name, true); zval property_registerNodeNamespaces_default_value; ZVAL_UNDEF(&property_registerNodeNamespaces_default_value); - zend_string *property_registerNodeNamespaces_name = zend_string_init("registerNodeNamespaces", sizeof("registerNodeNamespaces") - 1, 1); + zend_string *property_registerNodeNamespaces_name = zend_string_init("registerNodeNamespaces", sizeof("registerNodeNamespaces") - 1, true); zend_declare_typed_property(class_entry, property_registerNodeNamespaces_name, &property_registerNodeNamespaces_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_registerNodeNamespaces_name); + zend_string_release_ex(property_registerNodeNamespaces_name, true); return class_entry; } @@ -2774,131 +2760,131 @@ static zend_class_entry *register_class_Dom_Node(void) zval const_DOCUMENT_POSITION_DISCONNECTED_value; ZVAL_LONG(&const_DOCUMENT_POSITION_DISCONNECTED_value, 0x1); - zend_string *const_DOCUMENT_POSITION_DISCONNECTED_name = zend_string_init_interned("DOCUMENT_POSITION_DISCONNECTED", sizeof("DOCUMENT_POSITION_DISCONNECTED") - 1, 1); + zend_string *const_DOCUMENT_POSITION_DISCONNECTED_name = zend_string_init_interned("DOCUMENT_POSITION_DISCONNECTED", sizeof("DOCUMENT_POSITION_DISCONNECTED") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOCUMENT_POSITION_DISCONNECTED_name, &const_DOCUMENT_POSITION_DISCONNECTED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOCUMENT_POSITION_DISCONNECTED_name); + zend_string_release_ex(const_DOCUMENT_POSITION_DISCONNECTED_name, true); zval const_DOCUMENT_POSITION_PRECEDING_value; ZVAL_LONG(&const_DOCUMENT_POSITION_PRECEDING_value, 0x2); - zend_string *const_DOCUMENT_POSITION_PRECEDING_name = zend_string_init_interned("DOCUMENT_POSITION_PRECEDING", sizeof("DOCUMENT_POSITION_PRECEDING") - 1, 1); + zend_string *const_DOCUMENT_POSITION_PRECEDING_name = zend_string_init_interned("DOCUMENT_POSITION_PRECEDING", sizeof("DOCUMENT_POSITION_PRECEDING") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOCUMENT_POSITION_PRECEDING_name, &const_DOCUMENT_POSITION_PRECEDING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOCUMENT_POSITION_PRECEDING_name); + zend_string_release_ex(const_DOCUMENT_POSITION_PRECEDING_name, true); zval const_DOCUMENT_POSITION_FOLLOWING_value; ZVAL_LONG(&const_DOCUMENT_POSITION_FOLLOWING_value, 0x4); - zend_string *const_DOCUMENT_POSITION_FOLLOWING_name = zend_string_init_interned("DOCUMENT_POSITION_FOLLOWING", sizeof("DOCUMENT_POSITION_FOLLOWING") - 1, 1); + zend_string *const_DOCUMENT_POSITION_FOLLOWING_name = zend_string_init_interned("DOCUMENT_POSITION_FOLLOWING", sizeof("DOCUMENT_POSITION_FOLLOWING") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOCUMENT_POSITION_FOLLOWING_name, &const_DOCUMENT_POSITION_FOLLOWING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOCUMENT_POSITION_FOLLOWING_name); + zend_string_release_ex(const_DOCUMENT_POSITION_FOLLOWING_name, true); zval const_DOCUMENT_POSITION_CONTAINS_value; ZVAL_LONG(&const_DOCUMENT_POSITION_CONTAINS_value, 0x8); - zend_string *const_DOCUMENT_POSITION_CONTAINS_name = zend_string_init_interned("DOCUMENT_POSITION_CONTAINS", sizeof("DOCUMENT_POSITION_CONTAINS") - 1, 1); + zend_string *const_DOCUMENT_POSITION_CONTAINS_name = zend_string_init_interned("DOCUMENT_POSITION_CONTAINS", sizeof("DOCUMENT_POSITION_CONTAINS") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOCUMENT_POSITION_CONTAINS_name, &const_DOCUMENT_POSITION_CONTAINS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOCUMENT_POSITION_CONTAINS_name); + zend_string_release_ex(const_DOCUMENT_POSITION_CONTAINS_name, true); zval const_DOCUMENT_POSITION_CONTAINED_BY_value; ZVAL_LONG(&const_DOCUMENT_POSITION_CONTAINED_BY_value, 0x10); - zend_string *const_DOCUMENT_POSITION_CONTAINED_BY_name = zend_string_init_interned("DOCUMENT_POSITION_CONTAINED_BY", sizeof("DOCUMENT_POSITION_CONTAINED_BY") - 1, 1); + zend_string *const_DOCUMENT_POSITION_CONTAINED_BY_name = zend_string_init_interned("DOCUMENT_POSITION_CONTAINED_BY", sizeof("DOCUMENT_POSITION_CONTAINED_BY") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOCUMENT_POSITION_CONTAINED_BY_name, &const_DOCUMENT_POSITION_CONTAINED_BY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOCUMENT_POSITION_CONTAINED_BY_name); + zend_string_release_ex(const_DOCUMENT_POSITION_CONTAINED_BY_name, true); zval const_DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC_value; ZVAL_LONG(&const_DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC_value, 0x20); - zend_string *const_DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC_name = zend_string_init_interned("DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC", sizeof("DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC") - 1, 1); + zend_string *const_DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC_name = zend_string_init_interned("DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC", sizeof("DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC_name, &const_DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC_name); + zend_string_release_ex(const_DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC_name, true); zval property_nodeType_default_value; ZVAL_UNDEF(&property_nodeType_default_value); - zend_string *property_nodeType_name = zend_string_init("nodeType", sizeof("nodeType") - 1, 1); + zend_string *property_nodeType_name = zend_string_init("nodeType", sizeof("nodeType") - 1, true); zend_declare_typed_property(class_entry, property_nodeType_name, &property_nodeType_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_nodeType_name); + zend_string_release_ex(property_nodeType_name, true); zval property_nodeName_default_value; ZVAL_UNDEF(&property_nodeName_default_value); - zend_string *property_nodeName_name = zend_string_init("nodeName", sizeof("nodeName") - 1, 1); + zend_string *property_nodeName_name = zend_string_init("nodeName", sizeof("nodeName") - 1, true); zend_declare_typed_property(class_entry, property_nodeName_name, &property_nodeName_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_nodeName_name); + zend_string_release_ex(property_nodeName_name, true); zval property_baseURI_default_value; ZVAL_UNDEF(&property_baseURI_default_value); - zend_string *property_baseURI_name = zend_string_init("baseURI", sizeof("baseURI") - 1, 1); + zend_string *property_baseURI_name = zend_string_init("baseURI", sizeof("baseURI") - 1, true); zend_declare_typed_property(class_entry, property_baseURI_name, &property_baseURI_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_baseURI_name); + zend_string_release_ex(property_baseURI_name, true); zval property_isConnected_default_value; ZVAL_UNDEF(&property_isConnected_default_value); - zend_string *property_isConnected_name = zend_string_init("isConnected", sizeof("isConnected") - 1, 1); + zend_string *property_isConnected_name = zend_string_init("isConnected", sizeof("isConnected") - 1, true); zend_declare_typed_property(class_entry, property_isConnected_name, &property_isConnected_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_isConnected_name); + zend_string_release_ex(property_isConnected_name, true); zval property_ownerDocument_default_value; ZVAL_UNDEF(&property_ownerDocument_default_value); - zend_string *property_ownerDocument_name = zend_string_init("ownerDocument", sizeof("ownerDocument") - 1, 1); + zend_string *property_ownerDocument_name = zend_string_init("ownerDocument", sizeof("ownerDocument") - 1, true); zend_string *property_ownerDocument_class_Dom_Document = zend_string_init("Dom\\Document", sizeof("Dom\\Document")-1, 1); zend_declare_typed_property(class_entry, property_ownerDocument_name, &property_ownerDocument_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_ownerDocument_class_Dom_Document, 0, MAY_BE_NULL)); - zend_string_release(property_ownerDocument_name); + zend_string_release_ex(property_ownerDocument_name, true); zval property_parentNode_default_value; ZVAL_UNDEF(&property_parentNode_default_value); - zend_string *property_parentNode_name = zend_string_init("parentNode", sizeof("parentNode") - 1, 1); + zend_string *property_parentNode_name = zend_string_init("parentNode", sizeof("parentNode") - 1, true); zend_string *property_parentNode_class_Dom_Node = zend_string_init("Dom\\\116ode", sizeof("Dom\\\116ode")-1, 1); zend_declare_typed_property(class_entry, property_parentNode_name, &property_parentNode_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_parentNode_class_Dom_Node, 0, MAY_BE_NULL)); - zend_string_release(property_parentNode_name); + zend_string_release_ex(property_parentNode_name, true); zval property_parentElement_default_value; ZVAL_UNDEF(&property_parentElement_default_value); - zend_string *property_parentElement_name = zend_string_init("parentElement", sizeof("parentElement") - 1, 1); + zend_string *property_parentElement_name = zend_string_init("parentElement", sizeof("parentElement") - 1, true); zend_string *property_parentElement_class_Dom_Element = zend_string_init("Dom\\Element", sizeof("Dom\\Element")-1, 1); zend_declare_typed_property(class_entry, property_parentElement_name, &property_parentElement_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_parentElement_class_Dom_Element, 0, MAY_BE_NULL)); - zend_string_release(property_parentElement_name); + zend_string_release_ex(property_parentElement_name, true); zval property_childNodes_default_value; ZVAL_UNDEF(&property_childNodes_default_value); - zend_string *property_childNodes_name = zend_string_init("childNodes", sizeof("childNodes") - 1, 1); + zend_string *property_childNodes_name = zend_string_init("childNodes", sizeof("childNodes") - 1, true); zend_string *property_childNodes_class_Dom_NodeList = zend_string_init("Dom\\\116odeList", sizeof("Dom\\\116odeList")-1, 1); zend_declare_typed_property(class_entry, property_childNodes_name, &property_childNodes_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_childNodes_class_Dom_NodeList, 0, 0)); - zend_string_release(property_childNodes_name); + zend_string_release_ex(property_childNodes_name, true); zval property_firstChild_default_value; ZVAL_UNDEF(&property_firstChild_default_value); - zend_string *property_firstChild_name = zend_string_init("firstChild", sizeof("firstChild") - 1, 1); + zend_string *property_firstChild_name = zend_string_init("firstChild", sizeof("firstChild") - 1, true); zend_string *property_firstChild_class_Dom_Node = zend_string_init("Dom\\\116ode", sizeof("Dom\\\116ode")-1, 1); zend_declare_typed_property(class_entry, property_firstChild_name, &property_firstChild_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_firstChild_class_Dom_Node, 0, MAY_BE_NULL)); - zend_string_release(property_firstChild_name); + zend_string_release_ex(property_firstChild_name, true); zval property_lastChild_default_value; ZVAL_UNDEF(&property_lastChild_default_value); - zend_string *property_lastChild_name = zend_string_init("lastChild", sizeof("lastChild") - 1, 1); + zend_string *property_lastChild_name = zend_string_init("lastChild", sizeof("lastChild") - 1, true); zend_string *property_lastChild_class_Dom_Node = zend_string_init("Dom\\\116ode", sizeof("Dom\\\116ode")-1, 1); zend_declare_typed_property(class_entry, property_lastChild_name, &property_lastChild_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_lastChild_class_Dom_Node, 0, MAY_BE_NULL)); - zend_string_release(property_lastChild_name); + zend_string_release_ex(property_lastChild_name, true); zval property_previousSibling_default_value; ZVAL_UNDEF(&property_previousSibling_default_value); - zend_string *property_previousSibling_name = zend_string_init("previousSibling", sizeof("previousSibling") - 1, 1); + zend_string *property_previousSibling_name = zend_string_init("previousSibling", sizeof("previousSibling") - 1, true); zend_string *property_previousSibling_class_Dom_Node = zend_string_init("Dom\\\116ode", sizeof("Dom\\\116ode")-1, 1); zend_declare_typed_property(class_entry, property_previousSibling_name, &property_previousSibling_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_previousSibling_class_Dom_Node, 0, MAY_BE_NULL)); - zend_string_release(property_previousSibling_name); + zend_string_release_ex(property_previousSibling_name, true); zval property_nextSibling_default_value; ZVAL_UNDEF(&property_nextSibling_default_value); - zend_string *property_nextSibling_name = zend_string_init("nextSibling", sizeof("nextSibling") - 1, 1); + zend_string *property_nextSibling_name = zend_string_init("nextSibling", sizeof("nextSibling") - 1, true); zend_string *property_nextSibling_class_Dom_Node = zend_string_init("Dom\\\116ode", sizeof("Dom\\\116ode")-1, 1); zend_declare_typed_property(class_entry, property_nextSibling_name, &property_nextSibling_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_nextSibling_class_Dom_Node, 0, MAY_BE_NULL)); - zend_string_release(property_nextSibling_name); + zend_string_release_ex(property_nextSibling_name, true); zval property_nodeValue_default_value; ZVAL_UNDEF(&property_nodeValue_default_value); - zend_string *property_nodeValue_name = zend_string_init("nodeValue", sizeof("nodeValue") - 1, 1); + zend_string *property_nodeValue_name = zend_string_init("nodeValue", sizeof("nodeValue") - 1, true); zend_declare_typed_property(class_entry, property_nodeValue_name, &property_nodeValue_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_nodeValue_name); + zend_string_release_ex(property_nodeValue_name, true); zval property_textContent_default_value; ZVAL_UNDEF(&property_textContent_default_value); - zend_string *property_textContent_name = zend_string_init("textContent", sizeof("textContent") - 1, 1); + zend_string *property_textContent_name = zend_string_init("textContent", sizeof("textContent") - 1, true); zend_declare_typed_property(class_entry, property_textContent_name, &property_textContent_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_textContent_name); + zend_string_release_ex(property_textContent_name, true); return class_entry; } @@ -2913,9 +2899,9 @@ static zend_class_entry *register_class_Dom_NodeList(zend_class_entry *class_ent zval property_length_default_value; ZVAL_UNDEF(&property_length_default_value); - zend_string *property_length_name = zend_string_init("length", sizeof("length") - 1, 1); + zend_string *property_length_name = zend_string_init("length", sizeof("length") - 1, true); zend_declare_typed_property(class_entry, property_length_name, &property_length_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_length_name); + zend_string_release_ex(property_length_name, true); return class_entry; } @@ -2930,9 +2916,9 @@ static zend_class_entry *register_class_Dom_NamedNodeMap(zend_class_entry *class zval property_length_default_value; ZVAL_UNDEF(&property_length_default_value); - zend_string *property_length_name = zend_string_init("length", sizeof("length") - 1, 1); + zend_string *property_length_name = zend_string_init("length", sizeof("length") - 1, true); zend_declare_typed_property(class_entry, property_length_name, &property_length_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_length_name); + zend_string_release_ex(property_length_name, true); return class_entry; } @@ -2947,9 +2933,9 @@ static zend_class_entry *register_class_Dom_DtdNamedNodeMap(zend_class_entry *cl zval property_length_default_value; ZVAL_UNDEF(&property_length_default_value); - zend_string *property_length_name = zend_string_init("length", sizeof("length") - 1, 1); + zend_string *property_length_name = zend_string_init("length", sizeof("length") - 1, true); zend_declare_typed_property(class_entry, property_length_name, &property_length_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_length_name); + zend_string_release_ex(property_length_name, true); return class_entry; } @@ -2964,9 +2950,9 @@ static zend_class_entry *register_class_Dom_HTMLCollection(zend_class_entry *cla zval property_length_default_value; ZVAL_UNDEF(&property_length_default_value); - zend_string *property_length_name = zend_string_init("length", sizeof("length") - 1, 1); + zend_string *property_length_name = zend_string_init("length", sizeof("length") - 1, true); zend_declare_typed_property(class_entry, property_length_name, &property_length_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_length_name); + zend_string_release_ex(property_length_name, true); return class_entry; } @@ -3008,112 +2994,112 @@ static zend_class_entry *register_class_Dom_Element(zend_class_entry *class_entr zval property_namespaceURI_default_value; ZVAL_UNDEF(&property_namespaceURI_default_value); - zend_string *property_namespaceURI_name = zend_string_init("namespaceURI", sizeof("namespaceURI") - 1, 1); + zend_string *property_namespaceURI_name = zend_string_init("namespaceURI", sizeof("namespaceURI") - 1, true); zend_declare_typed_property(class_entry, property_namespaceURI_name, &property_namespaceURI_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_namespaceURI_name); + zend_string_release_ex(property_namespaceURI_name, true); zval property_prefix_default_value; ZVAL_UNDEF(&property_prefix_default_value); - zend_string *property_prefix_name = zend_string_init("prefix", sizeof("prefix") - 1, 1); + zend_string *property_prefix_name = zend_string_init("prefix", sizeof("prefix") - 1, true); zend_declare_typed_property(class_entry, property_prefix_name, &property_prefix_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_prefix_name); + zend_string_release_ex(property_prefix_name, true); zval property_localName_default_value; ZVAL_UNDEF(&property_localName_default_value); - zend_string *property_localName_name = zend_string_init("localName", sizeof("localName") - 1, 1); + zend_string *property_localName_name = zend_string_init("localName", sizeof("localName") - 1, true); zend_declare_typed_property(class_entry, property_localName_name, &property_localName_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_localName_name); + zend_string_release_ex(property_localName_name, true); zval property_tagName_default_value; ZVAL_UNDEF(&property_tagName_default_value); - zend_string *property_tagName_name = zend_string_init("tagName", sizeof("tagName") - 1, 1); + zend_string *property_tagName_name = zend_string_init("tagName", sizeof("tagName") - 1, true); 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); + zend_string_release_ex(property_tagName_name, true); 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_name = zend_string_init("children", sizeof("children") - 1, true); 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); + zend_string_release_ex(property_children_name, true); 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_name = zend_string_init("firstElementChild", sizeof("firstElementChild") - 1, true); 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); + zend_string_release_ex(property_firstElementChild_name, true); 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_name = zend_string_init("lastElementChild", sizeof("lastElementChild") - 1, true); 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); + zend_string_release_ex(property_lastElementChild_name, true); 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_string *property_childElementCount_name = zend_string_init("childElementCount", sizeof("childElementCount") - 1, true); 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); + zend_string_release_ex(property_childElementCount_name, true); zval property_previousElementSibling_default_value; ZVAL_UNDEF(&property_previousElementSibling_default_value); - zend_string *property_previousElementSibling_name = zend_string_init("previousElementSibling", sizeof("previousElementSibling") - 1, 1); + zend_string *property_previousElementSibling_name = zend_string_init("previousElementSibling", sizeof("previousElementSibling") - 1, true); zend_string *property_previousElementSibling_class_Dom_Element = zend_string_init("Dom\\Element", sizeof("Dom\\Element")-1, 1); zend_declare_typed_property(class_entry, property_previousElementSibling_name, &property_previousElementSibling_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_previousElementSibling_class_Dom_Element, 0, MAY_BE_NULL)); - zend_string_release(property_previousElementSibling_name); + zend_string_release_ex(property_previousElementSibling_name, true); zval property_nextElementSibling_default_value; ZVAL_UNDEF(&property_nextElementSibling_default_value); - zend_string *property_nextElementSibling_name = zend_string_init("nextElementSibling", sizeof("nextElementSibling") - 1, 1); + zend_string *property_nextElementSibling_name = zend_string_init("nextElementSibling", sizeof("nextElementSibling") - 1, true); zend_string *property_nextElementSibling_class_Dom_Element = zend_string_init("Dom\\Element", sizeof("Dom\\Element")-1, 1); 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); + zend_string_release_ex(property_nextElementSibling_name, true); 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_string *property_id_name = zend_string_init("id", sizeof("id") - 1, true); 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); + zend_string_release_ex(property_id_name, true); 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_string *property_className_name = zend_string_init("className", sizeof("className") - 1, true); 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); + zend_string_release_ex(property_className_name, true); 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_name = zend_string_init("classList", sizeof("classList") - 1, true); 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); + zend_string_release_ex(property_classList_name, true); 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_name = zend_string_init("attributes", sizeof("attributes") - 1, true); 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); + zend_string_release_ex(property_attributes_name, true); zval property_innerHTML_default_value; ZVAL_UNDEF(&property_innerHTML_default_value); - zend_string *property_innerHTML_name = zend_string_init("innerHTML", sizeof("innerHTML") - 1, 1); + zend_string *property_innerHTML_name = zend_string_init("innerHTML", sizeof("innerHTML") - 1, true); zend_declare_typed_property(class_entry, property_innerHTML_name, &property_innerHTML_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_innerHTML_name); + zend_string_release_ex(property_innerHTML_name, true); zval property_outerHTML_default_value; ZVAL_UNDEF(&property_outerHTML_default_value); - zend_string *property_outerHTML_name = zend_string_init("outerHTML", sizeof("outerHTML") - 1, 1); + zend_string *property_outerHTML_name = zend_string_init("outerHTML", sizeof("outerHTML") - 1, true); zend_declare_typed_property(class_entry, property_outerHTML_name, &property_outerHTML_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_outerHTML_name); + zend_string_release_ex(property_outerHTML_name, true); zval property_substitutedNodeValue_default_value; ZVAL_UNDEF(&property_substitutedNodeValue_default_value); - zend_string *property_substitutedNodeValue_name = zend_string_init("substitutedNodeValue", sizeof("substitutedNodeValue") - 1, 1); + zend_string *property_substitutedNodeValue_name = zend_string_init("substitutedNodeValue", sizeof("substitutedNodeValue") - 1, true); zend_declare_typed_property(class_entry, property_substitutedNodeValue_name, &property_substitutedNodeValue_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_substitutedNodeValue_name); + zend_string_release_ex(property_substitutedNodeValue_name, true); return class_entry; } @@ -3137,21 +3123,21 @@ static zend_class_entry *register_class_Dom_Attr(zend_class_entry *class_entry_D zval property_namespaceURI_default_value; ZVAL_UNDEF(&property_namespaceURI_default_value); - zend_string *property_namespaceURI_name = zend_string_init("namespaceURI", sizeof("namespaceURI") - 1, 1); + zend_string *property_namespaceURI_name = zend_string_init("namespaceURI", sizeof("namespaceURI") - 1, true); zend_declare_typed_property(class_entry, property_namespaceURI_name, &property_namespaceURI_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_namespaceURI_name); + zend_string_release_ex(property_namespaceURI_name, true); zval property_prefix_default_value; ZVAL_UNDEF(&property_prefix_default_value); - zend_string *property_prefix_name = zend_string_init("prefix", sizeof("prefix") - 1, 1); + zend_string *property_prefix_name = zend_string_init("prefix", sizeof("prefix") - 1, true); zend_declare_typed_property(class_entry, property_prefix_name, &property_prefix_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_prefix_name); + zend_string_release_ex(property_prefix_name, true); zval property_localName_default_value; ZVAL_UNDEF(&property_localName_default_value); - zend_string *property_localName_name = zend_string_init("localName", sizeof("localName") - 1, 1); + zend_string *property_localName_name = zend_string_init("localName", sizeof("localName") - 1, true); zend_declare_typed_property(class_entry, property_localName_name, &property_localName_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_localName_name); + zend_string_release_ex(property_localName_name, true); zval property_name_default_value; ZVAL_UNDEF(&property_name_default_value); @@ -3163,16 +3149,16 @@ static zend_class_entry *register_class_Dom_Attr(zend_class_entry *class_entry_D zval property_ownerElement_default_value; ZVAL_UNDEF(&property_ownerElement_default_value); - zend_string *property_ownerElement_name = zend_string_init("ownerElement", sizeof("ownerElement") - 1, 1); + zend_string *property_ownerElement_name = zend_string_init("ownerElement", sizeof("ownerElement") - 1, true); zend_string *property_ownerElement_class_Dom_Element = zend_string_init("Dom\\Element", sizeof("Dom\\Element")-1, 1); zend_declare_typed_property(class_entry, property_ownerElement_name, &property_ownerElement_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_ownerElement_class_Dom_Element, 0, MAY_BE_NULL)); - zend_string_release(property_ownerElement_name); + zend_string_release_ex(property_ownerElement_name, true); zval property_specified_default_value; ZVAL_UNDEF(&property_specified_default_value); - zend_string *property_specified_name = zend_string_init("specified", sizeof("specified") - 1, 1); + zend_string *property_specified_name = zend_string_init("specified", sizeof("specified") - 1, true); zend_declare_typed_property(class_entry, property_specified_name, &property_specified_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_specified_name); + zend_string_release_ex(property_specified_name, true); return class_entry; } @@ -3187,29 +3173,29 @@ static zend_class_entry *register_class_Dom_CharacterData(zend_class_entry *clas zval property_previousElementSibling_default_value; ZVAL_UNDEF(&property_previousElementSibling_default_value); - zend_string *property_previousElementSibling_name = zend_string_init("previousElementSibling", sizeof("previousElementSibling") - 1, 1); + zend_string *property_previousElementSibling_name = zend_string_init("previousElementSibling", sizeof("previousElementSibling") - 1, true); zend_string *property_previousElementSibling_class_Dom_Element = zend_string_init("Dom\\Element", sizeof("Dom\\Element")-1, 1); zend_declare_typed_property(class_entry, property_previousElementSibling_name, &property_previousElementSibling_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_previousElementSibling_class_Dom_Element, 0, MAY_BE_NULL)); - zend_string_release(property_previousElementSibling_name); + zend_string_release_ex(property_previousElementSibling_name, true); zval property_nextElementSibling_default_value; ZVAL_UNDEF(&property_nextElementSibling_default_value); - zend_string *property_nextElementSibling_name = zend_string_init("nextElementSibling", sizeof("nextElementSibling") - 1, 1); + zend_string *property_nextElementSibling_name = zend_string_init("nextElementSibling", sizeof("nextElementSibling") - 1, true); zend_string *property_nextElementSibling_class_Dom_Element = zend_string_init("Dom\\Element", sizeof("Dom\\Element")-1, 1); 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); + zend_string_release_ex(property_nextElementSibling_name, true); zval property_data_default_value; ZVAL_UNDEF(&property_data_default_value); - zend_string *property_data_name = zend_string_init("data", sizeof("data") - 1, 1); + zend_string *property_data_name = zend_string_init("data", sizeof("data") - 1, true); zend_declare_typed_property(class_entry, property_data_name, &property_data_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_data_name); + zend_string_release_ex(property_data_name, true); zval property_length_default_value; ZVAL_UNDEF(&property_length_default_value); - zend_string *property_length_name = zend_string_init("length", sizeof("length") - 1, 1); + zend_string *property_length_name = zend_string_init("length", sizeof("length") - 1, true); zend_declare_typed_property(class_entry, property_length_name, &property_length_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_length_name); + zend_string_release_ex(property_length_name, true); return class_entry; } @@ -3223,9 +3209,9 @@ static zend_class_entry *register_class_Dom_Text(zend_class_entry *class_entry_D zval property_wholeText_default_value; ZVAL_UNDEF(&property_wholeText_default_value); - zend_string *property_wholeText_name = zend_string_init("wholeText", sizeof("wholeText") - 1, 1); + zend_string *property_wholeText_name = zend_string_init("wholeText", sizeof("wholeText") - 1, true); zend_declare_typed_property(class_entry, property_wholeText_name, &property_wholeText_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_wholeText_name); + zend_string_release_ex(property_wholeText_name, true); return class_entry; } @@ -3249,9 +3235,9 @@ static zend_class_entry *register_class_Dom_ProcessingInstruction(zend_class_ent zval property_target_default_value; ZVAL_UNDEF(&property_target_default_value); - zend_string *property_target_name = zend_string_init("target", sizeof("target") - 1, 1); + zend_string *property_target_name = zend_string_init("target", sizeof("target") - 1, true); zend_declare_typed_property(class_entry, property_target_name, &property_target_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_target_name); + zend_string_release_ex(property_target_name, true); return class_entry; } @@ -3280,35 +3266,35 @@ static zend_class_entry *register_class_Dom_DocumentType(zend_class_entry *class zval property_entities_default_value; ZVAL_UNDEF(&property_entities_default_value); - zend_string *property_entities_name = zend_string_init("entities", sizeof("entities") - 1, 1); + zend_string *property_entities_name = zend_string_init("entities", sizeof("entities") - 1, true); zend_string *property_entities_class_Dom_DtdNamedNodeMap = zend_string_init("Dom\\DtdNamedNodeMap", sizeof("Dom\\DtdNamedNodeMap")-1, 1); zend_declare_typed_property(class_entry, property_entities_name, &property_entities_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_entities_class_Dom_DtdNamedNodeMap, 0, 0)); - zend_string_release(property_entities_name); + zend_string_release_ex(property_entities_name, true); zval property_notations_default_value; ZVAL_UNDEF(&property_notations_default_value); - zend_string *property_notations_name = zend_string_init("notations", sizeof("notations") - 1, 1); + zend_string *property_notations_name = zend_string_init("notations", sizeof("notations") - 1, true); zend_string *property_notations_class_Dom_DtdNamedNodeMap = zend_string_init("Dom\\DtdNamedNodeMap", sizeof("Dom\\DtdNamedNodeMap")-1, 1); zend_declare_typed_property(class_entry, property_notations_name, &property_notations_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_notations_class_Dom_DtdNamedNodeMap, 0, 0)); - zend_string_release(property_notations_name); + zend_string_release_ex(property_notations_name, true); zval property_publicId_default_value; ZVAL_UNDEF(&property_publicId_default_value); - zend_string *property_publicId_name = zend_string_init("publicId", sizeof("publicId") - 1, 1); + zend_string *property_publicId_name = zend_string_init("publicId", sizeof("publicId") - 1, true); zend_declare_typed_property(class_entry, property_publicId_name, &property_publicId_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_publicId_name); + zend_string_release_ex(property_publicId_name, true); zval property_systemId_default_value; ZVAL_UNDEF(&property_systemId_default_value); - zend_string *property_systemId_name = zend_string_init("systemId", sizeof("systemId") - 1, 1); + zend_string *property_systemId_name = zend_string_init("systemId", sizeof("systemId") - 1, true); zend_declare_typed_property(class_entry, property_systemId_name, &property_systemId_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_systemId_name); + zend_string_release_ex(property_systemId_name, true); zval property_internalSubset_default_value; ZVAL_UNDEF(&property_internalSubset_default_value); - zend_string *property_internalSubset_name = zend_string_init("internalSubset", sizeof("internalSubset") - 1, 1); + zend_string *property_internalSubset_name = zend_string_init("internalSubset", sizeof("internalSubset") - 1, true); zend_declare_typed_property(class_entry, property_internalSubset_name, &property_internalSubset_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_internalSubset_name); + zend_string_release_ex(property_internalSubset_name, true); return class_entry; } @@ -3323,30 +3309,30 @@ static zend_class_entry *register_class_Dom_DocumentFragment(zend_class_entry *c 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_name = zend_string_init("children", sizeof("children") - 1, true); 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); + zend_string_release_ex(property_children_name, true); 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_name = zend_string_init("firstElementChild", sizeof("firstElementChild") - 1, true); 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); + zend_string_release_ex(property_firstElementChild_name, true); 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_name = zend_string_init("lastElementChild", sizeof("lastElementChild") - 1, true); 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); + zend_string_release_ex(property_lastElementChild_name, true); 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_string *property_childElementCount_name = zend_string_init("childElementCount", sizeof("childElementCount") - 1, true); 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); + zend_string_release_ex(property_childElementCount_name, true); return class_entry; } @@ -3360,21 +3346,21 @@ static zend_class_entry *register_class_Dom_Entity(zend_class_entry *class_entry zval property_publicId_default_value; ZVAL_UNDEF(&property_publicId_default_value); - zend_string *property_publicId_name = zend_string_init("publicId", sizeof("publicId") - 1, 1); + zend_string *property_publicId_name = zend_string_init("publicId", sizeof("publicId") - 1, true); zend_declare_typed_property(class_entry, property_publicId_name, &property_publicId_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_publicId_name); + zend_string_release_ex(property_publicId_name, true); zval property_systemId_default_value; ZVAL_UNDEF(&property_systemId_default_value); - zend_string *property_systemId_name = zend_string_init("systemId", sizeof("systemId") - 1, 1); + zend_string *property_systemId_name = zend_string_init("systemId", sizeof("systemId") - 1, true); zend_declare_typed_property(class_entry, property_systemId_name, &property_systemId_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_systemId_name); + zend_string_release_ex(property_systemId_name, true); zval property_notationName_default_value; ZVAL_UNDEF(&property_notationName_default_value); - zend_string *property_notationName_name = zend_string_init("notationName", sizeof("notationName") - 1, 1); + zend_string *property_notationName_name = zend_string_init("notationName", sizeof("notationName") - 1, true); zend_declare_typed_property(class_entry, property_notationName_name, &property_notationName_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_notationName_name); + zend_string_release_ex(property_notationName_name, true); return class_entry; } @@ -3398,15 +3384,15 @@ static zend_class_entry *register_class_Dom_Notation(zend_class_entry *class_ent zval property_publicId_default_value; ZVAL_UNDEF(&property_publicId_default_value); - zend_string *property_publicId_name = zend_string_init("publicId", sizeof("publicId") - 1, 1); + zend_string *property_publicId_name = zend_string_init("publicId", sizeof("publicId") - 1, true); zend_declare_typed_property(class_entry, property_publicId_name, &property_publicId_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_publicId_name); + zend_string_release_ex(property_publicId_name, true); zval property_systemId_default_value; ZVAL_UNDEF(&property_systemId_default_value); - zend_string *property_systemId_name = zend_string_init("systemId", sizeof("systemId") - 1, 1); + zend_string *property_systemId_name = zend_string_init("systemId", sizeof("systemId") - 1, true); zend_declare_typed_property(class_entry, property_systemId_name, &property_systemId_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_systemId_name); + zend_string_release_ex(property_systemId_name, true); return class_entry; } @@ -3421,101 +3407,101 @@ static zend_class_entry *register_class_Dom_Document(zend_class_entry *class_ent 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_name = zend_string_init("children", sizeof("children") - 1, true); 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); + zend_string_release_ex(property_children_name, true); 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_name = zend_string_init("firstElementChild", sizeof("firstElementChild") - 1, true); 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); + zend_string_release_ex(property_firstElementChild_name, true); 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_name = zend_string_init("lastElementChild", sizeof("lastElementChild") - 1, true); 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); + zend_string_release_ex(property_lastElementChild_name, true); 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_string *property_childElementCount_name = zend_string_init("childElementCount", sizeof("childElementCount") - 1, true); 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); + zend_string_release_ex(property_childElementCount_name, true); zval property_implementation_default_value; ZVAL_UNDEF(&property_implementation_default_value); - zend_string *property_implementation_name = zend_string_init("implementation", sizeof("implementation") - 1, 1); + zend_string *property_implementation_name = zend_string_init("implementation", sizeof("implementation") - 1, true); zend_string *property_implementation_class_Dom_Implementation = zend_string_init("Dom\\Implementation", sizeof("Dom\\Implementation")-1, 1); zend_declare_typed_property(class_entry, property_implementation_name, &property_implementation_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_implementation_class_Dom_Implementation, 0, 0)); - zend_string_release(property_implementation_name); + zend_string_release_ex(property_implementation_name, true); zval property_URL_default_value; ZVAL_UNDEF(&property_URL_default_value); - zend_string *property_URL_name = zend_string_init("URL", sizeof("URL") - 1, 1); + zend_string *property_URL_name = zend_string_init("URL", sizeof("URL") - 1, true); zend_declare_typed_property(class_entry, property_URL_name, &property_URL_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_URL_name); + zend_string_release_ex(property_URL_name, true); zval property_documentURI_default_value; ZVAL_UNDEF(&property_documentURI_default_value); - zend_string *property_documentURI_name = zend_string_init("documentURI", sizeof("documentURI") - 1, 1); + zend_string *property_documentURI_name = zend_string_init("documentURI", sizeof("documentURI") - 1, true); zend_declare_typed_property(class_entry, property_documentURI_name, &property_documentURI_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_documentURI_name); + zend_string_release_ex(property_documentURI_name, true); zval property_characterSet_default_value; ZVAL_UNDEF(&property_characterSet_default_value); - zend_string *property_characterSet_name = zend_string_init("characterSet", sizeof("characterSet") - 1, 1); + zend_string *property_characterSet_name = zend_string_init("characterSet", sizeof("characterSet") - 1, true); zend_declare_typed_property(class_entry, property_characterSet_name, &property_characterSet_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_characterSet_name); + zend_string_release_ex(property_characterSet_name, true); zval property_charset_default_value; ZVAL_UNDEF(&property_charset_default_value); - zend_string *property_charset_name = zend_string_init("charset", sizeof("charset") - 1, 1); + zend_string *property_charset_name = zend_string_init("charset", sizeof("charset") - 1, true); zend_declare_typed_property(class_entry, property_charset_name, &property_charset_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_charset_name); + zend_string_release_ex(property_charset_name, true); zval property_inputEncoding_default_value; ZVAL_UNDEF(&property_inputEncoding_default_value); - zend_string *property_inputEncoding_name = zend_string_init("inputEncoding", sizeof("inputEncoding") - 1, 1); + zend_string *property_inputEncoding_name = zend_string_init("inputEncoding", sizeof("inputEncoding") - 1, true); zend_declare_typed_property(class_entry, property_inputEncoding_name, &property_inputEncoding_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_inputEncoding_name); + zend_string_release_ex(property_inputEncoding_name, true); zval property_doctype_default_value; ZVAL_UNDEF(&property_doctype_default_value); - zend_string *property_doctype_name = zend_string_init("doctype", sizeof("doctype") - 1, 1); + zend_string *property_doctype_name = zend_string_init("doctype", sizeof("doctype") - 1, true); zend_string *property_doctype_class_Dom_DocumentType = zend_string_init("Dom\\DocumentType", sizeof("Dom\\DocumentType")-1, 1); zend_declare_typed_property(class_entry, property_doctype_name, &property_doctype_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_doctype_class_Dom_DocumentType, 0, MAY_BE_NULL)); - zend_string_release(property_doctype_name); + zend_string_release_ex(property_doctype_name, true); zval property_documentElement_default_value; ZVAL_UNDEF(&property_documentElement_default_value); - zend_string *property_documentElement_name = zend_string_init("documentElement", sizeof("documentElement") - 1, 1); + zend_string *property_documentElement_name = zend_string_init("documentElement", sizeof("documentElement") - 1, true); zend_string *property_documentElement_class_Dom_Element = zend_string_init("Dom\\Element", sizeof("Dom\\Element")-1, 1); 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); + zend_string_release_ex(property_documentElement_name, true); zval property_body_default_value; ZVAL_UNDEF(&property_body_default_value); - zend_string *property_body_name = zend_string_init("body", sizeof("body") - 1, 1); + zend_string *property_body_name = zend_string_init("body", sizeof("body") - 1, true); zend_string *property_body_class_Dom_HTMLElement = zend_string_init("Dom\\HTMLElement", sizeof("Dom\\HTMLElement")-1, 1); zend_declare_typed_property(class_entry, property_body_name, &property_body_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_body_class_Dom_HTMLElement, 0, MAY_BE_NULL)); - zend_string_release(property_body_name); + zend_string_release_ex(property_body_name, true); zval property_head_default_value; ZVAL_UNDEF(&property_head_default_value); - zend_string *property_head_name = zend_string_init("head", sizeof("head") - 1, 1); + zend_string *property_head_name = zend_string_init("head", sizeof("head") - 1, true); zend_string *property_head_class_Dom_HTMLElement = zend_string_init("Dom\\HTMLElement", sizeof("Dom\\HTMLElement")-1, 1); zend_declare_typed_property(class_entry, property_head_name, &property_head_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_head_class_Dom_HTMLElement, 0, MAY_BE_NULL)); - zend_string_release(property_head_name); + zend_string_release_ex(property_head_name, true); zval property_title_default_value; ZVAL_UNDEF(&property_title_default_value); - zend_string *property_title_name = zend_string_init("title", sizeof("title") - 1, 1); + zend_string *property_title_name = zend_string_init("title", sizeof("title") - 1, true); zend_declare_typed_property(class_entry, property_title_name, &property_title_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_title_name); + zend_string_release_ex(property_title_name, true); return class_entry; } @@ -3539,27 +3525,27 @@ static zend_class_entry *register_class_Dom_XMLDocument(zend_class_entry *class_ zval property_xmlEncoding_default_value; ZVAL_UNDEF(&property_xmlEncoding_default_value); - zend_string *property_xmlEncoding_name = zend_string_init("xmlEncoding", sizeof("xmlEncoding") - 1, 1); + zend_string *property_xmlEncoding_name = zend_string_init("xmlEncoding", sizeof("xmlEncoding") - 1, true); zend_declare_typed_property(class_entry, property_xmlEncoding_name, &property_xmlEncoding_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_xmlEncoding_name); + zend_string_release_ex(property_xmlEncoding_name, true); zval property_xmlStandalone_default_value; ZVAL_UNDEF(&property_xmlStandalone_default_value); - zend_string *property_xmlStandalone_name = zend_string_init("xmlStandalone", sizeof("xmlStandalone") - 1, 1); + zend_string *property_xmlStandalone_name = zend_string_init("xmlStandalone", sizeof("xmlStandalone") - 1, true); zend_declare_typed_property(class_entry, property_xmlStandalone_name, &property_xmlStandalone_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_xmlStandalone_name); + zend_string_release_ex(property_xmlStandalone_name, true); zval property_xmlVersion_default_value; ZVAL_UNDEF(&property_xmlVersion_default_value); - zend_string *property_xmlVersion_name = zend_string_init("xmlVersion", sizeof("xmlVersion") - 1, 1); + zend_string *property_xmlVersion_name = zend_string_init("xmlVersion", sizeof("xmlVersion") - 1, true); zend_declare_typed_property(class_entry, property_xmlVersion_name, &property_xmlVersion_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_xmlVersion_name); + zend_string_release_ex(property_xmlVersion_name, true); zval property_formatOutput_default_value; ZVAL_UNDEF(&property_formatOutput_default_value); - zend_string *property_formatOutput_name = zend_string_init("formatOutput", sizeof("formatOutput") - 1, 1); + zend_string *property_formatOutput_name = zend_string_init("formatOutput", sizeof("formatOutput") - 1, true); zend_declare_typed_property(class_entry, property_formatOutput_name, &property_formatOutput_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_formatOutput_name); + zend_string_release_ex(property_formatOutput_name, true); return class_entry; } @@ -3574,9 +3560,9 @@ static zend_class_entry *register_class_Dom_TokenList(zend_class_entry *class_en zval property_length_default_value; ZVAL_UNDEF(&property_length_default_value); - zend_string *property_length_name = zend_string_init("length", sizeof("length") - 1, 1); + zend_string *property_length_name = zend_string_init("length", sizeof("length") - 1, true); zend_declare_typed_property(class_entry, property_length_name, &property_length_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_length_name); + zend_string_release_ex(property_length_name, true); zval property_value_default_value; ZVAL_UNDEF(&property_value_default_value); @@ -3594,22 +3580,22 @@ static zend_class_entry *register_class_Dom_NamespaceInfo(void) zval property_prefix_default_value; ZVAL_UNDEF(&property_prefix_default_value); - zend_string *property_prefix_name = zend_string_init("prefix", sizeof("prefix") - 1, 1); + zend_string *property_prefix_name = zend_string_init("prefix", sizeof("prefix") - 1, true); zend_declare_typed_property(class_entry, property_prefix_name, &property_prefix_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_prefix_name); + zend_string_release_ex(property_prefix_name, true); zval property_namespaceURI_default_value; ZVAL_UNDEF(&property_namespaceURI_default_value); - zend_string *property_namespaceURI_name = zend_string_init("namespaceURI", sizeof("namespaceURI") - 1, 1); + zend_string *property_namespaceURI_name = zend_string_init("namespaceURI", sizeof("namespaceURI") - 1, true); zend_declare_typed_property(class_entry, property_namespaceURI_name, &property_namespaceURI_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_namespaceURI_name); + zend_string_release_ex(property_namespaceURI_name, true); zval property_element_default_value; ZVAL_UNDEF(&property_element_default_value); - zend_string *property_element_name = zend_string_init("element", sizeof("element") - 1, 1); + zend_string *property_element_name = zend_string_init("element", sizeof("element") - 1, true); zend_string *property_element_class_Dom_Element = zend_string_init("Dom\\Element", sizeof("Dom\\Element")-1, 1); zend_declare_typed_property(class_entry, property_element_name, &property_element_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_element_class_Dom_Element, 0, 0)); - zend_string_release(property_element_name); + zend_string_release_ex(property_element_name, true); return class_entry; } @@ -3624,16 +3610,16 @@ static zend_class_entry *register_class_Dom_XPath(void) zval property_document_default_value; ZVAL_UNDEF(&property_document_default_value); - zend_string *property_document_name = zend_string_init("document", sizeof("document") - 1, 1); + zend_string *property_document_name = zend_string_init("document", sizeof("document") - 1, true); zend_string *property_document_class_Dom_Document = zend_string_init("Dom\\Document", sizeof("Dom\\Document")-1, 1); zend_declare_typed_property(class_entry, property_document_name, &property_document_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_document_class_Dom_Document, 0, 0)); - zend_string_release(property_document_name); + zend_string_release_ex(property_document_name, true); zval property_registerNodeNamespaces_default_value; ZVAL_UNDEF(&property_registerNodeNamespaces_default_value); - zend_string *property_registerNodeNamespaces_name = zend_string_init("registerNodeNamespaces", sizeof("registerNodeNamespaces") - 1, 1); + zend_string *property_registerNodeNamespaces_name = zend_string_init("registerNodeNamespaces", sizeof("registerNodeNamespaces") - 1, true); zend_declare_typed_property(class_entry, property_registerNodeNamespaces_name, &property_registerNodeNamespaces_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_registerNodeNamespaces_name); + zend_string_release_ex(property_registerNodeNamespaces_name, true); return class_entry; } diff --git a/ext/dom/tests/DOMXPath_callables_errors.phpt b/ext/dom/tests/DOMXPath_callables_errors.phpt index d11437398b158..10019474e7e7f 100644 --- a/ext/dom/tests/DOMXPath_callables_errors.phpt +++ b/ext/dom/tests/DOMXPath_callables_errors.phpt @@ -57,6 +57,19 @@ try { echo $e->getMessage(), "\n"; } +$x = new class { + public static function dump() {} +}; + +$classes = get_declared_classes(); + +try { + $str = str_repeat($classes[count($classes) - 1] . '::dump', random_int(1, 1)); + $xpath->registerPhpFunctions([$str]); +} catch (Throwable $e) { + echo $e->getMessage(), "\n"; +} + ?> --EXPECT-- DOMXPath::registerPhpFunctions(): Argument #1 ($restrict) must be a callable, function "nonexistent" not found or invalid function name @@ -67,3 +80,4 @@ DOMXPath::registerPhpFunctions(): Argument #1 ($restrict) must be an array with DOMXPath::registerPhpFunctions(): Argument #1 ($restrict) must be an array containing valid callback names DOMXPath::registerPhpFunctions(): Argument #1 ($restrict) must be an array containing valid callback names DOMXPath::registerPhpFunctions(): Argument #1 ($restrict) must be a valid callback name +DOMXPath::registerPhpFunctions(): Argument #1 ($restrict) must be an array containing valid callback names diff --git a/ext/dom/tests/gh16317.phpt b/ext/dom/tests/gh16317.phpt new file mode 100644 index 0000000000000..870c337716f01 --- /dev/null +++ b/ext/dom/tests/gh16317.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-16317 (DOM classes do not allow __debugInfo() overrides to work) +--FILE-- + 'y']; + } +} + +var_dump(new Demo()); + +?> +--EXPECT-- +object(Demo)#1 (1) { + ["x"]=> + string(1) "y" +} 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/gh20722.phpt b/ext/dom/tests/gh20722.phpt new file mode 100644 index 0000000000000..38d3314618f3e --- /dev/null +++ b/ext/dom/tests/gh20722.phpt @@ -0,0 +1,13 @@ +--TEST-- +GH-20722 (Null pointer dereference in DOM namespace node cloning via clone on malformed objects) +--EXTENSIONS-- +dom +--FILE-- + +--EXPECT-- +Done 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/css_selectors/gh20395.phpt b/ext/dom/tests/modern/css_selectors/gh20395.phpt new file mode 100644 index 0000000000000..af04cb1c27a42 --- /dev/null +++ b/ext/dom/tests/modern/css_selectors/gh20395.phpt @@ -0,0 +1,33 @@ +--TEST-- +GH-20395 (\Dom\ParentNode::querySelector and \Dom\ParentNode::querySelectorAll requires elements in $selectors to be lowercase) +--EXTENSIONS-- +dom +--CREDITS-- +DeveloperRob +--FILE-- +'; +$dom = Dom\HtmlDocument::createFromString($html); +var_dump(is_null($dom->querySelector('html'))); +var_dump(is_null($dom->querySelector('Html'))); +var_dump(is_null($dom->querySelector('HTML'))); + +$dom->body->appendChild($dom->createElement('div')); +$dom->body->appendChild($dom->createElementNS('http://www.w3.org/1999/xhtml', 'Div')); + +foreach ($dom->querySelectorAll('div') as $div) { + var_dump($div->localName); +} + +foreach ($dom->querySelectorAll('Div') as $div) { + var_dump($div->localName); +} + +?> +--EXPECT-- +bool(false) +bool(false) +bool(false) +string(3) "div" +string(3) "div" diff --git a/ext/dom/tests/modern/css_selectors/pseudo_classes_links.phpt b/ext/dom/tests/modern/css_selectors/pseudo_classes_links.phpt index 8a688286b6806..7afcb6e3cfbde 100644 --- a/ext/dom/tests/modern/css_selectors/pseudo_classes_links.phpt +++ b/ext/dom/tests/modern/css_selectors/pseudo_classes_links.phpt @@ -11,6 +11,7 @@ $dom = DOM\XMLDocument::createFromString(<< Link Link + Not actually a link Link XML); @@ -18,6 +19,7 @@ XML); test_helper($dom, ':any-link'); test_helper($dom, ':link'); test_helper($dom, 'a:not(:any-link)'); +test_helper($dom, ':not(:any-link)'); ?> --EXPECT-- @@ -29,3 +31,12 @@ test_helper($dom, 'a:not(:any-link)'); Link --- Selector: a:not(:any-link) --- Link +--- Selector: :not(:any-link) --- + + Link + Link + Not actually a link + Link + +Link +Not actually a link diff --git a/ext/dom/tests/modern/html/interactions/gh20281.phpt b/ext/dom/tests/modern/html/interactions/gh20281.phpt new file mode 100644 index 0000000000000..324c5a2756331 --- /dev/null +++ b/ext/dom/tests/modern/html/interactions/gh20281.phpt @@ -0,0 +1,15 @@ +--TEST-- +GH-20281 (\Dom\Document::getElementById() is inconsistent after nodes are removed) +--EXTENSIONS-- +dom +--CREDITS-- +cscott +--FILE-- +b

c

', LIBXML_NOERROR); +$p = $d->getElementById('a'); +$p->remove(); +echo $d->getElementById('a')->textContent, "\n"; +?> +--EXPECT-- +c diff --git a/ext/dom/tests/modern/xml/attribute_getNamedItemNS_incorrect_ns_check.phpt b/ext/dom/tests/modern/xml/attribute_getNamedItemNS_incorrect_ns_check.phpt new file mode 100644 index 0000000000000..dc8c1f87c14c8 --- /dev/null +++ b/ext/dom/tests/modern/xml/attribute_getNamedItemNS_incorrect_ns_check.phpt @@ -0,0 +1,26 @@ +--TEST-- +getNamedItemNS() incorrect namespace check +--EXTENSIONS-- +dom +--CREDITS-- +veewee +--FILE-- + + + +EOXML +); +$documentElement = $xml->documentElement; +$attributes = $documentElement->attributes; +$schemaLocation = $attributes->getNamedItemNS('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation'); +var_dump($schemaLocation->textContent); + +?> +--EXPECT-- +string(116) "http://www.happy-helpers1.com note-namespace1.xsd http://www.happy-helpers2.com http://localhost/note-namespace2.xsd" diff --git a/ext/dom/tests/registerPhpFunctionNS.phpt b/ext/dom/tests/registerPhpFunctionNS.phpt index 4c4fb157000bf..2ee98168251fd 100644 --- a/ext/dom/tests/registerPhpFunctionNS.phpt +++ b/ext/dom/tests/registerPhpFunctionNS.phpt @@ -62,14 +62,14 @@ $xpath->registerPhpFunctionNS('urn:bar', 'test', 'strtolower'); var_dump($xpath->query('//a[bar:test(string(@href)) = "https://php.net/"]')); ?> ---EXPECT-- +--EXPECTF-- --- Legit cases: global function callable --- object(DOMNodeList)#5 (1) { ["length"]=> int(1) } --- Legit cases: string callable --- -object(DOMNodeList)#5 (1) { +object(DOMNodeList)#%d (1) { ["length"]=> int(1) } @@ -79,12 +79,12 @@ array(1) { [0]=> string(15) "https://php.net/" } -object(DOMNodeList)#3 (1) { +object(DOMNodeList)#%d (1) { ["length"]=> int(0) } --- Legit cases: instance class method callable --- -object(DOMNodeList)#6 (1) { +object(DOMNodeList)#%d (1) { ["length"]=> int(1) } @@ -100,7 +100,7 @@ array(1) { --- Legit cases: global function callable that returns nothing --- string(15) "https://php.net/" --- Legit cases: multiple namespaces --- -object(DOMNodeList)#5 (1) { +object(DOMNodeList)#%d (1) { ["length"]=> int(1) } diff --git a/ext/dom/text.c b/ext/dom/text.c index ca8fcf63d3aca..4c503201c8bfe 100644 --- a/ext/dom/text.c +++ b/ext/dom/text.c @@ -96,7 +96,6 @@ Modern spec URL: https://dom.spec.whatwg.org/#dom-text-splittext */ PHP_METHOD(DOMText, splitText) { - zval *id; xmlChar *first; xmlChar *second; xmlNodePtr node; @@ -105,11 +104,10 @@ PHP_METHOD(DOMText, splitText) int length; dom_object *intern; - id = ZEND_THIS; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &offset) == FAILURE) { RETURN_THROWS(); } - DOM_GET_OBJ(node, id, xmlNodePtr, intern); + DOM_GET_OBJ(node, ZEND_THIS, xmlNodePtr, intern); if (offset < 0) { zend_argument_value_error(1, "must be greater than or equal to 0"); @@ -129,17 +127,18 @@ PHP_METHOD(DOMText, splitText) first = xmlUTF8Strndup(cur, (int)offset); second = xmlUTF8Strsub(cur, (int)offset, (int)(length - offset)); - xmlNodeSetContent(node, first); - nnode = xmlNewDocText(node->doc, second); - - xmlFree(first); - xmlFree(second); + xmlNodeSetContent(node, NULL); + node->content = first; + nnode = xmlNewDocText(node->doc, NULL); if (nnode == NULL) { + xmlFree(second); php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true); RETURN_THROWS(); } + nnode->content = second; + if (node->parent != NULL) { nnode->type = XML_ELEMENT_NODE; xmlAddNextSibling(node, nnode); @@ -155,21 +154,11 @@ Since: DOM Level 3 */ PHP_METHOD(DOMText, isWhitespaceInElementContent) { - zval *id; xmlNodePtr node; dom_object *intern; - - id = ZEND_THIS; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } - DOM_GET_OBJ(node, id, xmlNodePtr, intern); - - if (xmlIsBlankNode(node)) { - RETURN_TRUE; - } else { - RETURN_FALSE; - } + ZEND_PARSE_PARAMETERS_NONE(); + DOM_GET_OBJ(node, ZEND_THIS, xmlNodePtr, intern); + RETURN_BOOL(xmlIsBlankNode(node)); } /* }}} end dom_text_is_whitespace_in_element_content */ diff --git a/ext/dom/xml_serializer.c b/ext/dom/xml_serializer.c index a4b46082b0ee5..7684057a391c0 100644 --- a/ext/dom/xml_serializer.c +++ b/ext/dom/xml_serializer.c @@ -1097,7 +1097,10 @@ static int dom_xml_serialize_element_node( /* 14. If ns is the HTML namespace, and the node's list of children is empty, and the node's localName matches * any one of the following void elements: ... */ if (element->children == NULL) { - if (xmlSaveNoEmptyTags) { + ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations") + int saveNoEmptyTags = xmlSaveNoEmptyTags; + ZEND_DIAGNOSTIC_IGNORED_END + if (saveNoEmptyTags) { /* Do nothing, use the closing style. */ } else if (php_dom_ns_is_fast(element, php_dom_ns_is_html_magic_token)) { size_t name_length = strlen((const char *) element->name); diff --git a/ext/dom/xpath_callbacks.c b/ext/dom/xpath_callbacks.c index c4715fa67e80a..0974db475b3a9 100644 --- a/ext/dom/xpath_callbacks.c +++ b/ext/dom/xpath_callbacks.c @@ -215,6 +215,7 @@ static zend_result php_dom_xpath_callback_ns_update_method_handler( } zend_tmp_string_release(tmp_str); } else { + zend_tmp_string_release(tmp_str); zend_fcc_dtor(fcc); efree(fcc); return FAILURE; diff --git a/ext/enchant/enchant.c b/ext/enchant/enchant.c index eedb49b69e8f9..534908f9d1cc5 100644 --- a/ext/enchant/enchant.c +++ b/ext/enchant/enchant.c @@ -671,17 +671,18 @@ PHP_FUNCTION(enchant_dict_suggest) } PHP_ENCHANT_GET_DICT; - array_init(return_value); suggs = enchant_dict_suggest(pdict->pdict, word, wordlen, &n_sugg); if (suggs && n_sugg) { - size_t i; + array_init_size(return_value, n_sugg); - for (i = 0; i < n_sugg; i++) { + for (size_t i = 0; i < n_sugg; i++) { add_next_index_string(return_value, suggs[i]); } enchant_dict_free_string_list(pdict->pdict, suggs); + } else { + RETURN_EMPTY_ARRAY(); } } /* }}} */ diff --git a/ext/enchant/enchant_arginfo.h b/ext/enchant/enchant_arginfo.h index 07dba8b532869..01681072346a0 100644 --- a/ext/enchant/enchant_arginfo.h +++ b/ext/enchant/enchant_arginfo.h @@ -166,10 +166,8 @@ static void register_enchant_symbols(int module_number) 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_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); @@ -183,46 +181,35 @@ static void register_enchant_symbols(int module_number) 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_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_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_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); - zval attribute_Deprecated_const_ENCHANT_MYSPELL_0_arg1; 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_arg1, attribute_Deprecated_const_ENCHANT_MYSPELL_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_ENCHANT_MYSPELL_0->args[1].value, &attribute_Deprecated_const_ENCHANT_MYSPELL_0_arg1); + 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 attribute_Deprecated_const_ENCHANT_ISPELL_0_arg1; - zend_string *attribute_Deprecated_const_ENCHANT_ISPELL_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_ISPELL_0_arg1, attribute_Deprecated_const_ENCHANT_ISPELL_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_ENCHANT_ISPELL_0->args[1].value, &attribute_Deprecated_const_ENCHANT_ISPELL_0_arg1); + 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); } diff --git a/ext/exif/exif.c b/ext/exif/exif.c index 9169861728869..17dadc7539baf 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 @@ -2092,7 +2104,7 @@ static inline char *exif_offset_info_try_get( static inline bool exif_offset_info_contains( const exif_offset_info *info, const char *start, size_t length) { if (ptr_offset_overflows(start, length)) { - return 0; + return false; } /* start and valid_start are both inclusive, end and valid_end are both exclusive, @@ -3249,6 +3261,7 @@ static bool exif_process_IFD_in_MAKERNOTE(image_info_type *ImageInfo, char * val #define REQUIRE_NON_EMPTY() do { \ if (byte_count == 0) { \ + EFREE_IF(outside); \ exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "Process tag(x%04X=%s): Cannot be empty", tag, exif_get_tagname_debug(tag, tag_table)); \ return false; \ } \ @@ -4279,11 +4292,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 >= 2) && + (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 +4513,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/heic_iloc_underflow.phpt b/ext/exif/tests/heic_iloc_underflow.phpt new file mode 100644 index 0000000000000..9dd1878b60dd7 --- /dev/null +++ b/ext/exif/tests/heic_iloc_underflow.phpt @@ -0,0 +1,19 @@ +--TEST-- +HEIC iloc extent_length underflow +--EXTENSIONS-- +exif +--FILE-- + +--CLEAN-- + +--EXPECTF-- +Warning: exif_read_data(heic_iloc_underflow.heic): 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/ext_skel.php b/ext/ext_skel.php index cd82abb34697a..d396dfa3da749 100755 --- a/ext/ext_skel.php +++ b/ext/ext_skel.php @@ -42,7 +42,7 @@ function print_help() { Very simple. First, change to the ext/ directory of the PHP sources. Then run the following - php ext_skel.php --ext extension_name + php ext_skel.php --ext extension_name --vendor vendor_name and everything you need will be placed in directory ext/extension_name. @@ -90,11 +90,12 @@ functions strictly needed by others. Exposed internal function must be named OPTIONS - php ext_skel.php --ext [--experimental] [--author ] - [--dir ] [--std] [--onlyunix] - [--onlywindows] [--help] + php ext_skel.php --ext --vendor [--experimental] + [--author ] [--dir ] [--std] + [--onlyunix] [--onlywindows] [--help] --ext The name of the extension defined as + --vendor The vendor of the extension for Packagist --experimental Passed if this extension is experimental, this creates the EXPERIMENTAL file in the root of the extension --author Your name, this is used if --std is passed and for the @@ -147,6 +148,7 @@ function process_args($argv, $argc) { 'unix' => true, 'windows' => true, 'ext' => '', + 'vendor' => '', 'dir' => __DIR__ . DIRECTORY_SEPARATOR, 'skel' => __DIR__ . DIRECTORY_SEPARATOR . 'skeleton' . DIRECTORY_SEPARATOR, 'author' => false, @@ -185,6 +187,7 @@ function process_args($argv, $argc) { } break; case 'ext': + case 'vendor': case 'dir': case 'author': { if (!isset($argv[$i + 1]) || ($argv[$i + 1][0] == '-' && $argv[$i + 1][1] == '-')) { @@ -204,6 +207,8 @@ function process_args($argv, $argc) { if (empty($options['ext'])) { error('No extension name passed, use "--ext "'); + } else if (empty($options['vendor'])) { + error('No vendor name passed, use "--vendor "'); } else if (!$options['unix'] && !$options['windows']) { error('Cannot pass both --onlyunix and --onlywindows'); } else if (!is_dir($options['skel'])) { @@ -217,6 +222,12 @@ function process_args($argv, $argc) { .' Using only lower case letters is preferred.'); } + // Validate vendor + if (!preg_match('/^[a-z][a-z0-9_-]+$/i', $options['vendor'])) { + error('Invalid vendor name. Valid names start with a letter,' + .' followed by any number of letters, numbers, hypens, or underscores.'); + } + $options['ext'] = str_replace(['\\', '/'], '', strtolower($options['ext'])); return $options; @@ -231,6 +242,7 @@ function process_source_tags($file, $short_name) { error('Unable to open file for reading: ' . $short_name); } + $source = str_replace('%VENDORNAME%', $options['vendor'], $source); $source = str_replace('%EXTNAME%', $options['ext'], $source); $source = str_replace('%EXTNAMECAPS%', strtoupper($options['ext']), $source); @@ -290,6 +302,7 @@ function copy_config_scripts() { } $files[] = '.gitignore'; + $files[] = 'composer.json'; foreach($files as $config_script) { $new_config_script = $options['dir'] . $options['ext'] . DIRECTORY_SEPARATOR . $config_script; diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 10fc11f52e70f..d5b8eb59f0c90 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -957,7 +957,8 @@ static void zend_ffi_callback_trampoline(ffi_cif* cif, void* ret, void** args, v ZEND_HASH_PACKED_FOREACH_PTR(callback_data->type->func.args, arg_type) { arg_type = ZEND_FFI_TYPE(arg_type); - zend_ffi_cdata_to_zval(NULL, args[n], arg_type, BP_VAR_R, &fci.params[n], (zend_ffi_flags)(arg_type->attr & ZEND_FFI_ATTR_CONST), 0, 0); + zend_ffi_cdata_to_zval(NULL, args[n], arg_type, BP_VAR_R, &fci.params[n], (zend_ffi_flags)(arg_type->attr & ZEND_FFI_ATTR_CONST), + false, false); n++; } ZEND_HASH_FOREACH_END(); } @@ -1133,7 +1134,7 @@ static zval *zend_ffi_cdata_get(zend_object *obj, zend_string *member, int read_ return &EG(uninitialized_zval); } - zend_ffi_cdata_to_zval(cdata, cdata->ptr, type, BP_VAR_R, rv, 0, 0, 0); + zend_ffi_cdata_to_zval(cdata, cdata->ptr, type, BP_VAR_R, rv, 0, false, false); return rv; } /* }}} */ @@ -1302,7 +1303,8 @@ static zval *zend_ffi_cdata_read_field(zend_object *obj, zend_string *field_name } } ptr = (void*)(((char*)ptr) + field->offset); - zend_ffi_cdata_to_zval(NULL, ptr, field_type, read_type, rv, (cdata->flags & ZEND_FFI_FLAG_CONST) | (zend_ffi_flags)field->is_const, 0, 0); + zend_ffi_cdata_to_zval(NULL, ptr, field_type, read_type, rv, (cdata->flags & ZEND_FFI_FLAG_CONST) | (zend_ffi_flags)field->is_const, + false, false); } else { zend_ffi_bit_field_to_zval(ptr, field, rv); } @@ -1438,7 +1440,7 @@ static zval *zend_ffi_cdata_read_dim(zend_object *obj, zval *offset, int read_ty return &EG(uninitialized_zval); } - zend_ffi_cdata_to_zval(NULL, ptr, dim_type, read_type, rv, is_const, 0, 0); + zend_ffi_cdata_to_zval(NULL, ptr, dim_type, read_type, rv, is_const, false, false); return rv; } /* }}} */ @@ -1527,7 +1529,7 @@ static bool zend_ffi_ctype_name_append(zend_ffi_ctype_name_buf *buf, const char static bool zend_ffi_ctype_name(zend_ffi_ctype_name_buf *buf, const zend_ffi_type *type) /* {{{ */ { const char *name = NULL; - bool is_ptr = 0; + bool is_ptr = false; while (1) { switch (type->kind) { @@ -1587,12 +1589,12 @@ static bool zend_ffi_ctype_name(zend_ffi_ctype_name_buf *buf, const zend_ffi_typ if (!zend_ffi_ctype_name_prepend(buf, "*", 1)) { return 0; } - is_ptr = 1; + is_ptr = true; type = ZEND_FFI_TYPE(type->pointer.type); break; case ZEND_FFI_TYPE_FUNC: if (is_ptr) { - is_ptr = 0; + is_ptr = false; if (!zend_ffi_ctype_name_prepend(buf, "(", 1) || !zend_ffi_ctype_name_append(buf, ")", 1)) { return 0; @@ -1606,7 +1608,7 @@ static bool zend_ffi_ctype_name(zend_ffi_ctype_name_buf *buf, const zend_ffi_typ break; case ZEND_FFI_TYPE_ARRAY: if (is_ptr) { - is_ptr = 0; + is_ptr = false; if (!zend_ffi_ctype_name_prepend(buf, "(", 1) || !zend_ffi_ctype_name_append(buf, ")", 1)) { return 0; @@ -1984,7 +1986,8 @@ static zval *zend_ffi_cdata_it_get_current_data(zend_object_iterator *it) /* {{{ ptr = (void*)((char*)cdata->ptr + dim_type->size * iter->it.index); zval_ptr_dtor(&iter->value); - zend_ffi_cdata_to_zval(NULL, ptr, dim_type, iter->by_ref ? BP_VAR_RW : BP_VAR_R, &iter->value, (cdata->flags & ZEND_FFI_FLAG_CONST) | (zend_ffi_flags)(type->attr & ZEND_FFI_ATTR_CONST), 0, 0); + zend_ffi_cdata_to_zval(NULL, ptr, dim_type, iter->by_ref ? BP_VAR_RW : BP_VAR_R, &iter->value, (cdata->flags & ZEND_FFI_FLAG_CONST) | (zend_ffi_flags)(type->attr & ZEND_FFI_ATTR_CONST), + false, false); return &iter->value; } /* }}} */ @@ -2082,7 +2085,7 @@ static HashTable *zend_ffi_cdata_get_debug_info(zend_object *obj, int *is_temp) case ZEND_FFI_TYPE_SINT32: case ZEND_FFI_TYPE_UINT64: case ZEND_FFI_TYPE_SINT64: - zend_ffi_cdata_to_zval(cdata, ptr, type, BP_VAR_R, &tmp, ZEND_FFI_FLAG_CONST, 0, 0); + zend_ffi_cdata_to_zval(cdata, ptr, type, BP_VAR_R, &tmp, ZEND_FFI_FLAG_CONST, false, false); ht = zend_new_array(1); zend_hash_str_add(ht, "cdata", sizeof("cdata")-1, &tmp); *is_temp = 1; @@ -2102,7 +2105,8 @@ static HashTable *zend_ffi_cdata_get_debug_info(zend_object *obj, int *is_temp) *is_temp = 1; return ht; } else { - zend_ffi_cdata_to_zval(NULL, *(void**)ptr, ZEND_FFI_TYPE(type->pointer.type), BP_VAR_R, &tmp, ZEND_FFI_FLAG_CONST, 0, 0); + zend_ffi_cdata_to_zval(NULL, *(void**)ptr, ZEND_FFI_TYPE(type->pointer.type), BP_VAR_R, &tmp, ZEND_FFI_FLAG_CONST, + false, false); ht = zend_new_array(1); zend_hash_index_add_new(ht, 0, &tmp); *is_temp = 1; @@ -2115,7 +2119,8 @@ static HashTable *zend_ffi_cdata_get_debug_info(zend_object *obj, int *is_temp) if (key) { if (!f->bits) { void *f_ptr = (void*)(((char*)ptr) + f->offset); - zend_ffi_cdata_to_zval(NULL, f_ptr, ZEND_FFI_TYPE(f->type), BP_VAR_R, &tmp, ZEND_FFI_FLAG_CONST, 0, type->attr & ZEND_FFI_ATTR_UNION); + zend_ffi_cdata_to_zval(NULL, f_ptr, ZEND_FFI_TYPE(f->type), BP_VAR_R, &tmp, ZEND_FFI_FLAG_CONST, + false, type->attr & ZEND_FFI_ATTR_UNION); zend_hash_add(ht, key, &tmp); } else { zend_ffi_bit_field_to_zval(ptr, f, &tmp); @@ -2128,7 +2133,8 @@ static HashTable *zend_ffi_cdata_get_debug_info(zend_object *obj, int *is_temp) case ZEND_FFI_TYPE_ARRAY: ht = zend_new_array(type->array.length); for (n = 0; n < type->array.length; n++) { - zend_ffi_cdata_to_zval(NULL, ptr, ZEND_FFI_TYPE(type->array.type), BP_VAR_R, &tmp, ZEND_FFI_FLAG_CONST, 0, 0); + zend_ffi_cdata_to_zval(NULL, ptr, ZEND_FFI_TYPE(type->array.type), BP_VAR_R, &tmp, ZEND_FFI_FLAG_CONST, + false, false); zend_hash_index_add(ht, n, &tmp); ptr = (void*)(((char*)ptr) + ZEND_FFI_TYPE(type->array.type)->size); } @@ -2184,6 +2190,7 @@ static zend_result zend_ffi_cdata_get_closure(zend_object *obj, zend_class_entry func->common.arg_flags[1] = 0; func->common.arg_flags[2] = 0; func->common.fn_flags = ZEND_ACC_CALL_VIA_TRAMPOLINE; + func->common.fn_flags2 = 0; func->common.function_name = ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE); /* set to 0 to avoid arg_info[] allocation, because all values are passed by value anyway */ func->common.num_args = 0; @@ -2307,7 +2314,7 @@ static zend_object *zend_ffi_new(zend_class_entry *class_type) /* {{{ */ ffi->lib = NULL; ffi->symbols = NULL; ffi->tags = NULL; - ffi->persistent = 0; + ffi->persistent = false; return &ffi->std; } @@ -2509,7 +2516,8 @@ static zval *zend_ffi_read_var(zend_object *obj, zend_string *var_name, int read } if (sym->kind == ZEND_FFI_SYM_VAR) { - zend_ffi_cdata_to_zval(NULL, sym->addr, ZEND_FFI_TYPE(sym->type), read_type, rv, (zend_ffi_flags)sym->is_const, 0, 0); + zend_ffi_cdata_to_zval(NULL, sym->addr, ZEND_FFI_TYPE(sym->type), read_type, rv, (zend_ffi_flags)sym->is_const, + false, false); } else if (sym->kind == ZEND_FFI_SYM_FUNC) { zend_ffi_cdata *cdata; zend_ffi_type *new_type = emalloc(sizeof(zend_ffi_type)); @@ -2962,6 +2970,7 @@ static zend_function *zend_ffi_get_func(zend_object **obj, zend_string *name, co func->common.arg_flags[1] = 0; func->common.arg_flags[2] = 0; func->common.fn_flags = ZEND_ACC_CALL_VIA_TRAMPOLINE; + func->common.fn_flags2 = 0; func->common.function_name = zend_string_copy(name); /* set to 0 to avoid arg_info[] allocation, because all values are passed by value anyway */ func->common.num_args = 0; @@ -3581,7 +3590,7 @@ static zend_ffi *zend_ffi_load(const char *filename, bool preload) /* {{{ */ } ffi->symbols = scope->symbols; ffi->tags = scope->tags; - ffi->persistent = 1; + ffi->persistent = true; } else { ffi = (zend_ffi*)zend_ffi_new(zend_ffi_ce); ffi->lib = handle; @@ -3764,14 +3773,14 @@ static zend_result zend_ffi_validate_var_type(const zend_ffi_type *type, bool al zend_ffi_throw_parser_error("function type is not allowed at line %d", FFI_G(line)); return FAILURE; } - return zend_ffi_validate_type(type, 0, allow_incomplete_array); + return zend_ffi_validate_type(type, false, allow_incomplete_array); } /* }}} */ void zend_ffi_validate_type_name(zend_ffi_dcl *dcl) /* {{{ */ { zend_ffi_finalize_type(dcl); - if (zend_ffi_validate_var_type(ZEND_FFI_TYPE(dcl->type), 0) == FAILURE) { + if (zend_ffi_validate_var_type(ZEND_FFI_TYPE(dcl->type), false) == FAILURE) { zend_ffi_cleanup_dcl(dcl); LONGJMP(FFI_G(bailout), FAILURE); } @@ -4708,9 +4717,8 @@ ZEND_METHOD(FFI, isNull) /* {{{ */ ZEND_METHOD(FFI_CType, getName) /* {{{ */ { zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + + ZEND_PARSE_PARAMETERS_NONE(); zend_ffi_ctype_name_buf buf; @@ -4730,9 +4738,7 @@ ZEND_METHOD(FFI_CType, getKind) /* {{{ */ const zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); const zend_ffi_type *type; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); type = ZEND_FFI_TYPE(ctype->type); RETURN_LONG(type->kind); @@ -4744,9 +4750,7 @@ ZEND_METHOD(FFI_CType, getSize) /* {{{ */ const zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); const zend_ffi_type *type; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); type = ZEND_FFI_TYPE(ctype->type); RETURN_LONG(type->size); @@ -4758,9 +4762,7 @@ ZEND_METHOD(FFI_CType, getAlignment) /* {{{ */ const zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); const zend_ffi_type *type; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); type = ZEND_FFI_TYPE(ctype->type); RETURN_LONG(type->align); @@ -4772,9 +4774,7 @@ ZEND_METHOD(FFI_CType, getAttributes) /* {{{ */ const zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); const zend_ffi_type *type; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); type = ZEND_FFI_TYPE(ctype->type); RETURN_LONG(type->attr); @@ -4786,9 +4786,7 @@ ZEND_METHOD(FFI_CType, getEnumKind) /* {{{ */ const zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); const zend_ffi_type *type; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); type = ZEND_FFI_TYPE(ctype->type); if (type->kind != ZEND_FFI_TYPE_ENUM) { @@ -4805,9 +4803,7 @@ ZEND_METHOD(FFI_CType, getArrayElementType) /* {{{ */ zend_ffi_type *type; zend_ffi_ctype *ret; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); type = ZEND_FFI_TYPE(ctype->type); if (type->kind != ZEND_FFI_TYPE_ARRAY) { @@ -4826,9 +4822,7 @@ ZEND_METHOD(FFI_CType, getArrayLength) /* {{{ */ const zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); const zend_ffi_type *type; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); type = ZEND_FFI_TYPE(ctype->type); if (type->kind != ZEND_FFI_TYPE_ARRAY) { @@ -4845,9 +4839,7 @@ ZEND_METHOD(FFI_CType, getPointerType) /* {{{ */ zend_ffi_ctype *ret; zend_ffi_type *type; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); type = ZEND_FFI_TYPE(ctype->type); if (type->kind != ZEND_FFI_TYPE_POINTER) { @@ -4869,9 +4861,7 @@ ZEND_METHOD(FFI_CType, getStructFieldNames) /* {{{ */ zend_string* name; zval zv; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); type = ZEND_FFI_TYPE(ctype->type); if (type->kind != ZEND_FFI_TYPE_STRUCT) { @@ -4949,9 +4939,7 @@ ZEND_METHOD(FFI_CType, getFuncABI) /* {{{ */ const zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); const zend_ffi_type *type; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); type = ZEND_FFI_TYPE(ctype->type); if (type->kind != ZEND_FFI_TYPE_FUNC) { @@ -4968,9 +4956,7 @@ ZEND_METHOD(FFI_CType, getFuncReturnType) /* {{{ */ zend_ffi_ctype *ret; zend_ffi_type *type; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); type = ZEND_FFI_TYPE(ctype->type); if (type->kind != ZEND_FFI_TYPE_FUNC) { @@ -4989,9 +4975,7 @@ ZEND_METHOD(FFI_CType, getFuncParameterCount) /* {{{ */ const zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); const zend_ffi_type *type; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); type = ZEND_FFI_TYPE(ctype->type); if (type->kind != ZEND_FFI_TYPE_FUNC) { @@ -5369,7 +5353,7 @@ static zend_result zend_ffi_preload_glob(const char *filename) /* {{{ */ /* pass */ } else { for(i=0 ; itype); - bool overflow = 0; + bool overflow = false; bool is_signed = (enum_type->enumeration.kind == ZEND_FFI_TYPE_SINT8 || enum_type->enumeration.kind == ZEND_FFI_TYPE_SINT16 || @@ -6009,36 +5993,36 @@ void zend_ffi_add_enum_val(zend_ffi_dcl *enum_dcl, const char *name, size_t name if (val->kind == ZEND_FFI_VAL_EMPTY) { if (is_signed) { if (*last == 0x7FFFFFFFFFFFFFFFLL) { - overflow = 1; + overflow = true; } } else { if ((*min != 0 || *max != 0) && (uint64_t)*last == 0xFFFFFFFFFFFFFFFFULL) { - overflow = 1; + overflow = true; } } value = *last + 1; } else if (val->kind == ZEND_FFI_VAL_CHAR) { if (!is_signed && val->ch < 0) { if ((uint64_t)*max > 0x7FFFFFFFFFFFFFFFULL) { - overflow = 1; + overflow = true; } else { - is_signed = 1; + is_signed = true; } } value = val->ch; } else if (val->kind == ZEND_FFI_VAL_INT32 || val->kind == ZEND_FFI_VAL_INT64) { if (!is_signed && val->i64 < 0) { if ((uint64_t)*max > 0x7FFFFFFFFFFFFFFFULL) { - overflow = 1; + overflow = true; } else { - is_signed = 1; + is_signed = true; } } value = val->i64; } else if (val->kind == ZEND_FFI_VAL_UINT32 || val->kind == ZEND_FFI_VAL_UINT64) { if (is_signed && val->u64 > 0x7FFFFFFFFFFFFFFFULL) { - overflow = 1; + overflow = true; } value = val->u64; } else { @@ -6142,7 +6126,7 @@ static zend_result zend_ffi_validate_field_type(const zend_ffi_type *type, zend_ if (type == struct_type) { zend_ffi_throw_parser_error("Struct/union can't contain an instance of itself at line %d", FFI_G(line)); return FAILURE; - } else if (zend_ffi_validate_var_type(type, 1) == FAILURE) { + } else if (zend_ffi_validate_var_type(type, true) == FAILURE) { return FAILURE; } else if (struct_type->attr & ZEND_FFI_ATTR_UNION) { if (type->attr & ZEND_FFI_ATTR_INCOMPLETE_ARRAY) { @@ -6185,7 +6169,7 @@ void zend_ffi_add_field(zend_ffi_dcl *struct_dcl, const char *name, size_t name_ } field->type = field_dcl->type; field->is_const = (bool)(field_dcl->attr & ZEND_FFI_ATTR_CONST); - field->is_nested = 0; + field->is_nested = false; field->first_bit = 0; field->bits = 0; field_dcl->type = field_type; /* reset "owned" flag */ @@ -6238,7 +6222,7 @@ void zend_ffi_add_anonymous_field(zend_ffi_dcl *struct_dcl, zend_ffi_dcl *field_ } new_field->type = field->type; new_field->is_const = field->is_const; - new_field->is_nested = 1; + new_field->is_nested = true; new_field->first_bit = field->first_bit; new_field->bits = field->bits; field->type = ZEND_FFI_TYPE(field->type); /* reset "owned" flag */ @@ -6353,7 +6337,7 @@ void zend_ffi_add_bit_field(zend_ffi_dcl *struct_dcl, const char *name, size_t n } field->type = field_dcl->type; field->is_const = (bool)(field_dcl->attr & ZEND_FFI_ATTR_CONST); - field->is_nested = 0; + field->is_nested = false; field_dcl->type = field_type; /* reset "owned" flag */ if (name) { @@ -6412,7 +6396,7 @@ static zend_result zend_ffi_validate_array_element_type(const zend_ffi_type *typ zend_ffi_throw_parser_error("Only the leftmost array can be undimensioned at line %d", FFI_G(line)); return FAILURE; } - return zend_ffi_validate_type(type, 0, 1); + return zend_ffi_validate_type(type, false, true); } /* }}} */ @@ -6472,7 +6456,7 @@ static zend_result zend_ffi_validate_func_ret_type(const zend_ffi_type *type) /* zend_ffi_throw_parser_error("Function returning array is not allowed at line %d", FFI_G(line)); return FAILURE; } - return zend_ffi_validate_incomplete_type(type, 1, 0); + return zend_ffi_validate_incomplete_type(type, true, false); } /* }}} */ @@ -6646,7 +6630,7 @@ void zend_ffi_add_arg(HashTable **args, const char *name, size_t name_len, zend_ new_type->pointer.type = arg_dcl->type; arg_dcl->type = ZEND_FFI_TYPE_MAKE_OWNED(new_type); } - if (zend_ffi_validate_incomplete_type(type, 1, 1) == FAILURE) { + if (zend_ffi_validate_incomplete_type(type, true, true) == FAILURE) { zend_ffi_cleanup_dcl(arg_dcl); zend_hash_destroy(*args); pefree(*args, FFI_G(persistent)); @@ -6725,7 +6709,7 @@ void zend_ffi_declare(const char *name, size_t name_len, zend_ffi_dcl *dcl) /* { zend_ffi_type *type; type = ZEND_FFI_TYPE(dcl->type); - if (zend_ffi_validate_type(type, (dcl->flags & ZEND_FFI_DCL_STORAGE_CLASS) == ZEND_FFI_DCL_EXTERN, 1) == FAILURE) { + if (zend_ffi_validate_type(type, (dcl->flags & ZEND_FFI_DCL_STORAGE_CLASS) == ZEND_FFI_DCL_EXTERN, true) == FAILURE) { zend_ffi_cleanup_dcl(dcl); LONGJMP(FFI_G(bailout), FAILURE); } diff --git a/ext/ffi/ffi_arginfo.h b/ext/ffi/ffi_arginfo.h index 563c9f8b8e8b1..1485c973d9a11 100644 --- a/ext/ffi/ffi_arginfo.h +++ b/ext/ffi/ffi_arginfo.h @@ -205,9 +205,9 @@ static zend_class_entry *register_class_FFI(void) zval const___BIGGEST_ALIGNMENT___value; ZVAL_LONG(&const___BIGGEST_ALIGNMENT___value, __BIGGEST_ALIGNMENT__); - zend_string *const___BIGGEST_ALIGNMENT___name = zend_string_init_interned("__BIGGEST_ALIGNMENT__", sizeof("__BIGGEST_ALIGNMENT__") - 1, 1); + zend_string *const___BIGGEST_ALIGNMENT___name = zend_string_init_interned("__BIGGEST_ALIGNMENT__", sizeof("__BIGGEST_ALIGNMENT__") - 1, true); zend_declare_typed_class_constant(class_entry, const___BIGGEST_ALIGNMENT___name, &const___BIGGEST_ALIGNMENT___value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const___BIGGEST_ALIGNMENT___name); + zend_string_release_ex(const___BIGGEST_ALIGNMENT___name, true); return class_entry; } @@ -231,233 +231,233 @@ static zend_class_entry *register_class_FFI_CType(void) zval const_TYPE_VOID_value; ZVAL_LONG(&const_TYPE_VOID_value, ZEND_FFI_TYPE_VOID); - zend_string *const_TYPE_VOID_name = zend_string_init_interned("TYPE_VOID", sizeof("TYPE_VOID") - 1, 1); + zend_string *const_TYPE_VOID_name = zend_string_init_interned("TYPE_VOID", sizeof("TYPE_VOID") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_VOID_name, &const_TYPE_VOID_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_VOID_name); + zend_string_release_ex(const_TYPE_VOID_name, true); zval const_TYPE_FLOAT_value; ZVAL_LONG(&const_TYPE_FLOAT_value, ZEND_FFI_TYPE_FLOAT); - zend_string *const_TYPE_FLOAT_name = zend_string_init_interned("TYPE_FLOAT", sizeof("TYPE_FLOAT") - 1, 1); + zend_string *const_TYPE_FLOAT_name = zend_string_init_interned("TYPE_FLOAT", sizeof("TYPE_FLOAT") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_FLOAT_name, &const_TYPE_FLOAT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_FLOAT_name); + zend_string_release_ex(const_TYPE_FLOAT_name, true); zval const_TYPE_DOUBLE_value; ZVAL_LONG(&const_TYPE_DOUBLE_value, ZEND_FFI_TYPE_DOUBLE); - zend_string *const_TYPE_DOUBLE_name = zend_string_init_interned("TYPE_DOUBLE", sizeof("TYPE_DOUBLE") - 1, 1); + zend_string *const_TYPE_DOUBLE_name = zend_string_init_interned("TYPE_DOUBLE", sizeof("TYPE_DOUBLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_DOUBLE_name, &const_TYPE_DOUBLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_DOUBLE_name); + zend_string_release_ex(const_TYPE_DOUBLE_name, true); #if defined(HAVE_LONG_DOUBLE) zval const_TYPE_LONGDOUBLE_value; ZVAL_LONG(&const_TYPE_LONGDOUBLE_value, ZEND_FFI_TYPE_LONGDOUBLE); - zend_string *const_TYPE_LONGDOUBLE_name = zend_string_init_interned("TYPE_LONGDOUBLE", sizeof("TYPE_LONGDOUBLE") - 1, 1); + zend_string *const_TYPE_LONGDOUBLE_name = zend_string_init_interned("TYPE_LONGDOUBLE", sizeof("TYPE_LONGDOUBLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_LONGDOUBLE_name, &const_TYPE_LONGDOUBLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_LONGDOUBLE_name); + zend_string_release_ex(const_TYPE_LONGDOUBLE_name, true); #endif zval const_TYPE_UINT8_value; ZVAL_LONG(&const_TYPE_UINT8_value, ZEND_FFI_TYPE_UINT8); - zend_string *const_TYPE_UINT8_name = zend_string_init_interned("TYPE_UINT8", sizeof("TYPE_UINT8") - 1, 1); + zend_string *const_TYPE_UINT8_name = zend_string_init_interned("TYPE_UINT8", sizeof("TYPE_UINT8") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_UINT8_name, &const_TYPE_UINT8_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_UINT8_name); + zend_string_release_ex(const_TYPE_UINT8_name, true); zval const_TYPE_SINT8_value; ZVAL_LONG(&const_TYPE_SINT8_value, ZEND_FFI_TYPE_SINT8); - zend_string *const_TYPE_SINT8_name = zend_string_init_interned("TYPE_SINT8", sizeof("TYPE_SINT8") - 1, 1); + zend_string *const_TYPE_SINT8_name = zend_string_init_interned("TYPE_SINT8", sizeof("TYPE_SINT8") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_SINT8_name, &const_TYPE_SINT8_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_SINT8_name); + zend_string_release_ex(const_TYPE_SINT8_name, true); zval const_TYPE_UINT16_value; ZVAL_LONG(&const_TYPE_UINT16_value, ZEND_FFI_TYPE_UINT16); - zend_string *const_TYPE_UINT16_name = zend_string_init_interned("TYPE_UINT16", sizeof("TYPE_UINT16") - 1, 1); + zend_string *const_TYPE_UINT16_name = zend_string_init_interned("TYPE_UINT16", sizeof("TYPE_UINT16") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_UINT16_name, &const_TYPE_UINT16_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_UINT16_name); + zend_string_release_ex(const_TYPE_UINT16_name, true); zval const_TYPE_SINT16_value; ZVAL_LONG(&const_TYPE_SINT16_value, ZEND_FFI_TYPE_SINT16); - zend_string *const_TYPE_SINT16_name = zend_string_init_interned("TYPE_SINT16", sizeof("TYPE_SINT16") - 1, 1); + zend_string *const_TYPE_SINT16_name = zend_string_init_interned("TYPE_SINT16", sizeof("TYPE_SINT16") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_SINT16_name, &const_TYPE_SINT16_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_SINT16_name); + zend_string_release_ex(const_TYPE_SINT16_name, true); zval const_TYPE_UINT32_value; ZVAL_LONG(&const_TYPE_UINT32_value, ZEND_FFI_TYPE_UINT32); - zend_string *const_TYPE_UINT32_name = zend_string_init_interned("TYPE_UINT32", sizeof("TYPE_UINT32") - 1, 1); + zend_string *const_TYPE_UINT32_name = zend_string_init_interned("TYPE_UINT32", sizeof("TYPE_UINT32") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_UINT32_name, &const_TYPE_UINT32_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_UINT32_name); + zend_string_release_ex(const_TYPE_UINT32_name, true); zval const_TYPE_SINT32_value; ZVAL_LONG(&const_TYPE_SINT32_value, ZEND_FFI_TYPE_SINT32); - zend_string *const_TYPE_SINT32_name = zend_string_init_interned("TYPE_SINT32", sizeof("TYPE_SINT32") - 1, 1); + zend_string *const_TYPE_SINT32_name = zend_string_init_interned("TYPE_SINT32", sizeof("TYPE_SINT32") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_SINT32_name, &const_TYPE_SINT32_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_SINT32_name); + zend_string_release_ex(const_TYPE_SINT32_name, true); zval const_TYPE_UINT64_value; ZVAL_LONG(&const_TYPE_UINT64_value, ZEND_FFI_TYPE_UINT64); - zend_string *const_TYPE_UINT64_name = zend_string_init_interned("TYPE_UINT64", sizeof("TYPE_UINT64") - 1, 1); + zend_string *const_TYPE_UINT64_name = zend_string_init_interned("TYPE_UINT64", sizeof("TYPE_UINT64") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_UINT64_name, &const_TYPE_UINT64_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_UINT64_name); + zend_string_release_ex(const_TYPE_UINT64_name, true); zval const_TYPE_SINT64_value; ZVAL_LONG(&const_TYPE_SINT64_value, ZEND_FFI_TYPE_SINT64); - zend_string *const_TYPE_SINT64_name = zend_string_init_interned("TYPE_SINT64", sizeof("TYPE_SINT64") - 1, 1); + zend_string *const_TYPE_SINT64_name = zend_string_init_interned("TYPE_SINT64", sizeof("TYPE_SINT64") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_SINT64_name, &const_TYPE_SINT64_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_SINT64_name); + zend_string_release_ex(const_TYPE_SINT64_name, true); zval const_TYPE_ENUM_value; ZVAL_LONG(&const_TYPE_ENUM_value, ZEND_FFI_TYPE_ENUM); - zend_string *const_TYPE_ENUM_name = zend_string_init_interned("TYPE_ENUM", sizeof("TYPE_ENUM") - 1, 1); + zend_string *const_TYPE_ENUM_name = zend_string_init_interned("TYPE_ENUM", sizeof("TYPE_ENUM") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_ENUM_name, &const_TYPE_ENUM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_ENUM_name); + zend_string_release_ex(const_TYPE_ENUM_name, true); zval const_TYPE_BOOL_value; ZVAL_LONG(&const_TYPE_BOOL_value, ZEND_FFI_TYPE_BOOL); - zend_string *const_TYPE_BOOL_name = zend_string_init_interned("TYPE_BOOL", sizeof("TYPE_BOOL") - 1, 1); + zend_string *const_TYPE_BOOL_name = zend_string_init_interned("TYPE_BOOL", sizeof("TYPE_BOOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_BOOL_name, &const_TYPE_BOOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_BOOL_name); + zend_string_release_ex(const_TYPE_BOOL_name, true); zval const_TYPE_CHAR_value; ZVAL_LONG(&const_TYPE_CHAR_value, ZEND_FFI_TYPE_CHAR); - zend_string *const_TYPE_CHAR_name = zend_string_init_interned("TYPE_CHAR", sizeof("TYPE_CHAR") - 1, 1); + zend_string *const_TYPE_CHAR_name = zend_string_init_interned("TYPE_CHAR", sizeof("TYPE_CHAR") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_CHAR_name, &const_TYPE_CHAR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_CHAR_name); + zend_string_release_ex(const_TYPE_CHAR_name, true); zval const_TYPE_POINTER_value; ZVAL_LONG(&const_TYPE_POINTER_value, ZEND_FFI_TYPE_POINTER); - zend_string *const_TYPE_POINTER_name = zend_string_init_interned("TYPE_POINTER", sizeof("TYPE_POINTER") - 1, 1); + zend_string *const_TYPE_POINTER_name = zend_string_init_interned("TYPE_POINTER", sizeof("TYPE_POINTER") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_POINTER_name, &const_TYPE_POINTER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_POINTER_name); + zend_string_release_ex(const_TYPE_POINTER_name, true); zval const_TYPE_FUNC_value; ZVAL_LONG(&const_TYPE_FUNC_value, ZEND_FFI_TYPE_FUNC); - zend_string *const_TYPE_FUNC_name = zend_string_init_interned("TYPE_FUNC", sizeof("TYPE_FUNC") - 1, 1); + zend_string *const_TYPE_FUNC_name = zend_string_init_interned("TYPE_FUNC", sizeof("TYPE_FUNC") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_FUNC_name, &const_TYPE_FUNC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_FUNC_name); + zend_string_release_ex(const_TYPE_FUNC_name, true); zval const_TYPE_ARRAY_value; ZVAL_LONG(&const_TYPE_ARRAY_value, ZEND_FFI_TYPE_ARRAY); - zend_string *const_TYPE_ARRAY_name = zend_string_init_interned("TYPE_ARRAY", sizeof("TYPE_ARRAY") - 1, 1); + zend_string *const_TYPE_ARRAY_name = zend_string_init_interned("TYPE_ARRAY", sizeof("TYPE_ARRAY") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_ARRAY_name, &const_TYPE_ARRAY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_ARRAY_name); + zend_string_release_ex(const_TYPE_ARRAY_name, true); zval const_TYPE_STRUCT_value; ZVAL_LONG(&const_TYPE_STRUCT_value, ZEND_FFI_TYPE_STRUCT); - zend_string *const_TYPE_STRUCT_name = zend_string_init_interned("TYPE_STRUCT", sizeof("TYPE_STRUCT") - 1, 1); + zend_string *const_TYPE_STRUCT_name = zend_string_init_interned("TYPE_STRUCT", sizeof("TYPE_STRUCT") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_STRUCT_name, &const_TYPE_STRUCT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_STRUCT_name); + zend_string_release_ex(const_TYPE_STRUCT_name, true); zval const_ATTR_CONST_value; ZVAL_LONG(&const_ATTR_CONST_value, ZEND_FFI_ATTR_CONST); - zend_string *const_ATTR_CONST_name = zend_string_init_interned("ATTR_CONST", sizeof("ATTR_CONST") - 1, 1); + zend_string *const_ATTR_CONST_name = zend_string_init_interned("ATTR_CONST", sizeof("ATTR_CONST") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_CONST_name, &const_ATTR_CONST_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_CONST_name); + zend_string_release_ex(const_ATTR_CONST_name, true); zval const_ATTR_INCOMPLETE_TAG_value; ZVAL_LONG(&const_ATTR_INCOMPLETE_TAG_value, ZEND_FFI_ATTR_INCOMPLETE_TAG); - zend_string *const_ATTR_INCOMPLETE_TAG_name = zend_string_init_interned("ATTR_INCOMPLETE_TAG", sizeof("ATTR_INCOMPLETE_TAG") - 1, 1); + zend_string *const_ATTR_INCOMPLETE_TAG_name = zend_string_init_interned("ATTR_INCOMPLETE_TAG", sizeof("ATTR_INCOMPLETE_TAG") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_INCOMPLETE_TAG_name, &const_ATTR_INCOMPLETE_TAG_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_INCOMPLETE_TAG_name); + zend_string_release_ex(const_ATTR_INCOMPLETE_TAG_name, true); zval const_ATTR_VARIADIC_value; ZVAL_LONG(&const_ATTR_VARIADIC_value, ZEND_FFI_ATTR_VARIADIC); - zend_string *const_ATTR_VARIADIC_name = zend_string_init_interned("ATTR_VARIADIC", sizeof("ATTR_VARIADIC") - 1, 1); + zend_string *const_ATTR_VARIADIC_name = zend_string_init_interned("ATTR_VARIADIC", sizeof("ATTR_VARIADIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_VARIADIC_name, &const_ATTR_VARIADIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_VARIADIC_name); + zend_string_release_ex(const_ATTR_VARIADIC_name, true); zval const_ATTR_INCOMPLETE_ARRAY_value; ZVAL_LONG(&const_ATTR_INCOMPLETE_ARRAY_value, ZEND_FFI_ATTR_INCOMPLETE_ARRAY); - zend_string *const_ATTR_INCOMPLETE_ARRAY_name = zend_string_init_interned("ATTR_INCOMPLETE_ARRAY", sizeof("ATTR_INCOMPLETE_ARRAY") - 1, 1); + zend_string *const_ATTR_INCOMPLETE_ARRAY_name = zend_string_init_interned("ATTR_INCOMPLETE_ARRAY", sizeof("ATTR_INCOMPLETE_ARRAY") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_INCOMPLETE_ARRAY_name, &const_ATTR_INCOMPLETE_ARRAY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_INCOMPLETE_ARRAY_name); + zend_string_release_ex(const_ATTR_INCOMPLETE_ARRAY_name, true); zval const_ATTR_VLA_value; ZVAL_LONG(&const_ATTR_VLA_value, ZEND_FFI_ATTR_VLA); - zend_string *const_ATTR_VLA_name = zend_string_init_interned("ATTR_VLA", sizeof("ATTR_VLA") - 1, 1); + zend_string *const_ATTR_VLA_name = zend_string_init_interned("ATTR_VLA", sizeof("ATTR_VLA") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_VLA_name, &const_ATTR_VLA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_VLA_name); + zend_string_release_ex(const_ATTR_VLA_name, true); zval const_ATTR_UNION_value; ZVAL_LONG(&const_ATTR_UNION_value, ZEND_FFI_ATTR_UNION); - zend_string *const_ATTR_UNION_name = zend_string_init_interned("ATTR_UNION", sizeof("ATTR_UNION") - 1, 1); + zend_string *const_ATTR_UNION_name = zend_string_init_interned("ATTR_UNION", sizeof("ATTR_UNION") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_UNION_name, &const_ATTR_UNION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_UNION_name); + zend_string_release_ex(const_ATTR_UNION_name, true); zval const_ATTR_PACKED_value; ZVAL_LONG(&const_ATTR_PACKED_value, ZEND_FFI_ATTR_PACKED); - zend_string *const_ATTR_PACKED_name = zend_string_init_interned("ATTR_PACKED", sizeof("ATTR_PACKED") - 1, 1); + zend_string *const_ATTR_PACKED_name = zend_string_init_interned("ATTR_PACKED", sizeof("ATTR_PACKED") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_PACKED_name, &const_ATTR_PACKED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_PACKED_name); + zend_string_release_ex(const_ATTR_PACKED_name, true); zval const_ATTR_MS_STRUCT_value; ZVAL_LONG(&const_ATTR_MS_STRUCT_value, ZEND_FFI_ATTR_MS_STRUCT); - zend_string *const_ATTR_MS_STRUCT_name = zend_string_init_interned("ATTR_MS_STRUCT", sizeof("ATTR_MS_STRUCT") - 1, 1); + zend_string *const_ATTR_MS_STRUCT_name = zend_string_init_interned("ATTR_MS_STRUCT", sizeof("ATTR_MS_STRUCT") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_MS_STRUCT_name, &const_ATTR_MS_STRUCT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_MS_STRUCT_name); + zend_string_release_ex(const_ATTR_MS_STRUCT_name, true); zval const_ATTR_GCC_STRUCT_value; ZVAL_LONG(&const_ATTR_GCC_STRUCT_value, ZEND_FFI_ATTR_GCC_STRUCT); - zend_string *const_ATTR_GCC_STRUCT_name = zend_string_init_interned("ATTR_GCC_STRUCT", sizeof("ATTR_GCC_STRUCT") - 1, 1); + zend_string *const_ATTR_GCC_STRUCT_name = zend_string_init_interned("ATTR_GCC_STRUCT", sizeof("ATTR_GCC_STRUCT") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_GCC_STRUCT_name, &const_ATTR_GCC_STRUCT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_GCC_STRUCT_name); + zend_string_release_ex(const_ATTR_GCC_STRUCT_name, true); zval const_ABI_DEFAULT_value; ZVAL_LONG(&const_ABI_DEFAULT_value, ZEND_FFI_ABI_DEFAULT); - zend_string *const_ABI_DEFAULT_name = zend_string_init_interned("ABI_DEFAULT", sizeof("ABI_DEFAULT") - 1, 1); + zend_string *const_ABI_DEFAULT_name = zend_string_init_interned("ABI_DEFAULT", sizeof("ABI_DEFAULT") - 1, true); zend_declare_typed_class_constant(class_entry, const_ABI_DEFAULT_name, &const_ABI_DEFAULT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ABI_DEFAULT_name); + zend_string_release_ex(const_ABI_DEFAULT_name, true); zval const_ABI_CDECL_value; ZVAL_LONG(&const_ABI_CDECL_value, ZEND_FFI_ABI_CDECL); - zend_string *const_ABI_CDECL_name = zend_string_init_interned("ABI_CDECL", sizeof("ABI_CDECL") - 1, 1); + zend_string *const_ABI_CDECL_name = zend_string_init_interned("ABI_CDECL", sizeof("ABI_CDECL") - 1, true); zend_declare_typed_class_constant(class_entry, const_ABI_CDECL_name, &const_ABI_CDECL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ABI_CDECL_name); + zend_string_release_ex(const_ABI_CDECL_name, true); zval const_ABI_FASTCALL_value; ZVAL_LONG(&const_ABI_FASTCALL_value, ZEND_FFI_ABI_FASTCALL); - zend_string *const_ABI_FASTCALL_name = zend_string_init_interned("ABI_FASTCALL", sizeof("ABI_FASTCALL") - 1, 1); + zend_string *const_ABI_FASTCALL_name = zend_string_init_interned("ABI_FASTCALL", sizeof("ABI_FASTCALL") - 1, true); zend_declare_typed_class_constant(class_entry, const_ABI_FASTCALL_name, &const_ABI_FASTCALL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ABI_FASTCALL_name); + zend_string_release_ex(const_ABI_FASTCALL_name, true); zval const_ABI_THISCALL_value; ZVAL_LONG(&const_ABI_THISCALL_value, ZEND_FFI_ABI_THISCALL); - zend_string *const_ABI_THISCALL_name = zend_string_init_interned("ABI_THISCALL", sizeof("ABI_THISCALL") - 1, 1); + zend_string *const_ABI_THISCALL_name = zend_string_init_interned("ABI_THISCALL", sizeof("ABI_THISCALL") - 1, true); zend_declare_typed_class_constant(class_entry, const_ABI_THISCALL_name, &const_ABI_THISCALL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ABI_THISCALL_name); + zend_string_release_ex(const_ABI_THISCALL_name, true); zval const_ABI_STDCALL_value; ZVAL_LONG(&const_ABI_STDCALL_value, ZEND_FFI_ABI_STDCALL); - zend_string *const_ABI_STDCALL_name = zend_string_init_interned("ABI_STDCALL", sizeof("ABI_STDCALL") - 1, 1); + zend_string *const_ABI_STDCALL_name = zend_string_init_interned("ABI_STDCALL", sizeof("ABI_STDCALL") - 1, true); zend_declare_typed_class_constant(class_entry, const_ABI_STDCALL_name, &const_ABI_STDCALL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ABI_STDCALL_name); + zend_string_release_ex(const_ABI_STDCALL_name, true); zval const_ABI_PASCAL_value; ZVAL_LONG(&const_ABI_PASCAL_value, ZEND_FFI_ABI_PASCAL); - zend_string *const_ABI_PASCAL_name = zend_string_init_interned("ABI_PASCAL", sizeof("ABI_PASCAL") - 1, 1); + zend_string *const_ABI_PASCAL_name = zend_string_init_interned("ABI_PASCAL", sizeof("ABI_PASCAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_ABI_PASCAL_name, &const_ABI_PASCAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ABI_PASCAL_name); + zend_string_release_ex(const_ABI_PASCAL_name, true); zval const_ABI_REGISTER_value; ZVAL_LONG(&const_ABI_REGISTER_value, ZEND_FFI_ABI_REGISTER); - zend_string *const_ABI_REGISTER_name = zend_string_init_interned("ABI_REGISTER", sizeof("ABI_REGISTER") - 1, 1); + zend_string *const_ABI_REGISTER_name = zend_string_init_interned("ABI_REGISTER", sizeof("ABI_REGISTER") - 1, true); zend_declare_typed_class_constant(class_entry, const_ABI_REGISTER_name, &const_ABI_REGISTER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ABI_REGISTER_name); + zend_string_release_ex(const_ABI_REGISTER_name, true); zval const_ABI_MS_value; ZVAL_LONG(&const_ABI_MS_value, ZEND_FFI_ABI_MS); - zend_string *const_ABI_MS_name = zend_string_init_interned("ABI_MS", sizeof("ABI_MS") - 1, 1); + zend_string *const_ABI_MS_name = zend_string_init_interned("ABI_MS", sizeof("ABI_MS") - 1, true); zend_declare_typed_class_constant(class_entry, const_ABI_MS_name, &const_ABI_MS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ABI_MS_name); + zend_string_release_ex(const_ABI_MS_name, true); zval const_ABI_SYSV_value; ZVAL_LONG(&const_ABI_SYSV_value, ZEND_FFI_ABI_SYSV); - zend_string *const_ABI_SYSV_name = zend_string_init_interned("ABI_SYSV", sizeof("ABI_SYSV") - 1, 1); + zend_string *const_ABI_SYSV_name = zend_string_init_interned("ABI_SYSV", sizeof("ABI_SYSV") - 1, true); zend_declare_typed_class_constant(class_entry, const_ABI_SYSV_name, &const_ABI_SYSV_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ABI_SYSV_name); + zend_string_release_ex(const_ABI_SYSV_name, true); zval const_ABI_VECTORCALL_value; ZVAL_LONG(&const_ABI_VECTORCALL_value, ZEND_FFI_ABI_VECTORCALL); - zend_string *const_ABI_VECTORCALL_name = zend_string_init_interned("ABI_VECTORCALL", sizeof("ABI_VECTORCALL") - 1, 1); + zend_string *const_ABI_VECTORCALL_name = zend_string_init_interned("ABI_VECTORCALL", sizeof("ABI_VECTORCALL") - 1, true); zend_declare_typed_class_constant(class_entry, const_ABI_VECTORCALL_name, &const_ABI_VECTORCALL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ABI_VECTORCALL_name); + zend_string_release_ex(const_ABI_VECTORCALL_name, true); return class_entry; } diff --git a/ext/ffi/ffi_parser.c b/ext/ffi/ffi_parser.c index 26d623a40290e..1067f80939f39 100644 --- a/ext/ffi/ffi_parser.c +++ b/ext/ffi/ffi_parser.c @@ -2634,7 +2634,7 @@ static int parse_enumerator(int sym, zend_ffi_dcl *enum_dcl, int64_t *min, int64 static int parse_declarator(int sym, zend_ffi_dcl *dcl, const char **name, size_t *name_len) { zend_ffi_dcl nested_dcl = {ZEND_FFI_DCL_CHAR, 0, 0, 0, NULL}; - bool nested = 0; + bool nested = false; if (sym == YY__STAR) { sym = parse_pointer(sym, dcl); } @@ -2650,7 +2650,7 @@ static int parse_declarator(int sym, zend_ffi_dcl *dcl, const char **name, size_ yy_error_sym("')' expected, got", sym); } sym = get_sym(); - nested = 1; + nested = true; } else { yy_error_sym("unexpected", sym); } @@ -2663,7 +2663,7 @@ static int parse_declarator(int sym, zend_ffi_dcl *dcl, const char **name, size_ static int parse_abstract_declarator(int sym, zend_ffi_dcl *dcl) { zend_ffi_dcl nested_dcl = {ZEND_FFI_DCL_CHAR, 0, 0, 0, NULL}; - bool nested = 0; + bool nested = false; if (sym == YY__STAR) { sym = parse_pointer(sym, dcl); } @@ -2677,7 +2677,7 @@ static int parse_abstract_declarator(int sym, zend_ffi_dcl *dcl) { yy_error_sym("')' expected, got", sym); } sym = get_sym(); - nested = 1; + nested = true; } if (sym == YY__LBRACK || sym == YY__LPAREN) { sym = parse_array_or_function_declarators(sym, dcl, &nested_dcl); @@ -2688,7 +2688,7 @@ static int parse_abstract_declarator(int sym, zend_ffi_dcl *dcl) { static int parse_parameter_declarator(int sym, zend_ffi_dcl *dcl, const char **name, size_t *name_len) { zend_ffi_dcl nested_dcl = {ZEND_FFI_DCL_CHAR, 0, 0, 0, NULL}; - bool nested = 0; + bool nested = false; if (sym == YY__STAR) { sym = parse_pointer(sym, dcl); } @@ -2702,7 +2702,7 @@ static int parse_parameter_declarator(int sym, zend_ffi_dcl *dcl, const char **n yy_error_sym("')' expected, got", sym); } sym = get_sym(); - nested = 1; + nested = true; } else if (sym == YY_ID) { sym = parse_ID(sym, name, name_len); } else if (sym == YY__LBRACK || sym == YY__LPAREN || sym == YY__RPAREN || sym == YY__COMMA) { 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/libmagic/config.h b/ext/fileinfo/libmagic/config.h index 4af6e06c4127d..34a10d59faa18 100644 --- a/ext/fileinfo/libmagic/config.h +++ b/ext/fileinfo/libmagic/config.h @@ -2,11 +2,7 @@ #include "php_libmagic.h" #ifndef HAVE_STDINT_H -#define HAVE_STDINT_H 1 -#endif - -#ifndef HAVE_STDINT_H -#define HAVE_STDINT_H 1 +# define HAVE_STDINT_H 1 #endif #ifndef HAVE_VISIBILITY 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..dea39c6cc7c30 100644 --- a/ext/filter/callback_filter.c +++ b/ext/filter/callback_filter.c @@ -16,25 +16,25 @@ #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; + zend_fcall_info_cache fcc; - if (!option_array || !zend_is_callable(option_array, IS_CALLABLE_SUPPRESS_DEPRECATIONS, NULL)) { + if (!option_array || !zend_is_callable_ex(option_array, NULL, IS_CALLABLE_SUPPRESS_DEPRECATIONS, NULL, &fcc, NULL)) { 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); + zend_call_known_fcc(&fcc, &retval, 1, value, NULL); + zval_ptr_dtor(value); - if (status == SUCCESS && !Z_ISUNDEF(retval)) { - zval_ptr_dtor(value); + if (!Z_ISUNDEF(retval)) { ZVAL_COPY_VALUE(value, &retval); } else { - zval_ptr_dtor(value); ZVAL_NULL(value); } + return SUCCESS; } diff --git a/ext/filter/filter.c b/ext/filter/filter.c index 7f3624eb4c07a..4a928379877bc 100644 --- a/ext/filter/filter.c +++ b/ext/filter/filter.c @@ -30,11 +30,12 @@ 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 */ @@ -77,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, @@ -160,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; } /* }}} */ @@ -251,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); @@ -264,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 && @@ -450,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; @@ -492,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); @@ -506,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); @@ -516,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); @@ -530,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; @@ -554,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(); @@ -598,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 @@ -626,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); } /* }}} */ @@ -652,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 a8790bb7cd615..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 @@ -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 32a5c87184a87..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: a0f9a546d59bb27854af79a92e353f118ca6bdaf */ + * 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); @@ -119,18 +120,33 @@ static void register_filter_symbols(int module_number) 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); - zval attribute_Deprecated_const_FILTER_SANITIZE_STRING_0_arg1; 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_arg1, attribute_Deprecated_const_FILTER_SANITIZE_STRING_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_FILTER_SANITIZE_STRING_0->args[1].value, &attribute_Deprecated_const_FILTER_SANITIZE_STRING_0_arg1); + 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 attribute_Deprecated_const_FILTER_SANITIZE_STRIPPED_0_arg1; - zend_string *attribute_Deprecated_const_FILTER_SANITIZE_STRIPPED_0_arg1_str = zend_string_init("use htmlspecialchars() instead", strlen("use htmlspecialchars() instead"), 1); - ZVAL_STR(&attribute_Deprecated_const_FILTER_SANITIZE_STRIPPED_0_arg1, attribute_Deprecated_const_FILTER_SANITIZE_STRIPPED_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_FILTER_SANITIZE_STRIPPED_0->args[1].value, &attribute_Deprecated_const_FILTER_SANITIZE_STRIPPED_0_arg1); + 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..20760e656e763 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(http://github.com/PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ +zend_result php_filter_validate_url(http://github.com/PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ { - php_url *url; size_t old_len = Z_STRLEN_P(value); php_filter_url(http://github.com/value,%20flags,%20option_array,%20charset); @@ -600,56 +606,71 @@ void php_filter_validate_url(http://github.com/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; } /* }}} */ @@ -766,7 +788,7 @@ static bool _php_filter_validate_ipv6(const char *str, size_t str_len, int ip[8] const char *s = str; if (!memchr(str, ':', str_len)) { - return 0; + return false; } /* check for bundled IPv4 */ @@ -777,12 +799,12 @@ static bool _php_filter_validate_ipv6(const char *str, size_t str_len, int ip[8] } if (!_php_filter_validate_ipv4(ipv4, (str_len - (ipv4 - str)), ip4elm)) { - return 0; + return false; } str_len = ipv4 - str; /* length excluding ipv4 */ if (str_len < 2) { - return 0; + return false; } if (ipv4[-2] != ':') { @@ -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(http://github.com/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(http://github.com/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(http://github.com/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(http://github.com/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(http://github.com/value,%20(unsigned%20char%20*)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(http://github.com/PHP_INPUT_FILTER_PARAM_DECL) +zend_result php_filter_url(http://github.com/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(http://github.com/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/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/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:db8:0:85a3::ac1f:8001]/" +string(50) "http://[2001:db8:0:85a3::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:db8:0:85a3::ac1f:8001]/" +string(50) "http://[2001:db8:0:85a3::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/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..0c1287a3e7052 100644 --- a/ext/ftp/ftp.c +++ b/ext/ftp/ftp.c @@ -130,7 +130,7 @@ ftpbuf_t* ftp_open(const char *host, short port, zend_long timeout_sec) /* Default Settings */ ftp->timeout_sec = timeout_sec; - ftp->nb = 0; + ftp->nb = false; size = sizeof(ftp->localaddr); memset(&ftp->localaddr, 0, size); @@ -263,8 +263,8 @@ bool ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const cha if (ftp->resp != 334) { return false; } else { - ftp->old_ssl = 1; - ftp->use_ssl_for_data = 1; + ftp->old_ssl = true; + ftp->use_ssl_for_data = true; } } @@ -385,7 +385,7 @@ bool ftp_reinit(ftpbuf_t *ftp) ftp_gc(ftp); - ftp->nb = 0; + ftp->nb = false; if (!ftp_putcmd(ftp, "REIN", sizeof("REIN")-1, NULL, (size_t) 0)) { return false; @@ -1193,7 +1193,7 @@ static bool ftp_putcmd(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, con return false; } if (strpbrk(args, "\r\n")) { - return 0; + return false; } size = slprintf(data, sizeof(data), "%s %s\r\n", cmd, args); } else { @@ -1317,7 +1317,7 @@ static ssize_t my_recv_wrapper_with_restart(php_socket_t fd, void *buf, size_t s static int single_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t size) { #ifdef HAVE_FTP_SSL int err; - bool retry = 0; + bool retry = false; SSL *handle = NULL; php_socket_t fd; size_t sent; @@ -1338,11 +1338,11 @@ static int single_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t size) { switch (err) { case SSL_ERROR_NONE: - retry = 0; + retry = false; break; case SSL_ERROR_ZERO_RETURN: - retry = 0; + retry = false; SSL_shutdown(handle); break; @@ -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 @@ -1436,7 +1437,7 @@ static int my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) int n, nr_bytes; #ifdef HAVE_FTP_SSL int err; - bool retry = 0; + bool retry = false; SSL *handle = NULL; php_socket_t fd; #endif @@ -1470,11 +1471,11 @@ static int my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) switch (err) { case SSL_ERROR_NONE: - retry = 0; + retry = false; break; case SSL_ERROR_ZERO_RETURN: - retry = 0; + retry = false; SSL_shutdown(handle); break; @@ -1507,7 +1508,7 @@ static int my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) return (nr_bytes); } -static bool data_available(ftpbuf_t *ftp, php_socket_t s) +static bool data_available(ftpbuf_t *ftp, php_socket_t s, bool silent) { int n; @@ -1515,6 +1516,9 @@ static bool data_available(ftpbuf_t *ftp, php_socket_t s) if (n < 1) { char buf[256]; if (n == 0) { + if (silent) { + return false; + } #ifdef PHP_WIN32 _set_errno(ETIMEDOUT); #else @@ -1771,11 +1775,11 @@ static databuf_t* data_accept(databuf_t *data, ftpbuf_t *ftp) switch (err) { case SSL_ERROR_NONE: - retry = 0; + retry = false; break; case SSL_ERROR_ZERO_RETURN: - retry = 0; + retry = false; SSL_shutdown(data->ssl_handle); break; @@ -1830,7 +1834,9 @@ static void ftp_ssl_shutdown(ftpbuf_t *ftp, php_socket_t fd, SSL *ssl_handle) { done = 0; } - while (!done && data_available(ftp, fd)) { + /* Don't report timeouts on the control channel if we're negotiating a shutdown already. + * Some servers don't put a final response. */ + while (!done && data_available(ftp, fd, true)) { ERR_clear_error(); nread = SSL_read(ssl_handle, buf, sizeof(buf)); if (nread <= 0) { @@ -2057,7 +2063,7 @@ int ftp_nb_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, const siz ftp->data = data; ftp->stream = outstream; ftp->lastch = 0; - ftp->nb = 1; + ftp->nb = true; return (ftp_nb_continue_read(ftp)); @@ -2077,7 +2083,7 @@ int ftp_nb_continue_read(ftpbuf_t *ftp) data = ftp->data; /* check if there is already more data */ - if (!data_available(ftp, data->fd)) { + if (!data_available(ftp, data->fd, false)) { return PHP_FTP_MOREDATA; } @@ -2117,10 +2123,10 @@ int ftp_nb_continue_read(ftpbuf_t *ftp) goto bail; } - ftp->nb = 0; + ftp->nb = false; return PHP_FTP_FINISHED; bail: - ftp->nb = 0; + ftp->nb = false; data_close(ftp); return PHP_FTP_FAILED; } @@ -2165,7 +2171,7 @@ int ftp_nb_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_strea ftp->data = data; ftp->stream = instream; ftp->lastch = 0; - ftp->nb = 1; + ftp->nb = true; return (ftp_nb_continue_write(ftp)); @@ -2194,10 +2200,10 @@ int ftp_nb_continue_write(ftpbuf_t *ftp) if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250)) { goto bail; } - ftp->nb = 0; + ftp->nb = false; return PHP_FTP_FINISHED; bail: data_close(ftp); - ftp->nb = 0; + ftp->nb = false; return PHP_FTP_FAILED; } diff --git a/ext/ftp/php_ftp.c b/ext/ftp/php_ftp.c index fb771a66d73e4..63f5c222c1924 100644 --- a/ext/ftp/php_ftp.c +++ b/ext/ftp/php_ftp.c @@ -147,11 +147,18 @@ PHP_FUNCTION(ftp_connect) RETURN_THROWS(); } + const uint64_t timeoutmax = (uint64_t)((double) PHP_TIMEOUT_ULL_MAX / 1000000.0); + if (timeout_sec <= 0) { zend_argument_value_error(3, "must be greater than 0"); RETURN_THROWS(); } + if (timeout_sec >= timeoutmax) { + zend_argument_value_error(3, "must be less than " ZEND_ULONG_FMT, timeoutmax); + RETURN_THROWS(); + } + /* connect */ if (!(ftp = ftp_open(host, (short)port, timeout_sec))) { RETURN_FALSE; @@ -483,7 +490,7 @@ PHP_FUNCTION(ftp_rawlist) ftpbuf_t *ftp; char **llist, **ptr, *dir; size_t dir_len; - bool recursive = 0; + bool recursive = false; if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os|b", &z_ftp, php_ftp_ce, &dir, &dir_len, &recursive) == FAILURE) { RETURN_THROWS(); @@ -815,7 +822,7 @@ PHP_FUNCTION(ftp_nb_get) } /* }}} */ -/* {{{ Continues retrieving/sending a file nbronously */ +/* {{{ Continues to retrieve or send a file in non-blocking mode */ PHP_FUNCTION(ftp_nb_continue) { zval *z_ftp; @@ -828,7 +835,7 @@ PHP_FUNCTION(ftp_nb_continue) GET_FTPBUF(ftp, z_ftp); if (!ftp->nb) { - php_error_docref(NULL, E_WARNING, "No nbronous transfer to continue"); + php_error_docref(NULL, E_WARNING, "No non-blocking transfer to continue"); RETURN_LONG(PHP_FTP_FAILED); } diff --git a/ext/ftp/tests/005.phpt b/ext/ftp/tests/005.phpt index 409b60e184715..f08cadd2b4280 100644 --- a/ext/ftp/tests/005.phpt +++ b/ext/ftp/tests/005.phpt @@ -85,7 +85,7 @@ int(-1) Warning: ftp_mkdir(): Command not implemented (7). in %s005.php on line %d bool(false) -Warning: ftp_nb_continue(): No nbronous transfer to continue in %s005.php on line %d +Warning: ftp_nb_continue(): No non-blocking transfer to continue in %s on line %d int(0) ftp_nb_fget(): Argument #4 ($mode) must be either FTP_ASCII or FTP_BINARY ftp_nb_fput(): Argument #4 ($mode) must be either FTP_ASCII or FTP_BINARY diff --git a/ext/ftp/tests/gh20601.phpt b/ext/ftp/tests/gh20601.phpt new file mode 100644 index 0000000000000..3ece7736c3aaa --- /dev/null +++ b/ext/ftp/tests/gh20601.phpt @@ -0,0 +1,19 @@ +--TEST-- +GH-20601 (ftp_connect timeout overflow) +--EXTENSIONS-- +ftp +--SKIPIF-- + +--FILE-- +getMessage(); +} +?> +--EXPECTF-- +ftp_connect(): Argument #3 ($timeout) must be less than %d diff --git a/ext/gd/config.m4 b/ext/gd/config.m4 index 0d024c9ea1cf3..a997238b7f75c 100644 --- a/ext/gd/config.m4 +++ b/ext/gd/config.m4 @@ -265,6 +265,10 @@ if test "$PHP_GD" != "no"; then AC_DEFINE([HAVE_GD_BUNDLED], [1], [Define to 1 if gd extension uses GD library bundled in PHP.]) + AC_DEFINE([HAVE_GD_GET_INTERPOLATION], [1], + [Define to 1 if GD library has the 'gdImageGetInterpolationMethod' + function.]) + dnl Various checks for GD features PHP_SETUP_ZLIB([GD_SHARED_LIBADD]) PHP_GD_PNG diff --git a/ext/gd/gd.c b/ext/gd/gd.c index 3c1eac69b966a..60b2ad65bf65e 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 @@ -818,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); @@ -1573,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; @@ -2447,11 +2453,21 @@ PHP_FUNCTION(imagegammacorrect) RETURN_THROWS(); } + if (!zend_finite(input)) { + zend_argument_value_error(2, "must be finite"); + RETURN_THROWS(); + } + if (output <= 0.0) { zend_argument_value_error(3, "must be greater than 0"); RETURN_THROWS(); } + if (!zend_finite(output)) { + zend_argument_value_error(3, "must be finite"); + RETURN_THROWS(); + } + gamma = input / output; im = php_gd_libgdimageptr_from_zval_p(IM); @@ -2960,7 +2976,8 @@ static void php_imagechar(INTERNAL_FUNCTION_PARAMETERS, int mode) zend_long X, Y, COL; zend_string *C; gdImagePtr im; - int ch = 0, col, x, y, i; + int ch = 0, col, i; + unsigned int x, y; size_t l = 0; unsigned char *str = NULL; zend_object *font_obj = NULL; @@ -2993,21 +3010,21 @@ static void php_imagechar(INTERNAL_FUNCTION_PARAMETERS, int mode) switch (mode) { case 0: - gdImageChar(im, font, x, y, ch, col); + gdImageChar(im, font, (int)x, (int)y, ch, col); break; case 1: php_gdimagecharup(im, font, x, y, ch, col); break; case 2: for (i = 0; (i < l); i++) { - gdImageChar(im, font, x, y, (int) ((unsigned char) str[i]), col); + gdImageChar(im, font, (int)x, (int)y, (int) ((unsigned char) str[i]), col); x += font->w; } break; case 3: { for (i = 0; (i < l); i++) { /* php_gdimagecharup(im, font, x, y, (int) str[i], col); */ - gdImageCharUp(im, font, x, y, (int) str[i], col); + gdImageCharUp(im, font, (int)x, (int)y, (int) str[i], col); y -= font->w; } break; @@ -3599,7 +3616,7 @@ PHP_FUNCTION(imagefilter) zval *tmp; typedef void (*image_filter)(INTERNAL_FUNCTION_PARAMETERS); - zend_long filtertype; + zend_long filtertype = 0; image_filter filters[] = { php_image_filter_negate , @@ -3617,15 +3634,17 @@ PHP_FUNCTION(imagefilter) php_image_filter_scatter }; - if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > IMAGE_FILTER_MAX_ARGS) { - WRONG_PARAM_COUNT; - } else if (zend_parse_parameters(2, "Ol", &tmp, gd_image_ce, &filtertype) == FAILURE) { + /* We need to do some initial ZPP parsing to be able to extract the filter value */ + if (zend_parse_parameters(MIN(2, ZEND_NUM_ARGS()), "Ol*", &tmp, gd_image_ce, &filtertype) == FAILURE) { + RETURN_THROWS(); } - if (filtertype >= 0 && filtertype <= IMAGE_FILTER_MAX) { - filters[filtertype](INTERNAL_FUNCTION_PARAM_PASSTHRU); + if (UNEXPECTED(filtertype < 0 || filtertype > IMAGE_FILTER_MAX)) { + zend_argument_value_error(2, "must be one of the IMG_FILTER_* filter constants"); + RETURN_THROWS(); } + filters[filtertype](INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ @@ -3913,9 +3932,17 @@ PHP_FUNCTION(imagescale) src_y = gdImageSY(im); if (src_x && tmp_h < 0) { + if (tmp_w > (ZEND_LONG_MAX / src_y)) { + zend_argument_value_error(2, "must be less than or equal to " ZEND_LONG_FMT, (zend_long)(ZEND_LONG_MAX / src_y)); + RETURN_THROWS(); + } tmp_h = tmp_w * src_y / src_x; } if (src_y && tmp_w < 0) { + if (tmp_h > (ZEND_LONG_MAX / src_x)) { + zend_argument_value_error(3, "must be less than or equal to " ZEND_LONG_FMT, (zend_long)(ZEND_LONG_MAX / src_x)); + RETURN_THROWS(); + } tmp_w = tmp_h * src_x / src_y; } } @@ -4370,7 +4397,7 @@ static gdIOCtx *create_output_context(zval *to_zval, uint32_t arg_num) { } close_stream = 0; } else if (Z_TYPE_P(to_zval) == IS_STRING) { - if (CHECK_ZVAL_NULL_PATH(to_zval)) { + if (zend_str_has_nul_byte(Z_STR_P(to_zval))) { zend_argument_type_error(arg_num, "must not contain null bytes"); return NULL; } diff --git a/ext/gd/gd.stub.php b/ext/gd/gd.stub.php index d63c5ea7725ea..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; @@ -629,6 +623,7 @@ function imagegd2(GdImage $image, ?string $file = null, int $chunk_size = 128, i /** @param resource|string|null $file */ function imagebmp(GdImage $image, $file = null, bool $compressed = true): bool {} +#[\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 d46c9f06f6efd..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: 3db75a07cd5dfda50f239bc8c3992cd6d1e7afcb */ + * Stub hash: 2cdc0b485d9b62bb9021973d3c8cce0169b21ac0 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gd_info, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -759,7 +759,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(imagegd, arginfo_imagegd) ZEND_FE(imagegd2, arginfo_imagegd2) ZEND_FE(imagebmp, arginfo_imagebmp) - 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) @@ -923,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/libgd/gdkanji.c b/ext/gd/libgd/gdkanji.c index 21bc2280982a8..ef769f89badda 100644 --- a/ext/gd/libgd/gdkanji.c +++ b/ext/gd/libgd/gdkanji.c @@ -368,6 +368,8 @@ do_convert (unsigned char *to, unsigned char *from, const char *code) else error ("something happen"); strcpy ((char *) to, (const char *) from); + if (iconv_close (cd) != 0) + error ("iconv_close() error"); return; } 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/colorat.phpt b/ext/gd/tests/colorat.phpt index d0e62aca91024..82d6d56b5c7b2 100644 --- a/ext/gd/tests/colorat.phpt +++ b/ext/gd/tests/colorat.phpt @@ -15,7 +15,6 @@ echo 'test colorat truecolor: '; $c = imagecolorat($im, 3,3); echo $c == 0x0 ? 'ok' : 'failed'; echo "\n"; -imagedestroy($im); $im = imagecreate(6,6); $c1 = imagecolorallocate($im, 255,255,255); diff --git a/ext/gd/tests/colorclosest.phpt b/ext/gd/tests/colorclosest.phpt index 2633b24017d13..8cfcbdcdea4e7 100644 --- a/ext/gd/tests/colorclosest.phpt +++ b/ext/gd/tests/colorclosest.phpt @@ -8,7 +8,7 @@ gd $im = imagecreatetruecolor(5,5); $c = imagecolorclosest($im, 255,0,255); printf("%X\n", $c); -imagedestroy($im); +$im = null; $im = imagecreate(5,5); $c = imagecolorclosest($im, 255,0,255); @@ -17,13 +17,13 @@ try { } catch (ValueError $exception) { echo $exception->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/gh19955.phpt b/ext/gd/tests/gh19955.phpt new file mode 100644 index 0000000000000..30787bfc11c3d --- /dev/null +++ b/ext/gd/tests/gh19955.phpt @@ -0,0 +1,19 @@ +--TEST-- +GH-19955: (imagefttext() memory leak) +--EXTENSIONS-- +gd +--CREDITS-- +YuanchengJiang +--SKIPIF-- + +--FILE-- + +--EXPECT-- +OK diff --git a/ext/gd/tests/gh20551.phpt b/ext/gd/tests/gh20551.phpt new file mode 100644 index 0000000000000..32ca50ca5f626 --- /dev/null +++ b/ext/gd/tests/gh20551.phpt @@ -0,0 +1,36 @@ +--TEST-- +GH-20551: (imagegammacorrect out of range input/output value) +--EXTENSIONS-- +gd +--FILE-- +getMessage(), PHP_EOL; + } +} +?> +--EXPECT-- +imagegammacorrect(): Argument #2 ($input_gamma) must be finite +imagegammacorrect(): Argument #2 ($input_gamma) must be finite +imagegammacorrect(): Argument #2 ($input_gamma) must be finite +imagegammacorrect(): Argument #2 ($input_gamma) must be greater than 0 +imagegammacorrect(): Argument #3 ($output_gamma) must be finite +imagegammacorrect(): Argument #3 ($output_gamma) must be finite +imagegammacorrect(): Argument #3 ($output_gamma) must be finite +imagegammacorrect(): Argument #3 ($output_gamma) must be greater than 0 diff --git a/ext/gd/tests/gh20602.phpt b/ext/gd/tests/gh20602.phpt new file mode 100644 index 0000000000000..29c781e76a2d1 --- /dev/null +++ b/ext/gd/tests/gh20602.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-20551: (imagegammacorrect out of range input/output value) +--EXTENSIONS-- +gd +--FILE-- +getMessage(), PHP_EOL; +} +try { + imagescale($im, -1, PHP_INT_MAX); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} +?> +--EXPECTF-- +imagescale(): Argument #2 ($width) must be less than or equal to %d +imagescale(): Argument #3 ($height) must be less than or equal to %d diff --git a/ext/gd/tests/gh20622.phpt b/ext/gd/tests/gh20622.phpt new file mode 100644 index 0000000000000..42109ddc13e4d --- /dev/null +++ b/ext/gd/tests/gh20622.phpt @@ -0,0 +1,13 @@ +--TEST-- +GH-20622 (imagestring/imagestringup overflow/underflow) +--EXTENSIONS-- +gd +--FILE-- + +--EXPECT-- +OK diff --git a/ext/gd/tests/imagecolorclosesthwb_basic_001.phpt b/ext/gd/tests/imagecolorclosesthwb_basic_001.phpt index c450ee6f4e483..31982cc64deb9 100644 --- a/ext/gd/tests/imagecolorclosesthwb_basic_001.phpt +++ b/ext/gd/tests/imagecolorclosesthwb_basic_001.phpt @@ -21,8 +21,6 @@ gd var_dump(imagecolorclosesthwb($image, 0, 24, 200)); // 0 var_dump(imagecolorclosesthwb($image, 116, 120, 115)); // 1 var_dump(imagecolorclosesthwb($image, 50, 0, 90)); // 0 - - imagedestroy($image); ?> --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/imagedashedline_basic.phpt b/ext/gd/tests/imagedashedline_basic.phpt index d9ca69ad5f0b8..f676abd921d10 100644 --- a/ext/gd/tests/imagedashedline_basic.phpt +++ b/ext/gd/tests/imagedashedline_basic.phpt @@ -41,7 +41,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/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/imagefilter_error1.phpt b/ext/gd/tests/imagefilter_error1.phpt index 6e2ccabb874a8..cc9904e320dac 100644 --- a/ext/gd/tests/imagefilter_error1.phpt +++ b/ext/gd/tests/imagefilter_error1.phpt @@ -14,6 +14,12 @@ try { } catch (TypeError $e) { echo $e->getMessage(), "\n"; } +try { + var_dump(imagefilter(20, 1)); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} ?> --EXPECT-- -Wrong parameter count for imagefilter() +imagefilter() expects at least 2 arguments, 1 given +imagefilter(): Argument #1 ($image) must be of type GdImage, int given diff --git a/ext/gd/tests/imagefilter_invalid_filter_error.phpt b/ext/gd/tests/imagefilter_invalid_filter_error.phpt new file mode 100644 index 0000000000000..f543e4a69f5d1 --- /dev/null +++ b/ext/gd/tests/imagefilter_invalid_filter_error.phpt @@ -0,0 +1,16 @@ +--TEST-- +GH-20070: Testing wrong parameter passing in imagefilter() of GD library +--EXTENSIONS-- +gd +--FILE-- +getMessage(), "\n"; +} +?> +--EXPECT-- +ValueError: imagefilter(): Argument #2 ($filter) must be one of the IMG_FILTER_* filter constants 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/gmp/gmp.c b/ext/gmp/gmp.c index 8cf20c90fc7a2..b5451b8035e37 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -1535,7 +1535,7 @@ ZEND_FUNCTION(gmp_setbit) { zval *a_arg; zend_long index; - bool set = 1; + bool set = true; mpz_ptr gmpnum_a; if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol|b", &a_arg, gmp_ce, &index, &set) == FAILURE) { 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 465bbf3cd0949..d255711efbed9 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; } /* }}} */ @@ -369,7 +365,7 @@ static void php_hash_do_hash( RETURN_THROWS(); } if (isfilename) { - if (CHECK_NULL_PATH(data, data_len)) { + if (zend_char_has_nul_byte(data, data_len)) { zend_argument_value_error(1, "must not contain any null bytes"); RETURN_THROWS(); } @@ -512,7 +508,7 @@ static void php_hash_do_hash_hmac( } if (isfilename) { - if (CHECK_NULL_PATH(data, data_len)) { + if (zend_char_has_nul_byte(data, data_len)) { zend_argument_value_error(2, "must not contain any null bytes"); RETURN_THROWS(); } @@ -581,13 +577,13 @@ PHP_FUNCTION(hash_hmac) zend_string *algo; char *data, *key; size_t data_len, key_len; - bool raw_output = 0; + bool raw_output = false; if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sss|b", &algo, &data, &data_len, &key, &key_len, &raw_output) == FAILURE) { RETURN_THROWS(); } - php_hash_do_hash_hmac(return_value, algo, data, data_len, key, key_len, raw_output, 0); + php_hash_do_hash_hmac(return_value, algo, data, data_len, key, key_len, raw_output, false); } /* }}} */ @@ -598,13 +594,13 @@ PHP_FUNCTION(hash_hmac_file) zend_string *algo; char *data, *key; size_t data_len, key_len; - bool raw_output = 0; + bool raw_output = false; if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sss|b", &algo, &data, &data_len, &key, &key_len, &raw_output) == FAILURE) { RETURN_THROWS(); } - php_hash_do_hash_hmac(return_value, algo, data, data_len, key, key_len, raw_output, 1); + php_hash_do_hash_hmac(return_value, algo, data, data_len, key, key_len, raw_output, true); } /* }}} */ @@ -782,7 +778,7 @@ PHP_FUNCTION(hash_final) { zval *zhash; php_hashcontext_object *hash; - bool raw_output = 0; + bool raw_output = false; zend_string *digest; size_t digest_len; @@ -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(); } @@ -995,7 +989,7 @@ PHP_FUNCTION(hash_pbkdf2) unsigned char *computed_salt, *digest, *temp, *result, *K1, *K2 = NULL; zend_long loops, i, j, iterations, digest_length = 0, length = 0; size_t pass_len, salt_len = 0; - bool raw_output = 0; + bool raw_output = false; const php_hash_ops *ops; void *context; HashTable *args = NULL; @@ -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); */ } @@ -1222,9 +1227,9 @@ PHP_FUNCTION(mhash) } if (key) { - php_hash_do_hash_hmac(return_value, algo, data, data_len, key, key_len, 1, 0); + php_hash_do_hash_hmac(return_value, algo, data, data_len, key, key_len, true, false); } else { - php_hash_do_hash(return_value, algo, data, data_len, 1, 0, NULL); + php_hash_do_hash(return_value, algo, data, data_len, true, false, NULL); } if (algo) { @@ -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_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/hash/xxhash/xxhash.h b/ext/hash/xxhash/xxhash.h index 259371a3addd6..a18e8c762daaa 100644 --- a/ext/hash/xxhash/xxhash.h +++ b/ext/hash/xxhash/xxhash.h @@ -1,7 +1,7 @@ /* * xxHash - Extremely Fast Hash algorithm * Header File - * Copyright (C) 2012-2020 Yann Collet + * Copyright (C) 2012-2021 Yann Collet * * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) * @@ -32,49 +32,142 @@ * - xxHash homepage: https://www.xxhash.com * - xxHash source repository: https://github.com/Cyan4973/xxHash */ + /*! * @mainpage xxHash * + * xxHash is an extremely fast non-cryptographic hash algorithm, working at RAM speed + * limits. + * + * It is proposed in four flavors, in three families: + * 1. @ref XXH32_family + * - Classic 32-bit hash function. Simple, compact, and runs on almost all + * 32-bit and 64-bit systems. + * 2. @ref XXH64_family + * - Classic 64-bit adaptation of XXH32. Just as simple, and runs well on most + * 64-bit systems (but _not_ 32-bit systems). + * 3. @ref XXH3_family + * - Modern 64-bit and 128-bit hash function family which features improved + * strength and performance across the board, especially on smaller data. + * It benefits greatly from SIMD and 64-bit without requiring it. + * + * Benchmarks + * --- + * The reference system uses an Intel i7-9700K CPU, and runs Ubuntu x64 20.04. + * The open source benchmark program is compiled with clang v10.0 using -O3 flag. + * + * | Hash Name | ISA ext | Width | Large Data Speed | Small Data Velocity | + * | -------------------- | ------- | ----: | ---------------: | ------------------: | + * | XXH3_64bits() | @b AVX2 | 64 | 59.4 GB/s | 133.1 | + * | MeowHash | AES-NI | 128 | 58.2 GB/s | 52.5 | + * | XXH3_128bits() | @b AVX2 | 128 | 57.9 GB/s | 118.1 | + * | CLHash | PCLMUL | 64 | 37.1 GB/s | 58.1 | + * | XXH3_64bits() | @b SSE2 | 64 | 31.5 GB/s | 133.1 | + * | XXH3_128bits() | @b SSE2 | 128 | 29.6 GB/s | 118.1 | + * | RAM sequential read | | N/A | 28.0 GB/s | N/A | + * | ahash | AES-NI | 64 | 22.5 GB/s | 107.2 | + * | City64 | | 64 | 22.0 GB/s | 76.6 | + * | T1ha2 | | 64 | 22.0 GB/s | 99.0 | + * | City128 | | 128 | 21.7 GB/s | 57.7 | + * | FarmHash | AES-NI | 64 | 21.3 GB/s | 71.9 | + * | XXH64() | | 64 | 19.4 GB/s | 71.0 | + * | SpookyHash | | 64 | 19.3 GB/s | 53.2 | + * | Mum | | 64 | 18.0 GB/s | 67.0 | + * | CRC32C | SSE4.2 | 32 | 13.0 GB/s | 57.9 | + * | XXH32() | | 32 | 9.7 GB/s | 71.9 | + * | City32 | | 32 | 9.1 GB/s | 66.0 | + * | Blake3* | @b AVX2 | 256 | 4.4 GB/s | 8.1 | + * | Murmur3 | | 32 | 3.9 GB/s | 56.1 | + * | SipHash* | | 64 | 3.0 GB/s | 43.2 | + * | Blake3* | @b SSE2 | 256 | 2.4 GB/s | 8.1 | + * | HighwayHash | | 64 | 1.4 GB/s | 6.0 | + * | FNV64 | | 64 | 1.2 GB/s | 62.7 | + * | Blake2* | | 256 | 1.1 GB/s | 5.1 | + * | SHA1* | | 160 | 0.8 GB/s | 5.6 | + * | MD5* | | 128 | 0.6 GB/s | 7.8 | + * @note + * - Hashes which require a specific ISA extension are noted. SSE2 is also noted, + * even though it is mandatory on x64. + * - Hashes with an asterisk are cryptographic. Note that MD5 is non-cryptographic + * by modern standards. + * - Small data velocity is a rough average of algorithm's efficiency for small + * data. For more accurate information, see the wiki. + * - More benchmarks and strength tests are found on the wiki: + * https://github.com/Cyan4973/xxHash/wiki + * + * Usage + * ------ + * All xxHash variants use a similar API. Changing the algorithm is a trivial + * substitution. + * + * @pre + * For functions which take an input and length parameter, the following + * requirements are assumed: + * - The range from [`input`, `input + length`) is valid, readable memory. + * - The only exception is if the `length` is `0`, `input` may be `NULL`. + * - For C++, the objects must have the *TriviallyCopyable* property, as the + * functions access bytes directly as if it was an array of `unsigned char`. + * + * @anchor single_shot_example + * **Single Shot** + * + * These functions are stateless functions which hash a contiguous block of memory, + * immediately returning the result. They are the easiest and usually the fastest + * option. + * + * XXH32(), XXH64(), XXH3_64bits(), XXH3_128bits() + * + * @code{.c} + * #include + * #include "xxhash.h" + * + * // Example for a function which hashes a null terminated string with XXH32(). + * XXH32_hash_t hash_string(const char* string, XXH32_hash_t seed) + * { + * // NULL pointers are only valid if the length is zero + * size_t length = (string == NULL) ? 0 : strlen(string); + * return XXH32(string, length, seed); + * } + * @endcode + * + * @anchor streaming_example + * **Streaming** + * + * These groups of functions allow incremental hashing of unknown size, even + * more than what would fit in a size_t. + * + * XXH32_reset(), XXH64_reset(), XXH3_64bits_reset(), XXH3_128bits_reset() + * + * @code{.c} + * #include + * #include + * #include "xxhash.h" + * // Example for a function which hashes a FILE incrementally with XXH3_64bits(). + * XXH64_hash_t hashFile(FILE* f) + * { + * // Allocate a state struct. Do not just use malloc() or new. + * XXH3_state_t* state = XXH3_createState(); + * assert(state != NULL && "Out of memory!"); + * // Reset the state to start a new hashing session. + * XXH3_64bits_reset(state); + * char buffer[4096]; + * size_t count; + * // Read the file in chunks + * while ((count = fread(buffer, 1, sizeof(buffer), f)) != 0) { + * // Run update() as many times as necessary to process the data + * XXH3_64bits_update(state, buffer, count); + * } + * // Retrieve the finalized hash. This will not change the state. + * XXH64_hash_t result = XXH3_64bits_digest(state); + * // Free the state. Do not use free(). + * XXH3_freeState(state); + * return result; + * } + * @endcode + * * @file xxhash.h * xxHash prototypes and implementation */ -/* TODO: update */ -/* Notice extracted from xxHash homepage: - -xxHash is an extremely fast hash algorithm, running at RAM speed limits. -It also successfully passes all tests from the SMHasher suite. - -Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz) - -Name Speed Q.Score Author -xxHash 5.4 GB/s 10 -CrapWow 3.2 GB/s 2 Andrew -MurmurHash 3a 2.7 GB/s 10 Austin Appleby -SpookyHash 2.0 GB/s 10 Bob Jenkins -SBox 1.4 GB/s 9 Bret Mulvey -Lookup3 1.2 GB/s 9 Bob Jenkins -SuperFastHash 1.2 GB/s 1 Paul Hsieh -CityHash64 1.05 GB/s 10 Pike & Alakuijala -FNV 0.55 GB/s 5 Fowler, Noll, Vo -CRC32 0.43 GB/s 9 -MD5-32 0.33 GB/s 10 Ronald L. Rivest -SHA1-32 0.28 GB/s 10 - -Q.Score is a measure of quality of the hash function. -It depends on successfully passing SMHasher test set. -10 is a perfect score. - -Note: SMHasher's CRC32 implementation is not the fastest one. -Other speed-oriented implementations can be faster, -especially in combination with PCLMUL instruction: -https://fastcompression.blogspot.com/2019/03/presenting-xxh3.html?showComment=1552696407071#c3490092340461170735 - -A 64-bit version, named XXH64, is available since r35. -It offers much better speed, but for 64-bit applications only. -Name Speed on 64 bits Speed on 32 bits -XXH64 13.8 GB/s 1.9 GB/s -XXH32 6.8 GB/s 6.0 GB/s -*/ #if defined (__cplusplus) extern "C" { @@ -84,21 +177,80 @@ extern "C" { * INLINE mode ******************************/ /*! - * XXH_INLINE_ALL (and XXH_PRIVATE_API) + * @defgroup public Public API + * Contains details on the public xxHash functions. + * @{ + */ +#ifdef XXH_DOXYGEN +/*! + * @brief Gives access to internal state declaration, required for static allocation. + * + * Incompatible with dynamic linking, due to risks of ABI changes. + * + * Usage: + * @code{.c} + * #define XXH_STATIC_LINKING_ONLY + * #include "xxhash.h" + * @endcode + */ +# define XXH_STATIC_LINKING_ONLY +/* Do not undef XXH_STATIC_LINKING_ONLY for Doxygen */ + +/*! + * @brief Gives access to internal definitions. + * + * Usage: + * @code{.c} + * #define XXH_STATIC_LINKING_ONLY + * #define XXH_IMPLEMENTATION + * #include "xxhash.h" + * @endcode + */ +# define XXH_IMPLEMENTATION +/* Do not undef XXH_IMPLEMENTATION for Doxygen */ + +/*! + * @brief Exposes the implementation and marks all functions as `inline`. + * * Use these build macros to inline xxhash into the target unit. * Inlining improves performance on small inputs, especially when the length is * expressed as a compile-time constant: * - * https://fastcompression.blogspot.com/2018/03/xxhash-for-small-keys-impressive-power.html + * https://fastcompression.blogspot.com/2018/03/xxhash-for-small-keys-impressive-power.html * * It also keeps xxHash symbols private to the unit, so they are not exported. * * Usage: + * @code{.c} * #define XXH_INLINE_ALL * #include "xxhash.h" - * + * @endcode * Do not compile and link xxhash.o as a separate object, as it is not useful. */ +# define XXH_INLINE_ALL +# undef XXH_INLINE_ALL +/*! + * @brief Exposes the implementation without marking functions as inline. + */ +# define XXH_PRIVATE_API +# undef XXH_PRIVATE_API +/*! + * @brief Emulate a namespace by transparently prefixing all symbols. + * + * If you want to include _and expose_ xxHash functions from within your own + * library, but also want to avoid symbol collisions with other libraries which + * may also include xxHash, you can use @ref XXH_NAMESPACE to automatically prefix + * any public symbol from xxhash library with the value of @ref XXH_NAMESPACE + * (therefore, avoid empty or numeric values). + * + * Note that no change is required within the calling program as long as it + * includes `xxhash.h`: Regular symbol names will be automatically translated + * by this header. + */ +# define XXH_NAMESPACE /* YOUR NAME HERE */ +# undef XXH_NAMESPACE +#endif + #if (defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)) \ && !defined(XXH_INLINE_ALL_31684351384) /* this section should be traversed only once */ @@ -213,23 +365,15 @@ extern "C" { # undef XXHASH_H_STATIC_13879238742 #endif /* XXH_INLINE_ALL || XXH_PRIVATE_API */ - - /* **************************************************************** * Stable API *****************************************************************/ #ifndef XXHASH_H_5627135585666179 #define XXHASH_H_5627135585666179 1 - -/*! - * @defgroup public Public API - * Contains details on the public xxHash functions. - * @{ - */ -/* specific declaration modes for Windows */ +/*! @brief Marks a global symbol. */ #if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API) -# if defined(_WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT)) +# if defined(WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT)) # ifdef XXH_EXPORT # define XXH_PUBLIC_API __declspec(dllexport) # elif XXH_IMPORT @@ -240,24 +384,6 @@ extern "C" { # endif #endif -#ifdef XXH_DOXYGEN -/*! - * @brief Emulate a namespace by transparently prefixing all symbols. - * - * If you want to include _and expose_ xxHash functions from within your own - * library, but also want to avoid symbol collisions with other libraries which - * may also include xxHash, you can use XXH_NAMESPACE to automatically prefix - * any public symbol from xxhash library with the value of XXH_NAMESPACE - * (therefore, avoid empty or numeric values). - * - * Note that no change is required within the calling program as long as it - * includes `xxhash.h`: Regular symbol names will be automatically translated - * by this header. - */ -# define XXH_NAMESPACE /* YOUR NAME HERE */ -# undef XXH_NAMESPACE -#endif - #ifdef XXH_NAMESPACE # define XXH_CAT(A,B) A##B # define XXH_NAME2(A,B) XXH_CAT(A,B) @@ -317,12 +443,40 @@ extern "C" { #endif +/* ************************************* +* Compiler specifics +***************************************/ + +/* specific declaration modes for Windows */ +#if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API) +# if defined(WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT)) +# ifdef XXH_EXPORT +# define XXH_PUBLIC_API __declspec(dllexport) +# elif XXH_IMPORT +# define XXH_PUBLIC_API __declspec(dllimport) +# endif +# else +# define XXH_PUBLIC_API /* do nothing */ +# endif +#endif + +#if defined (__GNUC__) +# define XXH_CONSTF __attribute__((const)) +# define XXH_PUREF __attribute__((pure)) +# define XXH_MALLOCF __attribute__((malloc)) +#else +# define XXH_CONSTF /* disable */ +# define XXH_PUREF +# define XXH_MALLOCF +#endif + /* ************************************* * Version ***************************************/ #define XXH_VERSION_MAJOR 0 #define XXH_VERSION_MINOR 8 -#define XXH_VERSION_RELEASE 1 +#define XXH_VERSION_RELEASE 2 +/*! @brief Version number, encoded as two digits each */ #define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE) /*! @@ -331,16 +485,22 @@ extern "C" { * This is mostly useful when xxHash is compiled as a shared library, * since the returned value comes from the library, as opposed to header file. * - * @return `XXH_VERSION_NUMBER` of the invoked library. + * @return @ref XXH_VERSION_NUMBER of the invoked library. */ -XXH_PUBLIC_API unsigned XXH_versionNumber (void); +XXH_PUBLIC_API XXH_CONSTF unsigned XXH_versionNumber (void); /* **************************** * Common basic types ******************************/ #include /* size_t */ -typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode; +/*! + * @brief Exit code for the streaming API. + */ +typedef enum { + XXH_OK = 0, /*!< OK */ + XXH_ERROR /*!< Error */ +} XXH_errorcode; /*-********************************************************************** @@ -364,29 +524,27 @@ typedef uint32_t XXH32_hash_t; # include # if UINT_MAX == 0xFFFFFFFFUL typedef unsigned int XXH32_hash_t; +# elif ULONG_MAX == 0xFFFFFFFFUL + typedef unsigned long XXH32_hash_t; # else -# if ULONG_MAX == 0xFFFFFFFFUL - typedef unsigned long XXH32_hash_t; -# else -# error "unsupported platform: need a 32-bit type" -# endif +# error "unsupported platform: need a 32-bit type" # endif #endif /*! * @} * - * @defgroup xxh32_family XXH32 family + * @defgroup XXH32_family XXH32 family * @ingroup public * Contains functions used in the classic 32-bit xxHash algorithm. * * @note * XXH32 is useful for older platforms, with no or poor 64-bit performance. - * Note that @ref xxh3_family provides competitive speed - * for both 32-bit and 64-bit systems, and offers true 64/128 bit hash results. + * Note that the @ref XXH3_family provides competitive speed for both 32-bit + * and 64-bit systems, and offers true 64/128 bit hash results. * - * @see @ref xxh64_family, @ref xxh3_family : Other xxHash families - * @see @ref xxh32_impl for implementation details + * @see @ref XXH64_family, @ref XXH3_family : Other xxHash families + * @see @ref XXH32_impl for implementation details * @{ */ @@ -395,6 +553,8 @@ typedef uint32_t XXH32_hash_t; * * Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark): 5.4 GB/s * + * See @ref single_shot_example "Single Shot Example" for an example. + * * @param input The block of data to be hashed, at least @p length bytes in size. * @param length The length of @p input, in bytes. * @param seed The 32-bit seed to alter the hash's output predictably. @@ -412,8 +572,9 @@ typedef uint32_t XXH32_hash_t; * @see * XXH32_createState(), XXH32_update(), XXH32_digest(): Streaming version. */ -XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t length, XXH32_hash_t seed); +XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32 (const void* input, size_t length, XXH32_hash_t seed); +#ifndef XXH_NO_STREAM /*! * Streaming functions generate the xxHash value from an incremental input. * This method is slower than single-call functions, due to state management. @@ -436,32 +597,7 @@ XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t length, XXH32_hash_ * * When done, release the state using `XXH*_freeState()`. * - * Example code for incrementally hashing a file: - * @code{.c} - * #include - * #include - * #define BUFFER_SIZE 256 - * - * // Note: XXH64 and XXH3 use the same interface. - * XXH32_hash_t - * hashFile(FILE* stream) - * { - * XXH32_state_t* state; - * unsigned char buf[BUFFER_SIZE]; - * size_t amt; - * XXH32_hash_t hash; - * - * state = XXH32_createState(); // Create a state - * assert(state != NULL); // Error check here - * XXH32_reset(state, 0xbaad5eed); // Reset state with our seed - * while ((amt = fread(buf, 1, sizeof(buf), stream)) != 0) { - * XXH32_update(state, buf, amt); // Hash the file in chunks - * } - * hash = XXH32_digest(state); // Finalize the hash - * XXH32_freeState(state); // Clean up - * return hash; - * } - * @endcode + * @see streaming_example at the top of @ref xxhash.h for an example. */ /*! @@ -478,7 +614,7 @@ typedef struct XXH32_state_s XXH32_state_t; * Must be freed with XXH32_freeState(). * @return An allocated XXH32_state_t on success, `NULL` on failure. */ -XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void); +XXH_PUBLIC_API XXH_MALLOCF XXH32_state_t* XXH32_createState(void); /*! * @brief Frees an @ref XXH32_state_t. * @@ -546,7 +682,8 @@ XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* * * @return The calculated xxHash32 value from that state. */ -XXH_PUBLIC_API XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr); +XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr); +#endif /* !XXH_NO_STREAM */ /******* Canonical representation *******/ @@ -597,43 +734,72 @@ XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t * * @return The converted hash. */ -XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src); +XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src); +/*! @cond Doxygen ignores this part */ #ifdef __has_attribute # define XXH_HAS_ATTRIBUTE(x) __has_attribute(x) #else # define XXH_HAS_ATTRIBUTE(x) 0 #endif +/*! @endcond */ +/*! @cond Doxygen ignores this part */ +/* + * C23 __STDC_VERSION__ number hasn't been specified yet. For now + * leave as `201711L` (C17 + 1). + * TODO: Update to correct value when its been specified. + */ +#define XXH_C23_VN 201711L +/*! @endcond */ + +/*! @cond Doxygen ignores this part */ /* C-language Attributes are added in C23. */ -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ > 201710L) && defined(__has_c_attribute) +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= XXH_C23_VN) && defined(__has_c_attribute) # define XXH_HAS_C_ATTRIBUTE(x) __has_c_attribute(x) #else # define XXH_HAS_C_ATTRIBUTE(x) 0 #endif +/*! @endcond */ +/*! @cond Doxygen ignores this part */ #if defined(__cplusplus) && defined(__has_cpp_attribute) # define XXH_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) #else # define XXH_HAS_CPP_ATTRIBUTE(x) 0 #endif +/*! @endcond */ +/*! @cond Doxygen ignores this part */ /* -Define XXH_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute -introduced in CPP17 and C23. -CPP17 : https://en.cppreference.com/w/cpp/language/attributes/fallthrough -C23 : https://en.cppreference.com/w/c/language/attributes/fallthrough -*/ -#if XXH_HAS_C_ATTRIBUTE(x) -# define XXH_FALLTHROUGH [[fallthrough]] -#elif XXH_HAS_CPP_ATTRIBUTE(x) + * Define XXH_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute + * introduced in CPP17 and C23. + * CPP17 : https://en.cppreference.com/w/cpp/language/attributes/fallthrough + * C23 : https://en.cppreference.com/w/c/language/attributes/fallthrough + */ +#if XXH_HAS_C_ATTRIBUTE(fallthrough) || XXH_HAS_CPP_ATTRIBUTE(fallthrough) # define XXH_FALLTHROUGH [[fallthrough]] #elif XXH_HAS_ATTRIBUTE(__fallthrough__) -# define XXH_FALLTHROUGH __attribute__ ((fallthrough)) +# define XXH_FALLTHROUGH __attribute__ ((__fallthrough__)) #else -# define XXH_FALLTHROUGH +# define XXH_FALLTHROUGH /* fallthrough */ #endif +/*! @endcond */ + +/*! @cond Doxygen ignores this part */ +/* + * Define XXH_NOESCAPE for annotated pointers in public API. + * https://clang.llvm.org/docs/AttributeReference.html#noescape + * As of writing this, only supported by clang. + */ +#if XXH_HAS_ATTRIBUTE(noescape) +# define XXH_NOESCAPE __attribute__((noescape)) +#else +# define XXH_NOESCAPE +#endif +/*! @endcond */ + /*! * @} @@ -671,7 +837,7 @@ typedef uint64_t XXH64_hash_t; /*! * @} * - * @defgroup xxh64_family XXH64 family + * @defgroup XXH64_family XXH64 family * @ingroup public * @{ * Contains functions used in the classic 64-bit xxHash algorithm. @@ -682,7 +848,6 @@ typedef uint64_t XXH64_hash_t; * It provides better speed for systems with vector processing capabilities. */ - /*! * @brief Calculates the 64-bit hash of @p input using xxHash64. * @@ -706,32 +871,131 @@ typedef uint64_t XXH64_hash_t; * @see * XXH64_createState(), XXH64_update(), XXH64_digest(): Streaming version. */ -XXH_PUBLIC_API XXH64_hash_t XXH64(const void* input, size_t length, XXH64_hash_t seed); +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed); /******* Streaming *******/ +#ifndef XXH_NO_STREAM /*! * @brief The opaque state struct for the XXH64 streaming API. * * @see XXH64_state_s for details. */ typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */ -XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void); + +/*! + * @brief Allocates an @ref XXH64_state_t. + * + * Must be freed with XXH64_freeState(). + * @return An allocated XXH64_state_t on success, `NULL` on failure. + */ +XXH_PUBLIC_API XXH_MALLOCF XXH64_state_t* XXH64_createState(void); + +/*! + * @brief Frees an @ref XXH64_state_t. + * + * Must be allocated with XXH64_createState(). + * @param statePtr A pointer to an @ref XXH64_state_t allocated with @ref XXH64_createState(). + * @return XXH_OK. + */ XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr); -XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dst_state, const XXH64_state_t* src_state); -XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, XXH64_hash_t seed); -XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length); -XXH_PUBLIC_API XXH64_hash_t XXH64_digest (const XXH64_state_t* statePtr); +/*! + * @brief Copies one @ref XXH64_state_t to another. + * + * @param dst_state The state to copy to. + * @param src_state The state to copy from. + * @pre + * @p dst_state and @p src_state must not be `NULL` and must not overlap. + */ +XXH_PUBLIC_API void XXH64_copyState(XXH_NOESCAPE XXH64_state_t* dst_state, const XXH64_state_t* src_state); +/*! + * @brief Resets an @ref XXH64_state_t to begin a new hash. + * + * This function resets and seeds a state. Call it before @ref XXH64_update(). + * + * @param statePtr The state struct to reset. + * @param seed The 64-bit seed to alter the hash result predictably. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. + */ +XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH_NOESCAPE XXH64_state_t* statePtr, XXH64_hash_t seed); + +/*! + * @brief Consumes a block of @p input to an @ref XXH64_state_t. + * + * Call this to incrementally consume blocks of data. + * + * @param statePtr The state struct to update. + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. + */ +XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH_NOESCAPE XXH64_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length); + +/*! + * @brief Returns the calculated hash value from an @ref XXH64_state_t. + * + * @note + * Calling XXH64_digest() will not affect @p statePtr, so you can update, + * digest, and update again. + * + * @param statePtr The state struct to calculate the hash from. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return The calculated xxHash64 value from that state. + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_digest (XXH_NOESCAPE const XXH64_state_t* statePtr); +#endif /* !XXH_NO_STREAM */ /******* Canonical representation *******/ + +/*! + * @brief Canonical (big endian) representation of @ref XXH64_hash_t. + */ typedef struct { unsigned char digest[sizeof(XXH64_hash_t)]; } XXH64_canonical_t; -XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash); -XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src); + +/*! + * @brief Converts an @ref XXH64_hash_t to a big endian @ref XXH64_canonical_t. + * + * @param dst The @ref XXH64_canonical_t pointer to be stored to. + * @param hash The @ref XXH64_hash_t to be converted. + * + * @pre + * @p dst must not be `NULL`. + */ +XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH_NOESCAPE XXH64_canonical_t* dst, XXH64_hash_t hash); + +/*! + * @brief Converts an @ref XXH64_canonical_t to a native @ref XXH64_hash_t. + * + * @param src The @ref XXH64_canonical_t to convert. + * + * @pre + * @p src must not be `NULL`. + * + * @return The converted hash. + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_canonical_t* src); + +#ifndef XXH_NO_XXH3 /*! * @} * ************************************************************************ - * @defgroup xxh3_family XXH3 family + * @defgroup XXH3_family XXH3 family * @ingroup public * @{ * @@ -751,16 +1015,26 @@ XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src * * XXH3's speed benefits greatly from SIMD and 64-bit arithmetic, * but does not require it. - * Any 32-bit and 64-bit targets that can run XXH32 smoothly - * can run XXH3 at competitive speeds, even without vector support. - * Further details are explained in the implementation. - * - * Optimized implementations are provided for AVX512, AVX2, SSE2, NEON, POWER8, - * ZVector and scalar targets. This can be controlled via the XXH_VECTOR macro. + * Most 32-bit and 64-bit targets that can run XXH32 smoothly can run XXH3 + * at competitive speeds, even without vector support. Further details are + * explained in the implementation. + * + * XXH3 has a fast scalar implementation, but it also includes accelerated SIMD + * implementations for many common platforms: + * - AVX512 + * - AVX2 + * - SSE2 + * - ARM NEON + * - WebAssembly SIMD128 + * - POWER8 VSX + * - s390x ZVector + * This can be controlled via the @ref XXH_VECTOR macro, but it automatically + * selects the best version according to predefined macros. For the x86 family, an + * automatic runtime dispatcher is included separately in @ref xxh_x86dispatch.c. * * XXH3 implementation is portable: * it has a generic C90 formulation that can be compiled on any platform, - * all implementations generage exactly the same hash value on all platforms. + * all implementations generate exactly the same hash value on all platforms. * Starting from v0.8.0, it's also labelled "stable", meaning that * any future version will also generate the same hash value. * @@ -772,24 +1046,42 @@ XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src * * The API supports one-shot hashing, streaming mode, and custom secrets. */ - /*-********************************************************************** * XXH3 64-bit variant ************************************************************************/ -/* XXH3_64bits(): - * default 64-bit variant, using default secret and default seed of 0. - * It's the fastest variant. */ -XXH_PUBLIC_API XXH64_hash_t XXH3_64bits(const void* data, size_t len); +/*! + * @brief 64-bit unseeded variant of XXH3. + * + * This is equivalent to @ref XXH3_64bits_withSeed() with a seed of 0, however + * it may have slightly better performance due to constant propagation of the + * defaults. + * + * @see + * XXH32(), XXH64(), XXH3_128bits(): equivalent for the other xxHash algorithms + * @see + * XXH3_64bits_withSeed(), XXH3_64bits_withSecret(): other seeding variants + * @see + * XXH3_64bits_reset(), XXH3_64bits_update(), XXH3_64bits_digest(): Streaming version. + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits(XXH_NOESCAPE const void* input, size_t length); -/* - * XXH3_64bits_withSeed(): - * This variant generates a custom secret on the fly - * based on default secret altered using the `seed` value. +/*! + * @brief 64-bit seeded variant of XXH3 + * + * This variant generates a custom secret on the fly based on default secret + * altered using the `seed` value. + * * While this operation is decently fast, note that it's not completely free. - * Note: seed==0 produces the same results as XXH3_64bits(). + * + * @note + * seed == 0 produces the same results as @ref XXH3_64bits(). + * + * @param input The data to hash + * @param length The length + * @param seed The 64-bit seed to alter the state. */ -XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSeed(const void* data, size_t len, XXH64_hash_t seed); +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSeed(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed); /*! * The bare minimum size for a custom secret. @@ -800,8 +1092,9 @@ XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSeed(const void* data, size_t len, X */ #define XXH3_SECRET_SIZE_MIN 136 -/* - * XXH3_64bits_withSecret(): +/*! + * @brief 64-bit variant of XXH3 with a custom "secret". + * * It's possible to provide any blob of bytes as a "secret" to generate the hash. * This makes it more difficult for an external actor to prepare an intentional collision. * The main condition is that secretSize *must* be large enough (>= XXH3_SECRET_SIZE_MIN). @@ -817,10 +1110,11 @@ XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSeed(const void* data, size_t len, X * This is not necessarily the case when using the blob of bytes directly * because, when hashing _small_ inputs, only a portion of the secret is employed. */ -XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSecret(const void* data, size_t len, const void* secret, size_t secretSize); +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSecret(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize); /******* Streaming *******/ +#ifndef XXH_NO_STREAM /* * Streaming requires state maintenance. * This operation costs memory and CPU. @@ -834,23 +1128,53 @@ XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSecret(const void* data, size_t len, * @see XXH3_state_s for details. */ typedef struct XXH3_state_s XXH3_state_t; -XXH_PUBLIC_API XXH3_state_t* XXH3_createState(void); +XXH_PUBLIC_API XXH_MALLOCF XXH3_state_t* XXH3_createState(void); XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr); -XXH_PUBLIC_API void XXH3_copyState(XXH3_state_t* dst_state, const XXH3_state_t* src_state); -/* - * XXH3_64bits_reset(): - * Initialize with default parameters. - * digest will be equivalent to `XXH3_64bits()`. +/*! + * @brief Copies one @ref XXH3_state_t to another. + * + * @param dst_state The state to copy to. + * @param src_state The state to copy from. + * @pre + * @p dst_state and @p src_state must not be `NULL` and must not overlap. */ -XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset(XXH3_state_t* statePtr); -/* - * XXH3_64bits_reset_withSeed(): - * Generate a custom secret from `seed`, and store it into `statePtr`. - * digest will be equivalent to `XXH3_64bits_withSeed()`. +XXH_PUBLIC_API void XXH3_copyState(XXH_NOESCAPE XXH3_state_t* dst_state, XXH_NOESCAPE const XXH3_state_t* src_state); + +/*! + * @brief Resets an @ref XXH3_state_t to begin a new hash. + * + * This function resets `statePtr` and generate a secret with default parameters. Call it before @ref XXH3_64bits_update(). + * Digest will be equivalent to `XXH3_64bits()`. + * + * @param statePtr The state struct to reset. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. + * */ -XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSeed(XXH3_state_t* statePtr, XXH64_hash_t seed); -/* +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr); + +/*! + * @brief Resets an @ref XXH3_state_t with 64-bit seed to begin a new hash. + * + * This function resets `statePtr` and generate a secret from `seed`. Call it before @ref XXH3_64bits_update(). + * Digest will be equivalent to `XXH3_64bits_withSeed()`. + * + * @param statePtr The state struct to reset. + * @param seed The 64-bit seed to alter the state. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. + * + */ +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed); + +/*! * XXH3_64bits_reset_withSecret(): * `secret` is referenced, it _must outlive_ the hash streaming session. * Similar to one-shot API, `secretSize` must be >= `XXH3_SECRET_SIZE_MIN`, @@ -859,10 +1183,44 @@ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSeed(XXH3_state_t* statePtr, * When in doubt about the randomness of a candidate `secret`, * consider employing `XXH3_generateSecret()` instead (see below). */ -XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecret(XXH3_state_t* statePtr, const void* secret, size_t secretSize); +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize); -XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update (XXH3_state_t* statePtr, const void* input, size_t length); -XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_digest (const XXH3_state_t* statePtr); +/*! + * @brief Consumes a block of @p input to an @ref XXH3_state_t. + * + * Call this to incrementally consume blocks of data. + * + * @param statePtr The state struct to update. + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. + */ +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length); + +/*! + * @brief Returns the calculated XXH3 64-bit hash value from an @ref XXH3_state_t. + * + * @note + * Calling XXH3_64bits_digest() will not affect @p statePtr, so you can update, + * digest, and update again. + * + * @param statePtr The state struct to calculate the hash from. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return The calculated XXH3 64-bit hash value from that state. + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_digest (XXH_NOESCAPE const XXH3_state_t* statePtr); +#endif /* !XXH_NO_STREAM */ /* note : canonical representation of XXH3 is the same as XXH64 * since they both produce XXH64_hash_t values */ @@ -883,11 +1241,31 @@ typedef struct { XXH64_hash_t high64; /*!< `value >> 64` */ } XXH128_hash_t; -XXH_PUBLIC_API XXH128_hash_t XXH3_128bits(const void* data, size_t len); -XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSeed(const void* data, size_t len, XXH64_hash_t seed); -XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSecret(const void* data, size_t len, const void* secret, size_t secretSize); +/*! + * @brief Unseeded 128-bit variant of XXH3 + * + * The 128-bit variant of XXH3 has more strength, but it has a bit of overhead + * for shorter inputs. + * + * This is equivalent to @ref XXH3_128bits_withSeed() with a seed of 0, however + * it may have slightly better performance due to constant propagation of the + * defaults. + * + * @see + * XXH32(), XXH64(), XXH3_64bits(): equivalent for the other xxHash algorithms + * @see + * XXH3_128bits_withSeed(), XXH3_128bits_withSecret(): other seeding variants + * @see + * XXH3_128bits_reset(), XXH3_128bits_update(), XXH3_128bits_digest(): Streaming version. + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits(XXH_NOESCAPE const void* data, size_t len); +/*! @brief Seeded 128-bit variant of XXH3. @see XXH3_64bits_withSeed(). */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSeed(XXH_NOESCAPE const void* data, size_t len, XXH64_hash_t seed); +/*! @brief Custom secret 128-bit variant of XXH3. @see XXH3_64bits_withSecret(). */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSecret(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize); /******* Streaming *******/ +#ifndef XXH_NO_STREAM /* * Streaming requires state maintenance. * This operation costs memory and CPU. @@ -900,12 +1278,77 @@ XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSecret(const void* data, size_t le * All reset and streaming functions have same meaning as their 64-bit counterpart. */ -XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset(XXH3_state_t* statePtr); -XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSeed(XXH3_state_t* statePtr, XXH64_hash_t seed); -XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecret(XXH3_state_t* statePtr, const void* secret, size_t secretSize); +/*! + * @brief Resets an @ref XXH3_state_t to begin a new hash. + * + * This function resets `statePtr` and generate a secret with default parameters. Call it before @ref XXH3_128bits_update(). + * Digest will be equivalent to `XXH3_128bits()`. + * + * @param statePtr The state struct to reset. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. + * + */ +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr); + +/*! + * @brief Resets an @ref XXH3_state_t with 64-bit seed to begin a new hash. + * + * This function resets `statePtr` and generate a secret from `seed`. Call it before @ref XXH3_128bits_update(). + * Digest will be equivalent to `XXH3_128bits_withSeed()`. + * + * @param statePtr The state struct to reset. + * @param seed The 64-bit seed to alter the state. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. + * + */ +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed); +/*! @brief Custom secret 128-bit variant of XXH3. @see XXH_64bits_reset_withSecret(). */ +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize); + +/*! + * @brief Consumes a block of @p input to an @ref XXH3_state_t. + * + * Call this to incrementally consume blocks of data. + * + * @param statePtr The state struct to update. + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. + */ +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length); -XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update (XXH3_state_t* statePtr, const void* input, size_t length); -XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_digest (const XXH3_state_t* statePtr); +/*! + * @brief Returns the calculated XXH3 128-bit hash value from an @ref XXH3_state_t. + * + * @note + * Calling XXH3_128bits_digest() will not affect @p statePtr, so you can update, + * digest, and update again. + * + * @param statePtr The state struct to calculate the hash from. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return The calculated XXH3 128-bit hash value from that state. + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE const XXH3_state_t* statePtr); +#endif /* !XXH_NO_STREAM */ /* Following helper functions make it possible to compare XXH128_hast_t values. * Since XXH128_hash_t is a structure, this capability is not offered by the language. @@ -915,26 +1358,48 @@ XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_digest (const XXH3_state_t* statePtr); * XXH128_isEqual(): * Return: 1 if `h1` and `h2` are equal, 0 if they are not. */ -XXH_PUBLIC_API int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2); +XXH_PUBLIC_API XXH_PUREF int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2); /*! - * XXH128_cmp(): - * + * @brief Compares two @ref XXH128_hash_t * This comparator is compatible with stdlib's `qsort()`/`bsearch()`. * - * return: >0 if *h128_1 > *h128_2 - * =0 if *h128_1 == *h128_2 - * <0 if *h128_1 < *h128_2 + * @return: >0 if *h128_1 > *h128_2 + * =0 if *h128_1 == *h128_2 + * <0 if *h128_1 < *h128_2 */ -XXH_PUBLIC_API int XXH128_cmp(const void* h128_1, const void* h128_2); +XXH_PUBLIC_API XXH_PUREF int XXH128_cmp(XXH_NOESCAPE const void* h128_1, XXH_NOESCAPE const void* h128_2); /******* Canonical representation *******/ typedef struct { unsigned char digest[sizeof(XXH128_hash_t)]; } XXH128_canonical_t; -static zend_always_inline void XXH128_canonicalFromHash(XXH128_canonical_t* dst, XXH128_hash_t hash); -XXH_PUBLIC_API XXH128_hash_t XXH128_hashFromCanonical(const XXH128_canonical_t* src); +/*! + * @brief Converts an @ref XXH128_hash_t to a big endian @ref XXH128_canonical_t. + * + * @param dst The @ref XXH128_canonical_t pointer to be stored to. + * @param hash The @ref XXH128_hash_t to be converted. + * + * @pre + * @p dst must not be `NULL`. + */ +XXH_PUBLIC_API void XXH128_canonicalFromHash(XXH_NOESCAPE XXH128_canonical_t* dst, XXH128_hash_t hash); + +/*! + * @brief Converts an @ref XXH128_canonical_t to a native @ref XXH128_hash_t. + * + * @param src The @ref XXH128_canonical_t to convert. + * + * @pre + * @p src must not be `NULL`. + * + * @return The converted hash. + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t* src); + + +#endif /* !XXH_NO_XXH3 */ #endif /* XXH_NO_LONG_LONG */ /*! @@ -978,7 +1443,7 @@ struct XXH32_state_s { XXH32_hash_t v[4]; /*!< Accumulator lanes */ XXH32_hash_t mem32[4]; /*!< Internal buffer for partial reads. Treated as unsigned char[16]. */ XXH32_hash_t memsize; /*!< Amount of data in @ref mem32 */ - XXH32_hash_t reserved; /*!< Reserved field. Do not read or write to it, it may be removed. */ + XXH32_hash_t reserved; /*!< Reserved field. Do not read nor write to it. */ }; /* typedef'd to XXH32_state_t */ @@ -1002,9 +1467,11 @@ struct XXH64_state_s { XXH64_hash_t mem64[4]; /*!< Internal buffer for partial reads. Treated as unsigned char[32]. */ XXH32_hash_t memsize; /*!< Amount of data in @ref mem64 */ XXH32_hash_t reserved32; /*!< Reserved field, needed for padding anyways*/ - XXH64_hash_t reserved64; /*!< Reserved field. Do not read or write to it, it may be removed. */ + XXH64_hash_t reserved64; /*!< Reserved field. Do not read or write to it. */ }; /* typedef'd to XXH64_state_t */ +#ifndef XXH_NO_XXH3 + #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* >= C11 */ # include # define XXH_ALIGN(n) alignas(n) @@ -1038,6 +1505,7 @@ struct XXH64_state_s { #define XXH3_INTERNALBUFFER_SIZE 256 /*! + * @internal * @brief Default size of the secret buffer (and @ref XXH3_kSecret). * * This is the size used in @ref XXH3_kSecret and the seeded functions. @@ -1070,7 +1538,7 @@ struct XXH64_state_s { */ struct XXH3_state_s { XXH_ALIGN_MEMBER(64, XXH64_hash_t acc[8]); - /*!< The 8 accumulators. Similar to `vN` in @ref XXH32_state_s::v1 and @ref XXH64_state_s */ + /*!< The 8 accumulators. See @ref XXH32_state_s::v and @ref XXH64_state_s::v */ XXH_ALIGN_MEMBER(64, unsigned char customSecret[XXH3_SECRET_DEFAULT_SIZE]); /*!< Used to store a custom secret generated from a seed. */ XXH_ALIGN_MEMBER(64, unsigned char buffer[XXH3_INTERNALBUFFER_SIZE]); @@ -1110,69 +1578,119 @@ struct XXH3_state_s { * Note that this doesn't prepare the state for a streaming operation, * it's still necessary to use XXH3_NNbits_reset*() afterwards. */ -#define XXH3_INITSTATE(XXH3_state_ptr) { (XXH3_state_ptr)->seed = 0; } +#define XXH3_INITSTATE(XXH3_state_ptr) \ + do { \ + XXH3_state_t* tmp_xxh3_state_ptr = (XXH3_state_ptr); \ + tmp_xxh3_state_ptr->seed = 0; \ + tmp_xxh3_state_ptr->extSecret = NULL; \ + } while(0) -/* XXH128() : +/*! * simple alias to pre-selected XXH3_128bits variant */ -XXH_PUBLIC_API XXH128_hash_t XXH128(const void* data, size_t len, XXH64_hash_t seed); +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128(XXH_NOESCAPE const void* data, size_t len, XXH64_hash_t seed); /* === Experimental API === */ /* Symbols defined below must be considered tied to a specific library version. */ -/* +/*! * XXH3_generateSecret(): * * Derive a high-entropy secret from any user-defined content, named customSeed. * The generated secret can be used in combination with `*_withSecret()` functions. - * The `_withSecret()` variants are useful to provide a higher level of protection than 64-bit seed, - * as it becomes much more difficult for an external actor to guess how to impact the calculation logic. + * The `_withSecret()` variants are useful to provide a higher level of protection + * than 64-bit seed, as it becomes much more difficult for an external actor to + * guess how to impact the calculation logic. * * The function accepts as input a custom seed of any length and any content, - * and derives from it a high-entropy secret of length @secretSize - * into an already allocated buffer @secretBuffer. - * @secretSize must be >= XXH3_SECRET_SIZE_MIN + * and derives from it a high-entropy secret of length @p secretSize into an + * already allocated buffer @p secretBuffer. * * The generated secret can then be used with any `*_withSecret()` variant. - * Functions `XXH3_128bits_withSecret()`, `XXH3_64bits_withSecret()`, - * `XXH3_128bits_reset_withSecret()` and `XXH3_64bits_reset_withSecret()` + * The functions @ref XXH3_128bits_withSecret(), @ref XXH3_64bits_withSecret(), + * @ref XXH3_128bits_reset_withSecret() and @ref XXH3_64bits_reset_withSecret() * are part of this list. They all accept a `secret` parameter - * which must be large enough for implementation reasons (>= XXH3_SECRET_SIZE_MIN) + * which must be large enough for implementation reasons (>= @ref XXH3_SECRET_SIZE_MIN) * _and_ feature very high entropy (consist of random-looking bytes). - * These conditions can be a high bar to meet, so - * XXH3_generateSecret() can be employed to ensure proper quality. + * These conditions can be a high bar to meet, so @ref XXH3_generateSecret() can + * be employed to ensure proper quality. * - * customSeed can be anything. It can have any size, even small ones, - * and its content can be anything, even "poor entropy" sources such as a bunch of zeroes. - * The resulting `secret` will nonetheless provide all required qualities. + * @p customSeed can be anything. It can have any size, even small ones, + * and its content can be anything, even "poor entropy" sources such as a bunch + * of zeroes. The resulting `secret` will nonetheless provide all required qualities. + * + * @pre + * - @p secretSize must be >= @ref XXH3_SECRET_SIZE_MIN + * - When @p customSeedSize > 0, supplying NULL as customSeed is undefined behavior. * - * When customSeedSize > 0, supplying NULL as customSeed is undefined behavior. + * Example code: + * @code{.c} + * #include + * #include + * #include + * #define XXH_STATIC_LINKING_ONLY // expose unstable API + * #include "xxhash.h" + * // Hashes argv[2] using the entropy from argv[1]. + * int main(int argc, char* argv[]) + * { + * char secret[XXH3_SECRET_SIZE_MIN]; + * if (argv != 3) { return 1; } + * XXH3_generateSecret(secret, sizeof(secret), argv[1], strlen(argv[1])); + * XXH64_hash_t h = XXH3_64bits_withSecret( + * argv[2], strlen(argv[2]), + * secret, sizeof(secret) + * ); + * printf("%016llx\n", (unsigned long long) h); + * } + * @endcode */ -XXH_PUBLIC_API XXH_errorcode XXH3_generateSecret(void* secretBuffer, size_t secretSize, const void* customSeed, size_t customSeedSize); - +XXH_PUBLIC_API XXH_errorcode XXH3_generateSecret(XXH_NOESCAPE void* secretBuffer, size_t secretSize, XXH_NOESCAPE const void* customSeed, size_t customSeedSize); -/* - * XXH3_generateSecret_fromSeed(): - * - * Generate the same secret as the _withSeed() variants. - * - * The resulting secret has a length of XXH3_SECRET_DEFAULT_SIZE (necessarily). - * @secretBuffer must be already allocated, of size at least XXH3_SECRET_DEFAULT_SIZE bytes. +/*! + * @brief Generate the same secret as the _withSeed() variants. * * The generated secret can be used in combination with *`*_withSecret()` and `_withSecretandSeed()` variants. - * This generator is notably useful in combination with `_withSecretandSeed()`, - * as a way to emulate a faster `_withSeed()` variant. + * + * Example C++ `std::string` hash class: + * @code{.cpp} + * #include + * #define XXH_STATIC_LINKING_ONLY // expose unstable API + * #include "xxhash.h" + * // Slow, seeds each time + * class HashSlow { + * XXH64_hash_t seed; + * public: + * HashSlow(XXH64_hash_t s) : seed{s} {} + * size_t operator()(const std::string& x) const { + * return size_t{XXH3_64bits_withSeed(x.c_str(), x.length(), seed)}; + * } + * }; + * // Fast, caches the seeded secret for future uses. + * class HashFast { + * unsigned char secret[XXH3_SECRET_SIZE_MIN]; + * public: + * HashFast(XXH64_hash_t s) { + * XXH3_generateSecret_fromSeed(secret, seed); + * } + * size_t operator()(const std::string& x) const { + * return size_t{ + * XXH3_64bits_withSecret(x.c_str(), x.length(), secret, sizeof(secret)) + * }; + * } + * }; + * @endcode + * @param secretBuffer A writable buffer of @ref XXH3_SECRET_SIZE_MIN bytes + * @param seed The seed to seed the state. */ -XXH_PUBLIC_API void XXH3_generateSecret_fromSeed(void* secretBuffer, XXH64_hash_t seed); +XXH_PUBLIC_API void XXH3_generateSecret_fromSeed(XXH_NOESCAPE void* secretBuffer, XXH64_hash_t seed); -/* - * *_withSecretandSeed() : +/*! * These variants generate hash values using either - * @seed for "short" keys (< XXH3_MIDSIZE_MAX = 240 bytes) - * or @secret for "large" keys (>= XXH3_MIDSIZE_MAX). + * @p seed for "short" keys (< XXH3_MIDSIZE_MAX = 240 bytes) + * or @p secret for "large" keys (>= XXH3_MIDSIZE_MAX). * * This generally benefits speed, compared to `_withSeed()` or `_withSecret()`. * `_withSeed()` has to generate the secret on the fly for "large" keys. @@ -1181,7 +1699,7 @@ XXH_PUBLIC_API void XXH3_generateSecret_fromSeed(void* secretBuffer, XXH64_hash_ * which requires more instructions than _withSeed() variants. * Therefore, _withSecretandSeed variant combines the best of both worlds. * - * When @secret has been generated by XXH3_generateSecret_fromSeed(), + * When @p secret has been generated by XXH3_generateSecret_fromSeed(), * this variant produces *exactly* the same results as `_withSeed()` variant, * hence offering only a pure speed benefit on "large" input, * by skipping the need to regenerate the secret for every large input. @@ -1190,32 +1708,34 @@ XXH_PUBLIC_API void XXH3_generateSecret_fromSeed(void* secretBuffer, XXH64_hash_ * for example with XXH3_64bits(), which then becomes the seed, * and then employ both the seed and the secret in _withSecretandSeed(). * On top of speed, an added benefit is that each bit in the secret - * has a 50% chance to swap each bit in the output, - * via its impact to the seed. + * has a 50% chance to swap each bit in the output, via its impact to the seed. + * * This is not guaranteed when using the secret directly in "small data" scenarios, * because only portions of the secret are employed for small data. */ -XXH_PUBLIC_API XXH64_hash_t -XXH3_64bits_withSecretandSeed(const void* data, size_t len, - const void* secret, size_t secretSize, +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t +XXH3_64bits_withSecretandSeed(XXH_NOESCAPE const void* data, size_t len, + XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed); - -XXH_PUBLIC_API XXH128_hash_t -XXH3_128bits_withSecretandSeed(const void* data, size_t len, - const void* secret, size_t secretSize, +/*! @copydoc XXH3_64bits_withSecretandSeed() */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t +XXH3_128bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t length, + XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed64); - +#ifndef XXH_NO_STREAM +/*! @copydoc XXH3_64bits_withSecretandSeed() */ XXH_PUBLIC_API XXH_errorcode -XXH3_64bits_reset_withSecretandSeed(XXH3_state_t* statePtr, - const void* secret, size_t secretSize, +XXH3_64bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, + XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed64); - +/*! @copydoc XXH3_64bits_withSecretandSeed() */ XXH_PUBLIC_API XXH_errorcode -XXH3_128bits_reset_withSecretandSeed(XXH3_state_t* statePtr, - const void* secret, size_t secretSize, +XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, + XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed64); +#endif /* !XXH_NO_STREAM */ - +#endif /* !XXH_NO_XXH3 */ #endif /* XXH_NO_LONG_LONG */ #if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) # define XXH_IMPLEMENTATION @@ -1269,7 +1789,7 @@ XXH3_128bits_reset_withSecretandSeed(XXH3_state_t* statePtr, /*! * @brief Define this to disable 64-bit code. * - * Useful if only using the @ref xxh32_family and you have a strict C90 compiler. + * Useful if only using the @ref XXH32_family and you have a strict C90 compiler. */ # define XXH_NO_LONG_LONG # undef XXH_NO_LONG_LONG /* don't actually */ @@ -1292,7 +1812,7 @@ XXH3_128bits_reset_withSecretandSeed(XXH3_state_t* statePtr, * Use `memcpy()`. Safe and portable. Note that most modern compilers will * eliminate the function call and treat it as an unaligned access. * - * - `XXH_FORCE_MEMORY_ACCESS=1`: `__attribute__((packed))` + * - `XXH_FORCE_MEMORY_ACCESS=1`: `__attribute__((aligned(1)))` * @par * Depends on compiler extensions and is therefore not portable. * This method is safe _if_ your compiler supports it, @@ -1312,19 +1832,47 @@ XXH3_128bits_reset_withSecretandSeed(XXH3_state_t* statePtr, * inline small `memcpy()` calls, and it might also be faster on big-endian * systems which lack a native byteswap instruction. However, some compilers * will emit literal byteshifts even if the target supports unaligned access. - * . + * * * @warning * Methods 1 and 2 rely on implementation-defined behavior. Use these with * care, as what works on one compiler/platform/optimization level may cause * another to read garbage data or even crash. * - * See http://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html for details. + * See https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html for details. * * Prefer these methods in priority order (0 > 3 > 1 > 2) */ # define XXH_FORCE_MEMORY_ACCESS 0 +/*! + * @def XXH_SIZE_OPT + * @brief Controls how much xxHash optimizes for size. + * + * xxHash, when compiled, tends to result in a rather large binary size. This + * is mostly due to heavy usage to forced inlining and constant folding of the + * @ref XXH3_family to increase performance. + * + * However, some developers prefer size over speed. This option can + * significantly reduce the size of the generated code. When using the `-Os` + * or `-Oz` options on GCC or Clang, this is defined to 1 by default, + * otherwise it is defined to 0. + * + * Most of these size optimizations can be controlled manually. + * + * This is a number from 0-2. + * - `XXH_SIZE_OPT` == 0: Default. xxHash makes no size optimizations. Speed + * comes first. + * - `XXH_SIZE_OPT` == 1: Default for `-Os` and `-Oz`. xxHash is more + * conservative and disables hacks that increase code size. It implies the + * options @ref XXH_NO_INLINE_HINTS == 1, @ref XXH_FORCE_ALIGN_CHECK == 0, + * and @ref XXH3_NEON_LANES == 8 if they are not already defined. + * - `XXH_SIZE_OPT` == 2: xxHash tries to make itself as small as possible. + * Performance may cry. For example, the single shot functions just use the + * streaming API. + */ +# define XXH_SIZE_OPT 0 + /*! * @def XXH_FORCE_ALIGN_CHECK * @brief If defined to non-zero, adds a special path for aligned inputs (XXH32() @@ -1346,9 +1894,11 @@ XXH3_128bits_reset_withSecretandSeed(XXH3_state_t* statePtr, * * In these cases, the alignment check can be removed by setting this macro to 0. * Then the code will always use unaligned memory access. - * Align check is automatically disabled on x86, x64 & arm64, + * Align check is automatically disabled on x86, x64, ARM64, and some ARM chips * which are platforms known to offer good unaligned memory accesses performance. * + * It is also disabled by default when @ref XXH_SIZE_OPT >= 1. + * * This option does not affect XXH3 (only XXH32 and XXH64). */ # define XXH_FORCE_ALIGN_CHECK 0 @@ -1370,8 +1920,8 @@ XXH3_128bits_reset_withSecretandSeed(XXH3_state_t* statePtr, * XXH_NO_INLINE_HINTS marks all internal functions as static, giving the * compiler full control on whether to inline or not. * - * When not optimizing (-O0), optimizing for size (-Os, -Oz), or using - * -fno-inline with GCC or Clang, this will automatically be defined. + * When not optimizing (-O0), using `-fno-inline` with GCC or Clang, or if + * @ref XXH_SIZE_OPT >= 1, this will automatically be defined. */ # define XXH_NO_INLINE_HINTS 0 @@ -1413,34 +1963,45 @@ XXH3_128bits_reset_withSecretandSeed(XXH3_state_t* statePtr, */ # define XXH_OLD_NAMES # undef XXH_OLD_NAMES /* don't actually use, it is ugly. */ + +/*! + * @def XXH_NO_STREAM + * @brief Disables the streaming API. + * + * When xxHash is not inlined and the streaming functions are not used, disabling + * the streaming functions can improve code size significantly, especially with + * the @ref XXH3_family which tends to make constant folded copies of itself. + */ +# define XXH_NO_STREAM +# undef XXH_NO_STREAM /* don't actually */ #endif /* XXH_DOXYGEN */ /*! * @} */ #ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ - /* prefer __packed__ structures (method 1) for gcc on armv7+ and mips */ -# if !defined(__clang__) && \ -( \ - (defined(__INTEL_COMPILER) && !defined(_WIN32)) || \ - ( \ - defined(__GNUC__) && ( \ - (defined(__ARM_ARCH) && __ARM_ARCH >= 7) || \ - ( \ - defined(__mips__) && \ - (__mips <= 5 || __mips_isa_rev < 6) && \ - (!defined(__mips16) || defined(__mips_mips16e2)) \ - ) \ - ) \ - ) \ -) + /* prefer __packed__ structures (method 1) for GCC + * < ARMv7 with unaligned access (e.g. Raspbian armhf) still uses byte shifting, so we use memcpy + * which for some reason does unaligned loads. */ +# if defined(__GNUC__) && !(defined(__ARM_ARCH) && __ARM_ARCH < 7 && defined(__ARM_FEATURE_UNALIGNED)) # define XXH_FORCE_MEMORY_ACCESS 1 # endif #endif +#ifndef XXH_SIZE_OPT + /* default to 1 for -Os or -Oz */ +# if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE_SIZE__) +# define XXH_SIZE_OPT 1 +# else +# define XXH_SIZE_OPT 0 +# endif +#endif + #ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */ -# if defined(__i386) || defined(__x86_64__) || defined(__aarch64__) \ - || defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM64) /* visual */ + /* don't check on sizeopt, x86, aarch64, or arm when unaligned access is available */ +# if XXH_SIZE_OPT >= 1 || \ + defined(__i386) || defined(__x86_64__) || defined(__aarch64__) || defined(__ARM_FEATURE_UNALIGNED) \ + || defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM64) || defined(_M_ARM) /* visual */ # define XXH_FORCE_ALIGN_CHECK 0 # else # define XXH_FORCE_ALIGN_CHECK 1 @@ -1448,8 +2009,7 @@ XXH3_128bits_reset_withSecretandSeed(XXH3_state_t* statePtr, #endif #ifndef XXH_NO_INLINE_HINTS -# if defined(__OPTIMIZE_SIZE__) /* -Os, -Oz */ \ - || defined(__NO_INLINE__) /* -O0, -fno-inline */ +# if XXH_SIZE_OPT >= 1 || defined(__NO_INLINE__) /* -O0, -fno-inline */ # define XXH_NO_INLINE_HINTS 1 # else # define XXH_NO_INLINE_HINTS 0 @@ -1479,6 +2039,24 @@ XXH3_128bits_reset_withSecretandSeed(XXH3_state_t* statePtr, /* ************************************* * Includes & Memory related functions ***************************************/ +#if defined(XXH_NO_STREAM) +/* nothing */ +#elif defined(XXH_NO_STDLIB) + +/* When requesting to disable any mention of stdlib, + * the library loses the ability to invoked malloc / free. + * In practice, it means that functions like `XXH*_createState()` + * will always fail, and return NULL. + * This flag is useful in situations where + * xxhash.h is integrated into some kernel, embedded or limited environment + * without access to dynamic allocation. + */ + +static XXH_CONSTF void* XXH_malloc(size_t s) { (void)s; return NULL; } +static void XXH_free(void* p) { (void)p; } + +#else + /* * Modify the local functions below should you wish to use * different memory routines for malloc() and free() @@ -1489,7 +2067,7 @@ XXH3_128bits_reset_withSecretandSeed(XXH3_state_t* statePtr, * @internal * @brief Modify this function to use a different routine than malloc(). */ -static void* XXH_malloc(size_t s) { return malloc(s); } +static XXH_MALLOCF void* XXH_malloc(size_t s) { return malloc(s); } /*! * @internal @@ -1497,6 +2075,8 @@ static void* XXH_malloc(size_t s) { return malloc(s); } */ static void XXH_free(void* p) { free(p); } +#endif /* XXH_NO_STDLIB */ + #include /*! @@ -1571,7 +2151,11 @@ static void* XXH_memcpy(void* dest, const void* src, size_t size) # include /* note: can still be disabled with NDEBUG */ # define XXH_ASSERT(c) assert(c) #else -# define XXH_ASSERT(c) ((void)0) +# if defined(__INTEL_COMPILER) +# define XXH_ASSERT(c) XXH_ASSUME((unsigned char) (c)) +# else +# define XXH_ASSERT(c) XXH_ASSUME(c) +# endif #endif /* note: use after variable declarations */ @@ -1603,11 +2187,19 @@ static void* XXH_memcpy(void* dest, const void* src, size_t size) * XXH3_initCustomSecret_scalar(). */ #if defined(__GNUC__) || defined(__clang__) -# define XXH_COMPILER_GUARD(var) __asm__ __volatile__("" : "+r" (var)) +# define XXH_COMPILER_GUARD(var) __asm__("" : "+r" (var)) #else # define XXH_COMPILER_GUARD(var) ((void)0) #endif +/* Specifically for NEON vectors which use the "w" constraint, on + * Clang. */ +#if defined(__clang__) && defined(__ARM_ARCH) && !defined(__wasm__) +# define XXH_COMPILER_GUARD_CLANG_NEON(var) __asm__("" : "+w" (var)) +#else +# define XXH_COMPILER_GUARD_CLANG_NEON(var) ((void)0) +#endif + /* ************************************* * Basic Types ***************************************/ @@ -1622,6 +2214,7 @@ static void* XXH_memcpy(void* dest, const void* src, size_t size) typedef XXH32_hash_t xxh_u32; #ifdef XXH_OLD_NAMES +# warning "XXH_OLD_NAMES is planned to be removed starting v0.9. If the program depends on it, consider moving away from it by employing newer type names directly" # define BYTE xxh_u8 # define U8 xxh_u8 # define U32 xxh_u32 @@ -1695,25 +2288,26 @@ static xxh_u32 XXH_read32(const void* memPtr) { return *(const xxh_u32*) memPtr; #elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) /* - * __pack instructions are safer but compiler specific, hence potentially - * problematic for some compilers. - * - * Currently only defined for GCC and ICC. + * __attribute__((aligned(1))) is supported by gcc and clang. Originally the + * documentation claimed that it only increased the alignment, but actually it + * can decrease it on gcc, clang, and icc: + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69502, + * https://gcc.godbolt.org/z/xYez1j67Y. */ #ifdef XXH_OLD_NAMES typedef union { xxh_u32 u32; } __attribute__((packed)) unalign; #endif static xxh_u32 XXH_read32(const void* ptr) { - typedef union { xxh_u32 u32; } __attribute__((packed)) xxh_unalign; - return ((const xxh_unalign*)ptr)->u32; + typedef __attribute__((aligned(1))) xxh_u32 xxh_unalign32; + return *((const xxh_unalign32*)ptr); } #else /* * Portable and safe solution. Generally efficient. - * see: http://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html + * see: https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html */ static xxh_u32 XXH_read32(const void* memPtr) { @@ -1789,6 +2383,51 @@ static int XXH_isLittleEndian(void) # define XXH_HAS_BUILTIN(x) 0 #endif + + +/* + * C23 and future versions have standard "unreachable()". + * Once it has been implemented reliably we can add it as an + * additional case: + * + * ``` + * #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= XXH_C23_VN) + * # include + * # ifdef unreachable + * # define XXH_UNREACHABLE() unreachable() + * # endif + * #endif + * ``` + * + * Note C++23 also has std::unreachable() which can be detected + * as follows: + * ``` + * #if defined(__cpp_lib_unreachable) && (__cpp_lib_unreachable >= 202202L) + * # include + * # define XXH_UNREACHABLE() std::unreachable() + * #endif + * ``` + * NB: `__cpp_lib_unreachable` is defined in the `` header. + * We don't use that as including `` in `extern "C"` blocks + * doesn't work on GCC12 + */ + +#if XXH_HAS_BUILTIN(__builtin_unreachable) +# define XXH_UNREACHABLE() __builtin_unreachable() + +#elif defined(_MSC_VER) +# define XXH_UNREACHABLE() __assume(0) + +#else +# define XXH_UNREACHABLE() +#endif + +#if XXH_HAS_BUILTIN(__builtin_assume) +# define XXH_ASSUME(c) __builtin_assume(c) +#else +# define XXH_ASSUME(c) if (!(c)) { XXH_UNREACHABLE(); } +#endif + /*! * @internal * @def XXH_rotl32(x,r) @@ -1911,8 +2550,10 @@ XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; } *********************************************************************/ /*! * @} - * @defgroup xxh32_impl XXH32 implementation + * @defgroup XXH32_impl XXH32 implementation * @ingroup impl + * + * Details on the XXH32 implementation. * @{ */ /* #define instead of static const, to be used as initializers */ @@ -1946,7 +2587,7 @@ static xxh_u32 XXH32_round(xxh_u32 acc, xxh_u32 input) acc += input * XXH_PRIME32_2; acc = XXH_rotl32(acc, 13); acc *= XXH_PRIME32_1; -#if (defined(__SSE4_1__) || defined(__aarch64__)) && !defined(XXH_ENABLE_AUTOVECTORIZE) +#if (defined(__SSE4_1__) || defined(__aarch64__) || defined(__wasm_simd128__)) && !defined(XXH_ENABLE_AUTOVECTORIZE) /* * UGLY HACK: * A compiler fence is the only thing that prevents GCC and Clang from @@ -1976,9 +2617,12 @@ static xxh_u32 XXH32_round(xxh_u32 acc, xxh_u32 input) * can load data, while v3 can multiply. SSE forces them to operate * together. * - * This is also enabled on AArch64, as Clang autovectorizes it incorrectly - * and it is pointless writing a NEON implementation that is basically the - * same speed as scalar for XXH32. + * This is also enabled on AArch64, as Clang is *very aggressive* in vectorizing + * the loop. NEON is only faster on the A53, and with the newer cores, it is less + * than half the speed. + * + * Additionally, this is used on WASM SIMD128 because it JITs to the same + * SIMD instructions and has the same issue. */ XXH_COMPILER_GUARD(acc); #endif @@ -1992,17 +2636,17 @@ static xxh_u32 XXH32_round(xxh_u32 acc, xxh_u32 input) * The final mix ensures that all input bits have a chance to impact any bit in * the output digest, resulting in an unbiased distribution. * - * @param h32 The hash to avalanche. + * @param hash The hash to avalanche. * @return The avalanched hash. */ -static xxh_u32 XXH32_avalanche(xxh_u32 h32) +static xxh_u32 XXH32_avalanche(xxh_u32 hash) { - h32 ^= h32 >> 15; - h32 *= XXH_PRIME32_2; - h32 ^= h32 >> 13; - h32 *= XXH_PRIME32_3; - h32 ^= h32 >> 16; - return(h32); + hash ^= hash >> 15; + hash *= XXH_PRIME32_2; + hash ^= hash >> 13; + hash *= XXH_PRIME32_3; + hash ^= hash >> 16; + return hash; } #define XXH_get32bits(p) XXH_readLE32_align(p, align) @@ -2015,24 +2659,25 @@ static xxh_u32 XXH32_avalanche(xxh_u32 h32) * This final stage will digest them to ensure that all input bytes are present * in the final mix. * - * @param h32 The hash to finalize. + * @param hash The hash to finalize. * @param ptr The pointer to the remaining input. * @param len The remaining length, modulo 16. * @param align Whether @p ptr is aligned. * @return The finalized hash. + * @see XXH64_finalize(). */ -static xxh_u32 -XXH32_finalize(xxh_u32 h32, const xxh_u8* ptr, size_t len, XXH_alignment align) +static XXH_PUREF xxh_u32 +XXH32_finalize(xxh_u32 hash, const xxh_u8* ptr, size_t len, XXH_alignment align) { -#define XXH_PROCESS1 do { \ - h32 += (*ptr++) * XXH_PRIME32_5; \ - h32 = XXH_rotl32(h32, 11) * XXH_PRIME32_1; \ +#define XXH_PROCESS1 do { \ + hash += (*ptr++) * XXH_PRIME32_5; \ + hash = XXH_rotl32(hash, 11) * XXH_PRIME32_1; \ } while (0) -#define XXH_PROCESS4 do { \ - h32 += XXH_get32bits(ptr) * XXH_PRIME32_3; \ - ptr += 4; \ - h32 = XXH_rotl32(h32, 17) * XXH_PRIME32_4; \ +#define XXH_PROCESS4 do { \ + hash += XXH_get32bits(ptr) * XXH_PRIME32_3; \ + ptr += 4; \ + hash = XXH_rotl32(hash, 17) * XXH_PRIME32_4; \ } while (0) if (ptr==NULL) XXH_ASSERT(len == 0); @@ -2048,49 +2693,49 @@ XXH32_finalize(xxh_u32 h32, const xxh_u8* ptr, size_t len, XXH_alignment align) XXH_PROCESS1; --len; } - return XXH32_avalanche(h32); + return XXH32_avalanche(hash); } else { switch(len&15) /* or switch(bEnd - p) */ { case 12: XXH_PROCESS4; - XXH_FALLTHROUGH; + XXH_FALLTHROUGH; /* fallthrough */ case 8: XXH_PROCESS4; - XXH_FALLTHROUGH; + XXH_FALLTHROUGH; /* fallthrough */ case 4: XXH_PROCESS4; - return XXH32_avalanche(h32); + return XXH32_avalanche(hash); case 13: XXH_PROCESS4; - XXH_FALLTHROUGH; + XXH_FALLTHROUGH; /* fallthrough */ case 9: XXH_PROCESS4; - XXH_FALLTHROUGH; + XXH_FALLTHROUGH; /* fallthrough */ case 5: XXH_PROCESS4; XXH_PROCESS1; - return XXH32_avalanche(h32); + return XXH32_avalanche(hash); case 14: XXH_PROCESS4; - XXH_FALLTHROUGH; + XXH_FALLTHROUGH; /* fallthrough */ case 10: XXH_PROCESS4; - XXH_FALLTHROUGH; + XXH_FALLTHROUGH; /* fallthrough */ case 6: XXH_PROCESS4; XXH_PROCESS1; XXH_PROCESS1; - return XXH32_avalanche(h32); + return XXH32_avalanche(hash); case 15: XXH_PROCESS4; - XXH_FALLTHROUGH; + XXH_FALLTHROUGH; /* fallthrough */ case 11: XXH_PROCESS4; - XXH_FALLTHROUGH; + XXH_FALLTHROUGH; /* fallthrough */ case 7: XXH_PROCESS4; - XXH_FALLTHROUGH; + XXH_FALLTHROUGH; /* fallthrough */ case 3: XXH_PROCESS1; - XXH_FALLTHROUGH; + XXH_FALLTHROUGH; /* fallthrough */ case 2: XXH_PROCESS1; - XXH_FALLTHROUGH; + XXH_FALLTHROUGH; /* fallthrough */ case 1: XXH_PROCESS1; - XXH_FALLTHROUGH; - case 0: return XXH32_avalanche(h32); + XXH_FALLTHROUGH; /* fallthrough */ + case 0: return XXH32_avalanche(hash); } XXH_ASSERT(0); - return h32; /* reaching this point is deemed impossible */ + return hash; /* reaching this point is deemed impossible */ } } @@ -2110,7 +2755,7 @@ XXH32_finalize(xxh_u32 h32, const xxh_u8* ptr, size_t len, XXH_alignment align) * @param align Whether @p input is aligned. * @return The calculated hash. */ -XXH_FORCE_INLINE xxh_u32 +XXH_FORCE_INLINE XXH_PUREF xxh_u32 XXH32_endian_align(const xxh_u8* input, size_t len, xxh_u32 seed, XXH_alignment align) { xxh_u32 h32; @@ -2143,10 +2788,10 @@ XXH32_endian_align(const xxh_u8* input, size_t len, xxh_u32 seed, XXH_alignment return XXH32_finalize(h32, input, len&15, align); } -/*! @ingroup xxh32_family */ +/*! @ingroup XXH32_family */ XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t len, XXH32_hash_t seed) { -#if 0 +#if !defined(XXH_NO_STREAM) && XXH_SIZE_OPT >= 2 /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ XXH32_state_t state; XXH32_reset(&state, seed); @@ -2165,42 +2810,39 @@ XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t len, XXH32_hash_t s /******* Hash streaming *******/ -/*! - * @ingroup xxh32_family - */ +#ifndef XXH_NO_STREAM +/*! @ingroup XXH32_family */ XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void) { return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t)); } -/*! @ingroup xxh32_family */ +/*! @ingroup XXH32_family */ XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr) { XXH_free(statePtr); return XXH_OK; } -/*! @ingroup xxh32_family */ +/*! @ingroup XXH32_family */ XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dstState, const XXH32_state_t* srcState) { XXH_memcpy(dstState, srcState, sizeof(*dstState)); } -/*! @ingroup xxh32_family */ +/*! @ingroup XXH32_family */ XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, XXH32_hash_t seed) { - XXH32_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ - memset(&state, 0, sizeof(state)); - state.v[0] = seed + XXH_PRIME32_1 + XXH_PRIME32_2; - state.v[1] = seed + XXH_PRIME32_2; - state.v[2] = seed + 0; - state.v[3] = seed - XXH_PRIME32_1; - /* do not write into reserved, planned to be removed in a future version */ - XXH_memcpy(statePtr, &state, sizeof(state) - sizeof(state.reserved)); + XXH_ASSERT(statePtr != NULL); + memset(statePtr, 0, sizeof(*statePtr)); + statePtr->v[0] = seed + XXH_PRIME32_1 + XXH_PRIME32_2; + statePtr->v[1] = seed + XXH_PRIME32_2; + statePtr->v[2] = seed + 0; + statePtr->v[3] = seed - XXH_PRIME32_1; return XXH_OK; } -/*! @ingroup xxh32_family */ +/*! @ingroup XXH32_family */ XXH_PUBLIC_API XXH_errorcode XXH32_update(XXH32_state_t* state, const void* input, size_t len) { @@ -2255,7 +2897,7 @@ XXH32_update(XXH32_state_t* state, const void* input, size_t len) } -/*! @ingroup xxh32_family */ +/*! @ingroup XXH32_family */ XXH_PUBLIC_API XXH32_hash_t XXH32_digest(const XXH32_state_t* state) { xxh_u32 h32; @@ -2273,12 +2915,12 @@ XXH_PUBLIC_API XXH32_hash_t XXH32_digest(const XXH32_state_t* state) return XXH32_finalize(h32, (const xxh_u8*)state->mem32, state->memsize, XXH_aligned); } - +#endif /* !XXH_NO_STREAM */ /******* Canonical representation *******/ /*! - * @ingroup xxh32_family + * @ingroup XXH32_family * The default return values from XXH functions are unsigned 32 and 64 bit * integers. * @@ -2297,7 +2939,7 @@ XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash); XXH_memcpy(dst, &hash, sizeof(*dst)); } -/*! @ingroup xxh32_family */ +/*! @ingroup XXH32_family */ XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src) { return XXH_readBE32(src); @@ -2338,25 +2980,26 @@ static xxh_u64 XXH_read64(const void* memPtr) #elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) /* - * __pack instructions are safer, but compiler specific, hence potentially - * problematic for some compilers. - * - * Currently only defined for GCC and ICC. + * __attribute__((aligned(1))) is supported by gcc and clang. Originally the + * documentation claimed that it only increased the alignment, but actually it + * can decrease it on gcc, clang, and icc: + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69502, + * https://gcc.godbolt.org/z/xYez1j67Y. */ #ifdef XXH_OLD_NAMES typedef union { xxh_u32 u32; xxh_u64 u64; } __attribute__((packed)) unalign64; #endif static xxh_u64 XXH_read64(const void* ptr) { - typedef union { xxh_u32 u32; xxh_u64 u64; } __attribute__((packed)) xxh_unalign64; - return ((const xxh_unalign64*)ptr)->u64; + typedef __attribute__((aligned(1))) xxh_u64 xxh_unalign64; + return *((const xxh_unalign64*)ptr); } #else /* * Portable and safe solution. Generally efficient. - * see: http://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html + * see: https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html */ static xxh_u64 XXH_read64(const void* memPtr) { @@ -2440,8 +3083,10 @@ XXH_readLE64_align(const void* ptr, XXH_alignment align) /******* xxh64 *******/ /*! * @} - * @defgroup xxh64_impl XXH64 implementation + * @defgroup XXH64_impl XXH64 implementation * @ingroup impl + * + * Details on the XXH64 implementation. * @{ */ /* #define rather that static const, to be used as initializers */ @@ -2459,6 +3104,7 @@ XXH_readLE64_align(const void* ptr, XXH_alignment align) # define PRIME64_5 XXH_PRIME64_5 #endif +/*! @copydoc XXH32_round */ static xxh_u64 XXH64_round(xxh_u64 acc, xxh_u64 input) { acc += input * XXH_PRIME64_2; @@ -2475,43 +3121,59 @@ static xxh_u64 XXH64_mergeRound(xxh_u64 acc, xxh_u64 val) return acc; } -static xxh_u64 XXH64_avalanche(xxh_u64 h64) +/*! @copydoc XXH32_avalanche */ +static xxh_u64 XXH64_avalanche(xxh_u64 hash) { - h64 ^= h64 >> 33; - h64 *= XXH_PRIME64_2; - h64 ^= h64 >> 29; - h64 *= XXH_PRIME64_3; - h64 ^= h64 >> 32; - return h64; + hash ^= hash >> 33; + hash *= XXH_PRIME64_2; + hash ^= hash >> 29; + hash *= XXH_PRIME64_3; + hash ^= hash >> 32; + return hash; } #define XXH_get64bits(p) XXH_readLE64_align(p, align) -static xxh_u64 -XXH64_finalize(xxh_u64 h64, const xxh_u8* ptr, size_t len, XXH_alignment align) +/*! + * @internal + * @brief Processes the last 0-31 bytes of @p ptr. + * + * There may be up to 31 bytes remaining to consume from the input. + * This final stage will digest them to ensure that all input bytes are present + * in the final mix. + * + * @param hash The hash to finalize. + * @param ptr The pointer to the remaining input. + * @param len The remaining length, modulo 32. + * @param align Whether @p ptr is aligned. + * @return The finalized hash + * @see XXH32_finalize(). + */ +static XXH_PUREF xxh_u64 +XXH64_finalize(xxh_u64 hash, const xxh_u8* ptr, size_t len, XXH_alignment align) { if (ptr==NULL) XXH_ASSERT(len == 0); len &= 31; while (len >= 8) { xxh_u64 const k1 = XXH64_round(0, XXH_get64bits(ptr)); ptr += 8; - h64 ^= k1; - h64 = XXH_rotl64(h64,27) * XXH_PRIME64_1 + XXH_PRIME64_4; + hash ^= k1; + hash = XXH_rotl64(hash,27) * XXH_PRIME64_1 + XXH_PRIME64_4; len -= 8; } if (len >= 4) { - h64 ^= (xxh_u64)(XXH_get32bits(ptr)) * XXH_PRIME64_1; + hash ^= (xxh_u64)(XXH_get32bits(ptr)) * XXH_PRIME64_1; ptr += 4; - h64 = XXH_rotl64(h64, 23) * XXH_PRIME64_2 + XXH_PRIME64_3; + hash = XXH_rotl64(hash, 23) * XXH_PRIME64_2 + XXH_PRIME64_3; len -= 4; } while (len > 0) { - h64 ^= (*ptr++) * XXH_PRIME64_5; - h64 = XXH_rotl64(h64, 11) * XXH_PRIME64_1; + hash ^= (*ptr++) * XXH_PRIME64_5; + hash = XXH_rotl64(hash, 11) * XXH_PRIME64_1; --len; } - return XXH64_avalanche(h64); + return XXH64_avalanche(hash); } #ifdef XXH_OLD_NAMES @@ -2524,7 +3186,15 @@ XXH64_finalize(xxh_u64 h64, const xxh_u8* ptr, size_t len, XXH_alignment align) # undef XXH_PROCESS8_64 #endif -XXH_FORCE_INLINE xxh_u64 +/*! + * @internal + * @brief The implementation for @ref XXH64(). + * + * @param input , len , seed Directly passed from @ref XXH64(). + * @param align Whether @p input is aligned. + * @return The calculated hash. + */ +XXH_FORCE_INLINE XXH_PUREF xxh_u64 XXH64_endian_align(const xxh_u8* input, size_t len, xxh_u64 seed, XXH_alignment align) { xxh_u64 h64; @@ -2561,10 +3231,10 @@ XXH64_endian_align(const xxh_u8* input, size_t len, xxh_u64 seed, XXH_alignment } -/*! @ingroup xxh64_family */ -XXH_PUBLIC_API XXH64_hash_t XXH64 (const void* input, size_t len, XXH64_hash_t seed) +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API XXH64_hash_t XXH64 (XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed) { -#if 0 +#if !defined(XXH_NO_STREAM) && XXH_SIZE_OPT >= 2 /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ XXH64_state_t state; XXH64_reset(&state, seed); @@ -2582,42 +3252,40 @@ XXH_PUBLIC_API XXH64_hash_t XXH64 (const void* input, size_t len, XXH64_hash_t s } /******* Hash Streaming *******/ - -/*! @ingroup xxh64_family*/ +#ifndef XXH_NO_STREAM +/*! @ingroup XXH64_family*/ XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void) { return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t)); } -/*! @ingroup xxh64_family */ +/*! @ingroup XXH64_family */ XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr) { XXH_free(statePtr); return XXH_OK; } -/*! @ingroup xxh64_family */ -XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dstState, const XXH64_state_t* srcState) +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API void XXH64_copyState(XXH_NOESCAPE XXH64_state_t* dstState, const XXH64_state_t* srcState) { XXH_memcpy(dstState, srcState, sizeof(*dstState)); } -/*! @ingroup xxh64_family */ -XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, XXH64_hash_t seed) +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH_NOESCAPE XXH64_state_t* statePtr, XXH64_hash_t seed) { - XXH64_state_t state; /* use a local state to memcpy() in order to avoid strict-aliasing warnings */ - memset(&state, 0, sizeof(state)); - state.v[0] = seed + XXH_PRIME64_1 + XXH_PRIME64_2; - state.v[1] = seed + XXH_PRIME64_2; - state.v[2] = seed + 0; - state.v[3] = seed - XXH_PRIME64_1; - /* do not write into reserved64, might be removed in a future version */ - XXH_memcpy(statePtr, &state, sizeof(state) - sizeof(state.reserved64)); + XXH_ASSERT(statePtr != NULL); + memset(statePtr, 0, sizeof(*statePtr)); + statePtr->v[0] = seed + XXH_PRIME64_1 + XXH_PRIME64_2; + statePtr->v[1] = seed + XXH_PRIME64_2; + statePtr->v[2] = seed + 0; + statePtr->v[3] = seed - XXH_PRIME64_1; return XXH_OK; } -/*! @ingroup xxh64_family */ +/*! @ingroup XXH64_family */ XXH_PUBLIC_API XXH_errorcode -XXH64_update (XXH64_state_t* state, const void* input, size_t len) +XXH64_update (XXH_NOESCAPE XXH64_state_t* state, XXH_NOESCAPE const void* input, size_t len) { if (input==NULL) { XXH_ASSERT(len == 0); @@ -2667,8 +3335,8 @@ XXH64_update (XXH64_state_t* state, const void* input, size_t len) } -/*! @ingroup xxh64_family */ -XXH_PUBLIC_API XXH64_hash_t XXH64_digest(const XXH64_state_t* state) +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API XXH64_hash_t XXH64_digest(XXH_NOESCAPE const XXH64_state_t* state) { xxh_u64 h64; @@ -2686,20 +3354,20 @@ XXH_PUBLIC_API XXH64_hash_t XXH64_digest(const XXH64_state_t* state) return XXH64_finalize(h64, (const xxh_u8*)state->mem64, (size_t)state->total_len, XXH_aligned); } - +#endif /* !XXH_NO_STREAM */ /******* Canonical representation *******/ -/*! @ingroup xxh64_family */ -XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash) +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH_NOESCAPE XXH64_canonical_t* dst, XXH64_hash_t hash) { XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t)); if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash); XXH_memcpy(dst, &hash, sizeof(*dst)); } -/*! @ingroup xxh64_family */ -XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src) +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_canonical_t* src) { return XXH_readBE64(src); } @@ -2712,7 +3380,7 @@ XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src ************************************************************************ */ /*! * @} - * @defgroup xxh3_impl XXH3 implementation + * @defgroup XXH3_impl XXH3 implementation * @ingroup impl * @{ */ @@ -2720,11 +3388,19 @@ XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src /* === Compiler specifics === */ #if ((defined(sun) || defined(__sun)) && __cplusplus) /* Solaris includes __STDC_VERSION__ with C++. Tested with GCC 5.5 */ -# define XXH_RESTRICT /* disable */ +# define XXH_RESTRICT /* disable */ #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* >= C99 */ # define XXH_RESTRICT restrict +#elif (defined (__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) \ + || (defined (__clang__)) \ + || (defined (_MSC_VER) && (_MSC_VER >= 1400)) \ + || (defined (__INTEL_COMPILER) && (__INTEL_COMPILER >= 1300)) +/* + * There are a LOT more compilers that recognize __restrict but this + * covers the major ones. + */ +# define XXH_RESTRICT __restrict #else -/* Note: it might be useful to define __restrict or __restrict__ for some C++ compilers */ # define XXH_RESTRICT /* disable */ #endif @@ -2738,17 +3414,33 @@ XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src # define XXH_unlikely(x) (x) #endif -#if defined(__GNUC__) -# if defined(__AVX2__) -# include -# elif defined(__SSE2__) -# include -# elif defined(__ARM_NEON__) || defined(__ARM_NEON) +#ifndef XXH_HAS_INCLUDE +# ifdef __has_include +# define XXH_HAS_INCLUDE(x) __has_include(x) +# else +# define XXH_HAS_INCLUDE(x) 0 +# endif +#endif + +#if defined(__GNUC__) || defined(__clang__) +# if defined(__ARM_FEATURE_SVE) +# include +# endif +# if defined(__ARM_NEON__) || defined(__ARM_NEON) \ + || (defined(_M_ARM) && _M_ARM >= 7) \ + || defined(_M_ARM64) || defined(_M_ARM64EC) \ + || (defined(__wasm_simd128__) && XXH_HAS_INCLUDE()) /* WASM SIMD128 via SIMDe */ # define inline __inline__ /* circumvent a clang bug */ # include # undef inline +# elif defined(__AVX2__) +# include +# elif defined(__SSE2__) +# include # endif -#elif defined(_MSC_VER) +#endif + +#if defined(_MSC_VER) # include #endif @@ -2848,7 +3540,7 @@ XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src * Note that these are actually implemented as macros. * * If this is not defined, it is detected automatically. - * @ref XXH_X86DISPATCH overrides this. + * internal macro XXH_X86DISPATCH overrides this. */ enum XXH_VECTOR_TYPE /* fake enum */ { XXH_SCALAR = 0, /*!< Portable scalar version */ @@ -2860,14 +3552,19 @@ enum XXH_VECTOR_TYPE /* fake enum */ { */ XXH_AVX2 = 2, /*!< AVX2 for Haswell and Bulldozer */ XXH_AVX512 = 3, /*!< AVX512 for Skylake and Icelake */ - XXH_NEON = 4, /*!< NEON for most ARMv7-A and all AArch64 */ + XXH_NEON = 4, /*!< + * NEON for most ARMv7-A, all AArch64, and WASM SIMD128 + * via the SIMDeverywhere polyfill provided with the + * Emscripten SDK. + */ XXH_VSX = 5, /*!< VSX and ZVector for POWER8/z13 (64-bit) */ + XXH_SVE = 6, /*!< SVE for some ARMv8-A and ARMv9-A */ }; /*! * @ingroup tuning * @brief Selects the minimum alignment for XXH3's accumulators. * - * When using SIMD, this should match the alignment reqired for said vector + * When using SIMD, this should match the alignment required for said vector * type, so, for example, 32 for AVX2. * * Default: Auto detected. @@ -2883,23 +3580,27 @@ enum XXH_VECTOR_TYPE /* fake enum */ { # define XXH_AVX512 3 # define XXH_NEON 4 # define XXH_VSX 5 +# define XXH_SVE 6 #endif #ifndef XXH_VECTOR /* can be defined on command line */ -# if defined(__AVX512F__) -# define XXH_VECTOR XXH_AVX512 -# elif defined(__AVX2__) -# define XXH_VECTOR XXH_AVX2 -# elif defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64) || (defined(_M_IX86_FP) && (_M_IX86_FP == 2)) -# define XXH_VECTOR XXH_SSE2 +# if defined(__ARM_FEATURE_SVE) +# define XXH_VECTOR XXH_SVE # elif ( \ defined(__ARM_NEON__) || defined(__ARM_NEON) /* gcc */ \ - || defined(_M_ARM64) || defined(_M_ARM_ARMV7VE) /* msvc */ \ + || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC) /* msvc */ \ + || (defined(__wasm_simd128__) && XXH_HAS_INCLUDE()) /* wasm simd128 via SIMDe */ \ ) && ( \ defined(_WIN32) || defined(__LITTLE_ENDIAN__) /* little endian only */ \ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) \ ) # define XXH_VECTOR XXH_NEON +# elif defined(__AVX512F__) +# define XXH_VECTOR XXH_AVX512 +# elif defined(__AVX2__) +# define XXH_VECTOR XXH_AVX2 +# elif defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64) || (defined(_M_IX86_FP) && (_M_IX86_FP == 2)) +# define XXH_VECTOR XXH_SSE2 # elif (defined(__PPC64__) && defined(__POWER8_VECTOR__)) \ || (defined(__s390x__) && defined(__VEC__)) \ && defined(__GNUC__) /* TODO: IBM XL */ @@ -2909,6 +3610,17 @@ enum XXH_VECTOR_TYPE /* fake enum */ { # endif #endif +/* __ARM_FEATURE_SVE is only supported by GCC & Clang. */ +#if (XXH_VECTOR == XXH_SVE) && !defined(__ARM_FEATURE_SVE) +# ifdef _MSC_VER +# pragma warning(once : 4606) +# else +# warning "__ARM_FEATURE_SVE isn't supported. Use SCALAR instead." +# endif +# undef XXH_VECTOR +# define XXH_VECTOR XXH_SCALAR +#endif + /* * Controls the alignment of the accumulator, * for compatibility with aligned vector loads, which are usually faster. @@ -2928,16 +3640,26 @@ enum XXH_VECTOR_TYPE /* fake enum */ { # define XXH_ACC_ALIGN 16 # elif XXH_VECTOR == XXH_AVX512 /* avx512 */ # define XXH_ACC_ALIGN 64 +# elif XXH_VECTOR == XXH_SVE /* sve */ +# define XXH_ACC_ALIGN 64 # endif #endif #if defined(XXH_X86DISPATCH) || XXH_VECTOR == XXH_SSE2 \ || XXH_VECTOR == XXH_AVX2 || XXH_VECTOR == XXH_AVX512 # define XXH_SEC_ALIGN XXH_ACC_ALIGN +#elif XXH_VECTOR == XXH_SVE +# define XXH_SEC_ALIGN XXH_ACC_ALIGN #else # define XXH_SEC_ALIGN 8 #endif +#if defined(__GNUC__) || defined(__clang__) +# define XXH_ALIASING __attribute__((may_alias)) +#else +# define XXH_ALIASING /* nothing */ +#endif + /* * UGLY HACK: * GCC usually generates the best code with -O3 for xxHash. @@ -2961,111 +3683,130 @@ enum XXH_VECTOR_TYPE /* fake enum */ { */ #if XXH_VECTOR == XXH_AVX2 /* AVX2 */ \ && defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \ - && defined(__OPTIMIZE__) && !defined(__OPTIMIZE_SIZE__) /* respect -O0 and -Os */ + && defined(__OPTIMIZE__) && XXH_SIZE_OPT <= 0 /* respect -O0 and -Os */ # pragma GCC push_options # pragma GCC optimize("-O2") #endif - #if XXH_VECTOR == XXH_NEON + /* - * NEON's setup for vmlal_u32 is a little more complicated than it is on - * SSE2, AVX2, and VSX. - * - * While PMULUDQ and VMULEUW both perform a mask, VMLAL.U32 performs an upcast. - * - * To do the same operation, the 128-bit 'Q' register needs to be split into - * two 64-bit 'D' registers, performing this operation:: + * UGLY HACK: While AArch64 GCC on Linux does not seem to care, on macOS, GCC -O3 + * optimizes out the entire hashLong loop because of the aliasing violation. * - * [ a | b ] - * | '---------. .--------' | - * | x | - * | .---------' '--------. | - * [ a & 0xFFFFFFFF | b & 0xFFFFFFFF ],[ a >> 32 | b >> 32 ] - * - * Due to significant changes in aarch64, the fastest method for aarch64 is - * completely different than the fastest method for ARMv7-A. - * - * ARMv7-A treats D registers as unions overlaying Q registers, so modifying - * D11 will modify the high half of Q5. This is similar to how modifying AH - * will only affect bits 8-15 of AX on x86. - * - * VZIP takes two registers, and puts even lanes in one register and odd lanes - * in the other. + * However, GCC is also inefficient at load-store optimization with vld1q/vst1q, + * so the only option is to mark it as aliasing. + */ +typedef uint64x2_t xxh_aliasing_uint64x2_t XXH_ALIASING; + +/*! + * @internal + * @brief `vld1q_u64` but faster and alignment-safe. * - * On ARMv7-A, this strangely modifies both parameters in place instead of - * taking the usual 3-operand form. + * On AArch64, unaligned access is always safe, but on ARMv7-a, it is only + * *conditionally* safe (`vld1` has an alignment bit like `movdq[ua]` in x86). * - * Therefore, if we want to do this, we can simply use a D-form VZIP.32 on the - * lower and upper halves of the Q register to end up with the high and low - * halves where we want - all in one instruction. + * GCC for AArch64 sees `vld1q_u8` as an intrinsic instead of a load, so it + * prohibits load-store optimizations. Therefore, a direct dereference is used. * - * vzip.32 d10, d11 @ d10 = { d10[0], d11[0] }; d11 = { d10[1], d11[1] } + * Otherwise, `vld1q_u8` is used with `vreinterpretq_u8_u64` to do a safe + * unaligned load. + */ +#if defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__) +XXH_FORCE_INLINE uint64x2_t XXH_vld1q_u64(void const* ptr) /* silence -Wcast-align */ +{ + return *(xxh_aliasing_uint64x2_t const *)ptr; +} +#else +XXH_FORCE_INLINE uint64x2_t XXH_vld1q_u64(void const* ptr) +{ + return vreinterpretq_u64_u8(vld1q_u8((uint8_t const*)ptr)); +} +#endif + +/*! + * @internal + * @brief `vmlal_u32` on low and high halves of a vector. * - * Unfortunately we need inline assembly for this: Instructions modifying two - * registers at once is not possible in GCC or Clang's IR, and they have to - * create a copy. + * This is a workaround for AArch64 GCC < 11 which implemented arm_neon.h with + * inline assembly and were therefore incapable of merging the `vget_{low, high}_u32` + * with `vmlal_u32`. + */ +#if defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 11 +XXH_FORCE_INLINE uint64x2_t +XXH_vmlal_low_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) +{ + /* Inline assembly is the only way */ + __asm__("umlal %0.2d, %1.2s, %2.2s" : "+w" (acc) : "w" (lhs), "w" (rhs)); + return acc; +} +XXH_FORCE_INLINE uint64x2_t +XXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) +{ + /* This intrinsic works as expected */ + return vmlal_high_u32(acc, lhs, rhs); +} +#else +/* Portable intrinsic versions */ +XXH_FORCE_INLINE uint64x2_t +XXH_vmlal_low_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) +{ + return vmlal_u32(acc, vget_low_u32(lhs), vget_low_u32(rhs)); +} +/*! @copydoc XXH_vmlal_low_u32 + * Assume the compiler converts this to vmlal_high_u32 on aarch64 */ +XXH_FORCE_INLINE uint64x2_t +XXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) +{ + return vmlal_u32(acc, vget_high_u32(lhs), vget_high_u32(rhs)); +} +#endif + +/*! + * @ingroup tuning + * @brief Controls the NEON to scalar ratio for XXH3 * - * aarch64 requires a different approach. + * This can be set to 2, 4, 6, or 8. * - * In order to make it easier to write a decent compiler for aarch64, many - * quirks were removed, such as conditional execution. + * ARM Cortex CPUs are _very_ sensitive to how their pipelines are used. * - * NEON was also affected by this. + * For example, the Cortex-A73 can dispatch 3 micro-ops per cycle, but only 2 of those + * can be NEON. If you are only using NEON instructions, you are only using 2/3 of the CPU + * bandwidth. * - * aarch64 cannot access the high bits of a Q-form register, and writes to a - * D-form register zero the high bits, similar to how writes to W-form scalar - * registers (or DWORD registers on x86_64) work. + * This is even more noticeable on the more advanced cores like the Cortex-A76 which + * can dispatch 8 micro-ops per cycle, but still only 2 NEON micro-ops at once. * - * The formerly free vget_high intrinsics now require a vext (with a few - * exceptions) + * Therefore, to make the most out of the pipeline, it is beneficial to run 6 NEON lanes + * and 2 scalar lanes, which is chosen by default. * - * Additionally, VZIP was replaced by ZIP1 and ZIP2, which are the equivalent - * of PUNPCKL* and PUNPCKH* in SSE, respectively, in order to only modify one - * operand. + * This does not apply to Apple processors or 32-bit processors, which run better with + * full NEON. These will default to 8. Additionally, size-optimized builds run 8 lanes. * - * The equivalent of the VZIP.32 on the lower and upper halves would be this - * mess: + * This change benefits CPUs with large micro-op buffers without negatively affecting + * most other CPUs: * - * ext v2.4s, v0.4s, v0.4s, #2 // v2 = { v0[2], v0[3], v0[0], v0[1] } - * zip1 v1.2s, v0.2s, v2.2s // v1 = { v0[0], v2[0] } - * zip2 v0.2s, v0.2s, v1.2s // v0 = { v0[1], v2[1] } + * | Chipset | Dispatch type | NEON only | 6:2 hybrid | Diff. | + * |:----------------------|:--------------------|----------:|-----------:|------:| + * | Snapdragon 730 (A76) | 2 NEON/8 micro-ops | 8.8 GB/s | 10.1 GB/s | ~16% | + * | Snapdragon 835 (A73) | 2 NEON/3 micro-ops | 5.1 GB/s | 5.3 GB/s | ~5% | + * | Marvell PXA1928 (A53) | In-order dual-issue | 1.9 GB/s | 1.9 GB/s | 0% | + * | Apple M1 | 4 NEON/8 micro-ops | 37.3 GB/s | 36.1 GB/s | ~-3% | * - * Instead, we use a literal downcast, vmovn_u64 (XTN), and vshrn_n_u64 (SHRN): + * It also seems to fix some bad codegen on GCC, making it almost as fast as clang. * - * shrn v1.2s, v0.2d, #32 // v1 = (uint32x2_t)(v0 >> 32); - * xtn v0.2s, v0.2d // v0 = (uint32x2_t)(v0 & 0xFFFFFFFF); + * When using WASM SIMD128, if this is 2 or 6, SIMDe will scalarize 2 of the lanes meaning + * it effectively becomes worse 4. * - * This is available on ARMv7-A, but is less efficient than a single VZIP.32. + * @see XXH3_accumulate_512_neon() */ - -/*! - * Function-like macro: - * void XXH_SPLIT_IN_PLACE(uint64x2_t &in, uint32x2_t &outLo, uint32x2_t &outHi) - * { - * outLo = (uint32x2_t)(in & 0xFFFFFFFF); - * outHi = (uint32x2_t)(in >> 32); - * in = UNDEFINED; - * } - */ -# if !defined(XXH_NO_VZIP_HACK) /* define to disable */ \ - && defined(__GNUC__) \ - && !defined(__aarch64__) && !defined(__arm64__) && !defined(_M_ARM64) -# define XXH_SPLIT_IN_PLACE(in, outLo, outHi) \ - do { \ - /* Undocumented GCC/Clang operand modifier: %e0 = lower D half, %f0 = upper D half */ \ - /* https://github.com/gcc-mirror/gcc/blob/38cf91e5/gcc/config/arm/arm.c#L22486 */ \ - /* https://github.com/llvm-mirror/llvm/blob/2c4ca683/lib/Target/ARM/ARMAsmPrinter.cpp#L399 */ \ - __asm__("vzip.32 %e0, %f0" : "+w" (in)); \ - (outLo) = vget_low_u32 (vreinterpretq_u32_u64(in)); \ - (outHi) = vget_high_u32(vreinterpretq_u32_u64(in)); \ - } while (0) -# else -# define XXH_SPLIT_IN_PLACE(in, outLo, outHi) \ - do { \ - (outLo) = vmovn_u64 (in); \ - (outHi) = vshrn_n_u64 ((in), 32); \ - } while (0) +# ifndef XXH3_NEON_LANES +# if (defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) || defined(_M_ARM64EC)) \ + && !defined(__APPLE__) && XXH_SIZE_OPT <= 0 +# define XXH3_NEON_LANES 6 +# else +# define XXH3_NEON_LANES XXH_ACC_NB +# endif # endif #endif /* XXH_VECTOR == XXH_NEON */ @@ -3078,27 +3819,42 @@ enum XXH_VECTOR_TYPE /* fake enum */ { * inconsistent intrinsics, spotty coverage, and multiple endiannesses. */ #if XXH_VECTOR == XXH_VSX +/* Annoyingly, these headers _may_ define three macros: `bool`, `vector`, + * and `pixel`. This is a problem for obvious reasons. + * + * These keywords are unnecessary; the spec literally says they are + * equivalent to `__bool`, `__vector`, and `__pixel` and may be undef'd + * after including the header. + * + * We use pragma push_macro/pop_macro to keep the namespace clean. */ +# pragma push_macro("bool") +# pragma push_macro("vector") +# pragma push_macro("pixel") +/* silence potential macro redefined warnings */ +# undef bool +# undef vector +# undef pixel + # if defined(__s390x__) # include # else -/* gcc's altivec.h can have the unwanted consequence to unconditionally - * #define bool, vector, and pixel keywords, - * with bad consequences for programs already using these keywords for other purposes. - * The paragraph defining these macros is skipped when __APPLE_ALTIVEC__ is defined. - * __APPLE_ALTIVEC__ is _generally_ defined automatically by the compiler, - * but it seems that, in some cases, it isn't. - * Force the build macro to be defined, so that keywords are not altered. - */ -# if defined(__GNUC__) && !defined(__APPLE_ALTIVEC__) -# define __APPLE_ALTIVEC__ -# endif # include # endif +/* Restore the original macro values, if applicable. */ +# pragma pop_macro("pixel") +# pragma pop_macro("vector") +# pragma pop_macro("bool") + typedef __vector unsigned long long xxh_u64x2; typedef __vector unsigned char xxh_u8x16; typedef __vector unsigned xxh_u32x4; +/* + * UGLY HACK: Similar to aarch64 macOS GCC, s390x GCC has the same aliasing issue. + */ +typedef xxh_u64x2 xxh_aliasing_u64x2 XXH_ALIASING; + # ifndef XXH_VSX_BE # if defined(__BIG_ENDIAN__) \ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) @@ -3150,8 +3906,9 @@ XXH_FORCE_INLINE xxh_u64x2 XXH_vec_loadu(const void *ptr) /* s390x is always big endian, no issue on this platform */ # define XXH_vec_mulo vec_mulo # define XXH_vec_mule vec_mule -# elif defined(__clang__) && XXH_HAS_BUILTIN(__builtin_altivec_vmuleuw) +# elif defined(__clang__) && XXH_HAS_BUILTIN(__builtin_altivec_vmuleuw) && !defined(__ibmxl__) /* Clang has a better way to control this, we can just use the builtin which doesn't swap. */ + /* The IBM XL Compiler (which defined __clang__) only implements the vec_* operations */ # define XXH_vec_mulo __builtin_altivec_vmulouw # define XXH_vec_mule __builtin_altivec_vmuleuw # else @@ -3172,13 +3929,28 @@ XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mule(xxh_u32x4 a, xxh_u32x4 b) # endif /* XXH_vec_mulo, XXH_vec_mule */ #endif /* XXH_VECTOR == XXH_VSX */ +#if XXH_VECTOR == XXH_SVE +#define ACCRND(acc, offset) \ +do { \ + svuint64_t input_vec = svld1_u64(mask, xinput + offset); \ + svuint64_t secret_vec = svld1_u64(mask, xsecret + offset); \ + svuint64_t mixed = sveor_u64_x(mask, secret_vec, input_vec); \ + svuint64_t swapped = svtbl_u64(input_vec, kSwap); \ + svuint64_t mixed_lo = svextw_u64_x(mask, mixed); \ + svuint64_t mixed_hi = svlsr_n_u64_x(mask, mixed, 32); \ + svuint64_t mul = svmad_u64_x(mask, mixed_lo, mixed_hi, swapped); \ + acc = svadd_u64_x(mask, acc, mul); \ +} while (0) +#endif /* XXH_VECTOR == XXH_SVE */ /* prefetch * can be disabled, by declaring XXH_NO_PREFETCH build macro */ #if defined(XXH_NO_PREFETCH) # define XXH_PREFETCH(ptr) (void)(ptr) /* disabled */ #else -# if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86)) /* _mm_prefetch() not defined outside of x86/x64 */ +# if XXH_SIZE_OPT >= 1 +# define XXH_PREFETCH(ptr) (void)(ptr) +# elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86)) /* _mm_prefetch() not defined outside of x86/x64 */ # include /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */ # define XXH_PREFETCH(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0) # elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) ) @@ -3215,6 +3987,8 @@ XXH_ALIGN(64) static const xxh_u8 XXH3_kSecret[XXH_SECRET_DEFAULT_SIZE] = { 0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e, }; +static const xxh_u64 PRIME_MX1 = 0x165667919E3779F9ULL; /*!< 0b0001011001010110011001111001000110011110001101110111100111111001 */ +static const xxh_u64 PRIME_MX2 = 0x9FB21C651E98DF25ULL; /*!< 0b1001111110110010000111000110010100011110100110001101111100100101 */ #ifdef XXH_OLD_NAMES # define kSecret XXH3_kSecret @@ -3243,7 +4017,6 @@ XXH_mult32to64(xxh_u64 x, xxh_u64 y) return (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF); } #elif defined(_MSC_VER) && defined(_M_IX86) -# include # define XXH_mult32to64(x, y) __emulu((unsigned)(x), (unsigned)(y)) #else /* @@ -3283,7 +4056,7 @@ XXH_mult64to128(xxh_u64 lhs, xxh_u64 rhs) * In that case it is best to use the portable one. * https://github.com/Cyan4973/xxHash/issues/211#issuecomment-515575677 */ -#if defined(__GNUC__) && !defined(__wasm__) \ +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__wasm__) \ && defined(__SIZEOF_INT128__) \ || (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 128) @@ -3300,7 +4073,7 @@ XXH_mult64to128(xxh_u64 lhs, xxh_u64 rhs) * * This compiles to single operand MUL on x64. */ -#elif defined(_M_X64) || defined(_M_IA64) +#elif (defined(_M_X64) || defined(_M_IA64)) && !defined(_M_ARM64EC) #ifndef _MSC_VER # pragma intrinsic(_umul128) @@ -3317,7 +4090,7 @@ XXH_mult64to128(xxh_u64 lhs, xxh_u64 rhs) * * This compiles to the same MUL + UMULH as GCC/Clang's __uint128_t method. */ -#elif defined(_M_ARM64) +#elif defined(_M_ARM64) || defined(_M_ARM64EC) #ifndef _MSC_VER # pragma intrinsic(__umulh) @@ -3407,7 +4180,7 @@ XXH3_mul128_fold64(xxh_u64 lhs, xxh_u64 rhs) } /*! Seems to produce slightly better code on GCC for some reason. */ -XXH_FORCE_INLINE xxh_u64 XXH_xorshift64(xxh_u64 v64, int shift) +XXH_FORCE_INLINE XXH_CONSTF xxh_u64 XXH_xorshift64(xxh_u64 v64, int shift) { XXH_ASSERT(0 <= shift && shift < 64); return v64 ^ (v64 >> shift); @@ -3420,7 +4193,7 @@ XXH_FORCE_INLINE xxh_u64 XXH_xorshift64(xxh_u64 v64, int shift) static XXH64_hash_t XXH3_avalanche(xxh_u64 h64) { h64 = XXH_xorshift64(h64, 37); - h64 *= 0x165667919E3779F9ULL; + h64 *= PRIME_MX1; h64 = XXH_xorshift64(h64, 32); return h64; } @@ -3434,9 +4207,9 @@ static XXH64_hash_t XXH3_rrmxmx(xxh_u64 h64, xxh_u64 len) { /* this mix is inspired by Pelle Evensen's rrmxmx */ h64 ^= XXH_rotl64(h64, 49) ^ XXH_rotl64(h64, 24); - h64 *= 0x9FB21C651E98DF25ULL; + h64 *= PRIME_MX2; h64 ^= (h64 >> 35) + len ; - h64 *= 0x9FB21C651E98DF25ULL; + h64 *= PRIME_MX2; return XXH_xorshift64(h64, 28); } @@ -3474,7 +4247,7 @@ static XXH64_hash_t XXH3_rrmxmx(xxh_u64 h64, xxh_u64 len) * * This adds an extra layer of strength for custom secrets. */ -XXH_FORCE_INLINE XXH64_hash_t +XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t XXH3_len_1to3_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { XXH_ASSERT(input != NULL); @@ -3496,7 +4269,7 @@ XXH3_len_1to3_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_h } } -XXH_FORCE_INLINE XXH64_hash_t +XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t XXH3_len_4to8_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { XXH_ASSERT(input != NULL); @@ -3512,7 +4285,7 @@ XXH3_len_4to8_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_h } } -XXH_FORCE_INLINE XXH64_hash_t +XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t XXH3_len_9to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { XXH_ASSERT(input != NULL); @@ -3529,7 +4302,7 @@ XXH3_len_9to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_ } } -XXH_FORCE_INLINE XXH64_hash_t +XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t XXH3_len_0to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { XXH_ASSERT(len <= 16); @@ -3599,7 +4372,7 @@ XXH_FORCE_INLINE xxh_u64 XXH3_mix16B(const xxh_u8* XXH_RESTRICT input, } /* For mid range keys, XXH3 uses a Mum-hash variant. */ -XXH_FORCE_INLINE XXH64_hash_t +XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t XXH3_len_17to128_64b(const xxh_u8* XXH_RESTRICT input, size_t len, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, XXH64_hash_t seed) @@ -3608,6 +4381,14 @@ XXH3_len_17to128_64b(const xxh_u8* XXH_RESTRICT input, size_t len, XXH_ASSERT(16 < len && len <= 128); { xxh_u64 acc = len * XXH_PRIME64_1; +#if XXH_SIZE_OPT >= 1 + /* Smaller and cleaner, but slightly slower. */ + unsigned int i = (unsigned int)(len - 1) / 32; + do { + acc += XXH3_mix16B(input+16 * i, secret+32*i, seed); + acc += XXH3_mix16B(input+len-16*(i+1), secret+32*i+16, seed); + } while (i-- != 0); +#else if (len > 32) { if (len > 64) { if (len > 96) { @@ -3622,14 +4403,14 @@ XXH3_len_17to128_64b(const xxh_u8* XXH_RESTRICT input, size_t len, } acc += XXH3_mix16B(input+0, secret+0, seed); acc += XXH3_mix16B(input+len-16, secret+16, seed); - +#endif return XXH3_avalanche(acc); } } #define XXH3_MIDSIZE_MAX 240 -XXH_NO_INLINE XXH64_hash_t +XXH_NO_INLINE XXH_PUREF XXH64_hash_t XXH3_len_129to240_64b(const xxh_u8* XXH_RESTRICT input, size_t len, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, XXH64_hash_t seed) @@ -3641,13 +4422,17 @@ XXH3_len_129to240_64b(const xxh_u8* XXH_RESTRICT input, size_t len, #define XXH3_MIDSIZE_LASTOFFSET 17 { xxh_u64 acc = len * XXH_PRIME64_1; - int const nbRounds = (int)len / 16; - int i; + xxh_u64 acc_end; + unsigned int const nbRounds = (unsigned int)len / 16; + unsigned int i; + XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX); for (i=0; i<8; i++) { acc += XXH3_mix16B(input+(16*i), secret+(16*i), seed); } - acc = XXH3_avalanche(acc); + /* last bytes */ + acc_end = XXH3_mix16B(input + len - 16, secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET, seed); XXH_ASSERT(nbRounds >= 8); + acc = XXH3_avalanche(acc); #if defined(__clang__) /* Clang */ \ && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */ \ && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable */ @@ -3674,11 +4459,13 @@ XXH3_len_129to240_64b(const xxh_u8* XXH_RESTRICT input, size_t len, #pragma clang loop vectorize(disable) #endif for (i=8 ; i < nbRounds; i++) { - acc += XXH3_mix16B(input+(16*i), secret+(16*(i-8)) + XXH3_MIDSIZE_STARTOFFSET, seed); + /* + * Prevents clang for unrolling the acc loop and interleaving with this one. + */ + XXH_COMPILER_GUARD(acc); + acc_end += XXH3_mix16B(input+(16*i), secret+(16*(i-8)) + XXH3_MIDSIZE_STARTOFFSET, seed); } - /* last bytes */ - acc += XXH3_mix16B(input + len - 16, secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET, seed); - return XXH3_avalanche(acc); + return XXH3_avalanche(acc + acc_end); } } @@ -3694,6 +4481,47 @@ XXH3_len_129to240_64b(const xxh_u8* XXH_RESTRICT input, size_t len, # define ACC_NB XXH_ACC_NB #endif +#ifndef XXH_PREFETCH_DIST +# ifdef __clang__ +# define XXH_PREFETCH_DIST 320 +# else +# if (XXH_VECTOR == XXH_AVX512) +# define XXH_PREFETCH_DIST 512 +# else +# define XXH_PREFETCH_DIST 384 +# endif +# endif /* __clang__ */ +#endif /* XXH_PREFETCH_DIST */ + +/* + * These macros are to generate an XXH3_accumulate() function. + * The two arguments select the name suffix and target attribute. + * + * The name of this symbol is XXH3_accumulate_() and it calls + * XXH3_accumulate_512_(). + * + * It may be useful to hand implement this function if the compiler fails to + * optimize the inline function. + */ +#define XXH3_ACCUMULATE_TEMPLATE(name) \ +void \ +XXH3_accumulate_##name(xxh_u64* XXH_RESTRICT acc, \ + const xxh_u8* XXH_RESTRICT input, \ + const xxh_u8* XXH_RESTRICT secret, \ + size_t nbStripes) \ +{ \ + size_t n; \ + for (n = 0; n < nbStripes; n++ ) { \ + const xxh_u8* const in = input + n*XXH_STRIPE_LEN; \ + XXH_PREFETCH(in + XXH_PREFETCH_DIST); \ + XXH3_accumulate_512_##name( \ + acc, \ + in, \ + secret + n*XXH_SECRET_CONSUME_RATE); \ + } \ +} + + XXH_FORCE_INLINE void XXH_writeLE64(void* dst, xxh_u64 v64) { if (!XXH_CPU_LITTLE_ENDIAN) v64 = XXH_swap64(v64); @@ -3714,6 +4542,7 @@ XXH_FORCE_INLINE void XXH_writeLE64(void* dst, xxh_u64 v64) typedef long long xxh_i64; #endif + /* * XXH3_accumulate_512 is the tightest loop for long inputs, and it is the most optimized. * @@ -3761,7 +4590,7 @@ XXH3_accumulate_512_avx512(void* XXH_RESTRICT acc, /* data_key = data_vec ^ key_vec; */ __m512i const data_key = _mm512_xor_si512 (data_vec, key_vec); /* data_key_lo = data_key >> 32; */ - __m512i const data_key_lo = _mm512_shuffle_epi32 (data_key, (_MM_PERM_ENUM)_MM_SHUFFLE(0, 3, 0, 1)); + __m512i const data_key_lo = _mm512_srli_epi64 (data_key, 32); /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ __m512i const product = _mm512_mul_epu32 (data_key, data_key_lo); /* xacc[0] += swap(data_vec); */ @@ -3771,6 +4600,7 @@ XXH3_accumulate_512_avx512(void* XXH_RESTRICT acc, *xacc = _mm512_add_epi64(product, sum); } } +XXH_FORCE_INLINE XXH_TARGET_AVX512 XXH3_ACCUMULATE_TEMPLATE(avx512) /* * XXH3_scrambleAcc: Scrambles the accumulators to improve mixing. @@ -3804,13 +4634,12 @@ XXH3_scrambleAcc_avx512(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) /* xacc[0] ^= (xacc[0] >> 47) */ __m512i const acc_vec = *xacc; __m512i const shifted = _mm512_srli_epi64 (acc_vec, 47); - __m512i const data_vec = _mm512_xor_si512 (acc_vec, shifted); /* xacc[0] ^= secret; */ __m512i const key_vec = _mm512_loadu_si512 (secret); - __m512i const data_key = _mm512_xor_si512 (data_vec, key_vec); + __m512i const data_key = _mm512_ternarylogic_epi32(key_vec, acc_vec, shifted, 0x96 /* key_vec ^ acc_vec ^ shifted */); /* xacc[0] *= XXH_PRIME32_1; */ - __m512i const data_key_hi = _mm512_shuffle_epi32 (data_key, (_MM_PERM_ENUM)_MM_SHUFFLE(0, 3, 0, 1)); + __m512i const data_key_hi = _mm512_srli_epi64 (data_key, 32); __m512i const prod_lo = _mm512_mul_epu32 (data_key, prime32); __m512i const prod_hi = _mm512_mul_epu32 (data_key_hi, prime32); *xacc = _mm512_add_epi64(prod_lo, _mm512_slli_epi64(prod_hi, 32)); @@ -3825,7 +4654,8 @@ XXH3_initCustomSecret_avx512(void* XXH_RESTRICT customSecret, xxh_u64 seed64) XXH_ASSERT(((size_t)customSecret & 63) == 0); (void)(&XXH_writeLE64); { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m512i); - __m512i const seed = _mm512_mask_set1_epi64(_mm512_set1_epi64((xxh_i64)seed64), 0xAA, (xxh_i64)(0U - seed64)); + __m512i const seed_pos = _mm512_set1_epi64((xxh_i64)seed64); + __m512i const seed = _mm512_mask_sub_epi64(seed_pos, 0xAA, _mm512_set1_epi8(0), seed_pos); const __m512i* const src = (const __m512i*) ((const void*) XXH3_kSecret); __m512i* const dest = ( __m512i*) customSecret; @@ -3833,14 +4663,7 @@ XXH3_initCustomSecret_avx512(void* XXH_RESTRICT customSecret, xxh_u64 seed64) XXH_ASSERT(((size_t)src & 63) == 0); /* control alignment */ XXH_ASSERT(((size_t)dest & 63) == 0); for (i=0; i < nbRounds; ++i) { - /* GCC has a bug, _mm512_stream_load_si512 accepts 'void*', not 'void const*', - * this will warn "discards 'const' qualifier". */ - union { - const __m512i* cp; - void* p; - } remote_const_void; - remote_const_void.cp = src + i; - dest[i] = _mm512_add_epi64(_mm512_stream_load_si512(remote_const_void.p), seed); + dest[i] = _mm512_add_epi64(_mm512_load_si512(src + i), seed); } } } @@ -3876,7 +4699,7 @@ XXH3_accumulate_512_avx2( void* XXH_RESTRICT acc, /* data_key = data_vec ^ key_vec; */ __m256i const data_key = _mm256_xor_si256 (data_vec, key_vec); /* data_key_lo = data_key >> 32; */ - __m256i const data_key_lo = _mm256_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1)); + __m256i const data_key_lo = _mm256_srli_epi64 (data_key, 32); /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ __m256i const product = _mm256_mul_epu32 (data_key, data_key_lo); /* xacc[i] += swap(data_vec); */ @@ -3886,6 +4709,7 @@ XXH3_accumulate_512_avx2( void* XXH_RESTRICT acc, xacc[i] = _mm256_add_epi64(product, sum); } } } +XXH_FORCE_INLINE XXH_TARGET_AVX2 XXH3_ACCUMULATE_TEMPLATE(avx2) XXH_FORCE_INLINE XXH_TARGET_AVX2 void XXH3_scrambleAcc_avx2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) @@ -3908,7 +4732,7 @@ XXH3_scrambleAcc_avx2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) __m256i const data_key = _mm256_xor_si256 (data_vec, key_vec); /* xacc[i] *= XXH_PRIME32_1; */ - __m256i const data_key_hi = _mm256_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1)); + __m256i const data_key_hi = _mm256_srli_epi64 (data_key, 32); __m256i const prod_lo = _mm256_mul_epu32 (data_key, prime32); __m256i const prod_hi = _mm256_mul_epu32 (data_key_hi, prime32); xacc[i] = _mm256_add_epi64(prod_lo, _mm256_slli_epi64(prod_hi, 32)); @@ -3940,12 +4764,12 @@ XXH_FORCE_INLINE XXH_TARGET_AVX2 void XXH3_initCustomSecret_avx2(void* XXH_RESTR XXH_ASSERT(((size_t)dest & 31) == 0); /* GCC -O2 need unroll loop manually */ - dest[0] = _mm256_add_epi64(_mm256_stream_load_si256(src+0), seed); - dest[1] = _mm256_add_epi64(_mm256_stream_load_si256(src+1), seed); - dest[2] = _mm256_add_epi64(_mm256_stream_load_si256(src+2), seed); - dest[3] = _mm256_add_epi64(_mm256_stream_load_si256(src+3), seed); - dest[4] = _mm256_add_epi64(_mm256_stream_load_si256(src+4), seed); - dest[5] = _mm256_add_epi64(_mm256_stream_load_si256(src+5), seed); + dest[0] = _mm256_add_epi64(_mm256_load_si256(src+0), seed); + dest[1] = _mm256_add_epi64(_mm256_load_si256(src+1), seed); + dest[2] = _mm256_add_epi64(_mm256_load_si256(src+2), seed); + dest[3] = _mm256_add_epi64(_mm256_load_si256(src+3), seed); + dest[4] = _mm256_add_epi64(_mm256_load_si256(src+4), seed); + dest[5] = _mm256_add_epi64(_mm256_load_si256(src+5), seed); } } @@ -3992,6 +4816,7 @@ XXH3_accumulate_512_sse2( void* XXH_RESTRICT acc, xacc[i] = _mm_add_epi64(product, sum); } } } +XXH_FORCE_INLINE XXH_TARGET_SSE2 XXH3_ACCUMULATE_TEMPLATE(sse2) XXH_FORCE_INLINE XXH_TARGET_SSE2 void XXH3_scrambleAcc_sse2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) @@ -4059,96 +4884,222 @@ XXH_FORCE_INLINE XXH_TARGET_SSE2 void XXH3_initCustomSecret_sse2(void* XXH_RESTR #if (XXH_VECTOR == XXH_NEON) +/* forward declarations for the scalar routines */ +XXH_FORCE_INLINE void +XXH3_scalarRound(void* XXH_RESTRICT acc, void const* XXH_RESTRICT input, + void const* XXH_RESTRICT secret, size_t lane); + +XXH_FORCE_INLINE void +XXH3_scalarScrambleRound(void* XXH_RESTRICT acc, + void const* XXH_RESTRICT secret, size_t lane); + +/*! + * @internal + * @brief The bulk processing loop for NEON and WASM SIMD128. + * + * The NEON code path is actually partially scalar when running on AArch64. This + * is to optimize the pipelining and can have up to 15% speedup depending on the + * CPU, and it also mitigates some GCC codegen issues. + * + * @see XXH3_NEON_LANES for configuring this and details about this optimization. + * + * NEON's 32-bit to 64-bit long multiply takes a half vector of 32-bit + * integers instead of the other platforms which mask full 64-bit vectors, + * so the setup is more complicated than just shifting right. + * + * Additionally, there is an optimization for 4 lanes at once noted below. + * + * Since, as stated, the most optimal amount of lanes for Cortexes is 6, + * there needs to be *three* versions of the accumulate operation used + * for the remaining 2 lanes. + * + * WASM's SIMD128 uses SIMDe's arm_neon.h polyfill because the intrinsics overlap + * nearly perfectly. + */ + XXH_FORCE_INLINE void XXH3_accumulate_512_neon( void* XXH_RESTRICT acc, const void* XXH_RESTRICT input, const void* XXH_RESTRICT secret) { XXH_ASSERT((((size_t)acc) & 15) == 0); - { - uint64x2_t* const xacc = (uint64x2_t *) acc; + XXH_STATIC_ASSERT(XXH3_NEON_LANES > 0 && XXH3_NEON_LANES <= XXH_ACC_NB && XXH3_NEON_LANES % 2 == 0); + { /* GCC for darwin arm64 does not like aliasing here */ + xxh_aliasing_uint64x2_t* const xacc = (xxh_aliasing_uint64x2_t*) acc; /* We don't use a uint32x4_t pointer because it causes bus errors on ARMv7. */ - uint8_t const* const xinput = (const uint8_t *) input; - uint8_t const* const xsecret = (const uint8_t *) secret; + uint8_t const* xinput = (const uint8_t *) input; + uint8_t const* xsecret = (const uint8_t *) secret; size_t i; - for (i=0; i < XXH_STRIPE_LEN / sizeof(uint64x2_t); i++) { +#ifdef __wasm_simd128__ + /* + * On WASM SIMD128, Clang emits direct address loads when XXH3_kSecret + * is constant propagated, which results in it converting it to this + * inside the loop: + * + * a = v128.load(XXH3_kSecret + 0 + $secret_offset, offset = 0) + * b = v128.load(XXH3_kSecret + 16 + $secret_offset, offset = 0) + * ... + * + * This requires a full 32-bit address immediate (and therefore a 6 byte + * instruction) as well as an add for each offset. + * + * Putting an asm guard prevents it from folding (at the cost of losing + * the alignment hint), and uses the free offset in `v128.load` instead + * of adding secret_offset each time which overall reduces code size by + * about a kilobyte and improves performance. + */ + XXH_COMPILER_GUARD(xsecret); +#endif + /* Scalar lanes use the normal scalarRound routine */ + for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) { + XXH3_scalarRound(acc, input, secret, i); + } + i = 0; + /* 4 NEON lanes at a time. */ + for (; i+1 < XXH3_NEON_LANES / 2; i+=2) { /* data_vec = xinput[i]; */ - uint8x16_t data_vec = vld1q_u8(xinput + (i * 16)); + uint64x2_t data_vec_1 = XXH_vld1q_u64(xinput + (i * 16)); + uint64x2_t data_vec_2 = XXH_vld1q_u64(xinput + ((i+1) * 16)); /* key_vec = xsecret[i]; */ - uint8x16_t key_vec = vld1q_u8(xsecret + (i * 16)); - uint64x2_t data_key; - uint32x2_t data_key_lo, data_key_hi; - /* xacc[i] += swap(data_vec); */ - uint64x2_t const data64 = vreinterpretq_u64_u8(data_vec); - uint64x2_t const swapped = vextq_u64(data64, data64, 1); - xacc[i] = vaddq_u64 (xacc[i], swapped); + uint64x2_t key_vec_1 = XXH_vld1q_u64(xsecret + (i * 16)); + uint64x2_t key_vec_2 = XXH_vld1q_u64(xsecret + ((i+1) * 16)); + /* data_swap = swap(data_vec) */ + uint64x2_t data_swap_1 = vextq_u64(data_vec_1, data_vec_1, 1); + uint64x2_t data_swap_2 = vextq_u64(data_vec_2, data_vec_2, 1); /* data_key = data_vec ^ key_vec; */ - data_key = vreinterpretq_u64_u8(veorq_u8(data_vec, key_vec)); - /* data_key_lo = (uint32x2_t) (data_key & 0xFFFFFFFF); - * data_key_hi = (uint32x2_t) (data_key >> 32); - * data_key = UNDEFINED; */ - XXH_SPLIT_IN_PLACE(data_key, data_key_lo, data_key_hi); - /* xacc[i] += (uint64x2_t) data_key_lo * (uint64x2_t) data_key_hi; */ - xacc[i] = vmlal_u32 (xacc[i], data_key_lo, data_key_hi); + uint64x2_t data_key_1 = veorq_u64(data_vec_1, key_vec_1); + uint64x2_t data_key_2 = veorq_u64(data_vec_2, key_vec_2); + /* + * If we reinterpret the 64x2 vectors as 32x4 vectors, we can use a + * de-interleave operation for 4 lanes in 1 step with `vuzpq_u32` to + * get one vector with the low 32 bits of each lane, and one vector + * with the high 32 bits of each lane. + * + * The intrinsic returns a double vector because the original ARMv7-a + * instruction modified both arguments in place. AArch64 and SIMD128 emit + * two instructions from this intrinsic. + * + * [ dk11L | dk11H | dk12L | dk12H ] -> [ dk11L | dk12L | dk21L | dk22L ] + * [ dk21L | dk21H | dk22L | dk22H ] -> [ dk11H | dk12H | dk21H | dk22H ] + */ + uint32x4x2_t unzipped = vuzpq_u32( + vreinterpretq_u32_u64(data_key_1), + vreinterpretq_u32_u64(data_key_2) + ); + /* data_key_lo = data_key & 0xFFFFFFFF */ + uint32x4_t data_key_lo = unzipped.val[0]; + /* data_key_hi = data_key >> 32 */ + uint32x4_t data_key_hi = unzipped.val[1]; + /* + * Then, we can split the vectors horizontally and multiply which, as for most + * widening intrinsics, have a variant that works on both high half vectors + * for free on AArch64. A similar instruction is available on SIMD128. + * + * sum = data_swap + (u64x2) data_key_lo * (u64x2) data_key_hi + */ + uint64x2_t sum_1 = XXH_vmlal_low_u32(data_swap_1, data_key_lo, data_key_hi); + uint64x2_t sum_2 = XXH_vmlal_high_u32(data_swap_2, data_key_lo, data_key_hi); + /* + * Clang reorders + * a += b * c; // umlal swap.2d, dkl.2s, dkh.2s + * c += a; // add acc.2d, acc.2d, swap.2d + * to + * c += a; // add acc.2d, acc.2d, swap.2d + * c += b * c; // umlal acc.2d, dkl.2s, dkh.2s + * + * While it would make sense in theory since the addition is faster, + * for reasons likely related to umlal being limited to certain NEON + * pipelines, this is worse. A compiler guard fixes this. + */ + XXH_COMPILER_GUARD_CLANG_NEON(sum_1); + XXH_COMPILER_GUARD_CLANG_NEON(sum_2); + /* xacc[i] = acc_vec + sum; */ + xacc[i] = vaddq_u64(xacc[i], sum_1); + xacc[i+1] = vaddq_u64(xacc[i+1], sum_2); + } + /* Operate on the remaining NEON lanes 2 at a time. */ + for (; i < XXH3_NEON_LANES / 2; i++) { + /* data_vec = xinput[i]; */ + uint64x2_t data_vec = XXH_vld1q_u64(xinput + (i * 16)); + /* key_vec = xsecret[i]; */ + uint64x2_t key_vec = XXH_vld1q_u64(xsecret + (i * 16)); + /* acc_vec_2 = swap(data_vec) */ + uint64x2_t data_swap = vextq_u64(data_vec, data_vec, 1); + /* data_key = data_vec ^ key_vec; */ + uint64x2_t data_key = veorq_u64(data_vec, key_vec); + /* For two lanes, just use VMOVN and VSHRN. */ + /* data_key_lo = data_key & 0xFFFFFFFF; */ + uint32x2_t data_key_lo = vmovn_u64(data_key); + /* data_key_hi = data_key >> 32; */ + uint32x2_t data_key_hi = vshrn_n_u64(data_key, 32); + /* sum = data_swap + (u64x2) data_key_lo * (u64x2) data_key_hi; */ + uint64x2_t sum = vmlal_u32(data_swap, data_key_lo, data_key_hi); + /* Same Clang workaround as before */ + XXH_COMPILER_GUARD_CLANG_NEON(sum); + /* xacc[i] = acc_vec + sum; */ + xacc[i] = vaddq_u64 (xacc[i], sum); } } } +XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(neon) XXH_FORCE_INLINE void XXH3_scrambleAcc_neon(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) { XXH_ASSERT((((size_t)acc) & 15) == 0); - { uint64x2_t* xacc = (uint64x2_t*) acc; + { xxh_aliasing_uint64x2_t* xacc = (xxh_aliasing_uint64x2_t*) acc; uint8_t const* xsecret = (uint8_t const*) secret; - uint32x2_t prime = vdup_n_u32 (XXH_PRIME32_1); size_t i; - for (i=0; i < XXH_STRIPE_LEN/sizeof(uint64x2_t); i++) { + /* WASM uses operator overloads and doesn't need these. */ +#ifndef __wasm_simd128__ + /* { prime32_1, prime32_1 } */ + uint32x2_t const kPrimeLo = vdup_n_u32(XXH_PRIME32_1); + /* { 0, prime32_1, 0, prime32_1 } */ + uint32x4_t const kPrimeHi = vreinterpretq_u32_u64(vdupq_n_u64((xxh_u64)XXH_PRIME32_1 << 32)); +#endif + + /* AArch64 uses both scalar and neon at the same time */ + for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) { + XXH3_scalarScrambleRound(acc, secret, i); + } + for (i=0; i < XXH3_NEON_LANES / 2; i++) { /* xacc[i] ^= (xacc[i] >> 47); */ uint64x2_t acc_vec = xacc[i]; - uint64x2_t shifted = vshrq_n_u64 (acc_vec, 47); - uint64x2_t data_vec = veorq_u64 (acc_vec, shifted); + uint64x2_t shifted = vshrq_n_u64(acc_vec, 47); + uint64x2_t data_vec = veorq_u64(acc_vec, shifted); /* xacc[i] ^= xsecret[i]; */ - uint8x16_t key_vec = vld1q_u8 (xsecret + (i * 16)); - uint64x2_t data_key = veorq_u64 (data_vec, vreinterpretq_u64_u8(key_vec)); - + uint64x2_t key_vec = XXH_vld1q_u64(xsecret + (i * 16)); + uint64x2_t data_key = veorq_u64(data_vec, key_vec); /* xacc[i] *= XXH_PRIME32_1 */ - uint32x2_t data_key_lo, data_key_hi; - /* data_key_lo = (uint32x2_t) (xacc[i] & 0xFFFFFFFF); - * data_key_hi = (uint32x2_t) (xacc[i] >> 32); - * xacc[i] = UNDEFINED; */ - XXH_SPLIT_IN_PLACE(data_key, data_key_lo, data_key_hi); - { /* - * prod_hi = (data_key >> 32) * XXH_PRIME32_1; - * - * Avoid vmul_u32 + vshll_n_u32 since Clang 6 and 7 will - * incorrectly "optimize" this: - * tmp = vmul_u32(vmovn_u64(a), vmovn_u64(b)); - * shifted = vshll_n_u32(tmp, 32); - * to this: - * tmp = "vmulq_u64"(a, b); // no such thing! - * shifted = vshlq_n_u64(tmp, 32); - * - * However, unlike SSE, Clang lacks a 64-bit multiply routine - * for NEON, and it scalarizes two 64-bit multiplies instead. - * - * vmull_u32 has the same timing as vmul_u32, and it avoids - * this bug completely. - * See https://bugs.llvm.org/show_bug.cgi?id=39967 - */ - uint64x2_t prod_hi = vmull_u32 (data_key_hi, prime); - /* xacc[i] = prod_hi << 32; */ - xacc[i] = vshlq_n_u64(prod_hi, 32); - /* xacc[i] += (prod_hi & 0xFFFFFFFF) * XXH_PRIME32_1; */ - xacc[i] = vmlal_u32(xacc[i], data_key_lo, prime); - } - } } +#ifdef __wasm_simd128__ + /* SIMD128 has multiply by u64x2, use it instead of expanding and scalarizing */ + xacc[i] = data_key * XXH_PRIME32_1; +#else + /* + * Expanded version with portable NEON intrinsics + * + * lo(x) * lo(y) + (hi(x) * lo(y) << 32) + * + * prod_hi = hi(data_key) * lo(prime) << 32 + * + * Since we only need 32 bits of this multiply a trick can be used, reinterpreting the vector + * as a uint32x4_t and multiplying by { 0, prime, 0, prime } to cancel out the unwanted bits + * and avoid the shift. + */ + uint32x4_t prod_hi = vmulq_u32 (vreinterpretq_u32_u64(data_key), kPrimeHi); + /* Extract low bits for vmlal_u32 */ + uint32x2_t data_key_lo = vmovn_u64(data_key); + /* xacc[i] = prod_hi + lo(data_key) * XXH_PRIME32_1; */ + xacc[i] = vmlal_u32(vreinterpretq_u64_u32(prod_hi), data_key_lo, kPrimeLo); +#endif + } + } } - #endif #if (XXH_VECTOR == XXH_VSX) @@ -4159,23 +5110,23 @@ XXH3_accumulate_512_vsx( void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) { /* presumed aligned */ - unsigned int* const xacc = (unsigned int*) acc; - xxh_u64x2 const* const xinput = (xxh_u64x2 const*) input; /* no alignment restriction */ - xxh_u64x2 const* const xsecret = (xxh_u64x2 const*) secret; /* no alignment restriction */ + xxh_aliasing_u64x2* const xacc = (xxh_aliasing_u64x2*) acc; + xxh_u8 const* const xinput = (xxh_u8 const*) input; /* no alignment restriction */ + xxh_u8 const* const xsecret = (xxh_u8 const*) secret; /* no alignment restriction */ xxh_u64x2 const v32 = { 32, 32 }; size_t i; for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) { /* data_vec = xinput[i]; */ - xxh_u64x2 const data_vec = XXH_vec_loadu(xinput + i); + xxh_u64x2 const data_vec = XXH_vec_loadu(xinput + 16*i); /* key_vec = xsecret[i]; */ - xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + i); + xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + 16*i); xxh_u64x2 const data_key = data_vec ^ key_vec; /* shuffled = (data_key << 32) | (data_key >> 32); */ xxh_u32x4 const shuffled = (xxh_u32x4)vec_rl(data_key, v32); /* product = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)shuffled & 0xFFFFFFFF); */ xxh_u64x2 const product = XXH_vec_mulo((xxh_u32x4)data_key, shuffled); /* acc_vec = xacc[i]; */ - xxh_u64x2 acc_vec = (xxh_u64x2)vec_xl(0, xacc + 4 * i); + xxh_u64x2 acc_vec = xacc[i]; acc_vec += product; /* swap high and low halves */ @@ -4184,18 +5135,18 @@ XXH3_accumulate_512_vsx( void* XXH_RESTRICT acc, #else acc_vec += vec_xxpermdi(data_vec, data_vec, 2); #endif - /* xacc[i] = acc_vec; */ - vec_xst((xxh_u32x4)acc_vec, 0, xacc + 4 * i); + xacc[i] = acc_vec; } } +XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(vsx) XXH_FORCE_INLINE void XXH3_scrambleAcc_vsx(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) { XXH_ASSERT((((size_t)acc) & 15) == 0); - { xxh_u64x2* const xacc = (xxh_u64x2*) acc; - const xxh_u64x2* const xsecret = (const xxh_u64x2*) secret; + { xxh_aliasing_u64x2* const xacc = (xxh_aliasing_u64x2*) acc; + const xxh_u8* const xsecret = (const xxh_u8*) secret; /* constants */ xxh_u64x2 const v32 = { 32, 32 }; xxh_u64x2 const v47 = { 47, 47 }; @@ -4207,7 +5158,7 @@ XXH3_scrambleAcc_vsx(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) xxh_u64x2 const data_vec = acc_vec ^ (acc_vec >> v47); /* xacc[i] ^= xsecret[i]; */ - xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + i); + xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + 16*i); xxh_u64x2 const data_key = data_vec ^ key_vec; /* xacc[i] *= XXH_PRIME32_1 */ @@ -4221,40 +5172,233 @@ XXH3_scrambleAcc_vsx(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) #endif +#if (XXH_VECTOR == XXH_SVE) + +XXH_FORCE_INLINE void +XXH3_accumulate_512_sve( void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + uint64_t *xacc = (uint64_t *)acc; + const uint64_t *xinput = (const uint64_t *)(const void *)input; + const uint64_t *xsecret = (const uint64_t *)(const void *)secret; + svuint64_t kSwap = sveor_n_u64_z(svptrue_b64(), svindex_u64(0, 1), 1); + uint64_t element_count = svcntd(); + if (element_count >= 8) { + svbool_t mask = svptrue_pat_b64(SV_VL8); + svuint64_t vacc = svld1_u64(mask, xacc); + ACCRND(vacc, 0); + svst1_u64(mask, xacc, vacc); + } else if (element_count == 2) { /* sve128 */ + svbool_t mask = svptrue_pat_b64(SV_VL2); + svuint64_t acc0 = svld1_u64(mask, xacc + 0); + svuint64_t acc1 = svld1_u64(mask, xacc + 2); + svuint64_t acc2 = svld1_u64(mask, xacc + 4); + svuint64_t acc3 = svld1_u64(mask, xacc + 6); + ACCRND(acc0, 0); + ACCRND(acc1, 2); + ACCRND(acc2, 4); + ACCRND(acc3, 6); + svst1_u64(mask, xacc + 0, acc0); + svst1_u64(mask, xacc + 2, acc1); + svst1_u64(mask, xacc + 4, acc2); + svst1_u64(mask, xacc + 6, acc3); + } else { + svbool_t mask = svptrue_pat_b64(SV_VL4); + svuint64_t acc0 = svld1_u64(mask, xacc + 0); + svuint64_t acc1 = svld1_u64(mask, xacc + 4); + ACCRND(acc0, 0); + ACCRND(acc1, 4); + svst1_u64(mask, xacc + 0, acc0); + svst1_u64(mask, xacc + 4, acc1); + } +} + +XXH_FORCE_INLINE void +XXH3_accumulate_sve(xxh_u64* XXH_RESTRICT acc, + const xxh_u8* XXH_RESTRICT input, + const xxh_u8* XXH_RESTRICT secret, + size_t nbStripes) +{ + if (nbStripes != 0) { + uint64_t *xacc = (uint64_t *)acc; + const uint64_t *xinput = (const uint64_t *)(const void *)input; + const uint64_t *xsecret = (const uint64_t *)(const void *)secret; + svuint64_t kSwap = sveor_n_u64_z(svptrue_b64(), svindex_u64(0, 1), 1); + uint64_t element_count = svcntd(); + if (element_count >= 8) { + svbool_t mask = svptrue_pat_b64(SV_VL8); + svuint64_t vacc = svld1_u64(mask, xacc + 0); + do { + /* svprfd(svbool_t, void *, enum svfprop); */ + svprfd(mask, xinput + 128, SV_PLDL1STRM); + ACCRND(vacc, 0); + xinput += 8; + xsecret += 1; + nbStripes--; + } while (nbStripes != 0); + + svst1_u64(mask, xacc + 0, vacc); + } else if (element_count == 2) { /* sve128 */ + svbool_t mask = svptrue_pat_b64(SV_VL2); + svuint64_t acc0 = svld1_u64(mask, xacc + 0); + svuint64_t acc1 = svld1_u64(mask, xacc + 2); + svuint64_t acc2 = svld1_u64(mask, xacc + 4); + svuint64_t acc3 = svld1_u64(mask, xacc + 6); + do { + svprfd(mask, xinput + 128, SV_PLDL1STRM); + ACCRND(acc0, 0); + ACCRND(acc1, 2); + ACCRND(acc2, 4); + ACCRND(acc3, 6); + xinput += 8; + xsecret += 1; + nbStripes--; + } while (nbStripes != 0); + + svst1_u64(mask, xacc + 0, acc0); + svst1_u64(mask, xacc + 2, acc1); + svst1_u64(mask, xacc + 4, acc2); + svst1_u64(mask, xacc + 6, acc3); + } else { + svbool_t mask = svptrue_pat_b64(SV_VL4); + svuint64_t acc0 = svld1_u64(mask, xacc + 0); + svuint64_t acc1 = svld1_u64(mask, xacc + 4); + do { + svprfd(mask, xinput + 128, SV_PLDL1STRM); + ACCRND(acc0, 0); + ACCRND(acc1, 4); + xinput += 8; + xsecret += 1; + nbStripes--; + } while (nbStripes != 0); + + svst1_u64(mask, xacc + 0, acc0); + svst1_u64(mask, xacc + 4, acc1); + } + } +} + +#endif + /* scalar variants - universal */ +#if defined(__aarch64__) && (defined(__GNUC__) || defined(__clang__)) +/* + * In XXH3_scalarRound(), GCC and Clang have a similar codegen issue, where they + * emit an excess mask and a full 64-bit multiply-add (MADD X-form). + * + * While this might not seem like much, as AArch64 is a 64-bit architecture, only + * big Cortex designs have a full 64-bit multiplier. + * + * On the little cores, the smaller 32-bit multiplier is used, and full 64-bit + * multiplies expand to 2-3 multiplies in microcode. This has a major penalty + * of up to 4 latency cycles and 2 stall cycles in the multiply pipeline. + * + * Thankfully, AArch64 still provides the 32-bit long multiply-add (UMADDL) which does + * not have this penalty and does the mask automatically. + */ +XXH_FORCE_INLINE xxh_u64 +XXH_mult32to64_add64(xxh_u64 lhs, xxh_u64 rhs, xxh_u64 acc) +{ + xxh_u64 ret; + /* note: %x = 64-bit register, %w = 32-bit register */ + __asm__("umaddl %x0, %w1, %w2, %x3" : "=r" (ret) : "r" (lhs), "r" (rhs), "r" (acc)); + return ret; +} +#else +XXH_FORCE_INLINE xxh_u64 +XXH_mult32to64_add64(xxh_u64 lhs, xxh_u64 rhs, xxh_u64 acc) +{ + return XXH_mult32to64((xxh_u32)lhs, (xxh_u32)rhs) + acc; +} +#endif + +/*! + * @internal + * @brief Scalar round for @ref XXH3_accumulate_512_scalar(). + * + * This is extracted to its own function because the NEON path uses a combination + * of NEON and scalar. + */ +XXH_FORCE_INLINE void +XXH3_scalarRound(void* XXH_RESTRICT acc, + void const* XXH_RESTRICT input, + void const* XXH_RESTRICT secret, + size_t lane) +{ + xxh_u64* xacc = (xxh_u64*) acc; + xxh_u8 const* xinput = (xxh_u8 const*) input; + xxh_u8 const* xsecret = (xxh_u8 const*) secret; + XXH_ASSERT(lane < XXH_ACC_NB); + XXH_ASSERT(((size_t)acc & (XXH_ACC_ALIGN-1)) == 0); + { + xxh_u64 const data_val = XXH_readLE64(xinput + lane * 8); + xxh_u64 const data_key = data_val ^ XXH_readLE64(xsecret + lane * 8); + xacc[lane ^ 1] += data_val; /* swap adjacent lanes */ + xacc[lane] = XXH_mult32to64_add64(data_key /* & 0xFFFFFFFF */, data_key >> 32, xacc[lane]); + } +} + +/*! + * @internal + * @brief Processes a 64 byte block of data using the scalar path. + */ XXH_FORCE_INLINE void XXH3_accumulate_512_scalar(void* XXH_RESTRICT acc, const void* XXH_RESTRICT input, const void* XXH_RESTRICT secret) { - xxh_u64* const xacc = (xxh_u64*) acc; /* presumed aligned */ - const xxh_u8* const xinput = (const xxh_u8*) input; /* no alignment restriction */ - const xxh_u8* const xsecret = (const xxh_u8*) secret; /* no alignment restriction */ size_t i; - XXH_ASSERT(((size_t)acc & (XXH_ACC_ALIGN-1)) == 0); + /* ARM GCC refuses to unroll this loop, resulting in a 24% slowdown on ARMv6. */ +#if defined(__GNUC__) && !defined(__clang__) \ + && (defined(__arm__) || defined(__thumb2__)) \ + && defined(__ARM_FEATURE_UNALIGNED) /* no unaligned access just wastes bytes */ \ + && XXH_SIZE_OPT <= 0 +# pragma GCC unroll 8 +#endif for (i=0; i < XXH_ACC_NB; i++) { - xxh_u64 const data_val = XXH_readLE64(xinput + 8*i); - xxh_u64 const data_key = data_val ^ XXH_readLE64(xsecret + i*8); - xacc[i ^ 1] += data_val; /* swap adjacent lanes */ - xacc[i] += XXH_mult32to64(data_key & 0xFFFFFFFF, data_key >> 32); + XXH3_scalarRound(acc, input, secret, i); } } +XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(scalar) +/*! + * @internal + * @brief Scalar scramble step for @ref XXH3_scrambleAcc_scalar(). + * + * This is extracted to its own function because the NEON path uses a combination + * of NEON and scalar. + */ XXH_FORCE_INLINE void -XXH3_scrambleAcc_scalar(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +XXH3_scalarScrambleRound(void* XXH_RESTRICT acc, + void const* XXH_RESTRICT secret, + size_t lane) { xxh_u64* const xacc = (xxh_u64*) acc; /* presumed aligned */ const xxh_u8* const xsecret = (const xxh_u8*) secret; /* no alignment restriction */ - size_t i; XXH_ASSERT((((size_t)acc) & (XXH_ACC_ALIGN-1)) == 0); - for (i=0; i < XXH_ACC_NB; i++) { - xxh_u64 const key64 = XXH_readLE64(xsecret + 8*i); - xxh_u64 acc64 = xacc[i]; + XXH_ASSERT(lane < XXH_ACC_NB); + { + xxh_u64 const key64 = XXH_readLE64(xsecret + lane * 8); + xxh_u64 acc64 = xacc[lane]; acc64 = XXH_xorshift64(acc64, 47); acc64 ^= key64; acc64 *= XXH_PRIME32_1; - xacc[i] = acc64; + xacc[lane] = acc64; + } +} + +/*! + * @internal + * @brief Scrambles the accumulators after a large chunk has been read + */ +XXH_FORCE_INLINE void +XXH3_scrambleAcc_scalar(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + size_t i; + for (i=0; i < XXH_ACC_NB; i++) { + XXH3_scalarScrambleRound(acc, secret, i); } } @@ -4269,15 +5413,16 @@ XXH3_initCustomSecret_scalar(void* XXH_RESTRICT customSecret, xxh_u64 seed64) const xxh_u8* kSecretPtr = XXH3_kSecret; XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0); -#if defined(__clang__) && defined(__aarch64__) +#if defined(__GNUC__) && defined(__aarch64__) /* * UGLY HACK: - * Clang generates a bunch of MOV/MOVK pairs for aarch64, and they are + * GCC and Clang generate a bunch of MOV/MOVK pairs for aarch64, and they are * placed sequentially, in order, at the top of the unrolled loop. * * While MOVK is great for generating constants (2 cycles for a 64-bit - * constant compared to 4 cycles for LDR), long MOVK chains stall the - * integer pipelines: + * constant compared to 4 cycles for LDR), it fights for bandwidth with + * the arithmetic instructions. + * * I L S * MOVK * MOVK @@ -4286,7 +5431,7 @@ XXH3_initCustomSecret_scalar(void* XXH_RESTRICT customSecret, xxh_u64 seed64) * ADD * SUB STR * STR - * By forcing loads from memory (as the asm line causes Clang to assume + * By forcing loads from memory (as the asm line causes the compiler to assume * that XXH3_kSecretPtr has been changed), the pipelines are used more * efficiently: * I L S @@ -4294,23 +5439,20 @@ XXH3_initCustomSecret_scalar(void* XXH_RESTRICT customSecret, xxh_u64 seed64) * ADD LDR * SUB STR * STR + * + * See XXH3_NEON_LANES for details on the pipsline. + * * XXH3_64bits_withSeed, len == 256, Snapdragon 835 * without hack: 2654.4 MB/s * with hack: 3202.9 MB/s */ XXH_COMPILER_GUARD(kSecretPtr); #endif - /* - * Note: in debug mode, this overrides the asm optimization - * and Clang will emit MOVK chains again. - */ - XXH_ASSERT(kSecretPtr == XXH3_kSecret); - { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / 16; int i; for (i=0; i < nbRounds; i++) { /* - * The asm hack causes Clang to assume that kSecretPtr aliases with + * The asm hack causes the compiler to assume that kSecretPtr aliases with * customSecret, and on aarch64, this prevented LDP from merging two * loads together for free. Putting the loads together before the stores * properly generates LDP. @@ -4323,7 +5465,7 @@ XXH3_initCustomSecret_scalar(void* XXH_RESTRICT customSecret, xxh_u64 seed64) } -typedef void (*XXH3_f_accumulate_512)(void* XXH_RESTRICT, const void*, const void*); +typedef void (*XXH3_f_accumulate)(xxh_u64* XXH_RESTRICT, const xxh_u8* XXH_RESTRICT, const xxh_u8* XXH_RESTRICT, size_t); typedef void (*XXH3_f_scrambleAcc)(void* XXH_RESTRICT, const void*); typedef void (*XXH3_f_initCustomSecret)(void* XXH_RESTRICT, xxh_u64); @@ -4331,82 +5473,63 @@ typedef void (*XXH3_f_initCustomSecret)(void* XXH_RESTRICT, xxh_u64); #if (XXH_VECTOR == XXH_AVX512) #define XXH3_accumulate_512 XXH3_accumulate_512_avx512 +#define XXH3_accumulate XXH3_accumulate_avx512 #define XXH3_scrambleAcc XXH3_scrambleAcc_avx512 #define XXH3_initCustomSecret XXH3_initCustomSecret_avx512 #elif (XXH_VECTOR == XXH_AVX2) #define XXH3_accumulate_512 XXH3_accumulate_512_avx2 +#define XXH3_accumulate XXH3_accumulate_avx2 #define XXH3_scrambleAcc XXH3_scrambleAcc_avx2 #define XXH3_initCustomSecret XXH3_initCustomSecret_avx2 #elif (XXH_VECTOR == XXH_SSE2) #define XXH3_accumulate_512 XXH3_accumulate_512_sse2 +#define XXH3_accumulate XXH3_accumulate_sse2 #define XXH3_scrambleAcc XXH3_scrambleAcc_sse2 #define XXH3_initCustomSecret XXH3_initCustomSecret_sse2 #elif (XXH_VECTOR == XXH_NEON) #define XXH3_accumulate_512 XXH3_accumulate_512_neon +#define XXH3_accumulate XXH3_accumulate_neon #define XXH3_scrambleAcc XXH3_scrambleAcc_neon #define XXH3_initCustomSecret XXH3_initCustomSecret_scalar #elif (XXH_VECTOR == XXH_VSX) #define XXH3_accumulate_512 XXH3_accumulate_512_vsx +#define XXH3_accumulate XXH3_accumulate_vsx #define XXH3_scrambleAcc XXH3_scrambleAcc_vsx #define XXH3_initCustomSecret XXH3_initCustomSecret_scalar +#elif (XXH_VECTOR == XXH_SVE) +#define XXH3_accumulate_512 XXH3_accumulate_512_sve +#define XXH3_accumulate XXH3_accumulate_sve +#define XXH3_scrambleAcc XXH3_scrambleAcc_scalar +#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar + #else /* scalar */ #define XXH3_accumulate_512 XXH3_accumulate_512_scalar +#define XXH3_accumulate XXH3_accumulate_scalar #define XXH3_scrambleAcc XXH3_scrambleAcc_scalar #define XXH3_initCustomSecret XXH3_initCustomSecret_scalar #endif - - -#ifndef XXH_PREFETCH_DIST -# ifdef __clang__ -# define XXH_PREFETCH_DIST 320 -# else -# if (XXH_VECTOR == XXH_AVX512) -# define XXH_PREFETCH_DIST 512 -# else -# define XXH_PREFETCH_DIST 384 -# endif -# endif /* __clang__ */ -#endif /* XXH_PREFETCH_DIST */ - -/* - * XXH3_accumulate() - * Loops over XXH3_accumulate_512(). - * Assumption: nbStripes will not overflow the secret size - */ -XXH_FORCE_INLINE void -XXH3_accumulate( xxh_u64* XXH_RESTRICT acc, - const xxh_u8* XXH_RESTRICT input, - const xxh_u8* XXH_RESTRICT secret, - size_t nbStripes, - XXH3_f_accumulate_512 f_acc512) -{ - size_t n; - for (n = 0; n < nbStripes; n++ ) { - const xxh_u8* const in = input + n*XXH_STRIPE_LEN; - XXH_PREFETCH(in + XXH_PREFETCH_DIST); - f_acc512(acc, - in, - secret + n*XXH_SECRET_CONSUME_RATE); - } -} +#if XXH_SIZE_OPT >= 1 /* don't do SIMD for initialization */ +# undef XXH3_initCustomSecret +# define XXH3_initCustomSecret XXH3_initCustomSecret_scalar +#endif XXH_FORCE_INLINE void XXH3_hashLong_internal_loop(xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT input, size_t len, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, - XXH3_f_accumulate_512 f_acc512, + XXH3_f_accumulate f_acc, XXH3_f_scrambleAcc f_scramble) { size_t const nbStripesPerBlock = (secretSize - XXH_STRIPE_LEN) / XXH_SECRET_CONSUME_RATE; @@ -4418,7 +5541,7 @@ XXH3_hashLong_internal_loop(xxh_u64* XXH_RESTRICT acc, XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); for (n = 0; n < nb_blocks; n++) { - XXH3_accumulate(acc, input + n*block_len, secret, nbStripesPerBlock, f_acc512); + f_acc(acc, input + n*block_len, secret, nbStripesPerBlock); f_scramble(acc, secret + secretSize - XXH_STRIPE_LEN); } @@ -4426,12 +5549,12 @@ XXH3_hashLong_internal_loop(xxh_u64* XXH_RESTRICT acc, XXH_ASSERT(len > XXH_STRIPE_LEN); { size_t const nbStripes = ((len - 1) - (block_len * nb_blocks)) / XXH_STRIPE_LEN; XXH_ASSERT(nbStripes <= (secretSize / XXH_SECRET_CONSUME_RATE)); - XXH3_accumulate(acc, input + nb_blocks*block_len, secret, nbStripes, f_acc512); + f_acc(acc, input + nb_blocks*block_len, secret, nbStripes); /* last stripe */ { const xxh_u8* const p = input + len - XXH_STRIPE_LEN; #define XXH_SECRET_LASTACC_START 7 /* not aligned on 8, last secret is different from acc & scrambler */ - f_acc512(acc, p, secret + secretSize - XXH_STRIPE_LEN - XXH_SECRET_LASTACC_START); + XXH3_accumulate_512(acc, p, secret + secretSize - XXH_STRIPE_LEN - XXH_SECRET_LASTACC_START); } } } @@ -4476,12 +5599,12 @@ XXH3_mergeAccs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secre XXH_FORCE_INLINE XXH64_hash_t XXH3_hashLong_64b_internal(const void* XXH_RESTRICT input, size_t len, const void* XXH_RESTRICT secret, size_t secretSize, - XXH3_f_accumulate_512 f_acc512, + XXH3_f_accumulate f_acc, XXH3_f_scrambleAcc f_scramble) { XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC; - XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, (const xxh_u8*)secret, secretSize, f_acc512, f_scramble); + XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, (const xxh_u8*)secret, secretSize, f_acc, f_scramble); /* converge into final hash */ XXH_STATIC_ASSERT(sizeof(acc) == 64); @@ -4495,13 +5618,15 @@ XXH3_hashLong_64b_internal(const void* XXH_RESTRICT input, size_t len, * It's important for performance to transmit secret's size (when it's static) * so that the compiler can properly optimize the vectorized loop. * This makes a big performance difference for "medium" keys (<1 KB) when using AVX instruction set. + * When the secret size is unknown, or on GCC 12 where the mix of NO_INLINE and FORCE_INLINE + * breaks -Og, this is XXH_NO_INLINE. */ XXH3_WITH_SECRET_INLINE XXH64_hash_t XXH3_hashLong_64b_withSecret(const void* XXH_RESTRICT input, size_t len, XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) { (void)seed64; - return XXH3_hashLong_64b_internal(input, len, secret, secretLen, XXH3_accumulate_512, XXH3_scrambleAcc); + return XXH3_hashLong_64b_internal(input, len, secret, secretLen, XXH3_accumulate, XXH3_scrambleAcc); } /* @@ -4510,12 +5635,12 @@ XXH3_hashLong_64b_withSecret(const void* XXH_RESTRICT input, size_t len, * Note that inside this no_inline function, we do inline the internal loop, * and provide a statically defined secret size to allow optimization of vector loop. */ -XXH_NO_INLINE XXH64_hash_t +XXH_NO_INLINE XXH_PUREF XXH64_hash_t XXH3_hashLong_64b_default(const void* XXH_RESTRICT input, size_t len, XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) { (void)seed64; (void)secret; (void)secretLen; - return XXH3_hashLong_64b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_accumulate_512, XXH3_scrambleAcc); + return XXH3_hashLong_64b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_accumulate, XXH3_scrambleAcc); } /* @@ -4532,18 +5657,20 @@ XXH3_hashLong_64b_default(const void* XXH_RESTRICT input, size_t len, XXH_FORCE_INLINE XXH64_hash_t XXH3_hashLong_64b_withSeed_internal(const void* input, size_t len, XXH64_hash_t seed, - XXH3_f_accumulate_512 f_acc512, + XXH3_f_accumulate f_acc, XXH3_f_scrambleAcc f_scramble, XXH3_f_initCustomSecret f_initSec) { +#if XXH_SIZE_OPT <= 0 if (seed == 0) return XXH3_hashLong_64b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), - f_acc512, f_scramble); + f_acc, f_scramble); +#endif { XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE]; f_initSec(secret, seed); return XXH3_hashLong_64b_internal(input, len, secret, sizeof(secret), - f_acc512, f_scramble); + f_acc, f_scramble); } } @@ -4551,12 +5678,12 @@ XXH3_hashLong_64b_withSeed_internal(const void* input, size_t len, * It's important for performance that XXH3_hashLong is not inlined. */ XXH_NO_INLINE XXH64_hash_t -XXH3_hashLong_64b_withSeed(const void* input, size_t len, - XXH64_hash_t seed, const xxh_u8* secret, size_t secretLen) +XXH3_hashLong_64b_withSeed(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) { (void)secret; (void)secretLen; return XXH3_hashLong_64b_withSeed_internal(input, len, seed, - XXH3_accumulate_512, XXH3_scrambleAcc, XXH3_initCustomSecret); + XXH3_accumulate, XXH3_scrambleAcc, XXH3_initCustomSecret); } @@ -4588,37 +5715,37 @@ XXH3_64bits_internal(const void* XXH_RESTRICT input, size_t len, /* === Public entry point === */ -/*! @ingroup xxh3_family */ -XXH_PUBLIC_API XXH64_hash_t XXH3_64bits(const void* input, size_t len) +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits(XXH_NOESCAPE const void* input, size_t length) { - return XXH3_64bits_internal(input, len, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_default); + return XXH3_64bits_internal(input, length, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_default); } -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH64_hash_t -XXH3_64bits_withSecret(const void* input, size_t len, const void* secret, size_t secretSize) +XXH3_64bits_withSecret(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize) { - return XXH3_64bits_internal(input, len, 0, secret, secretSize, XXH3_hashLong_64b_withSecret); + return XXH3_64bits_internal(input, length, 0, secret, secretSize, XXH3_hashLong_64b_withSecret); } -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH64_hash_t -XXH3_64bits_withSeed(const void* input, size_t len, XXH64_hash_t seed) +XXH3_64bits_withSeed(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed) { - return XXH3_64bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_withSeed); + return XXH3_64bits_internal(input, length, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_withSeed); } XXH_PUBLIC_API XXH64_hash_t -XXH3_64bits_withSecretandSeed(const void* input, size_t len, const void* secret, size_t secretSize, XXH64_hash_t seed) +XXH3_64bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed) { - if (len <= XXH3_MIDSIZE_MAX) - return XXH3_64bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL); - return XXH3_hashLong_64b_withSecret(input, len, seed, (const xxh_u8*)secret, secretSize); + if (length <= XXH3_MIDSIZE_MAX) + return XXH3_64bits_internal(input, length, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL); + return XXH3_hashLong_64b_withSecret(input, length, seed, (const xxh_u8*)secret, secretSize); } /* === XXH3 streaming === */ - +#ifndef XXH_NO_STREAM /* * Malloc's a pointer that is always aligned to align. * @@ -4642,7 +5769,7 @@ XXH3_64bits_withSecretandSeed(const void* input, size_t len, const void* secret, * * Align must be a power of 2 and 8 <= align <= 128. */ -static void* XXH_alignedMalloc(size_t s, size_t align) +static XXH_MALLOCF void* XXH_alignedMalloc(size_t s, size_t align) { XXH_ASSERT(align <= 128 && align >= 8); /* range check */ XXH_ASSERT((align & (align-1)) == 0); /* power of 2 */ @@ -4684,7 +5811,13 @@ static void XXH_alignedFree(void* p) XXH_free(base); } } -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ +/*! + * @brief Allocate an @ref XXH3_state_t. + * + * Must be freed with XXH3_freeState(). + * @return An allocated XXH3_state_t on success, `NULL` on failure. + */ XXH_PUBLIC_API XXH3_state_t* XXH3_createState(void) { XXH3_state_t* const state = (XXH3_state_t*)XXH_alignedMalloc(sizeof(XXH3_state_t), 64); @@ -4693,16 +5826,23 @@ XXH_PUBLIC_API XXH3_state_t* XXH3_createState(void) return state; } -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ +/*! + * @brief Frees an @ref XXH3_state_t. + * + * Must be allocated with XXH3_createState(). + * @param statePtr A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState(). + * @return XXH_OK. + */ XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr) { XXH_alignedFree(statePtr); return XXH_OK; } -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ XXH_PUBLIC_API void -XXH3_copyState(XXH3_state_t* dst_state, const XXH3_state_t* src_state) +XXH3_copyState(XXH_NOESCAPE XXH3_state_t* dst_state, XXH_NOESCAPE const XXH3_state_t* src_state) { XXH_memcpy(dst_state, src_state, sizeof(*dst_state)); } @@ -4734,18 +5874,18 @@ XXH3_reset_internal(XXH3_state_t* statePtr, statePtr->nbStripesPerBlock = statePtr->secretLimit / XXH_SECRET_CONSUME_RATE; } -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode -XXH3_64bits_reset(XXH3_state_t* statePtr) +XXH3_64bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr) { if (statePtr == NULL) return XXH_ERROR; XXH3_reset_internal(statePtr, 0, XXH3_kSecret, XXH_SECRET_DEFAULT_SIZE); return XXH_OK; } -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode -XXH3_64bits_reset_withSecret(XXH3_state_t* statePtr, const void* secret, size_t secretSize) +XXH3_64bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize) { if (statePtr == NULL) return XXH_ERROR; XXH3_reset_internal(statePtr, 0, secret, secretSize); @@ -4754,9 +5894,9 @@ XXH3_64bits_reset_withSecret(XXH3_state_t* statePtr, const void* secret, size_t return XXH_OK; } -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode -XXH3_64bits_reset_withSeed(XXH3_state_t* statePtr, XXH64_hash_t seed) +XXH3_64bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed) { if (statePtr == NULL) return XXH_ERROR; if (seed==0) return XXH3_64bits_reset(statePtr); @@ -4766,9 +5906,9 @@ XXH3_64bits_reset_withSeed(XXH3_state_t* statePtr, XXH64_hash_t seed) return XXH_OK; } -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode -XXH3_64bits_reset_withSecretandSeed(XXH3_state_t* statePtr, const void* secret, size_t secretSize, XXH64_hash_t seed64) +XXH3_64bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed64) { if (statePtr == NULL) return XXH_ERROR; if (secret == NULL) return XXH_ERROR; @@ -4778,35 +5918,61 @@ XXH3_64bits_reset_withSecretandSeed(XXH3_state_t* statePtr, const void* secret, return XXH_OK; } -/* Note : when XXH3_consumeStripes() is invoked, - * there must be a guarantee that at least one more byte must be consumed from input - * so that the function can blindly consume all stripes using the "normal" secret segment */ -XXH_FORCE_INLINE void +/*! + * @internal + * @brief Processes a large input for XXH3_update() and XXH3_digest_long(). + * + * Unlike XXH3_hashLong_internal_loop(), this can process data that overlaps a block. + * + * @param acc Pointer to the 8 accumulator lanes + * @param nbStripesSoFarPtr In/out pointer to the number of leftover stripes in the block* + * @param nbStripesPerBlock Number of stripes in a block + * @param input Input pointer + * @param nbStripes Number of stripes to process + * @param secret Secret pointer + * @param secretLimit Offset of the last block in @p secret + * @param f_acc Pointer to an XXH3_accumulate implementation + * @param f_scramble Pointer to an XXH3_scrambleAcc implementation + * @return Pointer past the end of @p input after processing + */ +XXH_FORCE_INLINE const xxh_u8 * XXH3_consumeStripes(xxh_u64* XXH_RESTRICT acc, size_t* XXH_RESTRICT nbStripesSoFarPtr, size_t nbStripesPerBlock, const xxh_u8* XXH_RESTRICT input, size_t nbStripes, const xxh_u8* XXH_RESTRICT secret, size_t secretLimit, - XXH3_f_accumulate_512 f_acc512, + XXH3_f_accumulate f_acc, XXH3_f_scrambleAcc f_scramble) { - XXH_ASSERT(nbStripes <= nbStripesPerBlock); /* can handle max 1 scramble per invocation */ - XXH_ASSERT(*nbStripesSoFarPtr < nbStripesPerBlock); - if (nbStripesPerBlock - *nbStripesSoFarPtr <= nbStripes) { - /* need a scrambling operation */ - size_t const nbStripesToEndofBlock = nbStripesPerBlock - *nbStripesSoFarPtr; - size_t const nbStripesAfterBlock = nbStripes - nbStripesToEndofBlock; - XXH3_accumulate(acc, input, secret + nbStripesSoFarPtr[0] * XXH_SECRET_CONSUME_RATE, nbStripesToEndofBlock, f_acc512); - f_scramble(acc, secret + secretLimit); - XXH3_accumulate(acc, input + nbStripesToEndofBlock * XXH_STRIPE_LEN, secret, nbStripesAfterBlock, f_acc512); - *nbStripesSoFarPtr = nbStripesAfterBlock; - } else { - XXH3_accumulate(acc, input, secret + nbStripesSoFarPtr[0] * XXH_SECRET_CONSUME_RATE, nbStripes, f_acc512); + const xxh_u8* initialSecret = secret + *nbStripesSoFarPtr * XXH_SECRET_CONSUME_RATE; + /* Process full blocks */ + if (nbStripes >= (nbStripesPerBlock - *nbStripesSoFarPtr)) { + /* Process the initial partial block... */ + size_t nbStripesThisIter = nbStripesPerBlock - *nbStripesSoFarPtr; + + do { + /* Accumulate and scramble */ + f_acc(acc, input, initialSecret, nbStripesThisIter); + f_scramble(acc, secret + secretLimit); + input += nbStripesThisIter * XXH_STRIPE_LEN; + nbStripes -= nbStripesThisIter; + /* Then continue the loop with the full block size */ + nbStripesThisIter = nbStripesPerBlock; + initialSecret = secret; + } while (nbStripes >= nbStripesPerBlock); + *nbStripesSoFarPtr = 0; + } + /* Process a partial block */ + if (nbStripes > 0) { + f_acc(acc, input, initialSecret, nbStripes); + input += nbStripes * XXH_STRIPE_LEN; *nbStripesSoFarPtr += nbStripes; } + /* Return end pointer */ + return input; } #ifndef XXH3_STREAM_USE_STACK -# ifndef __clang__ /* clang doesn't need additional stack space */ +# if XXH_SIZE_OPT <= 0 && !defined(__clang__) /* clang doesn't need additional stack space */ # define XXH3_STREAM_USE_STACK 1 # endif #endif @@ -4816,7 +5982,7 @@ XXH3_consumeStripes(xxh_u64* XXH_RESTRICT acc, XXH_FORCE_INLINE XXH_errorcode XXH3_update(XXH3_state_t* XXH_RESTRICT const state, const xxh_u8* XXH_RESTRICT input, size_t len, - XXH3_f_accumulate_512 f_acc512, + XXH3_f_accumulate f_acc, XXH3_f_scrambleAcc f_scramble) { if (input==NULL) { @@ -4832,7 +5998,8 @@ XXH3_update(XXH3_state_t* XXH_RESTRICT const state, * when operating accumulators directly into state. * Operating into stack space seems to enable proper optimization. * clang, on the other hand, doesn't seem to need this trick */ - XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[8]; memcpy(acc, state->acc, sizeof(acc)); + XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[8]; + XXH_memcpy(acc, state->acc, sizeof(acc)); #else xxh_u64* XXH_RESTRICT const acc = state->acc; #endif @@ -4840,7 +6007,7 @@ XXH3_update(XXH3_state_t* XXH_RESTRICT const state, XXH_ASSERT(state->bufferedSize <= XXH3_INTERNALBUFFER_SIZE); /* small input : just fill in tmp buffer */ - if (state->bufferedSize + len <= XXH3_INTERNALBUFFER_SIZE) { + if (len <= XXH3_INTERNALBUFFER_SIZE - state->bufferedSize) { XXH_memcpy(state->buffer + state->bufferedSize, input, len); state->bufferedSize += (XXH32_hash_t)len; return XXH_OK; @@ -4862,57 +6029,20 @@ XXH3_update(XXH3_state_t* XXH_RESTRICT const state, &state->nbStripesSoFar, state->nbStripesPerBlock, state->buffer, XXH3_INTERNALBUFFER_STRIPES, secret, state->secretLimit, - f_acc512, f_scramble); + f_acc, f_scramble); state->bufferedSize = 0; } XXH_ASSERT(input < bEnd); - - /* large input to consume : ingest per full block */ - if ((size_t)(bEnd - input) > state->nbStripesPerBlock * XXH_STRIPE_LEN) { + if (bEnd - input > XXH3_INTERNALBUFFER_SIZE) { size_t nbStripes = (size_t)(bEnd - 1 - input) / XXH_STRIPE_LEN; - XXH_ASSERT(state->nbStripesPerBlock >= state->nbStripesSoFar); - /* join to current block's end */ - { size_t const nbStripesToEnd = state->nbStripesPerBlock - state->nbStripesSoFar; - XXH_ASSERT(nbStripes <= nbStripes); - XXH3_accumulate(acc, input, secret + state->nbStripesSoFar * XXH_SECRET_CONSUME_RATE, nbStripesToEnd, f_acc512); - f_scramble(acc, secret + state->secretLimit); - state->nbStripesSoFar = 0; - input += nbStripesToEnd * XXH_STRIPE_LEN; - nbStripes -= nbStripesToEnd; - } - /* consume per entire blocks */ - while(nbStripes >= state->nbStripesPerBlock) { - XXH3_accumulate(acc, input, secret, state->nbStripesPerBlock, f_acc512); - f_scramble(acc, secret + state->secretLimit); - input += state->nbStripesPerBlock * XXH_STRIPE_LEN; - nbStripes -= state->nbStripesPerBlock; - } - /* consume last partial block */ - XXH3_accumulate(acc, input, secret, nbStripes, f_acc512); - input += nbStripes * XXH_STRIPE_LEN; - XXH_ASSERT(input < bEnd); /* at least some bytes left */ - state->nbStripesSoFar = nbStripes; - /* buffer predecessor of last partial stripe */ - XXH_memcpy(state->buffer + sizeof(state->buffer) - XXH_STRIPE_LEN, input - XXH_STRIPE_LEN, XXH_STRIPE_LEN); - XXH_ASSERT(bEnd - input <= XXH_STRIPE_LEN); - } else { - /* content to consume <= block size */ - /* Consume input by a multiple of internal buffer size */ - if (bEnd - input > XXH3_INTERNALBUFFER_SIZE) { - const xxh_u8* const limit = bEnd - XXH3_INTERNALBUFFER_SIZE; - do { - XXH3_consumeStripes(acc, + input = XXH3_consumeStripes(acc, &state->nbStripesSoFar, state->nbStripesPerBlock, - input, XXH3_INTERNALBUFFER_STRIPES, - secret, state->secretLimit, - f_acc512, f_scramble); - input += XXH3_INTERNALBUFFER_SIZE; - } while (inputbuffer + sizeof(state->buffer) - XXH_STRIPE_LEN, input - XXH_STRIPE_LEN, XXH_STRIPE_LEN); - } - } + input, nbStripes, + secret, state->secretLimit, + f_acc, f_scramble); + XXH_memcpy(state->buffer + sizeof(state->buffer) - XXH_STRIPE_LEN, input - XXH_STRIPE_LEN, XXH_STRIPE_LEN); + } /* Some remaining input (always) : buffer it */ XXH_ASSERT(input < bEnd); XXH_ASSERT(bEnd - input <= XXH3_INTERNALBUFFER_SIZE); @@ -4921,19 +6051,19 @@ XXH3_update(XXH3_state_t* XXH_RESTRICT const state, state->bufferedSize = (XXH32_hash_t)(bEnd-input); #if defined(XXH3_STREAM_USE_STACK) && XXH3_STREAM_USE_STACK >= 1 /* save stack accumulators into state */ - memcpy(state->acc, acc, sizeof(acc)); + XXH_memcpy(state->acc, acc, sizeof(acc)); #endif } return XXH_OK; } -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode -XXH3_64bits_update(XXH3_state_t* state, const void* input, size_t len) +XXH3_64bits_update(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len) { return XXH3_update(state, (const xxh_u8*)input, len, - XXH3_accumulate_512, XXH3_scrambleAcc); + XXH3_accumulate, XXH3_scrambleAcc); } @@ -4942,37 +6072,40 @@ XXH3_digest_long (XXH64_hash_t* acc, const XXH3_state_t* state, const unsigned char* secret) { + xxh_u8 lastStripe[XXH_STRIPE_LEN]; + const xxh_u8* lastStripePtr; + /* * Digest on a local copy. This way, the state remains unaltered, and it can * continue ingesting more input afterwards. */ XXH_memcpy(acc, state->acc, sizeof(state->acc)); if (state->bufferedSize >= XXH_STRIPE_LEN) { + /* Consume remaining stripes then point to remaining data in buffer */ size_t const nbStripes = (state->bufferedSize - 1) / XXH_STRIPE_LEN; size_t nbStripesSoFar = state->nbStripesSoFar; XXH3_consumeStripes(acc, &nbStripesSoFar, state->nbStripesPerBlock, state->buffer, nbStripes, secret, state->secretLimit, - XXH3_accumulate_512, XXH3_scrambleAcc); - /* last stripe */ - XXH3_accumulate_512(acc, - state->buffer + state->bufferedSize - XXH_STRIPE_LEN, - secret + state->secretLimit - XXH_SECRET_LASTACC_START); + XXH3_accumulate, XXH3_scrambleAcc); + lastStripePtr = state->buffer + state->bufferedSize - XXH_STRIPE_LEN; } else { /* bufferedSize < XXH_STRIPE_LEN */ - xxh_u8 lastStripe[XXH_STRIPE_LEN]; + /* Copy to temp buffer */ size_t const catchupSize = XXH_STRIPE_LEN - state->bufferedSize; XXH_ASSERT(state->bufferedSize > 0); /* there is always some input buffered */ XXH_memcpy(lastStripe, state->buffer + sizeof(state->buffer) - catchupSize, catchupSize); XXH_memcpy(lastStripe + catchupSize, state->buffer, state->bufferedSize); - XXH3_accumulate_512(acc, - lastStripe, - secret + state->secretLimit - XXH_SECRET_LASTACC_START); + lastStripePtr = lastStripe; } + /* Last stripe */ + XXH3_accumulate_512(acc, + lastStripePtr, + secret + state->secretLimit - XXH_SECRET_LASTACC_START); } -/*! @ingroup xxh3_family */ -XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_digest (const XXH3_state_t* state) +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_digest (XXH_NOESCAPE const XXH3_state_t* state) { const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; if (state->totalLen > XXH3_MIDSIZE_MAX) { @@ -4988,7 +6121,7 @@ XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_digest (const XXH3_state_t* state) return XXH3_64bits_withSecret(state->buffer, (size_t)(state->totalLen), secret, state->secretLimit + XXH_STRIPE_LEN); } - +#endif /* !XXH_NO_STREAM */ /* ========================================== @@ -5008,7 +6141,7 @@ XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_digest (const XXH3_state_t* state) * fast for a _128-bit_ hash on 32-bit (it usually clears XXH64). */ -XXH_FORCE_INLINE XXH128_hash_t +XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t XXH3_len_1to3_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { /* A doubled version of 1to3_64b with different constants. */ @@ -5037,7 +6170,7 @@ XXH3_len_1to3_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_ } } -XXH_FORCE_INLINE XXH128_hash_t +XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t XXH3_len_4to8_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { XXH_ASSERT(input != NULL); @@ -5057,14 +6190,14 @@ XXH3_len_4to8_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_ m128.low64 ^= (m128.high64 >> 3); m128.low64 = XXH_xorshift64(m128.low64, 35); - m128.low64 *= 0x9FB21C651E98DF25ULL; + m128.low64 *= PRIME_MX2; m128.low64 = XXH_xorshift64(m128.low64, 28); m128.high64 = XXH3_avalanche(m128.high64); return m128; } } -XXH_FORCE_INLINE XXH128_hash_t +XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t XXH3_len_9to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { XXH_ASSERT(input != NULL); @@ -5139,7 +6272,7 @@ XXH3_len_9to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64 /* * Assumption: `secret` size is >= XXH3_SECRET_SIZE_MIN */ -XXH_FORCE_INLINE XXH128_hash_t +XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t XXH3_len_0to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { XXH_ASSERT(len <= 16); @@ -5170,7 +6303,7 @@ XXH128_mix32B(XXH128_hash_t acc, const xxh_u8* input_1, const xxh_u8* input_2, } -XXH_FORCE_INLINE XXH128_hash_t +XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t XXH3_len_17to128_128b(const xxh_u8* XXH_RESTRICT input, size_t len, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, XXH64_hash_t seed) @@ -5181,6 +6314,16 @@ XXH3_len_17to128_128b(const xxh_u8* XXH_RESTRICT input, size_t len, { XXH128_hash_t acc; acc.low64 = len * XXH_PRIME64_1; acc.high64 = 0; + +#if XXH_SIZE_OPT >= 1 + { + /* Smaller, but slightly slower. */ + unsigned int i = (unsigned int)(len - 1) / 32; + do { + acc = XXH128_mix32B(acc, input+16*i, input+len-16*(i+1), secret+32*i, seed); + } while (i-- != 0); + } +#else if (len > 32) { if (len > 64) { if (len > 96) { @@ -5191,6 +6334,7 @@ XXH3_len_17to128_128b(const xxh_u8* XXH_RESTRICT input, size_t len, acc = XXH128_mix32B(acc, input+16, input+len-32, secret+32, seed); } acc = XXH128_mix32B(acc, input, input+len-16, secret, seed); +#endif { XXH128_hash_t h128; h128.low64 = acc.low64 + acc.high64; h128.high64 = (acc.low64 * XXH_PRIME64_1) @@ -5203,7 +6347,7 @@ XXH3_len_17to128_128b(const xxh_u8* XXH_RESTRICT input, size_t len, } } -XXH_NO_INLINE XXH128_hash_t +XXH_NO_INLINE XXH_PUREF XXH128_hash_t XXH3_len_129to240_128b(const xxh_u8* XXH_RESTRICT input, size_t len, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, XXH64_hash_t seed) @@ -5212,25 +6356,34 @@ XXH3_len_129to240_128b(const xxh_u8* XXH_RESTRICT input, size_t len, XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX); { XXH128_hash_t acc; - int const nbRounds = (int)len / 32; - int i; + unsigned i; acc.low64 = len * XXH_PRIME64_1; acc.high64 = 0; - for (i=0; i<4; i++) { + /* + * We set as `i` as offset + 32. We do this so that unchanged + * `len` can be used as upper bound. This reaches a sweet spot + * where both x86 and aarch64 get simple agen and good codegen + * for the loop. + */ + for (i = 32; i < 160; i += 32) { acc = XXH128_mix32B(acc, - input + (32 * i), - input + (32 * i) + 16, - secret + (32 * i), + input + i - 32, + input + i - 16, + secret + i - 32, seed); } acc.low64 = XXH3_avalanche(acc.low64); acc.high64 = XXH3_avalanche(acc.high64); - XXH_ASSERT(nbRounds >= 4); - for (i=4 ; i < nbRounds; i++) { + /* + * NB: `i <= len` will duplicate the last 32-bytes if + * len % 32 was zero. This is an unfortunate necessity to keep + * the hash result stable. + */ + for (i=160; i <= len; i += 32) { acc = XXH128_mix32B(acc, - input + (32 * i), - input + (32 * i) + 16, - secret + XXH3_MIDSIZE_STARTOFFSET + (32 * (i - 4)), + input + i - 32, + input + i - 16, + secret + XXH3_MIDSIZE_STARTOFFSET + i - 160, seed); } /* last bytes */ @@ -5238,7 +6391,7 @@ XXH3_len_129to240_128b(const xxh_u8* XXH_RESTRICT input, size_t len, input + len - 16, input + len - 32, secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET - 16, - 0ULL - seed); + (XXH64_hash_t)0 - seed); { XXH128_hash_t h128; h128.low64 = acc.low64 + acc.high64; @@ -5255,12 +6408,12 @@ XXH3_len_129to240_128b(const xxh_u8* XXH_RESTRICT input, size_t len, XXH_FORCE_INLINE XXH128_hash_t XXH3_hashLong_128b_internal(const void* XXH_RESTRICT input, size_t len, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, - XXH3_f_accumulate_512 f_acc512, + XXH3_f_accumulate f_acc, XXH3_f_scrambleAcc f_scramble) { XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC; - XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, secret, secretSize, f_acc512, f_scramble); + XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, secret, secretSize, f_acc, f_scramble); /* converge into final hash */ XXH_STATIC_ASSERT(sizeof(acc) == 64); @@ -5278,21 +6431,24 @@ XXH3_hashLong_128b_internal(const void* XXH_RESTRICT input, size_t len, } /* - * It's important for performance that XXH3_hashLong is not inlined. + * It's important for performance that XXH3_hashLong() is not inlined. */ -XXH_NO_INLINE XXH128_hash_t +XXH_NO_INLINE XXH_PUREF XXH128_hash_t XXH3_hashLong_128b_default(const void* XXH_RESTRICT input, size_t len, XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen) { (void)seed64; (void)secret; (void)secretLen; return XXH3_hashLong_128b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), - XXH3_accumulate_512, XXH3_scrambleAcc); + XXH3_accumulate, XXH3_scrambleAcc); } /* - * It's important for performance to pass @secretLen (when it's static) + * It's important for performance to pass @p secretLen (when it's static) * to the compiler, so that it can properly optimize the vectorized loop. + * + * When the secret size is unknown, or on GCC 12 where the mix of NO_INLINE and FORCE_INLINE + * breaks -Og, this is XXH_NO_INLINE. */ XXH3_WITH_SECRET_INLINE XXH128_hash_t XXH3_hashLong_128b_withSecret(const void* XXH_RESTRICT input, size_t len, @@ -5301,24 +6457,24 @@ XXH3_hashLong_128b_withSecret(const void* XXH_RESTRICT input, size_t len, { (void)seed64; return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, secretLen, - XXH3_accumulate_512, XXH3_scrambleAcc); + XXH3_accumulate, XXH3_scrambleAcc); } XXH_FORCE_INLINE XXH128_hash_t XXH3_hashLong_128b_withSeed_internal(const void* XXH_RESTRICT input, size_t len, XXH64_hash_t seed64, - XXH3_f_accumulate_512 f_acc512, + XXH3_f_accumulate f_acc, XXH3_f_scrambleAcc f_scramble, XXH3_f_initCustomSecret f_initSec) { if (seed64 == 0) return XXH3_hashLong_128b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), - f_acc512, f_scramble); + f_acc, f_scramble); { XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE]; f_initSec(secret, seed64); return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, sizeof(secret), - f_acc512, f_scramble); + f_acc, f_scramble); } } @@ -5331,7 +6487,7 @@ XXH3_hashLong_128b_withSeed(const void* input, size_t len, { (void)secret; (void)secretLen; return XXH3_hashLong_128b_withSeed_internal(input, len, seed64, - XXH3_accumulate_512, XXH3_scrambleAcc, XXH3_initCustomSecret); + XXH3_accumulate, XXH3_scrambleAcc, XXH3_initCustomSecret); } typedef XXH128_hash_t (*XXH3_hashLong128_f)(const void* XXH_RESTRICT, size_t, @@ -5361,94 +6517,93 @@ XXH3_128bits_internal(const void* input, size_t len, /* === Public XXH128 API === */ -/*! @ingroup xxh3_family */ -XXH_PUBLIC_API XXH128_hash_t XXH3_128bits(const void* input, size_t len) +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits(XXH_NOESCAPE const void* input, size_t len) { return XXH3_128bits_internal(input, len, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_128b_default); } -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH128_hash_t -XXH3_128bits_withSecret(const void* input, size_t len, const void* secret, size_t secretSize) +XXH3_128bits_withSecret(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize) { return XXH3_128bits_internal(input, len, 0, (const xxh_u8*)secret, secretSize, XXH3_hashLong_128b_withSecret); } -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH128_hash_t -XXH3_128bits_withSeed(const void* input, size_t len, XXH64_hash_t seed) +XXH3_128bits_withSeed(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed) { return XXH3_128bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_128b_withSeed); } -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH128_hash_t -XXH3_128bits_withSecretandSeed(const void* input, size_t len, const void* secret, size_t secretSize, XXH64_hash_t seed) +XXH3_128bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed) { if (len <= XXH3_MIDSIZE_MAX) return XXH3_128bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL); return XXH3_hashLong_128b_withSecret(input, len, seed, secret, secretSize); } -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH128_hash_t -XXH128(const void* input, size_t len, XXH64_hash_t seed) +XXH128(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed) { return XXH3_128bits_withSeed(input, len, seed); } /* === XXH3 128-bit streaming === */ - +#ifndef XXH_NO_STREAM /* * All initialization and update functions are identical to 64-bit streaming variant. * The only difference is the finalization routine. */ -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode -XXH3_128bits_reset(XXH3_state_t* statePtr) +XXH3_128bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr) { return XXH3_64bits_reset(statePtr); } -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode -XXH3_128bits_reset_withSecret(XXH3_state_t* statePtr, const void* secret, size_t secretSize) +XXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize) { return XXH3_64bits_reset_withSecret(statePtr, secret, secretSize); } -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode -XXH3_128bits_reset_withSeed(XXH3_state_t* statePtr, XXH64_hash_t seed) +XXH3_128bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed) { return XXH3_64bits_reset_withSeed(statePtr, seed); } -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode -XXH3_128bits_reset_withSecretandSeed(XXH3_state_t* statePtr, const void* secret, size_t secretSize, XXH64_hash_t seed) +XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed) { return XXH3_64bits_reset_withSecretandSeed(statePtr, secret, secretSize, seed); } -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode -XXH3_128bits_update(XXH3_state_t* state, const void* input, size_t len) +XXH3_128bits_update(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len) { - return XXH3_update(state, (const xxh_u8*)input, len, - XXH3_accumulate_512, XXH3_scrambleAcc); + return XXH3_64bits_update(state, input, len); } -/*! @ingroup xxh3_family */ -XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_digest (const XXH3_state_t* state) +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE const XXH3_state_t* state) { const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; if (state->totalLen > XXH3_MIDSIZE_MAX) { @@ -5472,13 +6627,13 @@ XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_digest (const XXH3_state_t* state) return XXH3_128bits_withSecret(state->buffer, (size_t)(state->totalLen), secret, state->secretLimit + XXH_STRIPE_LEN); } - +#endif /* !XXH_NO_STREAM */ /* 128-bit utility functions */ #include /* memcmp, memcpy */ /* return : 1 is equal, 0 if different */ -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ XXH_PUBLIC_API int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2) { /* note : XXH128_hash_t is compact, it has no padding byte */ @@ -5486,11 +6641,11 @@ XXH_PUBLIC_API int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2) } /* This prototype is compatible with stdlib's qsort(). - * return : >0 if *h128_1 > *h128_2 - * <0 if *h128_1 < *h128_2 - * =0 if *h128_1 == *h128_2 */ -/*! @ingroup xxh3_family */ -XXH_PUBLIC_API int XXH128_cmp(const void* h128_1, const void* h128_2) + * @return : >0 if *h128_1 > *h128_2 + * <0 if *h128_1 < *h128_2 + * =0 if *h128_1 == *h128_2 */ +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API int XXH128_cmp(XXH_NOESCAPE const void* h128_1, XXH_NOESCAPE const void* h128_2) { XXH128_hash_t const h1 = *(const XXH128_hash_t*)h128_1; XXH128_hash_t const h2 = *(const XXH128_hash_t*)h128_2; @@ -5502,9 +6657,9 @@ XXH_PUBLIC_API int XXH128_cmp(const void* h128_1, const void* h128_2) /*====== Canonical representation ======*/ -/*! @ingroup xxh3_family */ -static zend_always_inline void -XXH128_canonicalFromHash(XXH128_canonical_t* dst, XXH128_hash_t hash) +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API void +XXH128_canonicalFromHash(XXH_NOESCAPE XXH128_canonical_t* dst, XXH128_hash_t hash) { XXH_STATIC_ASSERT(sizeof(XXH128_canonical_t) == sizeof(XXH128_hash_t)); if (XXH_CPU_LITTLE_ENDIAN) { @@ -5515,9 +6670,9 @@ XXH128_canonicalFromHash(XXH128_canonical_t* dst, XXH128_hash_t hash) XXH_memcpy((char*)dst + sizeof(hash.high64), &hash.low64, sizeof(hash.low64)); } -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH128_hash_t -XXH128_hashFromCanonical(const XXH128_canonical_t* src) +XXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t* src) { XXH128_hash_t h; h.high64 = XXH_readBE64(src); @@ -5533,26 +6688,34 @@ XXH128_hashFromCanonical(const XXH128_canonical_t* src) */ #define XXH_MIN(x, y) (((x) > (y)) ? (y) : (x)) -static void XXH3_combine16(void* dst, XXH128_hash_t h128) +XXH_FORCE_INLINE void XXH3_combine16(void* dst, XXH128_hash_t h128) { XXH_writeLE64( dst, XXH_readLE64(dst) ^ h128.low64 ); XXH_writeLE64( (char*)dst+8, XXH_readLE64((char*)dst+8) ^ h128.high64 ); } -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode -XXH3_generateSecret(void* secretBuffer, size_t secretSize, const void* customSeed, size_t customSeedSize) +XXH3_generateSecret(XXH_NOESCAPE void* secretBuffer, size_t secretSize, XXH_NOESCAPE const void* customSeed, size_t customSeedSize) { +#if (XXH_DEBUGLEVEL >= 1) XXH_ASSERT(secretBuffer != NULL); - if (secretBuffer == NULL) return XXH_ERROR; XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); +#else + /* production mode, assert() are disabled */ + if (secretBuffer == NULL) return XXH_ERROR; if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR; +#endif + if (customSeedSize == 0) { customSeed = XXH3_kSecret; customSeedSize = XXH_SECRET_DEFAULT_SIZE; } +#if (XXH_DEBUGLEVEL >= 1) XXH_ASSERT(customSeed != NULL); +#else if (customSeed == NULL) return XXH_ERROR; +#endif /* Fill secretBuffer with a copy of customSeed - repeat as needed */ { size_t pos = 0; @@ -5576,9 +6739,9 @@ XXH3_generateSecret(void* secretBuffer, size_t secretSize, const void* customSee return XXH_OK; } -/*! @ingroup xxh3_family */ +/*! @ingroup XXH3_family */ XXH_PUBLIC_API void -XXH3_generateSecret_fromSeed(void* secretBuffer, XXH64_hash_t seed) +XXH3_generateSecret_fromSeed(XXH_NOESCAPE void* secretBuffer, XXH64_hash_t seed) { XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE]; XXH3_initCustomSecret(secret, seed); @@ -5591,7 +6754,7 @@ XXH3_generateSecret_fromSeed(void* secretBuffer, XXH64_hash_t seed) /* Pop our optimization override from above */ #if XXH_VECTOR == XXH_AVX2 /* AVX2 */ \ && defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \ - && defined(__OPTIMIZE__) && !defined(__OPTIMIZE_SIZE__) /* respect -O0 and -Os */ + && defined(__OPTIMIZE__) && XXH_SIZE_OPT <= 0 /* respect -O0 and -Os */ # pragma GCC pop_options #endif @@ -5606,5 +6769,5 @@ XXH3_generateSecret_fromSeed(void* secretBuffer, XXH64_hash_t seed) #if defined (__cplusplus) -} +} /* extern "C" */ #endif diff --git a/ext/iconv/config.m4 b/ext/iconv/config.m4 index 4d0dc36489833..e86f3535a97c4 100644 --- a/ext/iconv/config.m4 +++ b/ext/iconv/config.m4 @@ -83,6 +83,20 @@ int main(void) { AS_VAR_IF([php_cv_iconv_errno], [yes],, [AC_MSG_FAILURE([The iconv check failed, 'errno' is missing.])]) + dnl iconv on some platforms (NetBSD pre-10, Solaris) may have a non-standard + dnl const input parameter; libiconv may imitate this on those platforms. + AC_CACHE_CHECK([if iconv input parameter is const (non-standard)], [php_cv_iconv_const], + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([ +#include + +size_t iconv(iconv_t cd, const char **src, size_t *srcleft, char **dst, size_t *dstleft); + ])], + [php_cv_iconv_const=const], + [php_cv_iconv_const=non-const])]) + dnl non-const is just used for display, set it back + AS_VAR_IF([php_cv_iconv_const], [non-const], + [php_cv_iconv_const=]) + AC_CACHE_CHECK([if iconv supports //IGNORE], [php_cv_iconv_ignore], [AC_RUN_IFELSE([AC_LANG_SOURCE([ #include @@ -120,7 +134,7 @@ int main(void) { PHP_NEW_EXTENSION([iconv], [iconv.c], [$ext_shared],, - [-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1]) + [-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 -DICONV_CONST=$php_cv_iconv_const]) PHP_SUBST([ICONV_SHARED_LIBADD]) PHP_INSTALL_HEADERS([ext/iconv], [php_iconv.h]) fi diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c index 157ee41a11a05..7c812f5af44b4 100644 --- a/ext/iconv/iconv.c +++ b/ext/iconv/iconv.c @@ -43,11 +43,11 @@ #undef iconv #endif -#if defined(__NetBSD__) -// unfortunately, netbsd has still the old non posix conformant signature -// libiconv tends to match the eventual system's iconv too. -#define ICONV_CONST const -#else +/* iconv can have different constiness for src on some platforms; + * this is explained in config.m4. On Windows, it's always non-const, + * but it can be awkward to set that on the command line. Do it here. + */ +#ifndef ICONV_CONST #define ICONV_CONST #endif @@ -1825,7 +1825,7 @@ PHP_FUNCTION(iconv_substr) size_t charset_len; zend_string *str; zend_long offset, length = 0; - bool len_is_null = 1; + bool len_is_null = true; php_iconv_err_t err; @@ -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/ERROR_CONVENTIONS.md b/ext/intl/ERROR_CONVENTIONS.md index af2450c8186a0..432862afd6855 100644 --- a/ext/intl/ERROR_CONVENTIONS.md +++ b/ext/intl/ERROR_CONVENTIONS.md @@ -75,7 +75,7 @@ and `intl_get_error_message()`. parsing errors), not `NULL`. Constructors and factory methods are the exception; these should return `NULL`, not `FALSE`. -Not that constructors in Intl generally (always?) don't throws exceptions. They +Note that constructors in Intl generally (always?) don't throws exceptions. They instead destroy the object to that the result of new `IntlClass()` can be `NULL`. This may be surprising. diff --git a/ext/intl/breakiterator/breakiterator_arginfo.h b/ext/intl/breakiterator/breakiterator_arginfo.h index 9475f5e987fc6..afaad17f03dbf 100644 --- a/ext/intl/breakiterator/breakiterator_arginfo.h +++ b/ext/intl/breakiterator/breakiterator_arginfo.h @@ -161,117 +161,117 @@ static zend_class_entry *register_class_IntlBreakIterator(zend_class_entry *clas zval const_DONE_value; ZVAL_LONG(&const_DONE_value, BreakIterator::DONE); - zend_string *const_DONE_name = zend_string_init_interned("DONE", sizeof("DONE") - 1, 1); + zend_string *const_DONE_name = zend_string_init_interned("DONE", sizeof("DONE") - 1, true); zend_declare_typed_class_constant(class_entry, const_DONE_name, &const_DONE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DONE_name); + zend_string_release_ex(const_DONE_name, true); zval const_WORD_NONE_value; ZVAL_LONG(&const_WORD_NONE_value, UBRK_WORD_NONE); - zend_string *const_WORD_NONE_name = zend_string_init_interned("WORD_NONE", sizeof("WORD_NONE") - 1, 1); + zend_string *const_WORD_NONE_name = zend_string_init_interned("WORD_NONE", sizeof("WORD_NONE") - 1, true); zend_declare_typed_class_constant(class_entry, const_WORD_NONE_name, &const_WORD_NONE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WORD_NONE_name); + zend_string_release_ex(const_WORD_NONE_name, true); zval const_WORD_NONE_LIMIT_value; ZVAL_LONG(&const_WORD_NONE_LIMIT_value, UBRK_WORD_NONE_LIMIT); - zend_string *const_WORD_NONE_LIMIT_name = zend_string_init_interned("WORD_NONE_LIMIT", sizeof("WORD_NONE_LIMIT") - 1, 1); + zend_string *const_WORD_NONE_LIMIT_name = zend_string_init_interned("WORD_NONE_LIMIT", sizeof("WORD_NONE_LIMIT") - 1, true); zend_declare_typed_class_constant(class_entry, const_WORD_NONE_LIMIT_name, &const_WORD_NONE_LIMIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WORD_NONE_LIMIT_name); + zend_string_release_ex(const_WORD_NONE_LIMIT_name, true); zval const_WORD_NUMBER_value; ZVAL_LONG(&const_WORD_NUMBER_value, UBRK_WORD_NUMBER); - zend_string *const_WORD_NUMBER_name = zend_string_init_interned("WORD_NUMBER", sizeof("WORD_NUMBER") - 1, 1); + zend_string *const_WORD_NUMBER_name = zend_string_init_interned("WORD_NUMBER", sizeof("WORD_NUMBER") - 1, true); zend_declare_typed_class_constant(class_entry, const_WORD_NUMBER_name, &const_WORD_NUMBER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WORD_NUMBER_name); + zend_string_release_ex(const_WORD_NUMBER_name, true); zval const_WORD_NUMBER_LIMIT_value; ZVAL_LONG(&const_WORD_NUMBER_LIMIT_value, UBRK_WORD_NUMBER_LIMIT); - zend_string *const_WORD_NUMBER_LIMIT_name = zend_string_init_interned("WORD_NUMBER_LIMIT", sizeof("WORD_NUMBER_LIMIT") - 1, 1); + zend_string *const_WORD_NUMBER_LIMIT_name = zend_string_init_interned("WORD_NUMBER_LIMIT", sizeof("WORD_NUMBER_LIMIT") - 1, true); zend_declare_typed_class_constant(class_entry, const_WORD_NUMBER_LIMIT_name, &const_WORD_NUMBER_LIMIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WORD_NUMBER_LIMIT_name); + zend_string_release_ex(const_WORD_NUMBER_LIMIT_name, true); zval const_WORD_LETTER_value; ZVAL_LONG(&const_WORD_LETTER_value, UBRK_WORD_LETTER); - zend_string *const_WORD_LETTER_name = zend_string_init_interned("WORD_LETTER", sizeof("WORD_LETTER") - 1, 1); + zend_string *const_WORD_LETTER_name = zend_string_init_interned("WORD_LETTER", sizeof("WORD_LETTER") - 1, true); zend_declare_typed_class_constant(class_entry, const_WORD_LETTER_name, &const_WORD_LETTER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WORD_LETTER_name); + zend_string_release_ex(const_WORD_LETTER_name, true); zval const_WORD_LETTER_LIMIT_value; ZVAL_LONG(&const_WORD_LETTER_LIMIT_value, UBRK_WORD_LETTER_LIMIT); - zend_string *const_WORD_LETTER_LIMIT_name = zend_string_init_interned("WORD_LETTER_LIMIT", sizeof("WORD_LETTER_LIMIT") - 1, 1); + zend_string *const_WORD_LETTER_LIMIT_name = zend_string_init_interned("WORD_LETTER_LIMIT", sizeof("WORD_LETTER_LIMIT") - 1, true); zend_declare_typed_class_constant(class_entry, const_WORD_LETTER_LIMIT_name, &const_WORD_LETTER_LIMIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WORD_LETTER_LIMIT_name); + zend_string_release_ex(const_WORD_LETTER_LIMIT_name, true); zval const_WORD_KANA_value; ZVAL_LONG(&const_WORD_KANA_value, UBRK_WORD_KANA); - zend_string *const_WORD_KANA_name = zend_string_init_interned("WORD_KANA", sizeof("WORD_KANA") - 1, 1); + zend_string *const_WORD_KANA_name = zend_string_init_interned("WORD_KANA", sizeof("WORD_KANA") - 1, true); zend_declare_typed_class_constant(class_entry, const_WORD_KANA_name, &const_WORD_KANA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WORD_KANA_name); + zend_string_release_ex(const_WORD_KANA_name, true); zval const_WORD_KANA_LIMIT_value; ZVAL_LONG(&const_WORD_KANA_LIMIT_value, UBRK_WORD_KANA_LIMIT); - zend_string *const_WORD_KANA_LIMIT_name = zend_string_init_interned("WORD_KANA_LIMIT", sizeof("WORD_KANA_LIMIT") - 1, 1); + zend_string *const_WORD_KANA_LIMIT_name = zend_string_init_interned("WORD_KANA_LIMIT", sizeof("WORD_KANA_LIMIT") - 1, true); zend_declare_typed_class_constant(class_entry, const_WORD_KANA_LIMIT_name, &const_WORD_KANA_LIMIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WORD_KANA_LIMIT_name); + zend_string_release_ex(const_WORD_KANA_LIMIT_name, true); zval const_WORD_IDEO_value; ZVAL_LONG(&const_WORD_IDEO_value, UBRK_WORD_IDEO); - zend_string *const_WORD_IDEO_name = zend_string_init_interned("WORD_IDEO", sizeof("WORD_IDEO") - 1, 1); + zend_string *const_WORD_IDEO_name = zend_string_init_interned("WORD_IDEO", sizeof("WORD_IDEO") - 1, true); zend_declare_typed_class_constant(class_entry, const_WORD_IDEO_name, &const_WORD_IDEO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WORD_IDEO_name); + zend_string_release_ex(const_WORD_IDEO_name, true); zval const_WORD_IDEO_LIMIT_value; ZVAL_LONG(&const_WORD_IDEO_LIMIT_value, UBRK_WORD_IDEO_LIMIT); - zend_string *const_WORD_IDEO_LIMIT_name = zend_string_init_interned("WORD_IDEO_LIMIT", sizeof("WORD_IDEO_LIMIT") - 1, 1); + zend_string *const_WORD_IDEO_LIMIT_name = zend_string_init_interned("WORD_IDEO_LIMIT", sizeof("WORD_IDEO_LIMIT") - 1, true); zend_declare_typed_class_constant(class_entry, const_WORD_IDEO_LIMIT_name, &const_WORD_IDEO_LIMIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WORD_IDEO_LIMIT_name); + zend_string_release_ex(const_WORD_IDEO_LIMIT_name, true); zval const_LINE_SOFT_value; ZVAL_LONG(&const_LINE_SOFT_value, UBRK_LINE_SOFT); - zend_string *const_LINE_SOFT_name = zend_string_init_interned("LINE_SOFT", sizeof("LINE_SOFT") - 1, 1); + zend_string *const_LINE_SOFT_name = zend_string_init_interned("LINE_SOFT", sizeof("LINE_SOFT") - 1, true); zend_declare_typed_class_constant(class_entry, const_LINE_SOFT_name, &const_LINE_SOFT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LINE_SOFT_name); + zend_string_release_ex(const_LINE_SOFT_name, true); zval const_LINE_SOFT_LIMIT_value; ZVAL_LONG(&const_LINE_SOFT_LIMIT_value, UBRK_LINE_SOFT_LIMIT); - zend_string *const_LINE_SOFT_LIMIT_name = zend_string_init_interned("LINE_SOFT_LIMIT", sizeof("LINE_SOFT_LIMIT") - 1, 1); + zend_string *const_LINE_SOFT_LIMIT_name = zend_string_init_interned("LINE_SOFT_LIMIT", sizeof("LINE_SOFT_LIMIT") - 1, true); zend_declare_typed_class_constant(class_entry, const_LINE_SOFT_LIMIT_name, &const_LINE_SOFT_LIMIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LINE_SOFT_LIMIT_name); + zend_string_release_ex(const_LINE_SOFT_LIMIT_name, true); zval const_LINE_HARD_value; ZVAL_LONG(&const_LINE_HARD_value, UBRK_LINE_HARD); - zend_string *const_LINE_HARD_name = zend_string_init_interned("LINE_HARD", sizeof("LINE_HARD") - 1, 1); + zend_string *const_LINE_HARD_name = zend_string_init_interned("LINE_HARD", sizeof("LINE_HARD") - 1, true); zend_declare_typed_class_constant(class_entry, const_LINE_HARD_name, &const_LINE_HARD_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LINE_HARD_name); + zend_string_release_ex(const_LINE_HARD_name, true); zval const_LINE_HARD_LIMIT_value; ZVAL_LONG(&const_LINE_HARD_LIMIT_value, UBRK_LINE_HARD_LIMIT); - zend_string *const_LINE_HARD_LIMIT_name = zend_string_init_interned("LINE_HARD_LIMIT", sizeof("LINE_HARD_LIMIT") - 1, 1); + zend_string *const_LINE_HARD_LIMIT_name = zend_string_init_interned("LINE_HARD_LIMIT", sizeof("LINE_HARD_LIMIT") - 1, true); zend_declare_typed_class_constant(class_entry, const_LINE_HARD_LIMIT_name, &const_LINE_HARD_LIMIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LINE_HARD_LIMIT_name); + zend_string_release_ex(const_LINE_HARD_LIMIT_name, true); zval const_SENTENCE_TERM_value; ZVAL_LONG(&const_SENTENCE_TERM_value, UBRK_SENTENCE_TERM); - zend_string *const_SENTENCE_TERM_name = zend_string_init_interned("SENTENCE_TERM", sizeof("SENTENCE_TERM") - 1, 1); + zend_string *const_SENTENCE_TERM_name = zend_string_init_interned("SENTENCE_TERM", sizeof("SENTENCE_TERM") - 1, true); zend_declare_typed_class_constant(class_entry, const_SENTENCE_TERM_name, &const_SENTENCE_TERM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SENTENCE_TERM_name); + zend_string_release_ex(const_SENTENCE_TERM_name, true); zval const_SENTENCE_TERM_LIMIT_value; ZVAL_LONG(&const_SENTENCE_TERM_LIMIT_value, UBRK_SENTENCE_TERM_LIMIT); - zend_string *const_SENTENCE_TERM_LIMIT_name = zend_string_init_interned("SENTENCE_TERM_LIMIT", sizeof("SENTENCE_TERM_LIMIT") - 1, 1); + zend_string *const_SENTENCE_TERM_LIMIT_name = zend_string_init_interned("SENTENCE_TERM_LIMIT", sizeof("SENTENCE_TERM_LIMIT") - 1, true); zend_declare_typed_class_constant(class_entry, const_SENTENCE_TERM_LIMIT_name, &const_SENTENCE_TERM_LIMIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SENTENCE_TERM_LIMIT_name); + zend_string_release_ex(const_SENTENCE_TERM_LIMIT_name, true); zval const_SENTENCE_SEP_value; ZVAL_LONG(&const_SENTENCE_SEP_value, UBRK_SENTENCE_SEP); - zend_string *const_SENTENCE_SEP_name = zend_string_init_interned("SENTENCE_SEP", sizeof("SENTENCE_SEP") - 1, 1); + zend_string *const_SENTENCE_SEP_name = zend_string_init_interned("SENTENCE_SEP", sizeof("SENTENCE_SEP") - 1, true); zend_declare_typed_class_constant(class_entry, const_SENTENCE_SEP_name, &const_SENTENCE_SEP_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SENTENCE_SEP_name); + zend_string_release_ex(const_SENTENCE_SEP_name, true); zval const_SENTENCE_SEP_LIMIT_value; ZVAL_LONG(&const_SENTENCE_SEP_LIMIT_value, UBRK_SENTENCE_SEP_LIMIT); - zend_string *const_SENTENCE_SEP_LIMIT_name = zend_string_init_interned("SENTENCE_SEP_LIMIT", sizeof("SENTENCE_SEP_LIMIT") - 1, 1); + zend_string *const_SENTENCE_SEP_LIMIT_name = zend_string_init_interned("SENTENCE_SEP_LIMIT", sizeof("SENTENCE_SEP_LIMIT") - 1, true); zend_declare_typed_class_constant(class_entry, const_SENTENCE_SEP_LIMIT_name, &const_SENTENCE_SEP_LIMIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SENTENCE_SEP_LIMIT_name); + zend_string_release_ex(const_SENTENCE_SEP_LIMIT_name, true); return class_entry; } 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_iterators_arginfo.h b/ext/intl/breakiterator/breakiterator_iterators_arginfo.h index f83c0accf6bf4..f4d0975a897f8 100644 --- a/ext/intl/breakiterator/breakiterator_iterators_arginfo.h +++ b/ext/intl/breakiterator/breakiterator_iterators_arginfo.h @@ -25,21 +25,21 @@ static zend_class_entry *register_class_IntlPartsIterator(zend_class_entry *clas zval const_KEY_SEQUENTIAL_value; ZVAL_LONG(&const_KEY_SEQUENTIAL_value, PARTS_ITERATOR_KEY_SEQUENTIAL); - zend_string *const_KEY_SEQUENTIAL_name = zend_string_init_interned("KEY_SEQUENTIAL", sizeof("KEY_SEQUENTIAL") - 1, 1); + zend_string *const_KEY_SEQUENTIAL_name = zend_string_init_interned("KEY_SEQUENTIAL", sizeof("KEY_SEQUENTIAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_KEY_SEQUENTIAL_name, &const_KEY_SEQUENTIAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_KEY_SEQUENTIAL_name); + zend_string_release_ex(const_KEY_SEQUENTIAL_name, true); zval const_KEY_LEFT_value; ZVAL_LONG(&const_KEY_LEFT_value, PARTS_ITERATOR_KEY_LEFT); - zend_string *const_KEY_LEFT_name = zend_string_init_interned("KEY_LEFT", sizeof("KEY_LEFT") - 1, 1); + zend_string *const_KEY_LEFT_name = zend_string_init_interned("KEY_LEFT", sizeof("KEY_LEFT") - 1, true); zend_declare_typed_class_constant(class_entry, const_KEY_LEFT_name, &const_KEY_LEFT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_KEY_LEFT_name); + zend_string_release_ex(const_KEY_LEFT_name, true); zval const_KEY_RIGHT_value; ZVAL_LONG(&const_KEY_RIGHT_value, PARTS_ITERATOR_KEY_RIGHT); - zend_string *const_KEY_RIGHT_name = zend_string_init_interned("KEY_RIGHT", sizeof("KEY_RIGHT") - 1, 1); + zend_string *const_KEY_RIGHT_name = zend_string_init_interned("KEY_RIGHT", sizeof("KEY_RIGHT") - 1, true); zend_declare_typed_class_constant(class_entry, const_KEY_RIGHT_name, &const_KEY_RIGHT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_KEY_RIGHT_name); + zend_string_release_ex(const_KEY_RIGHT_name, true); return class_entry; } 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..f9c5a018d9a8c 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 }; @@ -329,237 +329,237 @@ static zend_class_entry *register_class_IntlCalendar(void) zval const_FIELD_ERA_value; ZVAL_LONG(&const_FIELD_ERA_value, UCAL_ERA); - zend_string *const_FIELD_ERA_name = zend_string_init_interned("FIELD_ERA", sizeof("FIELD_ERA") - 1, 1); + zend_string *const_FIELD_ERA_name = zend_string_init_interned("FIELD_ERA", sizeof("FIELD_ERA") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_ERA_name, &const_FIELD_ERA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_ERA_name); + zend_string_release_ex(const_FIELD_ERA_name, true); zval const_FIELD_YEAR_value; ZVAL_LONG(&const_FIELD_YEAR_value, UCAL_YEAR); - zend_string *const_FIELD_YEAR_name = zend_string_init_interned("FIELD_YEAR", sizeof("FIELD_YEAR") - 1, 1); + zend_string *const_FIELD_YEAR_name = zend_string_init_interned("FIELD_YEAR", sizeof("FIELD_YEAR") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_YEAR_name, &const_FIELD_YEAR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_YEAR_name); + zend_string_release_ex(const_FIELD_YEAR_name, true); zval const_FIELD_MONTH_value; ZVAL_LONG(&const_FIELD_MONTH_value, UCAL_MONTH); - zend_string *const_FIELD_MONTH_name = zend_string_init_interned("FIELD_MONTH", sizeof("FIELD_MONTH") - 1, 1); + zend_string *const_FIELD_MONTH_name = zend_string_init_interned("FIELD_MONTH", sizeof("FIELD_MONTH") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_MONTH_name, &const_FIELD_MONTH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_MONTH_name); + zend_string_release_ex(const_FIELD_MONTH_name, true); zval const_FIELD_WEEK_OF_YEAR_value; ZVAL_LONG(&const_FIELD_WEEK_OF_YEAR_value, UCAL_WEEK_OF_YEAR); - zend_string *const_FIELD_WEEK_OF_YEAR_name = zend_string_init_interned("FIELD_WEEK_OF_YEAR", sizeof("FIELD_WEEK_OF_YEAR") - 1, 1); + zend_string *const_FIELD_WEEK_OF_YEAR_name = zend_string_init_interned("FIELD_WEEK_OF_YEAR", sizeof("FIELD_WEEK_OF_YEAR") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_WEEK_OF_YEAR_name, &const_FIELD_WEEK_OF_YEAR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_WEEK_OF_YEAR_name); + zend_string_release_ex(const_FIELD_WEEK_OF_YEAR_name, true); zval const_FIELD_WEEK_OF_MONTH_value; ZVAL_LONG(&const_FIELD_WEEK_OF_MONTH_value, UCAL_WEEK_OF_MONTH); - zend_string *const_FIELD_WEEK_OF_MONTH_name = zend_string_init_interned("FIELD_WEEK_OF_MONTH", sizeof("FIELD_WEEK_OF_MONTH") - 1, 1); + zend_string *const_FIELD_WEEK_OF_MONTH_name = zend_string_init_interned("FIELD_WEEK_OF_MONTH", sizeof("FIELD_WEEK_OF_MONTH") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_WEEK_OF_MONTH_name, &const_FIELD_WEEK_OF_MONTH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_WEEK_OF_MONTH_name); + zend_string_release_ex(const_FIELD_WEEK_OF_MONTH_name, true); zval const_FIELD_DATE_value; ZVAL_LONG(&const_FIELD_DATE_value, UCAL_DATE); - zend_string *const_FIELD_DATE_name = zend_string_init_interned("FIELD_DATE", sizeof("FIELD_DATE") - 1, 1); + zend_string *const_FIELD_DATE_name = zend_string_init_interned("FIELD_DATE", sizeof("FIELD_DATE") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_DATE_name, &const_FIELD_DATE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_DATE_name); + zend_string_release_ex(const_FIELD_DATE_name, true); zval const_FIELD_DAY_OF_YEAR_value; ZVAL_LONG(&const_FIELD_DAY_OF_YEAR_value, UCAL_DAY_OF_YEAR); - zend_string *const_FIELD_DAY_OF_YEAR_name = zend_string_init_interned("FIELD_DAY_OF_YEAR", sizeof("FIELD_DAY_OF_YEAR") - 1, 1); + zend_string *const_FIELD_DAY_OF_YEAR_name = zend_string_init_interned("FIELD_DAY_OF_YEAR", sizeof("FIELD_DAY_OF_YEAR") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_DAY_OF_YEAR_name, &const_FIELD_DAY_OF_YEAR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_DAY_OF_YEAR_name); + zend_string_release_ex(const_FIELD_DAY_OF_YEAR_name, true); zval const_FIELD_DAY_OF_WEEK_value; ZVAL_LONG(&const_FIELD_DAY_OF_WEEK_value, UCAL_DAY_OF_WEEK); - zend_string *const_FIELD_DAY_OF_WEEK_name = zend_string_init_interned("FIELD_DAY_OF_WEEK", sizeof("FIELD_DAY_OF_WEEK") - 1, 1); + zend_string *const_FIELD_DAY_OF_WEEK_name = zend_string_init_interned("FIELD_DAY_OF_WEEK", sizeof("FIELD_DAY_OF_WEEK") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_DAY_OF_WEEK_name, &const_FIELD_DAY_OF_WEEK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_DAY_OF_WEEK_name); + zend_string_release_ex(const_FIELD_DAY_OF_WEEK_name, true); zval const_FIELD_DAY_OF_WEEK_IN_MONTH_value; ZVAL_LONG(&const_FIELD_DAY_OF_WEEK_IN_MONTH_value, UCAL_DAY_OF_WEEK_IN_MONTH); - zend_string *const_FIELD_DAY_OF_WEEK_IN_MONTH_name = zend_string_init_interned("FIELD_DAY_OF_WEEK_IN_MONTH", sizeof("FIELD_DAY_OF_WEEK_IN_MONTH") - 1, 1); + zend_string *const_FIELD_DAY_OF_WEEK_IN_MONTH_name = zend_string_init_interned("FIELD_DAY_OF_WEEK_IN_MONTH", sizeof("FIELD_DAY_OF_WEEK_IN_MONTH") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_DAY_OF_WEEK_IN_MONTH_name, &const_FIELD_DAY_OF_WEEK_IN_MONTH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_DAY_OF_WEEK_IN_MONTH_name); + zend_string_release_ex(const_FIELD_DAY_OF_WEEK_IN_MONTH_name, true); zval const_FIELD_AM_PM_value; ZVAL_LONG(&const_FIELD_AM_PM_value, UCAL_AM_PM); - zend_string *const_FIELD_AM_PM_name = zend_string_init_interned("FIELD_AM_PM", sizeof("FIELD_AM_PM") - 1, 1); + zend_string *const_FIELD_AM_PM_name = zend_string_init_interned("FIELD_AM_PM", sizeof("FIELD_AM_PM") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_AM_PM_name, &const_FIELD_AM_PM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_AM_PM_name); + zend_string_release_ex(const_FIELD_AM_PM_name, true); zval const_FIELD_HOUR_value; ZVAL_LONG(&const_FIELD_HOUR_value, UCAL_HOUR); - zend_string *const_FIELD_HOUR_name = zend_string_init_interned("FIELD_HOUR", sizeof("FIELD_HOUR") - 1, 1); + zend_string *const_FIELD_HOUR_name = zend_string_init_interned("FIELD_HOUR", sizeof("FIELD_HOUR") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_HOUR_name, &const_FIELD_HOUR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_HOUR_name); + zend_string_release_ex(const_FIELD_HOUR_name, true); zval const_FIELD_HOUR_OF_DAY_value; ZVAL_LONG(&const_FIELD_HOUR_OF_DAY_value, UCAL_HOUR_OF_DAY); - zend_string *const_FIELD_HOUR_OF_DAY_name = zend_string_init_interned("FIELD_HOUR_OF_DAY", sizeof("FIELD_HOUR_OF_DAY") - 1, 1); + zend_string *const_FIELD_HOUR_OF_DAY_name = zend_string_init_interned("FIELD_HOUR_OF_DAY", sizeof("FIELD_HOUR_OF_DAY") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_HOUR_OF_DAY_name, &const_FIELD_HOUR_OF_DAY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_HOUR_OF_DAY_name); + zend_string_release_ex(const_FIELD_HOUR_OF_DAY_name, true); zval const_FIELD_MINUTE_value; ZVAL_LONG(&const_FIELD_MINUTE_value, UCAL_MINUTE); - zend_string *const_FIELD_MINUTE_name = zend_string_init_interned("FIELD_MINUTE", sizeof("FIELD_MINUTE") - 1, 1); + zend_string *const_FIELD_MINUTE_name = zend_string_init_interned("FIELD_MINUTE", sizeof("FIELD_MINUTE") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_MINUTE_name, &const_FIELD_MINUTE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_MINUTE_name); + zend_string_release_ex(const_FIELD_MINUTE_name, true); zval const_FIELD_SECOND_value; ZVAL_LONG(&const_FIELD_SECOND_value, UCAL_SECOND); - zend_string *const_FIELD_SECOND_name = zend_string_init_interned("FIELD_SECOND", sizeof("FIELD_SECOND") - 1, 1); + zend_string *const_FIELD_SECOND_name = zend_string_init_interned("FIELD_SECOND", sizeof("FIELD_SECOND") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_SECOND_name, &const_FIELD_SECOND_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_SECOND_name); + zend_string_release_ex(const_FIELD_SECOND_name, true); zval const_FIELD_MILLISECOND_value; ZVAL_LONG(&const_FIELD_MILLISECOND_value, UCAL_MILLISECOND); - zend_string *const_FIELD_MILLISECOND_name = zend_string_init_interned("FIELD_MILLISECOND", sizeof("FIELD_MILLISECOND") - 1, 1); + zend_string *const_FIELD_MILLISECOND_name = zend_string_init_interned("FIELD_MILLISECOND", sizeof("FIELD_MILLISECOND") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_MILLISECOND_name, &const_FIELD_MILLISECOND_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_MILLISECOND_name); + zend_string_release_ex(const_FIELD_MILLISECOND_name, true); zval const_FIELD_ZONE_OFFSET_value; ZVAL_LONG(&const_FIELD_ZONE_OFFSET_value, UCAL_ZONE_OFFSET); - zend_string *const_FIELD_ZONE_OFFSET_name = zend_string_init_interned("FIELD_ZONE_OFFSET", sizeof("FIELD_ZONE_OFFSET") - 1, 1); + zend_string *const_FIELD_ZONE_OFFSET_name = zend_string_init_interned("FIELD_ZONE_OFFSET", sizeof("FIELD_ZONE_OFFSET") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_ZONE_OFFSET_name, &const_FIELD_ZONE_OFFSET_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_ZONE_OFFSET_name); + zend_string_release_ex(const_FIELD_ZONE_OFFSET_name, true); zval const_FIELD_DST_OFFSET_value; ZVAL_LONG(&const_FIELD_DST_OFFSET_value, UCAL_DST_OFFSET); - zend_string *const_FIELD_DST_OFFSET_name = zend_string_init_interned("FIELD_DST_OFFSET", sizeof("FIELD_DST_OFFSET") - 1, 1); + zend_string *const_FIELD_DST_OFFSET_name = zend_string_init_interned("FIELD_DST_OFFSET", sizeof("FIELD_DST_OFFSET") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_DST_OFFSET_name, &const_FIELD_DST_OFFSET_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_DST_OFFSET_name); + zend_string_release_ex(const_FIELD_DST_OFFSET_name, true); zval const_FIELD_YEAR_WOY_value; ZVAL_LONG(&const_FIELD_YEAR_WOY_value, UCAL_YEAR_WOY); - zend_string *const_FIELD_YEAR_WOY_name = zend_string_init_interned("FIELD_YEAR_WOY", sizeof("FIELD_YEAR_WOY") - 1, 1); + zend_string *const_FIELD_YEAR_WOY_name = zend_string_init_interned("FIELD_YEAR_WOY", sizeof("FIELD_YEAR_WOY") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_YEAR_WOY_name, &const_FIELD_YEAR_WOY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_YEAR_WOY_name); + zend_string_release_ex(const_FIELD_YEAR_WOY_name, true); zval const_FIELD_DOW_LOCAL_value; ZVAL_LONG(&const_FIELD_DOW_LOCAL_value, UCAL_DOW_LOCAL); - zend_string *const_FIELD_DOW_LOCAL_name = zend_string_init_interned("FIELD_DOW_LOCAL", sizeof("FIELD_DOW_LOCAL") - 1, 1); + zend_string *const_FIELD_DOW_LOCAL_name = zend_string_init_interned("FIELD_DOW_LOCAL", sizeof("FIELD_DOW_LOCAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_DOW_LOCAL_name, &const_FIELD_DOW_LOCAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_DOW_LOCAL_name); + zend_string_release_ex(const_FIELD_DOW_LOCAL_name, true); zval const_FIELD_EXTENDED_YEAR_value; ZVAL_LONG(&const_FIELD_EXTENDED_YEAR_value, UCAL_EXTENDED_YEAR); - zend_string *const_FIELD_EXTENDED_YEAR_name = zend_string_init_interned("FIELD_EXTENDED_YEAR", sizeof("FIELD_EXTENDED_YEAR") - 1, 1); + zend_string *const_FIELD_EXTENDED_YEAR_name = zend_string_init_interned("FIELD_EXTENDED_YEAR", sizeof("FIELD_EXTENDED_YEAR") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_EXTENDED_YEAR_name, &const_FIELD_EXTENDED_YEAR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_EXTENDED_YEAR_name); + zend_string_release_ex(const_FIELD_EXTENDED_YEAR_name, true); zval const_FIELD_JULIAN_DAY_value; ZVAL_LONG(&const_FIELD_JULIAN_DAY_value, UCAL_JULIAN_DAY); - zend_string *const_FIELD_JULIAN_DAY_name = zend_string_init_interned("FIELD_JULIAN_DAY", sizeof("FIELD_JULIAN_DAY") - 1, 1); + zend_string *const_FIELD_JULIAN_DAY_name = zend_string_init_interned("FIELD_JULIAN_DAY", sizeof("FIELD_JULIAN_DAY") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_JULIAN_DAY_name, &const_FIELD_JULIAN_DAY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_JULIAN_DAY_name); + zend_string_release_ex(const_FIELD_JULIAN_DAY_name, true); zval const_FIELD_MILLISECONDS_IN_DAY_value; ZVAL_LONG(&const_FIELD_MILLISECONDS_IN_DAY_value, UCAL_MILLISECONDS_IN_DAY); - zend_string *const_FIELD_MILLISECONDS_IN_DAY_name = zend_string_init_interned("FIELD_MILLISECONDS_IN_DAY", sizeof("FIELD_MILLISECONDS_IN_DAY") - 1, 1); + zend_string *const_FIELD_MILLISECONDS_IN_DAY_name = zend_string_init_interned("FIELD_MILLISECONDS_IN_DAY", sizeof("FIELD_MILLISECONDS_IN_DAY") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_MILLISECONDS_IN_DAY_name, &const_FIELD_MILLISECONDS_IN_DAY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_MILLISECONDS_IN_DAY_name); + zend_string_release_ex(const_FIELD_MILLISECONDS_IN_DAY_name, true); zval const_FIELD_IS_LEAP_MONTH_value; ZVAL_LONG(&const_FIELD_IS_LEAP_MONTH_value, UCAL_IS_LEAP_MONTH); - zend_string *const_FIELD_IS_LEAP_MONTH_name = zend_string_init_interned("FIELD_IS_LEAP_MONTH", sizeof("FIELD_IS_LEAP_MONTH") - 1, 1); + zend_string *const_FIELD_IS_LEAP_MONTH_name = zend_string_init_interned("FIELD_IS_LEAP_MONTH", sizeof("FIELD_IS_LEAP_MONTH") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_IS_LEAP_MONTH_name, &const_FIELD_IS_LEAP_MONTH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_IS_LEAP_MONTH_name); + zend_string_release_ex(const_FIELD_IS_LEAP_MONTH_name, true); zval const_FIELD_FIELD_COUNT_value; ZVAL_LONG(&const_FIELD_FIELD_COUNT_value, UCAL_FIELD_COUNT); - zend_string *const_FIELD_FIELD_COUNT_name = zend_string_init_interned("FIELD_FIELD_COUNT", sizeof("FIELD_FIELD_COUNT") - 1, 1); + zend_string *const_FIELD_FIELD_COUNT_name = zend_string_init_interned("FIELD_FIELD_COUNT", sizeof("FIELD_FIELD_COUNT") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_FIELD_COUNT_name, &const_FIELD_FIELD_COUNT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_FIELD_COUNT_name); + zend_string_release_ex(const_FIELD_FIELD_COUNT_name, true); zval const_FIELD_DAY_OF_MONTH_value; ZVAL_LONG(&const_FIELD_DAY_OF_MONTH_value, UCAL_DAY_OF_MONTH); - zend_string *const_FIELD_DAY_OF_MONTH_name = zend_string_init_interned("FIELD_DAY_OF_MONTH", sizeof("FIELD_DAY_OF_MONTH") - 1, 1); + zend_string *const_FIELD_DAY_OF_MONTH_name = zend_string_init_interned("FIELD_DAY_OF_MONTH", sizeof("FIELD_DAY_OF_MONTH") - 1, true); zend_declare_typed_class_constant(class_entry, const_FIELD_DAY_OF_MONTH_name, &const_FIELD_DAY_OF_MONTH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FIELD_DAY_OF_MONTH_name); + zend_string_release_ex(const_FIELD_DAY_OF_MONTH_name, true); zval const_DOW_SUNDAY_value; ZVAL_LONG(&const_DOW_SUNDAY_value, UCAL_SUNDAY); - zend_string *const_DOW_SUNDAY_name = zend_string_init_interned("DOW_SUNDAY", sizeof("DOW_SUNDAY") - 1, 1); + zend_string *const_DOW_SUNDAY_name = zend_string_init_interned("DOW_SUNDAY", sizeof("DOW_SUNDAY") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOW_SUNDAY_name, &const_DOW_SUNDAY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOW_SUNDAY_name); + zend_string_release_ex(const_DOW_SUNDAY_name, true); zval const_DOW_MONDAY_value; ZVAL_LONG(&const_DOW_MONDAY_value, UCAL_MONDAY); - zend_string *const_DOW_MONDAY_name = zend_string_init_interned("DOW_MONDAY", sizeof("DOW_MONDAY") - 1, 1); + zend_string *const_DOW_MONDAY_name = zend_string_init_interned("DOW_MONDAY", sizeof("DOW_MONDAY") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOW_MONDAY_name, &const_DOW_MONDAY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOW_MONDAY_name); + zend_string_release_ex(const_DOW_MONDAY_name, true); zval const_DOW_TUESDAY_value; ZVAL_LONG(&const_DOW_TUESDAY_value, UCAL_TUESDAY); - zend_string *const_DOW_TUESDAY_name = zend_string_init_interned("DOW_TUESDAY", sizeof("DOW_TUESDAY") - 1, 1); + zend_string *const_DOW_TUESDAY_name = zend_string_init_interned("DOW_TUESDAY", sizeof("DOW_TUESDAY") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOW_TUESDAY_name, &const_DOW_TUESDAY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOW_TUESDAY_name); + zend_string_release_ex(const_DOW_TUESDAY_name, true); zval const_DOW_WEDNESDAY_value; ZVAL_LONG(&const_DOW_WEDNESDAY_value, UCAL_WEDNESDAY); - zend_string *const_DOW_WEDNESDAY_name = zend_string_init_interned("DOW_WEDNESDAY", sizeof("DOW_WEDNESDAY") - 1, 1); + zend_string *const_DOW_WEDNESDAY_name = zend_string_init_interned("DOW_WEDNESDAY", sizeof("DOW_WEDNESDAY") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOW_WEDNESDAY_name, &const_DOW_WEDNESDAY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOW_WEDNESDAY_name); + zend_string_release_ex(const_DOW_WEDNESDAY_name, true); zval const_DOW_THURSDAY_value; ZVAL_LONG(&const_DOW_THURSDAY_value, UCAL_THURSDAY); - zend_string *const_DOW_THURSDAY_name = zend_string_init_interned("DOW_THURSDAY", sizeof("DOW_THURSDAY") - 1, 1); + zend_string *const_DOW_THURSDAY_name = zend_string_init_interned("DOW_THURSDAY", sizeof("DOW_THURSDAY") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOW_THURSDAY_name, &const_DOW_THURSDAY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOW_THURSDAY_name); + zend_string_release_ex(const_DOW_THURSDAY_name, true); zval const_DOW_FRIDAY_value; ZVAL_LONG(&const_DOW_FRIDAY_value, UCAL_FRIDAY); - zend_string *const_DOW_FRIDAY_name = zend_string_init_interned("DOW_FRIDAY", sizeof("DOW_FRIDAY") - 1, 1); + zend_string *const_DOW_FRIDAY_name = zend_string_init_interned("DOW_FRIDAY", sizeof("DOW_FRIDAY") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOW_FRIDAY_name, &const_DOW_FRIDAY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOW_FRIDAY_name); + zend_string_release_ex(const_DOW_FRIDAY_name, true); zval const_DOW_SATURDAY_value; ZVAL_LONG(&const_DOW_SATURDAY_value, UCAL_SATURDAY); - zend_string *const_DOW_SATURDAY_name = zend_string_init_interned("DOW_SATURDAY", sizeof("DOW_SATURDAY") - 1, 1); + zend_string *const_DOW_SATURDAY_name = zend_string_init_interned("DOW_SATURDAY", sizeof("DOW_SATURDAY") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOW_SATURDAY_name, &const_DOW_SATURDAY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOW_SATURDAY_name); + zend_string_release_ex(const_DOW_SATURDAY_name, true); zval const_DOW_TYPE_WEEKDAY_value; ZVAL_LONG(&const_DOW_TYPE_WEEKDAY_value, UCAL_WEEKDAY); - zend_string *const_DOW_TYPE_WEEKDAY_name = zend_string_init_interned("DOW_TYPE_WEEKDAY", sizeof("DOW_TYPE_WEEKDAY") - 1, 1); + zend_string *const_DOW_TYPE_WEEKDAY_name = zend_string_init_interned("DOW_TYPE_WEEKDAY", sizeof("DOW_TYPE_WEEKDAY") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOW_TYPE_WEEKDAY_name, &const_DOW_TYPE_WEEKDAY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOW_TYPE_WEEKDAY_name); + zend_string_release_ex(const_DOW_TYPE_WEEKDAY_name, true); zval const_DOW_TYPE_WEEKEND_value; ZVAL_LONG(&const_DOW_TYPE_WEEKEND_value, UCAL_WEEKEND); - zend_string *const_DOW_TYPE_WEEKEND_name = zend_string_init_interned("DOW_TYPE_WEEKEND", sizeof("DOW_TYPE_WEEKEND") - 1, 1); + zend_string *const_DOW_TYPE_WEEKEND_name = zend_string_init_interned("DOW_TYPE_WEEKEND", sizeof("DOW_TYPE_WEEKEND") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOW_TYPE_WEEKEND_name, &const_DOW_TYPE_WEEKEND_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOW_TYPE_WEEKEND_name); + zend_string_release_ex(const_DOW_TYPE_WEEKEND_name, true); zval const_DOW_TYPE_WEEKEND_OFFSET_value; ZVAL_LONG(&const_DOW_TYPE_WEEKEND_OFFSET_value, UCAL_WEEKEND_ONSET); - zend_string *const_DOW_TYPE_WEEKEND_OFFSET_name = zend_string_init_interned("DOW_TYPE_WEEKEND_OFFSET", sizeof("DOW_TYPE_WEEKEND_OFFSET") - 1, 1); + zend_string *const_DOW_TYPE_WEEKEND_OFFSET_name = zend_string_init_interned("DOW_TYPE_WEEKEND_OFFSET", sizeof("DOW_TYPE_WEEKEND_OFFSET") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOW_TYPE_WEEKEND_OFFSET_name, &const_DOW_TYPE_WEEKEND_OFFSET_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOW_TYPE_WEEKEND_OFFSET_name); + zend_string_release_ex(const_DOW_TYPE_WEEKEND_OFFSET_name, true); zval const_DOW_TYPE_WEEKEND_CEASE_value; ZVAL_LONG(&const_DOW_TYPE_WEEKEND_CEASE_value, UCAL_WEEKEND_CEASE); - zend_string *const_DOW_TYPE_WEEKEND_CEASE_name = zend_string_init_interned("DOW_TYPE_WEEKEND_CEASE", sizeof("DOW_TYPE_WEEKEND_CEASE") - 1, 1); + zend_string *const_DOW_TYPE_WEEKEND_CEASE_name = zend_string_init_interned("DOW_TYPE_WEEKEND_CEASE", sizeof("DOW_TYPE_WEEKEND_CEASE") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOW_TYPE_WEEKEND_CEASE_name, &const_DOW_TYPE_WEEKEND_CEASE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOW_TYPE_WEEKEND_CEASE_name); + zend_string_release_ex(const_DOW_TYPE_WEEKEND_CEASE_name, true); zval const_WALLTIME_FIRST_value; ZVAL_LONG(&const_WALLTIME_FIRST_value, UCAL_WALLTIME_FIRST); - zend_string *const_WALLTIME_FIRST_name = zend_string_init_interned("WALLTIME_FIRST", sizeof("WALLTIME_FIRST") - 1, 1); + zend_string *const_WALLTIME_FIRST_name = zend_string_init_interned("WALLTIME_FIRST", sizeof("WALLTIME_FIRST") - 1, true); zend_declare_typed_class_constant(class_entry, const_WALLTIME_FIRST_name, &const_WALLTIME_FIRST_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WALLTIME_FIRST_name); + zend_string_release_ex(const_WALLTIME_FIRST_name, true); zval const_WALLTIME_LAST_value; ZVAL_LONG(&const_WALLTIME_LAST_value, UCAL_WALLTIME_LAST); - zend_string *const_WALLTIME_LAST_name = zend_string_init_interned("WALLTIME_LAST", sizeof("WALLTIME_LAST") - 1, 1); + zend_string *const_WALLTIME_LAST_name = zend_string_init_interned("WALLTIME_LAST", sizeof("WALLTIME_LAST") - 1, true); zend_declare_typed_class_constant(class_entry, const_WALLTIME_LAST_name, &const_WALLTIME_LAST_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WALLTIME_LAST_name); + zend_string_release_ex(const_WALLTIME_LAST_name, true); zval const_WALLTIME_NEXT_VALID_value; ZVAL_LONG(&const_WALLTIME_NEXT_VALID_value, UCAL_WALLTIME_NEXT_VALID); - zend_string *const_WALLTIME_NEXT_VALID_name = zend_string_init_interned("WALLTIME_NEXT_VALID", sizeof("WALLTIME_NEXT_VALID") - 1, 1); + zend_string *const_WALLTIME_NEXT_VALID_name = zend_string_init_interned("WALLTIME_NEXT_VALID", sizeof("WALLTIME_NEXT_VALID") - 1, true); zend_declare_typed_class_constant(class_entry, const_WALLTIME_NEXT_VALID_name, &const_WALLTIME_NEXT_VALID_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WALLTIME_NEXT_VALID_name); + zend_string_release_ex(const_WALLTIME_NEXT_VALID_name, true); return class_entry; } 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_arginfo.h b/ext/intl/collator/collator_arginfo.h index 3f469b02facd4..a35adbd3d1e05 100644 --- a/ext/intl/collator/collator_arginfo.h +++ b/ext/intl/collator/collator_arginfo.h @@ -103,147 +103,147 @@ static zend_class_entry *register_class_Collator(void) zval const_DEFAULT_VALUE_value; ZVAL_LONG(&const_DEFAULT_VALUE_value, UCOL_DEFAULT); - zend_string *const_DEFAULT_VALUE_name = zend_string_init_interned("DEFAULT_VALUE", sizeof("DEFAULT_VALUE") - 1, 1); + zend_string *const_DEFAULT_VALUE_name = zend_string_init_interned("DEFAULT_VALUE", sizeof("DEFAULT_VALUE") - 1, true); zend_declare_typed_class_constant(class_entry, const_DEFAULT_VALUE_name, &const_DEFAULT_VALUE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DEFAULT_VALUE_name); + zend_string_release_ex(const_DEFAULT_VALUE_name, true); zval const_PRIMARY_value; ZVAL_LONG(&const_PRIMARY_value, UCOL_PRIMARY); - zend_string *const_PRIMARY_name = zend_string_init_interned("PRIMARY", sizeof("PRIMARY") - 1, 1); + zend_string *const_PRIMARY_name = zend_string_init_interned("PRIMARY", sizeof("PRIMARY") - 1, true); zend_declare_typed_class_constant(class_entry, const_PRIMARY_name, &const_PRIMARY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PRIMARY_name); + zend_string_release_ex(const_PRIMARY_name, true); zval const_SECONDARY_value; ZVAL_LONG(&const_SECONDARY_value, UCOL_SECONDARY); - zend_string *const_SECONDARY_name = zend_string_init_interned("SECONDARY", sizeof("SECONDARY") - 1, 1); + zend_string *const_SECONDARY_name = zend_string_init_interned("SECONDARY", sizeof("SECONDARY") - 1, true); zend_declare_typed_class_constant(class_entry, const_SECONDARY_name, &const_SECONDARY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SECONDARY_name); + zend_string_release_ex(const_SECONDARY_name, true); zval const_TERTIARY_value; ZVAL_LONG(&const_TERTIARY_value, UCOL_TERTIARY); - zend_string *const_TERTIARY_name = zend_string_init_interned("TERTIARY", sizeof("TERTIARY") - 1, 1); + zend_string *const_TERTIARY_name = zend_string_init_interned("TERTIARY", sizeof("TERTIARY") - 1, true); zend_declare_typed_class_constant(class_entry, const_TERTIARY_name, &const_TERTIARY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TERTIARY_name); + zend_string_release_ex(const_TERTIARY_name, true); zval const_DEFAULT_STRENGTH_value; ZVAL_LONG(&const_DEFAULT_STRENGTH_value, UCOL_DEFAULT_STRENGTH); - zend_string *const_DEFAULT_STRENGTH_name = zend_string_init_interned("DEFAULT_STRENGTH", sizeof("DEFAULT_STRENGTH") - 1, 1); + zend_string *const_DEFAULT_STRENGTH_name = zend_string_init_interned("DEFAULT_STRENGTH", sizeof("DEFAULT_STRENGTH") - 1, true); zend_declare_typed_class_constant(class_entry, const_DEFAULT_STRENGTH_name, &const_DEFAULT_STRENGTH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DEFAULT_STRENGTH_name); + zend_string_release_ex(const_DEFAULT_STRENGTH_name, true); zval const_QUATERNARY_value; ZVAL_LONG(&const_QUATERNARY_value, UCOL_QUATERNARY); - zend_string *const_QUATERNARY_name = zend_string_init_interned("QUATERNARY", sizeof("QUATERNARY") - 1, 1); + zend_string *const_QUATERNARY_name = zend_string_init_interned("QUATERNARY", sizeof("QUATERNARY") - 1, true); zend_declare_typed_class_constant(class_entry, const_QUATERNARY_name, &const_QUATERNARY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_QUATERNARY_name); + zend_string_release_ex(const_QUATERNARY_name, true); zval const_IDENTICAL_value; ZVAL_LONG(&const_IDENTICAL_value, UCOL_IDENTICAL); - zend_string *const_IDENTICAL_name = zend_string_init_interned("IDENTICAL", sizeof("IDENTICAL") - 1, 1); + zend_string *const_IDENTICAL_name = zend_string_init_interned("IDENTICAL", sizeof("IDENTICAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_IDENTICAL_name, &const_IDENTICAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IDENTICAL_name); + zend_string_release_ex(const_IDENTICAL_name, true); zval const_OFF_value; ZVAL_LONG(&const_OFF_value, UCOL_OFF); - zend_string *const_OFF_name = zend_string_init_interned("OFF", sizeof("OFF") - 1, 1); + zend_string *const_OFF_name = zend_string_init_interned("OFF", sizeof("OFF") - 1, true); zend_declare_typed_class_constant(class_entry, const_OFF_name, &const_OFF_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OFF_name); + zend_string_release_ex(const_OFF_name, true); zval const_ON_value; ZVAL_LONG(&const_ON_value, UCOL_ON); - zend_string *const_ON_name = zend_string_init_interned("ON", sizeof("ON") - 1, 1); + zend_string *const_ON_name = zend_string_init_interned("ON", sizeof("ON") - 1, true); zend_declare_typed_class_constant(class_entry, const_ON_name, &const_ON_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ON_name); + zend_string_release_ex(const_ON_name, true); zval const_SHIFTED_value; ZVAL_LONG(&const_SHIFTED_value, UCOL_SHIFTED); - zend_string *const_SHIFTED_name = zend_string_init_interned("SHIFTED", sizeof("SHIFTED") - 1, 1); + zend_string *const_SHIFTED_name = zend_string_init_interned("SHIFTED", sizeof("SHIFTED") - 1, true); zend_declare_typed_class_constant(class_entry, const_SHIFTED_name, &const_SHIFTED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SHIFTED_name); + zend_string_release_ex(const_SHIFTED_name, true); zval const_NON_IGNORABLE_value; ZVAL_LONG(&const_NON_IGNORABLE_value, UCOL_NON_IGNORABLE); - zend_string *const_NON_IGNORABLE_name = zend_string_init_interned("NON_IGNORABLE", sizeof("NON_IGNORABLE") - 1, 1); + zend_string *const_NON_IGNORABLE_name = zend_string_init_interned("NON_IGNORABLE", sizeof("NON_IGNORABLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_NON_IGNORABLE_name, &const_NON_IGNORABLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NON_IGNORABLE_name); + zend_string_release_ex(const_NON_IGNORABLE_name, true); zval const_LOWER_FIRST_value; ZVAL_LONG(&const_LOWER_FIRST_value, UCOL_LOWER_FIRST); - zend_string *const_LOWER_FIRST_name = zend_string_init_interned("LOWER_FIRST", sizeof("LOWER_FIRST") - 1, 1); + zend_string *const_LOWER_FIRST_name = zend_string_init_interned("LOWER_FIRST", sizeof("LOWER_FIRST") - 1, true); zend_declare_typed_class_constant(class_entry, const_LOWER_FIRST_name, &const_LOWER_FIRST_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LOWER_FIRST_name); + zend_string_release_ex(const_LOWER_FIRST_name, true); zval const_UPPER_FIRST_value; ZVAL_LONG(&const_UPPER_FIRST_value, UCOL_UPPER_FIRST); - zend_string *const_UPPER_FIRST_name = zend_string_init_interned("UPPER_FIRST", sizeof("UPPER_FIRST") - 1, 1); + zend_string *const_UPPER_FIRST_name = zend_string_init_interned("UPPER_FIRST", sizeof("UPPER_FIRST") - 1, true); zend_declare_typed_class_constant(class_entry, const_UPPER_FIRST_name, &const_UPPER_FIRST_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_UPPER_FIRST_name); + zend_string_release_ex(const_UPPER_FIRST_name, true); zval const_FRENCH_COLLATION_value; ZVAL_LONG(&const_FRENCH_COLLATION_value, UCOL_FRENCH_COLLATION); - zend_string *const_FRENCH_COLLATION_name = zend_string_init_interned("FRENCH_COLLATION", sizeof("FRENCH_COLLATION") - 1, 1); + zend_string *const_FRENCH_COLLATION_name = zend_string_init_interned("FRENCH_COLLATION", sizeof("FRENCH_COLLATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_FRENCH_COLLATION_name, &const_FRENCH_COLLATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FRENCH_COLLATION_name); + zend_string_release_ex(const_FRENCH_COLLATION_name, true); zval const_ALTERNATE_HANDLING_value; ZVAL_LONG(&const_ALTERNATE_HANDLING_value, UCOL_ALTERNATE_HANDLING); - zend_string *const_ALTERNATE_HANDLING_name = zend_string_init_interned("ALTERNATE_HANDLING", sizeof("ALTERNATE_HANDLING") - 1, 1); + zend_string *const_ALTERNATE_HANDLING_name = zend_string_init_interned("ALTERNATE_HANDLING", sizeof("ALTERNATE_HANDLING") - 1, true); zend_declare_typed_class_constant(class_entry, const_ALTERNATE_HANDLING_name, &const_ALTERNATE_HANDLING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ALTERNATE_HANDLING_name); + zend_string_release_ex(const_ALTERNATE_HANDLING_name, true); zval const_CASE_FIRST_value; ZVAL_LONG(&const_CASE_FIRST_value, UCOL_CASE_FIRST); - zend_string *const_CASE_FIRST_name = zend_string_init_interned("CASE_FIRST", sizeof("CASE_FIRST") - 1, 1); + zend_string *const_CASE_FIRST_name = zend_string_init_interned("CASE_FIRST", sizeof("CASE_FIRST") - 1, true); zend_declare_typed_class_constant(class_entry, const_CASE_FIRST_name, &const_CASE_FIRST_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CASE_FIRST_name); + zend_string_release_ex(const_CASE_FIRST_name, true); zval const_CASE_LEVEL_value; ZVAL_LONG(&const_CASE_LEVEL_value, UCOL_CASE_LEVEL); - zend_string *const_CASE_LEVEL_name = zend_string_init_interned("CASE_LEVEL", sizeof("CASE_LEVEL") - 1, 1); + zend_string *const_CASE_LEVEL_name = zend_string_init_interned("CASE_LEVEL", sizeof("CASE_LEVEL") - 1, true); zend_declare_typed_class_constant(class_entry, const_CASE_LEVEL_name, &const_CASE_LEVEL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CASE_LEVEL_name); + zend_string_release_ex(const_CASE_LEVEL_name, true); zval const_NORMALIZATION_MODE_value; ZVAL_LONG(&const_NORMALIZATION_MODE_value, UCOL_NORMALIZATION_MODE); - zend_string *const_NORMALIZATION_MODE_name = zend_string_init_interned("NORMALIZATION_MODE", sizeof("NORMALIZATION_MODE") - 1, 1); + zend_string *const_NORMALIZATION_MODE_name = zend_string_init_interned("NORMALIZATION_MODE", sizeof("NORMALIZATION_MODE") - 1, true); zend_declare_typed_class_constant(class_entry, const_NORMALIZATION_MODE_name, &const_NORMALIZATION_MODE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NORMALIZATION_MODE_name); + zend_string_release_ex(const_NORMALIZATION_MODE_name, true); zval const_STRENGTH_value; ZVAL_LONG(&const_STRENGTH_value, UCOL_STRENGTH); - zend_string *const_STRENGTH_name = zend_string_init_interned("STRENGTH", sizeof("STRENGTH") - 1, 1); + zend_string *const_STRENGTH_name = zend_string_init_interned("STRENGTH", sizeof("STRENGTH") - 1, true); zend_declare_typed_class_constant(class_entry, const_STRENGTH_name, &const_STRENGTH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_STRENGTH_name); + zend_string_release_ex(const_STRENGTH_name, true); zval const_HIRAGANA_QUATERNARY_MODE_value; ZVAL_LONG(&const_HIRAGANA_QUATERNARY_MODE_value, UCOL_HIRAGANA_QUATERNARY_MODE); - zend_string *const_HIRAGANA_QUATERNARY_MODE_name = zend_string_init_interned("HIRAGANA_QUATERNARY_MODE", sizeof("HIRAGANA_QUATERNARY_MODE") - 1, 1); + zend_string *const_HIRAGANA_QUATERNARY_MODE_name = zend_string_init_interned("HIRAGANA_QUATERNARY_MODE", sizeof("HIRAGANA_QUATERNARY_MODE") - 1, true); zend_declare_typed_class_constant(class_entry, const_HIRAGANA_QUATERNARY_MODE_name, &const_HIRAGANA_QUATERNARY_MODE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_HIRAGANA_QUATERNARY_MODE_name); + zend_string_release_ex(const_HIRAGANA_QUATERNARY_MODE_name, true); zval const_NUMERIC_COLLATION_value; ZVAL_LONG(&const_NUMERIC_COLLATION_value, UCOL_NUMERIC_COLLATION); - zend_string *const_NUMERIC_COLLATION_name = zend_string_init_interned("NUMERIC_COLLATION", sizeof("NUMERIC_COLLATION") - 1, 1); + zend_string *const_NUMERIC_COLLATION_name = zend_string_init_interned("NUMERIC_COLLATION", sizeof("NUMERIC_COLLATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_NUMERIC_COLLATION_name, &const_NUMERIC_COLLATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NUMERIC_COLLATION_name); + zend_string_release_ex(const_NUMERIC_COLLATION_name, true); zval const_SORT_REGULAR_value; ZVAL_LONG(&const_SORT_REGULAR_value, COLLATOR_SORT_REGULAR); - zend_string *const_SORT_REGULAR_name = zend_string_init_interned("SORT_REGULAR", sizeof("SORT_REGULAR") - 1, 1); + zend_string *const_SORT_REGULAR_name = zend_string_init_interned("SORT_REGULAR", sizeof("SORT_REGULAR") - 1, true); zend_declare_typed_class_constant(class_entry, const_SORT_REGULAR_name, &const_SORT_REGULAR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SORT_REGULAR_name); + zend_string_release_ex(const_SORT_REGULAR_name, true); zval const_SORT_STRING_value; ZVAL_LONG(&const_SORT_STRING_value, COLLATOR_SORT_STRING); - zend_string *const_SORT_STRING_name = zend_string_init_interned("SORT_STRING", sizeof("SORT_STRING") - 1, 1); + zend_string *const_SORT_STRING_name = zend_string_init_interned("SORT_STRING", sizeof("SORT_STRING") - 1, true); zend_declare_typed_class_constant(class_entry, const_SORT_STRING_name, &const_SORT_STRING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SORT_STRING_name); + zend_string_release_ex(const_SORT_STRING_name, true); zval const_SORT_NUMERIC_value; ZVAL_LONG(&const_SORT_NUMERIC_value, COLLATOR_SORT_NUMERIC); - zend_string *const_SORT_NUMERIC_name = zend_string_init_interned("SORT_NUMERIC", sizeof("SORT_NUMERIC") - 1, 1); + zend_string *const_SORT_NUMERIC_name = zend_string_init_interned("SORT_NUMERIC", sizeof("SORT_NUMERIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_SORT_NUMERIC_name, &const_SORT_NUMERIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SORT_NUMERIC_name); + zend_string_release_ex(const_SORT_NUMERIC_name, true); return class_entry; } diff --git a/ext/intl/collator/collator_attr.c b/ext/intl/collator/collator_attr.c deleted file mode 100644 index f16ae0cc5285d..0000000000000 --- a/ext/intl/collator/collator_attr.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Vadim Savchuk | - | Dmitry Lakhtyuk | - +----------------------------------------------------------------------+ - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "php_intl.h" -#include "collator_class.h" -#include "collator_convert.h" - -#include - -/* {{{ Get collation attribute value. */ -PHP_FUNCTION( collator_get_attribute ) -{ - zend_long attribute, value; - - COLLATOR_METHOD_INIT_VARS - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ol", - &object, Collator_ce_ptr, &attribute ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - COLLATOR_METHOD_FETCH_OBJECT; - - value = ucol_getAttribute( co->ucoll, attribute, COLLATOR_ERROR_CODE_P( co ) ); - COLLATOR_CHECK_STATUS( co, "Error getting attribute value" ); - - RETURN_LONG( value ); -} -/* }}} */ - -/* {{{ Set collation attribute. */ -PHP_FUNCTION( collator_set_attribute ) -{ - zend_long attribute, value; - COLLATOR_METHOD_INIT_VARS - - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Oll", - &object, Collator_ce_ptr, &attribute, &value ) == FAILURE) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - COLLATOR_METHOD_FETCH_OBJECT; - - /* Set new value for the given attribute. */ - ucol_setAttribute( co->ucoll, attribute, value, COLLATOR_ERROR_CODE_P( co ) ); - COLLATOR_CHECK_STATUS( co, "Error setting attribute value" ); - - RETURN_TRUE; -} -/* }}} */ - -/* {{{ Returns the current collation strength. */ -PHP_FUNCTION( collator_get_strength ) -{ - COLLATOR_METHOD_INIT_VARS - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", - &object, Collator_ce_ptr ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - COLLATOR_METHOD_FETCH_OBJECT; - - /* Get current strength and return it. */ - RETURN_LONG( ucol_getStrength( co->ucoll ) ); -} -/* }}} */ - -/* {{{ Set the collation strength. */ -PHP_FUNCTION( collator_set_strength ) -{ - zend_long strength; - - COLLATOR_METHOD_INIT_VARS - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ol", - &object, Collator_ce_ptr, &strength ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - COLLATOR_METHOD_FETCH_OBJECT; - - /* Set given strength. */ - ucol_setStrength( co->ucoll, strength ); - - RETURN_TRUE; -} -/* }}} */ diff --git a/ext/intl/collator/collator_attr.cpp b/ext/intl/collator/collator_attr.cpp new file mode 100644 index 0000000000000..f56596deb6b0e --- /dev/null +++ b/ext/intl/collator/collator_attr.cpp @@ -0,0 +1,124 @@ +/* + +----------------------------------------------------------------------+ + | 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: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if __cplusplus >= 201703L +#include +#include +#endif + +extern "C" { +#include "php_intl.h" +} +#include "collator_class.h" +#include "collator_convert.h" + +#include + +/* {{{ Get collation attribute value. */ +U_CFUNC PHP_FUNCTION( collator_get_attribute ) +{ + zend_long attribute, value; + + COLLATOR_METHOD_INIT_VARS + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ol", + &object, Collator_ce_ptr, &attribute ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + COLLATOR_METHOD_FETCH_OBJECT; + + value = ucol_getAttribute( co->ucoll, static_cast(attribute), COLLATOR_ERROR_CODE_P( co ) ); + COLLATOR_CHECK_STATUS( co, "Error getting attribute value" ); + + RETURN_LONG( value ); +} +/* }}} */ + +/* {{{ Set collation attribute. */ +U_CFUNC PHP_FUNCTION( collator_set_attribute ) +{ + zend_long attribute, value; + COLLATOR_METHOD_INIT_VARS + + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Oll", + &object, Collator_ce_ptr, &attribute, &value ) == FAILURE) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + COLLATOR_METHOD_FETCH_OBJECT; + + /* Set new value for the given attribute. */ + ucol_setAttribute( co->ucoll, static_cast(attribute), static_cast(value), COLLATOR_ERROR_CODE_P( co ) ); + COLLATOR_CHECK_STATUS( co, "Error setting attribute value" ); + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ Returns the current collation strength. */ +U_CFUNC PHP_FUNCTION( collator_get_strength ) +{ + COLLATOR_METHOD_INIT_VARS + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", + &object, Collator_ce_ptr ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + COLLATOR_METHOD_FETCH_OBJECT; + + /* Get current strength and return it. */ + RETURN_LONG( ucol_getStrength( co->ucoll ) ); +} +/* }}} */ + +/* {{{ Set the collation strength. */ +U_CFUNC PHP_FUNCTION( collator_set_strength ) +{ + zend_long strength; + + COLLATOR_METHOD_INIT_VARS + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ol", + &object, Collator_ce_ptr, &strength ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + COLLATOR_METHOD_FETCH_OBJECT; + + /* Set given strength. */ + ucol_setStrength( co->ucoll, static_cast(strength) ); + + RETURN_TRUE; +} +/* }}} */ diff --git a/ext/intl/collator/collator_class.c b/ext/intl/collator/collator_class.c deleted file mode 100644 index 3a883c9e2e645..0000000000000 --- a/ext/intl/collator/collator_class.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Vadim Savchuk | - | Dmitry Lakhtyuk | - +----------------------------------------------------------------------+ - */ - -#include "collator.h" -#include "collator_class.h" -#include "php_intl.h" -#include "collator_sort.h" -#include "collator_convert.h" -#include "intl_error.h" - -#include - -#include "collator_arginfo.h" - -zend_class_entry *Collator_ce_ptr = NULL; -static zend_object_handlers Collator_handlers; - -/* - * Auxiliary functions needed by objects of 'Collator' class - */ - -/* {{{ Collator_objects_free */ -void Collator_objects_free(zend_object *object ) -{ - Collator_object* co = php_intl_collator_fetch_object(object); - - zend_object_std_dtor(&co->zo ); - - collator_object_destroy(co ); -} -/* }}} */ - -/* {{{ Collator_object_create */ -zend_object *Collator_object_create(zend_class_entry *ce ) -{ - Collator_object *intern = zend_object_alloc(sizeof(Collator_object), ce); - intl_error_init(COLLATOR_ERROR_P(intern)); - zend_object_std_init(&intern->zo, ce ); - object_properties_init(&intern->zo, ce); - - return &intern->zo; -} -/* }}} */ - -/* - * 'Collator' class registration structures & functions - */ - -/* {{{ collator_register_Collator_symbols - * Initialize 'Collator' class - */ -void collator_register_Collator_symbols(int module_number) -{ - register_collator_symbols(module_number); - - /* Create and register 'Collator' class. */ - Collator_ce_ptr = register_class_Collator(); - Collator_ce_ptr->create_object = Collator_object_create; - Collator_ce_ptr->default_object_handlers = &Collator_handlers; - - memcpy(&Collator_handlers, &std_object_handlers, - sizeof Collator_handlers); - /* Collator has no usable clone semantics - ucol_cloneBinary/ucol_openBinary require binary buffer - for which we don't have the place to keep */ - Collator_handlers.offset = XtOffsetOf(Collator_object, zo); - Collator_handlers.clone_obj = NULL; - Collator_handlers.free_obj = Collator_objects_free; -} -/* }}} */ - -/* {{{ void collator_object_init( Collator_object* co ) - * Initialize internals of Collator_object. - * Must be called before any other call to 'collator_object_...' functions. - */ -void collator_object_init( Collator_object* co ) -{ - if( !co ) - return; - - intl_error_init( COLLATOR_ERROR_P( co ) ); -} -/* }}} */ - -/* {{{ void collator_object_destroy( Collator_object* co ) - * Clean up mem allocted by internals of Collator_object - */ -void collator_object_destroy( Collator_object* co ) -{ - if( !co ) - return; - - if( co->ucoll ) - { - ucol_close( co->ucoll ); - co->ucoll = NULL; - } - - intl_error_reset( COLLATOR_ERROR_P( co ) ); -} -/* }}} */ diff --git a/ext/intl/collator/collator_class.cpp b/ext/intl/collator/collator_class.cpp new file mode 100644 index 0000000000000..293a089c26796 --- /dev/null +++ b/ext/intl/collator/collator_class.cpp @@ -0,0 +1,114 @@ +/* + +----------------------------------------------------------------------+ + | 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: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#include "collator.h" +#include "collator_class.h" +extern "C" { +#include "php_intl.h" +#include "intl_error.h" +#include "collator_arginfo.h" +} +#include "collator_sort.h" +#include "collator_convert.h" + +#include + + +zend_class_entry *Collator_ce_ptr = nullptr; +static zend_object_handlers Collator_handlers; + +/* + * Auxiliary functions needed by objects of 'Collator' class + */ + +/* {{{ Collator_objects_free */ +void Collator_objects_free(zend_object *object ) +{ + Collator_object* co = php_intl_collator_fetch_object(object); + + zend_object_std_dtor(&co->zo ); + + collator_object_destroy(co ); +} +/* }}} */ + +/* {{{ Collator_object_create */ +U_CFUNC zend_object *Collator_object_create(zend_class_entry *ce ) +{ + Collator_object *intern = reinterpret_cast(zend_object_alloc(sizeof(Collator_object), ce)); + intl_error_init(COLLATOR_ERROR_P(intern)); + zend_object_std_init(&intern->zo, ce ); + object_properties_init(&intern->zo, ce); + + return &intern->zo; +} +/* }}} */ + +/* + * 'Collator' class registration structures & functions + */ + +/* {{{ collator_register_Collator_symbols + * Initialize 'Collator' class + */ +U_CFUNC void collator_register_Collator_symbols(int module_number) +{ + register_collator_symbols(module_number); + + /* Create and register 'Collator' class. */ + Collator_ce_ptr = register_class_Collator(); + Collator_ce_ptr->create_object = Collator_object_create; + Collator_ce_ptr->default_object_handlers = &Collator_handlers; + + memcpy(&Collator_handlers, &std_object_handlers, + sizeof Collator_handlers); + /* Collator has no usable clone semantics - ucol_cloneBinary/ucol_openBinary require binary buffer + for which we don't have the place to keep */ + Collator_handlers.offset = XtOffsetOf(Collator_object, zo); + Collator_handlers.clone_obj = nullptr; + Collator_handlers.free_obj = Collator_objects_free; +} +/* }}} */ + +/* {{{ void collator_object_init( Collator_object* co ) + * Initialize internals of Collator_object. + * Must be called before any other call to 'collator_object_...' functions. + */ +U_CFUNC void collator_object_init( Collator_object* co ) +{ + if( !co ) + return; + + intl_error_init( COLLATOR_ERROR_P( co ) ); +} +/* }}} */ + +/* {{{ void collator_object_destroy( Collator_object* co ) + * Clean up mem allocted by internals of Collator_object + */ +U_CFUNC void collator_object_destroy( Collator_object* co ) +{ + if( !co ) + return; + + if( co->ucoll ) + { + ucol_close( co->ucoll ); + co->ucoll = nullptr; + } + + intl_error_reset( COLLATOR_ERROR_P( co ) ); +} +/* }}} */ diff --git a/ext/intl/collator/collator_class.h b/ext/intl/collator/collator_class.h index 5c69c2e5affb2..a281b2bec8ada 100644 --- a/ext/intl/collator/collator_class.h +++ b/ext/intl/collator/collator_class.h @@ -18,9 +18,15 @@ #include +#ifdef __cplusplus +extern "C" { +#endif #include "../intl_common.h" #include "../intl_error.h" #include "../intl_data.h" +#ifdef __cplusplus +} +#endif #include @@ -46,9 +52,15 @@ static inline Collator_object *php_intl_collator_fetch_object(zend_object *obj) } #define Z_INTL_COLLATOR_P(zv) php_intl_collator_fetch_object(Z_OBJ_P(zv)) +#ifdef __cplusplus +extern "C" { +#endif void collator_register_Collator_symbols(int module_number); void collator_object_init( Collator_object* co ); void collator_object_destroy( Collator_object* co ); +#ifdef __cplusplus +} +#endif extern zend_class_entry *Collator_ce_ptr; @@ -66,7 +78,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 deleted file mode 100644 index f71d57f74f86a..0000000000000 --- a/ext/intl/collator/collator_compare.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Vadim Savchuk | - | Dmitry Lakhtyuk | - +----------------------------------------------------------------------+ - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "php_intl.h" -#include "collator_class.h" -#include "intl_convert.h" - -/* {{{ Compare two strings. */ -PHP_FUNCTION( collator_compare ) -{ - char* str1 = NULL; - char* str2 = NULL; - size_t str1_len = 0; - size_t str2_len = 0; - - UChar* ustr1 = NULL; - UChar* ustr2 = NULL; - int ustr1_len = 0; - int ustr2_len = 0; - - UCollationResult result; - - COLLATOR_METHOD_INIT_VARS - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Oss", - &object, Collator_ce_ptr, &str1, &str1_len, &str2, &str2_len ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - COLLATOR_METHOD_FETCH_OBJECT; - - 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 ); - zend_throw_error(NULL, "Object not initialized"); - - RETURN_THROWS(); - } - - /* - * Compare given strings (converting them to UTF-16 first). - */ - - /* First convert the strings to UTF-16. */ - intl_convert_utf8_to_utf16( - &ustr1, &ustr1_len, str1, str1_len, COLLATOR_ERROR_CODE_P( co ) ); - if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) ) - { - /* Set global error code. */ - 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 ); - if (ustr1) { - efree( ustr1 ); - } - RETURN_FALSE; - } - - intl_convert_utf8_to_utf16( - &ustr2, &ustr2_len, str2, str2_len, COLLATOR_ERROR_CODE_P( co ) ); - if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) ) - { - /* Set global error code. */ - 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 ); - if (ustr1) { - efree( ustr1 ); - } - if (ustr2) { - efree( ustr2 ); - } - RETURN_FALSE; - } - - /* Then compare them. */ - result = ucol_strcoll( - co->ucoll, - ustr1, ustr1_len, - ustr2, ustr2_len ); - - if( ustr1 ) - efree( ustr1 ); - if( ustr2 ) - efree( ustr2 ); - - /* Return result of the comparison. */ - RETURN_LONG( result ); -} -/* }}} */ diff --git a/ext/intl/collator/collator_compare.cpp b/ext/intl/collator/collator_compare.cpp new file mode 100644 index 0000000000000..38e283a6d8530 --- /dev/null +++ b/ext/intl/collator/collator_compare.cpp @@ -0,0 +1,118 @@ +/* + +----------------------------------------------------------------------+ + | 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: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if __cplusplus >= 201703L +#include +#include +#endif + +extern "C" { +#include "php_intl.h" +#include "intl_convert.h" +} +#include "collator_class.h" + +/* {{{ Compare two strings. */ +U_CFUNC PHP_FUNCTION( collator_compare ) +{ + char* str1 = NULL; + char* str2 = NULL; + size_t str1_len = 0; + size_t str2_len = 0; + + UChar* ustr1 = NULL; + UChar* ustr2 = NULL; + int ustr1_len = 0; + int ustr2_len = 0; + + UCollationResult result; + + COLLATOR_METHOD_INIT_VARS + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Oss", + &object, Collator_ce_ptr, &str1, &str1_len, &str2, &str2_len ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + COLLATOR_METHOD_FETCH_OBJECT; + + 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"); + zend_throw_error(NULL, "Object not initialized"); + + RETURN_THROWS(); + } + + /* + * Compare given strings (converting them to UTF-16 first). + */ + + /* First convert the strings to UTF-16. */ + intl_convert_utf8_to_utf16( + &ustr1, &ustr1_len, str1, str1_len, COLLATOR_ERROR_CODE_P( co ) ); + if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) ) + { + /* Set global error code. */ + 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"); + if (ustr1) { + efree( ustr1 ); + } + RETURN_FALSE; + } + + intl_convert_utf8_to_utf16( + &ustr2, &ustr2_len, str2, str2_len, COLLATOR_ERROR_CODE_P( co ) ); + if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) ) + { + /* Set global error code. */ + 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"); + if (ustr1) { + efree( ustr1 ); + } + if (ustr2) { + efree( ustr2 ); + } + RETURN_FALSE; + } + + /* Then compare them. */ + result = ucol_strcoll( + co->ucoll, + ustr1, ustr1_len, + ustr2, ustr2_len ); + + if( ustr1 ) + efree( ustr1 ); + if( ustr2 ) + efree( ustr2 ); + + /* Return result of the comparison. */ + RETURN_LONG( result ); +} +/* }}} */ diff --git a/ext/intl/collator/collator_convert.c b/ext/intl/collator/collator_convert.c deleted file mode 100644 index 68f177e36b0ff..0000000000000 --- a/ext/intl/collator/collator_convert.c +++ /dev/null @@ -1,376 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Vadim Savchuk | - | Dmitry Lakhtyuk | - +----------------------------------------------------------------------+ - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "php_intl.h" -#include "collator_class.h" -#include "collator_is_numeric.h" -#include "collator_convert.h" -#include "intl_convert.h" - -#include -#include - -#define COLLATOR_CONVERT_RETURN_FAILED(retval) { \ - Z_TRY_ADDREF_P(retval); \ - return retval; \ - } - -/* {{{ collator_convert_hash_item_from_utf8_to_utf16 */ -static void collator_convert_hash_item_from_utf8_to_utf16( - HashTable* hash, zval *hashData, zend_string *hashKey, zend_ulong hashIndex, - UErrorCode* status ) -{ - const char* old_val; - size_t old_val_len; - zval znew_val; - - /* Process string values only. */ - if( Z_TYPE_P( hashData ) != IS_STRING ) - return; - - old_val = Z_STRVAL_P( hashData ); - old_val_len = Z_STRLEN_P( hashData ); - - /* Convert it from UTF-8 to UTF-16LE. */ - zend_string *zstr = intl_convert_utf8_to_utf16_zstr( old_val, old_val_len, status ); - if( U_FAILURE( *status ) ) - return; - - /* Update current hash item with the converted value. */ - ZVAL_NEW_STR( &znew_val, zstr ); - - if( hashKey) - { - zend_hash_update( hash, hashKey, &znew_val); - } - else /* hashKeyType == HASH_KEY_IS_LONG */ - { - zend_hash_index_update( hash, hashIndex, &znew_val); - } -} -/* }}} */ - -/* {{{ collator_convert_hash_item_from_utf16_to_utf8 */ -static void collator_convert_hash_item_from_utf16_to_utf8( - HashTable* hash, zval * hashData, zend_string* hashKey, zend_ulong hashIndex, - UErrorCode* status ) -{ - const char* old_val; - size_t old_val_len; - zend_string* u8str; - zval znew_val; - - /* Process string values only. */ - if( Z_TYPE_P( hashData ) != IS_STRING ) - return; - - old_val = Z_STRVAL_P( hashData ); - old_val_len = Z_STRLEN_P( hashData ); - - /* Convert it from UTF-16LE to UTF-8 and save the result to new_val[_len]. */ - u8str = intl_convert_utf16_to_utf8( - (UChar*)old_val, UCHARS(old_val_len), status ); - if( !u8str ) - return; - - /* Update current hash item with the converted value. */ - ZVAL_NEW_STR( &znew_val, u8str); - - if( hashKey ) - { - zend_hash_update( hash, hashKey, &znew_val); - } - else /* hashKeyType == HASH_KEY_IS_LONG */ - { - zend_hash_index_update( hash, hashIndex, &znew_val); - } -} -/* }}} */ - -/* {{{ collator_convert_hash_from_utf8_to_utf16 - * Convert values of the given hash from UTF-8 encoding to UTF-16LE. - */ -void collator_convert_hash_from_utf8_to_utf16( HashTable* hash, UErrorCode* status ) -{ - zend_ulong hashIndex; - zval *hashData; - zend_string *hashKey; - - ZEND_HASH_FOREACH_KEY_VAL(hash, hashIndex, hashKey, hashData) { - /* Convert current hash item from UTF-8 to UTF-16LE. */ - collator_convert_hash_item_from_utf8_to_utf16( - hash, hashData, hashKey, hashIndex, status ); - if( U_FAILURE( *status ) ) - return; - } ZEND_HASH_FOREACH_END(); -} -/* }}} */ - -/* {{{ collator_convert_hash_from_utf16_to_utf8 - * Convert values of the given hash from UTF-16LE encoding to UTF-8. - */ -void collator_convert_hash_from_utf16_to_utf8( HashTable* hash, UErrorCode* status ) -{ - zend_ulong hashIndex; - zend_string *hashKey; - zval *hashData; - - ZEND_HASH_FOREACH_KEY_VAL(hash, hashIndex, hashKey, hashData) { - /* Convert current hash item from UTF-16LE to UTF-8. */ - collator_convert_hash_item_from_utf16_to_utf8( - hash, hashData, hashKey, hashIndex, status ); - if( U_FAILURE( *status ) ) { - return; - } - } ZEND_HASH_FOREACH_END(); -} -/* }}} */ - -/* {{{ collator_convert_zstr_utf16_to_utf8 - * - * Convert string from utf16 to utf8. - * - * @param zval* utf16_zval String to convert. - * - * @return zval* Converted string. - */ -zval* collator_convert_zstr_utf16_to_utf8( zval* utf16_zval, zval *rv ) -{ - zend_string* u8str; - UErrorCode status = U_ZERO_ERROR; - - /* Convert to utf8 then. */ - u8str = intl_convert_utf16_to_utf8( - (UChar*) Z_STRVAL_P(utf16_zval), UCHARS( Z_STRLEN_P(utf16_zval) ), &status ); - if( !u8str ) { - php_error( E_WARNING, "Error converting utf16 to utf8 in collator_convert_zval_utf16_to_utf8()" ); - ZVAL_EMPTY_STRING( rv ); - } else { - ZVAL_NEW_STR( rv, u8str ); - } - return rv; -} -/* }}} */ - -zend_string *collator_convert_zstr_utf8_to_utf16(zend_string *utf8_str) -{ - UErrorCode status = U_ZERO_ERROR; - - /* Convert the string to UTF-16. */ - zend_string *zstr = intl_convert_utf8_to_utf16_zstr( - ZSTR_VAL(utf8_str), ZSTR_LEN(utf8_str), - &status); - // FIXME Or throw error or use intl internal error handler - if (U_FAILURE(status)) { - php_error(E_WARNING, - "Error casting object to string in collator_convert_zstr_utf8_to_utf16()"); - zstr = ZSTR_EMPTY_ALLOC(); - } - - return zstr; -} - -/* {{{ collator_convert_object_to_string - * Convert object to UTF16-encoded string. - */ -zval* collator_convert_object_to_string( zval* obj, zval *rv ) -{ - zval* zstr = NULL; - UErrorCode status = U_ZERO_ERROR; - - /* Bail out if it's not an object. */ - if( Z_TYPE_P( obj ) != IS_OBJECT ) - { - COLLATOR_CONVERT_RETURN_FAILED( obj ); - } - - /* Try object's handlers. */ - zstr = rv; - - if( Z_OBJ_HT_P(obj)->cast_object( Z_OBJ_P(obj), zstr, IS_STRING ) == FAILURE ) - { - /* cast_object failed => bail out. */ - zval_ptr_dtor( zstr ); - COLLATOR_CONVERT_RETURN_FAILED( obj ); - } - - /* Object wasn't successfully converted => bail out. */ - if( zstr == NULL ) - { - COLLATOR_CONVERT_RETURN_FAILED( obj ); - } - - /* Convert the string to UTF-16. */ - zend_string *converted_str = intl_convert_utf8_to_utf16_zstr( - Z_STRVAL_P( zstr ), Z_STRLEN_P( zstr ), - &status ); - // FIXME Or throw error or use intl internal error handler - if( U_FAILURE( status ) ) { - php_error( E_WARNING, "Error casting object to string in collator_convert_object_to_string()" ); - converted_str = ZSTR_EMPTY_ALLOC(); - } - - /* Cleanup zstr to hold utf16 string. */ - zval_ptr_dtor_str( zstr ); - - /* Set string. */ - ZVAL_STR( zstr, converted_str ); - - return zstr; -} -/* }}} */ - -/* {{{ collator_convert_string_to_number - * - * Convert string to number. - * - * @param zval* str String to convert. - * - * @return zval* Number. If str is not numeric string return number zero. - */ -zval* collator_convert_string_to_number( zval* str, zval *rv ) -{ - zval* num = collator_convert_string_to_number_if_possible( str, rv ); - if( num == str ) - { - /* String wasn't converted => return zero. */ - zval_ptr_dtor( num ); - - num = rv; - ZVAL_LONG( num, 0 ); - } - - return num; -} -/* }}} */ - -/* {{{ collator_convert_string_to_double - * - * Convert string to double. - * - * @param zval* str String to convert. - * - * @return zval* Number. If str is not numeric string return number zero. - */ -zval* collator_convert_string_to_double( zval* str, zval *rv ) -{ - zval* num = collator_convert_string_to_number( str, rv ); - if( Z_TYPE_P(num) == IS_LONG ) - { - ZVAL_DOUBLE( num, Z_LVAL_P( num ) ); - } - - return num; -} -/* }}} */ - -/* {{{ collator_convert_string_to_number_if_possible - * - * Convert string to numer. - * - * @param zval* str String to convert. - * - * @return zval* Number if str is numeric string. Otherwise - * original str param. - */ -zval* collator_convert_string_to_number_if_possible( zval* str, zval *rv ) -{ - uint8_t is_numeric = 0; - zend_long lval = 0; - double dval = 0; - - if( Z_TYPE_P( str ) != IS_STRING ) - { - COLLATOR_CONVERT_RETURN_FAILED( str ); - } - - if ( ( is_numeric = collator_is_numeric( (UChar*) Z_STRVAL_P(str), UCHARS( Z_STRLEN_P(str) ), &lval, &dval, /* allow_errors */ false ) ) ) - { - if( is_numeric == IS_LONG ) { - ZVAL_LONG(rv, lval); - } - if( is_numeric == IS_DOUBLE ) - ZVAL_DOUBLE(rv, dval); - } - else - { - COLLATOR_CONVERT_RETURN_FAILED( str ); - } - - return rv; -} -/* }}} */ - -/* Returns string from input zval. - * - * @param zval* arg zval to get string from - * - * @return zend_string* UTF16 string. - */ -zend_string *collator_zval_to_string(zval *arg) -{ - // TODO: This is extremely weird in that it leaves pre-existing strings alone and does not - // perform a UTF-8 to UTF-16 conversion for them. The assumption is that values that are - // already strings have already been converted beforehand. It would be good to clean this up. - if (Z_TYPE_P(arg) == IS_STRING) { - return zend_string_copy(Z_STR_P(arg)); - } - - zend_string *utf8_str = zval_get_string(arg); - zend_string *utf16_str = collator_convert_zstr_utf8_to_utf16(utf8_str); - zend_string_release(utf8_str); - return utf16_str; -} - -/* {{{ collator_normalize_sort_argument - * - * Normalize argument to use in sort's compare function. - * - * @param zval* arg Sort's argument to normalize. - * - * @return zval* Normalized copy of arg or unmodified arg - * if normalization is not needed. - */ -zval* collator_normalize_sort_argument( zval* arg, zval *rv ) -{ - zval* n_arg = NULL; - - if( Z_TYPE_P( arg ) != IS_STRING ) - { - /* If it's not a string then nothing to do. - * Return original arg. - */ - COLLATOR_CONVERT_RETURN_FAILED( arg ); - } - - /* Try convert to number. */ - n_arg = collator_convert_string_to_number_if_possible( arg, rv ); - - if( n_arg == arg ) - { - /* Conversion to number failed. */ - zval_ptr_dtor( n_arg ); - - /* Convert string to utf8. */ - n_arg = collator_convert_zstr_utf16_to_utf8( arg, rv ); - } - - return n_arg; -} -/* }}} */ diff --git a/ext/intl/collator/collator_convert.cpp b/ext/intl/collator/collator_convert.cpp new file mode 100644 index 0000000000000..d4de15aa0b822 --- /dev/null +++ b/ext/intl/collator/collator_convert.cpp @@ -0,0 +1,383 @@ +/* + +----------------------------------------------------------------------+ + | 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: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if __cplusplus >= 201703L +#include +#include +#endif + +extern "C" { +#include "php_intl.h" +#include "intl_convert.h" +} +#include "collator_class.h" +#include "collator_is_numeric.h" +#include "collator_convert.h" + +#include +#include + +#define COLLATOR_CONVERT_RETURN_FAILED(retval) { \ + Z_TRY_ADDREF_P(retval); \ + return retval; \ + } + +/* {{{ collator_convert_hash_item_from_utf8_to_utf16 */ +static void collator_convert_hash_item_from_utf8_to_utf16( + HashTable* hash, zval *hashData, zend_string *hashKey, zend_ulong hashIndex, + UErrorCode* status ) +{ + const char* old_val; + size_t old_val_len; + zval znew_val; + + /* Process string values only. */ + if( Z_TYPE_P( hashData ) != IS_STRING ) + return; + + old_val = Z_STRVAL_P( hashData ); + old_val_len = Z_STRLEN_P( hashData ); + + /* Convert it from UTF-8 to UTF-16LE. */ + zend_string *zstr = intl_convert_utf8_to_utf16_zstr( old_val, old_val_len, status ); + if( U_FAILURE( *status ) ) + return; + + /* Update current hash item with the converted value. */ + ZVAL_NEW_STR( &znew_val, zstr ); + + if( hashKey) + { + zend_hash_update( hash, hashKey, &znew_val); + } + else /* hashKeyType == HASH_KEY_IS_LONG */ + { + zend_hash_index_update( hash, hashIndex, &znew_val); + } +} +/* }}} */ + +/* {{{ collator_convert_hash_item_from_utf16_to_utf8 */ +static void collator_convert_hash_item_from_utf16_to_utf8( + HashTable* hash, zval * hashData, zend_string* hashKey, zend_ulong hashIndex, + UErrorCode* status ) +{ + const char* old_val; + size_t old_val_len; + zend_string* u8str; + zval znew_val; + + /* Process string values only. */ + if( Z_TYPE_P( hashData ) != IS_STRING ) + return; + + old_val = Z_STRVAL_P( hashData ); + old_val_len = Z_STRLEN_P( hashData ); + + /* Convert it from UTF-16LE to UTF-8 and save the result to new_val[_len]. */ + u8str = intl_convert_utf16_to_utf8( + (UChar*)old_val, UCHARS(old_val_len), status ); + if( !u8str ) + return; + + /* Update current hash item with the converted value. */ + ZVAL_NEW_STR( &znew_val, u8str); + + if( hashKey ) + { + zend_hash_update( hash, hashKey, &znew_val); + } + else /* hashKeyType == HASH_KEY_IS_LONG */ + { + zend_hash_index_update( hash, hashIndex, &znew_val); + } +} +/* }}} */ + +/* {{{ collator_convert_hash_from_utf8_to_utf16 + * Convert values of the given hash from UTF-8 encoding to UTF-16LE. + */ +U_CFUNC void collator_convert_hash_from_utf8_to_utf16( HashTable* hash, UErrorCode* status ) +{ + zend_ulong hashIndex; + zval *hashData; + zend_string *hashKey; + + ZEND_HASH_FOREACH_KEY_VAL(hash, hashIndex, hashKey, hashData) { + /* Convert current hash item from UTF-8 to UTF-16LE. */ + collator_convert_hash_item_from_utf8_to_utf16( + hash, hashData, hashKey, hashIndex, status ); + if( U_FAILURE( *status ) ) + return; + } ZEND_HASH_FOREACH_END(); +} +/* }}} */ + +/* {{{ collator_convert_hash_from_utf16_to_utf8 + * Convert values of the given hash from UTF-16LE encoding to UTF-8. + */ +U_CFUNC void collator_convert_hash_from_utf16_to_utf8( HashTable* hash, UErrorCode* status ) +{ + zend_ulong hashIndex; + zend_string *hashKey; + zval *hashData; + + ZEND_HASH_FOREACH_KEY_VAL(hash, hashIndex, hashKey, hashData) { + /* Convert current hash item from UTF-16LE to UTF-8. */ + collator_convert_hash_item_from_utf16_to_utf8( + hash, hashData, hashKey, hashIndex, status ); + if( U_FAILURE( *status ) ) { + return; + } + } ZEND_HASH_FOREACH_END(); +} +/* }}} */ + +/* {{{ collator_convert_zstr_utf16_to_utf8 + * + * Convert string from utf16 to utf8. + * + * @param zval* utf16_zval String to convert. + * + * @return zval* Converted string. + */ +U_CFUNC zval* collator_convert_zstr_utf16_to_utf8( zval* utf16_zval, zval *rv ) +{ + zend_string* u8str; + UErrorCode status = U_ZERO_ERROR; + + /* Convert to utf8 then. */ + u8str = intl_convert_utf16_to_utf8( + (UChar*) Z_STRVAL_P(utf16_zval), UCHARS( Z_STRLEN_P(utf16_zval) ), &status ); + if( !u8str ) { + php_error( E_WARNING, "Error converting utf16 to utf8 in collator_convert_zval_utf16_to_utf8()" ); + ZVAL_EMPTY_STRING( rv ); + } else { + ZVAL_NEW_STR( rv, u8str ); + } + return rv; +} +/* }}} */ + +U_CFUNC zend_string *collator_convert_zstr_utf8_to_utf16(zend_string *utf8_str) +{ + UErrorCode status = U_ZERO_ERROR; + + /* Convert the string to UTF-16. */ + zend_string *zstr = intl_convert_utf8_to_utf16_zstr( + ZSTR_VAL(utf8_str), ZSTR_LEN(utf8_str), + &status); + // FIXME Or throw error or use intl internal error handler + if (U_FAILURE(status)) { + php_error(E_WARNING, + "Error casting object to string in collator_convert_zstr_utf8_to_utf16()"); + zstr = ZSTR_EMPTY_ALLOC(); + } + + return zstr; +} + +/* {{{ collator_convert_object_to_string + * Convert object to UTF16-encoded string. + */ +U_CFUNC zval* collator_convert_object_to_string( zval* obj, zval *rv ) +{ + zval* zstr = nullptr; + UErrorCode status = U_ZERO_ERROR; + + /* Bail out if it's not an object. */ + if( Z_TYPE_P( obj ) != IS_OBJECT ) + { + COLLATOR_CONVERT_RETURN_FAILED( obj ); + } + + /* Try object's handlers. */ + zstr = rv; + + if( Z_OBJ_HT_P(obj)->cast_object( Z_OBJ_P(obj), zstr, IS_STRING ) == FAILURE ) + { + /* cast_object failed => bail out. */ + zval_ptr_dtor( zstr ); + COLLATOR_CONVERT_RETURN_FAILED( obj ); + } + + /* Object wasn't successfully converted => bail out. */ + if( zstr == nullptr ) + { + COLLATOR_CONVERT_RETURN_FAILED( obj ); + } + + /* Convert the string to UTF-16. */ + zend_string *converted_str = intl_convert_utf8_to_utf16_zstr( + Z_STRVAL_P( zstr ), Z_STRLEN_P( zstr ), + &status ); + // FIXME Or throw error or use intl internal error handler + if( U_FAILURE( status ) ) { + php_error( E_WARNING, "Error casting object to string in collator_convert_object_to_string()" ); + converted_str = ZSTR_EMPTY_ALLOC(); + } + + /* Cleanup zstr to hold utf16 string. */ + zval_ptr_dtor_str( zstr ); + + /* Set string. */ + ZVAL_STR( zstr, converted_str ); + + return zstr; +} +/* }}} */ + +/* {{{ collator_convert_string_to_number + * + * Convert string to number. + * + * @param zval* str String to convert. + * + * @return zval* Number. If str is not numeric string return number zero. + */ +U_CFUNC zval* collator_convert_string_to_number( zval* str, zval *rv ) +{ + zval* num = collator_convert_string_to_number_if_possible( str, rv ); + if( num == str ) + { + /* String wasn't converted => return zero. */ + zval_ptr_dtor( num ); + + num = rv; + ZVAL_LONG( num, 0 ); + } + + return num; +} +/* }}} */ + +/* {{{ collator_convert_string_to_double + * + * Convert string to double. + * + * @param zval* str String to convert. + * + * @return zval* Number. If str is not numeric string return number zero. + */ +U_CFUNC zval* collator_convert_string_to_double( zval* str, zval *rv ) +{ + zval* num = collator_convert_string_to_number( str, rv ); + if( Z_TYPE_P(num) == IS_LONG ) + { + ZVAL_DOUBLE( num, Z_LVAL_P( num ) ); + } + + return num; +} +/* }}} */ + +/* {{{ collator_convert_string_to_number_if_possible + * + * Convert string to numer. + * + * @param zval* str String to convert. + * + * @return zval* Number if str is numeric string. Otherwise + * original str param. + */ +U_CFUNC zval* collator_convert_string_to_number_if_possible( zval* str, zval *rv ) +{ + uint8_t is_numeric = 0; + zend_long lval = 0; + double dval = 0; + + if( Z_TYPE_P( str ) != IS_STRING ) + { + COLLATOR_CONVERT_RETURN_FAILED( str ); + } + + if ( ( is_numeric = collator_is_numeric( (UChar*) Z_STRVAL_P(str), UCHARS( Z_STRLEN_P(str) ), &lval, &dval, /* allow_errors */ false ) ) ) + { + if( is_numeric == IS_LONG ) { + ZVAL_LONG(rv, lval); + } + if( is_numeric == IS_DOUBLE ) + ZVAL_DOUBLE(rv, dval); + } + else + { + COLLATOR_CONVERT_RETURN_FAILED( str ); + } + + return rv; +} +/* }}} */ + +/* Returns string from input zval. + * + * @param zval* arg zval to get string from + * + * @return zend_string* UTF16 string. + */ +U_CFUNC zend_string *collator_zval_to_string(zval *arg) +{ + // TODO: This is extremely weird in that it leaves pre-existing strings alone and does not + // perform a UTF-8 to UTF-16 conversion for them. The assumption is that values that are + // already strings have already been converted beforehand. It would be good to clean this up. + if (Z_TYPE_P(arg) == IS_STRING) { + return zend_string_copy(Z_STR_P(arg)); + } + + zend_string *utf8_str = zval_get_string(arg); + zend_string *utf16_str = collator_convert_zstr_utf8_to_utf16(utf8_str); + zend_string_release(utf8_str); + return utf16_str; +} + +/* {{{ collator_normalize_sort_argument + * + * Normalize argument to use in sort's compare function. + * + * @param zval* arg Sort's argument to normalize. + * + * @return zval* Normalized copy of arg or unmodified arg + * if normalization is not needed. + */ +U_CFUNC zval* collator_normalize_sort_argument( zval* arg, zval *rv ) +{ + zval* n_arg = nullptr; + + if( Z_TYPE_P( arg ) != IS_STRING ) + { + /* If it's not a string then nothing to do. + * Return original arg. + */ + COLLATOR_CONVERT_RETURN_FAILED( arg ); + } + + /* Try convert to number. */ + n_arg = collator_convert_string_to_number_if_possible( arg, rv ); + + if( n_arg == arg ) + { + /* Conversion to number failed. */ + zval_ptr_dtor( n_arg ); + + /* Convert string to utf8. */ + n_arg = collator_convert_zstr_utf16_to_utf8( arg, rv ); + } + + return n_arg; +} +/* }}} */ diff --git a/ext/intl/collator/collator_convert.h b/ext/intl/collator/collator_convert.h index 1d58560964399..8c5356095b7a1 100644 --- a/ext/intl/collator/collator_convert.h +++ b/ext/intl/collator/collator_convert.h @@ -19,6 +19,9 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif void collator_convert_hash_from_utf8_to_utf16( HashTable* hash, UErrorCode* status ); void collator_convert_hash_from_utf16_to_utf8( HashTable* hash, UErrorCode* status ); @@ -32,5 +35,8 @@ zval* collator_convert_string_to_number_if_possible( zval* str, zval *rv ); zval* collator_convert_string_to_double( zval* str, zval *rv ); zend_string *collator_zval_to_string(zval *arg); +#ifdef __cplusplus +} +#endif #endif // COLLATOR_CONVERT_H diff --git a/ext/intl/collator/collator_create.c b/ext/intl/collator/collator_create.c deleted file mode 100644 index 88dacc1c1db4e..0000000000000 --- a/ext/intl/collator/collator_create.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Vadim Savchuk | - | Dmitry Lakhtyuk | - +----------------------------------------------------------------------+ - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "php_intl.h" -#include "collator_class.h" -#include "intl_data.h" - -/* {{{ */ -static int collator_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling *error_handling, bool *error_handling_replaced) -{ - char* locale; - size_t locale_len = 0; - zval* object; - Collator_object* co; - - intl_error_reset( NULL ); - object = return_value; - ZEND_PARSE_PARAMETERS_START(1, 1) - 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; - - if(locale_len == 0) { - locale = (char *)intl_locale_get_default(); - } - - /* 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"); - return SUCCESS; -} -/* }}} */ - -/* {{{ Create collator. */ -PHP_FUNCTION( collator_create ) -{ - object_init_ex( return_value, Collator_ce_ptr ); - if (collator_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL, NULL) == FAILURE) { - zval_ptr_dtor(return_value); - RETURN_NULL(); - } -} -/* }}} */ - -/* {{{ Collator object constructor. */ -PHP_METHOD( Collator, __construct ) -{ - zend_error_handling error_handling; - bool error_handling_replaced = 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); - } -} -/* }}} */ diff --git a/ext/intl/collator/collator_create.cpp b/ext/intl/collator/collator_create.cpp new file mode 100644 index 0000000000000..59280bcdbed5e --- /dev/null +++ b/ext/intl/collator/collator_create.cpp @@ -0,0 +1,85 @@ +/* + +----------------------------------------------------------------------+ + | 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: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if __cplusplus >= 201703L +#include +#include +#endif + +extern "C" { +#include "php_intl.h" +} +#include "collator_class.h" +#include "intl_data.h" + +/* {{{ */ +static int collator_ctor(INTERNAL_FUNCTION_PARAMETERS) +{ + char* locale; + size_t locale_len = 0; + zval* object; + Collator_object* co; + + intl_error_reset( nullptr ); + object = return_value; + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STRING(locale, locale_len) + ZEND_PARSE_PARAMETERS_END_EX(return FAILURE); + + INTL_CHECK_LOCALE_LEN_OR_FAILURE(locale_len); + COLLATOR_METHOD_FETCH_OBJECT; + + if(locale_len == 0) { + locale = (char *)intl_locale_get_default(); + } + + /* Open ICU collator. */ + co->ucoll = ucol_open( locale, COLLATOR_ERROR_CODE_P( co ) ); + INTL_CTOR_CHECK_STATUS(co, "unable to open ICU collator"); + return SUCCESS; +} +/* }}} */ + +/* {{{ Create collator. */ +U_CFUNC PHP_FUNCTION( collator_create ) +{ + object_init_ex( return_value, Collator_ce_ptr ); + if (collator_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU) == FAILURE) { + zval_ptr_dtor(return_value); + RETURN_NULL(); + } +} +/* }}} */ + +/* {{{ Collator object constructor. */ +U_CFUNC PHP_METHOD( Collator, __construct ) +{ + 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) == 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_error.c b/ext/intl/collator/collator_error.c deleted file mode 100644 index 2189b312d7c29..0000000000000 --- a/ext/intl/collator/collator_error.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Vadim Savchuk | - | Dmitry Lakhtyuk | - +----------------------------------------------------------------------+ - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "php_intl.h" -#include "collator_class.h" - -/* {{{ Get collator's last error code. */ -PHP_FUNCTION( collator_get_error_code ) -{ - COLLATOR_METHOD_INIT_VARS - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", - &object, Collator_ce_ptr ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object (without resetting its last error code). */ - co = Z_INTL_COLLATOR_P(object); - if( co == NULL ) - RETURN_FALSE; - - /* Return collator's last error code. */ - RETURN_LONG( COLLATOR_ERROR_CODE( co ) ); -} -/* }}} */ - -/* {{{ Get text description for collator's last error code. */ -PHP_FUNCTION( collator_get_error_message ) -{ - zend_string* message = NULL; - - COLLATOR_METHOD_INIT_VARS - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", - &object, Collator_ce_ptr ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object (without resetting its last error code). */ - co = Z_INTL_COLLATOR_P( object ); - if( co == NULL ) - RETURN_FALSE; - - /* Return last error message. */ - message = intl_error_get_message( COLLATOR_ERROR_P( co ) ); - RETURN_STR(message); -} -/* }}} */ diff --git a/ext/intl/collator/collator_error.cpp b/ext/intl/collator/collator_error.cpp new file mode 100644 index 0000000000000..aa333b5098a04 --- /dev/null +++ b/ext/intl/collator/collator_error.cpp @@ -0,0 +1,75 @@ +/* + +----------------------------------------------------------------------+ + | 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: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if __cplusplus >= 201703L +#include +#include +#endif + +extern "C" { +#include "php_intl.h" +} +#include "collator_class.h" + +/* {{{ Get collator's last error code. */ +U_CFUNC PHP_FUNCTION( collator_get_error_code ) +{ + COLLATOR_METHOD_INIT_VARS + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", + &object, Collator_ce_ptr ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object (without resetting its last error code). */ + co = Z_INTL_COLLATOR_P(object); + if( co == nullptr ) + RETURN_FALSE; + + /* Return collator's last error code. */ + RETURN_LONG( COLLATOR_ERROR_CODE( co ) ); +} +/* }}} */ + +/* {{{ Get text description for collator's last error code. */ +U_CFUNC PHP_FUNCTION( collator_get_error_message ) +{ + zend_string* message = nullptr; + + COLLATOR_METHOD_INIT_VARS + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", + &object, Collator_ce_ptr ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object (without resetting its last error code). */ + co = Z_INTL_COLLATOR_P( object ); + if( co == nullptr ) + RETURN_FALSE; + + /* Return last error message. */ + message = intl_error_get_message( COLLATOR_ERROR_P( co ) ); + RETURN_STR(message); +} +/* }}} */ diff --git a/ext/intl/collator/collator_is_numeric.c b/ext/intl/collator/collator_is_numeric.c deleted file mode 100644 index 4c473d9477116..0000000000000 --- a/ext/intl/collator/collator_is_numeric.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Vadim Savchuk | - | Dmitry Lakhtyuk | - +----------------------------------------------------------------------+ - */ - -#include "collator_is_numeric.h" - -/* {{{ Taken from PHP6:zend_u_strtod() */ -static double collator_u_strtod(const UChar *nptr, UChar **endptr) /* {{{ */ -{ - const UChar *u = nptr, *nstart; - UChar c = *u; - int any = 0; - - while (u_isspace(c)) { - c = *++u; - } - nstart = u; - - if (c == 0x2D /*'-'*/ || c == 0x2B /*'+'*/) { - c = *++u; - } - - while (c >= 0x30 /*'0'*/ && c <= 0x39 /*'9'*/) { - any = 1; - c = *++u; - } - - if (c == 0x2E /*'.'*/) { - c = *++u; - while (c >= 0x30 /*'0'*/ && c <= 0x39 /*'9'*/) { - any = 1; - c = *++u; - } - } - - if ((c == 0x65 /*'e'*/ || c == 0x45 /*'E'*/) && any) { - const UChar *e = u; - int any_exp = 0; - - c = *++u; - if (c == 0x2D /*'-'*/ || c == 0x2B /*'+'*/) { - c = *++u; - } - - while (c >= 0x30 /*'0'*/ && c <= 0x39 /*'9'*/) { - any_exp = 1; - c = *++u; - } - - if (!any_exp) { - u = e; - } - } - - if (any) { - char buf[64], *numbuf, *bufpos; - size_t length = u - nstart; - double value; - ALLOCA_FLAG(use_heap = 0); - - if (length < sizeof(buf)) { - numbuf = buf; - } else { - numbuf = (char *) do_alloca(length + 1, use_heap); - } - - bufpos = numbuf; - - while (nstart < u) { - *bufpos++ = (char) *nstart++; - } - - *bufpos = '\0'; - value = zend_strtod(numbuf, NULL); - - if (numbuf != buf) { - free_alloca(numbuf, use_heap); - } - - if (endptr != NULL) { - *endptr = (UChar *)u; - } - - return value; - } - - if (endptr != NULL) { - *endptr = (UChar *)nptr; - } - - return 0; -} -/* }}} */ - -/* {{{ collator_u_strtol - * Taken from PHP6:zend_u_strtol() - * - * Convert a Unicode string to a long integer. - * - * Ignores `locale' stuff. - */ -static zend_long collator_u_strtol(const UChar *nptr, UChar **endptr, int base) -{ - const UChar *s = nptr; - zend_ulong acc; - UChar c; - zend_ulong cutoff; - int neg = 0, any, cutlim; - - if (s == NULL) { - errno = ERANGE; - if (endptr != NULL) { - *endptr = NULL; - } - return 0; - } - - /* - * Skip white space and pick up leading +/- sign if any. - * If base is 0, allow 0x for hex and 0 for octal, else - * assume decimal; if base is already 16, allow 0x. - */ - do { - c = *s++; - } while (u_isspace(c)); - if (c == 0x2D /*'-'*/) { - neg = 1; - c = *s++; - } else if (c == 0x2B /*'+'*/) - c = *s++; - if ((base == 0 || base == 16) && - (c == 0x30 /*'0'*/) - && (*s == 0x78 /*'x'*/ || *s == 0x58 /*'X'*/)) { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) - base = (c == 0x30 /*'0'*/) ? 8 : 10; - - /* - * Compute the cutoff value between legal numbers and illegal - * numbers. That is the largest legal value, divided by the - * base. An input number that is greater than this value, if - * followed by a legal input character, is too big. One that - * is equal to this value may be valid or not; the limit - * between valid and invalid numbers is then based on the last - * digit. For instance, if the range for longs is - * [-2147483648..2147483647] and the input base is 10, - * cutoff will be set to 214748364 and cutlim to either - * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated - * a value > 214748364, or equal but the next digit is > 7 (or 8), - * the number is too big, and we will return a range error. - * - * Set any if any `digits' consumed; make it negative to indicate - * overflow. - */ - cutoff = neg ? -(zend_ulong)ZEND_LONG_MIN : ZEND_LONG_MAX; - cutlim = cutoff % (zend_ulong)base; - cutoff /= (zend_ulong)base; - for (acc = 0, any = 0;; c = *s++) { - if (c >= 0x30 /*'0'*/ && c <= 0x39 /*'9'*/) - c -= 0x30 /*'0'*/; - else if (c >= 0x41 /*'A'*/ && c <= 0x5A /*'Z'*/) - c -= 0x41 /*'A'*/ - 10; - else if (c >= 0x61 /*'a'*/ && c <= 0x7A /*'z'*/) - c -= 0x61 /*'a'*/ - 10; - else - break; - if (c >= base) - break; - - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) - any = -1; - else { - any = 1; - acc *= base; - acc += c; - } - } - if (any < 0) { - acc = neg ? ZEND_LONG_MIN : ZEND_LONG_MAX; - errno = ERANGE; - } else if (neg) - acc = -acc; - if (endptr != NULL) - *endptr = (UChar *)(any ? s - 1 : nptr); - return (acc); -} -/* }}} */ - -/* Consume (trailing) whitespace just like collator_u_strtol() consumes leading whitespace */ -static zend_always_inline UChar *collator_skip_ws(UChar *end_ptr) -{ - while (u_isspace(*end_ptr)) { - end_ptr++; - } - return end_ptr; -} - -/* {{{ collator_is_numeric] - * Taken from PHP6:is_numeric_unicode() - */ -uint8_t collator_is_numeric( UChar *str, int32_t length, zend_long *lval, double *dval, bool allow_errors ) -{ - zend_long local_lval; - double local_dval; - UChar *end_ptr_long, *end_ptr_double; - - if (!length) { - return 0; - } - - errno=0; - local_lval = collator_u_strtol(str, &end_ptr_long, 10); - if (errno != ERANGE) { - end_ptr_long = collator_skip_ws(end_ptr_long); - if (end_ptr_long == str+length) { /* integer string */ - if (lval) { - *lval = local_lval; - } - return IS_LONG; - } else if (end_ptr_long == str && *end_ptr_long != '\0' && *str != '.' && *str != '-') { /* ignore partial string matches */ - return 0; - } - } else { - end_ptr_long = NULL; - } - - local_dval = collator_u_strtod(str, &end_ptr_double); - if (local_dval == 0 && end_ptr_double == str) { - end_ptr_double = NULL; - } else { - end_ptr_double = collator_skip_ws(end_ptr_double); - if (end_ptr_double == str+length) { /* floating point string */ - if (!zend_finite(local_dval)) { - /* "inf","nan" and maybe other weird ones */ - return 0; - } - - if (dval) { - *dval = local_dval; - } - return IS_DOUBLE; - } - } - - if (!allow_errors) { - return 0; - } - - if (allow_errors) { - if (end_ptr_double > end_ptr_long && dval) { - *dval = local_dval; - return IS_DOUBLE; - } else if (end_ptr_long && lval) { - *lval = local_lval; - return IS_LONG; - } - } - return 0; -} -/* }}} */ diff --git a/ext/intl/collator/collator_is_numeric.cpp b/ext/intl/collator/collator_is_numeric.cpp new file mode 100644 index 0000000000000..b3cc52085deaa --- /dev/null +++ b/ext/intl/collator/collator_is_numeric.cpp @@ -0,0 +1,274 @@ +/* + +----------------------------------------------------------------------+ + | 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: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#include "collator_is_numeric.h" + +/* {{{ Taken from PHP6:zend_u_strtod() */ +static double collator_u_strtod(const UChar *nptr, UChar **endptr) /* {{{ */ +{ + const UChar *u = nptr, *nstart; + UChar c = *u; + int any = 0; + + while (u_isspace(c)) { + c = *++u; + } + nstart = u; + + if (c == 0x2D /*'-'*/ || c == 0x2B /*'+'*/) { + c = *++u; + } + + while (c >= 0x30 /*'0'*/ && c <= 0x39 /*'9'*/) { + any = 1; + c = *++u; + } + + if (c == 0x2E /*'.'*/) { + c = *++u; + while (c >= 0x30 /*'0'*/ && c <= 0x39 /*'9'*/) { + any = 1; + c = *++u; + } + } + + if ((c == 0x65 /*'e'*/ || c == 0x45 /*'E'*/) && any) { + const UChar *e = u; + int any_exp = 0; + + c = *++u; + if (c == 0x2D /*'-'*/ || c == 0x2B /*'+'*/) { + c = *++u; + } + + while (c >= 0x30 /*'0'*/ && c <= 0x39 /*'9'*/) { + any_exp = 1; + c = *++u; + } + + if (!any_exp) { + u = e; + } + } + + if (any) { + char buf[64], *numbuf, *bufpos; + size_t length = u - nstart; + double value; + ALLOCA_FLAG(use_heap = 0); + + if (length < sizeof(buf)) { + numbuf = buf; + } else { + numbuf = (char *) do_alloca(length + 1, use_heap); + } + + bufpos = numbuf; + + while (nstart < u) { + *bufpos++ = (char) *nstart++; + } + + *bufpos = '\0'; + value = zend_strtod(numbuf, nullptr); + + if (numbuf != buf) { + free_alloca(numbuf, use_heap); + } + + if (endptr != nullptr) { + *endptr = (UChar *)u; + } + + return value; + } + + if (endptr != nullptr) { + *endptr = (UChar *)nptr; + } + + return 0; +} +/* }}} */ + +/* {{{ collator_u_strtol + * Taken from PHP6:zend_u_strtol() + * + * Convert a Unicode string to a long integer. + * + * Ignores `locale' stuff. + */ +static zend_long collator_u_strtol(const UChar *nptr, UChar **endptr, int base) +{ + const UChar *s = nptr; + zend_ulong acc; + UChar c; + zend_ulong cutoff; + int neg = 0, any, cutlim; + + if (s == nullptr) { + errno = ERANGE; + if (endptr != nullptr) { + *endptr = nullptr; + } + return 0; + } + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + do { + c = *s++; + } while (u_isspace(c)); + if (c == 0x2D /*'-'*/) { + neg = 1; + c = *s++; + } else if (c == 0x2B /*'+'*/) + c = *s++; + if ((base == 0 || base == 16) && + (c == 0x30 /*'0'*/) + && (*s == 0x78 /*'x'*/ || *s == 0x58 /*'X'*/)) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = (c == 0x30 /*'0'*/) ? 8 : 10; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for longs is + * [-2147483648..2147483647] and the input base is 10, + * cutoff will be set to 214748364 and cutlim to either + * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated + * a value > 214748364, or equal but the next digit is > 7 (or 8), + * the number is too big, and we will return a range error. + * + * Set any if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? -(zend_ulong)ZEND_LONG_MIN : ZEND_LONG_MAX; + cutlim = cutoff % (zend_ulong)base; + cutoff /= (zend_ulong)base; + for (acc = 0, any = 0;; c = *s++) { + if (c >= 0x30 /*'0'*/ && c <= 0x39 /*'9'*/) + c -= 0x30 /*'0'*/; + else if (c >= 0x41 /*'A'*/ && c <= 0x5A /*'Z'*/) + c -= 0x41 /*'A'*/ - 10; + else if (c >= 0x61 /*'a'*/ && c <= 0x7A /*'z'*/) + c -= 0x61 /*'a'*/ - 10; + else + break; + if (c >= base) + break; + + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = neg ? ZEND_LONG_MIN : ZEND_LONG_MAX; + errno = ERANGE; + } else if (neg) + acc = -acc; + if (endptr != nullptr) + *endptr = (UChar *)(any ? s - 1 : nptr); + return (acc); +} +/* }}} */ + +/* Consume (trailing) whitespace just like collator_u_strtol() consumes leading whitespace */ +static zend_always_inline UChar *collator_skip_ws(UChar *end_ptr) +{ + while (u_isspace(*end_ptr)) { + end_ptr++; + } + return end_ptr; +} + +/* {{{ collator_is_numeric] + * Taken from PHP6:is_numeric_unicode() + */ +uint8_t collator_is_numeric( UChar *str, int32_t length, zend_long *lval, double *dval, bool allow_errors ) +{ + zend_long local_lval; + double local_dval; + UChar *end_ptr_long, *end_ptr_double; + + if (!length) { + return 0; + } + + errno=0; + local_lval = collator_u_strtol(str, &end_ptr_long, 10); + if (errno != ERANGE) { + end_ptr_long = collator_skip_ws(end_ptr_long); + if (end_ptr_long == str+length) { /* integer string */ + if (lval) { + *lval = local_lval; + } + return IS_LONG; + } else if (end_ptr_long == str && *end_ptr_long != '\0' && *str != '.' && *str != '-') { /* ignore partial string matches */ + return 0; + } + } else { + end_ptr_long = nullptr; + } + + local_dval = collator_u_strtod(str, &end_ptr_double); + if (local_dval == 0 && end_ptr_double == str) { + end_ptr_double = nullptr; + } else { + end_ptr_double = collator_skip_ws(end_ptr_double); + if (end_ptr_double == str+length) { /* floating point string */ + if (!zend_finite(local_dval)) { + /* "inf","nan" and maybe other weird ones */ + return 0; + } + + if (dval) { + *dval = local_dval; + } + return IS_DOUBLE; + } + } + + if (!allow_errors) { + return 0; + } + + if (allow_errors) { + if (end_ptr_double > end_ptr_long && dval) { + *dval = local_dval; + return IS_DOUBLE; + } else if (end_ptr_long && lval) { + *lval = local_lval; + return IS_LONG; + } + } + return 0; +} +/* }}} */ diff --git a/ext/intl/collator/collator_locale.c b/ext/intl/collator/collator_locale.c deleted file mode 100644 index e1cdcdf2a6091..0000000000000 --- a/ext/intl/collator/collator_locale.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Vadim Savchuk | - | Dmitry Lakhtyuk | - +----------------------------------------------------------------------+ - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "php_intl.h" -#include "collator_class.h" -#include "intl_convert.h" - -#include - -/* {{{ Gets the locale name of the collator. */ -PHP_FUNCTION( collator_get_locale ) -{ - zend_long type = 0; - char* locale_name = NULL; - - COLLATOR_METHOD_INIT_VARS - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ol", - &object, Collator_ce_ptr, &type ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - COLLATOR_METHOD_FETCH_OBJECT; - - 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 ); - zend_throw_error(NULL, "Object not initialized"); - - RETURN_THROWS(); - } - - /* Get locale by specified type. */ - locale_name = (char*) ucol_getLocaleByType( - co->ucoll, type, COLLATOR_ERROR_CODE_P( co ) ); - COLLATOR_CHECK_STATUS( co, "Error getting locale by type" ); - - /* Return it. */ - RETVAL_STRINGL( locale_name, strlen(locale_name) ); -} -/* }}} */ diff --git a/ext/intl/collator/collator_locale.cpp b/ext/intl/collator/collator_locale.cpp new file mode 100644 index 0000000000000..67b3d1342cc75 --- /dev/null +++ b/ext/intl/collator/collator_locale.cpp @@ -0,0 +1,67 @@ +/* + +----------------------------------------------------------------------+ + | 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: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if __cplusplus >= 201703L +#include +#include +#endif + +extern "C" { +#include "php_intl.h" +} +#include "collator_class.h" +#include "intl_convert.h" + +#include + +/* {{{ Gets the locale name of the collator. */ +U_CFUNC PHP_FUNCTION( collator_get_locale ) +{ + zend_long type = 0; + char* locale_name = nullptr; + + COLLATOR_METHOD_INIT_VARS + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ol", + &object, Collator_ce_ptr, &type ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + COLLATOR_METHOD_FETCH_OBJECT; + + if (!co || !co->ucoll) { + intl_error_set_code( nullptr, COLLATOR_ERROR_CODE( co ) ); + intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), "Object not initialized"); + zend_throw_error(nullptr, "Object not initialized"); + + RETURN_THROWS(); + } + + /* Get locale by specified type. */ + locale_name = (char*) ucol_getLocaleByType( + co->ucoll, static_cast(type), COLLATOR_ERROR_CODE_P( co ) ); + COLLATOR_CHECK_STATUS( co, "Error getting locale by type" ); + + /* Return it. */ + RETVAL_STRINGL( locale_name, strlen(locale_name) ); +} +/* }}} */ diff --git a/ext/intl/collator/collator_sort.c b/ext/intl/collator/collator_sort.c deleted file mode 100644 index 215f150c4faf9..0000000000000 --- a/ext/intl/collator/collator_sort.c +++ /dev/null @@ -1,562 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Vadim Savchuk | - | Dmitry Lakhtyuk | - +----------------------------------------------------------------------+ - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "php_intl.h" -#include "collator.h" -#include "collator_class.h" -#include "collator_sort.h" -#include "collator_convert.h" -#include "intl_convert.h" - -/** - * Declare 'index' which will point to sort key in sort key - * buffer. - */ -typedef struct _collator_sort_key_index { - char* key; /* pointer to sort key */ - zval* zstr; /* pointer to original string(hash-item) */ -} collator_sort_key_index_t; - -ZEND_EXTERN_MODULE_GLOBALS( intl ) - -static const size_t DEF_SORT_KEYS_BUF_SIZE = 1048576; -static const size_t DEF_SORT_KEYS_BUF_INCREMENT = 1048576; - -static const size_t DEF_SORT_KEYS_INDX_BUF_SIZE = 1048576; -static const size_t DEF_SORT_KEYS_INDX_BUF_INCREMENT = 1048576; - -static const size_t DEF_UTF16_BUF_SIZE = 1024; - -/* {{{ collator_regular_compare_function */ -static int collator_regular_compare_function(zval *result, zval *op1, zval *op2) -{ - int rc = SUCCESS; - zval str1, str2; - zval num1, num2; - zval norm1, norm2; - zval *num1_p = NULL, *num2_p = NULL; - zval *norm1_p = NULL, *norm2_p = NULL; - zval *str1_p, *str2_p; - - ZVAL_NULL(&str1); - str1_p = collator_convert_object_to_string( op1, &str1 ); - ZVAL_NULL(&str2); - str2_p = collator_convert_object_to_string( op2, &str2 ); - - /* If both args are strings AND either of args is not numeric string - * then use ICU-compare. Otherwise PHP-compare. */ - if( Z_TYPE_P(str1_p) == IS_STRING && Z_TYPE_P(str2_p) == IS_STRING && - ( str1_p == ( num1_p = collator_convert_string_to_number_if_possible( str1_p, &num1 ) ) || - str2_p == ( num2_p = collator_convert_string_to_number_if_possible( str2_p, &num2 ) ) ) ) - { - /* Compare the strings using ICU. */ - ZEND_ASSERT(INTL_G(current_collator) != NULL); - ZVAL_LONG(result, ucol_strcoll( - INTL_G(current_collator), - INTL_ZSTR_VAL(Z_STR_P(str1_p)), INTL_ZSTR_LEN(Z_STR_P(str1_p)), - INTL_ZSTR_VAL(Z_STR_P(str2_p)), INTL_ZSTR_LEN(Z_STR_P(str2_p)) )); - } - else - { - /* num1 is set if str1 and str2 are strings. */ - if( num1_p ) - { - if( num1_p == str1_p ) - { - /* str1 is string but not numeric string - * just convert it to utf8. - */ - norm1_p = collator_convert_zstr_utf16_to_utf8( str1_p, &norm1 ); - - /* num2 is not set but str2 is string => do normalization. */ - norm2_p = collator_normalize_sort_argument( str2_p, &norm2 ); - } - else - { - /* str1 is numeric strings => passthru to PHP-compare. */ - Z_TRY_ADDREF_P(num1_p); - norm1_p = num1_p; - - /* str2 is numeric strings => passthru to PHP-compare. */ - Z_TRY_ADDREF_P(num2_p); - norm2_p = num2_p; - } - } - else - { - /* num1 is not set if str1 or str2 is not a string => do normalization. */ - norm1_p = collator_normalize_sort_argument( str1_p, &norm1 ); - - /* if num1 is not set then num2 is not set as well => do normalization. */ - norm2_p = collator_normalize_sort_argument( str2_p, &norm2 ); - } - - rc = compare_function( result, norm1_p, norm2_p ); - - zval_ptr_dtor( norm1_p ); - zval_ptr_dtor( norm2_p ); - } - - if( num1_p ) - zval_ptr_dtor( num1_p ); - - if( num2_p ) - zval_ptr_dtor( num2_p ); - - zval_ptr_dtor( str1_p ); - zval_ptr_dtor( str2_p ); - - return rc; -} -/* }}} */ - -/* {{{ collator_numeric_compare_function - * Convert input args to double and compare it. - */ -static int collator_numeric_compare_function(zval *result, zval *op1, zval *op2) -{ - zval num1, num2; - zval *num1_p = NULL; - zval *num2_p = NULL; - - if( Z_TYPE_P(op1) == IS_STRING ) - { - num1_p = collator_convert_string_to_double( op1, &num1 ); - op1 = num1_p; - } - - if( Z_TYPE_P(op2) == IS_STRING ) - { - num2_p = collator_convert_string_to_double( op2, &num2 ); - op2 = num2_p; - } - - ZVAL_LONG(result, numeric_compare_function(op1, op2)); - - if( num1_p ) - zval_ptr_dtor( num1_p ); - if( num2_p ) - zval_ptr_dtor( num2_p ); - - return SUCCESS; -} -/* }}} */ - -/* {{{ collator_icu_compare_function - * Direct use of ucol_strcoll. -*/ -static int collator_icu_compare_function(zval *result, zval *op1, zval *op2) -{ - int rc = SUCCESS; - zend_string *str1 = collator_zval_to_string(op1); - zend_string *str2 = collator_zval_to_string(op2); - - /* Compare the strings using ICU. */ - ZEND_ASSERT(INTL_G(current_collator) != NULL); - ZVAL_LONG(result, ucol_strcoll( - INTL_G(current_collator), - INTL_ZSTR_VAL(str1), INTL_ZSTR_LEN(str1), - INTL_ZSTR_VAL(str2), INTL_ZSTR_LEN(str2) )); - - zend_string_release(str1); - zend_string_release(str2); - - return rc; -} -/* }}} */ - -/* {{{ collator_compare_func - * Taken from PHP7 source (array_data_compare). - */ -static int collator_compare_func(Bucket *f, Bucket *s) -{ - zval result; - zval *first = &f->val; - zval *second = &s->val; - - if( INTL_G(compare_func)( &result, first, second) == FAILURE ) - return 0; - - if( Z_TYPE(result) == IS_DOUBLE ) - { - if( Z_DVAL(result) < 0 ) - return -1; - else if( Z_DVAL(result) > 0 ) - return 1; - else - return 0; - } - - convert_to_long(&result); - - if( Z_LVAL(result) < 0 ) - return -1; - else if( Z_LVAL(result) > 0 ) - return 1; - - return 0; -} -/* }}} */ - -/* {{{ Compare sort keys */ -static int collator_cmp_sort_keys( const void *p1, const void *p2 ) -{ - char* key1 = ((collator_sort_key_index_t*)p1)->key; - char* key2 = ((collator_sort_key_index_t*)p2)->key; - - return strcmp( key1, key2 ); -} -/* }}} */ - -/* {{{ Choose compare function according to sort flags. */ -static collator_compare_func_t collator_get_compare_function( const zend_long sort_flags ) -{ - collator_compare_func_t func; - - switch( sort_flags ) - { - case COLLATOR_SORT_NUMERIC: - func = collator_numeric_compare_function; - break; - - case COLLATOR_SORT_STRING: - func = collator_icu_compare_function; - break; - - case COLLATOR_SORT_REGULAR: - default: - func = collator_regular_compare_function; - break; - } - - return func; -} -/* }}} */ - -/* {{{ Common code shared by collator_sort() and collator_asort() API functions. */ -static void collator_sort_internal( int renumber, INTERNAL_FUNCTION_PARAMETERS ) -{ - UCollator* saved_collator; - zval* array = NULL; - HashTable* hash = NULL; - zend_long sort_flags = COLLATOR_SORT_REGULAR; - - COLLATOR_METHOD_INIT_VARS - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Oa/|l", - &object, Collator_ce_ptr, &array, &sort_flags ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - COLLATOR_METHOD_FETCH_OBJECT; - - if (!co->ucoll) { - zend_throw_error(NULL, "Object not initialized"); - RETURN_THROWS(); - } - - /* Set 'compare function' according to sort flags. */ - INTL_G(compare_func) = collator_get_compare_function( sort_flags ); - - hash = Z_ARRVAL_P( array ); - - /* Convert strings in the specified array from UTF-8 to UTF-16. */ - collator_convert_hash_from_utf8_to_utf16( hash, COLLATOR_ERROR_CODE_P( co ) ); - COLLATOR_CHECK_STATUS( co, "Error converting hash from UTF-8 to UTF-16" ); - - /* Save specified collator in the request-global (?) variable. */ - saved_collator = INTL_G( current_collator ); - INTL_G( current_collator ) = co->ucoll; - - /* Sort specified array. */ - zend_hash_sort(hash, collator_compare_func, renumber); - - /* Restore saved collator. */ - INTL_G( current_collator ) = saved_collator; - - /* Convert strings in the specified array back to UTF-8. */ - collator_convert_hash_from_utf16_to_utf8( hash, COLLATOR_ERROR_CODE_P( co ) ); - COLLATOR_CHECK_STATUS( co, "Error converting hash from UTF-16 to UTF-8" ); - - RETURN_TRUE; -} -/* }}} */ - -/* {{{ Sort array using specified collator. */ -PHP_FUNCTION( collator_sort ) -{ - collator_sort_internal( true, INTERNAL_FUNCTION_PARAM_PASSTHRU ); -} -/* }}} */ - -static void collator_sortkey_swap(collator_sort_key_index_t *p, collator_sort_key_index_t *q) /* {{{ */ -{ - collator_sort_key_index_t t; - t = *p; - *p = *q; - *q = t; -} -/* }}} */ - -/* {{{ Equivalent to standard PHP sort using Collator. - * Uses ICU ucol_getSortKey for performance. - */ -PHP_FUNCTION( collator_sort_with_sort_keys ) -{ - zval* array = NULL; - zval garbage; - HashTable* hash = NULL; - zval* hashData = NULL; /* currently processed item of input hash */ - - char* sortKeyBuf = NULL; /* buffer to store sort keys */ - uint32_t sortKeyBufSize = DEF_SORT_KEYS_BUF_SIZE; /* buffer size */ - ptrdiff_t sortKeyBufOffset = 0; /* pos in buffer to store sort key */ - uint32_t sortKeyLen = 0; /* the length of currently processing key */ - uint32_t bufLeft = 0; - uint32_t bufIncrement = 0; - - collator_sort_key_index_t* sortKeyIndxBuf = NULL; /* buffer to store 'indexes' which will be passed to 'qsort' */ - uint32_t sortKeyIndxBufSize = DEF_SORT_KEYS_INDX_BUF_SIZE; - uint32_t sortKeyIndxSize = sizeof( collator_sort_key_index_t ); - - uint32_t sortKeyCount = 0; - uint32_t j = 0; - - UChar* utf16_buf = NULL; /* tmp buffer to hold current processing string in utf-16 */ - int utf16_buf_size = DEF_UTF16_BUF_SIZE; /* the length of utf16_buf */ - int utf16_len = 0; /* length of converted string */ - - COLLATOR_METHOD_INIT_VARS - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Oa", - &object, Collator_ce_ptr, &array ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - COLLATOR_METHOD_FETCH_OBJECT; - - 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 ); - zend_throw_error(NULL, "Object not initialized"); - - RETURN_THROWS(); - } - - /* - * Sort specified array. - */ - hash = Z_ARRVAL_P( array ); - - if( !hash || zend_hash_num_elements( hash ) == 0 ) - RETURN_TRUE; - - /* Create bufers */ - sortKeyBuf = ecalloc( sortKeyBufSize, sizeof( char ) ); - sortKeyIndxBuf = ecalloc( sortKeyIndxBufSize, sizeof( uint8_t ) ); - utf16_buf = eumalloc( utf16_buf_size ); - - /* Iterate through input hash and create a sort key for each value. */ - ZEND_HASH_FOREACH_VAL(hash, hashData) { - /* Convert current hash item from UTF-8 to UTF-16LE and save the result to utf16_buf. */ - - utf16_len = utf16_buf_size; - - /* Process string values only. */ - if( Z_TYPE_P( hashData ) == IS_STRING ) - { - intl_convert_utf8_to_utf16( &utf16_buf, &utf16_len, Z_STRVAL_P( hashData ), Z_STRLEN_P( hashData ), COLLATOR_ERROR_CODE_P( co ) ); - - 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 ); - - if( utf16_buf ) - efree( utf16_buf ); - - efree( sortKeyIndxBuf ); - efree( sortKeyBuf ); - - RETURN_FALSE; - } - } - else - { - /* Set empty string */ - utf16_len = 0; - utf16_buf[utf16_len] = 0; - } - - if( (utf16_len + 1) > utf16_buf_size ) - utf16_buf_size = utf16_len + 1; - - /* Get sort key, reallocating the buffer if needed. */ - bufLeft = sortKeyBufSize - sortKeyBufOffset; - - sortKeyLen = ucol_getSortKey( co->ucoll, - utf16_buf, - utf16_len, - (uint8_t*)sortKeyBuf + sortKeyBufOffset, - bufLeft ); - - /* check for sortKeyBuf overflow, increasing its size of the buffer if needed */ - if( sortKeyLen > bufLeft ) - { - bufIncrement = ( sortKeyLen > DEF_SORT_KEYS_BUF_INCREMENT ) ? sortKeyLen : DEF_SORT_KEYS_BUF_INCREMENT; - - sortKeyBufSize += bufIncrement; - bufLeft += bufIncrement; - - sortKeyBuf = erealloc( sortKeyBuf, sortKeyBufSize ); - - sortKeyLen = ucol_getSortKey( co->ucoll, utf16_buf, utf16_len, (uint8_t*)sortKeyBuf + sortKeyBufOffset, bufLeft ); - } - - /* check sortKeyIndxBuf overflow, increasing its size of the buffer if needed */ - if( ( sortKeyCount + 1 ) * sortKeyIndxSize > sortKeyIndxBufSize ) - { - bufIncrement = ( sortKeyIndxSize > DEF_SORT_KEYS_INDX_BUF_INCREMENT ) ? sortKeyIndxSize : DEF_SORT_KEYS_INDX_BUF_INCREMENT; - - sortKeyIndxBufSize += bufIncrement; - - sortKeyIndxBuf = erealloc( sortKeyIndxBuf, sortKeyIndxBufSize ); - } - - sortKeyIndxBuf[sortKeyCount].key = (char*)sortKeyBufOffset; /* remember just offset, cause address */ - /* of 'sortKeyBuf' may be changed due to realloc. */ - sortKeyIndxBuf[sortKeyCount].zstr = hashData; - - sortKeyBufOffset += sortKeyLen; - ++sortKeyCount; - - } ZEND_HASH_FOREACH_END(); - - /* update ptrs to point to valid keys. */ - for( j = 0; j < sortKeyCount; j++ ) - sortKeyIndxBuf[j].key = sortKeyBuf + (ptrdiff_t)sortKeyIndxBuf[j].key; - - /* sort it */ - zend_sort( sortKeyIndxBuf, sortKeyCount, - sortKeyIndxSize, collator_cmp_sort_keys, (swap_func_t)collator_sortkey_swap); - - ZVAL_COPY_VALUE(&garbage, array); - /* for resulting hash we'll assign new hash keys rather then reordering */ - array_init_size(array, sortKeyCount); - zend_hash_real_init_packed(Z_ARRVAL_P(array)); - - for( j = 0; j < sortKeyCount; j++ ) - { - Z_TRY_ADDREF_P( sortKeyIndxBuf[j].zstr ); - zend_hash_next_index_insert( Z_ARRVAL_P(array), sortKeyIndxBuf[j].zstr); - } - - if( utf16_buf ) - efree( utf16_buf ); - - zval_ptr_dtor(&garbage); - efree( sortKeyIndxBuf ); - efree( sortKeyBuf ); - - RETURN_TRUE; -} -/* }}} */ - -/* {{{ Sort array using specified collator, maintaining index association. */ -PHP_FUNCTION( collator_asort ) -{ - collator_sort_internal( false, INTERNAL_FUNCTION_PARAM_PASSTHRU ); -} -/* }}} */ - -/* {{{ Get a sort key for a string from a Collator. */ -PHP_FUNCTION( collator_get_sort_key ) -{ - char* str = NULL; - size_t str_len = 0; - UChar* ustr = NULL; - int32_t ustr_len = 0; - int key_len = 0; - zend_string* key_str; - - COLLATOR_METHOD_INIT_VARS - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Os", - &object, Collator_ce_ptr, &str, &str_len ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - COLLATOR_METHOD_FETCH_OBJECT; - - 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 ); - zend_throw_error(NULL, "Object not initialized"); - - RETURN_THROWS(); - } - - /* - * Compare given strings (converting them to UTF-16 first). - */ - - /* First convert the strings to UTF-16. */ - intl_convert_utf8_to_utf16( - &ustr, &ustr_len, str, str_len, COLLATOR_ERROR_CODE_P( co ) ); - if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) ) - { - /* Set global error code. */ - 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 ); - efree( ustr ); - RETURN_FALSE; - } - - /* ucol_getSortKey is exception in that the key length includes the - * NUL terminator*/ - key_len = ucol_getSortKey(co->ucoll, ustr, ustr_len, NULL, 0); - if(!key_len) { - efree( ustr ); - RETURN_FALSE; - } - key_str = zend_string_alloc(key_len, 0); - 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; - RETVAL_NEW_STR(key_str); -} -/* }}} */ diff --git a/ext/intl/collator/collator_sort.cpp b/ext/intl/collator/collator_sort.cpp new file mode 100644 index 0000000000000..003d7f45a837f --- /dev/null +++ b/ext/intl/collator/collator_sort.cpp @@ -0,0 +1,566 @@ +/* + +----------------------------------------------------------------------+ + | 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: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if __cplusplus >= 201703L +#include +#include +#endif + +extern "C" { +#include "php_intl.h" +#include "intl_convert.h" +} +#include "collator.h" +#include "collator_class.h" +#include "collator_sort.h" +#include "collator_convert.h" + +/** + * Declare 'index' which will point to sort key in sort key + * buffer. + */ +typedef struct _collator_sort_key_index { + char* key; /* pointer to sort key */ + zval* zstr; /* pointer to original string(hash-item) */ +} collator_sort_key_index_t; + +ZEND_EXTERN_MODULE_GLOBALS( intl ) + +static const size_t DEF_SORT_KEYS_BUF_SIZE = 1048576; +static const size_t DEF_SORT_KEYS_BUF_INCREMENT = 1048576; + +static const size_t DEF_SORT_KEYS_INDX_BUF_SIZE = 1048576; +static const size_t DEF_SORT_KEYS_INDX_BUF_INCREMENT = 1048576; + +static const size_t DEF_UTF16_BUF_SIZE = 1024; + +/* {{{ collator_regular_compare_function */ +static int collator_regular_compare_function(zval *result, zval *op1, zval *op2) +{ + int rc = SUCCESS; + zval str1, str2; + zval num1, num2; + zval norm1, norm2; + zval *num1_p = nullptr, *num2_p = nullptr; + zval *norm1_p = nullptr, *norm2_p = nullptr; + zval *str1_p, *str2_p; + + ZVAL_NULL(&str1); + str1_p = collator_convert_object_to_string( op1, &str1 ); + ZVAL_NULL(&str2); + str2_p = collator_convert_object_to_string( op2, &str2 ); + + /* If both args are strings AND either of args is not numeric string + * then use ICU-compare. Otherwise PHP-compare. */ + if( Z_TYPE_P(str1_p) == IS_STRING && Z_TYPE_P(str2_p) == IS_STRING && + ( str1_p == ( num1_p = collator_convert_string_to_number_if_possible( str1_p, &num1 ) ) || + str2_p == ( num2_p = collator_convert_string_to_number_if_possible( str2_p, &num2 ) ) ) ) + { + /* Compare the strings using ICU. */ + ZEND_ASSERT(INTL_G(current_collator) != nullptr); + ZVAL_LONG(result, ucol_strcoll( + INTL_G(current_collator), + INTL_ZSTR_VAL(Z_STR_P(str1_p)), INTL_ZSTR_LEN(Z_STR_P(str1_p)), + INTL_ZSTR_VAL(Z_STR_P(str2_p)), INTL_ZSTR_LEN(Z_STR_P(str2_p)) )); + } + else + { + /* num1 is set if str1 and str2 are strings. */ + if( num1_p ) + { + if( num1_p == str1_p ) + { + /* str1 is string but not numeric string + * just convert it to utf8. + */ + norm1_p = collator_convert_zstr_utf16_to_utf8( str1_p, &norm1 ); + + /* num2 is not set but str2 is string => do normalization. */ + norm2_p = collator_normalize_sort_argument( str2_p, &norm2 ); + } + else + { + /* str1 is numeric strings => passthru to PHP-compare. */ + Z_TRY_ADDREF_P(num1_p); + norm1_p = num1_p; + + /* str2 is numeric strings => passthru to PHP-compare. */ + Z_TRY_ADDREF_P(num2_p); + norm2_p = num2_p; + } + } + else + { + /* num1 is not set if str1 or str2 is not a string => do normalization. */ + norm1_p = collator_normalize_sort_argument( str1_p, &norm1 ); + + /* if num1 is not set then num2 is not set as well => do normalization. */ + norm2_p = collator_normalize_sort_argument( str2_p, &norm2 ); + } + + rc = compare_function( result, norm1_p, norm2_p ); + + zval_ptr_dtor( norm1_p ); + zval_ptr_dtor( norm2_p ); + } + + if( num1_p ) + zval_ptr_dtor( num1_p ); + + if( num2_p ) + zval_ptr_dtor( num2_p ); + + zval_ptr_dtor( str1_p ); + zval_ptr_dtor( str2_p ); + + return rc; +} +/* }}} */ + +/* {{{ collator_numeric_compare_function + * Convert input args to double and compare it. + */ +static int collator_numeric_compare_function(zval *result, zval *op1, zval *op2) +{ + zval num1, num2; + zval *num1_p = nullptr; + zval *num2_p = nullptr; + + if( Z_TYPE_P(op1) == IS_STRING ) + { + num1_p = collator_convert_string_to_double( op1, &num1 ); + op1 = num1_p; + } + + if( Z_TYPE_P(op2) == IS_STRING ) + { + num2_p = collator_convert_string_to_double( op2, &num2 ); + op2 = num2_p; + } + + ZVAL_LONG(result, numeric_compare_function(op1, op2)); + + if( num1_p ) + zval_ptr_dtor( num1_p ); + if( num2_p ) + zval_ptr_dtor( num2_p ); + + return SUCCESS; +} +/* }}} */ + +/* {{{ collator_icu_compare_function + * Direct use of ucol_strcoll. +*/ +static int collator_icu_compare_function(zval *result, zval *op1, zval *op2) +{ + int rc = SUCCESS; + zend_string *str1 = collator_zval_to_string(op1); + zend_string *str2 = collator_zval_to_string(op2); + + /* Compare the strings using ICU. */ + ZEND_ASSERT(INTL_G(current_collator) != nullptr); + ZVAL_LONG(result, ucol_strcoll( + INTL_G(current_collator), + INTL_ZSTR_VAL(str1), INTL_ZSTR_LEN(str1), + INTL_ZSTR_VAL(str2), INTL_ZSTR_LEN(str2) )); + + zend_string_release(str1); + zend_string_release(str2); + + return rc; +} +/* }}} */ + +/* {{{ collator_compare_func + * Taken from PHP7 source (array_data_compare). + */ +static int collator_compare_func(Bucket *f, Bucket *s) +{ + zval result; + zval *first = &f->val; + zval *second = &s->val; + + if( INTL_G(compare_func)( &result, first, second) == FAILURE ) + return 0; + + if( Z_TYPE(result) == IS_DOUBLE ) + { + if( Z_DVAL(result) < 0 ) + return -1; + else if( Z_DVAL(result) > 0 ) + return 1; + else + return 0; + } + + convert_to_long(&result); + + if( Z_LVAL(result) < 0 ) + return -1; + else if( Z_LVAL(result) > 0 ) + return 1; + + return 0; +} +/* }}} */ + +/* {{{ Compare sort keys */ +static int collator_cmp_sort_keys( const void *p1, const void *p2 ) +{ + char* key1 = ((collator_sort_key_index_t*)p1)->key; + char* key2 = ((collator_sort_key_index_t*)p2)->key; + + return strcmp( key1, key2 ); +} +/* }}} */ + +/* {{{ Choose compare function according to sort flags. */ +static collator_compare_func_t collator_get_compare_function( const zend_long sort_flags ) +{ + collator_compare_func_t func; + + switch( sort_flags ) + { + case COLLATOR_SORT_NUMERIC: + func = collator_numeric_compare_function; + break; + + case COLLATOR_SORT_STRING: + func = collator_icu_compare_function; + break; + + case COLLATOR_SORT_REGULAR: + default: + func = collator_regular_compare_function; + break; + } + + return func; +} +/* }}} */ + +/* {{{ Common code shared by collator_sort() and collator_asort() API functions. */ +static void collator_sort_internal( int renumber, INTERNAL_FUNCTION_PARAMETERS ) +{ + UCollator* saved_collator; + zval* array = nullptr; + HashTable* hash = nullptr; + zend_long sort_flags = COLLATOR_SORT_REGULAR; + + COLLATOR_METHOD_INIT_VARS + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Oa/|l", + &object, Collator_ce_ptr, &array, &sort_flags ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + COLLATOR_METHOD_FETCH_OBJECT; + + if (!co->ucoll) { + zend_throw_error(NULL, "Object not initialized"); + RETURN_THROWS(); + } + + /* Set 'compare function' according to sort flags. */ + INTL_G(compare_func) = collator_get_compare_function( sort_flags ); + + hash = Z_ARRVAL_P( array ); + + /* Convert strings in the specified array from UTF-8 to UTF-16. */ + collator_convert_hash_from_utf8_to_utf16( hash, COLLATOR_ERROR_CODE_P( co ) ); + COLLATOR_CHECK_STATUS( co, "Error converting hash from UTF-8 to UTF-16" ); + + /* Save specified collator in the request-global (?) variable. */ + saved_collator = INTL_G( current_collator ); + INTL_G( current_collator ) = co->ucoll; + + /* Sort specified array. */ + zend_hash_sort(hash, collator_compare_func, renumber); + + /* Restore saved collator. */ + INTL_G( current_collator ) = saved_collator; + + /* Convert strings in the specified array back to UTF-8. */ + collator_convert_hash_from_utf16_to_utf8( hash, COLLATOR_ERROR_CODE_P( co ) ); + COLLATOR_CHECK_STATUS( co, "Error converting hash from UTF-16 to UTF-8" ); + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ Sort array using specified collator. */ +U_CFUNC PHP_FUNCTION( collator_sort ) +{ + collator_sort_internal( true, INTERNAL_FUNCTION_PARAM_PASSTHRU ); +} +/* }}} */ + +static void collator_sortkey_swap(collator_sort_key_index_t *p, collator_sort_key_index_t *q) /* {{{ */ +{ + collator_sort_key_index_t t; + t = *p; + *p = *q; + *q = t; +} +/* }}} */ + +/* {{{ Equivalent to standard PHP sort using Collator. + * Uses ICU ucol_getSortKey for performance. + */ +U_CFUNC PHP_FUNCTION( collator_sort_with_sort_keys ) +{ + zval* array = nullptr; + zval garbage; + HashTable* hash = nullptr; + zval* hashData = nullptr; /* currently processed item of input hash */ + + char* sortKeyBuf = nullptr; /* buffer to store sort keys */ + uint32_t sortKeyBufSize = DEF_SORT_KEYS_BUF_SIZE; /* buffer size */ + ptrdiff_t sortKeyBufOffset = 0; /* pos in buffer to store sort key */ + uint32_t sortKeyLen = 0; /* the length of currently processing key */ + uint32_t bufLeft = 0; + uint32_t bufIncrement = 0; + + collator_sort_key_index_t* sortKeyIndxBuf = nullptr; /* buffer to store 'indexes' which will be passed to 'qsort' */ + uint32_t sortKeyIndxBufSize = DEF_SORT_KEYS_INDX_BUF_SIZE; + uint32_t sortKeyIndxSize = sizeof( collator_sort_key_index_t ); + + uint32_t sortKeyCount = 0; + uint32_t j = 0; + + UChar* utf16_buf = nullptr; /* tmp buffer to hold current processing string in utf-16 */ + int utf16_buf_size = DEF_UTF16_BUF_SIZE; /* the length of utf16_buf */ + int utf16_len = 0; /* length of converted string */ + + COLLATOR_METHOD_INIT_VARS + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Oa", + &object, Collator_ce_ptr, &array ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + COLLATOR_METHOD_FETCH_OBJECT; + + if (!co || !co->ucoll) { + intl_error_set_code( nullptr, COLLATOR_ERROR_CODE( co ) ); + intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), "Object not initialized"); + zend_throw_error(NULL, "Object not initialized"); + + RETURN_THROWS(); + } + + /* + * Sort specified array. + */ + hash = Z_ARRVAL_P( array ); + + if( !hash || zend_hash_num_elements( hash ) == 0 ) + RETURN_TRUE; + + /* Create bufers */ + sortKeyBuf = reinterpret_cast(ecalloc( sortKeyBufSize, sizeof( char ) )); + sortKeyIndxBuf = reinterpret_cast(ecalloc( sortKeyIndxBufSize, sizeof( uint8_t ) )); + utf16_buf = eumalloc( utf16_buf_size ); + + /* Iterate through input hash and create a sort key for each value. */ + ZEND_HASH_FOREACH_VAL(hash, hashData) { + /* Convert current hash item from UTF-8 to UTF-16LE and save the result to utf16_buf. */ + + utf16_len = utf16_buf_size; + + /* Process string values only. */ + if( Z_TYPE_P( hashData ) == IS_STRING ) + { + intl_convert_utf8_to_utf16( &utf16_buf, &utf16_len, Z_STRVAL_P( hashData ), Z_STRLEN_P( hashData ), COLLATOR_ERROR_CODE_P( co ) ); + + if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) ) + { + intl_error_set_code( nullptr, COLLATOR_ERROR_CODE( co ) ); + intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), "Sort with sort keys failed"); + + if( utf16_buf ) + efree( utf16_buf ); + + efree( sortKeyIndxBuf ); + efree( sortKeyBuf ); + + RETURN_FALSE; + } + } + else + { + /* Set empty string */ + utf16_len = 0; + utf16_buf[utf16_len] = 0; + } + + if( (utf16_len + 1) > utf16_buf_size ) + utf16_buf_size = utf16_len + 1; + + /* Get sort key, reallocating the buffer if needed. */ + bufLeft = sortKeyBufSize - sortKeyBufOffset; + + sortKeyLen = ucol_getSortKey( co->ucoll, + utf16_buf, + utf16_len, + (uint8_t*)sortKeyBuf + sortKeyBufOffset, + bufLeft ); + + /* check for sortKeyBuf overflow, increasing its size of the buffer if needed */ + if( sortKeyLen > bufLeft ) + { + bufIncrement = ( sortKeyLen > DEF_SORT_KEYS_BUF_INCREMENT ) ? sortKeyLen : DEF_SORT_KEYS_BUF_INCREMENT; + + sortKeyBufSize += bufIncrement; + bufLeft += bufIncrement; + + sortKeyBuf = reinterpret_cast(erealloc( sortKeyBuf, sortKeyBufSize )); + + sortKeyLen = ucol_getSortKey( co->ucoll, utf16_buf, utf16_len, (uint8_t*)sortKeyBuf + sortKeyBufOffset, bufLeft ); + } + + /* check sortKeyIndxBuf overflow, increasing its size of the buffer if needed */ + if( ( sortKeyCount + 1 ) * sortKeyIndxSize > sortKeyIndxBufSize ) + { + bufIncrement = ( sortKeyIndxSize > DEF_SORT_KEYS_INDX_BUF_INCREMENT ) ? sortKeyIndxSize : DEF_SORT_KEYS_INDX_BUF_INCREMENT; + + sortKeyIndxBufSize += bufIncrement; + + sortKeyIndxBuf = reinterpret_cast(erealloc( sortKeyIndxBuf, sortKeyIndxBufSize )); + } + + sortKeyIndxBuf[sortKeyCount].key = (char*)sortKeyBufOffset; /* remember just offset, cause address */ + /* of 'sortKeyBuf' may be changed due to realloc. */ + sortKeyIndxBuf[sortKeyCount].zstr = hashData; + + sortKeyBufOffset += sortKeyLen; + ++sortKeyCount; + + } ZEND_HASH_FOREACH_END(); + + /* update ptrs to point to valid keys. */ + for( j = 0; j < sortKeyCount; j++ ) + sortKeyIndxBuf[j].key = sortKeyBuf + (ptrdiff_t)sortKeyIndxBuf[j].key; + + /* sort it */ + zend_sort( sortKeyIndxBuf, sortKeyCount, + sortKeyIndxSize, collator_cmp_sort_keys, (swap_func_t)collator_sortkey_swap); + + ZVAL_COPY_VALUE(&garbage, array); + /* for resulting hash we'll assign new hash keys rather then reordering */ + array_init_size(array, sortKeyCount); + zend_hash_real_init_packed(Z_ARRVAL_P(array)); + + for( j = 0; j < sortKeyCount; j++ ) + { + Z_TRY_ADDREF_P( sortKeyIndxBuf[j].zstr ); + zend_hash_next_index_insert( Z_ARRVAL_P(array), sortKeyIndxBuf[j].zstr); + } + + if( utf16_buf ) + efree( utf16_buf ); + + zval_ptr_dtor(&garbage); + efree( sortKeyIndxBuf ); + efree( sortKeyBuf ); + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ Sort array using specified collator, maintaining index association. */ +U_CFUNC PHP_FUNCTION( collator_asort ) +{ + collator_sort_internal( false, INTERNAL_FUNCTION_PARAM_PASSTHRU ); +} +/* }}} */ + +/* {{{ Get a sort key for a string from a Collator. */ +U_CFUNC PHP_FUNCTION( collator_get_sort_key ) +{ + char* str = nullptr; + size_t str_len = 0; + UChar* ustr = nullptr; + int32_t ustr_len = 0; + int key_len = 0; + zend_string* key_str; + + COLLATOR_METHOD_INIT_VARS + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Os", + &object, Collator_ce_ptr, &str, &str_len ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + COLLATOR_METHOD_FETCH_OBJECT; + + if (!co || !co->ucoll) { + intl_error_set_code( nullptr, COLLATOR_ERROR_CODE( co ) ); + intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), "Object not initialized"); + zend_throw_error(NULL, "Object not initialized"); + + RETURN_THROWS(); + } + + /* + * Compare given strings (converting them to UTF-16 first). + */ + + /* First convert the strings to UTF-16. */ + intl_convert_utf8_to_utf16( + &ustr, &ustr_len, str, str_len, COLLATOR_ERROR_CODE_P( co ) ); + if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) ) + { + /* Set global error code. */ + intl_error_set_code( nullptr, COLLATOR_ERROR_CODE( co ) ); + + /* Set error messages. */ + intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), "Error converting first argument to UTF-16"); + efree( ustr ); + RETURN_FALSE; + } + + /* ucol_getSortKey is exception in that the key length includes the + * NUL terminator*/ + key_len = ucol_getSortKey(co->ucoll, ustr, ustr_len, nullptr, 0); + if(!key_len) { + efree( ustr ); + RETURN_FALSE; + } + key_str = zend_string_alloc(key_len, 0); + 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; + RETVAL_NEW_STR(key_str); +} +/* }}} */ 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..988f279294c3c 100644 --- a/ext/intl/common/common_date.h +++ b/ext/intl/common/common_date.h @@ -24,15 +24,18 @@ U_CDECL_END #ifdef __cplusplus +// TODO once C++ migration done we can drop this workaround +#undef U_SHOW_CPLUSPLUS_API +#define U_SHOW_CPLUSPLUS_API 1 #include 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/common/common_error.c b/ext/intl/common/common_error.c deleted file mode 100644 index 733a1913ad08f..0000000000000 --- a/ext/intl/common/common_error.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Vadim Savchuk | - | Dmitry Lakhtyuk | - +----------------------------------------------------------------------+ - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "php_intl.h" -#include "intl_error.h" - -/* {{{ Get code of the last occurred error. */ -PHP_FUNCTION( intl_get_error_code ) -{ - ZEND_PARSE_PARAMETERS_NONE(); - - RETURN_LONG( intl_error_get_code( NULL ) ); -} -/* }}} */ - -/* {{{ Get text description of the last occurred error. */ -PHP_FUNCTION( intl_get_error_message ) -{ - ZEND_PARSE_PARAMETERS_NONE(); - - RETURN_STR(intl_error_get_message( NULL )); -} -/* }}} */ - -/* {{{ Check whether the given error code indicates a failure. - * Returns true if it does, and false if the code - * indicates success or a warning. - */ -PHP_FUNCTION( intl_is_failure ) -{ - zend_long err_code; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_LONG(err_code) - ZEND_PARSE_PARAMETERS_END(); - - RETURN_BOOL( U_FAILURE( err_code ) ); -} -/* }}} */ - -/* {{{ Return a string for a given error code. - * The string will be the same as the name of the error code constant. - */ -PHP_FUNCTION( intl_error_name ) -{ - zend_long err_code; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_LONG(err_code) - ZEND_PARSE_PARAMETERS_END(); - - RETURN_STRING( (char*)u_errorName( err_code ) ); -} -/* }}} */ diff --git a/ext/intl/common/common_error.cpp b/ext/intl/common/common_error.cpp new file mode 100644 index 0000000000000..cb12d8dff8f3d --- /dev/null +++ b/ext/intl/common/common_error.cpp @@ -0,0 +1,72 @@ +/* + +----------------------------------------------------------------------+ + | 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: Vadim Savchuk | + | Dmitry Lakhtyuk | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +extern "C" { +#include "php_intl.h" +#include "intl_error.h" +} + +/* {{{ Get code of the last occurred error. */ +U_CFUNC PHP_FUNCTION( intl_get_error_code ) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + RETURN_LONG( intl_error_get_code( NULL ) ); +} +/* }}} */ + +/* {{{ Get text description of the last occurred error. */ +U_CFUNC PHP_FUNCTION( intl_get_error_message ) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + RETURN_STR(intl_error_get_message( NULL )); +} +/* }}} */ + +/* {{{ Check whether the given error code indicates a failure. + * Returns true if it does, and false if the code + * indicates success or a warning. + */ +U_CFUNC PHP_FUNCTION( intl_is_failure ) +{ + zend_long err_code; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_LONG(err_code) + ZEND_PARSE_PARAMETERS_END(); + + RETURN_BOOL( U_FAILURE( static_cast(err_code) ) ); +} +/* }}} */ + +/* {{{ Return a string for a given error code. + * The string will be the same as the name of the error code constant. + */ +U_CFUNC PHP_FUNCTION( intl_error_name ) +{ + zend_long err_code; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_LONG(err_code) + ZEND_PARSE_PARAMETERS_END(); + + RETURN_STRING( (char*)u_errorName( static_cast(err_code) ) ); +} +/* }}} */ diff --git a/ext/intl/config.m4 b/ext/intl/config.m4 index 20adc3a4ce3a7..7251f22835349 100644 --- a/ext/intl/config.m4 +++ b/ext/intl/config.m4 @@ -8,82 +8,83 @@ if test "$PHP_INTL" != "no"; then PHP_SUBST([INTL_SHARED_LIBADD]) INTL_COMMON_FLAGS="$ICU_CFLAGS -Wno-write-strings -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1" PHP_NEW_EXTENSION([intl], m4_normalize([ - collator/collator_attr.c - collator/collator_class.c - collator/collator_compare.c - collator/collator_convert.c - collator/collator_create.c - collator/collator_error.c - collator/collator_is_numeric.c - collator/collator_locale.c - collator/collator_sort.c - common/common_error.c - converter/converter.c - dateformat/dateformat_attr.c - dateformat/dateformat_class.c - dateformat/dateformat_data.c - dateformat/dateformat_format.c - dateformat/dateformat_parse.c - dateformat/dateformat.c - formatter/formatter_attr.c - formatter/formatter_class.c - formatter/formatter_data.c - formatter/formatter_format.c - formatter/formatter_main.c - 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 - resourcebundle/resourcebundle.c - spoofchecker/spoofchecker_class.c - spoofchecker/spoofchecker_create.c - spoofchecker/spoofchecker_main.c - transliterator/transliterator_class.c - transliterator/transliterator_methods.c - uchar/uchar.c ]), [$ext_shared],, [$INTL_COMMON_FLAGS], [cxx]) PHP_INTL_CXX_SOURCES="intl_convertcpp.cpp \ + collator/collator_attr.cpp \ + collator/collator_class.cpp \ + collator/collator_compare.cpp \ + collator/collator_convert.cpp \ + collator/collator_create.cpp \ + collator/collator_error.cpp \ + collator/collator_is_numeric.cpp \ + collator/collator_locale.cpp \ + collator/collator_sort.cpp \ common/common_enum.cpp \ common/common_date.cpp \ - dateformat/dateformat_format_object.cpp \ - dateformat/dateformat_create.cpp \ + common/common_error.cpp \ + dateformat/dateformat_class.cpp \ + converter/converter.cpp \ + dateformat/dateformat.cpp \ + dateformat/dateformat_attr.cpp \ dateformat/dateformat_attrcpp.cpp \ + dateformat/dateformat_create.cpp \ + dateformat/dateformat_data.cpp \ + dateformat/dateformat_format.cpp \ + dateformat/dateformat_format_object.cpp \ dateformat/dateformat_helpers.cpp \ + dateformat/dateformat_parse.cpp \ dateformat/datepatterngenerator_class.cpp \ dateformat/datepatterngenerator_methods.cpp \ + formatter/formatter_class.cpp \ + grapheme/grapheme_string.cpp \ + grapheme/grapheme_util.cpp \ msgformat/msgformat_helpers.cpp \ + rangeformatter/rangeformatter_class.cpp \ timezone/timezone_class.cpp \ timezone/timezone_methods.cpp \ calendar/calendar_class.cpp \ calendar/calendar_methods.cpp \ calendar/gregoriancalendar_methods.cpp \ + formatter/formatter_attr.cpp \ + formatter/formatter_data.cpp \ + formatter/formatter_format.cpp \ + formatter/formatter_main.cpp \ + formatter/formatter_parse.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 \ + listformatter/listformatter_class.cpp \ + transliterator/transliterator_class.cpp \ + transliterator/transliterator_methods.cpp \ + idn/idn.cpp \ + locale/locale_class.cpp \ + locale/locale_methods.cpp \ + locale/locale.cpp \ + resourcebundle/resourcebundle_class.cpp \ + resourcebundle/resourcebundle_iterator.cpp \ + resourcebundle/resourcebundle.cpp \ + spoofchecker/spoofchecker_class.cpp \ + spoofchecker/spoofchecker_create.cpp \ + spoofchecker/spoofchecker_main.cpp \ + uchar/uchar.cpp" PHP_REQUIRE_CXX() @@ -123,6 +124,7 @@ if test "$PHP_INTL" != "no"; then $ext_builddir/listformatter $ext_builddir/msgformat $ext_builddir/normalizer + $ext_builddir/rangeformatter $ext_builddir/resourcebundle $ext_builddir/spoofchecker $ext_builddir/timezone diff --git a/ext/intl/config.w32 b/ext/intl/config.w32 index b8161865d2540..d5c86d1236712 100644 --- a/ext/intl/config.w32 +++ b/ext/intl/config.w32 @@ -13,64 +13,67 @@ if (PHP_INTL != "no") { "/I \"" + configure_module_dirname + "\" /DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); ADD_EXTENSION_DEP('intl', 'date'); ADD_SOURCES(configure_module_dirname + "/collator", "\ - collator_attr.c \ - collator_class.c \ - collator_compare.c \ - collator_convert.c \ - collator_create.c \ - collator_error.c \ - collator_is_numeric.c \ - collator_locale.c \ - collator_sort.c \ + collator_attr.cpp \ + collator_class.cpp \ + collator_compare.cpp \ + collator_convert.cpp \ + collator_create.cpp \ + collator_error.cpp \ + collator_is_numeric.cpp \ + collator_locale.cpp \ + collator_sort.cpp \ ", "intl"); ADD_SOURCES(configure_module_dirname + "/common", "\ - common_error.c \ + common_error.cpp \ common_enum.cpp \ common_date.cpp \ ", "intl"); ADD_SOURCES(configure_module_dirname + "/converter", "\ - converter.c \ + converter.cpp \ ", "intl"); ADD_SOURCES(configure_module_dirname + "/formatter", "\ - formatter_attr.c \ - formatter_class.c \ - formatter_data.c \ - formatter_format.c \ - formatter_main.c \ - formatter_parse.c \ + formatter_attr.cpp \ + formatter_class.cpp \ + formatter_data.cpp \ + formatter_format.cpp \ + formatter_main.cpp \ + formatter_parse.cpp \ ", "intl"); ADD_SOURCES(configure_module_dirname + "/listformatter", "\ - listformatter_class.c \ + listformatter_class.cpp \ ", "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 \ + grapheme_string.cpp grapheme_util.cpp \ ", "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 + "/rangeformatter", "\ + rangeformatter_class.cpp \ ", "intl"); ADD_SOURCES(configure_module_dirname + "/dateformat", "\ - dateformat.c \ - dateformat_class.c \ - dateformat_attr.c \ - dateformat_format.c \ + dateformat.cpp \ + dateformat_class.cpp \ + dateformat_attr.cpp \ + dateformat_format.cpp \ dateformat_format_object.cpp \ - dateformat_parse.c \ - dateformat_data.c \ + dateformat_parse.cpp \ + dateformat_data.cpp \ dateformat_attrcpp.cpp \ dateformat_helpers.cpp \ dateformat_create.cpp \ @@ -78,28 +81,28 @@ 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 \ - resourcebundle_class.c \ - resourcebundle_iterator.c", + resourcebundle.cpp \ + resourcebundle_class.cpp \ + resourcebundle_iterator.cpp", "intl"); if (CHECK_HEADER_ADD_INCLUDE("unicode/uspoof.h", "CFLAGS_INTL")) { ADD_SOURCES(configure_module_dirname + "/spoofchecker", "\ - spoofchecker_class.c \ - spoofchecker_create.c \ - spoofchecker_main.c", + spoofchecker_class.cpp \ + spoofchecker_create.cpp \ + spoofchecker_main.cpp", "intl"); } ADD_SOURCES(configure_module_dirname + "/transliterator", "\ - transliterator_class.c \ - transliterator_methods.c", + transliterator_class.cpp \ + transliterator_methods.cpp", "intl"); ADD_SOURCES(configure_module_dirname + "/timezone", "\ diff --git a/ext/intl/converter/converter.c b/ext/intl/converter/converter.c deleted file mode 100644 index 3aa7a53aa485b..0000000000000 --- a/ext/intl/converter/converter.c +++ /dev/null @@ -1,965 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Sara Golemon | - +----------------------------------------------------------------------+ - */ - -#include "converter.h" -#include "zend_exceptions.h" - -#include -#include -#include -#include -#include - -#include "../intl_error.h" -#include "../intl_common.h" -#include "converter_arginfo.h" - -typedef struct _php_converter_object { - UConverter *src, *dest; - zend_fcall_info_cache to_cache, from_cache; - intl_error error; - zend_object obj; -} php_converter_object; - - -static inline php_converter_object *php_converter_fetch_object(zend_object *obj) { - return (php_converter_object *)((char*)(obj) - XtOffsetOf(php_converter_object, obj)); -} -#define Z_INTL_CONVERTER_P(zv) php_converter_fetch_object(Z_OBJ_P(zv)) - -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)) - -/* {{{ php_converter_throw_failure */ -static inline void php_converter_throw_failure(php_converter_object *objval, UErrorCode error, const char *format, ...) { - intl_error *err = objval ? &(objval->error) : NULL; - char message[1024]; - va_list vargs; - - va_start(vargs, format); - vsnprintf(message, sizeof(message), format, vargs); - va_end(vargs); - - intl_errors_set(err, error, message, 1); -} -/* }}} */ - -/* {{{ php_converter_default_callback */ -static void php_converter_default_callback(zval *return_value, zval *zobj, zend_long reason, zval *error) { - /* Basic functionality so children can call parent::toUCallback() */ - switch (reason) { - case UCNV_UNASSIGNED: - case UCNV_ILLEGAL: - case UCNV_IRREGULAR: - { - php_converter_object *objval = (php_converter_object*)CONV_GET(zobj); - char chars[127]; - int8_t chars_len = sizeof(chars); - UErrorCode uerror = U_ZERO_ERROR; - if(!objval->src) { - php_converter_throw_failure(objval, U_INVALID_STATE_ERROR, "Source Converter has not been initialized yet"); - chars[0] = 0x1A; - chars[1] = 0; - chars_len = 1; - ZEND_TRY_ASSIGN_REF_LONG(error, U_INVALID_STATE_ERROR); - RETVAL_STRINGL(chars, chars_len); - return; - } - - /* Yes, this is fairly wasteful at first glance, - * but considering that the alternative is to store - * what's sent into setSubstChars() and the fact - * that this is an extremely unlikely codepath - * I'd rather take the CPU hit here, than waste time - * storing a value I'm unlikely to use. - */ - ucnv_getSubstChars(objval->src, chars, &chars_len, &uerror); - if (U_FAILURE(uerror)) { - THROW_UFAILURE(objval, "ucnv_getSubstChars", uerror); - chars[0] = 0x1A; - chars[1] = 0; - chars_len = 1; - } - ZEND_TRY_ASSIGN_REF_LONG(error, uerror); - RETVAL_STRINGL(chars, chars_len); - } - } -} -/* }}} */ - -/* {{{ */ -PHP_METHOD(UConverter, toUCallback) { - zend_long reason; - zend_string *source, *codeUnits; - zval *error; - - ZEND_PARSE_PARAMETERS_START(4, 4) - Z_PARAM_LONG(reason) - Z_PARAM_STR(source) - Z_PARAM_STR(codeUnits) - Z_PARAM_ZVAL(error) - ZEND_PARSE_PARAMETERS_END(); - - php_converter_default_callback(return_value, ZEND_THIS, reason, error); -} -/* }}} */ - -/* {{{ */ -PHP_METHOD(UConverter, fromUCallback) { - zend_long reason; - zval *source, *error; - zend_long codePoint; - - ZEND_PARSE_PARAMETERS_START(4, 4) - Z_PARAM_LONG(reason) - Z_PARAM_ARRAY(source) - Z_PARAM_LONG(codePoint) - Z_PARAM_ZVAL(error) - ZEND_PARSE_PARAMETERS_END(); - - php_converter_default_callback(return_value, ZEND_THIS, reason, error); -} -/* }}} */ - -/* {{{ php_converter_check_limits */ -static inline bool php_converter_check_limits(php_converter_object *objval, zend_long available, zend_long needed) { - if (available < needed) { - php_converter_throw_failure(objval, U_BUFFER_OVERFLOW_ERROR, "Buffer overrun " ZEND_LONG_FMT " bytes needed, " ZEND_LONG_FMT " available", needed, available); - return 0; - } - return 1; -} -/* }}} */ - -#define TARGET_CHECK(cnvargs, needed) php_converter_check_limits(objval, cnvargs->targetLimit - cnvargs->target, needed) - -/* {{{ php_converter_append_toUnicode_target */ -static void php_converter_append_toUnicode_target(zval *val, UConverterToUnicodeArgs *args, php_converter_object *objval) { - switch (Z_TYPE_P(val)) { - case IS_NULL: - /* Code unit is being skipped */ - return; - case IS_LONG: - { - zend_long lval = Z_LVAL_P(val); - if ((lval < 0) || (lval > 0x10FFFF)) { - php_converter_throw_failure(objval, U_ILLEGAL_ARGUMENT_ERROR, "Invalid codepoint U+%04lx", lval); - return; - } - if (lval > 0xFFFF) { - /* Supplemental planes U+010000 - U+10FFFF */ - if (TARGET_CHECK(args, 2)) { - /* TODO: Find the ICU call which does this properly */ - *(args->target++) = (UChar)(((lval - 0x10000) >> 10) | 0xD800); - *(args->target++) = (UChar)(((lval - 0x10000) & 0x3FF) | 0xDC00); - } - return; - } - /* Non-suggogate BMP codepoint */ - if (TARGET_CHECK(args, 1)) { - *(args->target++) = (UChar)lval; - } - return; - } - case IS_STRING: - { - const char *strval = Z_STRVAL_P(val); - int i = 0, strlen = Z_STRLEN_P(val); - - while((i != strlen) && TARGET_CHECK(args, 1)) { - UChar c; - U8_NEXT(strval, i, strlen, c); - *(args->target++) = c; - } - return; - } - case IS_ARRAY: - { - HashTable *ht = Z_ARRVAL_P(val); - zval *tmpzval; - - ZEND_HASH_FOREACH_VAL(ht, tmpzval) { - php_converter_append_toUnicode_target(tmpzval, args, objval); - } ZEND_HASH_FOREACH_END(); - return; - } - default: - php_converter_throw_failure(objval, U_ILLEGAL_ARGUMENT_ERROR, - "toUCallback() specified illegal type for substitution character"); - } -} -/* }}} */ - -/* {{{ php_converter_to_u_callback */ -static void php_converter_to_u_callback(const void *context, - UConverterToUnicodeArgs *args, - const char *codeUnits, int32_t length, - UConverterCallbackReason reason, - UErrorCode *pErrorCode) { - php_converter_object *objval = (php_converter_object*)context; - zval retval; - zval zargs[4]; - - ZVAL_LONG(&zargs[0], reason); - if (args->source) { - ZVAL_STRINGL(&zargs[1], args->source, args->sourceLimit - args->source); - } else { - ZVAL_EMPTY_STRING(&zargs[1]); - } - if (codeUnits) { - ZVAL_STRINGL(&zargs[2], codeUnits, length); - } else { - ZVAL_EMPTY_STRING(&zargs[2]); - } - ZVAL_LONG(&zargs[3], *pErrorCode); - ZVAL_MAKE_REF(&zargs[3]); - - zend_call_known_fcc(&objval->to_cache, &retval, 4, zargs, NULL); - /* When no exception is thrown */ - if (EXPECTED(!Z_ISUNDEF(retval))) { - php_converter_append_toUnicode_target(&retval, args, objval); - zval_ptr_dtor(&retval); - } - - if (Z_TYPE(zargs[3]) == IS_LONG) { - *pErrorCode = Z_LVAL(zargs[3]); - } else if (Z_ISREF(zargs[3]) && Z_TYPE_P(Z_REFVAL(zargs[3])) == IS_LONG) { - *pErrorCode = Z_LVAL_P(Z_REFVAL(zargs[3])); - } - - zval_ptr_dtor(&zargs[0]); - zval_ptr_dtor(&zargs[1]); - zval_ptr_dtor(&zargs[2]); - zval_ptr_dtor(&zargs[3]); -} -/* }}} */ - -/* {{{ php_converter_append_fromUnicode_target */ -static void php_converter_append_fromUnicode_target(zval *val, UConverterFromUnicodeArgs *args, php_converter_object *objval) { - switch (Z_TYPE_P(val)) { - case IS_NULL: - /* Ignore */ - return; - case IS_LONG: - if (TARGET_CHECK(args, 1)) { - *(args->target++) = Z_LVAL_P(val); - } - return; - case IS_STRING: - { - size_t vallen = Z_STRLEN_P(val); - if (TARGET_CHECK(args, vallen)) { - args->target = zend_mempcpy(args->target, Z_STRVAL_P(val), vallen); - } - return; - } - case IS_ARRAY: - { - HashTable *ht = Z_ARRVAL_P(val); - zval *tmpzval; - ZEND_HASH_FOREACH_VAL(ht, tmpzval) { - php_converter_append_fromUnicode_target(tmpzval, args, objval); - } ZEND_HASH_FOREACH_END(); - return; - } - default: - php_converter_throw_failure(objval, U_ILLEGAL_ARGUMENT_ERROR, "fromUCallback() specified illegal type for substitution character"); - } -} -/* }}} */ - -/* {{{ php_converter_from_u_callback */ -static void php_converter_from_u_callback(const void *context, - UConverterFromUnicodeArgs *args, - const UChar *codeUnits, int32_t length, UChar32 codePoint, - UConverterCallbackReason reason, - UErrorCode *pErrorCode) { - php_converter_object *objval = (php_converter_object*)context; - zval retval; - zval zargs[4]; - - ZVAL_LONG(&zargs[0], reason); - array_init_size(&zargs[1], length); - zend_hash_real_init_packed(Z_ARRVAL(zargs[1])); - int i = 0; - while (i < length) { - UChar32 c; - U16_NEXT(codeUnits, i, length, c); - add_next_index_long(&zargs[1], c); - } - ZVAL_LONG(&zargs[2], codePoint); - ZVAL_LONG(&zargs[3], *pErrorCode); - ZVAL_MAKE_REF(&zargs[3]); - - zend_call_known_fcc(&objval->from_cache, &retval, 4, zargs, NULL); - /* When no exception is thrown */ - if (EXPECTED(!Z_ISUNDEF(retval))) { - php_converter_append_fromUnicode_target(&retval, args, objval); - zval_ptr_dtor(&retval); - } - - if (Z_TYPE(zargs[3]) == IS_LONG) { - *pErrorCode = Z_LVAL(zargs[3]); - } else if (Z_ISREF(zargs[3]) && Z_TYPE_P(Z_REFVAL(zargs[3])) == IS_LONG) { - *pErrorCode = Z_LVAL_P(Z_REFVAL(zargs[3])); - } - - zval_ptr_dtor(&zargs[0]); - zval_ptr_dtor(&zargs[1]); - zval_ptr_dtor(&zargs[2]); - zval_ptr_dtor(&zargs[3]); -} -/* }}} */ - -/* {{{ php_converter_set_callbacks */ -static inline bool php_converter_set_callbacks(php_converter_object *objval, UConverter *cnv) { - bool ret = true; - UErrorCode error = U_ZERO_ERROR; - - if (objval->obj.ce == php_converter_ce) { - /* Short-circuit having to go through method calls and data marshalling - * when we're using default behavior - */ - return 1; - } - - 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); - ret = 0; - } - - error = U_ZERO_ERROR; - 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); - ret = 0; - } - return ret; -} -/* }}} */ - -/* {{{ php_converter_set_encoding */ -static bool php_converter_set_encoding(php_converter_object *objval, - UConverter **pcnv, - const char *enc, size_t enc_len) { - UErrorCode error = U_ZERO_ERROR; - UConverter *cnv = ucnv_open(enc, &error); - - if (error == U_AMBIGUOUS_ALIAS_WARNING) { - UErrorCode getname_error = U_ZERO_ERROR; - const char *actual_encoding = ucnv_getName(cnv, &getname_error); - if (U_FAILURE(getname_error)) { - /* Should never happen */ - actual_encoding = "(unknown)"; - } - php_error_docref(NULL, E_WARNING, "Ambiguous encoding specified, using %s", actual_encoding); - } else if (U_FAILURE(error)) { - if (objval) { - THROW_UFAILURE(objval, "ucnv_open", error); - } else { - char *msg; - spprintf(&msg, 0, "Error setting encoding: %d - %s", (int)error, u_errorName(error)); - intl_error_set(NULL, error, msg, 1); - efree(msg); - } - return false; - } - - if (objval && !php_converter_set_callbacks(objval, cnv)) { - return false; - } - - if (*pcnv) { - ucnv_close(*pcnv); - } - *pcnv = cnv; - return true; -} -/* }}} */ - -/* {{{ php_converter_do_set_encoding */ -static void php_converter_do_set_encoding(UConverter **pcnv, INTERNAL_FUNCTION_PARAMETERS) { - php_converter_object *objval = CONV_GET(ZEND_THIS); - char *enc; - size_t enc_len; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(enc, enc_len) - ZEND_PARSE_PARAMETERS_END(); - - intl_errors_reset(&objval->error); - - RETURN_BOOL(php_converter_set_encoding(objval, pcnv, enc, enc_len)); -} -/* }}} */ - -/* {{{ */ -PHP_METHOD(UConverter, setSourceEncoding) { - php_converter_object *objval = CONV_GET(ZEND_THIS); - php_converter_do_set_encoding(&(objval->src), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ */ -PHP_METHOD(UConverter, setDestinationEncoding) { - php_converter_object *objval = CONV_GET(ZEND_THIS); - php_converter_do_set_encoding(&(objval->dest), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ php_converter_do_get_encoding */ -static void php_converter_do_get_encoding(php_converter_object *objval, UConverter *cnv, INTERNAL_FUNCTION_PARAMETERS) { - const char *name; - - ZEND_PARSE_PARAMETERS_NONE(); - - intl_errors_reset(&objval->error); - - if (!cnv) { - RETURN_NULL(); - } - - name = ucnv_getName(cnv, &objval->error.code); - if (U_FAILURE(objval->error.code)) { - THROW_UFAILURE(objval, "ucnv_getName()", objval->error.code); - RETURN_FALSE; - } - - RETURN_STRING(name); -} -/* }}} */ - -/* {{{ */ -PHP_METHOD(UConverter, getSourceEncoding) { - php_converter_object *objval = CONV_GET(ZEND_THIS); - php_converter_do_get_encoding(objval, objval->src, INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ */ -PHP_METHOD(UConverter, getDestinationEncoding) { - php_converter_object *objval = CONV_GET(ZEND_THIS); - php_converter_do_get_encoding(objval, objval->dest, INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ php_converter_do_get_type */ -static void php_converter_do_get_type(php_converter_object *objval, UConverter *cnv, INTERNAL_FUNCTION_PARAMETERS) { - UConverterType t; - - ZEND_PARSE_PARAMETERS_NONE(); - intl_errors_reset(&objval->error); - - if (!cnv) { - RETURN_NULL(); - } - - t = ucnv_getType(cnv); - if (U_FAILURE(objval->error.code)) { - THROW_UFAILURE(objval, "ucnv_getType", objval->error.code); - RETURN_FALSE; - } - - RETURN_LONG(t); -} -/* }}} */ - -/* {{{ */ -PHP_METHOD(UConverter, getSourceType) { - php_converter_object *objval = CONV_GET(ZEND_THIS); - php_converter_do_get_type(objval, objval->src, INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ */ -PHP_METHOD(UConverter, getDestinationType) { - php_converter_object *objval = CONV_GET(ZEND_THIS); - php_converter_do_get_type(objval, objval->dest, INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ php_converter_resolve_callback */ -static void php_converter_resolve_callback( - zend_fcall_info_cache *fcc, - zend_object *obj, - const char *callback_name, - size_t callback_name_len -) { - zend_function *fn = zend_hash_str_find_ptr_lc(&obj->ce->function_table, callback_name, callback_name_len); - ZEND_ASSERT(fn != NULL); - - fcc->function_handler = fn; - fcc->object = obj; - fcc->called_scope = obj->ce; - fcc->calling_scope = NULL; - fcc->closure = NULL; -} -/* }}} */ - -/* {{{ */ -PHP_METHOD(UConverter, __construct) { - php_converter_object *objval = CONV_GET(ZEND_THIS); - char *src = "utf-8"; - size_t src_len = sizeof("utf-8") - 1; - char *dest = src; - size_t dest_len = src_len; - - intl_error_reset(NULL); - - ZEND_PARSE_PARAMETERS_START(0, 2) - Z_PARAM_OPTIONAL - Z_PARAM_STRING_OR_NULL(dest, dest_len) - 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); - 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")); -} -/* }}} */ - -/* {{{ */ -PHP_METHOD(UConverter, setSubstChars) { - php_converter_object *objval = CONV_GET(ZEND_THIS); - char *chars; - size_t chars_len; - int ret = 1; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(chars, chars_len) - ZEND_PARSE_PARAMETERS_END(); - - intl_errors_reset(&objval->error); - - if (objval->src) { - UErrorCode error = U_ZERO_ERROR; - ucnv_setSubstChars(objval->src, chars, chars_len, &error); - if (U_FAILURE(error)) { - THROW_UFAILURE(objval, "ucnv_setSubstChars", error); - ret = 0; - } - } else { - php_converter_throw_failure(objval, U_INVALID_STATE_ERROR, "Source Converter has not been initialized yet"); - ret = 0; - } - - if (objval->dest) { - UErrorCode error = U_ZERO_ERROR; - ucnv_setSubstChars(objval->dest, chars, chars_len, &error); - if (U_FAILURE(error)) { - THROW_UFAILURE(objval, "ucnv_setSubstChars", error); - ret = 0; - } - } else { - php_converter_throw_failure(objval, U_INVALID_STATE_ERROR, "Destination Converter has not been initialized yet"); - ret = 0; - } - - RETURN_BOOL(ret); -} -/* }}} */ - -/* {{{ */ -PHP_METHOD(UConverter, getSubstChars) { - php_converter_object *objval = CONV_GET(ZEND_THIS); - char chars[127]; - int8_t chars_len = sizeof(chars); - UErrorCode error = U_ZERO_ERROR; - - ZEND_PARSE_PARAMETERS_NONE(); - intl_errors_reset(&objval->error); - - if (!objval->src) { - RETURN_NULL(); - } - - /* src and dest get the same subst chars set, - * so it doesn't really matter which one we read from - */ - ucnv_getSubstChars(objval->src, chars, &chars_len, &error); - if (U_FAILURE(error)) { - THROW_UFAILURE(objval, "ucnv_getSubstChars", error); - RETURN_FALSE; - } - - RETURN_STRINGL(chars, chars_len); -} -/* }}} */ - -/* {{{ php_converter_do_convert */ -static zend_string* php_converter_do_convert(UConverter *dest_cnv, - UConverter *src_cnv, const char *src, int32_t src_len, - php_converter_object *objval - ) { - UErrorCode error = U_ZERO_ERROR; - int32_t temp_len, ret_len; - zend_string *ret; - UChar *temp; - - if (!src_cnv || !dest_cnv) { - php_converter_throw_failure(objval, U_INVALID_STATE_ERROR, - "Internal converters not initialized"); - return NULL; - } - - /* 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); - return NULL; - } - temp = safe_emalloc(sizeof(UChar), temp_len, sizeof(UChar)); - - /* Convert to intermediate UChar* array */ - 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); - efree(temp); - return NULL; - } - temp[temp_len] = 0; - - /* 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); - efree(temp); - return NULL; - } - - ret = zend_string_alloc(ret_len, 0); - - /* Convert to final encoding */ - error = U_ZERO_ERROR; - 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); - zend_string_efree(ret); - return NULL; - } - - return ret; -} -/* }}} */ - -/* {{{ */ -#define UCNV_REASON_CASE(v) case (UCNV_ ## v) : RETURN_STRINGL( "REASON_" #v , sizeof( "REASON_" #v ) - 1); -PHP_METHOD(UConverter, reasonText) { - zend_long reason; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_LONG(reason) - ZEND_PARSE_PARAMETERS_END(); - intl_error_reset(NULL); - - switch (reason) { - UCNV_REASON_CASE(UNASSIGNED) - UCNV_REASON_CASE(ILLEGAL) - UCNV_REASON_CASE(IRREGULAR) - UCNV_REASON_CASE(RESET) - UCNV_REASON_CASE(CLOSE) - UCNV_REASON_CASE(CLONE) - default: - zend_argument_value_error(1, "must be a UConverter::REASON_* constant"); - RETURN_THROWS(); - } -} -/* }}} */ - -/* {{{ */ -PHP_METHOD(UConverter, convert) { - php_converter_object *objval = CONV_GET(ZEND_THIS); - char *str; - size_t str_len; - zend_string *ret; - bool reverse = false; - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_STRING(str, str_len) - Z_PARAM_OPTIONAL - Z_PARAM_BOOL(reverse) - ZEND_PARSE_PARAMETERS_END(); - intl_errors_reset(&objval->error); - - ret = php_converter_do_convert(reverse ? objval->src : objval->dest, - reverse ? objval->dest : objval->src, - str, str_len, - objval); - if (ret) { - RETURN_NEW_STR(ret); - } else { - RETURN_FALSE; - } -} -/* }}} */ - -/* {{{ */ -PHP_METHOD(UConverter, transcode) { - char *str, *src, *dest; - size_t str_len, src_len, dest_len; - zval *options = NULL; - UConverter *src_cnv = NULL, *dest_cnv = NULL; - - ZEND_PARSE_PARAMETERS_START(3, 4) - Z_PARAM_STRING(str, str_len) - Z_PARAM_STRING(dest, dest_len) - Z_PARAM_STRING(src, src_len) - Z_PARAM_OPTIONAL - Z_PARAM_ARRAY_OR_NULL(options) - ZEND_PARSE_PARAMETERS_END(); - intl_error_reset(NULL); - - if (php_converter_set_encoding(NULL, &src_cnv, src, src_len) && - php_converter_set_encoding(NULL, &dest_cnv, dest, dest_len)) { - zend_string *ret; - UErrorCode error = U_ZERO_ERROR; - - if (options && zend_hash_num_elements(Z_ARRVAL_P(options))) { - zval *tmpzval; - - if (U_SUCCESS(error) && - (tmpzval = zend_hash_str_find_deref(Z_ARRVAL_P(options), "from_subst", sizeof("from_subst") - 1)) != NULL && - Z_TYPE_P(tmpzval) == IS_STRING) { - error = U_ZERO_ERROR; - ucnv_setSubstChars(src_cnv, Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval) & 0x7F, &error); - } - if (U_SUCCESS(error) && - (tmpzval = zend_hash_str_find_deref(Z_ARRVAL_P(options), "to_subst", sizeof("to_subst") - 1)) != NULL && - Z_TYPE_P(tmpzval) == IS_STRING) { - error = U_ZERO_ERROR; - ucnv_setSubstChars(dest_cnv, Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval) & 0x7F, &error); - } - } - - if (U_SUCCESS(error) && - (ret = php_converter_do_convert(dest_cnv, src_cnv, str, str_len, NULL)) != NULL) { - RETVAL_NEW_STR(ret); - } - - if (U_FAILURE(error)) { - THROW_UFAILURE(NULL, "transcode", error); - RETVAL_FALSE; - } - } else { - RETVAL_FALSE; - } - - if (src_cnv) { - ucnv_close(src_cnv); - } - if (dest_cnv) { - ucnv_close(dest_cnv); - } -} -/* }}} */ - -/* {{{ */ -PHP_METHOD(UConverter, getErrorCode) { - php_converter_object *objval = CONV_GET(ZEND_THIS); - - ZEND_PARSE_PARAMETERS_NONE(); - - RETURN_LONG(intl_error_get_code(&(objval->error))); -} -/* }}} */ - -/* {{{ */ -PHP_METHOD(UConverter, getErrorMessage) { - php_converter_object *objval = CONV_GET(ZEND_THIS); - - ZEND_PARSE_PARAMETERS_NONE(); - - zend_string *message = intl_error_get_message(&(objval->error)); - if (message) { - RETURN_STR(message); - } else { - RETURN_NULL(); - } -} -/* }}} */ - -/* {{{ */ -PHP_METHOD(UConverter, getAvailable) { - int32_t i, - count = ucnv_countAvailable(); - - ZEND_PARSE_PARAMETERS_NONE(); - - intl_error_reset(NULL); - - array_init_size(return_value, count); - zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); - for(i = 0; i < count; i++) { - const char *name = ucnv_getAvailableName(i); - add_next_index_string(return_value, name); - } -} -/* }}} */ - -/* {{{ */ -PHP_METHOD(UConverter, getAliases) { - char *name; - size_t name_len; - UErrorCode error = U_ZERO_ERROR; - uint16_t i, count; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(name, name_len) - ZEND_PARSE_PARAMETERS_END(); - intl_error_reset(NULL); - - count = ucnv_countAliases(name, &error); - if (U_FAILURE(error)) { - THROW_UFAILURE(NULL, "ucnv_countAliases", error); - RETURN_FALSE; - } - - array_init_size(return_value, count); - zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); - for(i = 0; i < count; i++) { - const char *alias; - - error = U_ZERO_ERROR; - alias = ucnv_getAlias(name, i, &error); - if (U_FAILURE(error)) { - THROW_UFAILURE(NULL, "ucnv_getAlias", error); - zend_array_destroy(Z_ARR_P(return_value)); - RETURN_NULL(); - } - add_next_index_string(return_value, alias); - } -} -/* }}} */ - -/* {{{ */ -PHP_METHOD(UConverter, getStandards) { - uint16_t i, count; - - ZEND_PARSE_PARAMETERS_NONE(); - intl_error_reset(NULL); - - count = ucnv_countStandards(); - array_init_size(return_value, count); - zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); - for(i = 0; i < count; i++) { - UErrorCode error = U_ZERO_ERROR; - const char *name = ucnv_getStandard(i, &error); - if (U_FAILURE(error)) { - THROW_UFAILURE(NULL, "ucnv_getStandard", error); - zend_array_destroy(Z_ARR_P(return_value)); - RETURN_NULL(); - } - add_next_index_string(return_value, name); - } -} -/* }}} */ - -/* {{{ Converter create/clone/destroy */ -static void php_converter_free_object(zend_object *obj) { - php_converter_object *objval = php_converter_fetch_object(obj); - - if (objval->src) { - ucnv_close(objval->src); - } - - if (objval->dest) { - ucnv_close(objval->dest); - } - - intl_error_reset(&objval->error); - zend_object_std_dtor(obj); -} - -static zend_object *php_converter_object_ctor(zend_class_entry *ce, php_converter_object **pobjval) { - php_converter_object *objval; - - objval = zend_object_alloc(sizeof(php_converter_object), ce); - - zend_object_std_init(&objval->obj, ce); - object_properties_init(&objval->obj, ce); - intl_error_init(&(objval->error)); - - *pobjval = objval; - - return &objval->obj; -} - -static zend_object *php_converter_create_object(zend_class_entry *ce) { - php_converter_object *objval = NULL; - zend_object *retval = php_converter_object_ctor(ce, &objval); - - object_properties_init(&(objval->obj), ce); - - return retval; -} - -static zend_object *php_converter_clone_object(zend_object *object) { - php_converter_object *objval, *oldobj = php_converter_fetch_object(object); - zend_object *retval = php_converter_object_ctor(object->ce, &objval); - UErrorCode error = U_ZERO_ERROR; - -#if U_ICU_VERSION_MAJOR_NUM > 70 - objval->src = ucnv_clone(oldobj->src, &error); -#else - objval->src = ucnv_safeClone(oldobj->src, NULL, NULL, &error); -#endif - if (U_SUCCESS(error)) { - error = U_ZERO_ERROR; -#if U_ICU_VERSION_MAJOR_NUM > 70 - objval->dest = ucnv_clone(oldobj->dest, &error); -#else - objval->dest = ucnv_safeClone(oldobj->dest, NULL, NULL, &error); -#endif - } - - if (U_FAILURE(error)) { - zend_throw_error(NULL, "Failed to clone UConverter"); - return retval; - } - - /* Update contexts for converter error handlers */ - php_converter_set_callbacks(objval, objval->src ); - php_converter_set_callbacks(objval, objval->dest); - - zend_objects_clone_members(&(objval->obj), &(oldobj->obj)); - - /* Newly cloned object deliberately does not inherit error state from original object */ - - return retval; -} -/* }}} */ - -/* {{{ php_converter_minit */ -int php_converter_minit(INIT_FUNC_ARGS) { - php_converter_ce = register_class_UConverter(); - php_converter_ce->create_object = php_converter_create_object; - php_converter_ce->default_object_handlers = &php_converter_object_handlers; - memcpy(&php_converter_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - php_converter_object_handlers.offset = XtOffsetOf(php_converter_object, obj); - php_converter_object_handlers.clone_obj = php_converter_clone_object; - php_converter_object_handlers.free_obj = php_converter_free_object; - - return SUCCESS; -} -/* }}} */ diff --git a/ext/intl/converter/converter.cpp b/ext/intl/converter/converter.cpp new file mode 100644 index 0000000000000..ad68909b5ea3c --- /dev/null +++ b/ext/intl/converter/converter.cpp @@ -0,0 +1,984 @@ +/* + +----------------------------------------------------------------------+ + | 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: Sara Golemon | + +----------------------------------------------------------------------+ + */ + +#include "zend_exceptions.h" + +#include +#include +#include +#include +#include + +extern "C" { +#include "converter.h" +#include "php_intl.h" +#include "../intl_error.h" +#include "../intl_common.h" +} +#include "converter_arginfo.h" + +typedef struct _php_converter_object { + UConverter *src, *dest; + zend_fcall_info_cache to_cache, from_cache; + intl_error error; + zend_object obj; +} php_converter_object; + + +static inline php_converter_object *php_converter_fetch_object(zend_object *obj) { + return (php_converter_object *)((char*)(obj) - XtOffsetOf(php_converter_object, obj)); +} +#define Z_INTL_CONVERTER_P(zv) php_converter_fetch_object(Z_OBJ_P(zv)) + +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, 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, ...) { + intl_error *err = objval ? &(objval->error) : NULL; + char message[1024]; + va_list vargs; + + va_start(vargs, format); + vsnprintf(message, sizeof(message), format, vargs); + va_end(vargs); + + intl_errors_set(err, error, message); +} +/* }}} */ + +/* {{{ php_converter_default_callback */ +static void php_converter_default_callback(zval *return_value, zval *zobj, zend_long reason, zval *error) { + /* Basic functionality so children can call parent::toUCallback() */ + switch (reason) { + case UCNV_UNASSIGNED: + case UCNV_ILLEGAL: + case UCNV_IRREGULAR: + { + php_converter_object *objval = (php_converter_object*)CONV_GET(zobj); + char chars[127]; + int8_t chars_len = sizeof(chars); + UErrorCode uerror = U_ZERO_ERROR; + if(!objval->src) { + php_converter_throw_failure(objval, U_INVALID_STATE_ERROR, "Source Converter has not been initialized yet"); + chars[0] = 0x1A; + chars[1] = 0; + chars_len = 1; + ZEND_TRY_ASSIGN_REF_LONG(error, U_INVALID_STATE_ERROR); + RETVAL_STRINGL(chars, chars_len); + return; + } + + /* Yes, this is fairly wasteful at first glance, + * but considering that the alternative is to store + * what's sent into setSubstChars() and the fact + * that this is an extremely unlikely codepath + * I'd rather take the CPU hit here, than waste time + * storing a value I'm unlikely to use. + */ + ucnv_getSubstChars(objval->src, chars, &chars_len, &uerror); + if (U_FAILURE(uerror)) { + THROW_UFAILURE(objval, uerror); + chars[0] = 0x1A; + chars[1] = 0; + chars_len = 1; + } + ZEND_TRY_ASSIGN_REF_LONG(error, uerror); + RETVAL_STRINGL(chars, chars_len); + } + } +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(UConverter, toUCallback) { + zend_long reason; + zend_string *source, *codeUnits; + zval *error; + + ZEND_PARSE_PARAMETERS_START(4, 4) + Z_PARAM_LONG(reason) + Z_PARAM_STR(source) + Z_PARAM_STR(codeUnits) + Z_PARAM_ZVAL(error) + ZEND_PARSE_PARAMETERS_END(); + + php_converter_default_callback(return_value, ZEND_THIS, reason, error); +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(UConverter, fromUCallback) { + zend_long reason; + zval *source, *error; + zend_long codePoint; + + ZEND_PARSE_PARAMETERS_START(4, 4) + Z_PARAM_LONG(reason) + Z_PARAM_ARRAY(source) + Z_PARAM_LONG(codePoint) + Z_PARAM_ZVAL(error) + ZEND_PARSE_PARAMETERS_END(); + + php_converter_default_callback(return_value, ZEND_THIS, reason, error); +} +/* }}} */ + +/* {{{ php_converter_check_limits */ +static inline bool php_converter_check_limits(php_converter_object *objval, zend_long available, zend_long needed) { + if (available < needed) { + php_converter_throw_failure(objval, U_BUFFER_OVERFLOW_ERROR, "Buffer overrun " ZEND_LONG_FMT " bytes needed, " ZEND_LONG_FMT " available", needed, available); + return false; + } + return true; +} +/* }}} */ + +#define TARGET_CHECK(cnvargs, needed) php_converter_check_limits(objval, cnvargs->targetLimit - cnvargs->target, needed) + +/* {{{ php_converter_append_toUnicode_target */ +static void php_converter_append_toUnicode_target(zval *val, UConverterToUnicodeArgs *args, php_converter_object *objval) { + switch (Z_TYPE_P(val)) { + case IS_NULL: + /* Code unit is being skipped */ + return; + case IS_LONG: + { + zend_long lval = Z_LVAL_P(val); + if ((lval < 0) || (lval > 0x10FFFF)) { + php_converter_throw_failure(objval, U_ILLEGAL_ARGUMENT_ERROR, "Invalid codepoint U+%04lx", lval); + return; + } + if (lval > 0xFFFF) { + /* Supplemental planes U+010000 - U+10FFFF */ + if (TARGET_CHECK(args, 2)) { + /* TODO: Find the ICU call which does this properly */ + *(args->target++) = (UChar)(((lval - 0x10000) >> 10) | 0xD800); + *(args->target++) = (UChar)(((lval - 0x10000) & 0x3FF) | 0xDC00); + } + return; + } + /* Non-suggogate BMP codepoint */ + if (TARGET_CHECK(args, 1)) { + *(args->target++) = (UChar)lval; + } + return; + } + case IS_STRING: + { + const char *strval = Z_STRVAL_P(val); + int i = 0, strlen = Z_STRLEN_P(val); + + while((i != strlen) && TARGET_CHECK(args, 1)) { + UChar c; + U8_NEXT(strval, i, strlen, c); + *(args->target++) = c; + } + return; + } + case IS_ARRAY: + { + HashTable *ht = Z_ARRVAL_P(val); + zval *tmpzval; + + ZEND_HASH_FOREACH_VAL(ht, tmpzval) { + php_converter_append_toUnicode_target(tmpzval, args, objval); + } ZEND_HASH_FOREACH_END(); + return; + } + default: + php_converter_throw_failure(objval, U_ILLEGAL_ARGUMENT_ERROR, + "toUCallback() specified illegal type for substitution character"); + } +} +/* }}} */ + +/* {{{ php_converter_to_u_callback */ +static void php_converter_to_u_callback(const void *context, + UConverterToUnicodeArgs *args, + const char *codeUnits, int32_t length, + UConverterCallbackReason reason, + UErrorCode *pErrorCode) { + php_converter_object *objval = (php_converter_object*)context; + zval retval; + zval zargs[4]; + + ZVAL_LONG(&zargs[0], reason); + if (args->source) { + ZVAL_STRINGL(&zargs[1], args->source, args->sourceLimit - args->source); + } else { + ZVAL_EMPTY_STRING(&zargs[1]); + } + if (codeUnits) { + ZVAL_STRINGL(&zargs[2], codeUnits, length); + } else { + ZVAL_EMPTY_STRING(&zargs[2]); + } + ZVAL_LONG(&zargs[3], *pErrorCode); + ZVAL_MAKE_REF(&zargs[3]); + + zend_call_known_fcc(&objval->to_cache, &retval, 4, zargs, NULL); + /* When no exception is thrown */ + if (EXPECTED(!Z_ISUNDEF(retval))) { + php_converter_append_toUnicode_target(&retval, args, objval); + zval_ptr_dtor(&retval); + } + + if (Z_TYPE(zargs[3]) == IS_LONG) { + *pErrorCode = static_cast(Z_LVAL(zargs[3])); + } else if (Z_ISREF(zargs[3]) && Z_TYPE_P(Z_REFVAL(zargs[3])) == IS_LONG) { + *pErrorCode = static_cast(Z_LVAL_P(Z_REFVAL(zargs[3]))); + } + + zval_ptr_dtor(&zargs[0]); + zval_ptr_dtor(&zargs[1]); + zval_ptr_dtor(&zargs[2]); + zval_ptr_dtor(&zargs[3]); +} +/* }}} */ + +/* {{{ php_converter_append_fromUnicode_target */ +static void php_converter_append_fromUnicode_target(zval *val, UConverterFromUnicodeArgs *args, php_converter_object *objval) { + switch (Z_TYPE_P(val)) { + case IS_NULL: + /* Ignore */ + return; + case IS_LONG: + if (TARGET_CHECK(args, 1)) { + *(args->target++) = Z_LVAL_P(val); + } + return; + case IS_STRING: + { + size_t vallen = Z_STRLEN_P(val); + if (TARGET_CHECK(args, vallen)) { + args->target = reinterpret_cast(zend_mempcpy(args->target, Z_STRVAL_P(val), vallen)); + } + return; + } + case IS_ARRAY: + { + HashTable *ht = Z_ARRVAL_P(val); + zval *tmpzval; + ZEND_HASH_FOREACH_VAL(ht, tmpzval) { + php_converter_append_fromUnicode_target(tmpzval, args, objval); + } ZEND_HASH_FOREACH_END(); + return; + } + default: + php_converter_throw_failure(objval, U_ILLEGAL_ARGUMENT_ERROR, "fromUCallback() specified illegal type for substitution character"); + } +} +/* }}} */ + +/* {{{ php_converter_from_u_callback */ +static void php_converter_from_u_callback(const void *context, + UConverterFromUnicodeArgs *args, + const UChar *codeUnits, int32_t length, UChar32 codePoint, + UConverterCallbackReason reason, + UErrorCode *pErrorCode) { + php_converter_object *objval = (php_converter_object*)context; + zval retval; + zval zargs[4]; + + ZVAL_LONG(&zargs[0], reason); + array_init_size(&zargs[1], length); + zend_hash_real_init_packed(Z_ARRVAL(zargs[1])); + int i = 0; + while (i < length) { + UChar32 c; + U16_NEXT(codeUnits, i, length, c); + add_next_index_long(&zargs[1], c); + } + ZVAL_LONG(&zargs[2], codePoint); + ZVAL_LONG(&zargs[3], *pErrorCode); + ZVAL_MAKE_REF(&zargs[3]); + + zend_call_known_fcc(&objval->from_cache, &retval, 4, zargs, NULL); + /* When no exception is thrown */ + if (EXPECTED(!Z_ISUNDEF(retval))) { + php_converter_append_fromUnicode_target(&retval, args, objval); + zval_ptr_dtor(&retval); + } + + if (Z_TYPE(zargs[3]) == IS_LONG) { + *pErrorCode = static_cast(Z_LVAL(zargs[3])); + } else if (Z_ISREF(zargs[3]) && Z_TYPE_P(Z_REFVAL(zargs[3])) == IS_LONG) { + *pErrorCode = static_cast(Z_LVAL_P(Z_REFVAL(zargs[3]))); + } + + zval_ptr_dtor(&zargs[0]); + zval_ptr_dtor(&zargs[1]); + zval_ptr_dtor(&zargs[2]); + zval_ptr_dtor(&zargs[3]); +} +/* }}} */ + +/* {{{ php_converter_set_callbacks */ +static inline bool php_converter_set_callbacks(php_converter_object *objval, UConverter *cnv) { + bool ret = true; + UErrorCode error = U_ZERO_ERROR; + + if (objval->obj.ce == php_converter_ce) { + /* Short-circuit having to go through method calls and data marshalling + * when we're using default behavior + */ + return true; + } + + ucnv_setToUCallBack(cnv, (UConverterToUCallback)php_converter_to_u_callback, (const void*)objval, + nullptr, nullptr, &error); + if (U_FAILURE(error)) { + THROW_UFAILURE(objval, error); + ret = false; + } + + error = U_ZERO_ERROR; + ucnv_setFromUCallBack(cnv, (UConverterFromUCallback)php_converter_from_u_callback, (const void*)objval, + nullptr, nullptr, &error); + if (U_FAILURE(error)) { + THROW_UFAILURE(objval, error); + ret = false; + } + return ret; +} +/* }}} */ + +/* {{{ php_converter_set_encoding */ +static bool php_converter_set_encoding(php_converter_object *objval, + UConverter **pcnv, + const char *enc, size_t enc_len) { + UErrorCode error = U_ZERO_ERROR; + UConverter *cnv = ucnv_open(enc, &error); + + if (error == U_AMBIGUOUS_ALIAS_WARNING) { + UErrorCode getname_error = U_ZERO_ERROR; + const char *actual_encoding = ucnv_getName(cnv, &getname_error); + if (U_FAILURE(getname_error)) { + /* Should never happen */ + actual_encoding = "(unknown)"; + } + 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, error); + } else { + char *msg; + spprintf(&msg, 0, "Error setting encoding: %d - %s", (int)error, u_errorName(error)); + intl_error_set(NULL, error, msg); + efree(msg); + } + return false; + } + + if (objval && !php_converter_set_callbacks(objval, cnv)) { + return false; + } + + if (*pcnv) { + ucnv_close(*pcnv); + } + *pcnv = cnv; + return true; +} +/* }}} */ + +/* {{{ php_converter_do_set_encoding */ +static void php_converter_do_set_encoding(UConverter **pcnv, INTERNAL_FUNCTION_PARAMETERS) { + php_converter_object *objval = CONV_GET(ZEND_THIS); + char *enc; + size_t enc_len; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STRING(enc, enc_len) + ZEND_PARSE_PARAMETERS_END(); + + intl_errors_reset(&objval->error); + + RETURN_BOOL(php_converter_set_encoding(objval, pcnv, enc, enc_len)); +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(UConverter, setSourceEncoding) { + php_converter_object *objval = CONV_GET(ZEND_THIS); + php_converter_do_set_encoding(&(objval->src), INTERNAL_FUNCTION_PARAM_PASSTHRU); +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(UConverter, setDestinationEncoding) { + php_converter_object *objval = CONV_GET(ZEND_THIS); + php_converter_do_set_encoding(&(objval->dest), INTERNAL_FUNCTION_PARAM_PASSTHRU); +} +/* }}} */ + +/* {{{ php_converter_do_get_encoding */ +static void php_converter_do_get_encoding(php_converter_object *objval, UConverter *cnv, INTERNAL_FUNCTION_PARAMETERS) { + const char *name; + + ZEND_PARSE_PARAMETERS_NONE(); + + intl_errors_reset(&objval->error); + + if (!cnv) { + RETURN_NULL(); + } + + name = ucnv_getName(cnv, &objval->error.code); + if (U_FAILURE(objval->error.code)) { + THROW_UFAILURE(objval, objval->error.code); + RETURN_FALSE; + } + + RETURN_STRING(name); +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(UConverter, getSourceEncoding) { + php_converter_object *objval = CONV_GET(ZEND_THIS); + php_converter_do_get_encoding(objval, objval->src, INTERNAL_FUNCTION_PARAM_PASSTHRU); +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(UConverter, getDestinationEncoding) { + php_converter_object *objval = CONV_GET(ZEND_THIS); + php_converter_do_get_encoding(objval, objval->dest, INTERNAL_FUNCTION_PARAM_PASSTHRU); +} +/* }}} */ + +/* {{{ php_converter_do_get_type */ +static void php_converter_do_get_type(php_converter_object *objval, UConverter *cnv, INTERNAL_FUNCTION_PARAMETERS) { + UConverterType t; + + ZEND_PARSE_PARAMETERS_NONE(); + intl_errors_reset(&objval->error); + + if (!cnv) { + RETURN_NULL(); + } + + t = ucnv_getType(cnv); + if (U_FAILURE(objval->error.code)) { + THROW_UFAILURE(objval, objval->error.code); + RETURN_FALSE; + } + + RETURN_LONG(t); +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(UConverter, getSourceType) { + php_converter_object *objval = CONV_GET(ZEND_THIS); + php_converter_do_get_type(objval, objval->src, INTERNAL_FUNCTION_PARAM_PASSTHRU); +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(UConverter, getDestinationType) { + php_converter_object *objval = CONV_GET(ZEND_THIS); + php_converter_do_get_type(objval, objval->dest, INTERNAL_FUNCTION_PARAM_PASSTHRU); +} +/* }}} */ + +/* {{{ php_converter_resolve_callback */ +static void php_converter_resolve_callback( + zend_fcall_info_cache *fcc, + zend_object *obj, + const char *callback_name, + size_t callback_name_len +) { + zend_function *fn = reinterpret_cast(zend_hash_str_find_ptr_lc(&obj->ce->function_table, callback_name, callback_name_len)); + ZEND_ASSERT(fn != nullptr); + + fcc->function_handler = fn; + fcc->object = obj; + fcc->called_scope = obj->ce; + fcc->calling_scope = nullptr; + fcc->closure = nullptr; +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(UConverter, __construct) { + php_converter_object *objval = CONV_GET(ZEND_THIS); + char *src = "utf-8"; + size_t src_len = sizeof("utf-8") - 1; + char *dest = src; + size_t dest_len = src_len; + + intl_error_reset(NULL); + + ZEND_PARSE_PARAMETERS_START(0, 2) + Z_PARAM_OPTIONAL + Z_PARAM_STRING_OR_NULL(dest, dest_len) + Z_PARAM_STRING_OR_NULL(src, src_len) + ZEND_PARSE_PARAMETERS_END(); + + 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; +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(UConverter, setSubstChars) { + php_converter_object *objval = CONV_GET(ZEND_THIS); + char *chars; + size_t chars_len; + int ret = 1; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STRING(chars, chars_len) + ZEND_PARSE_PARAMETERS_END(); + + intl_errors_reset(&objval->error); + + if (objval->src) { + UErrorCode error = U_ZERO_ERROR; + ucnv_setSubstChars(objval->src, chars, chars_len, &error); + if (U_FAILURE(error)) { + THROW_UFAILURE(objval, error); + ret = 0; + } + } else { + php_converter_throw_failure(objval, U_INVALID_STATE_ERROR, "Source Converter has not been initialized yet"); + ret = 0; + } + + if (objval->dest) { + UErrorCode error = U_ZERO_ERROR; + ucnv_setSubstChars(objval->dest, chars, chars_len, &error); + if (U_FAILURE(error)) { + THROW_UFAILURE(objval, error); + ret = 0; + } + } else { + php_converter_throw_failure(objval, U_INVALID_STATE_ERROR, "Destination Converter has not been initialized yet"); + ret = 0; + } + + RETURN_BOOL(ret); +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(UConverter, getSubstChars) { + php_converter_object *objval = CONV_GET(ZEND_THIS); + char chars[127]; + int8_t chars_len = sizeof(chars); + UErrorCode error = U_ZERO_ERROR; + + ZEND_PARSE_PARAMETERS_NONE(); + intl_errors_reset(&objval->error); + + if (!objval->src) { + RETURN_NULL(); + } + + /* src and dest get the same subst chars set, + * so it doesn't really matter which one we read from + */ + ucnv_getSubstChars(objval->src, chars, &chars_len, &error); + if (U_FAILURE(error)) { + THROW_UFAILURE(objval, error); + RETURN_FALSE; + } + + RETURN_STRINGL(chars, chars_len); +} +/* }}} */ + +/* {{{ php_converter_do_convert */ +static zend_string* php_converter_do_convert(UConverter *dest_cnv, + UConverter *src_cnv, const char *src, int32_t src_len, + php_converter_object *objval + ) { + UErrorCode error = U_ZERO_ERROR; + int32_t temp_len, ret_len; + zend_string *ret; + UChar *temp; + + if (!src_cnv || !dest_cnv) { + php_converter_throw_failure(objval, U_INVALID_STATE_ERROR, + "Internal converters not initialized"); + return nullptr; + } + + /* 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, error); + return nullptr; + } + temp = reinterpret_cast(safe_emalloc(sizeof(UChar), temp_len, sizeof(UChar))); + + /* Convert to intermediate UChar* array */ + error = U_ZERO_ERROR; + temp_len = ucnv_toUChars(src_cnv, temp, temp_len, src, src_len, &error); + if (U_FAILURE(error)) { + THROW_UFAILURE(objval, error); + efree(temp); + return nullptr; + } + temp[temp_len] = 0; + + /* 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, error); + efree(temp); + return nullptr; + } + + ret = zend_string_alloc(ret_len, 0); + + /* Convert to final encoding */ + error = U_ZERO_ERROR; + 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, error); + zend_string_efree(ret); + return nullptr; + } + + return ret; +} +/* }}} */ + +/* {{{ */ +#define UCNV_REASON_CASE(v) case (UCNV_ ## v) : RETURN_STRINGL( "REASON_" #v , sizeof( "REASON_" #v ) - 1); +PHP_METHOD(UConverter, reasonText) { + zend_long reason; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_LONG(reason) + ZEND_PARSE_PARAMETERS_END(); + intl_error_reset(NULL); + + switch (reason) { + UCNV_REASON_CASE(UNASSIGNED) + UCNV_REASON_CASE(ILLEGAL) + UCNV_REASON_CASE(IRREGULAR) + UCNV_REASON_CASE(RESET) + UCNV_REASON_CASE(CLOSE) + UCNV_REASON_CASE(CLONE) + default: + zend_argument_value_error(1, "must be a UConverter::REASON_* constant"); + RETURN_THROWS(); + } +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(UConverter, convert) { + php_converter_object *objval = CONV_GET(ZEND_THIS); + char *str; + size_t str_len; + zend_string *ret; + bool reverse = false; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STRING(str, str_len) + Z_PARAM_OPTIONAL + Z_PARAM_BOOL(reverse) + ZEND_PARSE_PARAMETERS_END(); + intl_errors_reset(&objval->error); + + ret = php_converter_do_convert(reverse ? objval->src : objval->dest, + reverse ? objval->dest : objval->src, + str, str_len, + objval); + if (ret) { + RETURN_NEW_STR(ret); + } else { + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(UConverter, transcode) { + char *str, *src, *dest; + size_t str_len, src_len, dest_len; + zval *options = nullptr; + UConverter *src_cnv = nullptr, *dest_cnv = nullptr; + + ZEND_PARSE_PARAMETERS_START(3, 4) + Z_PARAM_STRING(str, str_len) + Z_PARAM_STRING(dest, dest_len) + Z_PARAM_STRING(src, src_len) + Z_PARAM_OPTIONAL + Z_PARAM_ARRAY_OR_NULL(options) + ZEND_PARSE_PARAMETERS_END(); + intl_error_reset(NULL); + + if (php_converter_set_encoding(NULL, &src_cnv, src, src_len) && + php_converter_set_encoding(NULL, &dest_cnv, dest, dest_len)) { + zend_string *ret; + UErrorCode error = U_ZERO_ERROR; + + if (options && zend_hash_num_elements(Z_ARRVAL_P(options))) { + zval *tmpzval; + + if (U_SUCCESS(error) && + (tmpzval = zend_hash_str_find_deref(Z_ARRVAL_P(options), "from_subst", sizeof("from_subst") - 1)) != NULL && + Z_TYPE_P(tmpzval) == IS_STRING) { + error = U_ZERO_ERROR; + ucnv_setSubstChars(src_cnv, Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval) & 0x7F, &error); + } + if (U_SUCCESS(error) && + (tmpzval = zend_hash_str_find_deref(Z_ARRVAL_P(options), "to_subst", sizeof("to_subst") - 1)) != NULL && + Z_TYPE_P(tmpzval) == IS_STRING) { + error = U_ZERO_ERROR; + ucnv_setSubstChars(dest_cnv, Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval) & 0x7F, &error); + } + } + + if (U_SUCCESS(error) && + (ret = php_converter_do_convert(dest_cnv, src_cnv, str, str_len, NULL)) != NULL) { + RETVAL_NEW_STR(ret); + } + + if (U_FAILURE(error)) { + THROW_UFAILURE(NULL, error); + RETVAL_FALSE; + } + } else { + RETVAL_FALSE; + } + + if (src_cnv) { + ucnv_close(src_cnv); + } + if (dest_cnv) { + ucnv_close(dest_cnv); + } +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(UConverter, getErrorCode) { + php_converter_object *objval = CONV_GET(ZEND_THIS); + + ZEND_PARSE_PARAMETERS_NONE(); + + RETURN_LONG(intl_error_get_code(&(objval->error))); +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(UConverter, getErrorMessage) { + php_converter_object *objval = CONV_GET(ZEND_THIS); + + ZEND_PARSE_PARAMETERS_NONE(); + + zend_string *message = intl_error_get_message(&(objval->error)); + if (message) { + RETURN_STR(message); + } else { + RETURN_NULL(); + } +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(UConverter, getAvailable) { + int32_t i, + count = ucnv_countAvailable(); + + ZEND_PARSE_PARAMETERS_NONE(); + + intl_error_reset(NULL); + + array_init_size(return_value, count); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); + for(i = 0; i < count; i++) { + const char *name = ucnv_getAvailableName(i); + add_next_index_string(return_value, name); + } +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(UConverter, getAliases) { + char *name; + size_t name_len; + UErrorCode error = U_ZERO_ERROR; + uint16_t i, count; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STRING(name, name_len) + ZEND_PARSE_PARAMETERS_END(); + intl_error_reset(NULL); + + count = ucnv_countAliases(name, &error); + if (U_FAILURE(error)) { + THROW_UFAILURE(NULL, error); + RETURN_FALSE; + } + + array_init_size(return_value, count); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); + for(i = 0; i < count; i++) { + const char *alias; + + error = U_ZERO_ERROR; + alias = ucnv_getAlias(name, i, &error); + if (U_FAILURE(error)) { + THROW_UFAILURE(NULL, error); + zend_array_destroy(Z_ARR_P(return_value)); + RETURN_NULL(); + } + add_next_index_string(return_value, alias); + } +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(UConverter, getStandards) { + uint16_t i, count; + + ZEND_PARSE_PARAMETERS_NONE(); + intl_error_reset(NULL); + + count = ucnv_countStandards(); + array_init_size(return_value, count); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); + for(i = 0; i < count; i++) { + UErrorCode error = U_ZERO_ERROR; + const char *name = ucnv_getStandard(i, &error); + if (U_FAILURE(error)) { + THROW_UFAILURE(NULL, error); + zend_array_destroy(Z_ARR_P(return_value)); + RETURN_NULL(); + } + add_next_index_string(return_value, name); + } +} +/* }}} */ + +/* {{{ Converter create/clone/destroy */ +static void php_converter_free_object(zend_object *obj) { + php_converter_object *objval = php_converter_fetch_object(obj); + + if (objval->src) { + ucnv_close(objval->src); + } + + if (objval->dest) { + ucnv_close(objval->dest); + } + + intl_error_reset(&objval->error); + zend_object_std_dtor(obj); +} + +static zend_object *php_converter_object_ctor(zend_class_entry *ce, php_converter_object **pobjval) { + php_converter_object *objval; + + objval = reinterpret_cast(zend_object_alloc(sizeof(php_converter_object), ce)); + + zend_object_std_init(&objval->obj, ce); + object_properties_init(&objval->obj, ce); + intl_error_init(&(objval->error)); + + *pobjval = objval; + + return &objval->obj; +} + +static zend_object *php_converter_create_object(zend_class_entry *ce) { + php_converter_object *objval = nullptr; + zend_object *retval = php_converter_object_ctor(ce, &objval); + + object_properties_init(&(objval->obj), ce); + + return retval; +} + +static zend_object *php_converter_clone_object(zend_object *object) { + php_converter_object *objval, *oldobj = php_converter_fetch_object(object); + zend_object *retval = php_converter_object_ctor(object->ce, &objval); + UErrorCode error = U_ZERO_ERROR; + +#if U_ICU_VERSION_MAJOR_NUM > 70 + objval->src = ucnv_clone(oldobj->src, &error); +#else + objval->src = ucnv_safeClone(oldobj->src, NULL, NULL, &error); +#endif + if (U_SUCCESS(error)) { + error = U_ZERO_ERROR; +#if U_ICU_VERSION_MAJOR_NUM > 70 + objval->dest = ucnv_clone(oldobj->dest, &error); +#else + objval->dest = ucnv_safeClone(oldobj->dest, NULL, NULL, &error); +#endif + } + + if (U_FAILURE(error)) { + zend_throw_error(NULL, "Failed to clone UConverter"); + return retval; + } + + /* Update contexts for converter error handlers */ + php_converter_set_callbacks(objval, objval->src ); + php_converter_set_callbacks(objval, objval->dest); + + zend_objects_clone_members(&(objval->obj), &(oldobj->obj)); + + /* Newly cloned object deliberately does not inherit error state from original object */ + + return retval; +} +/* }}} */ + +/* {{{ php_converter_minit */ +U_CFUNC int php_converter_minit(INIT_FUNC_ARGS) { + php_converter_ce = register_class_UConverter(); + php_converter_ce->create_object = php_converter_create_object; + php_converter_ce->default_object_handlers = &php_converter_object_handlers; + memcpy(&php_converter_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); + php_converter_object_handlers.offset = XtOffsetOf(php_converter_object, obj); + php_converter_object_handlers.clone_obj = php_converter_clone_object; + php_converter_object_handlers.free_obj = php_converter_free_object; + + return SUCCESS; +} +/* }}} */ diff --git a/ext/intl/converter/converter.h b/ext/intl/converter/converter.h index f9fb27b82a7d0..5d779560811d0 100644 --- a/ext/intl/converter/converter.h +++ b/ext/intl/converter/converter.h @@ -21,6 +21,12 @@ #include "php.h" +#ifdef __cplusplus +extern "C" { +#endif int php_converter_minit(INIT_FUNC_ARGS); +#ifdef __cplusplus +} +#endif #endif /* PHP_INTL_CONVERTER_H */ diff --git a/ext/intl/converter/converter_arginfo.h b/ext/intl/converter/converter_arginfo.h index 4e02daf9478ad..9808e50b39dc8 100644 --- a/ext/intl/converter/converter_arginfo.h +++ b/ext/intl/converter/converter_arginfo.h @@ -126,249 +126,249 @@ static zend_class_entry *register_class_UConverter(void) zval const_REASON_UNASSIGNED_value; ZVAL_LONG(&const_REASON_UNASSIGNED_value, UCNV_UNASSIGNED); - zend_string *const_REASON_UNASSIGNED_name = zend_string_init_interned("REASON_UNASSIGNED", sizeof("REASON_UNASSIGNED") - 1, 1); + zend_string *const_REASON_UNASSIGNED_name = zend_string_init_interned("REASON_UNASSIGNED", sizeof("REASON_UNASSIGNED") - 1, true); zend_declare_typed_class_constant(class_entry, const_REASON_UNASSIGNED_name, &const_REASON_UNASSIGNED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_REASON_UNASSIGNED_name); + zend_string_release_ex(const_REASON_UNASSIGNED_name, true); zval const_REASON_ILLEGAL_value; ZVAL_LONG(&const_REASON_ILLEGAL_value, UCNV_ILLEGAL); - zend_string *const_REASON_ILLEGAL_name = zend_string_init_interned("REASON_ILLEGAL", sizeof("REASON_ILLEGAL") - 1, 1); + zend_string *const_REASON_ILLEGAL_name = zend_string_init_interned("REASON_ILLEGAL", sizeof("REASON_ILLEGAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_REASON_ILLEGAL_name, &const_REASON_ILLEGAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_REASON_ILLEGAL_name); + zend_string_release_ex(const_REASON_ILLEGAL_name, true); zval const_REASON_IRREGULAR_value; ZVAL_LONG(&const_REASON_IRREGULAR_value, UCNV_IRREGULAR); - zend_string *const_REASON_IRREGULAR_name = zend_string_init_interned("REASON_IRREGULAR", sizeof("REASON_IRREGULAR") - 1, 1); + zend_string *const_REASON_IRREGULAR_name = zend_string_init_interned("REASON_IRREGULAR", sizeof("REASON_IRREGULAR") - 1, true); zend_declare_typed_class_constant(class_entry, const_REASON_IRREGULAR_name, &const_REASON_IRREGULAR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_REASON_IRREGULAR_name); + zend_string_release_ex(const_REASON_IRREGULAR_name, true); zval const_REASON_RESET_value; ZVAL_LONG(&const_REASON_RESET_value, UCNV_RESET); - zend_string *const_REASON_RESET_name = zend_string_init_interned("REASON_RESET", sizeof("REASON_RESET") - 1, 1); + zend_string *const_REASON_RESET_name = zend_string_init_interned("REASON_RESET", sizeof("REASON_RESET") - 1, true); zend_declare_typed_class_constant(class_entry, const_REASON_RESET_name, &const_REASON_RESET_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_REASON_RESET_name); + zend_string_release_ex(const_REASON_RESET_name, true); zval const_REASON_CLOSE_value; ZVAL_LONG(&const_REASON_CLOSE_value, UCNV_CLOSE); - zend_string *const_REASON_CLOSE_name = zend_string_init_interned("REASON_CLOSE", sizeof("REASON_CLOSE") - 1, 1); + zend_string *const_REASON_CLOSE_name = zend_string_init_interned("REASON_CLOSE", sizeof("REASON_CLOSE") - 1, true); zend_declare_typed_class_constant(class_entry, const_REASON_CLOSE_name, &const_REASON_CLOSE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_REASON_CLOSE_name); + zend_string_release_ex(const_REASON_CLOSE_name, true); zval const_REASON_CLONE_value; ZVAL_LONG(&const_REASON_CLONE_value, UCNV_CLONE); - zend_string *const_REASON_CLONE_name = zend_string_init_interned("REASON_CLONE", sizeof("REASON_CLONE") - 1, 1); + zend_string *const_REASON_CLONE_name = zend_string_init_interned("REASON_CLONE", sizeof("REASON_CLONE") - 1, true); zend_declare_typed_class_constant(class_entry, const_REASON_CLONE_name, &const_REASON_CLONE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_REASON_CLONE_name); + zend_string_release_ex(const_REASON_CLONE_name, true); zval const_UNSUPPORTED_CONVERTER_value; ZVAL_LONG(&const_UNSUPPORTED_CONVERTER_value, UCNV_UNSUPPORTED_CONVERTER); - zend_string *const_UNSUPPORTED_CONVERTER_name = zend_string_init_interned("UNSUPPORTED_CONVERTER", sizeof("UNSUPPORTED_CONVERTER") - 1, 1); + zend_string *const_UNSUPPORTED_CONVERTER_name = zend_string_init_interned("UNSUPPORTED_CONVERTER", sizeof("UNSUPPORTED_CONVERTER") - 1, true); zend_declare_typed_class_constant(class_entry, const_UNSUPPORTED_CONVERTER_name, &const_UNSUPPORTED_CONVERTER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_UNSUPPORTED_CONVERTER_name); + zend_string_release_ex(const_UNSUPPORTED_CONVERTER_name, true); zval const_SBCS_value; ZVAL_LONG(&const_SBCS_value, UCNV_SBCS); - zend_string *const_SBCS_name = zend_string_init_interned("SBCS", sizeof("SBCS") - 1, 1); + zend_string *const_SBCS_name = zend_string_init_interned("SBCS", sizeof("SBCS") - 1, true); zend_declare_typed_class_constant(class_entry, const_SBCS_name, &const_SBCS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SBCS_name); + zend_string_release_ex(const_SBCS_name, true); zval const_DBCS_value; ZVAL_LONG(&const_DBCS_value, UCNV_DBCS); - zend_string *const_DBCS_name = zend_string_init_interned("DBCS", sizeof("DBCS") - 1, 1); + zend_string *const_DBCS_name = zend_string_init_interned("DBCS", sizeof("DBCS") - 1, true); zend_declare_typed_class_constant(class_entry, const_DBCS_name, &const_DBCS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DBCS_name); + zend_string_release_ex(const_DBCS_name, true); zval const_MBCS_value; ZVAL_LONG(&const_MBCS_value, UCNV_MBCS); - zend_string *const_MBCS_name = zend_string_init_interned("MBCS", sizeof("MBCS") - 1, 1); + zend_string *const_MBCS_name = zend_string_init_interned("MBCS", sizeof("MBCS") - 1, true); zend_declare_typed_class_constant(class_entry, const_MBCS_name, &const_MBCS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_MBCS_name); + zend_string_release_ex(const_MBCS_name, true); zval const_LATIN_1_value; ZVAL_LONG(&const_LATIN_1_value, UCNV_LATIN_1); - zend_string *const_LATIN_1_name = zend_string_init_interned("LATIN_1", sizeof("LATIN_1") - 1, 1); + zend_string *const_LATIN_1_name = zend_string_init_interned("LATIN_1", sizeof("LATIN_1") - 1, true); zend_declare_typed_class_constant(class_entry, const_LATIN_1_name, &const_LATIN_1_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LATIN_1_name); + zend_string_release_ex(const_LATIN_1_name, true); zval const_UTF8_value; ZVAL_LONG(&const_UTF8_value, UCNV_UTF8); - zend_string *const_UTF8_name = zend_string_init_interned("UTF8", sizeof("UTF8") - 1, 1); + zend_string *const_UTF8_name = zend_string_init_interned("UTF8", sizeof("UTF8") - 1, true); zend_declare_typed_class_constant(class_entry, const_UTF8_name, &const_UTF8_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_UTF8_name); + zend_string_release_ex(const_UTF8_name, true); zval const_UTF16_BigEndian_value; ZVAL_LONG(&const_UTF16_BigEndian_value, UCNV_UTF16_BigEndian); - zend_string *const_UTF16_BigEndian_name = zend_string_init_interned("UTF16_BigEndian", sizeof("UTF16_BigEndian") - 1, 1); + zend_string *const_UTF16_BigEndian_name = zend_string_init_interned("UTF16_BigEndian", sizeof("UTF16_BigEndian") - 1, true); zend_declare_typed_class_constant(class_entry, const_UTF16_BigEndian_name, &const_UTF16_BigEndian_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_UTF16_BigEndian_name); + zend_string_release_ex(const_UTF16_BigEndian_name, true); zval const_UTF16_LittleEndian_value; ZVAL_LONG(&const_UTF16_LittleEndian_value, UCNV_UTF16_LittleEndian); - zend_string *const_UTF16_LittleEndian_name = zend_string_init_interned("UTF16_LittleEndian", sizeof("UTF16_LittleEndian") - 1, 1); + zend_string *const_UTF16_LittleEndian_name = zend_string_init_interned("UTF16_LittleEndian", sizeof("UTF16_LittleEndian") - 1, true); zend_declare_typed_class_constant(class_entry, const_UTF16_LittleEndian_name, &const_UTF16_LittleEndian_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_UTF16_LittleEndian_name); + zend_string_release_ex(const_UTF16_LittleEndian_name, true); zval const_UTF32_BigEndian_value; ZVAL_LONG(&const_UTF32_BigEndian_value, UCNV_UTF32_BigEndian); - zend_string *const_UTF32_BigEndian_name = zend_string_init_interned("UTF32_BigEndian", sizeof("UTF32_BigEndian") - 1, 1); + zend_string *const_UTF32_BigEndian_name = zend_string_init_interned("UTF32_BigEndian", sizeof("UTF32_BigEndian") - 1, true); zend_declare_typed_class_constant(class_entry, const_UTF32_BigEndian_name, &const_UTF32_BigEndian_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_UTF32_BigEndian_name); + zend_string_release_ex(const_UTF32_BigEndian_name, true); zval const_UTF32_LittleEndian_value; ZVAL_LONG(&const_UTF32_LittleEndian_value, UCNV_UTF32_LittleEndian); - zend_string *const_UTF32_LittleEndian_name = zend_string_init_interned("UTF32_LittleEndian", sizeof("UTF32_LittleEndian") - 1, 1); + zend_string *const_UTF32_LittleEndian_name = zend_string_init_interned("UTF32_LittleEndian", sizeof("UTF32_LittleEndian") - 1, true); zend_declare_typed_class_constant(class_entry, const_UTF32_LittleEndian_name, &const_UTF32_LittleEndian_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_UTF32_LittleEndian_name); + zend_string_release_ex(const_UTF32_LittleEndian_name, true); zval const_EBCDIC_STATEFUL_value; ZVAL_LONG(&const_EBCDIC_STATEFUL_value, UCNV_EBCDIC_STATEFUL); - zend_string *const_EBCDIC_STATEFUL_name = zend_string_init_interned("EBCDIC_STATEFUL", sizeof("EBCDIC_STATEFUL") - 1, 1); + zend_string *const_EBCDIC_STATEFUL_name = zend_string_init_interned("EBCDIC_STATEFUL", sizeof("EBCDIC_STATEFUL") - 1, true); zend_declare_typed_class_constant(class_entry, const_EBCDIC_STATEFUL_name, &const_EBCDIC_STATEFUL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EBCDIC_STATEFUL_name); + zend_string_release_ex(const_EBCDIC_STATEFUL_name, true); zval const_ISO_2022_value; ZVAL_LONG(&const_ISO_2022_value, UCNV_ISO_2022); - zend_string *const_ISO_2022_name = zend_string_init_interned("ISO_2022", sizeof("ISO_2022") - 1, 1); + zend_string *const_ISO_2022_name = zend_string_init_interned("ISO_2022", sizeof("ISO_2022") - 1, true); zend_declare_typed_class_constant(class_entry, const_ISO_2022_name, &const_ISO_2022_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ISO_2022_name); + zend_string_release_ex(const_ISO_2022_name, true); zval const_LMBCS_1_value; ZVAL_LONG(&const_LMBCS_1_value, UCNV_LMBCS_1); - zend_string *const_LMBCS_1_name = zend_string_init_interned("LMBCS_1", sizeof("LMBCS_1") - 1, 1); + zend_string *const_LMBCS_1_name = zend_string_init_interned("LMBCS_1", sizeof("LMBCS_1") - 1, true); zend_declare_typed_class_constant(class_entry, const_LMBCS_1_name, &const_LMBCS_1_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LMBCS_1_name); + zend_string_release_ex(const_LMBCS_1_name, true); zval const_LMBCS_2_value; ZVAL_LONG(&const_LMBCS_2_value, UCNV_LMBCS_2); - zend_string *const_LMBCS_2_name = zend_string_init_interned("LMBCS_2", sizeof("LMBCS_2") - 1, 1); + zend_string *const_LMBCS_2_name = zend_string_init_interned("LMBCS_2", sizeof("LMBCS_2") - 1, true); zend_declare_typed_class_constant(class_entry, const_LMBCS_2_name, &const_LMBCS_2_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LMBCS_2_name); + zend_string_release_ex(const_LMBCS_2_name, true); zval const_LMBCS_3_value; ZVAL_LONG(&const_LMBCS_3_value, UCNV_LMBCS_3); - zend_string *const_LMBCS_3_name = zend_string_init_interned("LMBCS_3", sizeof("LMBCS_3") - 1, 1); + zend_string *const_LMBCS_3_name = zend_string_init_interned("LMBCS_3", sizeof("LMBCS_3") - 1, true); zend_declare_typed_class_constant(class_entry, const_LMBCS_3_name, &const_LMBCS_3_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LMBCS_3_name); + zend_string_release_ex(const_LMBCS_3_name, true); zval const_LMBCS_4_value; ZVAL_LONG(&const_LMBCS_4_value, UCNV_LMBCS_4); - zend_string *const_LMBCS_4_name = zend_string_init_interned("LMBCS_4", sizeof("LMBCS_4") - 1, 1); + zend_string *const_LMBCS_4_name = zend_string_init_interned("LMBCS_4", sizeof("LMBCS_4") - 1, true); zend_declare_typed_class_constant(class_entry, const_LMBCS_4_name, &const_LMBCS_4_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LMBCS_4_name); + zend_string_release_ex(const_LMBCS_4_name, true); zval const_LMBCS_5_value; ZVAL_LONG(&const_LMBCS_5_value, UCNV_LMBCS_5); - zend_string *const_LMBCS_5_name = zend_string_init_interned("LMBCS_5", sizeof("LMBCS_5") - 1, 1); + zend_string *const_LMBCS_5_name = zend_string_init_interned("LMBCS_5", sizeof("LMBCS_5") - 1, true); zend_declare_typed_class_constant(class_entry, const_LMBCS_5_name, &const_LMBCS_5_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LMBCS_5_name); + zend_string_release_ex(const_LMBCS_5_name, true); zval const_LMBCS_6_value; ZVAL_LONG(&const_LMBCS_6_value, UCNV_LMBCS_6); - zend_string *const_LMBCS_6_name = zend_string_init_interned("LMBCS_6", sizeof("LMBCS_6") - 1, 1); + zend_string *const_LMBCS_6_name = zend_string_init_interned("LMBCS_6", sizeof("LMBCS_6") - 1, true); zend_declare_typed_class_constant(class_entry, const_LMBCS_6_name, &const_LMBCS_6_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LMBCS_6_name); + zend_string_release_ex(const_LMBCS_6_name, true); zval const_LMBCS_8_value; ZVAL_LONG(&const_LMBCS_8_value, UCNV_LMBCS_8); - zend_string *const_LMBCS_8_name = zend_string_init_interned("LMBCS_8", sizeof("LMBCS_8") - 1, 1); + zend_string *const_LMBCS_8_name = zend_string_init_interned("LMBCS_8", sizeof("LMBCS_8") - 1, true); zend_declare_typed_class_constant(class_entry, const_LMBCS_8_name, &const_LMBCS_8_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LMBCS_8_name); + zend_string_release_ex(const_LMBCS_8_name, true); zval const_LMBCS_11_value; ZVAL_LONG(&const_LMBCS_11_value, UCNV_LMBCS_11); - zend_string *const_LMBCS_11_name = zend_string_init_interned("LMBCS_11", sizeof("LMBCS_11") - 1, 1); + zend_string *const_LMBCS_11_name = zend_string_init_interned("LMBCS_11", sizeof("LMBCS_11") - 1, true); zend_declare_typed_class_constant(class_entry, const_LMBCS_11_name, &const_LMBCS_11_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LMBCS_11_name); + zend_string_release_ex(const_LMBCS_11_name, true); zval const_LMBCS_16_value; ZVAL_LONG(&const_LMBCS_16_value, UCNV_LMBCS_16); - zend_string *const_LMBCS_16_name = zend_string_init_interned("LMBCS_16", sizeof("LMBCS_16") - 1, 1); + zend_string *const_LMBCS_16_name = zend_string_init_interned("LMBCS_16", sizeof("LMBCS_16") - 1, true); zend_declare_typed_class_constant(class_entry, const_LMBCS_16_name, &const_LMBCS_16_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LMBCS_16_name); + zend_string_release_ex(const_LMBCS_16_name, true); zval const_LMBCS_17_value; ZVAL_LONG(&const_LMBCS_17_value, UCNV_LMBCS_17); - zend_string *const_LMBCS_17_name = zend_string_init_interned("LMBCS_17", sizeof("LMBCS_17") - 1, 1); + zend_string *const_LMBCS_17_name = zend_string_init_interned("LMBCS_17", sizeof("LMBCS_17") - 1, true); zend_declare_typed_class_constant(class_entry, const_LMBCS_17_name, &const_LMBCS_17_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LMBCS_17_name); + zend_string_release_ex(const_LMBCS_17_name, true); zval const_LMBCS_18_value; ZVAL_LONG(&const_LMBCS_18_value, UCNV_LMBCS_18); - zend_string *const_LMBCS_18_name = zend_string_init_interned("LMBCS_18", sizeof("LMBCS_18") - 1, 1); + zend_string *const_LMBCS_18_name = zend_string_init_interned("LMBCS_18", sizeof("LMBCS_18") - 1, true); zend_declare_typed_class_constant(class_entry, const_LMBCS_18_name, &const_LMBCS_18_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LMBCS_18_name); + zend_string_release_ex(const_LMBCS_18_name, true); zval const_LMBCS_19_value; ZVAL_LONG(&const_LMBCS_19_value, UCNV_LMBCS_19); - zend_string *const_LMBCS_19_name = zend_string_init_interned("LMBCS_19", sizeof("LMBCS_19") - 1, 1); + zend_string *const_LMBCS_19_name = zend_string_init_interned("LMBCS_19", sizeof("LMBCS_19") - 1, true); zend_declare_typed_class_constant(class_entry, const_LMBCS_19_name, &const_LMBCS_19_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LMBCS_19_name); + zend_string_release_ex(const_LMBCS_19_name, true); zval const_LMBCS_LAST_value; ZVAL_LONG(&const_LMBCS_LAST_value, UCNV_LMBCS_LAST); - zend_string *const_LMBCS_LAST_name = zend_string_init_interned("LMBCS_LAST", sizeof("LMBCS_LAST") - 1, 1); + zend_string *const_LMBCS_LAST_name = zend_string_init_interned("LMBCS_LAST", sizeof("LMBCS_LAST") - 1, true); zend_declare_typed_class_constant(class_entry, const_LMBCS_LAST_name, &const_LMBCS_LAST_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LMBCS_LAST_name); + zend_string_release_ex(const_LMBCS_LAST_name, true); zval const_HZ_value; ZVAL_LONG(&const_HZ_value, UCNV_HZ); - zend_string *const_HZ_name = zend_string_init_interned("HZ", sizeof("HZ") - 1, 1); + zend_string *const_HZ_name = zend_string_init_interned("HZ", sizeof("HZ") - 1, true); zend_declare_typed_class_constant(class_entry, const_HZ_name, &const_HZ_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_HZ_name); + zend_string_release_ex(const_HZ_name, true); zval const_SCSU_value; ZVAL_LONG(&const_SCSU_value, UCNV_SCSU); - zend_string *const_SCSU_name = zend_string_init_interned("SCSU", sizeof("SCSU") - 1, 1); + zend_string *const_SCSU_name = zend_string_init_interned("SCSU", sizeof("SCSU") - 1, true); zend_declare_typed_class_constant(class_entry, const_SCSU_name, &const_SCSU_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SCSU_name); + zend_string_release_ex(const_SCSU_name, true); zval const_ISCII_value; ZVAL_LONG(&const_ISCII_value, UCNV_ISCII); - zend_string *const_ISCII_name = zend_string_init_interned("ISCII", sizeof("ISCII") - 1, 1); + zend_string *const_ISCII_name = zend_string_init_interned("ISCII", sizeof("ISCII") - 1, true); zend_declare_typed_class_constant(class_entry, const_ISCII_name, &const_ISCII_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ISCII_name); + zend_string_release_ex(const_ISCII_name, true); zval const_US_ASCII_value; ZVAL_LONG(&const_US_ASCII_value, UCNV_US_ASCII); - zend_string *const_US_ASCII_name = zend_string_init_interned("US_ASCII", sizeof("US_ASCII") - 1, 1); + zend_string *const_US_ASCII_name = zend_string_init_interned("US_ASCII", sizeof("US_ASCII") - 1, true); zend_declare_typed_class_constant(class_entry, const_US_ASCII_name, &const_US_ASCII_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_US_ASCII_name); + zend_string_release_ex(const_US_ASCII_name, true); zval const_UTF7_value; ZVAL_LONG(&const_UTF7_value, UCNV_UTF7); - zend_string *const_UTF7_name = zend_string_init_interned("UTF7", sizeof("UTF7") - 1, 1); + zend_string *const_UTF7_name = zend_string_init_interned("UTF7", sizeof("UTF7") - 1, true); zend_declare_typed_class_constant(class_entry, const_UTF7_name, &const_UTF7_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_UTF7_name); + zend_string_release_ex(const_UTF7_name, true); zval const_BOCU1_value; ZVAL_LONG(&const_BOCU1_value, UCNV_BOCU1); - zend_string *const_BOCU1_name = zend_string_init_interned("BOCU1", sizeof("BOCU1") - 1, 1); + zend_string *const_BOCU1_name = zend_string_init_interned("BOCU1", sizeof("BOCU1") - 1, true); zend_declare_typed_class_constant(class_entry, const_BOCU1_name, &const_BOCU1_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BOCU1_name); + zend_string_release_ex(const_BOCU1_name, true); zval const_UTF16_value; ZVAL_LONG(&const_UTF16_value, UCNV_UTF16); - zend_string *const_UTF16_name = zend_string_init_interned("UTF16", sizeof("UTF16") - 1, 1); + zend_string *const_UTF16_name = zend_string_init_interned("UTF16", sizeof("UTF16") - 1, true); zend_declare_typed_class_constant(class_entry, const_UTF16_name, &const_UTF16_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_UTF16_name); + zend_string_release_ex(const_UTF16_name, true); zval const_UTF32_value; ZVAL_LONG(&const_UTF32_value, UCNV_UTF32); - zend_string *const_UTF32_name = zend_string_init_interned("UTF32", sizeof("UTF32") - 1, 1); + zend_string *const_UTF32_name = zend_string_init_interned("UTF32", sizeof("UTF32") - 1, true); zend_declare_typed_class_constant(class_entry, const_UTF32_name, &const_UTF32_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_UTF32_name); + zend_string_release_ex(const_UTF32_name, true); zval const_CESU8_value; ZVAL_LONG(&const_CESU8_value, UCNV_CESU8); - zend_string *const_CESU8_name = zend_string_init_interned("CESU8", sizeof("CESU8") - 1, 1); + zend_string *const_CESU8_name = zend_string_init_interned("CESU8", sizeof("CESU8") - 1, true); zend_declare_typed_class_constant(class_entry, const_CESU8_name, &const_CESU8_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CESU8_name); + zend_string_release_ex(const_CESU8_name, true); zval const_IMAP_MAILBOX_value; ZVAL_LONG(&const_IMAP_MAILBOX_value, UCNV_IMAP_MAILBOX); - zend_string *const_IMAP_MAILBOX_name = zend_string_init_interned("IMAP_MAILBOX", sizeof("IMAP_MAILBOX") - 1, 1); + zend_string *const_IMAP_MAILBOX_name = zend_string_init_interned("IMAP_MAILBOX", sizeof("IMAP_MAILBOX") - 1, true); zend_declare_typed_class_constant(class_entry, const_IMAP_MAILBOX_name, &const_IMAP_MAILBOX_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IMAP_MAILBOX_name); + zend_string_release_ex(const_IMAP_MAILBOX_name, true); return class_entry; } diff --git a/ext/intl/dateformat/dateformat.c b/ext/intl/dateformat/dateformat.c deleted file mode 100644 index e6ebd5b789649..0000000000000 --- a/ext/intl/dateformat/dateformat.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Kirti Velankar | - +----------------------------------------------------------------------+ -*/ -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "php_intl.h" -#include "dateformat_class.h" -#include "dateformat.h" - -/* {{{ Get formatter's last error code. */ -PHP_FUNCTION( datefmt_get_error_code ) -{ - DATE_FORMAT_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", - &object, IntlDateFormatter_ce_ptr ) == FAILURE ) - { - RETURN_THROWS(); - } - - dfo = Z_INTL_DATEFORMATTER_P( object ); - - /* Return formatter's last error code. */ - RETURN_LONG( INTL_DATA_ERROR_CODE(dfo) ); -} -/* }}} */ - -/* {{{ Get text description for formatter's last error code. */ -PHP_FUNCTION( datefmt_get_error_message ) -{ - zend_string *message = NULL; - DATE_FORMAT_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", - &object, IntlDateFormatter_ce_ptr ) == FAILURE ) - { - RETURN_THROWS(); - } - - dfo = Z_INTL_DATEFORMATTER_P( object ); - - /* Return last error message. */ - message = intl_error_get_message( INTL_DATA_ERROR_P(dfo) ); - RETURN_STR( message); -} -/* }}} */ diff --git a/ext/intl/dateformat/dateformat.cpp b/ext/intl/dateformat/dateformat.cpp new file mode 100644 index 0000000000000..cf2b445590bb9 --- /dev/null +++ b/ext/intl/dateformat/dateformat.cpp @@ -0,0 +1,64 @@ +/* + +----------------------------------------------------------------------+ + | 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: Kirti Velankar | + +----------------------------------------------------------------------+ +*/ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +extern "C" { +#include "php_intl.h" +} +#include "dateformat_class.h" +#include "dateformat.h" + +/* {{{ Get formatter's last error code. */ +U_CFUNC PHP_FUNCTION( datefmt_get_error_code ) +{ + DATE_FORMAT_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", + &object, IntlDateFormatter_ce_ptr ) == FAILURE ) + { + RETURN_THROWS(); + } + + dfo = Z_INTL_DATEFORMATTER_P( object ); + + /* Return formatter's last error code. */ + RETURN_LONG( INTL_DATA_ERROR_CODE(dfo) ); +} +/* }}} */ + +/* {{{ Get text description for formatter's last error code. */ +U_CFUNC PHP_FUNCTION( datefmt_get_error_message ) +{ + zend_string *message = NULL; + DATE_FORMAT_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", + &object, IntlDateFormatter_ce_ptr ) == FAILURE ) + { + RETURN_THROWS(); + } + + dfo = Z_INTL_DATEFORMATTER_P( object ); + + /* Return last error message. */ + message = intl_error_get_message( INTL_DATA_ERROR_P(dfo) ); + RETURN_STR( message); +} +/* }}} */ 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..5a5c6a9f34c29 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) @@ -149,75 +149,75 @@ static zend_class_entry *register_class_IntlDateFormatter(void) zval const_FULL_value; ZVAL_LONG(&const_FULL_value, UDAT_FULL); - zend_string *const_FULL_name = zend_string_init_interned("FULL", sizeof("FULL") - 1, 1); + zend_string *const_FULL_name = zend_string_init_interned("FULL", sizeof("FULL") - 1, true); zend_declare_typed_class_constant(class_entry, const_FULL_name, &const_FULL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FULL_name); + zend_string_release_ex(const_FULL_name, true); zval const_LONG_value; ZVAL_LONG(&const_LONG_value, UDAT_LONG); - zend_string *const_LONG_name = zend_string_init_interned("LONG", sizeof("LONG") - 1, 1); + zend_string *const_LONG_name = zend_string_init_interned("LONG", sizeof("LONG") - 1, true); zend_declare_typed_class_constant(class_entry, const_LONG_name, &const_LONG_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LONG_name); + zend_string_release_ex(const_LONG_name, true); zval const_MEDIUM_value; ZVAL_LONG(&const_MEDIUM_value, UDAT_MEDIUM); - zend_string *const_MEDIUM_name = zend_string_init_interned("MEDIUM", sizeof("MEDIUM") - 1, 1); + zend_string *const_MEDIUM_name = zend_string_init_interned("MEDIUM", sizeof("MEDIUM") - 1, true); zend_declare_typed_class_constant(class_entry, const_MEDIUM_name, &const_MEDIUM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_MEDIUM_name); + zend_string_release_ex(const_MEDIUM_name, true); zval const_SHORT_value; ZVAL_LONG(&const_SHORT_value, UDAT_SHORT); - zend_string *const_SHORT_name = zend_string_init_interned("SHORT", sizeof("SHORT") - 1, 1); + zend_string *const_SHORT_name = zend_string_init_interned("SHORT", sizeof("SHORT") - 1, true); zend_declare_typed_class_constant(class_entry, const_SHORT_name, &const_SHORT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SHORT_name); + zend_string_release_ex(const_SHORT_name, true); zval const_NONE_value; ZVAL_LONG(&const_NONE_value, UDAT_NONE); - zend_string *const_NONE_name = zend_string_init_interned("NONE", sizeof("NONE") - 1, 1); + zend_string *const_NONE_name = zend_string_init_interned("NONE", sizeof("NONE") - 1, true); zend_declare_typed_class_constant(class_entry, const_NONE_name, &const_NONE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NONE_name); + zend_string_release_ex(const_NONE_name, true); zval const_RELATIVE_FULL_value; ZVAL_LONG(&const_RELATIVE_FULL_value, UDAT_FULL_RELATIVE); - zend_string *const_RELATIVE_FULL_name = zend_string_init_interned("RELATIVE_FULL", sizeof("RELATIVE_FULL") - 1, 1); + zend_string *const_RELATIVE_FULL_name = zend_string_init_interned("RELATIVE_FULL", sizeof("RELATIVE_FULL") - 1, true); zend_declare_typed_class_constant(class_entry, const_RELATIVE_FULL_name, &const_RELATIVE_FULL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_RELATIVE_FULL_name); + zend_string_release_ex(const_RELATIVE_FULL_name, true); zval const_RELATIVE_LONG_value; ZVAL_LONG(&const_RELATIVE_LONG_value, UDAT_LONG_RELATIVE); - zend_string *const_RELATIVE_LONG_name = zend_string_init_interned("RELATIVE_LONG", sizeof("RELATIVE_LONG") - 1, 1); + zend_string *const_RELATIVE_LONG_name = zend_string_init_interned("RELATIVE_LONG", sizeof("RELATIVE_LONG") - 1, true); zend_declare_typed_class_constant(class_entry, const_RELATIVE_LONG_name, &const_RELATIVE_LONG_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_RELATIVE_LONG_name); + zend_string_release_ex(const_RELATIVE_LONG_name, true); zval const_RELATIVE_MEDIUM_value; ZVAL_LONG(&const_RELATIVE_MEDIUM_value, UDAT_MEDIUM_RELATIVE); - zend_string *const_RELATIVE_MEDIUM_name = zend_string_init_interned("RELATIVE_MEDIUM", sizeof("RELATIVE_MEDIUM") - 1, 1); + zend_string *const_RELATIVE_MEDIUM_name = zend_string_init_interned("RELATIVE_MEDIUM", sizeof("RELATIVE_MEDIUM") - 1, true); zend_declare_typed_class_constant(class_entry, const_RELATIVE_MEDIUM_name, &const_RELATIVE_MEDIUM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_RELATIVE_MEDIUM_name); + zend_string_release_ex(const_RELATIVE_MEDIUM_name, true); zval const_RELATIVE_SHORT_value; ZVAL_LONG(&const_RELATIVE_SHORT_value, UDAT_SHORT_RELATIVE); - zend_string *const_RELATIVE_SHORT_name = zend_string_init_interned("RELATIVE_SHORT", sizeof("RELATIVE_SHORT") - 1, 1); + zend_string *const_RELATIVE_SHORT_name = zend_string_init_interned("RELATIVE_SHORT", sizeof("RELATIVE_SHORT") - 1, true); zend_declare_typed_class_constant(class_entry, const_RELATIVE_SHORT_name, &const_RELATIVE_SHORT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_RELATIVE_SHORT_name); + zend_string_release_ex(const_RELATIVE_SHORT_name, true); zval const_PATTERN_value; ZVAL_LONG(&const_PATTERN_value, UDAT_PATTERN); - zend_string *const_PATTERN_name = zend_string_init_interned("PATTERN", sizeof("PATTERN") - 1, 1); + zend_string *const_PATTERN_name = zend_string_init_interned("PATTERN", sizeof("PATTERN") - 1, true); zend_declare_typed_class_constant(class_entry, const_PATTERN_name, &const_PATTERN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PATTERN_name); + zend_string_release_ex(const_PATTERN_name, true); zval const_GREGORIAN_value; ZVAL_LONG(&const_GREGORIAN_value, UCAL_GREGORIAN); - zend_string *const_GREGORIAN_name = zend_string_init_interned("GREGORIAN", sizeof("GREGORIAN") - 1, 1); + zend_string *const_GREGORIAN_name = zend_string_init_interned("GREGORIAN", sizeof("GREGORIAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_GREGORIAN_name, &const_GREGORIAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_GREGORIAN_name); + zend_string_release_ex(const_GREGORIAN_name, true); zval const_TRADITIONAL_value; ZVAL_LONG(&const_TRADITIONAL_value, UCAL_TRADITIONAL); - zend_string *const_TRADITIONAL_name = zend_string_init_interned("TRADITIONAL", sizeof("TRADITIONAL") - 1, 1); + zend_string *const_TRADITIONAL_name = zend_string_init_interned("TRADITIONAL", sizeof("TRADITIONAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_TRADITIONAL_name, &const_TRADITIONAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TRADITIONAL_name); + zend_string_release_ex(const_TRADITIONAL_name, true); return class_entry; } diff --git a/ext/intl/dateformat/dateformat_attr.c b/ext/intl/dateformat/dateformat_attr.c deleted file mode 100644 index 8032d758a939b..0000000000000 --- a/ext/intl/dateformat/dateformat_attr.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Kirti Velankar | - +----------------------------------------------------------------------+ -*/ -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "../php_intl.h" -#include "dateformat_class.h" -#include "../intl_convert.h" -#include "dateformat_class.h" - -#include -#include - -/* {{{ Get formatter datetype. */ -PHP_FUNCTION( datefmt_get_datetype ) -{ - DATE_FORMAT_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", &object, IntlDateFormatter_ce_ptr ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - DATE_FORMAT_METHOD_FETCH_OBJECT; - - INTL_METHOD_CHECK_STATUS(dfo, "Error getting formatter datetype." ); - - RETURN_LONG(dfo->date_type ); -} -/* }}} */ - -/* {{{ Get formatter timetype. */ -PHP_FUNCTION( datefmt_get_timetype ) -{ - DATE_FORMAT_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", &object, IntlDateFormatter_ce_ptr ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - DATE_FORMAT_METHOD_FETCH_OBJECT; - - INTL_METHOD_CHECK_STATUS(dfo, "Error getting formatter timetype." ); - - RETURN_LONG(dfo->time_type ); -} -/* }}} */ - -/* {{{ Get formatter pattern. */ -PHP_FUNCTION( datefmt_get_pattern ) -{ - UChar value_buf[64]; - uint32_t length = USIZE( value_buf ); - UChar* value = value_buf; - bool is_pattern_localized = false; - - DATE_FORMAT_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", &object, IntlDateFormatter_ce_ptr ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - DATE_FORMAT_METHOD_FETCH_OBJECT; - - length = udat_toPattern(DATE_FORMAT_OBJECT(dfo), is_pattern_localized, value, length, &INTL_DATA_ERROR_CODE(dfo)); - if(INTL_DATA_ERROR_CODE(dfo) == U_BUFFER_OVERFLOW_ERROR && length >= USIZE( value_buf )) { - ++length; /* to avoid U_STRING_NOT_TERMINATED_WARNING */ - INTL_DATA_ERROR_CODE(dfo) = U_ZERO_ERROR; - value = eumalloc(length); - length = udat_toPattern(DATE_FORMAT_OBJECT(dfo), is_pattern_localized, value, length, &INTL_DATA_ERROR_CODE(dfo) ); - if(U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { - efree(value); - value = value_buf; - } - } - INTL_METHOD_CHECK_STATUS(dfo, "Error getting formatter pattern" ); - - INTL_METHOD_RETVAL_UTF8( dfo, value, length, ( value != value_buf ) ); -} -/* }}} */ - -/* {{{ Set formatter pattern. */ -PHP_FUNCTION( datefmt_set_pattern ) -{ - char* value = NULL; - size_t value_len = 0; - int32_t slength = 0; - UChar* svalue = NULL; - bool is_pattern_localized = false; - - - DATE_FORMAT_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Os", - &object, IntlDateFormatter_ce_ptr, &value, &value_len ) == FAILURE ) - { - RETURN_THROWS(); - } - - DATE_FORMAT_METHOD_FETCH_OBJECT; - - /* Convert given pattern to UTF-16. */ - intl_convert_utf8_to_utf16(&svalue, &slength, value, value_len, &INTL_DATA_ERROR_CODE(dfo)); - INTL_METHOD_CHECK_STATUS(dfo, "Error converting pattern to UTF-16" ); - - udat_applyPattern(DATE_FORMAT_OBJECT(dfo), (UBool)is_pattern_localized, svalue, slength); - - if (svalue) { - efree(svalue); - } - INTL_METHOD_CHECK_STATUS(dfo, "Error setting symbol value"); - - RETURN_TRUE; -} -/* }}} */ - -/* {{{ Get formatter locale. */ -PHP_FUNCTION( datefmt_get_locale ) -{ - char *loc; - zend_long loc_type =ULOC_ACTUAL_LOCALE; - - DATE_FORMAT_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O|l", - &object, IntlDateFormatter_ce_ptr,&loc_type) == FAILURE ) - { - - RETURN_THROWS(); - } - - /* Fetch the object. */ - DATE_FORMAT_METHOD_FETCH_OBJECT; - - loc = (char *)udat_getLocaleByType(DATE_FORMAT_OBJECT(dfo), loc_type,&INTL_DATA_ERROR_CODE(dfo)); - INTL_METHOD_CHECK_STATUS(dfo, "Error getting locale"); - RETURN_STRING(loc); -} -/* }}} */ - -/* {{{ Get formatter isLenient. */ -PHP_FUNCTION( datefmt_is_lenient ) -{ - - DATE_FORMAT_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", - &object, IntlDateFormatter_ce_ptr ) == FAILURE ) - { - - RETURN_THROWS(); - } - - /* Fetch the object. */ - DATE_FORMAT_METHOD_FETCH_OBJECT; - - RETVAL_BOOL(udat_isLenient(DATE_FORMAT_OBJECT(dfo))); -} -/* }}} */ - -/* {{{ Set formatter lenient. */ -PHP_FUNCTION( datefmt_set_lenient ) -{ - bool isLenient = false; - - DATE_FORMAT_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ob", - &object, IntlDateFormatter_ce_ptr,&isLenient ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - DATE_FORMAT_METHOD_FETCH_OBJECT; - - udat_setLenient(DATE_FORMAT_OBJECT(dfo), (UBool)isLenient ); -} -/* }}} */ diff --git a/ext/intl/dateformat/dateformat_attr.cpp b/ext/intl/dateformat/dateformat_attr.cpp new file mode 100644 index 0000000000000..1ec55a806a7ca --- /dev/null +++ b/ext/intl/dateformat/dateformat_attr.cpp @@ -0,0 +1,205 @@ +/* + +----------------------------------------------------------------------+ + | 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: Kirti Velankar | + +----------------------------------------------------------------------+ +*/ +#ifdef HAVE_CONFIG_H +#include +#endif + +extern "C" { +#include "../php_intl.h" +#include "../intl_convert.h" +} +#include "dateformat_class.h" +#include "dateformat_class.h" + +#include +#include + +/* {{{ Get formatter datetype. */ +U_CFUNC PHP_FUNCTION( datefmt_get_datetype ) +{ + DATE_FORMAT_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", &object, IntlDateFormatter_ce_ptr ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + DATE_FORMAT_METHOD_FETCH_OBJECT; + + INTL_METHOD_CHECK_STATUS(dfo, "Error getting formatter datetype." ); + + RETURN_LONG(dfo->date_type ); +} +/* }}} */ + +/* {{{ Get formatter timetype. */ +U_CFUNC PHP_FUNCTION( datefmt_get_timetype ) +{ + DATE_FORMAT_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", &object, IntlDateFormatter_ce_ptr ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + DATE_FORMAT_METHOD_FETCH_OBJECT; + + INTL_METHOD_CHECK_STATUS(dfo, "Error getting formatter timetype." ); + + RETURN_LONG(dfo->time_type ); +} +/* }}} */ + +/* {{{ Get formatter pattern. */ +U_CFUNC PHP_FUNCTION( datefmt_get_pattern ) +{ + UChar value_buf[64]; + uint32_t length = USIZE( value_buf ); + UChar* value = value_buf; + bool is_pattern_localized = false; + + DATE_FORMAT_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", &object, IntlDateFormatter_ce_ptr ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + DATE_FORMAT_METHOD_FETCH_OBJECT; + + length = udat_toPattern(DATE_FORMAT_OBJECT(dfo), is_pattern_localized, value, length, &INTL_DATA_ERROR_CODE(dfo)); + if(INTL_DATA_ERROR_CODE(dfo) == U_BUFFER_OVERFLOW_ERROR && length >= USIZE( value_buf )) { + ++length; /* to avoid U_STRING_NOT_TERMINATED_WARNING */ + INTL_DATA_ERROR_CODE(dfo) = U_ZERO_ERROR; + value = eumalloc(length); + length = udat_toPattern(DATE_FORMAT_OBJECT(dfo), is_pattern_localized, value, length, &INTL_DATA_ERROR_CODE(dfo) ); + if(U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { + efree(value); + value = value_buf; + } + } + INTL_METHOD_CHECK_STATUS(dfo, "Error getting formatter pattern" ); + + INTL_METHOD_RETVAL_UTF8( dfo, value, length, ( value != value_buf ) ); +} +/* }}} */ + +/* {{{ Set formatter pattern. */ +U_CFUNC PHP_FUNCTION( datefmt_set_pattern ) +{ + char* value = nullptr; + size_t value_len = 0; + int32_t slength = 0; + UChar* svalue = nullptr; + bool is_pattern_localized = false; + + + DATE_FORMAT_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Os", + &object, IntlDateFormatter_ce_ptr, &value, &value_len ) == FAILURE ) + { + RETURN_THROWS(); + } + + DATE_FORMAT_METHOD_FETCH_OBJECT; + + /* Convert given pattern to UTF-16. */ + intl_convert_utf8_to_utf16(&svalue, &slength, value, value_len, &INTL_DATA_ERROR_CODE(dfo)); + INTL_METHOD_CHECK_STATUS(dfo, "Error converting pattern to UTF-16" ); + + udat_applyPattern(DATE_FORMAT_OBJECT(dfo), (UBool)is_pattern_localized, svalue, slength); + + if (svalue) { + efree(svalue); + } + INTL_METHOD_CHECK_STATUS(dfo, "Error setting symbol value"); + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ Get formatter locale. */ +U_CFUNC PHP_FUNCTION( datefmt_get_locale ) +{ + const char *loc; + zend_long loc_type =ULOC_ACTUAL_LOCALE; + + DATE_FORMAT_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O|l", + &object, IntlDateFormatter_ce_ptr,&loc_type) == FAILURE ) + { + + RETURN_THROWS(); + } + + /* Fetch the object. */ + DATE_FORMAT_METHOD_FETCH_OBJECT; + + loc = udat_getLocaleByType(DATE_FORMAT_OBJECT(dfo), static_cast(loc_type),&INTL_DATA_ERROR_CODE(dfo)); + INTL_METHOD_CHECK_STATUS(dfo, "Error getting locale"); + RETURN_STRING(loc); +} +/* }}} */ + +/* {{{ Get formatter isLenient. */ +U_CFUNC PHP_FUNCTION( datefmt_is_lenient ) +{ + + DATE_FORMAT_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", + &object, IntlDateFormatter_ce_ptr ) == FAILURE ) + { + + RETURN_THROWS(); + } + + /* Fetch the object. */ + DATE_FORMAT_METHOD_FETCH_OBJECT; + + RETVAL_BOOL(udat_isLenient(DATE_FORMAT_OBJECT(dfo))); +} +/* }}} */ + +/* {{{ Set formatter lenient. */ +U_CFUNC PHP_FUNCTION( datefmt_set_lenient ) +{ + bool isLenient = false; + + DATE_FORMAT_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ob", + &object, IntlDateFormatter_ce_ptr,&isLenient ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + DATE_FORMAT_METHOD_FETCH_OBJECT; + + udat_setLenient(DATE_FORMAT_OBJECT(dfo), (UBool)isLenient ); +} +/* }}} */ 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_class.c b/ext/intl/dateformat/dateformat_class.c deleted file mode 100644 index 15bf5bf23ce57..0000000000000 --- a/ext/intl/dateformat/dateformat_class.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Kirti Velankar | - +----------------------------------------------------------------------+ -*/ -#include - -#include "dateformat_class.h" -#include "php_intl.h" -#include "dateformat_data.h" -#include "dateformat.h" -#include "dateformat_arginfo.h" - -#include - -zend_class_entry *IntlDateFormatter_ce_ptr = NULL; -static zend_object_handlers IntlDateFormatter_handlers; - -/* - * Auxiliary functions needed by objects of 'IntlDateFormatter' class - */ - -/* {{{ IntlDateFormatter_objects_free */ -void IntlDateFormatter_object_free( zend_object *object ) -{ - IntlDateFormatter_object* dfo = php_intl_dateformatter_fetch_object(object); - - zend_object_std_dtor( &dfo->zo ); - - if (dfo->requested_locale) { - efree( dfo->requested_locale ); - } - - dateformat_data_free( &dfo->datef_data ); -} -/* }}} */ - -/* {{{ IntlDateFormatter_object_create */ -zend_object *IntlDateFormatter_object_create(zend_class_entry *ce) -{ - IntlDateFormatter_object* intern; - - intern = zend_object_alloc(sizeof(IntlDateFormatter_object), ce); - dateformat_data_init( &intern->datef_data ); - zend_object_std_init( &intern->zo, ce ); - object_properties_init(&intern->zo, ce); - intern->date_type = 0; - intern->time_type = 0; - intern->calendar = -1; - intern->requested_locale = NULL; - - return &intern->zo; -} -/* }}} */ - -/* {{{ IntlDateFormatter_object_clone */ -zend_object *IntlDateFormatter_object_clone(zend_object *object) -{ - IntlDateFormatter_object *dfo = php_intl_dateformatter_fetch_object(object); - zend_object *new_obj = IntlDateFormatter_ce_ptr->create_object(object->ce); - IntlDateFormatter_object *new_dfo = php_intl_dateformatter_fetch_object(new_obj); - - /* clone standard parts */ - zend_objects_clone_members(&new_dfo->zo, &dfo->zo); - - /* clone formatter object */ - if (DATE_FORMAT_OBJECT(dfo) != NULL) { - UErrorCode error = U_ZERO_ERROR; - DATE_FORMAT_OBJECT(new_dfo) = udat_clone(DATE_FORMAT_OBJECT(dfo), &error); - - if (U_FAILURE(error)) { - zend_throw_error(NULL, "Failed to clone IntlDateFormatter"); - } - } else { - zend_throw_error(NULL, "Cannot clone uninitialized IntlDateFormatter"); - } - return new_obj; -} -/* }}} */ - -/* - * 'IntlDateFormatter' class registration structures & functions - */ - -/* {{{ dateformat_register_class - * Initialize 'IntlDateFormatter' class - */ -void dateformat_register_IntlDateFormatter_class( void ) -{ - /* Create and register 'IntlDateFormatter' class. */ - IntlDateFormatter_ce_ptr = register_class_IntlDateFormatter(); - IntlDateFormatter_ce_ptr->create_object = IntlDateFormatter_object_create; - IntlDateFormatter_ce_ptr->default_object_handlers = &IntlDateFormatter_handlers; - - memcpy(&IntlDateFormatter_handlers, &std_object_handlers, - sizeof IntlDateFormatter_handlers); - IntlDateFormatter_handlers.offset = XtOffsetOf(IntlDateFormatter_object, zo); - IntlDateFormatter_handlers.clone_obj = IntlDateFormatter_object_clone; - IntlDateFormatter_handlers.free_obj = IntlDateFormatter_object_free; -} -/* }}} */ diff --git a/ext/intl/dateformat/dateformat_class.cpp b/ext/intl/dateformat/dateformat_class.cpp new file mode 100644 index 0000000000000..b6ccf97990073 --- /dev/null +++ b/ext/intl/dateformat/dateformat_class.cpp @@ -0,0 +1,111 @@ +/* + +----------------------------------------------------------------------+ + | 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: Kirti Velankar | + +----------------------------------------------------------------------+ +*/ +#include + +extern "C" { +#include "dateformat_class.h" +#include "php_intl.h" +#include "dateformat_data.h" +#include "dateformat.h" +#include "dateformat_arginfo.h" +} + +#include + +zend_class_entry *IntlDateFormatter_ce_ptr = NULL; +static zend_object_handlers IntlDateFormatter_handlers; + +/* + * Auxiliary functions needed by objects of 'IntlDateFormatter' class + */ + +/* {{{ IntlDateFormatter_objects_free */ +void IntlDateFormatter_object_free( zend_object *object ) +{ + IntlDateFormatter_object* dfo = php_intl_dateformatter_fetch_object(object); + + zend_object_std_dtor( &dfo->zo ); + + if (dfo->requested_locale) { + efree( dfo->requested_locale ); + } + + dateformat_data_free( &dfo->datef_data ); +} +/* }}} */ + +/* {{{ IntlDateFormatter_object_create */ +zend_object *IntlDateFormatter_object_create(zend_class_entry *ce) +{ + IntlDateFormatter_object* intern; + + intern = reinterpret_cast(zend_object_alloc(sizeof(IntlDateFormatter_object), ce)); + dateformat_data_init( &intern->datef_data ); + zend_object_std_init( &intern->zo, ce ); + object_properties_init(&intern->zo, ce); + intern->date_type = 0; + intern->time_type = 0; + intern->calendar = -1; + intern->requested_locale = NULL; + + return &intern->zo; +} +/* }}} */ + +/* {{{ IntlDateFormatter_object_clone */ +zend_object *IntlDateFormatter_object_clone(zend_object *object) +{ + IntlDateFormatter_object *dfo = php_intl_dateformatter_fetch_object(object); + zend_object *new_obj = IntlDateFormatter_ce_ptr->create_object(object->ce); + IntlDateFormatter_object *new_dfo = php_intl_dateformatter_fetch_object(new_obj); + + /* clone standard parts */ + zend_objects_clone_members(&new_dfo->zo, &dfo->zo); + + /* clone formatter object */ + if (DATE_FORMAT_OBJECT(dfo) != NULL) { + UErrorCode error = U_ZERO_ERROR; + DATE_FORMAT_OBJECT(new_dfo) = udat_clone(DATE_FORMAT_OBJECT(dfo), &error); + + if (U_FAILURE(error)) { + zend_throw_error(NULL, "Failed to clone IntlDateFormatter"); + } + } else { + zend_throw_error(NULL, "Cannot clone uninitialized IntlDateFormatter"); + } + return new_obj; +} +/* }}} */ + +/* + * 'IntlDateFormatter' class registration structures & functions + */ + +/* {{{ dateformat_register_class + * Initialize 'IntlDateFormatter' class + */ +void dateformat_register_IntlDateFormatter_class( void ) +{ + /* Create and register 'IntlDateFormatter' class. */ + IntlDateFormatter_ce_ptr = register_class_IntlDateFormatter(); + IntlDateFormatter_ce_ptr->create_object = IntlDateFormatter_object_create; + IntlDateFormatter_ce_ptr->default_object_handlers = &IntlDateFormatter_handlers; + + memcpy(&IntlDateFormatter_handlers, &std_object_handlers, + sizeof IntlDateFormatter_handlers); + IntlDateFormatter_handlers.offset = XtOffsetOf(IntlDateFormatter_object, zo); + IntlDateFormatter_handlers.clone_obj = IntlDateFormatter_object_clone; + IntlDateFormatter_handlers.free_obj = IntlDateFormatter_object_free; +} +/* }}} */ diff --git a/ext/intl/dateformat/dateformat_class.h b/ext/intl/dateformat/dateformat_class.h index 18afb55023b42..e722c40b4bd9f 100644 --- a/ext/intl/dateformat/dateformat_class.h +++ b/ext/intl/dateformat/dateformat_class.h @@ -16,9 +16,15 @@ #include +#ifdef __cplusplus +extern "C" { +#endif #include "intl_common.h" #include "intl_error.h" #include "intl_data.h" +#ifdef __cplusplus +} +#endif #include "dateformat_data.h" typedef struct { @@ -35,8 +41,14 @@ static inline IntlDateFormatter_object *php_intl_dateformatter_fetch_object(zend } #define Z_INTL_DATEFORMATTER_P(zv) php_intl_dateformatter_fetch_object(Z_OBJ_P(zv)) +#ifdef __cplusplus +extern "C" { +#endif void dateformat_register_IntlDateFormatter_class( void ); extern zend_class_entry *IntlDateFormatter_ce_ptr; +#ifdef __cplusplus +} +#endif /* Auxiliary macros */ 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_data.c b/ext/intl/dateformat/dateformat_data.c deleted file mode 100644 index 9c12af6fb6059..0000000000000 --- a/ext/intl/dateformat/dateformat_data.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Kirti Velankar | - +----------------------------------------------------------------------+ -*/ -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "dateformat_data.h" - -/* {{{ void dateformat_data_init( dateformat_data* datef_data ) - * Initialize internals of dateformat_data. - */ -void dateformat_data_init( dateformat_data* datef_data ) -{ - if( !datef_data ) - return; - - datef_data->udatf = NULL; - intl_error_reset( &datef_data->error ); -} -/* }}} */ - -/* {{{ void dateformat_data_free( dateformat_data* datef_data ) - * Clean up memory allocated for dateformat_data - */ -void dateformat_data_free( dateformat_data* datef_data ) -{ - if( !datef_data ) - return; - - if( datef_data->udatf ) - udat_close( datef_data->udatf ); - - datef_data->udatf = NULL; - intl_error_reset( &datef_data->error ); -} -/* }}} */ - -/* {{{ dateformat_data* dateformat_data_create() - * Allocate memory for dateformat_data and initialize it with default values. - */ -dateformat_data* dateformat_data_create( void ) -{ - dateformat_data* datef_data = ecalloc( 1, sizeof(dateformat_data) ); - - dateformat_data_init( datef_data ); - - return datef_data; -} -/* }}} */ diff --git a/ext/intl/dateformat/dateformat_data.cpp b/ext/intl/dateformat/dateformat_data.cpp new file mode 100644 index 0000000000000..42e7c9522055f --- /dev/null +++ b/ext/intl/dateformat/dateformat_data.cpp @@ -0,0 +1,60 @@ +/* + +----------------------------------------------------------------------+ + | 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: Kirti Velankar | + +----------------------------------------------------------------------+ +*/ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "dateformat_data.h" + +/* {{{ void dateformat_data_init( dateformat_data* datef_data ) + * Initialize internals of dateformat_data. + */ +void dateformat_data_init( dateformat_data* datef_data ) +{ + if( !datef_data ) + return; + + datef_data->udatf = nullptr; + intl_error_reset( &datef_data->error ); +} +/* }}} */ + +/* {{{ void dateformat_data_free( dateformat_data* datef_data ) + * Clean up memory allocated for dateformat_data + */ +void dateformat_data_free( dateformat_data* datef_data ) +{ + if( !datef_data ) + return; + + if( datef_data->udatf ) + udat_close( datef_data->udatf ); + + datef_data->udatf = nullptr; + intl_error_reset( &datef_data->error ); +} +/* }}} */ + +/* {{{ dateformat_data* dateformat_data_create() + * Allocate memory for dateformat_data and initialize it with default values. + */ +dateformat_data* dateformat_data_create( void ) +{ + dateformat_data* datef_data = reinterpret_cast(ecalloc( 1, sizeof(dateformat_data) )); + + dateformat_data_init( datef_data ); + + return datef_data; +} +/* }}} */ diff --git a/ext/intl/dateformat/dateformat_data.h b/ext/intl/dateformat/dateformat_data.h index 4007d1344fbb6..962ffbade31d8 100644 --- a/ext/intl/dateformat/dateformat_data.h +++ b/ext/intl/dateformat/dateformat_data.h @@ -18,7 +18,13 @@ #include +#ifdef __cplusplus +extern "C" { +#endif #include "intl_error.h" +#ifdef __cplusplus +} +#endif typedef struct { // error handling @@ -28,8 +34,14 @@ typedef struct { UDateFormat * udatf; } dateformat_data; +#ifdef __cplusplus +extern "C" { +#endif dateformat_data* dateformat_data_create( void ); void dateformat_data_init( dateformat_data* datef_data ); void dateformat_data_free( dateformat_data* datef_data ); +#ifdef __cplusplus +} +#endif #endif // DATE_FORMAT_DATA_H diff --git a/ext/intl/dateformat/dateformat_format.c b/ext/intl/dateformat/dateformat_format.c deleted file mode 100644 index f4ef8a40d6458..0000000000000 --- a/ext/intl/dateformat/dateformat_format.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Kirti Velankar | - +----------------------------------------------------------------------+ -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "../php_intl.h" - -#include -#include - -#include "../intl_convert.h" -#include "../common/common_date.h" -#include "dateformat.h" -#include "dateformat_class.h" -#include "dateformat_data.h" - -/* {{{ Internal function which calls the udat_format */ -static void internal_format(IntlDateFormatter_object *dfo, UDate timestamp, zval *return_value) -{ - UChar* formatted = NULL; - int32_t resultlengthneeded =0 ; - - resultlengthneeded=udat_format( DATE_FORMAT_OBJECT(dfo), timestamp, NULL, resultlengthneeded, NULL, &INTL_DATA_ERROR_CODE(dfo)); - if(INTL_DATA_ERROR_CODE(dfo)==U_BUFFER_OVERFLOW_ERROR) - { - INTL_DATA_ERROR_CODE(dfo)=U_ZERO_ERROR; - formatted=(UChar*)emalloc(sizeof(UChar) * resultlengthneeded); - udat_format( DATE_FORMAT_OBJECT(dfo), timestamp, formatted, resultlengthneeded, NULL, &INTL_DATA_ERROR_CODE(dfo)); - } - - if (formatted && U_FAILURE( INTL_DATA_ERROR_CODE(dfo) ) ) { - efree(formatted); - } - - INTL_METHOD_CHECK_STATUS( dfo, "Date formatting failed" ); - INTL_METHOD_RETVAL_UTF8( dfo, formatted, resultlengthneeded, 1 ); - -} -/* }}} */ - - -/* {{{ Internal function which fetches an element from the passed array for the key_name passed */ -static int32_t internal_get_arr_ele(IntlDateFormatter_object *dfo, - HashTable* hash_arr, char* key_name, intl_error *err) -{ - zval *ele_value = NULL; - int32_t result = 0; - char *message; - - if (U_FAILURE(err->code)) { - return result; - } - - 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 " - "a non-integer element for key '%s'", key_name); - intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, message, 1); - 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 " - "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); - efree(message); - } else { - result = Z_LVAL_P(ele_value); - } - } - } - - return result; -} -/* }}} */ - -/* {{{ Internal function which sets UCalendar from the passed array and retrieves timestamp */ -static UDate internal_get_timestamp(IntlDateFormatter_object *dfo, - HashTable *hash_arr) -{ - int32_t year, - month, - hour, - minute, - second, - mday; - UCalendar *pcal; - UDate result; - intl_error *err = &dfo->datef_data.error; - -#define INTL_GET_ELEM(elem) \ - internal_get_arr_ele(dfo, hash_arr, (elem), err) - - /* Fetch values from the incoming array */ - year = INTL_GET_ELEM(CALENDAR_YEAR) + 1900; /* tm_year is years since 1900 */ - /* Month in ICU and PHP starts from January =0 */ - month = INTL_GET_ELEM(CALENDAR_MON); - hour = INTL_GET_ELEM(CALENDAR_HOUR); - minute = INTL_GET_ELEM(CALENDAR_MIN); - second = INTL_GET_ELEM(CALENDAR_SEC); - /* For the ucal_setDateTime() function, this is the 'date' value */ - mday = INTL_GET_ELEM(CALENDAR_MDAY); - -#undef INTL_GET_ELEM - - pcal = ucal_clone(udat_getCalendar(DATE_FORMAT_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); - return 0; - } - - /* set the incoming values for the calendar */ - ucal_setDateTime(pcal, year, month, mday, hour, minute, second, &INTL_DATA_ERROR_CODE(dfo)); - /* actually, ucal_setDateTime cannot fail */ - - /* Fetch the timestamp from the UCalendar */ - result = ucal_getMillis(pcal, &INTL_DATA_ERROR_CODE(dfo)); - ucal_close(pcal); - return result; -} - - -/* {{{ Format the time value as a string. */ -PHP_FUNCTION(datefmt_format) -{ - UDate timestamp = 0; - HashTable *hash_arr = NULL; - zval *zarg = NULL; - - DATE_FORMAT_METHOD_INIT_VARS; - - /* 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(); - } - - DATE_FORMAT_METHOD_FETCH_OBJECT; - - if (Z_TYPE_P(zarg) == IS_ARRAY) { - hash_arr = Z_ARRVAL_P(zarg); - if (!hash_arr || zend_hash_num_elements(hash_arr) == 0) { - RETURN_FALSE; - } - - timestamp = internal_get_timestamp(dfo, hash_arr); - INTL_METHOD_CHECK_STATUS(dfo, "datefmt_format: date formatting failed") - } else { - timestamp = intl_zval_to_millis(zarg, INTL_DATA_ERROR_P(dfo), - "datefmt_format"); - if (U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { - RETURN_FALSE; - } - } - - internal_format( dfo, timestamp, return_value); -} - -/* }}} */ diff --git a/ext/intl/dateformat/dateformat_format.cpp b/ext/intl/dateformat/dateformat_format.cpp new file mode 100644 index 0000000000000..30570a5887c17 --- /dev/null +++ b/ext/intl/dateformat/dateformat_format.cpp @@ -0,0 +1,176 @@ +/* + +----------------------------------------------------------------------+ + | 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: Kirti Velankar | + +----------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +extern "C" { +#include "../php_intl.h" +#include "../intl_convert.h" +} + +#include "../common/common_date.h" +#include "dateformat.h" +#include "dateformat_class.h" +#include "dateformat_data.h" + +/* {{{ Internal function which calls the udat_format */ +static void internal_format(IntlDateFormatter_object *dfo, UDate timestamp, zval *return_value) +{ + UChar* formatted = NULL; + int32_t resultlengthneeded =0 ; + + resultlengthneeded=udat_format( DATE_FORMAT_OBJECT(dfo), timestamp, NULL, resultlengthneeded, NULL, &INTL_DATA_ERROR_CODE(dfo)); + if(INTL_DATA_ERROR_CODE(dfo)==U_BUFFER_OVERFLOW_ERROR) + { + INTL_DATA_ERROR_CODE(dfo)=U_ZERO_ERROR; + formatted=(UChar*)emalloc(sizeof(UChar) * resultlengthneeded); + udat_format( DATE_FORMAT_OBJECT(dfo), timestamp, formatted, resultlengthneeded, NULL, &INTL_DATA_ERROR_CODE(dfo)); + } + + if (formatted && U_FAILURE( INTL_DATA_ERROR_CODE(dfo) ) ) { + efree(formatted); + } + + INTL_METHOD_CHECK_STATUS( dfo, "Date formatting failed" ); + INTL_METHOD_RETVAL_UTF8( dfo, formatted, resultlengthneeded, 1 ); + +} +/* }}} */ + + +/* {{{ Internal function which fetches an element from the passed array for the key_name passed */ +static int32_t internal_get_arr_ele(IntlDateFormatter_object *dfo, + HashTable* hash_arr, char* key_name, intl_error *err) +{ + zval *ele_value = NULL; + int32_t result = 0; + char *message; + + if (U_FAILURE(err->code)) { + return result; + } + + 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, "parameter array contains " + "a non-integer element for key '%s'", key_name); + 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, "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); + efree(message); + } else { + result = Z_LVAL_P(ele_value); + } + } + } + + return result; +} +/* }}} */ + +/* {{{ Internal function which sets UCalendar from the passed array and retrieves timestamp */ +static UDate internal_get_timestamp(IntlDateFormatter_object *dfo, + HashTable *hash_arr) +{ + int32_t year, + month, + hour, + minute, + second, + mday; + UCalendar *pcal; + UDate result; + intl_error *err = &dfo->datef_data.error; + +#define INTL_GET_ELEM(elem) \ + internal_get_arr_ele(dfo, hash_arr, (elem), err) + + /* Fetch values from the incoming array */ + year = INTL_GET_ELEM(CALENDAR_YEAR) + 1900; /* tm_year is years since 1900 */ + /* Month in ICU and PHP starts from January =0 */ + month = INTL_GET_ELEM(CALENDAR_MON); + hour = INTL_GET_ELEM(CALENDAR_HOUR); + minute = INTL_GET_ELEM(CALENDAR_MIN); + second = INTL_GET_ELEM(CALENDAR_SEC); + /* For the ucal_setDateTime() function, this is the 'date' value */ + mday = INTL_GET_ELEM(CALENDAR_MDAY); + +#undef INTL_GET_ELEM + + pcal = ucal_clone(udat_getCalendar(DATE_FORMAT_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), "error cloning calendar"); + return 0; + } + + /* set the incoming values for the calendar */ + ucal_setDateTime(pcal, year, month, mday, hour, minute, second, &INTL_DATA_ERROR_CODE(dfo)); + /* actually, ucal_setDateTime cannot fail */ + + /* Fetch the timestamp from the UCalendar */ + result = ucal_getMillis(pcal, &INTL_DATA_ERROR_CODE(dfo)); + ucal_close(pcal); + return result; +} + + +/* {{{ Format the time value as a string. */ +U_CFUNC PHP_FUNCTION(datefmt_format) +{ + UDate timestamp = 0; + HashTable *hash_arr = NULL; + zval *zarg = NULL; + + DATE_FORMAT_METHOD_INIT_VARS; + + /* Parse parameters. */ + if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oz", + &object, IntlDateFormatter_ce_ptr, &zarg) == FAILURE) { + RETURN_THROWS(); + } + + DATE_FORMAT_METHOD_FETCH_OBJECT; + + if (Z_TYPE_P(zarg) == IS_ARRAY) { + hash_arr = Z_ARRVAL_P(zarg); + if (!hash_arr || zend_hash_num_elements(hash_arr) == 0) { + RETURN_FALSE; + } + + timestamp = internal_get_timestamp(dfo, hash_arr); + INTL_METHOD_CHECK_STATUS(dfo, "date formatting failed") + } else { + timestamp = intl_zval_to_millis(zarg, INTL_DATA_ERROR_P(dfo)); + if (U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { + RETURN_FALSE; + } + } + + internal_format( dfo, timestamp, return_value); +} + +/* }}} */ 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 deleted file mode 100644 index 2bdde08bcaced..0000000000000 --- a/ext/intl/dateformat/dateformat_parse.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Kirti Velankar | - +----------------------------------------------------------------------+ -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include "php_intl.h" -#include "intl_convert.h" -#include "dateformat.h" -#include "dateformat_class.h" -#include "dateformat_data.h" - -/* {{{ - * Internal function which calls the udat_parse - * param int store_error acts like a boolean - * if set to 1 - store any error encountered in the parameter parse_error - * if set to 0 - no need to store any error encountered in the parameter parse_error -*/ -static void internal_parse_to_timestamp(IntlDateFormatter_object *dfo, char* text_to_parse, size_t text_len, int32_t *parse_pos, bool update_calendar, zval *return_value) -{ - double result = 0; - UDate timestamp =0; - UChar* text_utf16 = NULL; - int32_t text_utf16_len = 0; - - /* Convert timezone to UTF-16. */ - intl_convert_utf8_to_utf16(&text_utf16, &text_utf16_len, text_to_parse, text_len, &INTL_DATA_ERROR_CODE(dfo)); - INTL_METHOD_CHECK_STATUS(dfo, "Error converting timezone to UTF-16" ); - - if (UNEXPECTED(update_calendar)) { - UCalendar *parsed_calendar = (UCalendar *)udat_getCalendar(DATE_FORMAT_OBJECT(dfo)); - udat_parseCalendar(DATE_FORMAT_OBJECT(dfo), parsed_calendar, text_utf16, text_utf16_len, parse_pos, &INTL_DATA_ERROR_CODE(dfo)); - if (text_utf16) { - efree(text_utf16); - } - INTL_METHOD_CHECK_STATUS( dfo, "Calendar parsing failed" ); - timestamp = ucal_getMillis( parsed_calendar, &INTL_DATA_ERROR_CODE(dfo)); - } else { - timestamp = udat_parse(DATE_FORMAT_OBJECT(dfo), text_utf16, text_utf16_len, parse_pos, &INTL_DATA_ERROR_CODE(dfo)); - if (text_utf16) { - efree(text_utf16); - } - } - - INTL_METHOD_CHECK_STATUS( dfo, "Date parsing failed" ); - /* Since return is in sec. */ - result = (double)timestamp / U_MILLIS_PER_SECOND; - if (result > (double)LONG_MAX || result < (double)LONG_MIN) { - ZVAL_DOUBLE(return_value, result<0?ceil(result):floor(result)); - } else { - ZVAL_LONG(return_value, (zend_long)result); - } -} -/* }}} */ - -static void add_to_localtime_arr( IntlDateFormatter_object *dfo, zval* return_value, const UCalendar *parsed_calendar, zend_long calendar_field, char* key_name) -{ - zend_long calendar_field_val = ucal_get( parsed_calendar, calendar_field, &INTL_DATA_ERROR_CODE(dfo)); - INTL_METHOD_CHECK_STATUS( dfo, "Date parsing - localtime failed : could not get a field from calendar" ); - - if( strcmp(key_name, CALENDAR_YEAR )==0 ){ - /* since tm_year is years from 1900 */ - add_assoc_long( return_value, key_name,( calendar_field_val-1900) ); - }else if( strcmp(key_name, CALENDAR_WDAY )==0 ){ - /* since tm_wday starts from 0 whereas ICU WDAY start from 1 */ - add_assoc_long( return_value, key_name,( calendar_field_val-1) ); - }else{ - add_assoc_long( return_value, key_name, calendar_field_val ); - } -} - -/* {{{ Internal function which calls the udat_parseCalendar */ -static void internal_parse_to_localtime(IntlDateFormatter_object *dfo, char* text_to_parse, size_t text_len, int32_t *parse_pos, zval *return_value) -{ - UCalendar *parsed_calendar = NULL; - UChar* text_utf16 = NULL; - int32_t text_utf16_len = 0; - zend_long isInDST = 0; - - /* Convert timezone to UTF-16. */ - intl_convert_utf8_to_utf16(&text_utf16, &text_utf16_len, text_to_parse, text_len, &INTL_DATA_ERROR_CODE(dfo)); - INTL_METHOD_CHECK_STATUS(dfo, "Error converting timezone to UTF-16" ); - - parsed_calendar = (UCalendar *)udat_getCalendar(DATE_FORMAT_OBJECT(dfo)); - udat_parseCalendar( DATE_FORMAT_OBJECT(dfo), parsed_calendar, text_utf16, text_utf16_len, parse_pos, &INTL_DATA_ERROR_CODE(dfo)); - - if (text_utf16) { - efree(text_utf16); - } - - INTL_METHOD_CHECK_STATUS( dfo, "Date parsing failed" ); - - - array_init( return_value ); - /* Add entries from various fields of the obtained parsed_calendar */ - add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_SECOND, CALENDAR_SEC); - add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_MINUTE, CALENDAR_MIN); - add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_HOUR_OF_DAY, CALENDAR_HOUR); - add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_YEAR, CALENDAR_YEAR); - add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_DAY_OF_MONTH, CALENDAR_MDAY); - add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_DAY_OF_WEEK, CALENDAR_WDAY); - add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_DAY_OF_YEAR, CALENDAR_YDAY); - add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_MONTH, CALENDAR_MON); - - /* Is in DST? */ - isInDST = ucal_inDaylightTime(parsed_calendar , &INTL_DATA_ERROR_CODE(dfo)); - INTL_METHOD_CHECK_STATUS( dfo, "Date parsing - localtime failed : while checking if currently in DST." ); - add_assoc_long( return_value, CALENDAR_ISDST,isInDST==1); -} -/* }}} */ - - -/* {{{ Parse the string $value starting at parse_pos to a Unix timestamp -int */ -PHP_FUNCTION(datefmt_parse) -{ - char* text_to_parse = NULL; - size_t text_len =0; - zval* z_parse_pos = NULL; - int32_t parse_pos = -1; - - DATE_FORMAT_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Os|z!", - &object, IntlDateFormatter_ce_ptr, &text_to_parse, &text_len, &z_parse_pos ) == FAILURE ){ - RETURN_THROWS(); - } - - /* Fetch the object. */ - DATE_FORMAT_METHOD_FETCH_OBJECT; - - if (z_parse_pos) { - zval *z_parse_pos_tmp = z_parse_pos; - ZVAL_DEREF(z_parse_pos_tmp); - 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); - RETURN_FALSE; - } - parse_pos = (int32_t)long_parse_pos; - if ((size_t)parse_pos > text_len) { - RETURN_FALSE; - } - } - internal_parse_to_timestamp( dfo, text_to_parse, text_len, z_parse_pos ? &parse_pos : NULL, false, return_value); - if (z_parse_pos) { - ZEND_TRY_ASSIGN_REF_LONG(z_parse_pos, parse_pos); - } -} -/* }}} */ - -PHP_METHOD(IntlDateFormatter, parseToCalendar) -{ - zend_string *text_to_parse = NULL; - zval* z_parse_pos = NULL; - int32_t parse_pos = -1; - - DATE_FORMAT_METHOD_INIT_VARS; - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_STR(text_to_parse) - Z_PARAM_OPTIONAL - Z_PARAM_ZVAL(z_parse_pos) - ZEND_PARSE_PARAMETERS_END(); - - object = ZEND_THIS; - - /* Fetch the object. */ - DATE_FORMAT_METHOD_FETCH_OBJECT; - - if (z_parse_pos) { - bool failed; - zend_long long_parse_pos = zval_try_get_long(z_parse_pos, &failed); - if (failed) { - zend_argument_type_error(2, "must be of type int, %s given", zend_zval_value_name(z_parse_pos)); - RETURN_THROWS(); - } - 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); - RETURN_FALSE; - } - parse_pos = (int32_t)long_parse_pos; - if (parse_pos != -1 && (size_t)parse_pos > ZSTR_LEN(text_to_parse)) { - RETURN_FALSE; - } - } - internal_parse_to_timestamp( dfo, ZSTR_VAL(text_to_parse), ZSTR_LEN(text_to_parse), z_parse_pos ? &parse_pos : NULL, true, return_value); - if (z_parse_pos) { - ZEND_TRY_ASSIGN_REF_LONG(z_parse_pos, parse_pos); - } -} - -/* {{{ Parse the string $value to a localtime array */ -PHP_FUNCTION(datefmt_localtime) -{ - char* text_to_parse = NULL; - size_t text_len =0; - zval* z_parse_pos = NULL; - int32_t parse_pos = -1; - - DATE_FORMAT_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Os|z!", - &object, IntlDateFormatter_ce_ptr, &text_to_parse, &text_len, &z_parse_pos ) == FAILURE ){ - RETURN_THROWS(); - } - - /* Fetch the object. */ - DATE_FORMAT_METHOD_FETCH_OBJECT; - - if (z_parse_pos) { - zval *z_parse_pos_tmp = z_parse_pos; - ZVAL_DEREF(z_parse_pos_tmp); - 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); - RETURN_FALSE; - } - parse_pos = (int32_t)long_parse_pos; - if((size_t)parse_pos > text_len) { - RETURN_FALSE; - } - } - internal_parse_to_localtime( dfo, text_to_parse, text_len, z_parse_pos?&parse_pos:NULL, return_value); - if (z_parse_pos) { - ZEND_TRY_ASSIGN_REF_LONG(z_parse_pos, parse_pos); - } -} -/* }}} */ diff --git a/ext/intl/dateformat/dateformat_parse.cpp b/ext/intl/dateformat/dateformat_parse.cpp new file mode 100644 index 0000000000000..a82a20a42f969 --- /dev/null +++ b/ext/intl/dateformat/dateformat_parse.cpp @@ -0,0 +1,250 @@ +/* + +----------------------------------------------------------------------+ + | 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: Kirti Velankar | + +----------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +extern "C" { +#include "php_intl.h" +#include "intl_convert.h" +} +#include "dateformat.h" +#include "dateformat_class.h" +#include "dateformat_data.h" + +/* {{{ + * Internal function which calls the udat_parse + * param int store_error acts like a boolean + * if set to 1 - store any error encountered in the parameter parse_error + * if set to 0 - no need to store any error encountered in the parameter parse_error +*/ +static void internal_parse_to_timestamp(IntlDateFormatter_object *dfo, char* text_to_parse, size_t text_len, int32_t *parse_pos, bool update_calendar, zval *return_value) +{ + double result = 0; + UDate timestamp =0; + UChar* text_utf16 = NULL; + int32_t text_utf16_len = 0; + + /* Convert timezone to UTF-16. */ + intl_convert_utf8_to_utf16(&text_utf16, &text_utf16_len, text_to_parse, text_len, &INTL_DATA_ERROR_CODE(dfo)); + INTL_METHOD_CHECK_STATUS(dfo, "Error converting timezone to UTF-16" ); + + if (UNEXPECTED(update_calendar)) { + UCalendar *parsed_calendar = (UCalendar *)udat_getCalendar(DATE_FORMAT_OBJECT(dfo)); + udat_parseCalendar(DATE_FORMAT_OBJECT(dfo), parsed_calendar, text_utf16, text_utf16_len, parse_pos, &INTL_DATA_ERROR_CODE(dfo)); + if (text_utf16) { + efree(text_utf16); + } + INTL_METHOD_CHECK_STATUS( dfo, "Calendar parsing failed" ); + timestamp = ucal_getMillis( parsed_calendar, &INTL_DATA_ERROR_CODE(dfo)); + } else { + timestamp = udat_parse(DATE_FORMAT_OBJECT(dfo), text_utf16, text_utf16_len, parse_pos, &INTL_DATA_ERROR_CODE(dfo)); + if (text_utf16) { + efree(text_utf16); + } + } + + INTL_METHOD_CHECK_STATUS( dfo, "Date parsing failed" ); + /* Since return is in sec. */ + result = (double)timestamp / U_MILLIS_PER_SECOND; + if (result > (double)LONG_MAX || result < (double)LONG_MIN) { + ZVAL_DOUBLE(return_value, result<0?ceil(result):floor(result)); + } else { + ZVAL_LONG(return_value, (zend_long)result); + } +} +/* }}} */ + +static void add_to_localtime_arr( IntlDateFormatter_object *dfo, zval* return_value, const UCalendar *parsed_calendar, zend_long calendar_field, char* key_name) +{ + zend_long calendar_field_val = ucal_get( parsed_calendar, static_cast(calendar_field), &INTL_DATA_ERROR_CODE(dfo)); + INTL_METHOD_CHECK_STATUS( dfo, "Date parsing - localtime failed : could not get a field from calendar" ); + + if( strcmp(key_name, CALENDAR_YEAR )==0 ){ + /* since tm_year is years from 1900 */ + add_assoc_long( return_value, key_name,( calendar_field_val-1900) ); + }else if( strcmp(key_name, CALENDAR_WDAY )==0 ){ + /* since tm_wday starts from 0 whereas ICU WDAY start from 1 */ + add_assoc_long( return_value, key_name,( calendar_field_val-1) ); + }else{ + add_assoc_long( return_value, key_name, calendar_field_val ); + } +} + +/* {{{ Internal function which calls the udat_parseCalendar */ +static void internal_parse_to_localtime(IntlDateFormatter_object *dfo, char* text_to_parse, size_t text_len, int32_t *parse_pos, zval *return_value) +{ + UCalendar *parsed_calendar = NULL; + UChar* text_utf16 = NULL; + int32_t text_utf16_len = 0; + zend_long isInDST = 0; + + /* Convert timezone to UTF-16. */ + intl_convert_utf8_to_utf16(&text_utf16, &text_utf16_len, text_to_parse, text_len, &INTL_DATA_ERROR_CODE(dfo)); + INTL_METHOD_CHECK_STATUS(dfo, "Error converting timezone to UTF-16" ); + + parsed_calendar = (UCalendar *)udat_getCalendar(DATE_FORMAT_OBJECT(dfo)); + udat_parseCalendar( DATE_FORMAT_OBJECT(dfo), parsed_calendar, text_utf16, text_utf16_len, parse_pos, &INTL_DATA_ERROR_CODE(dfo)); + + if (text_utf16) { + efree(text_utf16); + } + + INTL_METHOD_CHECK_STATUS( dfo, "Date parsing failed" ); + + + array_init( return_value ); + /* Add entries from various fields of the obtained parsed_calendar */ + add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_SECOND, CALENDAR_SEC); + add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_MINUTE, CALENDAR_MIN); + add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_HOUR_OF_DAY, CALENDAR_HOUR); + add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_YEAR, CALENDAR_YEAR); + add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_DAY_OF_MONTH, CALENDAR_MDAY); + add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_DAY_OF_WEEK, CALENDAR_WDAY); + add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_DAY_OF_YEAR, CALENDAR_YDAY); + add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_MONTH, CALENDAR_MON); + + /* Is in DST? */ + isInDST = ucal_inDaylightTime(parsed_calendar , &INTL_DATA_ERROR_CODE(dfo)); + INTL_METHOD_CHECK_STATUS( dfo, "Date parsing - localtime failed : while checking if currently in DST." ); + add_assoc_long( return_value, CALENDAR_ISDST,isInDST==1); +} +/* }}} */ + + +/* {{{ Parse the string $value starting at parse_pos to a Unix timestamp -int */ +U_CFUNC PHP_FUNCTION(datefmt_parse) +{ + char* text_to_parse = NULL; + size_t text_len =0; + zval* z_parse_pos = NULL; + int32_t parse_pos = -1; + + DATE_FORMAT_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Os|z!", + &object, IntlDateFormatter_ce_ptr, &text_to_parse, &text_len, &z_parse_pos ) == FAILURE ){ + RETURN_THROWS(); + } + + /* Fetch the object. */ + DATE_FORMAT_METHOD_FETCH_OBJECT; + + if (z_parse_pos) { + zval *z_parse_pos_tmp = z_parse_pos; + ZVAL_DEREF(z_parse_pos_tmp); + 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."); + RETURN_FALSE; + } + parse_pos = (int32_t)long_parse_pos; + if ((size_t)parse_pos > text_len) { + RETURN_FALSE; + } + } + internal_parse_to_timestamp( dfo, text_to_parse, text_len, z_parse_pos ? &parse_pos : NULL, false, return_value); + if (z_parse_pos) { + ZEND_TRY_ASSIGN_REF_LONG(z_parse_pos, parse_pos); + } +} +/* }}} */ + +U_CFUNC PHP_METHOD(IntlDateFormatter, parseToCalendar) +{ + zend_string *text_to_parse = NULL; + zval* z_parse_pos = NULL; + int32_t parse_pos = -1; + + DATE_FORMAT_METHOD_INIT_VARS; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STR(text_to_parse) + Z_PARAM_OPTIONAL + Z_PARAM_ZVAL(z_parse_pos) + ZEND_PARSE_PARAMETERS_END(); + + object = ZEND_THIS; + + /* Fetch the object. */ + DATE_FORMAT_METHOD_FETCH_OBJECT; + + if (z_parse_pos) { + bool failed; + zend_long long_parse_pos = zval_try_get_long(z_parse_pos, &failed); + if (failed) { + zend_argument_type_error(2, "must be of type int, %s given", zend_zval_value_name(z_parse_pos)); + RETURN_THROWS(); + } + 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."); + RETURN_FALSE; + } + parse_pos = (int32_t)long_parse_pos; + if (parse_pos != -1 && (size_t)parse_pos > ZSTR_LEN(text_to_parse)) { + RETURN_FALSE; + } + } + internal_parse_to_timestamp( dfo, ZSTR_VAL(text_to_parse), ZSTR_LEN(text_to_parse), z_parse_pos ? &parse_pos : NULL, true, return_value); + if (z_parse_pos) { + ZEND_TRY_ASSIGN_REF_LONG(z_parse_pos, parse_pos); + } +} + +/* {{{ Parse the string $value to a localtime array */ +U_CFUNC PHP_FUNCTION(datefmt_localtime) +{ + char* text_to_parse = NULL; + size_t text_len =0; + zval* z_parse_pos = NULL; + int32_t parse_pos = -1; + + DATE_FORMAT_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Os|z!", + &object, IntlDateFormatter_ce_ptr, &text_to_parse, &text_len, &z_parse_pos ) == FAILURE ){ + RETURN_THROWS(); + } + + /* Fetch the object. */ + DATE_FORMAT_METHOD_FETCH_OBJECT; + + if (z_parse_pos) { + zval *z_parse_pos_tmp = z_parse_pos; + ZVAL_DEREF(z_parse_pos_tmp); + 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."); + RETURN_FALSE; + } + parse_pos = (int32_t)long_parse_pos; + if((size_t)parse_pos > text_len) { + RETURN_FALSE; + } + } + internal_parse_to_localtime( dfo, text_to_parse, text_len, z_parse_pos?&parse_pos:NULL, return_value); + if (z_parse_pos) { + ZEND_TRY_ASSIGN_REF_LONG(z_parse_pos, 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 ce9de964e77b1..df111763f8b96 100644 --- a/ext/intl/formatter/formatter_arginfo.h +++ b/ext/intl/formatter/formatter_arginfo.h @@ -127,503 +127,503 @@ static zend_class_entry *register_class_NumberFormatter(void) zval const_PATTERN_DECIMAL_value; ZVAL_LONG(&const_PATTERN_DECIMAL_value, UNUM_PATTERN_DECIMAL); - zend_string *const_PATTERN_DECIMAL_name = zend_string_init_interned("PATTERN_DECIMAL", sizeof("PATTERN_DECIMAL") - 1, 1); + zend_string *const_PATTERN_DECIMAL_name = zend_string_init_interned("PATTERN_DECIMAL", sizeof("PATTERN_DECIMAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_PATTERN_DECIMAL_name, &const_PATTERN_DECIMAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PATTERN_DECIMAL_name); + zend_string_release_ex(const_PATTERN_DECIMAL_name, true); zval const_DECIMAL_value; ZVAL_LONG(&const_DECIMAL_value, UNUM_DECIMAL); - zend_string *const_DECIMAL_name = zend_string_init_interned("DECIMAL", sizeof("DECIMAL") - 1, 1); + zend_string *const_DECIMAL_name = zend_string_init_interned("DECIMAL", sizeof("DECIMAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_DECIMAL_name, &const_DECIMAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DECIMAL_name); + zend_string_release_ex(const_DECIMAL_name, true); zval const_DECIMAL_COMPACT_SHORT_value; ZVAL_LONG(&const_DECIMAL_COMPACT_SHORT_value, UNUM_DECIMAL_COMPACT_SHORT); - zend_string *const_DECIMAL_COMPACT_SHORT_name = zend_string_init_interned("DECIMAL_COMPACT_SHORT", sizeof("DECIMAL_COMPACT_SHORT") - 1, 1); + zend_string *const_DECIMAL_COMPACT_SHORT_name = zend_string_init_interned("DECIMAL_COMPACT_SHORT", sizeof("DECIMAL_COMPACT_SHORT") - 1, true); zend_declare_typed_class_constant(class_entry, const_DECIMAL_COMPACT_SHORT_name, &const_DECIMAL_COMPACT_SHORT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DECIMAL_COMPACT_SHORT_name); + zend_string_release_ex(const_DECIMAL_COMPACT_SHORT_name, true); zval const_DECIMAL_COMPACT_LONG_value; ZVAL_LONG(&const_DECIMAL_COMPACT_LONG_value, UNUM_DECIMAL_COMPACT_LONG); - zend_string *const_DECIMAL_COMPACT_LONG_name = zend_string_init_interned("DECIMAL_COMPACT_LONG", sizeof("DECIMAL_COMPACT_LONG") - 1, 1); + zend_string *const_DECIMAL_COMPACT_LONG_name = zend_string_init_interned("DECIMAL_COMPACT_LONG", sizeof("DECIMAL_COMPACT_LONG") - 1, true); zend_declare_typed_class_constant(class_entry, const_DECIMAL_COMPACT_LONG_name, &const_DECIMAL_COMPACT_LONG_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DECIMAL_COMPACT_LONG_name); + zend_string_release_ex(const_DECIMAL_COMPACT_LONG_name, true); zval const_CURRENCY_value; ZVAL_LONG(&const_CURRENCY_value, UNUM_CURRENCY); - zend_string *const_CURRENCY_name = zend_string_init_interned("CURRENCY", sizeof("CURRENCY") - 1, 1); + zend_string *const_CURRENCY_name = zend_string_init_interned("CURRENCY", sizeof("CURRENCY") - 1, true); zend_declare_typed_class_constant(class_entry, const_CURRENCY_name, &const_CURRENCY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CURRENCY_name); + zend_string_release_ex(const_CURRENCY_name, true); zval const_PERCENT_value; ZVAL_LONG(&const_PERCENT_value, UNUM_PERCENT); - zend_string *const_PERCENT_name = zend_string_init_interned("PERCENT", sizeof("PERCENT") - 1, 1); + zend_string *const_PERCENT_name = zend_string_init_interned("PERCENT", sizeof("PERCENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PERCENT_name, &const_PERCENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PERCENT_name); + zend_string_release_ex(const_PERCENT_name, true); zval const_SCIENTIFIC_value; ZVAL_LONG(&const_SCIENTIFIC_value, UNUM_SCIENTIFIC); - zend_string *const_SCIENTIFIC_name = zend_string_init_interned("SCIENTIFIC", sizeof("SCIENTIFIC") - 1, 1); + zend_string *const_SCIENTIFIC_name = zend_string_init_interned("SCIENTIFIC", sizeof("SCIENTIFIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_SCIENTIFIC_name, &const_SCIENTIFIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SCIENTIFIC_name); + zend_string_release_ex(const_SCIENTIFIC_name, true); zval const_SPELLOUT_value; ZVAL_LONG(&const_SPELLOUT_value, UNUM_SPELLOUT); - zend_string *const_SPELLOUT_name = zend_string_init_interned("SPELLOUT", sizeof("SPELLOUT") - 1, 1); + zend_string *const_SPELLOUT_name = zend_string_init_interned("SPELLOUT", sizeof("SPELLOUT") - 1, true); zend_declare_typed_class_constant(class_entry, const_SPELLOUT_name, &const_SPELLOUT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SPELLOUT_name); + zend_string_release_ex(const_SPELLOUT_name, true); zval const_ORDINAL_value; ZVAL_LONG(&const_ORDINAL_value, UNUM_ORDINAL); - zend_string *const_ORDINAL_name = zend_string_init_interned("ORDINAL", sizeof("ORDINAL") - 1, 1); + zend_string *const_ORDINAL_name = zend_string_init_interned("ORDINAL", sizeof("ORDINAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_ORDINAL_name, &const_ORDINAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ORDINAL_name); + zend_string_release_ex(const_ORDINAL_name, true); zval const_DURATION_value; ZVAL_LONG(&const_DURATION_value, UNUM_DURATION); - zend_string *const_DURATION_name = zend_string_init_interned("DURATION", sizeof("DURATION") - 1, 1); + zend_string *const_DURATION_name = zend_string_init_interned("DURATION", sizeof("DURATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_DURATION_name, &const_DURATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DURATION_name); + zend_string_release_ex(const_DURATION_name, true); zval const_PATTERN_RULEBASED_value; ZVAL_LONG(&const_PATTERN_RULEBASED_value, UNUM_PATTERN_RULEBASED); - zend_string *const_PATTERN_RULEBASED_name = zend_string_init_interned("PATTERN_RULEBASED", sizeof("PATTERN_RULEBASED") - 1, 1); + zend_string *const_PATTERN_RULEBASED_name = zend_string_init_interned("PATTERN_RULEBASED", sizeof("PATTERN_RULEBASED") - 1, true); zend_declare_typed_class_constant(class_entry, const_PATTERN_RULEBASED_name, &const_PATTERN_RULEBASED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PATTERN_RULEBASED_name); + zend_string_release_ex(const_PATTERN_RULEBASED_name, true); zval const_IGNORE_value; ZVAL_LONG(&const_IGNORE_value, UNUM_IGNORE); - zend_string *const_IGNORE_name = zend_string_init_interned("IGNORE", sizeof("IGNORE") - 1, 1); + zend_string *const_IGNORE_name = zend_string_init_interned("IGNORE", sizeof("IGNORE") - 1, true); zend_declare_typed_class_constant(class_entry, const_IGNORE_name, &const_IGNORE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IGNORE_name); + zend_string_release_ex(const_IGNORE_name, true); zval const_CURRENCY_ISO_value; ZVAL_LONG(&const_CURRENCY_ISO_value, UNUM_CURRENCY_ISO); - zend_string *const_CURRENCY_ISO_name = zend_string_init_interned("CURRENCY_ISO", sizeof("CURRENCY_ISO") - 1, 1); + zend_string *const_CURRENCY_ISO_name = zend_string_init_interned("CURRENCY_ISO", sizeof("CURRENCY_ISO") - 1, true); zend_declare_typed_class_constant(class_entry, const_CURRENCY_ISO_name, &const_CURRENCY_ISO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CURRENCY_ISO_name); + zend_string_release_ex(const_CURRENCY_ISO_name, true); zval const_CURRENCY_PLURAL_value; ZVAL_LONG(&const_CURRENCY_PLURAL_value, UNUM_CURRENCY_PLURAL); - zend_string *const_CURRENCY_PLURAL_name = zend_string_init_interned("CURRENCY_PLURAL", sizeof("CURRENCY_PLURAL") - 1, 1); + zend_string *const_CURRENCY_PLURAL_name = zend_string_init_interned("CURRENCY_PLURAL", sizeof("CURRENCY_PLURAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_CURRENCY_PLURAL_name, &const_CURRENCY_PLURAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CURRENCY_PLURAL_name); + zend_string_release_ex(const_CURRENCY_PLURAL_name, true); zval const_CURRENCY_ACCOUNTING_value; ZVAL_LONG(&const_CURRENCY_ACCOUNTING_value, UNUM_CURRENCY_ACCOUNTING); - zend_string *const_CURRENCY_ACCOUNTING_name = zend_string_init_interned("CURRENCY_ACCOUNTING", sizeof("CURRENCY_ACCOUNTING") - 1, 1); + zend_string *const_CURRENCY_ACCOUNTING_name = zend_string_init_interned("CURRENCY_ACCOUNTING", sizeof("CURRENCY_ACCOUNTING") - 1, true); zend_declare_typed_class_constant(class_entry, const_CURRENCY_ACCOUNTING_name, &const_CURRENCY_ACCOUNTING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CURRENCY_ACCOUNTING_name); + zend_string_release_ex(const_CURRENCY_ACCOUNTING_name, true); zval const_CASH_CURRENCY_value; ZVAL_LONG(&const_CASH_CURRENCY_value, UNUM_CASH_CURRENCY); - zend_string *const_CASH_CURRENCY_name = zend_string_init_interned("CASH_CURRENCY", sizeof("CASH_CURRENCY") - 1, 1); + zend_string *const_CASH_CURRENCY_name = zend_string_init_interned("CASH_CURRENCY", sizeof("CASH_CURRENCY") - 1, true); zend_declare_typed_class_constant(class_entry, const_CASH_CURRENCY_name, &const_CASH_CURRENCY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CASH_CURRENCY_name); + zend_string_release_ex(const_CASH_CURRENCY_name, true); zval const_CURRENCY_STANDARD_value; ZVAL_LONG(&const_CURRENCY_STANDARD_value, UNUM_CURRENCY_STANDARD); - zend_string *const_CURRENCY_STANDARD_name = zend_string_init_interned("CURRENCY_STANDARD", sizeof("CURRENCY_STANDARD") - 1, 1); + zend_string *const_CURRENCY_STANDARD_name = zend_string_init_interned("CURRENCY_STANDARD", sizeof("CURRENCY_STANDARD") - 1, true); zend_declare_typed_class_constant(class_entry, const_CURRENCY_STANDARD_name, &const_CURRENCY_STANDARD_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CURRENCY_STANDARD_name); + zend_string_release_ex(const_CURRENCY_STANDARD_name, true); zval const_DEFAULT_STYLE_value; ZVAL_LONG(&const_DEFAULT_STYLE_value, UNUM_DEFAULT); - zend_string *const_DEFAULT_STYLE_name = zend_string_init_interned("DEFAULT_STYLE", sizeof("DEFAULT_STYLE") - 1, 1); + zend_string *const_DEFAULT_STYLE_name = zend_string_init_interned("DEFAULT_STYLE", sizeof("DEFAULT_STYLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_DEFAULT_STYLE_name, &const_DEFAULT_STYLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DEFAULT_STYLE_name); + zend_string_release_ex(const_DEFAULT_STYLE_name, true); zval const_ROUND_CEILING_value; ZVAL_LONG(&const_ROUND_CEILING_value, UNUM_ROUND_CEILING); - zend_string *const_ROUND_CEILING_name = zend_string_init_interned("ROUND_CEILING", sizeof("ROUND_CEILING") - 1, 1); + zend_string *const_ROUND_CEILING_name = zend_string_init_interned("ROUND_CEILING", sizeof("ROUND_CEILING") - 1, true); zend_declare_typed_class_constant(class_entry, const_ROUND_CEILING_name, &const_ROUND_CEILING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ROUND_CEILING_name); + zend_string_release_ex(const_ROUND_CEILING_name, true); zval const_ROUND_FLOOR_value; ZVAL_LONG(&const_ROUND_FLOOR_value, UNUM_ROUND_FLOOR); - zend_string *const_ROUND_FLOOR_name = zend_string_init_interned("ROUND_FLOOR", sizeof("ROUND_FLOOR") - 1, 1); + zend_string *const_ROUND_FLOOR_name = zend_string_init_interned("ROUND_FLOOR", sizeof("ROUND_FLOOR") - 1, true); zend_declare_typed_class_constant(class_entry, const_ROUND_FLOOR_name, &const_ROUND_FLOOR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ROUND_FLOOR_name); + zend_string_release_ex(const_ROUND_FLOOR_name, true); zval const_ROUND_DOWN_value; ZVAL_LONG(&const_ROUND_DOWN_value, UNUM_ROUND_DOWN); - zend_string *const_ROUND_DOWN_name = zend_string_init_interned("ROUND_DOWN", sizeof("ROUND_DOWN") - 1, 1); + zend_string *const_ROUND_DOWN_name = zend_string_init_interned("ROUND_DOWN", sizeof("ROUND_DOWN") - 1, true); zend_declare_typed_class_constant(class_entry, const_ROUND_DOWN_name, &const_ROUND_DOWN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ROUND_DOWN_name); + zend_string_release_ex(const_ROUND_DOWN_name, true); zval const_ROUND_UP_value; ZVAL_LONG(&const_ROUND_UP_value, UNUM_ROUND_UP); - zend_string *const_ROUND_UP_name = zend_string_init_interned("ROUND_UP", sizeof("ROUND_UP") - 1, 1); + zend_string *const_ROUND_UP_name = zend_string_init_interned("ROUND_UP", sizeof("ROUND_UP") - 1, true); zend_declare_typed_class_constant(class_entry, const_ROUND_UP_name, &const_ROUND_UP_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ROUND_UP_name); + zend_string_release_ex(const_ROUND_UP_name, true); zval const_ROUND_TOWARD_ZERO_value; ZVAL_LONG(&const_ROUND_TOWARD_ZERO_value, UNUM_ROUND_DOWN); - zend_string *const_ROUND_TOWARD_ZERO_name = zend_string_init_interned("ROUND_TOWARD_ZERO", sizeof("ROUND_TOWARD_ZERO") - 1, 1); + zend_string *const_ROUND_TOWARD_ZERO_name = zend_string_init_interned("ROUND_TOWARD_ZERO", sizeof("ROUND_TOWARD_ZERO") - 1, true); zend_declare_typed_class_constant(class_entry, const_ROUND_TOWARD_ZERO_name, &const_ROUND_TOWARD_ZERO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ROUND_TOWARD_ZERO_name); + zend_string_release_ex(const_ROUND_TOWARD_ZERO_name, true); zval const_ROUND_AWAY_FROM_ZERO_value; ZVAL_LONG(&const_ROUND_AWAY_FROM_ZERO_value, UNUM_ROUND_UP); - zend_string *const_ROUND_AWAY_FROM_ZERO_name = zend_string_init_interned("ROUND_AWAY_FROM_ZERO", sizeof("ROUND_AWAY_FROM_ZERO") - 1, 1); + zend_string *const_ROUND_AWAY_FROM_ZERO_name = zend_string_init_interned("ROUND_AWAY_FROM_ZERO", sizeof("ROUND_AWAY_FROM_ZERO") - 1, true); zend_declare_typed_class_constant(class_entry, const_ROUND_AWAY_FROM_ZERO_name, &const_ROUND_AWAY_FROM_ZERO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ROUND_AWAY_FROM_ZERO_name); + zend_string_release_ex(const_ROUND_AWAY_FROM_ZERO_name, true); zval const_ROUND_HALFEVEN_value; ZVAL_LONG(&const_ROUND_HALFEVEN_value, UNUM_ROUND_HALFEVEN); - zend_string *const_ROUND_HALFEVEN_name = zend_string_init_interned("ROUND_HALFEVEN", sizeof("ROUND_HALFEVEN") - 1, 1); + zend_string *const_ROUND_HALFEVEN_name = zend_string_init_interned("ROUND_HALFEVEN", sizeof("ROUND_HALFEVEN") - 1, true); zend_declare_typed_class_constant(class_entry, const_ROUND_HALFEVEN_name, &const_ROUND_HALFEVEN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ROUND_HALFEVEN_name); + zend_string_release_ex(const_ROUND_HALFEVEN_name, true); #if U_ICU_VERSION_MAJOR_NUM >= 69 zval const_ROUND_HALFODD_value; ZVAL_LONG(&const_ROUND_HALFODD_value, UNUM_ROUND_HALF_ODD); - zend_string *const_ROUND_HALFODD_name = zend_string_init_interned("ROUND_HALFODD", sizeof("ROUND_HALFODD") - 1, 1); + zend_string *const_ROUND_HALFODD_name = zend_string_init_interned("ROUND_HALFODD", sizeof("ROUND_HALFODD") - 1, true); zend_declare_typed_class_constant(class_entry, const_ROUND_HALFODD_name, &const_ROUND_HALFODD_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ROUND_HALFODD_name); + zend_string_release_ex(const_ROUND_HALFODD_name, true); #endif zval const_ROUND_HALFDOWN_value; ZVAL_LONG(&const_ROUND_HALFDOWN_value, UNUM_ROUND_HALFDOWN); - zend_string *const_ROUND_HALFDOWN_name = zend_string_init_interned("ROUND_HALFDOWN", sizeof("ROUND_HALFDOWN") - 1, 1); + zend_string *const_ROUND_HALFDOWN_name = zend_string_init_interned("ROUND_HALFDOWN", sizeof("ROUND_HALFDOWN") - 1, true); zend_declare_typed_class_constant(class_entry, const_ROUND_HALFDOWN_name, &const_ROUND_HALFDOWN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ROUND_HALFDOWN_name); + zend_string_release_ex(const_ROUND_HALFDOWN_name, true); zval const_ROUND_HALFUP_value; ZVAL_LONG(&const_ROUND_HALFUP_value, UNUM_ROUND_HALFUP); - zend_string *const_ROUND_HALFUP_name = zend_string_init_interned("ROUND_HALFUP", sizeof("ROUND_HALFUP") - 1, 1); + zend_string *const_ROUND_HALFUP_name = zend_string_init_interned("ROUND_HALFUP", sizeof("ROUND_HALFUP") - 1, true); zend_declare_typed_class_constant(class_entry, const_ROUND_HALFUP_name, &const_ROUND_HALFUP_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ROUND_HALFUP_name); + zend_string_release_ex(const_ROUND_HALFUP_name, true); zval const_PAD_BEFORE_PREFIX_value; ZVAL_LONG(&const_PAD_BEFORE_PREFIX_value, UNUM_PAD_BEFORE_PREFIX); - zend_string *const_PAD_BEFORE_PREFIX_name = zend_string_init_interned("PAD_BEFORE_PREFIX", sizeof("PAD_BEFORE_PREFIX") - 1, 1); + zend_string *const_PAD_BEFORE_PREFIX_name = zend_string_init_interned("PAD_BEFORE_PREFIX", sizeof("PAD_BEFORE_PREFIX") - 1, true); zend_declare_typed_class_constant(class_entry, const_PAD_BEFORE_PREFIX_name, &const_PAD_BEFORE_PREFIX_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PAD_BEFORE_PREFIX_name); + zend_string_release_ex(const_PAD_BEFORE_PREFIX_name, true); zval const_PAD_AFTER_PREFIX_value; ZVAL_LONG(&const_PAD_AFTER_PREFIX_value, UNUM_PAD_AFTER_PREFIX); - zend_string *const_PAD_AFTER_PREFIX_name = zend_string_init_interned("PAD_AFTER_PREFIX", sizeof("PAD_AFTER_PREFIX") - 1, 1); + zend_string *const_PAD_AFTER_PREFIX_name = zend_string_init_interned("PAD_AFTER_PREFIX", sizeof("PAD_AFTER_PREFIX") - 1, true); zend_declare_typed_class_constant(class_entry, const_PAD_AFTER_PREFIX_name, &const_PAD_AFTER_PREFIX_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PAD_AFTER_PREFIX_name); + zend_string_release_ex(const_PAD_AFTER_PREFIX_name, true); zval const_PAD_BEFORE_SUFFIX_value; ZVAL_LONG(&const_PAD_BEFORE_SUFFIX_value, UNUM_PAD_BEFORE_SUFFIX); - zend_string *const_PAD_BEFORE_SUFFIX_name = zend_string_init_interned("PAD_BEFORE_SUFFIX", sizeof("PAD_BEFORE_SUFFIX") - 1, 1); + zend_string *const_PAD_BEFORE_SUFFIX_name = zend_string_init_interned("PAD_BEFORE_SUFFIX", sizeof("PAD_BEFORE_SUFFIX") - 1, true); zend_declare_typed_class_constant(class_entry, const_PAD_BEFORE_SUFFIX_name, &const_PAD_BEFORE_SUFFIX_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PAD_BEFORE_SUFFIX_name); + zend_string_release_ex(const_PAD_BEFORE_SUFFIX_name, true); zval const_PAD_AFTER_SUFFIX_value; ZVAL_LONG(&const_PAD_AFTER_SUFFIX_value, UNUM_PAD_AFTER_SUFFIX); - zend_string *const_PAD_AFTER_SUFFIX_name = zend_string_init_interned("PAD_AFTER_SUFFIX", sizeof("PAD_AFTER_SUFFIX") - 1, 1); + zend_string *const_PAD_AFTER_SUFFIX_name = zend_string_init_interned("PAD_AFTER_SUFFIX", sizeof("PAD_AFTER_SUFFIX") - 1, true); zend_declare_typed_class_constant(class_entry, const_PAD_AFTER_SUFFIX_name, &const_PAD_AFTER_SUFFIX_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PAD_AFTER_SUFFIX_name); + zend_string_release_ex(const_PAD_AFTER_SUFFIX_name, true); zval const_PARSE_INT_ONLY_value; ZVAL_LONG(&const_PARSE_INT_ONLY_value, UNUM_PARSE_INT_ONLY); - zend_string *const_PARSE_INT_ONLY_name = zend_string_init_interned("PARSE_INT_ONLY", sizeof("PARSE_INT_ONLY") - 1, 1); + zend_string *const_PARSE_INT_ONLY_name = zend_string_init_interned("PARSE_INT_ONLY", sizeof("PARSE_INT_ONLY") - 1, true); zend_declare_typed_class_constant(class_entry, const_PARSE_INT_ONLY_name, &const_PARSE_INT_ONLY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PARSE_INT_ONLY_name); + zend_string_release_ex(const_PARSE_INT_ONLY_name, true); zval const_GROUPING_USED_value; ZVAL_LONG(&const_GROUPING_USED_value, UNUM_GROUPING_USED); - zend_string *const_GROUPING_USED_name = zend_string_init_interned("GROUPING_USED", sizeof("GROUPING_USED") - 1, 1); + zend_string *const_GROUPING_USED_name = zend_string_init_interned("GROUPING_USED", sizeof("GROUPING_USED") - 1, true); zend_declare_typed_class_constant(class_entry, const_GROUPING_USED_name, &const_GROUPING_USED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_GROUPING_USED_name); + zend_string_release_ex(const_GROUPING_USED_name, true); zval const_DECIMAL_ALWAYS_SHOWN_value; ZVAL_LONG(&const_DECIMAL_ALWAYS_SHOWN_value, UNUM_DECIMAL_ALWAYS_SHOWN); - zend_string *const_DECIMAL_ALWAYS_SHOWN_name = zend_string_init_interned("DECIMAL_ALWAYS_SHOWN", sizeof("DECIMAL_ALWAYS_SHOWN") - 1, 1); + zend_string *const_DECIMAL_ALWAYS_SHOWN_name = zend_string_init_interned("DECIMAL_ALWAYS_SHOWN", sizeof("DECIMAL_ALWAYS_SHOWN") - 1, true); zend_declare_typed_class_constant(class_entry, const_DECIMAL_ALWAYS_SHOWN_name, &const_DECIMAL_ALWAYS_SHOWN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DECIMAL_ALWAYS_SHOWN_name); + zend_string_release_ex(const_DECIMAL_ALWAYS_SHOWN_name, true); zval const_MAX_INTEGER_DIGITS_value; ZVAL_LONG(&const_MAX_INTEGER_DIGITS_value, UNUM_MAX_INTEGER_DIGITS); - zend_string *const_MAX_INTEGER_DIGITS_name = zend_string_init_interned("MAX_INTEGER_DIGITS", sizeof("MAX_INTEGER_DIGITS") - 1, 1); + zend_string *const_MAX_INTEGER_DIGITS_name = zend_string_init_interned("MAX_INTEGER_DIGITS", sizeof("MAX_INTEGER_DIGITS") - 1, true); zend_declare_typed_class_constant(class_entry, const_MAX_INTEGER_DIGITS_name, &const_MAX_INTEGER_DIGITS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_MAX_INTEGER_DIGITS_name); + zend_string_release_ex(const_MAX_INTEGER_DIGITS_name, true); zval const_MIN_INTEGER_DIGITS_value; ZVAL_LONG(&const_MIN_INTEGER_DIGITS_value, UNUM_MIN_INTEGER_DIGITS); - zend_string *const_MIN_INTEGER_DIGITS_name = zend_string_init_interned("MIN_INTEGER_DIGITS", sizeof("MIN_INTEGER_DIGITS") - 1, 1); + zend_string *const_MIN_INTEGER_DIGITS_name = zend_string_init_interned("MIN_INTEGER_DIGITS", sizeof("MIN_INTEGER_DIGITS") - 1, true); zend_declare_typed_class_constant(class_entry, const_MIN_INTEGER_DIGITS_name, &const_MIN_INTEGER_DIGITS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_MIN_INTEGER_DIGITS_name); + zend_string_release_ex(const_MIN_INTEGER_DIGITS_name, true); zval const_INTEGER_DIGITS_value; ZVAL_LONG(&const_INTEGER_DIGITS_value, UNUM_INTEGER_DIGITS); - zend_string *const_INTEGER_DIGITS_name = zend_string_init_interned("INTEGER_DIGITS", sizeof("INTEGER_DIGITS") - 1, 1); + zend_string *const_INTEGER_DIGITS_name = zend_string_init_interned("INTEGER_DIGITS", sizeof("INTEGER_DIGITS") - 1, true); zend_declare_typed_class_constant(class_entry, const_INTEGER_DIGITS_name, &const_INTEGER_DIGITS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_INTEGER_DIGITS_name); + zend_string_release_ex(const_INTEGER_DIGITS_name, true); zval const_MAX_FRACTION_DIGITS_value; ZVAL_LONG(&const_MAX_FRACTION_DIGITS_value, UNUM_MAX_FRACTION_DIGITS); - zend_string *const_MAX_FRACTION_DIGITS_name = zend_string_init_interned("MAX_FRACTION_DIGITS", sizeof("MAX_FRACTION_DIGITS") - 1, 1); + zend_string *const_MAX_FRACTION_DIGITS_name = zend_string_init_interned("MAX_FRACTION_DIGITS", sizeof("MAX_FRACTION_DIGITS") - 1, true); zend_declare_typed_class_constant(class_entry, const_MAX_FRACTION_DIGITS_name, &const_MAX_FRACTION_DIGITS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_MAX_FRACTION_DIGITS_name); + zend_string_release_ex(const_MAX_FRACTION_DIGITS_name, true); zval const_MIN_FRACTION_DIGITS_value; ZVAL_LONG(&const_MIN_FRACTION_DIGITS_value, UNUM_MIN_FRACTION_DIGITS); - zend_string *const_MIN_FRACTION_DIGITS_name = zend_string_init_interned("MIN_FRACTION_DIGITS", sizeof("MIN_FRACTION_DIGITS") - 1, 1); + zend_string *const_MIN_FRACTION_DIGITS_name = zend_string_init_interned("MIN_FRACTION_DIGITS", sizeof("MIN_FRACTION_DIGITS") - 1, true); zend_declare_typed_class_constant(class_entry, const_MIN_FRACTION_DIGITS_name, &const_MIN_FRACTION_DIGITS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_MIN_FRACTION_DIGITS_name); + zend_string_release_ex(const_MIN_FRACTION_DIGITS_name, true); zval const_FRACTION_DIGITS_value; ZVAL_LONG(&const_FRACTION_DIGITS_value, UNUM_FRACTION_DIGITS); - zend_string *const_FRACTION_DIGITS_name = zend_string_init_interned("FRACTION_DIGITS", sizeof("FRACTION_DIGITS") - 1, 1); + zend_string *const_FRACTION_DIGITS_name = zend_string_init_interned("FRACTION_DIGITS", sizeof("FRACTION_DIGITS") - 1, true); zend_declare_typed_class_constant(class_entry, const_FRACTION_DIGITS_name, &const_FRACTION_DIGITS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FRACTION_DIGITS_name); + zend_string_release_ex(const_FRACTION_DIGITS_name, true); zval const_MULTIPLIER_value; ZVAL_LONG(&const_MULTIPLIER_value, UNUM_MULTIPLIER); - zend_string *const_MULTIPLIER_name = zend_string_init_interned("MULTIPLIER", sizeof("MULTIPLIER") - 1, 1); + zend_string *const_MULTIPLIER_name = zend_string_init_interned("MULTIPLIER", sizeof("MULTIPLIER") - 1, true); zend_declare_typed_class_constant(class_entry, const_MULTIPLIER_name, &const_MULTIPLIER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_MULTIPLIER_name); + zend_string_release_ex(const_MULTIPLIER_name, true); zval const_GROUPING_SIZE_value; ZVAL_LONG(&const_GROUPING_SIZE_value, UNUM_GROUPING_SIZE); - zend_string *const_GROUPING_SIZE_name = zend_string_init_interned("GROUPING_SIZE", sizeof("GROUPING_SIZE") - 1, 1); + zend_string *const_GROUPING_SIZE_name = zend_string_init_interned("GROUPING_SIZE", sizeof("GROUPING_SIZE") - 1, true); zend_declare_typed_class_constant(class_entry, const_GROUPING_SIZE_name, &const_GROUPING_SIZE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_GROUPING_SIZE_name); + zend_string_release_ex(const_GROUPING_SIZE_name, true); zval const_ROUNDING_MODE_value; ZVAL_LONG(&const_ROUNDING_MODE_value, UNUM_ROUNDING_MODE); - zend_string *const_ROUNDING_MODE_name = zend_string_init_interned("ROUNDING_MODE", sizeof("ROUNDING_MODE") - 1, 1); + zend_string *const_ROUNDING_MODE_name = zend_string_init_interned("ROUNDING_MODE", sizeof("ROUNDING_MODE") - 1, true); zend_declare_typed_class_constant(class_entry, const_ROUNDING_MODE_name, &const_ROUNDING_MODE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ROUNDING_MODE_name); + zend_string_release_ex(const_ROUNDING_MODE_name, true); zval const_ROUNDING_INCREMENT_value; ZVAL_LONG(&const_ROUNDING_INCREMENT_value, UNUM_ROUNDING_INCREMENT); - zend_string *const_ROUNDING_INCREMENT_name = zend_string_init_interned("ROUNDING_INCREMENT", sizeof("ROUNDING_INCREMENT") - 1, 1); + zend_string *const_ROUNDING_INCREMENT_name = zend_string_init_interned("ROUNDING_INCREMENT", sizeof("ROUNDING_INCREMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_ROUNDING_INCREMENT_name, &const_ROUNDING_INCREMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ROUNDING_INCREMENT_name); + zend_string_release_ex(const_ROUNDING_INCREMENT_name, true); zval const_FORMAT_WIDTH_value; ZVAL_LONG(&const_FORMAT_WIDTH_value, UNUM_FORMAT_WIDTH); - zend_string *const_FORMAT_WIDTH_name = zend_string_init_interned("FORMAT_WIDTH", sizeof("FORMAT_WIDTH") - 1, 1); + zend_string *const_FORMAT_WIDTH_name = zend_string_init_interned("FORMAT_WIDTH", sizeof("FORMAT_WIDTH") - 1, true); zend_declare_typed_class_constant(class_entry, const_FORMAT_WIDTH_name, &const_FORMAT_WIDTH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FORMAT_WIDTH_name); + zend_string_release_ex(const_FORMAT_WIDTH_name, true); zval const_PADDING_POSITION_value; ZVAL_LONG(&const_PADDING_POSITION_value, UNUM_PADDING_POSITION); - zend_string *const_PADDING_POSITION_name = zend_string_init_interned("PADDING_POSITION", sizeof("PADDING_POSITION") - 1, 1); + zend_string *const_PADDING_POSITION_name = zend_string_init_interned("PADDING_POSITION", sizeof("PADDING_POSITION") - 1, true); zend_declare_typed_class_constant(class_entry, const_PADDING_POSITION_name, &const_PADDING_POSITION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PADDING_POSITION_name); + zend_string_release_ex(const_PADDING_POSITION_name, true); zval const_SECONDARY_GROUPING_SIZE_value; ZVAL_LONG(&const_SECONDARY_GROUPING_SIZE_value, UNUM_SECONDARY_GROUPING_SIZE); - zend_string *const_SECONDARY_GROUPING_SIZE_name = zend_string_init_interned("SECONDARY_GROUPING_SIZE", sizeof("SECONDARY_GROUPING_SIZE") - 1, 1); + zend_string *const_SECONDARY_GROUPING_SIZE_name = zend_string_init_interned("SECONDARY_GROUPING_SIZE", sizeof("SECONDARY_GROUPING_SIZE") - 1, true); zend_declare_typed_class_constant(class_entry, const_SECONDARY_GROUPING_SIZE_name, &const_SECONDARY_GROUPING_SIZE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SECONDARY_GROUPING_SIZE_name); + zend_string_release_ex(const_SECONDARY_GROUPING_SIZE_name, true); zval const_SIGNIFICANT_DIGITS_USED_value; ZVAL_LONG(&const_SIGNIFICANT_DIGITS_USED_value, UNUM_SIGNIFICANT_DIGITS_USED); - zend_string *const_SIGNIFICANT_DIGITS_USED_name = zend_string_init_interned("SIGNIFICANT_DIGITS_USED", sizeof("SIGNIFICANT_DIGITS_USED") - 1, 1); + zend_string *const_SIGNIFICANT_DIGITS_USED_name = zend_string_init_interned("SIGNIFICANT_DIGITS_USED", sizeof("SIGNIFICANT_DIGITS_USED") - 1, true); zend_declare_typed_class_constant(class_entry, const_SIGNIFICANT_DIGITS_USED_name, &const_SIGNIFICANT_DIGITS_USED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SIGNIFICANT_DIGITS_USED_name); + zend_string_release_ex(const_SIGNIFICANT_DIGITS_USED_name, true); zval const_MIN_SIGNIFICANT_DIGITS_value; ZVAL_LONG(&const_MIN_SIGNIFICANT_DIGITS_value, UNUM_MIN_SIGNIFICANT_DIGITS); - zend_string *const_MIN_SIGNIFICANT_DIGITS_name = zend_string_init_interned("MIN_SIGNIFICANT_DIGITS", sizeof("MIN_SIGNIFICANT_DIGITS") - 1, 1); + zend_string *const_MIN_SIGNIFICANT_DIGITS_name = zend_string_init_interned("MIN_SIGNIFICANT_DIGITS", sizeof("MIN_SIGNIFICANT_DIGITS") - 1, true); zend_declare_typed_class_constant(class_entry, const_MIN_SIGNIFICANT_DIGITS_name, &const_MIN_SIGNIFICANT_DIGITS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_MIN_SIGNIFICANT_DIGITS_name); + zend_string_release_ex(const_MIN_SIGNIFICANT_DIGITS_name, true); zval const_MAX_SIGNIFICANT_DIGITS_value; ZVAL_LONG(&const_MAX_SIGNIFICANT_DIGITS_value, UNUM_MAX_SIGNIFICANT_DIGITS); - zend_string *const_MAX_SIGNIFICANT_DIGITS_name = zend_string_init_interned("MAX_SIGNIFICANT_DIGITS", sizeof("MAX_SIGNIFICANT_DIGITS") - 1, 1); + zend_string *const_MAX_SIGNIFICANT_DIGITS_name = zend_string_init_interned("MAX_SIGNIFICANT_DIGITS", sizeof("MAX_SIGNIFICANT_DIGITS") - 1, true); zend_declare_typed_class_constant(class_entry, const_MAX_SIGNIFICANT_DIGITS_name, &const_MAX_SIGNIFICANT_DIGITS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_MAX_SIGNIFICANT_DIGITS_name); + zend_string_release_ex(const_MAX_SIGNIFICANT_DIGITS_name, true); zval const_LENIENT_PARSE_value; ZVAL_LONG(&const_LENIENT_PARSE_value, UNUM_LENIENT_PARSE); - zend_string *const_LENIENT_PARSE_name = zend_string_init_interned("LENIENT_PARSE", sizeof("LENIENT_PARSE") - 1, 1); + zend_string *const_LENIENT_PARSE_name = zend_string_init_interned("LENIENT_PARSE", sizeof("LENIENT_PARSE") - 1, true); zend_declare_typed_class_constant(class_entry, const_LENIENT_PARSE_name, &const_LENIENT_PARSE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LENIENT_PARSE_name); + zend_string_release_ex(const_LENIENT_PARSE_name, true); zval const_POSITIVE_PREFIX_value; ZVAL_LONG(&const_POSITIVE_PREFIX_value, UNUM_POSITIVE_PREFIX); - zend_string *const_POSITIVE_PREFIX_name = zend_string_init_interned("POSITIVE_PREFIX", sizeof("POSITIVE_PREFIX") - 1, 1); + zend_string *const_POSITIVE_PREFIX_name = zend_string_init_interned("POSITIVE_PREFIX", sizeof("POSITIVE_PREFIX") - 1, true); zend_declare_typed_class_constant(class_entry, const_POSITIVE_PREFIX_name, &const_POSITIVE_PREFIX_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_POSITIVE_PREFIX_name); + zend_string_release_ex(const_POSITIVE_PREFIX_name, true); zval const_POSITIVE_SUFFIX_value; ZVAL_LONG(&const_POSITIVE_SUFFIX_value, UNUM_POSITIVE_SUFFIX); - zend_string *const_POSITIVE_SUFFIX_name = zend_string_init_interned("POSITIVE_SUFFIX", sizeof("POSITIVE_SUFFIX") - 1, 1); + zend_string *const_POSITIVE_SUFFIX_name = zend_string_init_interned("POSITIVE_SUFFIX", sizeof("POSITIVE_SUFFIX") - 1, true); zend_declare_typed_class_constant(class_entry, const_POSITIVE_SUFFIX_name, &const_POSITIVE_SUFFIX_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_POSITIVE_SUFFIX_name); + zend_string_release_ex(const_POSITIVE_SUFFIX_name, true); zval const_NEGATIVE_PREFIX_value; ZVAL_LONG(&const_NEGATIVE_PREFIX_value, UNUM_NEGATIVE_PREFIX); - zend_string *const_NEGATIVE_PREFIX_name = zend_string_init_interned("NEGATIVE_PREFIX", sizeof("NEGATIVE_PREFIX") - 1, 1); + zend_string *const_NEGATIVE_PREFIX_name = zend_string_init_interned("NEGATIVE_PREFIX", sizeof("NEGATIVE_PREFIX") - 1, true); zend_declare_typed_class_constant(class_entry, const_NEGATIVE_PREFIX_name, &const_NEGATIVE_PREFIX_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NEGATIVE_PREFIX_name); + zend_string_release_ex(const_NEGATIVE_PREFIX_name, true); zval const_NEGATIVE_SUFFIX_value; ZVAL_LONG(&const_NEGATIVE_SUFFIX_value, UNUM_NEGATIVE_SUFFIX); - zend_string *const_NEGATIVE_SUFFIX_name = zend_string_init_interned("NEGATIVE_SUFFIX", sizeof("NEGATIVE_SUFFIX") - 1, 1); + zend_string *const_NEGATIVE_SUFFIX_name = zend_string_init_interned("NEGATIVE_SUFFIX", sizeof("NEGATIVE_SUFFIX") - 1, true); zend_declare_typed_class_constant(class_entry, const_NEGATIVE_SUFFIX_name, &const_NEGATIVE_SUFFIX_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NEGATIVE_SUFFIX_name); + zend_string_release_ex(const_NEGATIVE_SUFFIX_name, true); zval const_PADDING_CHARACTER_value; ZVAL_LONG(&const_PADDING_CHARACTER_value, UNUM_PADDING_CHARACTER); - zend_string *const_PADDING_CHARACTER_name = zend_string_init_interned("PADDING_CHARACTER", sizeof("PADDING_CHARACTER") - 1, 1); + zend_string *const_PADDING_CHARACTER_name = zend_string_init_interned("PADDING_CHARACTER", sizeof("PADDING_CHARACTER") - 1, true); zend_declare_typed_class_constant(class_entry, const_PADDING_CHARACTER_name, &const_PADDING_CHARACTER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PADDING_CHARACTER_name); + zend_string_release_ex(const_PADDING_CHARACTER_name, true); zval const_CURRENCY_CODE_value; ZVAL_LONG(&const_CURRENCY_CODE_value, UNUM_CURRENCY_CODE); - zend_string *const_CURRENCY_CODE_name = zend_string_init_interned("CURRENCY_CODE", sizeof("CURRENCY_CODE") - 1, 1); + zend_string *const_CURRENCY_CODE_name = zend_string_init_interned("CURRENCY_CODE", sizeof("CURRENCY_CODE") - 1, true); zend_declare_typed_class_constant(class_entry, const_CURRENCY_CODE_name, &const_CURRENCY_CODE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CURRENCY_CODE_name); + zend_string_release_ex(const_CURRENCY_CODE_name, true); zval const_DEFAULT_RULESET_value; ZVAL_LONG(&const_DEFAULT_RULESET_value, UNUM_DEFAULT_RULESET); - zend_string *const_DEFAULT_RULESET_name = zend_string_init_interned("DEFAULT_RULESET", sizeof("DEFAULT_RULESET") - 1, 1); + zend_string *const_DEFAULT_RULESET_name = zend_string_init_interned("DEFAULT_RULESET", sizeof("DEFAULT_RULESET") - 1, true); zend_declare_typed_class_constant(class_entry, const_DEFAULT_RULESET_name, &const_DEFAULT_RULESET_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DEFAULT_RULESET_name); + zend_string_release_ex(const_DEFAULT_RULESET_name, true); zval const_PUBLIC_RULESETS_value; ZVAL_LONG(&const_PUBLIC_RULESETS_value, UNUM_PUBLIC_RULESETS); - zend_string *const_PUBLIC_RULESETS_name = zend_string_init_interned("PUBLIC_RULESETS", sizeof("PUBLIC_RULESETS") - 1, 1); + zend_string *const_PUBLIC_RULESETS_name = zend_string_init_interned("PUBLIC_RULESETS", sizeof("PUBLIC_RULESETS") - 1, true); zend_declare_typed_class_constant(class_entry, const_PUBLIC_RULESETS_name, &const_PUBLIC_RULESETS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PUBLIC_RULESETS_name); + zend_string_release_ex(const_PUBLIC_RULESETS_name, true); zval const_DECIMAL_SEPARATOR_SYMBOL_value; ZVAL_LONG(&const_DECIMAL_SEPARATOR_SYMBOL_value, UNUM_DECIMAL_SEPARATOR_SYMBOL); - zend_string *const_DECIMAL_SEPARATOR_SYMBOL_name = zend_string_init_interned("DECIMAL_SEPARATOR_SYMBOL", sizeof("DECIMAL_SEPARATOR_SYMBOL") - 1, 1); + zend_string *const_DECIMAL_SEPARATOR_SYMBOL_name = zend_string_init_interned("DECIMAL_SEPARATOR_SYMBOL", sizeof("DECIMAL_SEPARATOR_SYMBOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_DECIMAL_SEPARATOR_SYMBOL_name, &const_DECIMAL_SEPARATOR_SYMBOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DECIMAL_SEPARATOR_SYMBOL_name); + zend_string_release_ex(const_DECIMAL_SEPARATOR_SYMBOL_name, true); zval const_GROUPING_SEPARATOR_SYMBOL_value; ZVAL_LONG(&const_GROUPING_SEPARATOR_SYMBOL_value, UNUM_GROUPING_SEPARATOR_SYMBOL); - zend_string *const_GROUPING_SEPARATOR_SYMBOL_name = zend_string_init_interned("GROUPING_SEPARATOR_SYMBOL", sizeof("GROUPING_SEPARATOR_SYMBOL") - 1, 1); + zend_string *const_GROUPING_SEPARATOR_SYMBOL_name = zend_string_init_interned("GROUPING_SEPARATOR_SYMBOL", sizeof("GROUPING_SEPARATOR_SYMBOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_GROUPING_SEPARATOR_SYMBOL_name, &const_GROUPING_SEPARATOR_SYMBOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_GROUPING_SEPARATOR_SYMBOL_name); + zend_string_release_ex(const_GROUPING_SEPARATOR_SYMBOL_name, true); zval const_PATTERN_SEPARATOR_SYMBOL_value; ZVAL_LONG(&const_PATTERN_SEPARATOR_SYMBOL_value, UNUM_PATTERN_SEPARATOR_SYMBOL); - zend_string *const_PATTERN_SEPARATOR_SYMBOL_name = zend_string_init_interned("PATTERN_SEPARATOR_SYMBOL", sizeof("PATTERN_SEPARATOR_SYMBOL") - 1, 1); + zend_string *const_PATTERN_SEPARATOR_SYMBOL_name = zend_string_init_interned("PATTERN_SEPARATOR_SYMBOL", sizeof("PATTERN_SEPARATOR_SYMBOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_PATTERN_SEPARATOR_SYMBOL_name, &const_PATTERN_SEPARATOR_SYMBOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PATTERN_SEPARATOR_SYMBOL_name); + zend_string_release_ex(const_PATTERN_SEPARATOR_SYMBOL_name, true); zval const_PERCENT_SYMBOL_value; ZVAL_LONG(&const_PERCENT_SYMBOL_value, UNUM_PERCENT_SYMBOL); - zend_string *const_PERCENT_SYMBOL_name = zend_string_init_interned("PERCENT_SYMBOL", sizeof("PERCENT_SYMBOL") - 1, 1); + zend_string *const_PERCENT_SYMBOL_name = zend_string_init_interned("PERCENT_SYMBOL", sizeof("PERCENT_SYMBOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_PERCENT_SYMBOL_name, &const_PERCENT_SYMBOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PERCENT_SYMBOL_name); + zend_string_release_ex(const_PERCENT_SYMBOL_name, true); zval const_ZERO_DIGIT_SYMBOL_value; ZVAL_LONG(&const_ZERO_DIGIT_SYMBOL_value, UNUM_ZERO_DIGIT_SYMBOL); - zend_string *const_ZERO_DIGIT_SYMBOL_name = zend_string_init_interned("ZERO_DIGIT_SYMBOL", sizeof("ZERO_DIGIT_SYMBOL") - 1, 1); + zend_string *const_ZERO_DIGIT_SYMBOL_name = zend_string_init_interned("ZERO_DIGIT_SYMBOL", sizeof("ZERO_DIGIT_SYMBOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_ZERO_DIGIT_SYMBOL_name, &const_ZERO_DIGIT_SYMBOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ZERO_DIGIT_SYMBOL_name); + zend_string_release_ex(const_ZERO_DIGIT_SYMBOL_name, true); zval const_DIGIT_SYMBOL_value; ZVAL_LONG(&const_DIGIT_SYMBOL_value, UNUM_DIGIT_SYMBOL); - zend_string *const_DIGIT_SYMBOL_name = zend_string_init_interned("DIGIT_SYMBOL", sizeof("DIGIT_SYMBOL") - 1, 1); + zend_string *const_DIGIT_SYMBOL_name = zend_string_init_interned("DIGIT_SYMBOL", sizeof("DIGIT_SYMBOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_DIGIT_SYMBOL_name, &const_DIGIT_SYMBOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DIGIT_SYMBOL_name); + zend_string_release_ex(const_DIGIT_SYMBOL_name, true); zval const_MINUS_SIGN_SYMBOL_value; ZVAL_LONG(&const_MINUS_SIGN_SYMBOL_value, UNUM_MINUS_SIGN_SYMBOL); - zend_string *const_MINUS_SIGN_SYMBOL_name = zend_string_init_interned("MINUS_SIGN_SYMBOL", sizeof("MINUS_SIGN_SYMBOL") - 1, 1); + zend_string *const_MINUS_SIGN_SYMBOL_name = zend_string_init_interned("MINUS_SIGN_SYMBOL", sizeof("MINUS_SIGN_SYMBOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_MINUS_SIGN_SYMBOL_name, &const_MINUS_SIGN_SYMBOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_MINUS_SIGN_SYMBOL_name); + zend_string_release_ex(const_MINUS_SIGN_SYMBOL_name, true); zval const_PLUS_SIGN_SYMBOL_value; ZVAL_LONG(&const_PLUS_SIGN_SYMBOL_value, UNUM_PLUS_SIGN_SYMBOL); - zend_string *const_PLUS_SIGN_SYMBOL_name = zend_string_init_interned("PLUS_SIGN_SYMBOL", sizeof("PLUS_SIGN_SYMBOL") - 1, 1); + zend_string *const_PLUS_SIGN_SYMBOL_name = zend_string_init_interned("PLUS_SIGN_SYMBOL", sizeof("PLUS_SIGN_SYMBOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_PLUS_SIGN_SYMBOL_name, &const_PLUS_SIGN_SYMBOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PLUS_SIGN_SYMBOL_name); + zend_string_release_ex(const_PLUS_SIGN_SYMBOL_name, true); zval const_CURRENCY_SYMBOL_value; ZVAL_LONG(&const_CURRENCY_SYMBOL_value, UNUM_CURRENCY_SYMBOL); - zend_string *const_CURRENCY_SYMBOL_name = zend_string_init_interned("CURRENCY_SYMBOL", sizeof("CURRENCY_SYMBOL") - 1, 1); + zend_string *const_CURRENCY_SYMBOL_name = zend_string_init_interned("CURRENCY_SYMBOL", sizeof("CURRENCY_SYMBOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_CURRENCY_SYMBOL_name, &const_CURRENCY_SYMBOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CURRENCY_SYMBOL_name); + zend_string_release_ex(const_CURRENCY_SYMBOL_name, true); zval const_INTL_CURRENCY_SYMBOL_value; ZVAL_LONG(&const_INTL_CURRENCY_SYMBOL_value, UNUM_INTL_CURRENCY_SYMBOL); - zend_string *const_INTL_CURRENCY_SYMBOL_name = zend_string_init_interned("INTL_CURRENCY_SYMBOL", sizeof("INTL_CURRENCY_SYMBOL") - 1, 1); + zend_string *const_INTL_CURRENCY_SYMBOL_name = zend_string_init_interned("INTL_CURRENCY_SYMBOL", sizeof("INTL_CURRENCY_SYMBOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_INTL_CURRENCY_SYMBOL_name, &const_INTL_CURRENCY_SYMBOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_INTL_CURRENCY_SYMBOL_name); + zend_string_release_ex(const_INTL_CURRENCY_SYMBOL_name, true); zval const_MONETARY_SEPARATOR_SYMBOL_value; ZVAL_LONG(&const_MONETARY_SEPARATOR_SYMBOL_value, UNUM_MONETARY_SEPARATOR_SYMBOL); - zend_string *const_MONETARY_SEPARATOR_SYMBOL_name = zend_string_init_interned("MONETARY_SEPARATOR_SYMBOL", sizeof("MONETARY_SEPARATOR_SYMBOL") - 1, 1); + zend_string *const_MONETARY_SEPARATOR_SYMBOL_name = zend_string_init_interned("MONETARY_SEPARATOR_SYMBOL", sizeof("MONETARY_SEPARATOR_SYMBOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_MONETARY_SEPARATOR_SYMBOL_name, &const_MONETARY_SEPARATOR_SYMBOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_MONETARY_SEPARATOR_SYMBOL_name); + zend_string_release_ex(const_MONETARY_SEPARATOR_SYMBOL_name, true); zval const_EXPONENTIAL_SYMBOL_value; ZVAL_LONG(&const_EXPONENTIAL_SYMBOL_value, UNUM_EXPONENTIAL_SYMBOL); - zend_string *const_EXPONENTIAL_SYMBOL_name = zend_string_init_interned("EXPONENTIAL_SYMBOL", sizeof("EXPONENTIAL_SYMBOL") - 1, 1); + zend_string *const_EXPONENTIAL_SYMBOL_name = zend_string_init_interned("EXPONENTIAL_SYMBOL", sizeof("EXPONENTIAL_SYMBOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_EXPONENTIAL_SYMBOL_name, &const_EXPONENTIAL_SYMBOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EXPONENTIAL_SYMBOL_name); + zend_string_release_ex(const_EXPONENTIAL_SYMBOL_name, true); zval const_PERMILL_SYMBOL_value; ZVAL_LONG(&const_PERMILL_SYMBOL_value, UNUM_PERMILL_SYMBOL); - zend_string *const_PERMILL_SYMBOL_name = zend_string_init_interned("PERMILL_SYMBOL", sizeof("PERMILL_SYMBOL") - 1, 1); + zend_string *const_PERMILL_SYMBOL_name = zend_string_init_interned("PERMILL_SYMBOL", sizeof("PERMILL_SYMBOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_PERMILL_SYMBOL_name, &const_PERMILL_SYMBOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PERMILL_SYMBOL_name); + zend_string_release_ex(const_PERMILL_SYMBOL_name, true); zval const_PAD_ESCAPE_SYMBOL_value; ZVAL_LONG(&const_PAD_ESCAPE_SYMBOL_value, UNUM_PAD_ESCAPE_SYMBOL); - zend_string *const_PAD_ESCAPE_SYMBOL_name = zend_string_init_interned("PAD_ESCAPE_SYMBOL", sizeof("PAD_ESCAPE_SYMBOL") - 1, 1); + zend_string *const_PAD_ESCAPE_SYMBOL_name = zend_string_init_interned("PAD_ESCAPE_SYMBOL", sizeof("PAD_ESCAPE_SYMBOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_PAD_ESCAPE_SYMBOL_name, &const_PAD_ESCAPE_SYMBOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PAD_ESCAPE_SYMBOL_name); + zend_string_release_ex(const_PAD_ESCAPE_SYMBOL_name, true); zval const_INFINITY_SYMBOL_value; ZVAL_LONG(&const_INFINITY_SYMBOL_value, UNUM_INFINITY_SYMBOL); - zend_string *const_INFINITY_SYMBOL_name = zend_string_init_interned("INFINITY_SYMBOL", sizeof("INFINITY_SYMBOL") - 1, 1); + zend_string *const_INFINITY_SYMBOL_name = zend_string_init_interned("INFINITY_SYMBOL", sizeof("INFINITY_SYMBOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_INFINITY_SYMBOL_name, &const_INFINITY_SYMBOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_INFINITY_SYMBOL_name); + zend_string_release_ex(const_INFINITY_SYMBOL_name, true); zval const_NAN_SYMBOL_value; ZVAL_LONG(&const_NAN_SYMBOL_value, UNUM_NAN_SYMBOL); - zend_string *const_NAN_SYMBOL_name = zend_string_init_interned("NAN_SYMBOL", sizeof("NAN_SYMBOL") - 1, 1); + zend_string *const_NAN_SYMBOL_name = zend_string_init_interned("NAN_SYMBOL", sizeof("NAN_SYMBOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_NAN_SYMBOL_name, &const_NAN_SYMBOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NAN_SYMBOL_name); + zend_string_release_ex(const_NAN_SYMBOL_name, true); zval const_SIGNIFICANT_DIGIT_SYMBOL_value; ZVAL_LONG(&const_SIGNIFICANT_DIGIT_SYMBOL_value, UNUM_SIGNIFICANT_DIGIT_SYMBOL); - zend_string *const_SIGNIFICANT_DIGIT_SYMBOL_name = zend_string_init_interned("SIGNIFICANT_DIGIT_SYMBOL", sizeof("SIGNIFICANT_DIGIT_SYMBOL") - 1, 1); + zend_string *const_SIGNIFICANT_DIGIT_SYMBOL_name = zend_string_init_interned("SIGNIFICANT_DIGIT_SYMBOL", sizeof("SIGNIFICANT_DIGIT_SYMBOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_SIGNIFICANT_DIGIT_SYMBOL_name, &const_SIGNIFICANT_DIGIT_SYMBOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SIGNIFICANT_DIGIT_SYMBOL_name); + zend_string_release_ex(const_SIGNIFICANT_DIGIT_SYMBOL_name, true); zval const_MONETARY_GROUPING_SEPARATOR_SYMBOL_value; ZVAL_LONG(&const_MONETARY_GROUPING_SEPARATOR_SYMBOL_value, UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL); - zend_string *const_MONETARY_GROUPING_SEPARATOR_SYMBOL_name = zend_string_init_interned("MONETARY_GROUPING_SEPARATOR_SYMBOL", sizeof("MONETARY_GROUPING_SEPARATOR_SYMBOL") - 1, 1); + zend_string *const_MONETARY_GROUPING_SEPARATOR_SYMBOL_name = zend_string_init_interned("MONETARY_GROUPING_SEPARATOR_SYMBOL", sizeof("MONETARY_GROUPING_SEPARATOR_SYMBOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_MONETARY_GROUPING_SEPARATOR_SYMBOL_name, &const_MONETARY_GROUPING_SEPARATOR_SYMBOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_MONETARY_GROUPING_SEPARATOR_SYMBOL_name); + zend_string_release_ex(const_MONETARY_GROUPING_SEPARATOR_SYMBOL_name, true); zval const_TYPE_DEFAULT_value; ZVAL_LONG(&const_TYPE_DEFAULT_value, FORMAT_TYPE_DEFAULT); - zend_string *const_TYPE_DEFAULT_name = zend_string_init_interned("TYPE_DEFAULT", sizeof("TYPE_DEFAULT") - 1, 1); + zend_string *const_TYPE_DEFAULT_name = zend_string_init_interned("TYPE_DEFAULT", sizeof("TYPE_DEFAULT") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_DEFAULT_name, &const_TYPE_DEFAULT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_DEFAULT_name); + zend_string_release_ex(const_TYPE_DEFAULT_name, true); zval const_TYPE_INT32_value; ZVAL_LONG(&const_TYPE_INT32_value, FORMAT_TYPE_INT32); - zend_string *const_TYPE_INT32_name = zend_string_init_interned("TYPE_INT32", sizeof("TYPE_INT32") - 1, 1); + zend_string *const_TYPE_INT32_name = zend_string_init_interned("TYPE_INT32", sizeof("TYPE_INT32") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_INT32_name, &const_TYPE_INT32_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_INT32_name); + zend_string_release_ex(const_TYPE_INT32_name, true); zval const_TYPE_INT64_value; ZVAL_LONG(&const_TYPE_INT64_value, FORMAT_TYPE_INT64); - zend_string *const_TYPE_INT64_name = zend_string_init_interned("TYPE_INT64", sizeof("TYPE_INT64") - 1, 1); + zend_string *const_TYPE_INT64_name = zend_string_init_interned("TYPE_INT64", sizeof("TYPE_INT64") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_INT64_name, &const_TYPE_INT64_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_INT64_name); + zend_string_release_ex(const_TYPE_INT64_name, true); zval const_TYPE_DOUBLE_value; ZVAL_LONG(&const_TYPE_DOUBLE_value, FORMAT_TYPE_DOUBLE); - zend_string *const_TYPE_DOUBLE_name = zend_string_init_interned("TYPE_DOUBLE", sizeof("TYPE_DOUBLE") - 1, 1); + zend_string *const_TYPE_DOUBLE_name = zend_string_init_interned("TYPE_DOUBLE", sizeof("TYPE_DOUBLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_DOUBLE_name, &const_TYPE_DOUBLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_DOUBLE_name); + zend_string_release_ex(const_TYPE_DOUBLE_name, true); zval const_TYPE_CURRENCY_value; ZVAL_LONG(&const_TYPE_CURRENCY_value, FORMAT_TYPE_CURRENCY); - zend_string *const_TYPE_CURRENCY_name = zend_string_init_interned("TYPE_CURRENCY", sizeof("TYPE_CURRENCY") - 1, 1); + zend_string *const_TYPE_CURRENCY_name = zend_string_init_interned("TYPE_CURRENCY", sizeof("TYPE_CURRENCY") - 1, true); zend_class_constant *const_TYPE_CURRENCY = zend_declare_typed_class_constant(class_entry, const_TYPE_CURRENCY_name, &const_TYPE_CURRENCY_value, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_CURRENCY_name); + zend_string_release_ex(const_TYPE_CURRENCY_name, true); 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); diff --git a/ext/intl/formatter/formatter_attr.c b/ext/intl/formatter/formatter_attr.c deleted file mode 100644 index 874984f5405f0..0000000000000 --- a/ext/intl/formatter/formatter_attr.c +++ /dev/null @@ -1,388 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Stanislav Malyshev | - +----------------------------------------------------------------------+ - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "php_intl.h" -#include "formatter_class.h" -#include "intl_convert.h" - -#include - -/* {{{ Get formatter attribute value. */ -PHP_FUNCTION( numfmt_get_attribute ) -{ - zend_long attribute, value; - FORMATTER_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ol", - &object, NumberFormatter_ce_ptr, &attribute ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - FORMATTER_METHOD_FETCH_OBJECT; - - switch(attribute) { - case UNUM_PARSE_INT_ONLY: - case UNUM_GROUPING_USED: - case UNUM_DECIMAL_ALWAYS_SHOWN: - case UNUM_MAX_INTEGER_DIGITS: - case UNUM_MIN_INTEGER_DIGITS: - case UNUM_INTEGER_DIGITS: - case UNUM_MAX_FRACTION_DIGITS: - case UNUM_MIN_FRACTION_DIGITS: - case UNUM_FRACTION_DIGITS: - case UNUM_MULTIPLIER: - case UNUM_GROUPING_SIZE: - case UNUM_ROUNDING_MODE: - case UNUM_FORMAT_WIDTH: - case UNUM_PADDING_POSITION: - case UNUM_SECONDARY_GROUPING_SIZE: - case UNUM_SIGNIFICANT_DIGITS_USED: - case UNUM_MIN_SIGNIFICANT_DIGITS: - case UNUM_MAX_SIGNIFICANT_DIGITS: - case UNUM_LENIENT_PARSE: - value = unum_getAttribute(FORMATTER_OBJECT(nfo), attribute); - if(value == -1) { - INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR; - } else { - RETVAL_LONG(value); - } - break; - case UNUM_ROUNDING_INCREMENT: - { - double value_double = unum_getDoubleAttribute(FORMATTER_OBJECT(nfo), attribute); - if(value_double == -1) { - INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR; - } else { - RETVAL_DOUBLE(value_double); - } - } - break; - default: - INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR; - break; - } - - INTL_METHOD_CHECK_STATUS( nfo, "Error getting attribute value" ); -} -/* }}} */ - -/* {{{ Get formatter attribute value. */ -PHP_FUNCTION( numfmt_get_text_attribute ) -{ - zend_long attribute; - UChar value_buf[64]; - int32_t value_buf_size = USIZE( value_buf ); - UChar* value = value_buf; - int32_t length = 0; - FORMATTER_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ol", - &object, NumberFormatter_ce_ptr, &attribute ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - FORMATTER_METHOD_FETCH_OBJECT; - - length = unum_getTextAttribute( FORMATTER_OBJECT(nfo), attribute, value, value_buf_size, &INTL_DATA_ERROR_CODE(nfo) ); - if(INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR && length >= value_buf_size) { - ++length; /* to avoid U_STRING_NOT_TERMINATED_WARNING */ - INTL_DATA_ERROR_CODE(nfo) = U_ZERO_ERROR; - value = eumalloc(length); - length = unum_getTextAttribute( FORMATTER_OBJECT(nfo), attribute, value, length, &INTL_DATA_ERROR_CODE(nfo) ); - if(U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) { - efree(value); - value = value_buf; - } - } - INTL_METHOD_CHECK_STATUS( nfo, "Error getting attribute value" ); - - INTL_METHOD_RETVAL_UTF8( nfo, value, length, ( value != value_buf ) ); -} -/* }}} */ - -/* {{{ Get formatter attribute value. */ -PHP_FUNCTION( numfmt_set_attribute ) -{ - zend_long attribute; - zval *value; - FORMATTER_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Oln", - &object, NumberFormatter_ce_ptr, &attribute, &value ) == FAILURE) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - FORMATTER_METHOD_FETCH_OBJECT; - - switch(attribute) { - case UNUM_PARSE_INT_ONLY: - case UNUM_GROUPING_USED: - case UNUM_DECIMAL_ALWAYS_SHOWN: - case UNUM_MAX_INTEGER_DIGITS: - case UNUM_MIN_INTEGER_DIGITS: - case UNUM_INTEGER_DIGITS: - case UNUM_MAX_FRACTION_DIGITS: - case UNUM_MIN_FRACTION_DIGITS: - case UNUM_FRACTION_DIGITS: - case UNUM_MULTIPLIER: - case UNUM_GROUPING_SIZE: - case UNUM_ROUNDING_MODE: - case UNUM_FORMAT_WIDTH: - case UNUM_PADDING_POSITION: - case UNUM_SECONDARY_GROUPING_SIZE: - case UNUM_SIGNIFICANT_DIGITS_USED: - case UNUM_MIN_SIGNIFICANT_DIGITS: - case UNUM_MAX_SIGNIFICANT_DIGITS: - case UNUM_LENIENT_PARSE: - unum_setAttribute(FORMATTER_OBJECT(nfo), attribute, zval_get_long(value)); - break; - case UNUM_ROUNDING_INCREMENT: - unum_setDoubleAttribute(FORMATTER_OBJECT(nfo), attribute, zval_get_double(value)); - break; - default: - INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR; - break; - } - - INTL_METHOD_CHECK_STATUS( nfo, "Error setting attribute value" ); - - RETURN_TRUE; -} -/* }}} */ - -/* {{{ Get formatter attribute value. */ -PHP_FUNCTION( numfmt_set_text_attribute ) -{ - int32_t slength = 0; - UChar *svalue = NULL; - zend_long attribute; - char *value; - size_t len; - FORMATTER_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ols", - &object, NumberFormatter_ce_ptr, &attribute, &value, &len ) == FAILURE) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - FORMATTER_METHOD_FETCH_OBJECT; - - /* Convert given attribute value to UTF-16. */ - intl_convert_utf8_to_utf16(&svalue, &slength, value, len, &INTL_DATA_ERROR_CODE(nfo)); - INTL_METHOD_CHECK_STATUS( nfo, "Error converting attribute value to UTF-16" ); - - /* Actually set new attribute value. */ - unum_setTextAttribute(FORMATTER_OBJECT(nfo), attribute, svalue, slength, &INTL_DATA_ERROR_CODE(nfo)); - if (svalue) { - efree(svalue); - } - INTL_METHOD_CHECK_STATUS( nfo, "Error setting text attribute" ); - - RETURN_TRUE; -} -/* }}} */ - -/* {{{ Get formatter symbol value. */ -PHP_FUNCTION( numfmt_get_symbol ) -{ - zend_long symbol; - UChar value_buf[4]; - UChar *value = value_buf; - uint32_t length = USIZE(value_buf); - FORMATTER_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ol", - &object, NumberFormatter_ce_ptr, &symbol ) == FAILURE ) - { - RETURN_THROWS(); - } - - if(symbol >= UNUM_FORMAT_SYMBOL_COUNT || symbol < 0) { - intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "numfmt_get_symbol: invalid symbol value", 0 ); - RETURN_FALSE; - } - - /* Fetch the object. */ - FORMATTER_METHOD_FETCH_OBJECT; - - length = unum_getSymbol(FORMATTER_OBJECT(nfo), symbol, value_buf, length, &INTL_DATA_ERROR_CODE(nfo)); - if(INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR && length >= USIZE( value_buf )) { - ++length; /* to avoid U_STRING_NOT_TERMINATED_WARNING */ - INTL_DATA_ERROR_CODE(nfo) = U_ZERO_ERROR; - value = eumalloc(length); - length = unum_getSymbol(FORMATTER_OBJECT(nfo), symbol, value, length, &INTL_DATA_ERROR_CODE(nfo)); - if(U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) { - efree(value); - value = value_buf; - } - } - INTL_METHOD_CHECK_STATUS( nfo, "Error getting symbol value" ); - - INTL_METHOD_RETVAL_UTF8( nfo, value, length, ( value_buf != value ) ); -} -/* }}} */ - -/* {{{ Set formatter symbol value. */ -PHP_FUNCTION( numfmt_set_symbol ) -{ - zend_long symbol; - char* value = NULL; - size_t value_len = 0; - UChar* svalue = 0; - int32_t slength = 0; - FORMATTER_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ols", - &object, NumberFormatter_ce_ptr, &symbol, &value, &value_len ) == FAILURE ) - { - RETURN_THROWS(); - } - - if (symbol >= UNUM_FORMAT_SYMBOL_COUNT || symbol < 0) { - intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "numfmt_set_symbol: invalid symbol value", 0 ); - RETURN_FALSE; - } - - /* Fetch the object. */ - FORMATTER_METHOD_FETCH_OBJECT; - - /* Convert given symbol to UTF-16. */ - intl_convert_utf8_to_utf16(&svalue, &slength, value, value_len, &INTL_DATA_ERROR_CODE(nfo)); - INTL_METHOD_CHECK_STATUS( nfo, "Error converting symbol value to UTF-16" ); - - /* Actually set the symbol. */ - unum_setSymbol(FORMATTER_OBJECT(nfo), symbol, svalue, slength, &INTL_DATA_ERROR_CODE(nfo)); - if (svalue) { - efree(svalue); - } - INTL_METHOD_CHECK_STATUS( nfo, "Error setting symbol value" ); - - RETURN_TRUE; -} -/* }}} */ - -/* {{{ Get formatter pattern. */ -PHP_FUNCTION( numfmt_get_pattern ) -{ - UChar value_buf[64]; - uint32_t length = USIZE( value_buf ); - UChar* value = value_buf; - FORMATTER_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", - &object, NumberFormatter_ce_ptr ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - FORMATTER_METHOD_FETCH_OBJECT; - - length = unum_toPattern(FORMATTER_OBJECT(nfo), 0, value, length, &INTL_DATA_ERROR_CODE(nfo)); - if(INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR && length >= USIZE( value_buf )) { - ++length; /* to avoid U_STRING_NOT_TERMINATED_WARNING */ - INTL_DATA_ERROR_CODE(nfo) = U_ZERO_ERROR; - value = eumalloc(length); - length = unum_toPattern( FORMATTER_OBJECT(nfo), 0, value, length, &INTL_DATA_ERROR_CODE(nfo) ); - if(U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) { - efree(value); - value = value_buf; - } - } - INTL_METHOD_CHECK_STATUS( nfo, "Error getting formatter pattern" ); - - INTL_METHOD_RETVAL_UTF8( nfo, value, length, ( value != value_buf ) ); -} -/* }}} */ - -/* {{{ Set formatter pattern. */ -PHP_FUNCTION( numfmt_set_pattern ) -{ - char* value = NULL; - size_t value_len = 0; - int32_t slength = 0; - UChar* svalue = NULL; - UParseError spattern_error = {0}; - FORMATTER_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Os", - &object, NumberFormatter_ce_ptr, &value, &value_len ) == FAILURE ) - { - RETURN_THROWS(); - } - - FORMATTER_METHOD_FETCH_OBJECT; - - /* Convert given pattern to UTF-16. */ - intl_convert_utf8_to_utf16(&svalue, &slength, value, value_len, &INTL_DATA_ERROR_CODE(nfo)); - INTL_METHOD_CHECK_STATUS( nfo, "Error converting pattern to UTF-16" ); - - unum_applyPattern(FORMATTER_OBJECT(nfo), 0, svalue, slength, &spattern_error, &INTL_DATA_ERROR_CODE(nfo)); - if (svalue) { - efree(svalue); - } - 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); - efree(msg); - RETURN_FALSE; - } - - RETURN_TRUE; -} -/* }}} */ - -/* {{{ Get formatter locale. */ -PHP_FUNCTION( numfmt_get_locale ) -{ - zend_long type = ULOC_ACTUAL_LOCALE; - char* loc; - FORMATTER_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O|l", - &object, NumberFormatter_ce_ptr, &type ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - FORMATTER_METHOD_FETCH_OBJECT; - - loc = (char *)unum_getLocaleByType(FORMATTER_OBJECT(nfo), type, &INTL_DATA_ERROR_CODE(nfo)); - INTL_METHOD_CHECK_STATUS( nfo, "Error getting locale" ); - RETURN_STRING(loc); -} -/* }}} */ diff --git a/ext/intl/formatter/formatter_attr.cpp b/ext/intl/formatter/formatter_attr.cpp new file mode 100644 index 0000000000000..905a4415ef59b --- /dev/null +++ b/ext/intl/formatter/formatter_attr.cpp @@ -0,0 +1,400 @@ +/* + +----------------------------------------------------------------------+ + | 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: Stanislav Malyshev | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +extern "C" { +#include "php_intl.h" +#include "intl_convert.h" +} +#include "formatter_class.h" + +#include + +/* {{{ Get formatter attribute value. */ +U_CFUNC PHP_FUNCTION( numfmt_get_attribute ) +{ + zend_long lattribute, value; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ol", + &object, NumberFormatter_ce_ptr, &lattribute ) == FAILURE ) + { + RETURN_THROWS(); + } + + UNumberFormatAttribute attribute = static_cast(lattribute); + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + switch(attribute) { + case UNUM_PARSE_INT_ONLY: + case UNUM_GROUPING_USED: + case UNUM_DECIMAL_ALWAYS_SHOWN: + case UNUM_MAX_INTEGER_DIGITS: + case UNUM_MIN_INTEGER_DIGITS: + case UNUM_INTEGER_DIGITS: + case UNUM_MAX_FRACTION_DIGITS: + case UNUM_MIN_FRACTION_DIGITS: + case UNUM_FRACTION_DIGITS: + case UNUM_MULTIPLIER: + case UNUM_GROUPING_SIZE: + case UNUM_ROUNDING_MODE: + case UNUM_FORMAT_WIDTH: + case UNUM_PADDING_POSITION: + case UNUM_SECONDARY_GROUPING_SIZE: + case UNUM_SIGNIFICANT_DIGITS_USED: + case UNUM_MIN_SIGNIFICANT_DIGITS: + case UNUM_MAX_SIGNIFICANT_DIGITS: + case UNUM_LENIENT_PARSE: + value = unum_getAttribute(FORMATTER_OBJECT(nfo), attribute); + if(value == -1) { + INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR; + } else { + RETVAL_LONG(value); + } + break; + case UNUM_ROUNDING_INCREMENT: + { + double value_double = unum_getDoubleAttribute(FORMATTER_OBJECT(nfo), attribute); + if(value_double == -1) { + INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR; + } else { + RETVAL_DOUBLE(value_double); + } + } + break; + default: + INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR; + break; + } + + INTL_METHOD_CHECK_STATUS( nfo, "Error getting attribute value" ); +} +/* }}} */ + +/* {{{ Get formatter attribute value. */ +U_CFUNC PHP_FUNCTION( numfmt_get_text_attribute ) +{ + zend_long lattribute; + UChar value_buf[64]; + int32_t value_buf_size = USIZE( value_buf ); + UChar* value = value_buf; + int32_t length = 0; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ol", + &object, NumberFormatter_ce_ptr, &lattribute ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + UNumberFormatTextAttribute attribute = static_cast(lattribute); + + length = unum_getTextAttribute( FORMATTER_OBJECT(nfo), attribute, value, value_buf_size, &INTL_DATA_ERROR_CODE(nfo) ); + if(INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR && length >= value_buf_size) { + ++length; /* to avoid U_STRING_NOT_TERMINATED_WARNING */ + INTL_DATA_ERROR_CODE(nfo) = U_ZERO_ERROR; + value = eumalloc(length); + length = unum_getTextAttribute( FORMATTER_OBJECT(nfo), attribute, value, length, &INTL_DATA_ERROR_CODE(nfo) ); + if(U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) { + efree(value); + value = value_buf; + } + } + INTL_METHOD_CHECK_STATUS( nfo, "Error getting attribute value" ); + + INTL_METHOD_RETVAL_UTF8( nfo, value, length, ( value != value_buf ) ); +} +/* }}} */ + +/* {{{ Get formatter attribute value. */ +U_CFUNC PHP_FUNCTION( numfmt_set_attribute ) +{ + zend_long lattribute; + zval *value; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Oln", + &object, NumberFormatter_ce_ptr, &lattribute, &value ) == FAILURE) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + UNumberFormatAttribute attribute = static_cast(lattribute); + + switch(attribute) { + case UNUM_PARSE_INT_ONLY: + case UNUM_GROUPING_USED: + case UNUM_DECIMAL_ALWAYS_SHOWN: + case UNUM_MAX_INTEGER_DIGITS: + case UNUM_MIN_INTEGER_DIGITS: + case UNUM_INTEGER_DIGITS: + case UNUM_MAX_FRACTION_DIGITS: + case UNUM_MIN_FRACTION_DIGITS: + case UNUM_FRACTION_DIGITS: + case UNUM_MULTIPLIER: + case UNUM_GROUPING_SIZE: + case UNUM_ROUNDING_MODE: + case UNUM_FORMAT_WIDTH: + case UNUM_PADDING_POSITION: + case UNUM_SECONDARY_GROUPING_SIZE: + case UNUM_SIGNIFICANT_DIGITS_USED: + case UNUM_MIN_SIGNIFICANT_DIGITS: + case UNUM_MAX_SIGNIFICANT_DIGITS: + case UNUM_LENIENT_PARSE: + unum_setAttribute(FORMATTER_OBJECT(nfo), attribute, zval_get_long(value)); + break; + case UNUM_ROUNDING_INCREMENT: + unum_setDoubleAttribute(FORMATTER_OBJECT(nfo), attribute, zval_get_double(value)); + break; + default: + INTL_DATA_ERROR_CODE(nfo) = U_UNSUPPORTED_ERROR; + break; + } + + INTL_METHOD_CHECK_STATUS( nfo, "Error setting attribute value" ); + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ Get formatter attribute value. */ +U_CFUNC PHP_FUNCTION( numfmt_set_text_attribute ) +{ + int32_t slength = 0; + UChar *svalue = NULL; + zend_long attribute; + char *value; + size_t len; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ols", + &object, NumberFormatter_ce_ptr, &attribute, &value, &len ) == FAILURE) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + /* Convert given attribute value to UTF-16. */ + intl_convert_utf8_to_utf16(&svalue, &slength, value, len, &INTL_DATA_ERROR_CODE(nfo)); + INTL_METHOD_CHECK_STATUS( nfo, "Error converting attribute value to UTF-16" ); + + /* Actually set new attribute value. */ + unum_setTextAttribute(FORMATTER_OBJECT(nfo), static_cast(attribute), svalue, slength, &INTL_DATA_ERROR_CODE(nfo)); + if (svalue) { + efree(svalue); + } + INTL_METHOD_CHECK_STATUS( nfo, "Error setting text attribute" ); + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ Get formatter symbol value. */ +U_CFUNC PHP_FUNCTION( numfmt_get_symbol ) +{ + zend_long lsymbol; + UChar value_buf[4]; + UChar *value = value_buf; + uint32_t length = USIZE(value_buf); + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ol", + &object, NumberFormatter_ce_ptr, &lsymbol ) == FAILURE ) + { + RETURN_THROWS(); + } + + UNumberFormatSymbol symbol = static_cast(lsymbol); + + if(symbol >= UNUM_FORMAT_SYMBOL_COUNT || symbol < 0) { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "invalid symbol value"); + RETURN_FALSE; + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + length = unum_getSymbol(FORMATTER_OBJECT(nfo), symbol, value_buf, length, &INTL_DATA_ERROR_CODE(nfo)); + if(INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR && length >= USIZE( value_buf )) { + ++length; /* to avoid U_STRING_NOT_TERMINATED_WARNING */ + INTL_DATA_ERROR_CODE(nfo) = U_ZERO_ERROR; + value = eumalloc(length); + length = unum_getSymbol(FORMATTER_OBJECT(nfo), symbol, value, length, &INTL_DATA_ERROR_CODE(nfo)); + if(U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) { + efree(value); + value = value_buf; + } + } + INTL_METHOD_CHECK_STATUS( nfo, "Error getting symbol value" ); + + INTL_METHOD_RETVAL_UTF8( nfo, value, length, ( value_buf != value ) ); +} +/* }}} */ + +/* {{{ Set formatter symbol value. */ +U_CFUNC PHP_FUNCTION( numfmt_set_symbol ) +{ + zend_long lsymbol; + char* value = NULL; + size_t value_len = 0; + UChar* svalue = 0; + int32_t slength = 0; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ols", + &object, NumberFormatter_ce_ptr, &lsymbol, &value, &value_len ) == FAILURE ) + { + RETURN_THROWS(); + } + + UNumberFormatSymbol symbol = static_cast(lsymbol); + + if (symbol >= UNUM_FORMAT_SYMBOL_COUNT || symbol < 0) { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "invalid symbol value"); + RETURN_FALSE; + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + /* Convert given symbol to UTF-16. */ + intl_convert_utf8_to_utf16(&svalue, &slength, value, value_len, &INTL_DATA_ERROR_CODE(nfo)); + INTL_METHOD_CHECK_STATUS( nfo, "Error converting symbol value to UTF-16" ); + + /* Actually set the symbol. */ + unum_setSymbol(FORMATTER_OBJECT(nfo), symbol, svalue, slength, &INTL_DATA_ERROR_CODE(nfo)); + if (svalue) { + efree(svalue); + } + INTL_METHOD_CHECK_STATUS( nfo, "Error setting symbol value" ); + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ Get formatter pattern. */ +U_CFUNC PHP_FUNCTION( numfmt_get_pattern ) +{ + UChar value_buf[64]; + uint32_t length = USIZE( value_buf ); + UChar* value = value_buf; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", + &object, NumberFormatter_ce_ptr ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + length = unum_toPattern(FORMATTER_OBJECT(nfo), 0, value, length, &INTL_DATA_ERROR_CODE(nfo)); + if(INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR && length >= USIZE( value_buf )) { + ++length; /* to avoid U_STRING_NOT_TERMINATED_WARNING */ + INTL_DATA_ERROR_CODE(nfo) = U_ZERO_ERROR; + value = eumalloc(length); + length = unum_toPattern( FORMATTER_OBJECT(nfo), 0, value, length, &INTL_DATA_ERROR_CODE(nfo) ); + if(U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) { + efree(value); + value = value_buf; + } + } + INTL_METHOD_CHECK_STATUS( nfo, "Error getting formatter pattern" ); + + INTL_METHOD_RETVAL_UTF8( nfo, value, length, ( value != value_buf ) ); +} +/* }}} */ + +/* {{{ Set formatter pattern. */ +U_CFUNC PHP_FUNCTION( numfmt_set_pattern ) +{ + char* value = NULL; + size_t value_len = 0; + int32_t slength = 0; + UChar* svalue = NULL; + UParseError spattern_error = {0}; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Os", + &object, NumberFormatter_ce_ptr, &value, &value_len ) == FAILURE ) + { + RETURN_THROWS(); + } + + FORMATTER_METHOD_FETCH_OBJECT; + + /* Convert given pattern to UTF-16. */ + intl_convert_utf8_to_utf16(&svalue, &slength, value, value_len, &INTL_DATA_ERROR_CODE(nfo)); + INTL_METHOD_CHECK_STATUS( nfo, "Error converting pattern to UTF-16" ); + + unum_applyPattern(FORMATTER_OBJECT(nfo), 0, svalue, slength, &spattern_error, &INTL_DATA_ERROR_CODE(nfo)); + if (svalue) { + efree(svalue); + } + 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); + efree(msg); + RETURN_FALSE; + } + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ Get formatter locale. */ +U_CFUNC PHP_FUNCTION( numfmt_get_locale ) +{ + zend_long type = ULOC_ACTUAL_LOCALE; + const char* loc; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O|l", + &object, NumberFormatter_ce_ptr, &type ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + loc = unum_getLocaleByType(FORMATTER_OBJECT(nfo), static_cast(type), &INTL_DATA_ERROR_CODE(nfo)); + INTL_METHOD_CHECK_STATUS( nfo, "Error getting locale" ); + RETURN_STRING(loc); +} +/* }}} */ diff --git a/ext/intl/formatter/formatter_class.c b/ext/intl/formatter/formatter_class.c deleted file mode 100644 index 7832824c94e1c..0000000000000 --- a/ext/intl/formatter/formatter_class.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Stanislav Malyshev | - +----------------------------------------------------------------------+ - */ - -#include - -#include "formatter_class.h" -#include "php_intl.h" -#include "formatter_data.h" -#include "formatter_format.h" - -#include -#include "Zend/zend_attributes.h" -#include "Zend/zend_interfaces.h" - -#include "formatter_arginfo.h" - -zend_class_entry *NumberFormatter_ce_ptr = NULL; -static zend_object_handlers NumberFormatter_handlers; - -/* - * Auxiliary functions needed by objects of 'NumberFormatter' class - */ - -/* {{{ NumberFormatter_objects_free */ -void NumberFormatter_object_free( zend_object *object ) -{ - NumberFormatter_object* nfo = php_intl_number_format_fetch_object(object); - - zend_object_std_dtor( &nfo->zo ); - - formatter_data_free( &nfo->nf_data ); -} -/* }}} */ - -/* {{{ NumberFormatter_object_create */ -zend_object *NumberFormatter_object_create(zend_class_entry *ce) -{ - NumberFormatter_object* intern; - - intern = zend_object_alloc(sizeof(NumberFormatter_object), ce); - formatter_data_init( &intern->nf_data ); - zend_object_std_init( &intern->zo, ce ); - object_properties_init(&intern->zo, ce); - - return &intern->zo; -} -/* }}} */ - -/* {{{ NumberFormatter_object_clone */ -zend_object *NumberFormatter_object_clone(zend_object *object) -{ - NumberFormatter_object *nfo = php_intl_number_format_fetch_object(object); - zend_object *new_obj = NumberFormatter_ce_ptr->create_object(object->ce); - NumberFormatter_object *new_nfo = php_intl_number_format_fetch_object(new_obj); - - /* clone standard parts */ - zend_objects_clone_members(&new_nfo->zo, &nfo->zo); - - /* clone formatter object. It may fail, the destruction code must handle this case */ - if (FORMATTER_OBJECT(nfo) != NULL) { - UErrorCode error = U_ZERO_ERROR; - FORMATTER_OBJECT(new_nfo) = unum_clone(FORMATTER_OBJECT(nfo), &error); - if (U_FAILURE(error)) { - zend_throw_error(NULL, "Failed to clone NumberFormatter"); - } - } else { - zend_throw_error(NULL, "Cannot clone uninitialized NumberFormatter"); - } - return new_obj; -} -/* }}} */ - -/* - * 'NumberFormatter' class registration structures & functions - */ - -/* {{{ formatter_register_class - * Initialize 'NumberFormatter' class - */ -void formatter_register_class( void ) -{ - /* Create and register 'NumberFormatter' class. */ - NumberFormatter_ce_ptr = register_class_NumberFormatter(); - NumberFormatter_ce_ptr->create_object = NumberFormatter_object_create; - NumberFormatter_ce_ptr->default_object_handlers = &NumberFormatter_handlers; - - memcpy(&NumberFormatter_handlers, &std_object_handlers, - sizeof(NumberFormatter_handlers)); - NumberFormatter_handlers.offset = XtOffsetOf(NumberFormatter_object, zo); - NumberFormatter_handlers.clone_obj = NumberFormatter_object_clone; - NumberFormatter_handlers.free_obj = NumberFormatter_object_free; -} -/* }}} */ diff --git a/ext/intl/formatter/formatter_class.cpp b/ext/intl/formatter/formatter_class.cpp new file mode 100644 index 0000000000000..214e1e57dae8a --- /dev/null +++ b/ext/intl/formatter/formatter_class.cpp @@ -0,0 +1,108 @@ +/* + +----------------------------------------------------------------------+ + | 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: Stanislav Malyshev | + +----------------------------------------------------------------------+ + */ + +#include + +#include "formatter_class.h" +extern "C" { +#include "php_intl.h" +#include "formatter_data.h" +#include "formatter_format.h" +} + +#include +#include "Zend/zend_attributes.h" +#include "Zend/zend_interfaces.h" + +extern "C" { +#include "formatter_arginfo.h" +} + +zend_class_entry *NumberFormatter_ce_ptr = NULL; +static zend_object_handlers NumberFormatter_handlers; + +/* + * Auxiliary functions needed by objects of 'NumberFormatter' class + */ + +/* {{{ NumberFormatter_objects_free */ +U_CFUNC void NumberFormatter_object_free( zend_object *object ) +{ + NumberFormatter_object* nfo = php_intl_number_format_fetch_object(object); + + zend_object_std_dtor( &nfo->zo ); + + formatter_data_free( &nfo->nf_data ); +} +/* }}} */ + +/* {{{ NumberFormatter_object_create */ +U_CFUNC zend_object *NumberFormatter_object_create(zend_class_entry *ce) +{ + NumberFormatter_object* intern; + + intern = reinterpret_cast(zend_object_alloc(sizeof(NumberFormatter_object), ce)); + formatter_data_init( &intern->nf_data ); + zend_object_std_init( &intern->zo, ce ); + object_properties_init(&intern->zo, ce); + + return &intern->zo; +} +/* }}} */ + +/* {{{ NumberFormatter_object_clone */ +U_CFUNC zend_object *NumberFormatter_object_clone(zend_object *object) +{ + NumberFormatter_object *nfo = php_intl_number_format_fetch_object(object); + zend_object *new_obj = NumberFormatter_ce_ptr->create_object(object->ce); + NumberFormatter_object *new_nfo = php_intl_number_format_fetch_object(new_obj); + + /* clone standard parts */ + zend_objects_clone_members(&new_nfo->zo, &nfo->zo); + + /* clone formatter object. It may fail, the destruction code must handle this case */ + if (FORMATTER_OBJECT(nfo) != NULL) { + UErrorCode error = U_ZERO_ERROR; + FORMATTER_OBJECT(new_nfo) = unum_clone(FORMATTER_OBJECT(nfo), &error); + if (U_FAILURE(error)) { + zend_throw_error(NULL, "Failed to clone NumberFormatter"); + } + } else { + zend_throw_error(NULL, "Cannot clone uninitialized NumberFormatter"); + } + return new_obj; +} +/* }}} */ + +/* + * 'NumberFormatter' class registration structures & functions + */ + +/* {{{ formatter_register_class + * Initialize 'NumberFormatter' class + */ +U_CFUNC void formatter_register_class( void ) +{ + /* Create and register 'NumberFormatter' class. */ + NumberFormatter_ce_ptr = register_class_NumberFormatter(); + NumberFormatter_ce_ptr->create_object = NumberFormatter_object_create; + NumberFormatter_ce_ptr->default_object_handlers = &NumberFormatter_handlers; + + memcpy(&NumberFormatter_handlers, &std_object_handlers, + sizeof(NumberFormatter_handlers)); + NumberFormatter_handlers.offset = XtOffsetOf(NumberFormatter_object, zo); + NumberFormatter_handlers.clone_obj = NumberFormatter_object_clone; + NumberFormatter_handlers.free_obj = NumberFormatter_object_free; +} +/* }}} */ diff --git a/ext/intl/formatter/formatter_class.h b/ext/intl/formatter/formatter_class.h index f7da2b2201917..bf21825b5f5f4 100644 --- a/ext/intl/formatter/formatter_class.h +++ b/ext/intl/formatter/formatter_class.h @@ -17,10 +17,16 @@ #include +#ifdef __cplusplus +extern "C" { +#endif #include "intl_common.h" #include "intl_error.h" #include "intl_data.h" #include "formatter_data.h" +#ifdef __cplusplus +} +#endif typedef struct { formatter_data nf_data; @@ -32,8 +38,14 @@ static inline NumberFormatter_object *php_intl_number_format_fetch_object(zend_o } #define Z_INTL_NUMBERFORMATTER_P(zv) php_intl_number_format_fetch_object(Z_OBJ_P(zv)) +#ifdef __cplusplus +extern "C" { +#endif void formatter_register_class( void ); extern zend_class_entry *NumberFormatter_ce_ptr; +#ifdef __cplusplus +} +#endif /* Auxiliary macros */ diff --git a/ext/intl/formatter/formatter_data.c b/ext/intl/formatter/formatter_data.c deleted file mode 100644 index 57dbc8bde6b5e..0000000000000 --- a/ext/intl/formatter/formatter_data.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Stanislav Malyshev | - +----------------------------------------------------------------------+ - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "formatter_data.h" - -/* {{{ void formatter_data_init( formatter_data* nf_data ) - * Initialize internals of formatter_data. - */ -void formatter_data_init( formatter_data* nf_data ) -{ - if( !nf_data ) - return; - - nf_data->unum = NULL; - intl_error_reset( &nf_data->error ); -} -/* }}} */ - -/* {{{ void formatter_data_free( formatter_data* nf_data ) - * Clean up mem allocted by internals of formatter_data - */ -void formatter_data_free( formatter_data* nf_data ) -{ - if( !nf_data ) - return; - - if( nf_data->unum ) - unum_close( nf_data->unum ); - - nf_data->unum = NULL; - intl_error_reset( &nf_data->error ); -} -/* }}} */ - -/* {{{ formatter_data* formatter_data_create() - * Alloc mem for formatter_data and initialize it with default values. - */ -formatter_data* formatter_data_create( void ) -{ - formatter_data* nf_data = ecalloc( 1, sizeof(formatter_data) ); - - formatter_data_init( nf_data ); - - return nf_data; -} -/* }}} */ diff --git a/ext/intl/formatter/formatter_data.cpp b/ext/intl/formatter/formatter_data.cpp new file mode 100644 index 0000000000000..095be92ed29e1 --- /dev/null +++ b/ext/intl/formatter/formatter_data.cpp @@ -0,0 +1,61 @@ +/* + +----------------------------------------------------------------------+ + | 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: Stanislav Malyshev | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "formatter_data.h" + +/* {{{ void formatter_data_init( formatter_data* nf_data ) + * Initialize internals of formatter_data. + */ +void formatter_data_init( formatter_data* nf_data ) +{ + if( !nf_data ) + return; + + nf_data->unum = NULL; + intl_error_reset( &nf_data->error ); +} +/* }}} */ + +/* {{{ void formatter_data_free( formatter_data* nf_data ) + * Clean up mem allocted by internals of formatter_data + */ +void formatter_data_free( formatter_data* nf_data ) +{ + if( !nf_data ) + return; + + if( nf_data->unum ) + unum_close( nf_data->unum ); + + nf_data->unum = NULL; + intl_error_reset( &nf_data->error ); +} +/* }}} */ + +/* {{{ formatter_data* formatter_data_create() + * Alloc mem for formatter_data and initialize it with default values. + */ +formatter_data* formatter_data_create( void ) +{ + formatter_data* nf_data = reinterpret_cast(ecalloc( 1, sizeof(formatter_data) )); + + formatter_data_init( nf_data ); + + return nf_data; +} +/* }}} */ diff --git a/ext/intl/formatter/formatter_data.h b/ext/intl/formatter/formatter_data.h index 817ad0d6055f3..35acc242a8db9 100644 --- a/ext/intl/formatter/formatter_data.h +++ b/ext/intl/formatter/formatter_data.h @@ -19,7 +19,13 @@ #include +#ifdef __cplusplus +extern "C" { +#endif #include "intl_error.h" +#ifdef __cplusplus +} +#endif typedef struct { // error hangling @@ -29,8 +35,14 @@ typedef struct { UNumberFormat* unum; } formatter_data; +#ifdef __cplusplus +extern "C" { +#endif formatter_data* formatter_data_create( void ); void formatter_data_init( formatter_data* nf_data ); void formatter_data_free( formatter_data* nf_data ); +#ifdef __cplusplus +} +#endif #endif // FORMATTER_DATA_H diff --git a/ext/intl/formatter/formatter_format.c b/ext/intl/formatter/formatter_format.c deleted file mode 100644 index 54c5d92fe18a1..0000000000000 --- a/ext/intl/formatter/formatter_format.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Stanislav Malyshev | - +----------------------------------------------------------------------+ - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "php_intl.h" - -#include - -#include "formatter_class.h" -#include "formatter_format.h" -#include "intl_convert.h" - -/* {{{ Format a number. */ -PHP_FUNCTION( numfmt_format ) -{ - zval *number; - zend_long type = FORMAT_TYPE_DEFAULT; - UChar format_buf[32]; - UChar* formatted = format_buf; - int32_t formatted_len = USIZE(format_buf); - FORMATTER_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "On|l", - &object, NumberFormatter_ce_ptr, &number, &type ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - FORMATTER_METHOD_FETCH_OBJECT; - - if(type == FORMAT_TYPE_DEFAULT) { - switch(Z_TYPE_P(number)) { - case IS_LONG: - /* take INT32 on 32-bit, int64 on 64-bit */ - type = (sizeof(zend_long) == 8)?FORMAT_TYPE_INT64:FORMAT_TYPE_INT32; - break; - case IS_DOUBLE: - type = FORMAT_TYPE_DOUBLE; - break; - EMPTY_SWITCH_DEFAULT_CASE(); - } - } - - switch(type) { - case FORMAT_TYPE_INT32: - convert_to_long(number); - formatted_len = unum_format(FORMATTER_OBJECT(nfo), (int32_t)Z_LVAL_P(number), - formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); - if (INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR) { - intl_error_reset(INTL_DATA_ERROR_P(nfo)); - formatted = eumalloc(formatted_len); - formatted_len = unum_format(FORMATTER_OBJECT(nfo), (int32_t)Z_LVAL_P(number), - formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); - if (U_FAILURE( INTL_DATA_ERROR_CODE(nfo) ) ) { - efree(formatted); - } - } - INTL_METHOD_CHECK_STATUS( nfo, "Number formatting failed" ); - break; - - case FORMAT_TYPE_INT64: - { - int64_t value = (Z_TYPE_P(number) == IS_DOUBLE)?(int64_t)Z_DVAL_P(number):Z_LVAL_P(number); - formatted_len = unum_formatInt64(FORMATTER_OBJECT(nfo), value, formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); - if (INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR) { - intl_error_reset(INTL_DATA_ERROR_P(nfo)); - formatted = eumalloc(formatted_len); - formatted_len = unum_formatInt64(FORMATTER_OBJECT(nfo), value, formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); - if (U_FAILURE( INTL_DATA_ERROR_CODE(nfo) ) ) { - efree(formatted); - } - } - INTL_METHOD_CHECK_STATUS( nfo, "Number formatting failed" ); - } - break; - - case FORMAT_TYPE_DOUBLE: - convert_to_double(number); - formatted_len = unum_formatDouble(FORMATTER_OBJECT(nfo), Z_DVAL_P(number), formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); - if (INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR) { - intl_error_reset(INTL_DATA_ERROR_P(nfo)); - formatted = eumalloc(formatted_len); - unum_formatDouble(FORMATTER_OBJECT(nfo), Z_DVAL_P(number), formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); - if (U_FAILURE( INTL_DATA_ERROR_CODE(nfo) ) ) { - efree(formatted); - } - } - INTL_METHOD_CHECK_STATUS( nfo, "Number formatting failed" ); - break; - case FORMAT_TYPE_CURRENCY: - 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, " - "use %s%sformatCurrency() method instead", class_name, space); - } else { - zend_argument_value_error(3, "cannot be NumberFormatter::TYPE_CURRENCY constant, use numfmt_format_currency() function instead"); - } - RETURN_THROWS(); - default: - zend_argument_value_error(hasThis() ? 2 : 3, "must be a NumberFormatter::TYPE_* constant"); - RETURN_THROWS(); - } - - INTL_METHOD_RETVAL_UTF8( nfo, formatted, formatted_len, ( formatted != format_buf ) ); -} -/* }}} */ - -/* {{{ Format a number as currency. */ -PHP_FUNCTION( numfmt_format_currency ) -{ - double number; - UChar format_buf[32]; - UChar* formatted = format_buf; - int32_t formatted_len = USIZE(format_buf); - char* currency = NULL; - size_t currency_len = 0; - UChar* scurrency = NULL; - int32_t scurrency_len = 0; - FORMATTER_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ods", - &object, NumberFormatter_ce_ptr, &number, ¤cy, ¤cy_len ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - FORMATTER_METHOD_FETCH_OBJECT; - - /* Convert currency to UTF-16. */ - intl_convert_utf8_to_utf16(&scurrency, &scurrency_len, currency, currency_len, &INTL_DATA_ERROR_CODE(nfo)); - INTL_METHOD_CHECK_STATUS( nfo, "Currency conversion to UTF-16 failed" ); - - /* Format the number using a fixed-length buffer. */ - formatted_len = unum_formatDoubleCurrency(FORMATTER_OBJECT(nfo), number, scurrency, formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); - - /* If the buffer turned out to be too small - * then allocate another buffer dynamically - * and use it to format the number. - */ - if (INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR) { - intl_error_reset(INTL_DATA_ERROR_P(nfo)); - formatted = eumalloc(formatted_len); - unum_formatDoubleCurrency(FORMATTER_OBJECT(nfo), number, scurrency, formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); - } - - 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 ); - RETVAL_FALSE; - if (formatted != format_buf) { - efree(formatted); - } - } else { - INTL_METHOD_RETVAL_UTF8( nfo, formatted, formatted_len, ( formatted != format_buf ) ); - } - - if(scurrency) { - efree(scurrency); - } -} - -/* }}} */ diff --git a/ext/intl/formatter/formatter_format.cpp b/ext/intl/formatter/formatter_format.cpp new file mode 100644 index 0000000000000..f28ea30b9ff8f --- /dev/null +++ b/ext/intl/formatter/formatter_format.cpp @@ -0,0 +1,183 @@ +/* + +----------------------------------------------------------------------+ + | 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: Stanislav Malyshev | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +extern "C" { +#include "php_intl.h" +#include "intl_convert.h" +} + +#include + +#include "formatter_class.h" +#include "formatter_format.h" + +/* {{{ Format a number. */ +U_CFUNC PHP_FUNCTION( numfmt_format ) +{ + zval *number; + zend_long type = FORMAT_TYPE_DEFAULT; + UChar format_buf[32]; + UChar* formatted = format_buf; + int32_t formatted_len = USIZE(format_buf); + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "On|l", + &object, NumberFormatter_ce_ptr, &number, &type ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + if(type == FORMAT_TYPE_DEFAULT) { + switch(Z_TYPE_P(number)) { + case IS_LONG: + /* take INT32 on 32-bit, int64 on 64-bit */ + type = (sizeof(zend_long) == 8)?FORMAT_TYPE_INT64:FORMAT_TYPE_INT32; + break; + case IS_DOUBLE: + type = FORMAT_TYPE_DOUBLE; + break; + EMPTY_SWITCH_DEFAULT_CASE(); + } + } + + switch(type) { + case FORMAT_TYPE_INT32: + convert_to_long(number); + formatted_len = unum_format(FORMATTER_OBJECT(nfo), (int32_t)Z_LVAL_P(number), + formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); + if (INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR) { + intl_error_reset(INTL_DATA_ERROR_P(nfo)); + formatted = eumalloc(formatted_len); + formatted_len = unum_format(FORMATTER_OBJECT(nfo), (int32_t)Z_LVAL_P(number), + formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); + if (U_FAILURE( INTL_DATA_ERROR_CODE(nfo) ) ) { + efree(formatted); + } + } + INTL_METHOD_CHECK_STATUS( nfo, "Number formatting failed" ); + break; + + case FORMAT_TYPE_INT64: + { + int64_t value = (Z_TYPE_P(number) == IS_DOUBLE)?(int64_t)Z_DVAL_P(number):Z_LVAL_P(number); + formatted_len = unum_formatInt64(FORMATTER_OBJECT(nfo), value, formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); + if (INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR) { + intl_error_reset(INTL_DATA_ERROR_P(nfo)); + formatted = eumalloc(formatted_len); + formatted_len = unum_formatInt64(FORMATTER_OBJECT(nfo), value, formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); + if (U_FAILURE( INTL_DATA_ERROR_CODE(nfo) ) ) { + efree(formatted); + } + } + INTL_METHOD_CHECK_STATUS( nfo, "Number formatting failed" ); + } + break; + + case FORMAT_TYPE_DOUBLE: + convert_to_double(number); + formatted_len = unum_formatDouble(FORMATTER_OBJECT(nfo), Z_DVAL_P(number), formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); + if (INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR) { + intl_error_reset(INTL_DATA_ERROR_P(nfo)); + formatted = eumalloc(formatted_len); + unum_formatDouble(FORMATTER_OBJECT(nfo), Z_DVAL_P(number), formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); + if (U_FAILURE( INTL_DATA_ERROR_CODE(nfo) ) ) { + efree(formatted); + } + } + INTL_METHOD_CHECK_STATUS( nfo, "Number formatting failed" ); + break; + case FORMAT_TYPE_CURRENCY: + 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, " + "use %s%sformatCurrency() method instead", class_name, space); + } else { + zend_argument_value_error(3, "cannot be NumberFormatter::TYPE_CURRENCY constant, use numfmt_format_currency() function instead"); + } + RETURN_THROWS(); + default: + zend_argument_value_error(hasThis() ? 2 : 3, "must be a NumberFormatter::TYPE_* constant"); + RETURN_THROWS(); + } + + INTL_METHOD_RETVAL_UTF8( nfo, formatted, formatted_len, ( formatted != format_buf ) ); +} +/* }}} */ + +/* {{{ Format a number as currency. */ +U_CFUNC PHP_FUNCTION( numfmt_format_currency ) +{ + double number; + UChar format_buf[32]; + UChar* formatted = format_buf; + int32_t formatted_len = USIZE(format_buf); + char* currency = NULL; + size_t currency_len = 0; + UChar* scurrency = NULL; + int32_t scurrency_len = 0; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ods", + &object, NumberFormatter_ce_ptr, &number, ¤cy, ¤cy_len ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + /* Convert currency to UTF-16. */ + intl_convert_utf8_to_utf16(&scurrency, &scurrency_len, currency, currency_len, &INTL_DATA_ERROR_CODE(nfo)); + INTL_METHOD_CHECK_STATUS( nfo, "Currency conversion to UTF-16 failed" ); + + /* Format the number using a fixed-length buffer. */ + formatted_len = unum_formatDoubleCurrency(FORMATTER_OBJECT(nfo), number, scurrency, formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); + + /* If the buffer turned out to be too small + * then allocate another buffer dynamically + * and use it to format the number. + */ + if (INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR) { + intl_error_reset(INTL_DATA_ERROR_P(nfo)); + formatted = eumalloc(formatted_len); + unum_formatDoubleCurrency(FORMATTER_OBJECT(nfo), number, scurrency, formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo)); + } + + 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"); + RETVAL_FALSE; + if (formatted != format_buf) { + efree(formatted); + } + } else { + INTL_METHOD_RETVAL_UTF8( nfo, formatted, formatted_len, ( formatted != format_buf ) ); + } + + if(scurrency) { + efree(scurrency); + } +} + +/* }}} */ diff --git a/ext/intl/formatter/formatter_main.c b/ext/intl/formatter/formatter_main.c deleted file mode 100644 index 6f8fb98d21434..0000000000000 --- a/ext/intl/formatter/formatter_main.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Stanislav Malyshev | - +----------------------------------------------------------------------+ - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include "php_intl.h" -#include "formatter_class.h" -#include "intl_convert.h" - -/* {{{ */ -static int numfmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling *error_handling, bool *error_handling_replaced) -{ - char* locale; - char* pattern = NULL; - size_t locale_len = 0, pattern_len = 0; - zend_long style; - UChar* spattern = NULL; - int32_t spattern_len = 0; - FORMATTER_METHOD_INIT_VARS; - - ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_STRING(locale, locale_len) - Z_PARAM_LONG(style) - Z_PARAM_OPTIONAL - 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; - if (FORMATTER_OBJECT(nfo)) { - zend_throw_error(NULL, "NumberFormatter object is already constructed"); - return FAILURE; - } - - /* 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"); - } - - if(locale_len == 0) { - locale = (char *)intl_locale_get_default(); - } - - if (strlen(uloc_getISO3Language(locale)) == 0) { - zend_argument_value_error(1, "\"%s\" is invalid", locale); - return FAILURE; - } - - /* Create an ICU number formatter. */ - FORMATTER_OBJECT(nfo) = unum_open(style, spattern, spattern_len, locale, NULL, &INTL_DATA_ERROR_CODE(nfo)); - - if(spattern) { - efree(spattern); - } - - INTL_CTOR_CHECK_STATUS(nfo, "numfmt_create: number formatter creation failed"); - return SUCCESS; -} -/* }}} */ - -/* {{{ Create number formatter. */ -PHP_FUNCTION( numfmt_create ) -{ - object_init_ex( return_value, NumberFormatter_ce_ptr ); - if (numfmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL, NULL) == FAILURE) { - zval_ptr_dtor(return_value); - RETURN_NULL(); - } -} -/* }}} */ - -/* {{{ NumberFormatter object constructor. */ -PHP_METHOD( NumberFormatter, __construct ) -{ - zend_error_handling error_handling; - bool error_handling_replaced = 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); - } -} -/* }}} */ - -/* {{{ Get formatter's last error code. */ -PHP_FUNCTION( numfmt_get_error_code ) -{ - FORMATTER_METHOD_INIT_VARS - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", - &object, NumberFormatter_ce_ptr ) == FAILURE ) - { - RETURN_THROWS(); - } - - nfo = Z_INTL_NUMBERFORMATTER_P(object); - - /* Return formatter's last error code. */ - RETURN_LONG( INTL_DATA_ERROR_CODE(nfo) ); -} -/* }}} */ - -/* {{{ Get text description for formatter's last error code. */ -PHP_FUNCTION( numfmt_get_error_message ) -{ - zend_string *message = NULL; - FORMATTER_METHOD_INIT_VARS - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", - &object, NumberFormatter_ce_ptr ) == FAILURE ) - { - RETURN_THROWS(); - } - - nfo = Z_INTL_NUMBERFORMATTER_P(object); - - /* Return last error message. */ - message = intl_error_get_message( INTL_DATA_ERROR_P(nfo) ); - RETURN_STR(message); -} -/* }}} */ diff --git a/ext/intl/formatter/formatter_main.cpp b/ext/intl/formatter/formatter_main.cpp new file mode 100644 index 0000000000000..a014323089a7e --- /dev/null +++ b/ext/intl/formatter/formatter_main.cpp @@ -0,0 +1,154 @@ +/* + +----------------------------------------------------------------------+ + | 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: Stanislav Malyshev | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +extern "C" { +#include "php_intl.h" +#include "intl_convert.h" +} +#include "formatter_class.h" + +/* {{{ */ +static int numfmt_ctor(INTERNAL_FUNCTION_PARAMETERS) +{ + char* locale; + char* pattern = NULL; + size_t locale_len = 0, pattern_len = 0; + zend_long style; + UChar* spattern = NULL; + int32_t spattern_len = 0; + FORMATTER_METHOD_INIT_VARS; + + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_STRING(locale, locale_len) + Z_PARAM_LONG(style) + Z_PARAM_OPTIONAL + Z_PARAM_STRING_OR_NULL(pattern, pattern_len) + ZEND_PARSE_PARAMETERS_END_EX(return FAILURE); + + INTL_CHECK_LOCALE_LEN_OR_FAILURE(locale_len); + object = return_value; + FORMATTER_METHOD_FETCH_OBJECT_NO_CHECK; + if (FORMATTER_OBJECT(nfo)) { + zend_throw_error(NULL, "NumberFormatter object is already constructed"); + return FAILURE; + } + + /* 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, "error converting pattern to UTF-16"); + } + + if(locale_len == 0) { + locale = (char *)intl_locale_get_default(); + } + + if (strlen(uloc_getISO3Language(locale)) == 0) { + zend_argument_value_error(1, "\"%s\" is invalid", locale); + return FAILURE; + } + + char* canonicalized_locale = canonicalize_locale_string(locale); + const char* final_locale = canonicalized_locale ? canonicalized_locale : locale; + + /* Create an ICU number formatter. */ + FORMATTER_OBJECT(nfo) = unum_open(static_cast(style), spattern, spattern_len, final_locale, nullptr, &INTL_DATA_ERROR_CODE(nfo)); + + if (spattern) { + efree(spattern); + } + + if (canonicalized_locale) { + efree(canonicalized_locale); + } + + INTL_CTOR_CHECK_STATUS(nfo, "number formatter creation failed"); + return SUCCESS; +} +/* }}} */ + +/* {{{ Create number formatter. */ +U_CFUNC PHP_FUNCTION( numfmt_create ) +{ + object_init_ex( return_value, NumberFormatter_ce_ptr ); + if (numfmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU) == FAILURE) { + zval_ptr_dtor(return_value); + RETURN_NULL(); + } +} +/* }}} */ + +/* {{{ NumberFormatter object constructor. */ +U_CFUNC PHP_METHOD( NumberFormatter, __construct ) +{ + 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) == 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. */ +U_CFUNC PHP_FUNCTION( numfmt_get_error_code ) +{ + FORMATTER_METHOD_INIT_VARS + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", + &object, NumberFormatter_ce_ptr ) == FAILURE ) + { + RETURN_THROWS(); + } + + nfo = Z_INTL_NUMBERFORMATTER_P(object); + + /* Return formatter's last error code. */ + RETURN_LONG( INTL_DATA_ERROR_CODE(nfo) ); +} +/* }}} */ + +/* {{{ Get text description for formatter's last error code. */ +U_CFUNC PHP_FUNCTION( numfmt_get_error_message ) +{ + zend_string *message = NULL; + FORMATTER_METHOD_INIT_VARS + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", + &object, NumberFormatter_ce_ptr ) == FAILURE ) + { + RETURN_THROWS(); + } + + nfo = Z_INTL_NUMBERFORMATTER_P(object); + + /* Return last error message. */ + message = intl_error_get_message( INTL_DATA_ERROR_P(nfo) ); + RETURN_STR(message); +} +/* }}} */ diff --git a/ext/intl/formatter/formatter_parse.c b/ext/intl/formatter/formatter_parse.c deleted file mode 100644 index ba8307419b4cf..0000000000000 --- a/ext/intl/formatter/formatter_parse.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Stanislav Malyshev | - +----------------------------------------------------------------------+ - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "php_intl.h" - -#include -#include - -#include "formatter_class.h" -#include "formatter_format.h" -#include "intl_convert.h" - -#define ICU_LOCALE_BUG 1 - -/* {{{ Parse a number. */ -PHP_FUNCTION( numfmt_parse ) -{ - zend_long type = FORMAT_TYPE_DOUBLE; - UChar* sstr = NULL; - int32_t sstr_len = 0; - char* str = NULL; - size_t str_len; - int32_t val32, position = 0; - int64_t val64; - double val_double; - int32_t* position_p = NULL; - zval *zposition = NULL; - char *oldlocale; - FORMATTER_METHOD_INIT_VARS; - - /* Parse parameters. */ - if (zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Os|lz!", - &object, NumberFormatter_ce_ptr, &str, &str_len, &type, &zposition ) == FAILURE ) - { - RETURN_THROWS(); - } - - if (zposition) { - position = (int32_t) zval_get_long(zposition); - position_p = &position; - } - - /* Fetch the object. */ - FORMATTER_METHOD_FETCH_OBJECT; - - /* Convert given string to UTF-16. */ - intl_convert_utf8_to_utf16(&sstr, &sstr_len, str, str_len, &INTL_DATA_ERROR_CODE(nfo)); - INTL_METHOD_CHECK_STATUS( nfo, "String conversion to UTF-16 failed" ); - -#if ICU_LOCALE_BUG && defined(LC_NUMERIC) - /* need to copy here since setlocale may change it later */ - oldlocale = estrdup(setlocale(LC_NUMERIC, NULL)); - setlocale(LC_NUMERIC, "C"); -#endif - - switch(type) { - case FORMAT_TYPE_INT32: - val32 = unum_parse(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, &INTL_DATA_ERROR_CODE(nfo)); - RETVAL_LONG(val32); - break; - case FORMAT_TYPE_INT64: - val64 = unum_parseInt64(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, &INTL_DATA_ERROR_CODE(nfo)); - if(val64 > ZEND_LONG_MAX || val64 < ZEND_LONG_MIN) { - RETVAL_DOUBLE(val64); - } else { - RETVAL_LONG((zend_long)val64); - } - break; - case FORMAT_TYPE_DOUBLE: - val_double = unum_parseDouble(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, &INTL_DATA_ERROR_CODE(nfo)); - RETVAL_DOUBLE(val_double); - break; - case FORMAT_TYPE_CURRENCY: - 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, " - "use %s%sparseCurrency() method instead", class_name, space); - } else { - zend_argument_value_error(3, "cannot be NumberFormatter::TYPE_CURRENCY constant, use numfmt_parse_currency() function instead"); - } - goto cleanup; - default: - zend_argument_value_error(hasThis() ? 2 : 3, "must be a NumberFormatter::TYPE_* constant"); - goto cleanup; - } - - if (zposition) { - ZEND_TRY_ASSIGN_REF_LONG(zposition, position); - } - -cleanup: - -#if ICU_LOCALE_BUG && defined(LC_NUMERIC) - setlocale(LC_NUMERIC, oldlocale); - efree(oldlocale); -#endif - - if (sstr) { - efree(sstr); - } - - INTL_METHOD_CHECK_STATUS( nfo, "Number parsing failed" ); -} -/* }}} */ - -/* {{{ Parse a number as currency. */ -PHP_FUNCTION( numfmt_parse_currency ) -{ - double number; - UChar currency[5] = {0}; - UChar* sstr = NULL; - int32_t sstr_len = 0; - zend_string *u8str; - char *str; - size_t str_len; - int32_t* position_p = NULL; - int32_t position = 0; - zval *zcurrency, *zposition = NULL; - FORMATTER_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Osz|z!", - &object, NumberFormatter_ce_ptr, &str, &str_len, &zcurrency, &zposition ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - FORMATTER_METHOD_FETCH_OBJECT; - - /* Convert given string to UTF-16. */ - intl_convert_utf8_to_utf16(&sstr, &sstr_len, str, str_len, &INTL_DATA_ERROR_CODE(nfo)); - INTL_METHOD_CHECK_STATUS( nfo, "String conversion to UTF-16 failed" ); - - if(zposition) { - position = (int32_t) zval_get_long(zposition); - position_p = &position; - } - - number = unum_parseDoubleCurrency(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, currency, &INTL_DATA_ERROR_CODE(nfo)); - if(zposition) { - ZEND_TRY_ASSIGN_REF_LONG(zposition, position); - } - if (sstr) { - efree(sstr); - } - INTL_METHOD_CHECK_STATUS( nfo, "Number parsing failed" ); - - /* Convert parsed currency to UTF-8 and pass it back to caller. */ - u8str = intl_convert_utf16_to_utf8(currency, u_strlen(currency), &INTL_DATA_ERROR_CODE(nfo)); - INTL_METHOD_CHECK_STATUS( nfo, "Currency conversion to UTF-8 failed" ); - ZEND_TRY_ASSIGN_REF_NEW_STR(zcurrency, u8str); - - RETVAL_DOUBLE( number ); -} -/* }}} */ diff --git a/ext/intl/formatter/formatter_parse.cpp b/ext/intl/formatter/formatter_parse.cpp new file mode 100644 index 0000000000000..c7d0df8cbda02 --- /dev/null +++ b/ext/intl/formatter/formatter_parse.cpp @@ -0,0 +1,174 @@ +/* + +----------------------------------------------------------------------+ + | 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: Stanislav Malyshev | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +extern "C" { +#include "php_intl.h" +#include "intl_convert.h" +} + +#include +#include + +#include "formatter_class.h" +#include "formatter_format.h" + +#define ICU_LOCALE_BUG 1 + +/* {{{ Parse a number. */ +U_CFUNC PHP_FUNCTION( numfmt_parse ) +{ + zend_long type = FORMAT_TYPE_DOUBLE; + UChar* sstr = NULL; + int32_t sstr_len = 0; + char* str = NULL; + size_t str_len; + int32_t val32, position = 0; + int64_t val64; + double val_double; + int32_t* position_p = NULL; + zval *zposition = NULL; + char *oldlocale; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if (zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Os|lz!", + &object, NumberFormatter_ce_ptr, &str, &str_len, &type, &zposition ) == FAILURE ) + { + RETURN_THROWS(); + } + + if (zposition) { + position = (int32_t) zval_get_long(zposition); + position_p = &position; + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + /* Convert given string to UTF-16. */ + intl_convert_utf8_to_utf16(&sstr, &sstr_len, str, str_len, &INTL_DATA_ERROR_CODE(nfo)); + INTL_METHOD_CHECK_STATUS( nfo, "String conversion to UTF-16 failed" ); + +#if ICU_LOCALE_BUG && defined(LC_NUMERIC) + /* need to copy here since setlocale may change it later */ + oldlocale = estrdup(setlocale(LC_NUMERIC, NULL)); + setlocale(LC_NUMERIC, "C"); +#endif + + switch(type) { + case FORMAT_TYPE_INT32: + val32 = unum_parse(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, &INTL_DATA_ERROR_CODE(nfo)); + RETVAL_LONG(val32); + break; + case FORMAT_TYPE_INT64: + val64 = unum_parseInt64(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, &INTL_DATA_ERROR_CODE(nfo)); + if(val64 > ZEND_LONG_MAX || val64 < ZEND_LONG_MIN) { + RETVAL_DOUBLE(val64); + } else { + RETVAL_LONG((zend_long)val64); + } + break; + case FORMAT_TYPE_DOUBLE: + val_double = unum_parseDouble(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, &INTL_DATA_ERROR_CODE(nfo)); + RETVAL_DOUBLE(val_double); + break; + case FORMAT_TYPE_CURRENCY: + 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, " + "use %s%sparseCurrency() method instead", class_name, space); + } else { + zend_argument_value_error(3, "cannot be NumberFormatter::TYPE_CURRENCY constant, use numfmt_parse_currency() function instead"); + } + goto cleanup; + default: + zend_argument_value_error(hasThis() ? 2 : 3, "must be a NumberFormatter::TYPE_* constant"); + goto cleanup; + } + + if (zposition) { + ZEND_TRY_ASSIGN_REF_LONG(zposition, position); + } + +cleanup: + +#if ICU_LOCALE_BUG && defined(LC_NUMERIC) + setlocale(LC_NUMERIC, oldlocale); + efree(oldlocale); +#endif + + if (sstr) { + efree(sstr); + } + + INTL_METHOD_CHECK_STATUS( nfo, "Number parsing failed" ); +} +/* }}} */ + +/* {{{ Parse a number as currency. */ +U_CFUNC PHP_FUNCTION( numfmt_parse_currency ) +{ + double number; + UChar currency[5] = {0}; + UChar* sstr = NULL; + int32_t sstr_len = 0; + zend_string *u8str; + char *str; + size_t str_len; + int32_t* position_p = NULL; + int32_t position = 0; + zval *zcurrency, *zposition = NULL; + FORMATTER_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Osz|z!", + &object, NumberFormatter_ce_ptr, &str, &str_len, &zcurrency, &zposition ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + FORMATTER_METHOD_FETCH_OBJECT; + + /* Convert given string to UTF-16. */ + intl_convert_utf8_to_utf16(&sstr, &sstr_len, str, str_len, &INTL_DATA_ERROR_CODE(nfo)); + INTL_METHOD_CHECK_STATUS( nfo, "String conversion to UTF-16 failed" ); + + if(zposition) { + position = (int32_t) zval_get_long(zposition); + position_p = &position; + } + + number = unum_parseDoubleCurrency(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, currency, &INTL_DATA_ERROR_CODE(nfo)); + if(zposition) { + ZEND_TRY_ASSIGN_REF_LONG(zposition, position); + } + if (sstr) { + efree(sstr); + } + INTL_METHOD_CHECK_STATUS( nfo, "Number parsing failed" ); + + /* Convert parsed currency to UTF-8 and pass it back to caller. */ + u8str = intl_convert_utf16_to_utf8(currency, u_strlen(currency), &INTL_DATA_ERROR_CODE(nfo)); + INTL_METHOD_CHECK_STATUS( nfo, "Currency conversion to UTF-8 failed" ); + ZEND_TRY_ASSIGN_REF_NEW_STR(zcurrency, u8str); + + RETVAL_DOUBLE( number ); +} +/* }}} */ diff --git a/ext/intl/grapheme/grapheme.h b/ext/intl/grapheme/grapheme.h index 003e0d49317a9..8ec470d479272 100644 --- a/ext/intl/grapheme/grapheme.h +++ b/ext/intl/grapheme/grapheme.h @@ -18,7 +18,13 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif void grapheme_close_global_iterator( void ); +#ifdef __cplusplus +} +#endif #define GRAPHEME_EXTRACT_TYPE_COUNT 0 #define GRAPHEME_EXTRACT_TYPE_MAXBYTES 1 diff --git a/ext/intl/grapheme/grapheme_string.c b/ext/intl/grapheme/grapheme_string.c deleted file mode 100644 index 34dd2ed369cfc..0000000000000 --- a/ext/intl/grapheme/grapheme_string.c +++ /dev/null @@ -1,1120 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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. | - +----------------------------------------------------------------------+ - | Author: Ed Batutis | - +----------------------------------------------------------------------+ - */ - -/* {{{ includes */ -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include "grapheme.h" -#include "grapheme_util.h" - -#include -#include -#include -#include -#include - -/* }}} */ - -/* {{{ Get number of graphemes in a string */ -PHP_FUNCTION(grapheme_strlen) -{ - char* string; - size_t string_len; - UChar* ustring = NULL; - int ustring_len = 0; - zend_long ret_len; - UErrorCode status; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(string, string_len) - ZEND_PARSE_PARAMETERS_END(); - - ret_len = grapheme_ascii_check((unsigned char *)string, string_len); - - if ( ret_len >= 0 ) - RETURN_LONG(string_len); - - /* convert the string to UTF-16. */ - status = U_ZERO_ERROR; - intl_convert_utf8_to_utf16(&ustring, &ustring_len, string, string_len, &status ); - - if ( U_FAILURE( status ) ) { - /* Set global error code. */ - intl_error_set_code( NULL, status ); - - /* Set error messages. */ - intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16", 0 ); - if (ustring) { - efree( ustring ); - } - RETURN_NULL(); - } - - ret_len = grapheme_split_string(ustring, ustring_len, NULL, 0 ); - - if (ustring) { - efree( ustring ); - } - - if (ret_len >= 0) { - RETVAL_LONG(ret_len); - } else { - RETVAL_FALSE; - } -} -/* }}} */ - -/* {{{ Find position of first occurrence of a string within another */ -PHP_FUNCTION(grapheme_strpos) -{ - char *haystack, *needle; - size_t haystack_len, needle_len; - 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) - Z_PARAM_STRING(haystack, haystack_len) - Z_PARAM_STRING(needle, needle_len) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(loffset) - ZEND_PARSE_PARAMETERS_END(); - - if ( OUTSIDE_STRING(loffset, haystack_len) ) { - zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); - RETURN_THROWS(); - } - - /* we checked that it will fit: */ - offset = (int32_t) loffset; - noffset = offset >= 0 ? offset : (int32_t)haystack_len + offset; - - /* the offset is 'grapheme count offset' so it still might be invalid - we'll check it later */ - - if (offset >= 0 && grapheme_ascii_check((unsigned char *)haystack, haystack_len) >= 0) { - /* quick check to see if the string might be there - * I realize that 'offset' is 'grapheme count offset' but will work in spite of that - */ - found = php_memnstr(haystack + noffset, needle, needle_len, haystack + haystack_len); - - /* if it isn't there the we are done */ - if (found) { - RETURN_LONG(found - haystack); - } - RETURN_FALSE; - } - - /* do utf16 part of the strpos */ - ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, NULL, 0 /* fIgnoreCase */, 0 /* last */ ); - - if ( ret_pos >= 0 ) { - RETURN_LONG(ret_pos); - } else { - RETURN_FALSE; - } -} -/* }}} */ - -/* {{{ 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; - const char *found; - zend_long loffset = 0; - int32_t offset = 0; - zend_long ret_pos; - int is_ascii; - - ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_STRING(haystack, haystack_len) - Z_PARAM_STRING(needle, needle_len) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(loffset) - ZEND_PARSE_PARAMETERS_END(); - - if ( OUTSIDE_STRING(loffset, haystack_len) ) { - zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); - RETURN_THROWS(); - } - - /* we checked that it will fit: */ - offset = (int32_t) loffset; - - /* the offset is 'grapheme count offset' so it still might be invalid - we'll check it later */ - - is_ascii = ( grapheme_ascii_check((unsigned char*)haystack, haystack_len) >= 0 ); - - if ( is_ascii ) { - char *haystack_dup, *needle_dup; - int32_t noffset = offset >= 0 ? offset : (int32_t)haystack_len + offset; - needle_dup = estrndup(needle, needle_len); - zend_str_tolower(needle_dup, needle_len); - haystack_dup = estrndup(haystack, haystack_len); - zend_str_tolower(haystack_dup, haystack_len); - - found = php_memnstr(haystack_dup + noffset, needle_dup, needle_len, haystack_dup + haystack_len); - - efree(haystack_dup); - efree(needle_dup); - - if (found) { - RETURN_LONG(found - haystack_dup); - } - - /* if needle was ascii too, we are all done, otherwise we need to try using Unicode to see what we get */ - if ( grapheme_ascii_check((unsigned char *)needle, needle_len) >= 0 ) { - RETURN_FALSE; - } - } - - /* do utf16 part of the strpos */ - ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, NULL, 1 /* fIgnoreCase */, 0 /*last */ ); - - if ( ret_pos >= 0 ) { - RETURN_LONG(ret_pos); - } else { - RETURN_FALSE; - } - -} -/* }}} */ - -/* {{{ Find position of last occurrence of a string within another */ -PHP_FUNCTION(grapheme_strrpos) -{ - char *haystack, *needle; - size_t haystack_len, needle_len; - zend_long loffset = 0; - int32_t offset = 0; - zend_long ret_pos; - int is_ascii; - - ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_STRING(haystack, haystack_len) - Z_PARAM_STRING(needle, needle_len) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(loffset) - ZEND_PARSE_PARAMETERS_END(); - - if ( OUTSIDE_STRING(loffset, haystack_len) ) { - zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); - RETURN_THROWS(); - } - - /* we checked that it will fit: */ - offset = (int32_t) loffset; - - /* the offset is 'grapheme count offset' so it still might be invalid - we'll check it later */ - - is_ascii = grapheme_ascii_check((unsigned char *)haystack, haystack_len) >= 0; - - if ( is_ascii ) { - - ret_pos = grapheme_strrpos_ascii(haystack, haystack_len, needle, needle_len, offset); - - if ( ret_pos >= 0 ) { - RETURN_LONG(ret_pos); - } - - /* if the needle was ascii too, we are done */ - - if ( grapheme_ascii_check((unsigned char *)needle, needle_len) >= 0 ) { - RETURN_FALSE; - } - - /* 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 */); - - if ( ret_pos >= 0 ) { - RETURN_LONG(ret_pos); - } else { - RETURN_FALSE; - } - - -} -/* }}} */ - -/* {{{ 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; - zend_long loffset = 0; - int32_t offset = 0; - zend_long ret_pos; - int is_ascii; - - ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_STRING(haystack, haystack_len) - Z_PARAM_STRING(needle, needle_len) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(loffset) - ZEND_PARSE_PARAMETERS_END(); - - if ( OUTSIDE_STRING(loffset, haystack_len) ) { - zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); - RETURN_THROWS(); - } - - /* we checked that it will fit: */ - offset = (int32_t) loffset; - - /* the offset is 'grapheme count offset' so it still might be invalid - we'll check it later */ - - is_ascii = grapheme_ascii_check((unsigned char *)haystack, haystack_len) >= 0; - - if ( is_ascii ) { - char *needle_dup, *haystack_dup; - - needle_dup = estrndup(needle, needle_len); - zend_str_tolower(needle_dup, needle_len); - haystack_dup = estrndup(haystack, haystack_len); - zend_str_tolower(haystack_dup, haystack_len); - - ret_pos = grapheme_strrpos_ascii(haystack_dup, haystack_len, needle_dup, needle_len, offset); - - efree(haystack_dup); - efree(needle_dup); - - if ( ret_pos >= 0 ) { - RETURN_LONG(ret_pos); - } - - /* if the needle was ascii too, we are done */ - - if ( grapheme_ascii_check((unsigned char *)needle, needle_len) >= 0 ) { - RETURN_FALSE; - } - - /* 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 */); - - if ( ret_pos >= 0 ) { - RETURN_LONG(ret_pos); - } else { - RETURN_FALSE; - } - - -} -/* }}} */ - -/* {{{ Returns part of a string */ -PHP_FUNCTION(grapheme_substr) -{ - char *str; - zend_string *u8_sub_str; - UChar *ustr; - size_t str_len; - int32_t ustr_len; - zend_long lstart = 0, length = 0; - int32_t start = 0; - int iter_val; - UErrorCode status; - unsigned char u_break_iterator_buffer[U_BRK_SAFECLONE_BUFFERSIZE]; - UBreakIterator* bi = NULL; - int sub_str_start_pos, sub_str_end_pos; - int32_t (*iter_func)(UBreakIterator *); - bool no_length = true; - - ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_STRING(str, str_len) - Z_PARAM_LONG(lstart) - Z_PARAM_OPTIONAL - Z_PARAM_LONG_OR_NULL(length, no_length) - ZEND_PARSE_PARAMETERS_END(); - - if (lstart < INT32_MIN || lstart > INT32_MAX) { - zend_argument_value_error(2, "is too large"); - RETURN_THROWS(); - } - - start = (int32_t) lstart; - - if (no_length) { - length = str_len; - } - - if (length < INT32_MIN || length > INT32_MAX) { - zend_argument_value_error(3, "is too large"); - RETURN_THROWS(); - } - - /* the offset is 'grapheme count offset' so it still might be invalid - we'll check it later */ - - if ( grapheme_ascii_check((unsigned char *)str, str_len) >= 0 ) { - int32_t asub_str_len; - char *sub_str; - 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 ); - RETURN_FALSE; - } - - RETURN_STRINGL(sub_str, asub_str_len); - } - - ustr = NULL; - ustr_len = 0; - status = U_ZERO_ERROR; - intl_convert_utf8_to_utf16(&ustr, &ustr_len, str, str_len, &status); - - if ( U_FAILURE( status ) ) { - /* Set global error code. */ - intl_error_set_code( NULL, status ); - - /* Set error messages. */ - intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16", 0 ); - if (ustr) { - efree( ustr ); - } - RETURN_FALSE; - } - - bi = grapheme_get_break_iterator((void*)u_break_iterator_buffer, &status ); - - if( U_FAILURE(status) ) { - RETURN_FALSE; - } - - ubrk_setText(bi, ustr, ustr_len, &status); - - if ( start < 0 ) { - iter_func = ubrk_previous; - ubrk_last(bi); - iter_val = 1; - } - else { - iter_func = ubrk_next; - iter_val = -1; - } - - sub_str_start_pos = 0; - - while ( start ) { - sub_str_start_pos = iter_func(bi); - - if ( UBRK_DONE == sub_str_start_pos ) { - break; - } - - start += iter_val; - } - - if (0 != start) { - if (start > 0) { - if (ustr) { - efree(ustr); - } - ubrk_close(bi); - RETURN_EMPTY_STRING(); - } - - sub_str_start_pos = 0; - ubrk_first(bi); - } - - /* OK to convert here since if str_len were big, convert above would fail */ - if (length >= (int32_t)str_len) { - - /* no length supplied or length is too big, return the rest of the string */ - - status = U_ZERO_ERROR; - u8_sub_str = intl_convert_utf16_to_utf8(ustr + sub_str_start_pos, ustr_len - sub_str_start_pos, &status); - - if (ustr) { - efree( ustr ); - } - ubrk_close( bi ); - - if ( !u8_sub_str ) { - /* Set global error code. */ - intl_error_set_code( NULL, status ); - - /* Set error messages. */ - intl_error_set_custom_msg( NULL, "Error converting output string to UTF-8", 0 ); - - RETURN_FALSE; - } - - /* return the allocated string, not a duplicate */ - RETVAL_NEW_STR(u8_sub_str); - return; - } - - if(length == 0) { - /* empty length - we've validated start, we can return "" now */ - if (ustr) { - efree(ustr); - } - ubrk_close(bi); - RETURN_EMPTY_STRING(); - } - - /* find the end point of the string to return */ - - if ( length < 0 ) { - iter_func = ubrk_previous; - ubrk_last(bi); - iter_val = 1; - } - else { - iter_func = ubrk_next; - iter_val = -1; - } - - sub_str_end_pos = 0; - - while ( length ) { - sub_str_end_pos = iter_func(bi); - - if ( UBRK_DONE == sub_str_end_pos ) { - break; - } - - length += iter_val; - } - - ubrk_close(bi); - - if ( UBRK_DONE == sub_str_end_pos) { - if (length < 0) { - efree(ustr); - RETURN_EMPTY_STRING(); - } else { - sub_str_end_pos = ustr_len; - } - } - - if (sub_str_start_pos > sub_str_end_pos) { - efree(ustr); - RETURN_EMPTY_STRING(); - } - - status = U_ZERO_ERROR; - u8_sub_str = intl_convert_utf16_to_utf8(ustr + sub_str_start_pos, ( sub_str_end_pos - sub_str_start_pos ), &status); - - efree( ustr ); - - if ( !u8_sub_str ) { - /* Set global error code. */ - intl_error_set_code( NULL, status ); - - /* Set error messages. */ - intl_error_set_custom_msg( NULL, "Error converting output string to UTF-8", 0 ); - - RETURN_FALSE; - } - - /* return the allocated string, not a duplicate */ - RETVAL_NEW_STR(u8_sub_str); -} -/* }}} */ - -/* {{{ strstr_common_handler */ -static void strstr_common_handler(INTERNAL_FUNCTION_PARAMETERS, int f_ignore_case) -{ - char *haystack, *needle; - const char *found; - size_t haystack_len, needle_len; - int32_t ret_pos, uchar_pos; - bool part = false; - - ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_STRING(haystack, haystack_len) - Z_PARAM_STRING(needle, needle_len) - Z_PARAM_OPTIONAL - Z_PARAM_BOOL(part) - ZEND_PARSE_PARAMETERS_END(); - - if ( !f_ignore_case ) { - - /* ASCII optimization: quick check to see if the string might be there */ - found = php_memnstr(haystack, needle, needle_len, haystack + haystack_len); - - /* if it isn't there the we are done */ - if ( !found ) { - RETURN_FALSE; - } - - /* if it is there, and if the haystack is ascii, we are all done */ - if ( grapheme_ascii_check((unsigned char *)haystack, haystack_len) >= 0 ) { - size_t found_offset = found - haystack; - - if (part) { - RETURN_STRINGL(haystack, found_offset); - } else { - RETURN_STRINGL(found, haystack_len - found_offset); - } - } - - } - - /* need to work in utf16 */ - ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, 0, &uchar_pos, f_ignore_case, 0 /*last */ ); - - if ( ret_pos < 0 ) { - RETURN_FALSE; - } - - /* uchar_pos is the 'nth' Unicode character position of the needle */ - - ret_pos = 0; - U8_FWD_N(haystack, ret_pos, haystack_len, uchar_pos); - - if (part) { - RETURN_STRINGL(haystack, ret_pos); - } else { - RETURN_STRINGL(haystack + ret_pos, haystack_len - ret_pos); - } - -} -/* }}} */ - -/* {{{ Finds first occurrence of a string within another */ -PHP_FUNCTION(grapheme_strstr) -{ - strstr_common_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0 /* f_ignore_case */); -} -/* }}} */ - -/* {{{ Finds first occurrence of a string within another */ -PHP_FUNCTION(grapheme_stristr) -{ - strstr_common_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1 /* f_ignore_case */); -} -/* }}} */ - -/* {{{ grapheme_extract_charcount_iter - grapheme iterator for grapheme_extract MAXCHARS */ -static inline int32_t -grapheme_extract_charcount_iter(UBreakIterator *bi, int32_t csize, unsigned char *pstr, int32_t str_len) -{ - int pos = 0; - int ret_pos = 0; - int break_pos, prev_break_pos; - int count = 0; - - while ( 1 ) { - pos = ubrk_next(bi); - - if ( UBRK_DONE == pos ) { - break; - } - - for ( break_pos = ret_pos; break_pos < pos; ) { - count++; - prev_break_pos = break_pos; - U8_FWD_1(pstr, break_pos, str_len); - - if ( prev_break_pos == break_pos ) { - /* something wrong - malformed utf8? */ - csize = 0; - break; - } - } - - /* if we are beyond our limit, then the loop is done */ - if ( count > csize ) { - break; - } - - ret_pos = break_pos; - } - - return ret_pos; -} -/* }}} */ - -/* {{{ grapheme_extract_bytecount_iter - grapheme iterator for grapheme_extract MAXBYTES */ -static inline int32_t -grapheme_extract_bytecount_iter(UBreakIterator *bi, int32_t bsize, unsigned char *pstr, int32_t str_len) -{ - int pos = 0; - int ret_pos = 0; - - while ( 1 ) { - pos = ubrk_next(bi); - - if ( UBRK_DONE == pos ) { - break; - } - - if ( pos > bsize ) { - break; - } - - ret_pos = pos; - } - - return ret_pos; -} -/* }}} */ - -/* {{{ grapheme_extract_count_iter - grapheme iterator for grapheme_extract COUNT */ -static inline int32_t -grapheme_extract_count_iter(UBreakIterator *bi, int32_t size, unsigned char *pstr, int32_t str_len) -{ - int next_pos = 0; - int ret_pos = 0; - - while ( size ) { - next_pos = ubrk_next(bi); - - if ( UBRK_DONE == next_pos ) { - break; - } - ret_pos = next_pos; - size--; - } - - return ret_pos; -} -/* }}} */ - -/* {{{ grapheme extract iter function pointer array */ -typedef int32_t (*grapheme_extract_iter)(UBreakIterator * /*bi*/, int32_t /*size*/, unsigned char * /*pstr*/, int32_t /*str_len*/); - -static const grapheme_extract_iter grapheme_extract_iters[] = { - &grapheme_extract_count_iter, - &grapheme_extract_bytecount_iter, - &grapheme_extract_charcount_iter, -}; -/* }}} */ - -/* {{{ Function to extract a sequence of default grapheme clusters */ -PHP_FUNCTION(grapheme_extract) -{ - char *str, *pstr; - UText ut = UTEXT_INITIALIZER; - size_t str_len; - zend_long size; /* maximum number of grapheme clusters, bytes, or characters (based on extract_type) to return */ - zend_long lstart = 0; /* starting position in str in bytes */ - int32_t start = 0; - zend_long extract_type = GRAPHEME_EXTRACT_TYPE_COUNT; - UErrorCode status; - unsigned char u_break_iterator_buffer[U_BRK_SAFECLONE_BUFFERSIZE]; - UBreakIterator* bi = NULL; - int ret_pos; - zval *next = NULL; /* return offset of next part of the string */ - - ZEND_PARSE_PARAMETERS_START(2, 5) - Z_PARAM_STRING(str, str_len) - Z_PARAM_LONG(size) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(extract_type) - Z_PARAM_LONG(lstart) - Z_PARAM_ZVAL(next) - ZEND_PARSE_PARAMETERS_END(); - - if (lstart < 0) { - lstart += str_len; - } - - if ( NULL != next ) { - ZEND_ASSERT(Z_ISREF_P(next)); - ZEND_TRY_ASSIGN_REF_LONG(next, lstart); - if (UNEXPECTED(EG(exception))) { - RETURN_THROWS(); - } - } - - if ( extract_type < GRAPHEME_EXTRACT_TYPE_MIN || extract_type > GRAPHEME_EXTRACT_TYPE_MAX ) { - zend_argument_value_error(3, "must be one of GRAPHEME_EXTR_COUNT, GRAPHEME_EXTR_MAXBYTES, or GRAPHEME_EXTR_MAXCHARS"); - RETURN_THROWS(); - } - - 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 ); - RETURN_FALSE; - } - - if (size < 0) { - zend_argument_value_error(2, "must be greater than or equal to 0"); - RETURN_THROWS(); - } - - if (size > INT32_MAX) { - zend_argument_value_error(2, "is too large"); - RETURN_THROWS(); - } - - if (size == 0) { - RETURN_EMPTY_STRING(); - } - - /* we checked that it will fit: */ - start = (int32_t) lstart; - - pstr = str + start; - - /* just in case pstr points in the middle of a character, move forward to the start of the next char */ - if ( !U8_IS_SINGLE(*pstr) && !U8_IS_LEAD(*pstr) ) { - char *str_end = str + str_len; - - while ( !U8_IS_SINGLE(*pstr) && !U8_IS_LEAD(*pstr) ) { - pstr++; - start++; - if ( pstr >= str_end ) { - intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, - "grapheme_extract: invalid input string", 0 ); - - RETURN_FALSE; - } - } - } - - str_len -= (pstr - str); - - /* if the string is all ASCII up to size+1 - or str_len whichever is first - then we are done. - (size + 1 because the size-th character might be the beginning of a grapheme cluster) - */ - - if ( -1 != grapheme_ascii_check((unsigned char *)pstr, MIN(size + 1, str_len)) ) { - size_t nsize = MIN(size, str_len); - if ( NULL != next ) { - ZEND_TRY_ASSIGN_REF_LONG(next, start + nsize); - } - RETURN_STRINGL(pstr, nsize); - } - - status = U_ZERO_ERROR; - utext_openUTF8(&ut, pstr, str_len, &status); - - if ( U_FAILURE( status ) ) { - /* Set global error code. */ - intl_error_set_code( NULL, status ); - - /* Set error messages. */ - intl_error_set_custom_msg( NULL, "Error opening UTF-8 text", 0 ); - - RETURN_FALSE; - } - - bi = NULL; - status = U_ZERO_ERROR; - bi = grapheme_get_break_iterator(u_break_iterator_buffer, &status ); - - ubrk_setUText(bi, &ut, &status); - /* if the caller put us in the middle of a grapheme, we can't detect it in all cases since we - can't back up. So, we will not do anything. */ - - /* now we need to find the end of the chunk the user wants us to return */ - /* it's ok to convert str_len to in32_t since if it were too big intl_convert_utf8_to_utf16 above would fail */ - ret_pos = (*grapheme_extract_iters[extract_type])(bi, size, (unsigned char *)pstr, (int32_t)str_len); - - utext_close(&ut); - ubrk_close(bi); - - if ( NULL != next ) { - ZEND_TRY_ASSIGN_REF_LONG(next, start + ret_pos); - } - - RETURN_STRINGL(((char *)pstr), ret_pos); -} - -PHP_FUNCTION(grapheme_str_split) -{ - char *pstr, *end; - zend_string *str; - zend_long split_len = 1; - - unsigned char u_break_iterator_buffer[U_BRK_SAFECLONE_BUFFERSIZE]; - UErrorCode ustatus = U_ZERO_ERROR; - int32_t pos, current, i, end_len = 0; - UBreakIterator* bi; - UText *ut = NULL; - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_STR(str) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(split_len) - ZEND_PARSE_PARAMETERS_END(); - - if (split_len <= 0 || split_len > UINT_MAX / 4) { - zend_argument_value_error(2, "must be greater than 0 and less than or equal to %d", UINT_MAX / 4); - RETURN_THROWS(); - } - - if (ZSTR_LEN(str) == 0) { - RETURN_EMPTY_ARRAY(); - } - - pstr = ZSTR_VAL(str); - ut = utext_openUTF8(ut, pstr, ZSTR_LEN(str), &ustatus); - - if ( U_FAILURE( ustatus ) ) { - /* Set global error code. */ - intl_error_set_code( NULL, ustatus ); - - /* Set error messages. */ - intl_error_set_custom_msg( NULL, "Error opening UTF-8 text", 0 ); - - RETURN_FALSE; - } - - bi = NULL; - ustatus = U_ZERO_ERROR; - bi = grapheme_get_break_iterator((void*)u_break_iterator_buffer, &ustatus ); - - if( U_FAILURE(ustatus) ) { - RETURN_FALSE; - } - - ubrk_setUText(bi, ut, &ustatus); - - pos = 0; - array_init(return_value); - - for (end = pstr, i = 0, current = 0; pos != UBRK_DONE;) { - end_len = pos - current; - pos = ubrk_next(bi); - - if (i == split_len - 1) { - if ( pos != UBRK_DONE ) { - add_next_index_stringl(return_value, pstr, pos - current); - end = pstr + pos - current; - i = 0; - } - pstr += pos - current; - current = pos; - } else { - i += 1; - } - } - - if (i != 0 && end_len != 0) { - add_next_index_stringl(return_value, end, end_len); - } - - utext_close(ut); - ubrk_close(bi); -} - -PHP_FUNCTION(grapheme_levenshtein) -{ - zend_string *string1, *string2; - zend_long cost_ins = 1; - zend_long cost_rep = 1; - zend_long cost_del = 1; - - ZEND_PARSE_PARAMETERS_START(2, 5) - 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) - ZEND_PARSE_PARAMETERS_END(); - - if (cost_ins <= 0 || cost_ins > UINT_MAX / 4) { - zend_argument_value_error(3, "must be greater than 0 and less than or equal to %d", UINT_MAX / 4); - RETURN_THROWS(); - } - - if (cost_rep <= 0 || cost_rep > UINT_MAX / 4) { - zend_argument_value_error(4, "must be greater than 0 and less than or equal to %d", UINT_MAX / 4); - RETURN_THROWS(); - } - - if (cost_del <= 0 || cost_del > UINT_MAX / 4) { - zend_argument_value_error(5, "must be greater than 0 and less than or equal to %d", UINT_MAX / 4); - RETURN_THROWS(); - } - - zend_long c0, c1, c2; - zend_long retval; - size_t i2; - char *pstr1, *pstr2; - - UChar *ustring1 = NULL; - UChar *ustring2 = NULL; - - int32_t ustring1_len = 0; - int32_t ustring2_len = 0; - - UErrorCode ustatus = U_ZERO_ERROR; - - /* When all costs are equal, levenshtein fulfills the requirements of a metric, which means - * that the distance is symmetric. If string1 is shorter than string2 we can save memory (and CPU time) - * by having shorter rows (p1 & p2). */ - if (ZSTR_LEN(string1) < ZSTR_LEN(string2) && cost_ins == cost_rep && cost_rep == cost_del) { - zend_string *tmp = string1; - string1 = string2; - string2 = tmp; - } - - pstr1 = ZSTR_VAL(string1); - pstr2 = ZSTR_VAL(string2); - - intl_convert_utf8_to_utf16(&ustring1, &ustring1_len, pstr1, ZSTR_LEN(string1), &ustatus); - - if (U_FAILURE(ustatus)) { - intl_error_set_code(NULL, ustatus); - - intl_error_set_custom_msg(NULL, "Error converting input string to UTF-16", 0); - RETVAL_FALSE; - goto out_ustring1; - } - - intl_convert_utf8_to_utf16(&ustring2, &ustring2_len, pstr2, ZSTR_LEN(string2), &ustatus); - - if (U_FAILURE(ustatus)) { - intl_error_set_code(NULL, ustatus); - - intl_error_set_custom_msg(NULL, "Error converting input string to UTF-16", 0); - RETVAL_FALSE; - goto out_ustring2; - } - - UBreakIterator *bi1, *bi2; - - int32_t strlen_1, strlen_2; - strlen_1 = grapheme_split_string(ustring1, ustring1_len, NULL, 0); - strlen_2 = grapheme_split_string(ustring2, ustring2_len, NULL, 0); - if (UNEXPECTED(strlen_1 < 0 || strlen_2 < 0)) { - RETVAL_FALSE; - goto out_ustring2; - } - - if (strlen_1 == 0) { - RETVAL_LONG(strlen_2 * cost_ins); - goto out_ustring2; - } - if (strlen_2 == 0) { - RETVAL_LONG(strlen_1 * cost_del); - goto out_ustring2; - } - - unsigned char u_break_iterator_buffer1[U_BRK_SAFECLONE_BUFFERSIZE]; - unsigned char u_break_iterator_buffer2[U_BRK_SAFECLONE_BUFFERSIZE]; - 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); - RETVAL_FALSE; - goto out_bi1; - } - - 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); - RETVAL_FALSE; - goto out_bi2; - } - - ubrk_setText(bi1, ustring1, ustring1_len, &ustatus); - 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); - RETVAL_FALSE; - goto out_bi2; - } - - ubrk_setText(bi2, ustring2, ustring2_len, &ustatus); - 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); - RETVAL_FALSE; - goto out_bi2; - } - UCollator *collator = ucol_open("", &ustatus); - if (U_FAILURE(ustatus)) { - intl_error_set_code(NULL, ustatus); - - intl_error_set_custom_msg(NULL, "Error on ucol_open", 0); - RETVAL_FALSE; - goto out_collator; - } - - zend_long *p1, *p2, *tmp; - p1 = safe_emalloc((size_t) strlen_2 + 1, sizeof(zend_long), 0); - p2 = safe_emalloc((size_t) strlen_2 + 1, sizeof(zend_long), 0); - - for (i2 = 0; i2 <= strlen_2; i2++) { - p1[i2] = i2 * cost_ins; - } - - int32_t current1 = 0; - int32_t current2 = 0; - int32_t pos1 = 0; - int32_t pos2 = 0; - - while (true) { - current1 = ubrk_current(bi1); - pos1 = ubrk_next(bi1); - if (pos1 == UBRK_DONE) { - break; - } - p2[0] = p1[0] + cost_del; - for (i2 = 0, pos2 = 0; pos2 != UBRK_DONE; i2++) { - current2 = ubrk_current(bi2); - pos2 = ubrk_next(bi2); - if (pos2 == UBRK_DONE) { - break; - } - if (ucol_strcoll(collator, ustring1 + current1, pos1 - current1, ustring2 + current2, pos2 - current2) == UCOL_EQUAL) { - c0 = p1[i2]; - } else { - c0 = p1[i2] + cost_rep; - } - c1 = p1[i2 + 1] + cost_del; - if (c1 < c0) { - c0 = c1; - } - c2 = p2[i2] + cost_ins; - if (c2 < c0) { - c0 = c2; - } - p2[i2 + 1] = c0; - } - ubrk_first(bi2); - tmp = p1; - p1 = p2; - p2 = tmp; - } - - retval = p1[strlen_2]; - RETVAL_LONG(retval); - - efree(p2); - efree(p1); - -out_collator: - ucol_close(collator); -out_bi2: - ubrk_close(bi2); -out_bi1: - ubrk_close(bi1); -out_ustring2: - efree(ustring2); -out_ustring1: - efree(ustring1); -} - -/* }}} */ diff --git a/ext/intl/grapheme/grapheme_string.cpp b/ext/intl/grapheme/grapheme_string.cpp new file mode 100644 index 0000000000000..6dd5a002a65b8 --- /dev/null +++ b/ext/intl/grapheme/grapheme_string.cpp @@ -0,0 +1,1138 @@ +/* + +----------------------------------------------------------------------+ + | 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. | + +----------------------------------------------------------------------+ + | Author: Ed Batutis | + +----------------------------------------------------------------------+ + */ + +/* {{{ includes */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#if __cplusplus >= 201703L +#include +#include +#endif + +extern "C" { +#include +#include "grapheme.h" +#include "grapheme_util.h" +} + +#include +#include +#include +#include +#include + +/* }}} */ + +/* {{{ Get number of graphemes in a string */ +U_CFUNC PHP_FUNCTION(grapheme_strlen) +{ + char* string; + size_t string_len; + UChar* ustring = nullptr; + int ustring_len = 0; + zend_long ret_len; + UErrorCode status; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STRING(string, string_len) + ZEND_PARSE_PARAMETERS_END(); + + ret_len = grapheme_ascii_check((unsigned char *)string, string_len); + + if ( ret_len >= 0 ) + RETURN_LONG(string_len); + + /* convert the string to UTF-16. */ + status = U_ZERO_ERROR; + intl_convert_utf8_to_utf16(&ustring, &ustring_len, string, string_len, &status ); + + if ( U_FAILURE( status ) ) { + /* Set global error code. */ + intl_error_set_code( nullptr, status ); + + /* Set error messages. */ + intl_error_set_custom_msg( nullptr, "Error converting input string to UTF-16"); + if (ustring) { + efree( ustring ); + } + RETURN_NULL(); + } + + ret_len = grapheme_split_string(ustring, ustring_len, nullptr, 0 ); + + if (ustring) { + efree( ustring ); + } + + if (ret_len >= 0) { + RETVAL_LONG(ret_len); + } else { + RETVAL_FALSE; + } +} +/* }}} */ + +/* {{{ Find position of first occurrence of a string within another */ +U_CFUNC PHP_FUNCTION(grapheme_strpos) +{ + 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, 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) ) { + zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); + RETURN_THROWS(); + } + + /* we checked that it will fit: */ + offset = (int32_t) loffset; + noffset = offset >= 0 ? offset : (int32_t)haystack_len + offset; + + /* the offset is 'grapheme count offset' so it still might be invalid - we'll check it later */ + + if (offset >= 0 && grapheme_ascii_check((unsigned char *)haystack, haystack_len) >= 0) { + /* quick check to see if the string might be there + * I realize that 'offset' is 'grapheme count offset' but will work in spite of that + */ + found = php_memnstr(haystack + noffset, needle, needle_len, haystack + haystack_len); + + /* if it isn't there the we are done */ + if (found) { + RETURN_LONG(found - haystack); + } + RETURN_FALSE; + } + + /* do utf16 part of the strpos */ + ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, nullptr, /* fIgnoreCase */ 0, /* last */ 0, locale); + + if ( ret_pos >= 0 ) { + RETURN_LONG(ret_pos); + } else { + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ Find position of first occurrence of a string within another, ignoring case differences */ +U_CFUNC PHP_FUNCTION(grapheme_stripos) +{ + 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, 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) ) { + zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); + RETURN_THROWS(); + } + + /* we checked that it will fit: */ + offset = (int32_t) loffset; + + /* the offset is 'grapheme count offset' so it still might be invalid - we'll check it later */ + + is_ascii = ( grapheme_ascii_check((unsigned char*)haystack, haystack_len) >= 0 ); + + if ( is_ascii ) { + char *haystack_dup, *needle_dup; + int32_t noffset = offset >= 0 ? offset : (int32_t)haystack_len + offset; + needle_dup = estrndup(needle, needle_len); + zend_str_tolower(needle_dup, needle_len); + haystack_dup = estrndup(haystack, haystack_len); + zend_str_tolower(haystack_dup, haystack_len); + + found = php_memnstr(haystack_dup + noffset, needle_dup, needle_len, haystack_dup + haystack_len); + + efree(haystack_dup); + efree(needle_dup); + + if (found) { + RETURN_LONG(found - haystack_dup); + } + + /* if needle was ascii too, we are all done, otherwise we need to try using Unicode to see what we get */ + if ( grapheme_ascii_check((unsigned char *)needle, needle_len) >= 0 ) { + RETURN_FALSE; + } + } + + /* do utf16 part of the strpos */ + ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, nullptr, /* fIgnoreCase */ 1, /*last */ 0, locale); + + if ( ret_pos >= 0 ) { + RETURN_LONG(ret_pos); + } else { + RETURN_FALSE; + } + +} +/* }}} */ + +/* {{{ Find position of last occurrence of a string within another */ +U_CFUNC PHP_FUNCTION(grapheme_strrpos) +{ + char *haystack, *needle; + 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, 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) ) { + zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); + RETURN_THROWS(); + } + + /* we checked that it will fit: */ + offset = (int32_t) loffset; + + /* the offset is 'grapheme count offset' so it still might be invalid - we'll check it later */ + + is_ascii = grapheme_ascii_check((unsigned char *)haystack, haystack_len) >= 0; + + if ( is_ascii ) { + + ret_pos = grapheme_strrpos_ascii(haystack, haystack_len, needle, needle_len, offset); + + if ( ret_pos >= 0 ) { + RETURN_LONG(ret_pos); + } + + /* if the needle was ascii too, we are done */ + + if ( grapheme_ascii_check((unsigned char *)needle, needle_len) >= 0 ) { + RETURN_FALSE; + } + + /* else we need to continue via utf16 */ + } + + ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, nullptr, /* f_ignore_case */ 0, /* last */ 1, locale); + + if ( ret_pos >= 0 ) { + RETURN_LONG(ret_pos); + } else { + RETURN_FALSE; + } + + +} +/* }}} */ + +/* {{{ Find position of last occurrence of a string within another, ignoring case */ +U_CFUNC PHP_FUNCTION(grapheme_strripos) +{ + 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, 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) ) { + zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); + RETURN_THROWS(); + } + + /* we checked that it will fit: */ + offset = (int32_t) loffset; + + /* the offset is 'grapheme count offset' so it still might be invalid - we'll check it later */ + + is_ascii = grapheme_ascii_check((unsigned char *)haystack, haystack_len) >= 0; + + if ( is_ascii ) { + char *needle_dup, *haystack_dup; + + needle_dup = estrndup(needle, needle_len); + zend_str_tolower(needle_dup, needle_len); + haystack_dup = estrndup(haystack, haystack_len); + zend_str_tolower(haystack_dup, haystack_len); + + ret_pos = grapheme_strrpos_ascii(haystack_dup, haystack_len, needle_dup, needle_len, offset); + + efree(haystack_dup); + efree(needle_dup); + + if ( ret_pos >= 0 ) { + RETURN_LONG(ret_pos); + } + + /* if the needle was ascii too, we are done */ + + if ( grapheme_ascii_check((unsigned char *)needle, needle_len) >= 0 ) { + RETURN_FALSE; + } + + /* else we need to continue via utf16 */ + } + + ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, nullptr, /* f_ignore_case */ 1, /*last */ 1, locale); + + if ( ret_pos >= 0 ) { + RETURN_LONG(ret_pos); + } else { + RETURN_FALSE; + } + + +} +/* }}} */ + +/* {{{ Returns part of a string */ +U_CFUNC PHP_FUNCTION(grapheme_substr) +{ + char *str, *locale = ""; + zend_string *u8_sub_str; + UChar *ustr; + size_t str_len, locale_len = 0; + int32_t ustr_len; + zend_long lstart = 0, length = 0; + int32_t start = 0; + int iter_val; + UErrorCode status; + unsigned char u_break_iterator_buffer[U_BRK_SAFECLONE_BUFFERSIZE]; + UBreakIterator* bi = nullptr; + int sub_str_start_pos, sub_str_end_pos; + int32_t (*iter_func)(UBreakIterator *); + bool no_length = true; + + 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) { + zend_argument_value_error(2, "is too large"); + RETURN_THROWS(); + } + + start = (int32_t) lstart; + + if (no_length) { + length = str_len; + } + + if (length < INT32_MIN || length > INT32_MAX) { + zend_argument_value_error(3, "is too large"); + RETURN_THROWS(); + } + + /* the offset is 'grapheme count offset' so it still might be invalid - we'll check it later */ + + if ( grapheme_ascii_check((unsigned char *)str, str_len) >= 0 ) { + int32_t asub_str_len; + char *sub_str; + grapheme_substr_ascii(str, str_len, start, (int32_t)length, &sub_str, &asub_str_len); + + if ( nullptr == sub_str ) { + intl_error_set( nullptr, U_ILLEGAL_ARGUMENT_ERROR, "invalid parameters"); + RETURN_FALSE; + } + + RETURN_STRINGL(sub_str, asub_str_len); + } + + ustr = nullptr; + ustr_len = 0; + status = U_ZERO_ERROR; + intl_convert_utf8_to_utf16(&ustr, &ustr_len, str, str_len, &status); + + if ( U_FAILURE( status ) ) { + /* Set global error code. */ + intl_error_set_code( nullptr, status ); + + /* Set error messages. */ + intl_error_set_custom_msg( nullptr, "Error converting input string to UTF-16"); + if (ustr) { + efree( ustr ); + } + RETURN_FALSE; + } + + bi = grapheme_get_break_iterator((void*)u_break_iterator_buffer, &status ); + + if( U_FAILURE(status) ) { + RETURN_FALSE; + } + + ubrk_setText(bi, ustr, ustr_len, &status); + + if ( start < 0 ) { + iter_func = ubrk_previous; + ubrk_last(bi); + iter_val = 1; + } + else { + iter_func = ubrk_next; + iter_val = -1; + } + + sub_str_start_pos = 0; + + while ( start ) { + sub_str_start_pos = iter_func(bi); + + if ( UBRK_DONE == sub_str_start_pos ) { + break; + } + + start += iter_val; + } + + if (0 != start) { + if (start > 0) { + if (ustr) { + efree(ustr); + } + ubrk_close(bi); + RETURN_EMPTY_STRING(); + } + + sub_str_start_pos = 0; + ubrk_first(bi); + } + + /* OK to convert here since if str_len were big, convert above would fail */ + if (length >= (int32_t)str_len) { + + /* no length supplied or length is too big, return the rest of the string */ + + status = U_ZERO_ERROR; + u8_sub_str = intl_convert_utf16_to_utf8(ustr + sub_str_start_pos, ustr_len - sub_str_start_pos, &status); + + if (ustr) { + efree( ustr ); + } + ubrk_close( bi ); + + if ( !u8_sub_str ) { + /* Set global error code. */ + intl_error_set_code( nullptr, status ); + + /* Set error messages. */ + intl_error_set_custom_msg( nullptr, "Error converting output string to UTF-8"); + + RETURN_FALSE; + } + + /* return the allocated string, not a duplicate */ + RETVAL_NEW_STR(u8_sub_str); + return; + } + + if(length == 0) { + /* empty length - we've validated start, we can return "" now */ + if (ustr) { + efree(ustr); + } + ubrk_close(bi); + RETURN_EMPTY_STRING(); + } + + /* find the end point of the string to return */ + + if ( length < 0 ) { + iter_func = ubrk_previous; + ubrk_last(bi); + iter_val = 1; + } + else { + iter_func = ubrk_next; + iter_val = -1; + } + + sub_str_end_pos = 0; + + while ( length ) { + sub_str_end_pos = iter_func(bi); + + if ( UBRK_DONE == sub_str_end_pos ) { + break; + } + + length += iter_val; + } + + ubrk_close(bi); + + if ( UBRK_DONE == sub_str_end_pos) { + if (length < 0) { + efree(ustr); + RETURN_EMPTY_STRING(); + } else { + sub_str_end_pos = ustr_len; + } + } + + if (sub_str_start_pos > sub_str_end_pos) { + efree(ustr); + RETURN_EMPTY_STRING(); + } + + status = U_ZERO_ERROR; + u8_sub_str = intl_convert_utf16_to_utf8(ustr + sub_str_start_pos, ( sub_str_end_pos - sub_str_start_pos ), &status); + + efree( ustr ); + + if ( !u8_sub_str ) { + /* Set global error code. */ + intl_error_set_code( nullptr, status ); + + /* Set error messages. */ + intl_error_set_custom_msg( nullptr, "Error converting output string to UTF-8"); + + RETURN_FALSE; + } + + /* return the allocated string, not a duplicate */ + RETVAL_NEW_STR(u8_sub_str); +} +/* }}} */ + +/* {{{ strstr_common_handler */ +static void strstr_common_handler(INTERNAL_FUNCTION_PARAMETERS, int f_ignore_case) +{ + char *haystack, *needle, *locale = ""; + const char *found; + size_t haystack_len, needle_len, locale_len = 0; + int32_t ret_pos, uchar_pos; + bool part = false; + + 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 ) { + + /* ASCII optimization: quick check to see if the string might be there */ + found = php_memnstr(haystack, needle, needle_len, haystack + haystack_len); + + /* if it isn't there the we are done */ + if ( !found ) { + RETURN_FALSE; + } + + /* if it is there, and if the haystack is ascii, we are all done */ + if ( grapheme_ascii_check((unsigned char *)haystack, haystack_len) >= 0 ) { + size_t found_offset = found - haystack; + + if (part) { + RETURN_STRINGL(haystack, found_offset); + } else { + RETURN_STRINGL(found, haystack_len - found_offset); + } + } + + } + + /* need to work in utf16 */ + 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; + } + + /* uchar_pos is the 'nth' Unicode character position of the needle */ + + ret_pos = 0; + U8_FWD_N(haystack, ret_pos, haystack_len, uchar_pos); + + if (part) { + RETURN_STRINGL(haystack, ret_pos); + } else { + RETURN_STRINGL(haystack + ret_pos, haystack_len - ret_pos); + } + +} +/* }}} */ + +/* {{{ Finds first occurrence of a string within another */ +U_CFUNC PHP_FUNCTION(grapheme_strstr) +{ + strstr_common_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0 /* f_ignore_case */); +} +/* }}} */ + +/* {{{ Finds first occurrence of a string within another */ +U_CFUNC PHP_FUNCTION(grapheme_stristr) +{ + strstr_common_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1 /* f_ignore_case */); +} +/* }}} */ + +/* {{{ grapheme_extract_charcount_iter - grapheme iterator for grapheme_extract MAXCHARS */ +static inline int32_t +grapheme_extract_charcount_iter(UBreakIterator *bi, int32_t csize, unsigned char *pstr, int32_t str_len) +{ + int pos = 0; + int ret_pos = 0; + int break_pos, prev_break_pos; + int count = 0; + + while ( 1 ) { + pos = ubrk_next(bi); + + if ( UBRK_DONE == pos ) { + break; + } + + for ( break_pos = ret_pos; break_pos < pos; ) { + count++; + prev_break_pos = break_pos; + U8_FWD_1(pstr, break_pos, str_len); + + if ( prev_break_pos == break_pos ) { + /* something wrong - malformed utf8? */ + csize = 0; + break; + } + } + + /* if we are beyond our limit, then the loop is done */ + if ( count > csize ) { + break; + } + + ret_pos = break_pos; + } + + return ret_pos; +} +/* }}} */ + +/* {{{ grapheme_extract_bytecount_iter - grapheme iterator for grapheme_extract MAXBYTES */ +static inline int32_t +grapheme_extract_bytecount_iter(UBreakIterator *bi, int32_t bsize, unsigned char *pstr, int32_t str_len) +{ + int pos = 0; + int ret_pos = 0; + + while ( 1 ) { + pos = ubrk_next(bi); + + if ( UBRK_DONE == pos ) { + break; + } + + if ( pos > bsize ) { + break; + } + + ret_pos = pos; + } + + return ret_pos; +} +/* }}} */ + +/* {{{ grapheme_extract_count_iter - grapheme iterator for grapheme_extract COUNT */ +static inline int32_t +grapheme_extract_count_iter(UBreakIterator *bi, int32_t size, unsigned char *pstr, int32_t str_len) +{ + int next_pos = 0; + int ret_pos = 0; + + while ( size ) { + next_pos = ubrk_next(bi); + + if ( UBRK_DONE == next_pos ) { + break; + } + ret_pos = next_pos; + size--; + } + + return ret_pos; +} +/* }}} */ + +/* {{{ grapheme extract iter function pointer array */ +typedef int32_t (*grapheme_extract_iter)(UBreakIterator * /*bi*/, int32_t /*size*/, unsigned char * /*pstr*/, int32_t /*str_len*/); + +static const grapheme_extract_iter grapheme_extract_iters[] = { + &grapheme_extract_count_iter, + &grapheme_extract_bytecount_iter, + &grapheme_extract_charcount_iter, +}; +/* }}} */ + +/* {{{ Function to extract a sequence of default grapheme clusters */ +U_CFUNC PHP_FUNCTION(grapheme_extract) +{ + char *str, *pstr; + UText ut = UTEXT_INITIALIZER; + size_t str_len; + zend_long size; /* maximum number of grapheme clusters, bytes, or characters (based on extract_type) to return */ + zend_long lstart = 0; /* starting position in str in bytes */ + int32_t start = 0; + zend_long extract_type = GRAPHEME_EXTRACT_TYPE_COUNT; + UErrorCode status; + unsigned char u_break_iterator_buffer[U_BRK_SAFECLONE_BUFFERSIZE]; + UBreakIterator* bi = nullptr; + int ret_pos; + zval *next = nullptr; /* return offset of next part of the string */ + + ZEND_PARSE_PARAMETERS_START(2, 5) + Z_PARAM_STRING(str, str_len) + Z_PARAM_LONG(size) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(extract_type) + Z_PARAM_LONG(lstart) + Z_PARAM_ZVAL(next) + ZEND_PARSE_PARAMETERS_END(); + + if (lstart < 0) { + lstart += str_len; + } + + if ( nullptr != next ) { + ZEND_ASSERT(Z_ISREF_P(next)); + ZEND_TRY_ASSIGN_REF_LONG(next, lstart); + if (UNEXPECTED(EG(exception))) { + RETURN_THROWS(); + } + } + + if ( extract_type < GRAPHEME_EXTRACT_TYPE_MIN || extract_type > GRAPHEME_EXTRACT_TYPE_MAX ) { + zend_argument_value_error(3, "must be one of GRAPHEME_EXTR_COUNT, GRAPHEME_EXTR_MAXBYTES, or GRAPHEME_EXTR_MAXCHARS"); + RETURN_THROWS(); + } + + if ( lstart > INT32_MAX || lstart < 0 || (size_t)lstart >= str_len ) { + intl_error_set( nullptr, U_ILLEGAL_ARGUMENT_ERROR, "start not contained in string"); + RETURN_FALSE; + } + + if (size < 0) { + zend_argument_value_error(2, "must be greater than or equal to 0"); + RETURN_THROWS(); + } + + if (size > INT32_MAX) { + zend_argument_value_error(2, "is too large"); + RETURN_THROWS(); + } + + if (size == 0) { + RETURN_EMPTY_STRING(); + } + + /* we checked that it will fit: */ + start = (int32_t) lstart; + + pstr = str + start; + + /* just in case pstr points in the middle of a character, move forward to the start of the next char */ + if ( !U8_IS_SINGLE(*pstr) && !U8_IS_LEAD(*pstr) ) { + char *str_end = str + str_len; + + while ( !U8_IS_SINGLE(*pstr) && !U8_IS_LEAD(*pstr) ) { + pstr++; + start++; + if ( pstr >= str_end ) { + intl_error_set( nullptr, U_ILLEGAL_ARGUMENT_ERROR, + "grapheme_extract: invalid input string"); + + RETURN_FALSE; + } + } + } + + str_len -= (pstr - str); + + /* if the string is all ASCII up to size+1 - or str_len whichever is first - then we are done. + (size + 1 because the size-th character might be the beginning of a grapheme cluster) + */ + + if ( -1 != grapheme_ascii_check((unsigned char *)pstr, MIN(size + 1, str_len)) ) { + size_t nsize = MIN(size, str_len); + if ( nullptr != next ) { + ZEND_TRY_ASSIGN_REF_LONG(next, start + nsize); + } + RETURN_STRINGL(pstr, nsize); + } + + status = U_ZERO_ERROR; + utext_openUTF8(&ut, pstr, str_len, &status); + + if ( U_FAILURE( status ) ) { + /* Set global error code. */ + intl_error_set_code( nullptr, status ); + + /* Set error messages. */ + intl_error_set_custom_msg( nullptr, "Error opening UTF-8 text"); + + RETURN_FALSE; + } + + bi = nullptr; + status = U_ZERO_ERROR; + bi = grapheme_get_break_iterator(u_break_iterator_buffer, &status ); + + ubrk_setUText(bi, &ut, &status); + /* if the caller put us in the middle of a grapheme, we can't detect it in all cases since we + can't back up. So, we will not do anything. */ + + /* now we need to find the end of the chunk the user wants us to return */ + /* it's ok to convert str_len to in32_t since if it were too big intl_convert_utf8_to_utf16 above would fail */ + ret_pos = (*grapheme_extract_iters[extract_type])(bi, size, (unsigned char *)pstr, (int32_t)str_len); + + utext_close(&ut); + ubrk_close(bi); + + if ( nullptr != next ) { + ZEND_TRY_ASSIGN_REF_LONG(next, start + ret_pos); + } + + RETURN_STRINGL(((char *)pstr), ret_pos); +} + +U_CFUNC PHP_FUNCTION(grapheme_str_split) +{ + char *pstr, *end; + zend_string *str; + zend_long split_len = 1; + + unsigned char u_break_iterator_buffer[U_BRK_SAFECLONE_BUFFERSIZE]; + UErrorCode ustatus = U_ZERO_ERROR; + int32_t pos, current, i, end_len = 0; + UBreakIterator* bi; + UText *ut = nullptr; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STR(str) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(split_len) + ZEND_PARSE_PARAMETERS_END(); + + if (split_len <= 0 || split_len > UINT_MAX / 4) { + zend_argument_value_error(2, "must be greater than 0 and less than or equal to %d", UINT_MAX / 4); + RETURN_THROWS(); + } + + if (ZSTR_LEN(str) == 0) { + RETURN_EMPTY_ARRAY(); + } + + pstr = ZSTR_VAL(str); + ut = utext_openUTF8(ut, pstr, ZSTR_LEN(str), &ustatus); + + if ( U_FAILURE( ustatus ) ) { + /* Set global error code. */ + intl_error_set_code( nullptr, ustatus ); + + /* Set error messages. */ + intl_error_set_custom_msg( nullptr, "Error opening UTF-8 text"); + + RETURN_FALSE; + } + + bi = nullptr; + ustatus = U_ZERO_ERROR; + bi = grapheme_get_break_iterator((void*)u_break_iterator_buffer, &ustatus ); + + if( U_FAILURE(ustatus) ) { + RETURN_FALSE; + } + + ubrk_setUText(bi, ut, &ustatus); + + pos = 0; + array_init(return_value); + + for (end = pstr, i = 0, current = 0; pos != UBRK_DONE;) { + end_len = pos - current; + pos = ubrk_next(bi); + + if (i == split_len - 1) { + if ( pos != UBRK_DONE ) { + add_next_index_stringl(return_value, pstr, pos - current); + end = pstr + pos - current; + i = 0; + } + pstr += pos - current; + current = pos; + } else { + i += 1; + } + } + + if (i != 0 && end_len != 0) { + add_next_index_stringl(return_value, end, end_len); + } + + utext_close(ut); + ubrk_close(bi); +} + +U_CFUNC PHP_FUNCTION(grapheme_levenshtein) +{ + zend_string *string1, *string2; + 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, 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) { + zend_argument_value_error(3, "must be greater than 0 and less than or equal to %d", UINT_MAX / 4); + RETURN_THROWS(); + } + + if (cost_rep <= 0 || cost_rep > UINT_MAX / 4) { + zend_argument_value_error(4, "must be greater than 0 and less than or equal to %d", UINT_MAX / 4); + RETURN_THROWS(); + } + + if (cost_del <= 0 || cost_del > UINT_MAX / 4) { + zend_argument_value_error(5, "must be greater than 0 and less than or equal to %d", UINT_MAX / 4); + RETURN_THROWS(); + } + + zend_long c0, c1, c2; + zend_long retval; + size_t i2; + char *pstr1, *pstr2; + + UChar *ustring1 = nullptr; + UChar *ustring2 = nullptr; + + int32_t ustring1_len = 0; + int32_t ustring2_len = 0; + int32_t current1 = 0; + int32_t current2 = 0; + int32_t pos1 = 0; + int32_t pos2 = 0; + + UCollator *collator = nullptr; + + UErrorCode ustatus = U_ZERO_ERROR; + + /* When all costs are equal, levenshtein fulfills the requirements of a metric, which means + * that the distance is symmetric. If string1 is shorter than string2 we can save memory (and CPU time) + * by having shorter rows (p1 & p2). */ + if (ZSTR_LEN(string1) < ZSTR_LEN(string2) && cost_ins == cost_rep && cost_rep == cost_del) { + zend_string *tmp = string1; + string1 = string2; + string2 = tmp; + } + + pstr1 = ZSTR_VAL(string1); + pstr2 = ZSTR_VAL(string2); + + intl_convert_utf8_to_utf16(&ustring1, &ustring1_len, pstr1, ZSTR_LEN(string1), &ustatus); + + if (U_FAILURE(ustatus)) { + intl_error_set_code(NULL, ustatus); + + intl_error_set_custom_msg(NULL, "Error converting input string to UTF-16"); + RETVAL_FALSE; + goto out_ustring1; + } + + intl_convert_utf8_to_utf16(&ustring2, &ustring2_len, pstr2, ZSTR_LEN(string2), &ustatus); + + if (U_FAILURE(ustatus)) { + intl_error_set_code(NULL, ustatus); + + intl_error_set_custom_msg(NULL, "Error converting input string to UTF-16"); + RETVAL_FALSE; + goto out_ustring2; + } + + UBreakIterator *bi1, *bi2; + + int32_t strlen_1, strlen_2; + strlen_1 = grapheme_split_string(ustring1, ustring1_len, nullptr, 0); + strlen_2 = grapheme_split_string(ustring2, ustring2_len, nullptr, 0); + if (UNEXPECTED(strlen_1 < 0 || strlen_2 < 0)) { + RETVAL_FALSE; + goto out_ustring2; + } + + if (strlen_1 == 0) { + RETVAL_LONG(strlen_2 * cost_ins); + goto out_ustring2; + } + if (strlen_2 == 0) { + RETVAL_LONG(strlen_1 * cost_del); + goto out_ustring2; + } + + unsigned char u_break_iterator_buffer1[U_BRK_SAFECLONE_BUFFERSIZE]; + unsigned char u_break_iterator_buffer2[U_BRK_SAFECLONE_BUFFERSIZE]; + 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)"); + RETVAL_FALSE; + goto out_bi1; + } + + 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)"); + RETVAL_FALSE; + goto out_bi2; + } + + ubrk_setText(bi1, ustring1, ustring1_len, &ustatus); + if (U_FAILURE(ustatus)) { + intl_error_set_code(NULL, ustatus); + + intl_error_set_custom_msg(NULL, "Error on ubrk_setText for argument #1 ($string1)"); + RETVAL_FALSE; + goto out_bi2; + } + + ubrk_setText(bi2, ustring2, ustring2_len, &ustatus); + if (U_FAILURE(ustatus)) { + intl_error_set_code(NULL, ustatus); + + intl_error_set_custom_msg(NULL, "Error on ubrk_setText for argument #2 ($string2)"); + RETVAL_FALSE; + goto out_bi2; + } + 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"); + RETVAL_FALSE; + goto out_collator; + } + + zend_long *p1, *p2, *tmp; + p1 = reinterpret_cast(safe_emalloc((size_t) strlen_2 + 1, sizeof(zend_long), 0)); + p2 = reinterpret_cast(safe_emalloc((size_t) strlen_2 + 1, sizeof(zend_long), 0)); + + for (i2 = 0; i2 <= strlen_2; i2++) { + p1[i2] = i2 * cost_ins; + } + + while (true) { + current1 = ubrk_current(bi1); + pos1 = ubrk_next(bi1); + if (pos1 == UBRK_DONE) { + break; + } + p2[0] = p1[0] + cost_del; + for (i2 = 0, pos2 = 0; pos2 != UBRK_DONE; i2++) { + current2 = ubrk_current(bi2); + pos2 = ubrk_next(bi2); + if (pos2 == UBRK_DONE) { + break; + } + if (ucol_strcoll(collator, ustring1 + current1, pos1 - current1, ustring2 + current2, pos2 - current2) == UCOL_EQUAL) { + c0 = p1[i2]; + } else { + c0 = p1[i2] + cost_rep; + } + c1 = p1[i2 + 1] + cost_del; + if (c1 < c0) { + c0 = c1; + } + c2 = p2[i2] + cost_ins; + if (c2 < c0) { + c0 = c2; + } + p2[i2 + 1] = c0; + } + ubrk_first(bi2); + tmp = p1; + p1 = p2; + p2 = tmp; + } + + retval = p1[strlen_2]; + RETVAL_LONG(retval); + + efree(p2); + efree(p1); + +out_collator: + ucol_close(collator); +out_bi2: + ubrk_close(bi2); +out_bi1: + ubrk_close(bi1); +out_ustring2: + efree(ustring2); +out_ustring1: + efree(ustring1); +} + +/* }}} */ diff --git a/ext/intl/grapheme/grapheme_util.c b/ext/intl/grapheme/grapheme_util.c deleted file mode 100644 index 501b9dfb221d0..0000000000000 --- a/ext/intl/grapheme/grapheme_util.c +++ /dev/null @@ -1,394 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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. | - +----------------------------------------------------------------------+ - | Author: Ed Batutis | - +----------------------------------------------------------------------+ - */ - -/* {{{ includes */ -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include "grapheme.h" -#include "grapheme_util.h" -#include "intl_common.h" - -#include -#include -#include -#include -#include - -ZEND_EXTERN_MODULE_GLOBALS( intl ) - -/* }}} */ - -/* {{{ grapheme_close_global_iterator - clean up */ -void -grapheme_close_global_iterator( void ) -{ - UBreakIterator *global_break_iterator = INTL_G( grapheme_iterator ); - - if ( NULL != global_break_iterator ) { - ubrk_close(global_break_iterator); - } -} -/* }}} */ - -/* {{{ grapheme_substr_ascii f='from' - starting point, l='length' */ -void grapheme_substr_ascii(char *str, size_t str_len, int32_t f, int32_t l, char **sub_str, int32_t *sub_str_len) -{ - int32_t str_len2 = (int32_t)str_len; /* in order to avoid signed/unsigned problems */ - *sub_str = NULL; - - if(str_len > INT32_MAX) { - /* We cannot return long strings from ICU functions, so we won't here too */ - return; - } - - /* if "from" position is negative, count start position from the end - * of the string - */ - if (f < 0) { - f = str_len2 + f; - if (f < 0) { - f = 0; - } - } else if (f > str_len2) { - f = str_len2; - } - - /* if "length" position is negative, set it to the length - * needed to stop that many chars from the end of the string - */ - if (l < 0) { - l = (str_len2 - f) + l; - if (l < 0) { - l = 0; - } - } else if (l > str_len2 - f) { - l = str_len2 - f; - } - - *sub_str = str + f; - *sub_str_len = l; -} -/* }}} */ - -#define STRPOS_CHECK_STATUS(status, error) \ - if ( U_FAILURE( (status) ) ) { \ - intl_error_set_code( NULL, (status) ); \ - intl_error_set_custom_msg( NULL, (error), 0 ); \ - 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) -{ - UChar *uhaystack = NULL, *uneedle = NULL; - int32_t uhaystack_len = 0, uneedle_len = 0, char_pos, ret_pos, offset_pos = 0; - unsigned char u_break_iterator_buffer[U_BRK_SAFECLONE_BUFFERSIZE]; - UBreakIterator* bi = NULL; - UErrorCode status; - UStringSearch* src = NULL; - - if(puchar_pos) { - *puchar_pos = -1; - } - /* convert the strings to UTF-16. */ - - status = U_ZERO_ERROR; - intl_convert_utf8_to_utf16(&uhaystack, &uhaystack_len, haystack, haystack_len, &status ); - STRPOS_CHECK_STATUS(status, "Error converting input string to UTF-16"); - - status = U_ZERO_ERROR; - intl_convert_utf8_to_utf16(&uneedle, &uneedle_len, needle, needle_len, &status ); - STRPOS_CHECK_STATUS(status, "Error converting needle string to UTF-16"); - - /* get a pointer to the haystack taking into account the offset */ - status = U_ZERO_ERROR; - bi = grapheme_get_break_iterator(u_break_iterator_buffer, &status ); - STRPOS_CHECK_STATUS(status, "Failed to get iterator"); - status = U_ZERO_ERROR; - ubrk_setText(bi, uhaystack, uhaystack_len, &status); - STRPOS_CHECK_STATUS(status, "Failed to set up iterator"); - - if (uneedle_len == 0) { - offset_pos = grapheme_get_haystack_offset(bi, offset); - if (offset_pos == -1) { - zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); - ret_pos = -1; - goto finish; - } - ret_pos = last && offset >= 0 ? uhaystack_len : offset_pos; - goto finish; - } - - status = U_ZERO_ERROR; - src = usearch_open(uneedle, uneedle_len, uhaystack, uhaystack_len, "", bi, &status); - STRPOS_CHECK_STATUS(status, "Error creating search object"); - - if(f_ignore_case) { - UCollator *coll = usearch_getCollator(src); - status = U_ZERO_ERROR; - ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_SECONDARY, &status); - STRPOS_CHECK_STATUS(status, "Error setting collation strength"); - usearch_reset(src); - } - - if(offset != 0) { - offset_pos = grapheme_get_haystack_offset(bi, offset); - if (offset_pos == -1) { - zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); - ret_pos = -1; - goto finish; - } - status = U_ZERO_ERROR; - usearch_setOffset(src, last ? 0 : offset_pos, &status); - STRPOS_CHECK_STATUS(status, "Invalid search offset"); - } - - - if(last) { - if (offset >= 0) { - char_pos = usearch_last(src, &status); - if(char_pos < offset_pos) { - /* last one is beyond our start offset */ - char_pos = USEARCH_DONE; - } - } else { - /* searching backwards is broken, so we search forwards, albeit it's less efficient */ - int32_t prev_pos = USEARCH_DONE; - do { - char_pos = usearch_next(src, &status); - if (char_pos == USEARCH_DONE || char_pos > offset_pos) { - char_pos = prev_pos; - break; - } - prev_pos = char_pos; - } while(1); - } - } else { - char_pos = usearch_next(src, &status); - } - STRPOS_CHECK_STATUS(status, "Error looking up string"); - if(char_pos != USEARCH_DONE && ubrk_isBoundary(bi, char_pos)) { - ret_pos = grapheme_count_graphemes(bi, uhaystack,char_pos); - if(puchar_pos) { - *puchar_pos = char_pos; - } - } else { - ret_pos = -1; - } - -finish: - if (uhaystack) { - efree( uhaystack ); - } - if (uneedle) { - efree( uneedle ); - } - if (bi) { - ubrk_close (bi); - } - if (src) { - usearch_close (src); - } - - return ret_pos; -} - -/* }}} */ - -/* {{{ grapheme_ascii_check: ASCII check */ -zend_long grapheme_ascii_check(const unsigned char *day, size_t len) -{ - int ret_len = len; - while ( len-- ) { - if ( *day++ > 0x7f || (*day == '\n' && *(day - 1) == '\r') ) - return -1; - } - - return ret_len; -} - -/* }}} */ - -/* {{{ grapheme_split_string: find and optionally return grapheme boundaries */ -int32_t grapheme_split_string(const UChar *text, int32_t text_length, int boundary_array[], int boundary_array_len ) -{ - unsigned char u_break_iterator_buffer[U_BRK_SAFECLONE_BUFFERSIZE]; - UErrorCode status = U_ZERO_ERROR; - int ret_len, pos; - UBreakIterator* bi; - - bi = grapheme_get_break_iterator((void*)u_break_iterator_buffer, &status ); - - if( U_FAILURE(status) ) { - return -1; - } - - ubrk_setText(bi, text, text_length, &status); - - pos = 0; - - for ( ret_len = 0; pos != UBRK_DONE; ) { - - pos = ubrk_next(bi); - - if ( pos != UBRK_DONE ) { - - if ( NULL != boundary_array && ret_len < boundary_array_len ) { - boundary_array[ret_len] = pos; - } - - ret_len++; - } - } - - ubrk_close(bi); - - return ret_len; -} -/* }}} */ - -/* {{{ grapheme_count_graphemes */ -int32_t grapheme_count_graphemes(UBreakIterator *bi, UChar *string, int32_t string_len) -{ - int ret_len = 0; - int pos = 0; - UErrorCode status = U_ZERO_ERROR; - - ubrk_setText(bi, string, string_len, &status); - - do { - - pos = ubrk_next(bi); - - if ( UBRK_DONE != pos ) { - ret_len++; - } - - } while ( UBRK_DONE != pos ); - - return ret_len; -} -/* }}} */ - - -/* {{{ grapheme_get_haystack_offset - bump the haystack pointer based on the grapheme count offset */ -int32_t grapheme_get_haystack_offset(UBreakIterator* bi, int32_t offset) -{ - int32_t pos; - int32_t (*iter_op)(UBreakIterator* bi); - int iter_incr; - - if ( 0 == offset ) { - return 0; - } - - if ( offset < 0 ) { - iter_op = ubrk_previous; - ubrk_last(bi); /* one past the end */ - iter_incr = 1; - } - else { - iter_op = ubrk_next; - iter_incr = -1; - } - - pos = 0; - - while ( pos != UBRK_DONE && offset != 0 ) { - - pos = iter_op(bi); - - if ( UBRK_DONE != pos ) { - offset += iter_incr; - } - } - - if ( offset != 0 ) { - return -1; - } - - return pos; -} -/* }}} */ - -/* {{{ grapheme_strrpos_ascii: borrowed from the php ext/standard/string.c */ -zend_long grapheme_strrpos_ascii(char *haystack, size_t haystack_len, char *needle, size_t needle_len, int32_t offset) -{ - char *p, *e; - - if (offset >= 0) { - p = haystack + offset; - e = haystack + haystack_len - needle_len; - } else { - p = haystack; - if (needle_len > (size_t)-offset) { - e = haystack + haystack_len - needle_len; - } else { - e = haystack + haystack_len + offset; - } - } - - if (needle_len == 1) { - /* Single character search can shortcut memcmps */ - while (e >= p) { - if (*e == *needle) { - return (e - p + (offset > 0 ? offset : 0)); - } - e--; - } - return -1; - } - - while (e >= p) { - if (memcmp(e, needle, needle_len) == 0) { - return (e - p + (offset > 0 ? offset : 0)); - } - e--; - } - - return -1; -} - -/* }}} */ - -/* {{{ grapheme_get_break_iterator: get a clone of the global character break iterator */ -UBreakIterator* grapheme_get_break_iterator(void *stack_buffer, UErrorCode *status ) -{ - UBreakIterator *global_break_iterator = INTL_G( grapheme_iterator ); - - if ( NULL == global_break_iterator ) { - - global_break_iterator = ubrk_open(UBRK_CHARACTER, - NULL, /* icu default locale - locale has no effect on this iterator */ - NULL, /* text not set in global iterator */ - 0, /* text length = 0 */ - status); - - INTL_G(grapheme_iterator) = global_break_iterator; - } - -#if U_ICU_VERSION_MAJOR_NUM >= 69 - return ubrk_clone(global_break_iterator, status); -#else - int32_t buffer_size = U_BRK_SAFECLONE_BUFFERSIZE; - - return ubrk_safeClone(global_break_iterator, stack_buffer, &buffer_size, status); -#endif -} -/* }}} */ diff --git a/ext/intl/grapheme/grapheme_util.cpp b/ext/intl/grapheme/grapheme_util.cpp new file mode 100644 index 0000000000000..a04f3db0b8a6d --- /dev/null +++ b/ext/intl/grapheme/grapheme_util.cpp @@ -0,0 +1,401 @@ +/* + +----------------------------------------------------------------------+ + | 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. | + +----------------------------------------------------------------------+ + | Author: Ed Batutis | + +----------------------------------------------------------------------+ + */ + +/* {{{ includes */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#if __cplusplus >= 201703L +#include +#include +#endif + +extern "C" { +#include +#include "grapheme.h" +#include "grapheme_util.h" +#include "intl_common.h" +} + +#include +#include +#include +#include +#include + +ZEND_EXTERN_MODULE_GLOBALS( intl ) + +/* }}} */ + +/* {{{ grapheme_close_global_iterator - clean up */ +U_CFUNC void +grapheme_close_global_iterator( void ) +{ + UBreakIterator *global_break_iterator = INTL_G( grapheme_iterator ); + + if ( NULL != global_break_iterator ) { + ubrk_close(global_break_iterator); + } +} +/* }}} */ + +/* {{{ grapheme_substr_ascii f='from' - starting point, l='length' */ +U_CFUNC void grapheme_substr_ascii(char *str, size_t str_len, int32_t f, int32_t l, char **sub_str, int32_t *sub_str_len) +{ + int32_t str_len2 = (int32_t)str_len; /* in order to avoid signed/unsigned problems */ + *sub_str = NULL; + + if(str_len > INT32_MAX) { + /* We cannot return long strings from ICU functions, so we won't here too */ + return; + } + + /* if "from" position is negative, count start position from the end + * of the string + */ + if (f < 0) { + f = str_len2 + f; + if (f < 0) { + f = 0; + } + } else if (f > str_len2) { + f = str_len2; + } + + /* if "length" position is negative, set it to the length + * needed to stop that many chars from the end of the string + */ + if (l < 0) { + l = (str_len2 - f) + l; + if (l < 0) { + l = 0; + } + } else if (l > str_len2 - f) { + l = str_len2 - f; + } + + *sub_str = str + f; + *sub_str_len = l; +} +/* }}} */ + +#define STRPOS_CHECK_STATUS(status, error) \ + if ( U_FAILURE( (status) ) ) { \ + intl_error_set_code( NULL, (status) ); \ + intl_error_set_custom_msg( NULL, (error)); \ + ret_pos = -1; \ + goto finish; \ + } + + +/* {{{ grapheme_strpos_utf16 - strrpos using utf16*/ +U_CFUNC 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; + unsigned char u_break_iterator_buffer[U_BRK_SAFECLONE_BUFFERSIZE]; + UBreakIterator* bi = NULL; + UErrorCode status; + UStringSearch* src = NULL; + + if(puchar_pos) { + *puchar_pos = -1; + } + /* convert the strings to UTF-16. */ + + status = U_ZERO_ERROR; + intl_convert_utf8_to_utf16(&uhaystack, &uhaystack_len, haystack, haystack_len, &status ); + STRPOS_CHECK_STATUS(status, "Error converting input string to UTF-16"); + + status = U_ZERO_ERROR; + intl_convert_utf8_to_utf16(&uneedle, &uneedle_len, needle, needle_len, &status ); + STRPOS_CHECK_STATUS(status, "Error converting needle string to UTF-16"); + + /* get a pointer to the haystack taking into account the offset */ + status = U_ZERO_ERROR; + bi = grapheme_get_break_iterator(u_break_iterator_buffer, &status ); + STRPOS_CHECK_STATUS(status, "Failed to get iterator"); + status = U_ZERO_ERROR; + ubrk_setText(bi, uhaystack, uhaystack_len, &status); + STRPOS_CHECK_STATUS(status, "Failed to set up iterator"); + + if (uneedle_len == 0) { + offset_pos = grapheme_get_haystack_offset(bi, offset); + if (offset_pos == -1) { + zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); + ret_pos = -1; + goto finish; + } + ret_pos = last && offset >= 0 ? uhaystack_len : offset_pos; + goto finish; + } + + status = U_ZERO_ERROR; + src = usearch_open(uneedle, uneedle_len, uhaystack, uhaystack_len, locale, bi, &status); + STRPOS_CHECK_STATUS(status, "Error creating search object"); + + if(f_ignore_case) { + UCollator *coll = usearch_getCollator(src); + status = U_ZERO_ERROR; + ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_SECONDARY, &status); + STRPOS_CHECK_STATUS(status, "Error setting collation strength"); + usearch_reset(src); + } + + if(offset != 0) { + offset_pos = grapheme_get_haystack_offset(bi, offset); + if (offset_pos == -1) { + zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); + ret_pos = -1; + goto finish; + } + status = U_ZERO_ERROR; + usearch_setOffset(src, last ? 0 : offset_pos, &status); + STRPOS_CHECK_STATUS(status, "Invalid search offset"); + } + + + if(last) { + if (offset >= 0) { + char_pos = usearch_last(src, &status); + if(char_pos < offset_pos) { + /* last one is beyond our start offset */ + char_pos = USEARCH_DONE; + } + } else { + /* searching backwards is broken, so we search forwards, albeit it's less efficient */ + int32_t prev_pos = USEARCH_DONE; + do { + char_pos = usearch_next(src, &status); + if (char_pos == USEARCH_DONE || char_pos > offset_pos) { + char_pos = prev_pos; + break; + } + prev_pos = char_pos; + } while(1); + } + } else { + char_pos = usearch_next(src, &status); + } + STRPOS_CHECK_STATUS(status, "Error looking up string"); + if(char_pos != USEARCH_DONE && ubrk_isBoundary(bi, char_pos)) { + ret_pos = grapheme_count_graphemes(bi, uhaystack,char_pos); + if(puchar_pos) { + *puchar_pos = char_pos; + } + } else { + ret_pos = -1; + } + +finish: + if (uhaystack) { + efree( uhaystack ); + } + if (uneedle) { + efree( uneedle ); + } + if (bi) { + ubrk_close (bi); + } + if (src) { + usearch_close (src); + } + + return ret_pos; +} + +/* }}} */ + +/* {{{ grapheme_ascii_check: ASCII check */ +U_CFUNC zend_long grapheme_ascii_check(const unsigned char *day, size_t len) +{ + int ret_len = len; + while ( len-- ) { + if ( *day++ > 0x7f || (*day == '\n' && *(day - 1) == '\r') ) + return -1; + } + + return ret_len; +} + +/* }}} */ + +/* {{{ grapheme_split_string: find and optionally return grapheme boundaries */ +U_CFUNC int32_t grapheme_split_string(const UChar *text, int32_t text_length, int boundary_array[], int boundary_array_len ) +{ + unsigned char u_break_iterator_buffer[U_BRK_SAFECLONE_BUFFERSIZE]; + UErrorCode status = U_ZERO_ERROR; + int ret_len, pos; + UBreakIterator* bi; + + bi = grapheme_get_break_iterator((void*)u_break_iterator_buffer, &status ); + + if( U_FAILURE(status) ) { + return -1; + } + + ubrk_setText(bi, text, text_length, &status); + + pos = 0; + + for ( ret_len = 0; pos != UBRK_DONE; ) { + + pos = ubrk_next(bi); + + if ( pos != UBRK_DONE ) { + + if ( NULL != boundary_array && ret_len < boundary_array_len ) { + boundary_array[ret_len] = pos; + } + + ret_len++; + } + } + + ubrk_close(bi); + + return ret_len; +} +/* }}} */ + +/* {{{ grapheme_count_graphemes */ +U_CFUNC int32_t grapheme_count_graphemes(UBreakIterator *bi, UChar *string, int32_t string_len) +{ + int ret_len = 0; + int pos = 0; + UErrorCode status = U_ZERO_ERROR; + + ubrk_setText(bi, string, string_len, &status); + + do { + + pos = ubrk_next(bi); + + if ( UBRK_DONE != pos ) { + ret_len++; + } + + } while ( UBRK_DONE != pos ); + + return ret_len; +} +/* }}} */ + + +/* {{{ grapheme_get_haystack_offset - bump the haystack pointer based on the grapheme count offset */ +U_CFUNC int32_t grapheme_get_haystack_offset(UBreakIterator* bi, int32_t offset) +{ + int32_t pos; + int32_t (*iter_op)(UBreakIterator* bi); + int iter_incr; + + if ( 0 == offset ) { + return 0; + } + + if ( offset < 0 ) { + iter_op = ubrk_previous; + ubrk_last(bi); /* one past the end */ + iter_incr = 1; + } + else { + iter_op = ubrk_next; + iter_incr = -1; + } + + pos = 0; + + while ( pos != UBRK_DONE && offset != 0 ) { + + pos = iter_op(bi); + + if ( UBRK_DONE != pos ) { + offset += iter_incr; + } + } + + if ( offset != 0 ) { + return -1; + } + + return pos; +} +/* }}} */ + +/* {{{ grapheme_strrpos_ascii: borrowed from the php ext/standard/string.c */ +U_CFUNC zend_long grapheme_strrpos_ascii(char *haystack, size_t haystack_len, char *needle, size_t needle_len, int32_t offset) +{ + char *p, *e; + + if (offset >= 0) { + p = haystack + offset; + e = haystack + haystack_len - needle_len; + } else { + p = haystack; + if (needle_len > (size_t)-offset) { + e = haystack + haystack_len - needle_len; + } else { + e = haystack + haystack_len + offset; + } + } + + if (needle_len == 1) { + /* Single character search can shortcut memcmps */ + while (e >= p) { + if (*e == *needle) { + return (e - p + (offset > 0 ? offset : 0)); + } + e--; + } + return -1; + } + + while (e >= p) { + if (memcmp(e, needle, needle_len) == 0) { + return (e - p + (offset > 0 ? offset : 0)); + } + e--; + } + + return -1; +} + +/* }}} */ + +/* {{{ grapheme_get_break_iterator: get a clone of the global character break iterator */ +U_CFUNC UBreakIterator* grapheme_get_break_iterator(void *stack_buffer, UErrorCode *status ) +{ + UBreakIterator *global_break_iterator = INTL_G( grapheme_iterator ); + + if ( NULL == global_break_iterator ) { + + global_break_iterator = ubrk_open(UBRK_CHARACTER, + NULL, /* icu default locale - locale has no effect on this iterator */ + NULL, /* text not set in global iterator */ + 0, /* text length = 0 */ + status); + + INTL_G(grapheme_iterator) = global_break_iterator; + } + +#if U_ICU_VERSION_MAJOR_NUM >= 69 + return ubrk_clone(global_break_iterator, status); +#else + int32_t buffer_size = U_BRK_SAFECLONE_BUFFERSIZE; + + return ubrk_safeClone(global_break_iterator, stack_buffer, &buffer_size, status); +#endif +} +/* }}} */ diff --git a/ext/intl/grapheme/grapheme_util.h b/ext/intl/grapheme/grapheme_util.h index d03194621acf3..57d2ace384f89 100644 --- a/ext/intl/grapheme/grapheme_util.h +++ b/ext/intl/grapheme/grapheme_util.h @@ -15,6 +15,9 @@ #ifndef GRAPHEME_GRAPHEME_UTIL_H #define GRAPHEME_GRAPHEME_UTIL_H +#ifdef __cplusplus +extern "C" { +#endif #include "php_intl.h" #include "intl_convert.h" @@ -25,8 +28,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 ); @@ -35,6 +38,9 @@ int32_t grapheme_count_graphemes(UBreakIterator *bi, UChar *string, int32_t stri int32_t grapheme_get_haystack_offset(UBreakIterator* bi, int32_t offset); UBreakIterator* grapheme_get_break_iterator(void *stack_buffer, UErrorCode *status ); +#ifdef __cplusplus +} +#endif /* OUTSIDE_STRING: check if (possibly negative) long offset is outside the string with int32_t length */ #define OUTSIDE_STRING(offset, max_len) ( offset <= INT32_MIN || offset > INT32_MAX || (offset < 0 ? -offset > (zend_long) max_len : offset > (zend_long) max_len) ) diff --git a/ext/intl/idn/idn.c b/ext/intl/idn/idn.c deleted file mode 100644 index cd4546ad7f8bb..0000000000000 --- a/ext/intl/idn/idn.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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. | - +----------------------------------------------------------------------+ - | Author: Pierre A. Joye | - | Gustavo Lopes | - +----------------------------------------------------------------------+ - */ - -/* {{{ includes */ -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include -#include - -#include "idn.h" -#include "intl_error.h" -/* }}} */ - -enum { - INTL_IDN_TO_ASCII = 0, - INTL_IDN_TO_UTF8 -}; - -/* like INTL_CHECK_STATUS, but as a function and varying the name of the func */ -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); - return FAILURE; - } - - return SUCCESS; -} - -static void php_intl_idn_to_46(INTERNAL_FUNCTION_PARAMETERS, - const zend_string *domain, uint32_t option, int mode, zval *idna_info) -{ - UErrorCode status = U_ZERO_ERROR; - UIDNA *uts46; - int32_t len; - int32_t buffer_capac; - zend_string *buffer; - UIDNAInfo info = UIDNA_INFO_INITIALIZER; - - uts46 = uidna_openUTS46(option, &status); - if (php_intl_idn_check_status(status, "failed to open UIDNA instance") == FAILURE) { - RETURN_FALSE; - } - - if (mode == INTL_IDN_TO_ASCII) { - buffer_capac = 255; - buffer = zend_string_alloc(buffer_capac, 0); - len = uidna_nameToASCII_UTF8(uts46, ZSTR_VAL(domain), ZSTR_LEN(domain), - ZSTR_VAL(buffer), buffer_capac, &info, &status); - } else { - buffer_capac = 252*4; - buffer = zend_string_alloc(buffer_capac, 0); - len = uidna_nameToUnicodeUTF8(uts46, ZSTR_VAL(domain), ZSTR_LEN(domain), - ZSTR_VAL(buffer), buffer_capac, &info, &status); - } - if (len >= buffer_capac || php_intl_idn_check_status(status, "failed to convert name") == FAILURE) { - uidna_close(uts46); - zend_string_efree(buffer); - RETURN_FALSE; - } - - ZSTR_VAL(buffer)[len] = '\0'; - ZSTR_LEN(buffer) = len; - - if (idna_info) { - add_assoc_str_ex(idna_info, "result", sizeof("result")-1, zend_string_copy(buffer)); - add_assoc_bool_ex(idna_info, "isTransitionalDifferent", - sizeof("isTransitionalDifferent")-1, info.isTransitionalDifferent); - add_assoc_long_ex(idna_info, "errors", sizeof("errors")-1, (zend_long)info.errors); - } - - if (info.errors == 0) { - RETVAL_STR(buffer); - } else { - zend_string_release_ex(buffer, false); - RETVAL_FALSE; - } - - uidna_close(uts46); -} - -static void php_intl_idn_handoff(INTERNAL_FUNCTION_PARAMETERS, int mode) -{ - zend_string *domain; - zend_long option = UIDNA_DEFAULT, - variant = INTL_IDN_VARIANT_UTS46; - zval *idna_info = NULL; - - intl_error_reset(NULL); - - ZEND_PARSE_PARAMETERS_START(1, 4) - Z_PARAM_STR(domain) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(option) - Z_PARAM_LONG(variant) - Z_PARAM_ZVAL(idna_info) - ZEND_PARSE_PARAMETERS_END(); - - if (ZSTR_LEN(domain) == 0) { - zend_argument_must_not_be_empty_error(1); - RETURN_THROWS(); - } - if (ZSTR_LEN(domain) > INT32_MAX - 1) { - zend_argument_value_error(1, "must be less than " PRId32 " bytes", INT32_MAX); - RETURN_THROWS(); - } - if (variant != INTL_IDN_VARIANT_UTS46) { - zend_argument_value_error(2, "must be INTL_IDNA_VARIANT_UTS46"); - RETURN_THROWS(); - } - /* don't check options; it wasn't checked before */ - - if (idna_info != NULL) { - idna_info = zend_try_array_init(idna_info); - if (!idna_info) { - RETURN_THROWS(); - } - } - - php_intl_idn_to_46(INTERNAL_FUNCTION_PARAM_PASSTHRU, domain, (uint32_t)option, mode, idna_info); -} - -/* {{{ Converts an Unicode domain to ASCII representation, as defined in the IDNA RFC */ -PHP_FUNCTION(idn_to_ascii) -{ - php_intl_idn_handoff(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTL_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) -{ - php_intl_idn_handoff(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTL_IDN_TO_UTF8); -} -/* }}} */ diff --git a/ext/intl/idn/idn.cpp b/ext/intl/idn/idn.cpp new file mode 100644 index 0000000000000..6c7e4d8c6d683 --- /dev/null +++ b/ext/intl/idn/idn.cpp @@ -0,0 +1,159 @@ +/* + +----------------------------------------------------------------------+ + | 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. | + +----------------------------------------------------------------------+ + | Author: Pierre A. Joye | + | Gustavo Lopes | + +----------------------------------------------------------------------+ + */ + +/* {{{ includes */ +#ifdef HAVE_CONFIG_H +#include +#endif + +extern "C" { +#include "../php_intl.h" +} +#include +#include + +#include "idn.h" + +extern "C" { +#include "intl_error.h" +} +/* }}} */ + +enum { + INTL_IDN_TO_ASCII = 0, + INTL_IDN_TO_UTF8 +}; + +/* like INTL_CHECK_STATUS, but as a function and varying the name of the func */ +static zend_result php_intl_idn_check_status(UErrorCode err, const char *msg) +{ + intl_error_set_code(NULL, err); + if (U_FAILURE(err)) { + intl_error_set_custom_msg(NULL, msg); + return FAILURE; + } + + return SUCCESS; +} + +static void php_intl_idn_to_46(INTERNAL_FUNCTION_PARAMETERS, + const zend_string *domain, uint32_t option, int mode, zval *idna_info) +{ + UErrorCode status = U_ZERO_ERROR; + UIDNA *uts46; + int32_t len; + int32_t buffer_capac; + zend_string *buffer; + UIDNAInfo info = UIDNA_INFO_INITIALIZER; + + uts46 = uidna_openUTS46(option, &status); + if (php_intl_idn_check_status(status, "failed to open UIDNA instance") == FAILURE) { + RETURN_FALSE; + } + + if (mode == INTL_IDN_TO_ASCII) { + buffer_capac = 255; + buffer = zend_string_alloc(buffer_capac, 0); + len = uidna_nameToASCII_UTF8(uts46, ZSTR_VAL(domain), ZSTR_LEN(domain), + ZSTR_VAL(buffer), buffer_capac, &info, &status); + } else { + buffer_capac = 252*4; + buffer = zend_string_alloc(buffer_capac, 0); + len = uidna_nameToUnicodeUTF8(uts46, ZSTR_VAL(domain), ZSTR_LEN(domain), + ZSTR_VAL(buffer), buffer_capac, &info, &status); + } + if (len >= buffer_capac || php_intl_idn_check_status(status, "failed to convert name") == FAILURE) { + uidna_close(uts46); + zend_string_efree(buffer); + RETURN_FALSE; + } + + ZSTR_VAL(buffer)[len] = '\0'; + ZSTR_LEN(buffer) = len; + + if (idna_info) { + add_assoc_str_ex(idna_info, "result", sizeof("result")-1, zend_string_copy(buffer)); + add_assoc_bool_ex(idna_info, "isTransitionalDifferent", + sizeof("isTransitionalDifferent")-1, info.isTransitionalDifferent); + add_assoc_long_ex(idna_info, "errors", sizeof("errors")-1, (zend_long)info.errors); + } + + if (info.errors == 0) { + RETVAL_STR(buffer); + } else { + zend_string_release_ex(buffer, false); + RETVAL_FALSE; + } + + uidna_close(uts46); +} + +static void php_intl_idn_handoff(INTERNAL_FUNCTION_PARAMETERS, int mode) +{ + zend_string *domain; + zend_long option = UIDNA_DEFAULT, + variant = INTL_IDN_VARIANT_UTS46; + zval *idna_info = NULL; + + intl_error_reset(NULL); + + ZEND_PARSE_PARAMETERS_START(1, 4) + Z_PARAM_STR(domain) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(option) + Z_PARAM_LONG(variant) + Z_PARAM_ZVAL(idna_info) + ZEND_PARSE_PARAMETERS_END(); + + if (ZSTR_LEN(domain) == 0) { + zend_argument_must_not_be_empty_error(1); + RETURN_THROWS(); + } + if (ZSTR_LEN(domain) > INT32_MAX - 1) { + zend_argument_value_error(1, "must be less than " PRId32 " bytes", INT32_MAX); + RETURN_THROWS(); + } + if (variant != INTL_IDN_VARIANT_UTS46) { + zend_argument_value_error(2, "must be INTL_IDNA_VARIANT_UTS46"); + RETURN_THROWS(); + } + /* don't check options; it wasn't checked before */ + + if (idna_info != NULL) { + idna_info = zend_try_array_init(idna_info); + if (!idna_info) { + RETURN_THROWS(); + } + } + + php_intl_idn_to_46(INTERNAL_FUNCTION_PARAM_PASSTHRU, domain, (uint32_t)option, mode, idna_info); +} + +/* {{{ Converts an Unicode domain to ASCII representation, as defined in the IDNA RFC */ +U_CFUNC PHP_FUNCTION(idn_to_ascii) +{ + php_intl_idn_handoff(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTL_IDN_TO_ASCII); +} +/* }}} */ + + +/* {{{ Converts an ASCII representation of the domain to Unicode (UTF-8), as defined in the IDNA RFC */ +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_arginfo.h b/ext/intl/listformatter/listformatter_arginfo.h index 3a2afa2d1c2d9..fda62aac9691d 100644 --- a/ext/intl/listformatter/listformatter_arginfo.h +++ b/ext/intl/listformatter/listformatter_arginfo.h @@ -40,59 +40,59 @@ static zend_class_entry *register_class_IntlListFormatter(void) zval const_TYPE_AND_value; ZVAL_LONG(&const_TYPE_AND_value, ULISTFMT_TYPE_AND); - zend_string *const_TYPE_AND_name = zend_string_init_interned("TYPE_AND", sizeof("TYPE_AND") - 1, 1); + zend_string *const_TYPE_AND_name = zend_string_init_interned("TYPE_AND", sizeof("TYPE_AND") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_AND_name, &const_TYPE_AND_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_AND_name); + zend_string_release_ex(const_TYPE_AND_name, true); #endif #if !(U_ICU_VERSION_MAJOR_NUM >= 67) zval const_TYPE_AND_value; ZVAL_LONG(&const_TYPE_AND_value, INTL_LISTFORMATTER_FALLBACK_TYPE_AND); - zend_string *const_TYPE_AND_name = zend_string_init_interned("TYPE_AND", sizeof("TYPE_AND") - 1, 1); + zend_string *const_TYPE_AND_name = zend_string_init_interned("TYPE_AND", sizeof("TYPE_AND") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_AND_name, &const_TYPE_AND_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_AND_name); + zend_string_release_ex(const_TYPE_AND_name, true); #endif #if U_ICU_VERSION_MAJOR_NUM >= 67 zval const_TYPE_OR_value; ZVAL_LONG(&const_TYPE_OR_value, ULISTFMT_TYPE_OR); - zend_string *const_TYPE_OR_name = zend_string_init_interned("TYPE_OR", sizeof("TYPE_OR") - 1, 1); + zend_string *const_TYPE_OR_name = zend_string_init_interned("TYPE_OR", sizeof("TYPE_OR") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_OR_name, &const_TYPE_OR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_OR_name); + zend_string_release_ex(const_TYPE_OR_name, true); zval const_TYPE_UNITS_value; ZVAL_LONG(&const_TYPE_UNITS_value, ULISTFMT_TYPE_UNITS); - zend_string *const_TYPE_UNITS_name = zend_string_init_interned("TYPE_UNITS", sizeof("TYPE_UNITS") - 1, 1); + zend_string *const_TYPE_UNITS_name = zend_string_init_interned("TYPE_UNITS", sizeof("TYPE_UNITS") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_UNITS_name, &const_TYPE_UNITS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_UNITS_name); + zend_string_release_ex(const_TYPE_UNITS_name, true); zval const_WIDTH_WIDE_value; ZVAL_LONG(&const_WIDTH_WIDE_value, ULISTFMT_WIDTH_WIDE); - zend_string *const_WIDTH_WIDE_name = zend_string_init_interned("WIDTH_WIDE", sizeof("WIDTH_WIDE") - 1, 1); + zend_string *const_WIDTH_WIDE_name = zend_string_init_interned("WIDTH_WIDE", sizeof("WIDTH_WIDE") - 1, true); zend_declare_typed_class_constant(class_entry, const_WIDTH_WIDE_name, &const_WIDTH_WIDE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WIDTH_WIDE_name); + zend_string_release_ex(const_WIDTH_WIDE_name, true); #endif #if !(U_ICU_VERSION_MAJOR_NUM >= 67) zval const_WIDTH_WIDE_value; ZVAL_LONG(&const_WIDTH_WIDE_value, INTL_LISTFORMATTER_FALLBACK_WIDTH_WIDE); - zend_string *const_WIDTH_WIDE_name = zend_string_init_interned("WIDTH_WIDE", sizeof("WIDTH_WIDE") - 1, 1); + zend_string *const_WIDTH_WIDE_name = zend_string_init_interned("WIDTH_WIDE", sizeof("WIDTH_WIDE") - 1, true); zend_declare_typed_class_constant(class_entry, const_WIDTH_WIDE_name, &const_WIDTH_WIDE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WIDTH_WIDE_name); + zend_string_release_ex(const_WIDTH_WIDE_name, true); #endif #if U_ICU_VERSION_MAJOR_NUM >= 67 zval const_WIDTH_SHORT_value; ZVAL_LONG(&const_WIDTH_SHORT_value, ULISTFMT_WIDTH_SHORT); - zend_string *const_WIDTH_SHORT_name = zend_string_init_interned("WIDTH_SHORT", sizeof("WIDTH_SHORT") - 1, 1); + zend_string *const_WIDTH_SHORT_name = zend_string_init_interned("WIDTH_SHORT", sizeof("WIDTH_SHORT") - 1, true); zend_declare_typed_class_constant(class_entry, const_WIDTH_SHORT_name, &const_WIDTH_SHORT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WIDTH_SHORT_name); + zend_string_release_ex(const_WIDTH_SHORT_name, true); zval const_WIDTH_NARROW_value; ZVAL_LONG(&const_WIDTH_NARROW_value, ULISTFMT_WIDTH_NARROW); - zend_string *const_WIDTH_NARROW_name = zend_string_init_interned("WIDTH_NARROW", sizeof("WIDTH_NARROW") - 1, 1); + zend_string *const_WIDTH_NARROW_name = zend_string_init_interned("WIDTH_NARROW", sizeof("WIDTH_NARROW") - 1, true); zend_declare_typed_class_constant(class_entry, const_WIDTH_NARROW_name, &const_WIDTH_NARROW_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WIDTH_NARROW_name); + zend_string_release_ex(const_WIDTH_NARROW_name, true); #endif return class_entry; diff --git a/ext/intl/listformatter/listformatter_class.c b/ext/intl/listformatter/listformatter_class.c deleted file mode 100644 index f1a5039079b8a..0000000000000 --- a/ext/intl/listformatter/listformatter_class.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Bogdan Ungureanu | - +----------------------------------------------------------------------+ -*/ - -#include "php.h" -#include "php_intl.h" -#include -#include "listformatter_class.h" -#include "listformatter_arginfo.h" -#include "intl_convert.h" - -static zend_object_handlers listformatter_handlers; - -static void listformatter_free_obj(zend_object *object) -{ - ListFormatter_object *obj = php_intl_listformatter_fetch_object(object); - - if( obj->lf_data.ulistfmt ) - ulistfmt_close( obj->lf_data.ulistfmt ); - - obj->lf_data.ulistfmt = NULL; - intl_error_reset( &obj->lf_data.error ); - - zend_object_std_dtor(&obj->zo); -} - -static zend_object *listformatter_create_object(zend_class_entry *class_type) -{ - ListFormatter_object *obj; - obj = zend_object_alloc(sizeof(ListFormatter_object), class_type); - - obj->lf_data.ulistfmt = NULL; - intl_error_reset( &obj->lf_data.error ); - - zend_object_std_init(&obj->zo, class_type); - object_properties_init(&obj->zo, class_type); - obj->zo.handlers = &listformatter_handlers; - return &obj->zo; -} - -PHP_METHOD(IntlListFormatter, __construct) -{ - ListFormatter_object *obj = Z_INTL_LISTFORMATTER_P(ZEND_THIS); - char* locale; - size_t locale_len = 0; - #if U_ICU_VERSION_MAJOR_NUM >= 67 - zend_long type = ULISTFMT_TYPE_AND; - zend_long width = ULISTFMT_WIDTH_WIDE; - #else - zend_long type = INTL_LISTFORMATTER_FALLBACK_TYPE_AND; - zend_long width = INTL_LISTFORMATTER_FALLBACK_WIDTH_WIDE; - #endif - ZEND_PARSE_PARAMETERS_START(1, 3) - Z_PARAM_STRING(locale, locale_len) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(type) - Z_PARAM_LONG(width) - ZEND_PARSE_PARAMETERS_END(); - - if(locale_len == 0) { - locale = (char *)intl_locale_get_default(); - } - - 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); - RETURN_THROWS(); - } - - if (strlen(uloc_getISO3Language(locale)) == 0) { - zend_argument_value_error(1, "\"%s\" is invalid", locale); - RETURN_THROWS(); - } - - UErrorCode status = U_ZERO_ERROR; - #if U_ICU_VERSION_MAJOR_NUM >= 67 - if (type != ULISTFMT_TYPE_AND && type != ULISTFMT_TYPE_OR && type != ULISTFMT_TYPE_UNITS) { - zend_argument_value_error(2, "must be one of IntlListFormatter::TYPE_AND, IntlListFormatter::TYPE_OR, or IntlListFormatter::TYPE_UNITS"); - RETURN_THROWS(); - } - - if (width != ULISTFMT_WIDTH_WIDE && width != ULISTFMT_WIDTH_SHORT && width != ULISTFMT_WIDTH_NARROW) { - zend_argument_value_error(3, "must be one of IntlListFormatter::WIDTH_WIDE, IntlListFormatter::WIDTH_SHORT, or IntlListFormatter::WIDTH_NARROW"); - RETURN_THROWS(); - } - - LISTFORMATTER_OBJECT(obj) = ulistfmt_openForType(locale, type, width, &status); - #else - if (type != INTL_LISTFORMATTER_FALLBACK_TYPE_AND) { - zend_argument_value_error(2, "contains an unsupported type. ICU 66 and below only support IntlListFormatter::TYPE_AND"); - RETURN_THROWS(); - } - - if (width != INTL_LISTFORMATTER_FALLBACK_WIDTH_WIDE) { - zend_argument_value_error(3, "contains an unsupported width. ICU 66 and below only support IntlListFormatter::WIDTH_WIDE"); - RETURN_THROWS(); - } - - LISTFORMATTER_OBJECT(obj) = ulistfmt_open(locale, &status); - #endif - - if (U_FAILURE(status)) { - intl_error_set(NULL, status, "Constructor failed", 0); - zend_throw_exception(IntlException_ce_ptr, "Constructor failed", 0); - RETURN_THROWS(); - } -} - -PHP_METHOD(IntlListFormatter, format) -{ - ListFormatter_object *obj = Z_INTL_LISTFORMATTER_P(ZEND_THIS); - HashTable *ht; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_ARRAY_HT(ht) - ZEND_PARSE_PARAMETERS_END(); - - uint32_t count = zend_hash_num_elements(ht); - if (count == 0) { - RETURN_EMPTY_STRING(); - } - - const UChar **items = (const UChar **)safe_emalloc(count, sizeof(const UChar *), 0); - int32_t *itemLengths = (int32_t *)safe_emalloc(count, sizeof(int32_t), 0); - uint32_t i = 0; - zval *val; - - ZEND_HASH_FOREACH_VAL(ht, val) { - zend_string *str_val, *tmp_str; - - str_val = zval_get_tmp_string(val, &tmp_str); - - // Convert PHP string to UTF-16 - UChar *ustr = NULL; - int32_t ustr_len = 0; - UErrorCode status = U_ZERO_ERROR; - - intl_convert_utf8_to_utf16(&ustr, &ustr_len, ZSTR_VAL(str_val), ZSTR_LEN(str_val), &status); - zend_tmp_string_release(tmp_str); - - if (U_FAILURE(status)) { - // We can't use goto cleanup because items and itemLengths are incompletely allocated - for (uint32_t j = 0; j < i; j++) { - efree((void *)items[j]); - } - efree(items); - efree(itemLengths); - intl_error_set(NULL, status, "Failed to convert string to UTF-16", 0); - RETURN_FALSE; - } - - items[i] = ustr; - itemLengths[i] = ustr_len; - i++; - } ZEND_HASH_FOREACH_END(); - - UErrorCode status = U_ZERO_ERROR; - int32_t resultLength; - UChar *result = NULL; - - 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); - RETVAL_FALSE; - goto cleanup; - } - - // Allocate buffer and try again - status = U_ZERO_ERROR; - result = (UChar *)safe_emalloc(resultLength + 1, sizeof(UChar), 0); - ulistfmt_format(LISTFORMATTER_OBJECT(obj), items, itemLengths, count, result, resultLength, &status); - - if (U_FAILURE(status)) { - if (result) { - efree(result); - } - intl_error_set(NULL, status, "Failed to format list", 0); - RETVAL_FALSE; - goto cleanup; - } - - // Convert result back to UTF-8 - zend_string *ret = intl_convert_utf16_to_utf8(result, resultLength, &status); - efree(result); - - if (!ret) { - intl_error_set(NULL, status, "Failed to convert result to UTF-8", 0); - RETVAL_FALSE; - } else { - RETVAL_NEW_STR(ret); - } - -cleanup: - for (i = 0; i < count; i++) { - efree((void *)items[i]); - } - efree(items); - efree(itemLengths); -} - -PHP_METHOD(IntlListFormatter, getErrorCode) -{ - ZEND_PARSE_PARAMETERS_NONE(); - - ListFormatter_object *obj = Z_INTL_LISTFORMATTER_P(ZEND_THIS); - - UErrorCode status = intl_error_get_code(LISTFORMATTER_ERROR_P(obj)); - - RETURN_LONG(status); -} - -PHP_METHOD(IntlListFormatter, getErrorMessage) -{ - ZEND_PARSE_PARAMETERS_NONE(); - - ListFormatter_object *obj = Z_INTL_LISTFORMATTER_P(ZEND_THIS); - - zend_string *message = intl_error_get_message(LISTFORMATTER_ERROR_P(obj)); - RETURN_STR(message); -} - -void listformatter_register_class(void) -{ - zend_class_entry *class_entry = register_class_IntlListFormatter(); - class_entry->create_object = listformatter_create_object; - - memcpy(&listformatter_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - listformatter_handlers.offset = XtOffsetOf(ListFormatter_object, zo); - listformatter_handlers.free_obj = listformatter_free_obj; - listformatter_handlers.clone_obj = NULL; -} diff --git a/ext/intl/listformatter/listformatter_class.cpp b/ext/intl/listformatter/listformatter_class.cpp new file mode 100644 index 0000000000000..8a7f9ffef9c2b --- /dev/null +++ b/ext/intl/listformatter/listformatter_class.cpp @@ -0,0 +1,244 @@ +/* + +----------------------------------------------------------------------+ + | 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: Bogdan Ungureanu | + +----------------------------------------------------------------------+ +*/ + +extern "C" { +#include "php.h" +#include "php_intl.h" +#include "intl_convert.h" +} +#include +#include "listformatter_class.h" +#include "listformatter_arginfo.h" + +static zend_object_handlers listformatter_handlers; + +static void listformatter_free_obj(zend_object *object) +{ + ListFormatter_object *obj = php_intl_listformatter_fetch_object(object); + + if( obj->lf_data.ulistfmt ) + ulistfmt_close( obj->lf_data.ulistfmt ); + + obj->lf_data.ulistfmt = nullptr; + intl_error_reset( &obj->lf_data.error ); + + zend_object_std_dtor(&obj->zo); +} + +static zend_object *listformatter_create_object(zend_class_entry *class_type) +{ + ListFormatter_object *obj; + obj = reinterpret_cast(zend_object_alloc(sizeof(ListFormatter_object), class_type)); + + obj->lf_data.ulistfmt = nullptr; + intl_error_reset( &obj->lf_data.error ); + + zend_object_std_init(&obj->zo, class_type); + object_properties_init(&obj->zo, class_type); + obj->zo.handlers = &listformatter_handlers; + return &obj->zo; +} + +PHP_METHOD(IntlListFormatter, __construct) +{ + ListFormatter_object *obj = Z_INTL_LISTFORMATTER_P(ZEND_THIS); + char* locale; + size_t locale_len = 0; + #if U_ICU_VERSION_MAJOR_NUM >= 67 + zend_long type = ULISTFMT_TYPE_AND; + zend_long width = ULISTFMT_WIDTH_WIDE; + #else + zend_long type = INTL_LISTFORMATTER_FALLBACK_TYPE_AND; + zend_long width = INTL_LISTFORMATTER_FALLBACK_WIDTH_WIDE; + #endif + ZEND_PARSE_PARAMETERS_START(1, 3) + Z_PARAM_STRING(locale, locale_len) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(type) + Z_PARAM_LONG(width) + ZEND_PARSE_PARAMETERS_END(); + + if(locale_len == 0) { + locale = (char *)intl_locale_get_default(); + } + + if (locale_len > INTL_MAX_LOCALE_LEN) { + zend_argument_value_error(1, "must be less than or equal to %d characters", INTL_MAX_LOCALE_LEN); + RETURN_THROWS(); + } + + if (strlen(uloc_getISO3Language(locale)) == 0) { + zend_argument_value_error(1, "\"%s\" is invalid", locale); + RETURN_THROWS(); + } + + UErrorCode status = U_ZERO_ERROR; + #if U_ICU_VERSION_MAJOR_NUM >= 67 + if (type != ULISTFMT_TYPE_AND && type != ULISTFMT_TYPE_OR && type != ULISTFMT_TYPE_UNITS) { + zend_argument_value_error(2, "must be one of IntlListFormatter::TYPE_AND, IntlListFormatter::TYPE_OR, or IntlListFormatter::TYPE_UNITS"); + RETURN_THROWS(); + } + + if (width != ULISTFMT_WIDTH_WIDE && width != ULISTFMT_WIDTH_SHORT && width != ULISTFMT_WIDTH_NARROW) { + zend_argument_value_error(3, "must be one of IntlListFormatter::WIDTH_WIDE, IntlListFormatter::WIDTH_SHORT, or IntlListFormatter::WIDTH_NARROW"); + RETURN_THROWS(); + } + + LISTFORMATTER_OBJECT(obj) = ulistfmt_openForType(locale, static_cast(type), static_cast(width), &status); + #else + if (type != INTL_LISTFORMATTER_FALLBACK_TYPE_AND) { + zend_argument_value_error(2, "contains an unsupported type. ICU 66 and below only support IntlListFormatter::TYPE_AND"); + RETURN_THROWS(); + } + + if (width != INTL_LISTFORMATTER_FALLBACK_WIDTH_WIDE) { + zend_argument_value_error(3, "contains an unsupported width. ICU 66 and below only support IntlListFormatter::WIDTH_WIDE"); + RETURN_THROWS(); + } + + LISTFORMATTER_OBJECT(obj) = ulistfmt_open(locale, &status); + #endif + + if (U_FAILURE(status)) { + intl_error_set(nullptr, status, "Constructor failed"); + zend_throw_exception(IntlException_ce_ptr, "Constructor failed", 0); + RETURN_THROWS(); + } +} + +PHP_METHOD(IntlListFormatter, format) +{ + ListFormatter_object *obj = Z_INTL_LISTFORMATTER_P(ZEND_THIS); + HashTable *ht; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ARRAY_HT(ht) + ZEND_PARSE_PARAMETERS_END(); + + uint32_t count = zend_hash_num_elements(ht); + if (count == 0) { + RETURN_EMPTY_STRING(); + } + + const UChar **items = (const UChar **)safe_emalloc(count, sizeof(const UChar *), 0); + int32_t *itemLengths = (int32_t *)safe_emalloc(count, sizeof(int32_t), 0); + uint32_t i = 0; + zval *val; + + ZEND_HASH_FOREACH_VAL(ht, val) { + zend_string *str_val, *tmp_str; + + str_val = zval_get_tmp_string(val, &tmp_str); + + // Convert PHP string to UTF-16 + UChar *ustr = nullptr; + int32_t ustr_len = 0; + UErrorCode status = U_ZERO_ERROR; + + intl_convert_utf8_to_utf16(&ustr, &ustr_len, ZSTR_VAL(str_val), ZSTR_LEN(str_val), &status); + zend_tmp_string_release(tmp_str); + + if (U_FAILURE(status)) { + // We can't use goto cleanup because items and itemLengths are incompletely allocated + for (uint32_t j = 0; j < i; j++) { + efree((void *)items[j]); + } + efree(items); + efree(itemLengths); + intl_error_set(nullptr, status, "Failed to convert string to UTF-16"); + RETURN_FALSE; + } + + items[i] = ustr; + itemLengths[i] = ustr_len; + i++; + } ZEND_HASH_FOREACH_END(); + + UErrorCode status = U_ZERO_ERROR; + int32_t resultLength; + UChar *result = nullptr; + zend_string *ret = nullptr; + + resultLength = ulistfmt_format(LISTFORMATTER_OBJECT(obj), items, itemLengths, count, nullptr, 0, &status); + + if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR) { + intl_error_set(nullptr, status, "Failed to format list"); + RETVAL_FALSE; + goto cleanup; + } + + // Allocate buffer and try again + status = U_ZERO_ERROR; + result = (UChar *)safe_emalloc(resultLength + 1, sizeof(UChar), 0); + ulistfmt_format(LISTFORMATTER_OBJECT(obj), items, itemLengths, count, result, resultLength, &status); + + if (U_FAILURE(status)) { + if (result) { + efree(result); + } + intl_error_set(nullptr, status, "Failed to format list"); + RETVAL_FALSE; + goto cleanup; + } + + // Convert result back to UTF-8 + ret = intl_convert_utf16_to_utf8(result, resultLength, &status); + efree(result); + + if (!ret) { + intl_error_set(nullptr, status, "Failed to convert result to UTF-8"); + RETVAL_FALSE; + } else { + RETVAL_NEW_STR(ret); + } + +cleanup: + for (i = 0; i < count; i++) { + efree((void *)items[i]); + } + efree(items); + efree(itemLengths); +} + +PHP_METHOD(IntlListFormatter, getErrorCode) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + ListFormatter_object *obj = Z_INTL_LISTFORMATTER_P(ZEND_THIS); + + UErrorCode status = intl_error_get_code(LISTFORMATTER_ERROR_P(obj)); + + RETURN_LONG(status); +} + +PHP_METHOD(IntlListFormatter, getErrorMessage) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + ListFormatter_object *obj = Z_INTL_LISTFORMATTER_P(ZEND_THIS); + + zend_string *message = intl_error_get_message(LISTFORMATTER_ERROR_P(obj)); + RETURN_STR(message); +} + +void listformatter_register_class(void) +{ + zend_class_entry *class_entry = register_class_IntlListFormatter(); + class_entry->create_object = listformatter_create_object; + + memcpy(&listformatter_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + listformatter_handlers.offset = XtOffsetOf(ListFormatter_object, zo); + listformatter_handlers.free_obj = listformatter_free_obj; + listformatter_handlers.clone_obj = nullptr; +} diff --git a/ext/intl/listformatter/listformatter_class.h b/ext/intl/listformatter/listformatter_class.h index 8fe8137796bfb..8edbf8d63e2d0 100644 --- a/ext/intl/listformatter/listformatter_class.h +++ b/ext/intl/listformatter/listformatter_class.h @@ -46,8 +46,14 @@ static inline ListFormatter_object *php_intl_listformatter_fetch_object(zend_obj #define LISTFORMATTER_OBJECT(lfo) (lfo)->lf_data.ulistfmt +#ifdef __cplusplus +extern "C" { +#endif void listformatter_register_class( void ); extern zend_class_entry *ListFormatter_ce_ptr; +#ifdef __cplusplus +} +#endif #define INTL_LISTFORMATTER_FALLBACK_TYPE_AND 0 #define INTL_LISTFORMATTER_FALLBACK_WIDTH_WIDE 0 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_arginfo.h b/ext/intl/locale/locale_arginfo.h index 79a16452e2975..e6fde7981a98c 100644 --- a/ext/intl/locale/locale_arginfo.h +++ b/ext/intl/locale/locale_arginfo.h @@ -128,70 +128,70 @@ static zend_class_entry *register_class_Locale(void) zval const_ACTUAL_LOCALE_value; ZVAL_LONG(&const_ACTUAL_LOCALE_value, ULOC_ACTUAL_LOCALE); - zend_string *const_ACTUAL_LOCALE_name = zend_string_init_interned("ACTUAL_LOCALE", sizeof("ACTUAL_LOCALE") - 1, 1); + zend_string *const_ACTUAL_LOCALE_name = zend_string_init_interned("ACTUAL_LOCALE", sizeof("ACTUAL_LOCALE") - 1, true); zend_declare_typed_class_constant(class_entry, const_ACTUAL_LOCALE_name, &const_ACTUAL_LOCALE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ACTUAL_LOCALE_name); + zend_string_release_ex(const_ACTUAL_LOCALE_name, true); zval const_VALID_LOCALE_value; ZVAL_LONG(&const_VALID_LOCALE_value, ULOC_VALID_LOCALE); - zend_string *const_VALID_LOCALE_name = zend_string_init_interned("VALID_LOCALE", sizeof("VALID_LOCALE") - 1, 1); + zend_string *const_VALID_LOCALE_name = zend_string_init_interned("VALID_LOCALE", sizeof("VALID_LOCALE") - 1, true); zend_declare_typed_class_constant(class_entry, const_VALID_LOCALE_name, &const_VALID_LOCALE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_VALID_LOCALE_name); + zend_string_release_ex(const_VALID_LOCALE_name, true); zval const_DEFAULT_LOCALE_value; ZVAL_NULL(&const_DEFAULT_LOCALE_value); - zend_string *const_DEFAULT_LOCALE_name = zend_string_init_interned("DEFAULT_LOCALE", sizeof("DEFAULT_LOCALE") - 1, 1); + zend_string *const_DEFAULT_LOCALE_name = zend_string_init_interned("DEFAULT_LOCALE", sizeof("DEFAULT_LOCALE") - 1, true); zend_declare_typed_class_constant(class_entry, const_DEFAULT_LOCALE_name, &const_DEFAULT_LOCALE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_NULL)); - zend_string_release(const_DEFAULT_LOCALE_name); + zend_string_release_ex(const_DEFAULT_LOCALE_name, true); zval const_LANG_TAG_value; zend_string *const_LANG_TAG_value_str = zend_string_init(LOC_LANG_TAG, strlen(LOC_LANG_TAG), 1); ZVAL_STR(&const_LANG_TAG_value, const_LANG_TAG_value_str); - zend_string *const_LANG_TAG_name = zend_string_init_interned("LANG_TAG", sizeof("LANG_TAG") - 1, 1); + zend_string *const_LANG_TAG_name = zend_string_init_interned("LANG_TAG", sizeof("LANG_TAG") - 1, true); zend_declare_typed_class_constant(class_entry, const_LANG_TAG_name, &const_LANG_TAG_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(const_LANG_TAG_name); + zend_string_release_ex(const_LANG_TAG_name, true); zval const_EXTLANG_TAG_value; zend_string *const_EXTLANG_TAG_value_str = zend_string_init(LOC_EXTLANG_TAG, strlen(LOC_EXTLANG_TAG), 1); ZVAL_STR(&const_EXTLANG_TAG_value, const_EXTLANG_TAG_value_str); - zend_string *const_EXTLANG_TAG_name = zend_string_init_interned("EXTLANG_TAG", sizeof("EXTLANG_TAG") - 1, 1); + zend_string *const_EXTLANG_TAG_name = zend_string_init_interned("EXTLANG_TAG", sizeof("EXTLANG_TAG") - 1, true); zend_declare_typed_class_constant(class_entry, const_EXTLANG_TAG_name, &const_EXTLANG_TAG_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(const_EXTLANG_TAG_name); + zend_string_release_ex(const_EXTLANG_TAG_name, true); zval const_SCRIPT_TAG_value; zend_string *const_SCRIPT_TAG_value_str = zend_string_init(LOC_SCRIPT_TAG, strlen(LOC_SCRIPT_TAG), 1); ZVAL_STR(&const_SCRIPT_TAG_value, const_SCRIPT_TAG_value_str); - zend_string *const_SCRIPT_TAG_name = zend_string_init_interned("SCRIPT_TAG", sizeof("SCRIPT_TAG") - 1, 1); + zend_string *const_SCRIPT_TAG_name = zend_string_init_interned("SCRIPT_TAG", sizeof("SCRIPT_TAG") - 1, true); zend_declare_typed_class_constant(class_entry, const_SCRIPT_TAG_name, &const_SCRIPT_TAG_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(const_SCRIPT_TAG_name); + zend_string_release_ex(const_SCRIPT_TAG_name, true); zval const_REGION_TAG_value; zend_string *const_REGION_TAG_value_str = zend_string_init(LOC_REGION_TAG, strlen(LOC_REGION_TAG), 1); ZVAL_STR(&const_REGION_TAG_value, const_REGION_TAG_value_str); - zend_string *const_REGION_TAG_name = zend_string_init_interned("REGION_TAG", sizeof("REGION_TAG") - 1, 1); + zend_string *const_REGION_TAG_name = zend_string_init_interned("REGION_TAG", sizeof("REGION_TAG") - 1, true); zend_declare_typed_class_constant(class_entry, const_REGION_TAG_name, &const_REGION_TAG_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(const_REGION_TAG_name); + zend_string_release_ex(const_REGION_TAG_name, true); zval const_VARIANT_TAG_value; zend_string *const_VARIANT_TAG_value_str = zend_string_init(LOC_VARIANT_TAG, strlen(LOC_VARIANT_TAG), 1); ZVAL_STR(&const_VARIANT_TAG_value, const_VARIANT_TAG_value_str); - zend_string *const_VARIANT_TAG_name = zend_string_init_interned("VARIANT_TAG", sizeof("VARIANT_TAG") - 1, 1); + zend_string *const_VARIANT_TAG_name = zend_string_init_interned("VARIANT_TAG", sizeof("VARIANT_TAG") - 1, true); zend_declare_typed_class_constant(class_entry, const_VARIANT_TAG_name, &const_VARIANT_TAG_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(const_VARIANT_TAG_name); + zend_string_release_ex(const_VARIANT_TAG_name, true); zval const_GRANDFATHERED_LANG_TAG_value; zend_string *const_GRANDFATHERED_LANG_TAG_value_str = zend_string_init(LOC_GRANDFATHERED_LANG_TAG, strlen(LOC_GRANDFATHERED_LANG_TAG), 1); ZVAL_STR(&const_GRANDFATHERED_LANG_TAG_value, const_GRANDFATHERED_LANG_TAG_value_str); - zend_string *const_GRANDFATHERED_LANG_TAG_name = zend_string_init_interned("GRANDFATHERED_LANG_TAG", sizeof("GRANDFATHERED_LANG_TAG") - 1, 1); + zend_string *const_GRANDFATHERED_LANG_TAG_name = zend_string_init_interned("GRANDFATHERED_LANG_TAG", sizeof("GRANDFATHERED_LANG_TAG") - 1, true); zend_declare_typed_class_constant(class_entry, const_GRANDFATHERED_LANG_TAG_name, &const_GRANDFATHERED_LANG_TAG_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(const_GRANDFATHERED_LANG_TAG_name); + zend_string_release_ex(const_GRANDFATHERED_LANG_TAG_name, true); zval const_PRIVATE_TAG_value; zend_string *const_PRIVATE_TAG_value_str = zend_string_init(LOC_PRIVATE_TAG, strlen(LOC_PRIVATE_TAG), 1); ZVAL_STR(&const_PRIVATE_TAG_value, const_PRIVATE_TAG_value_str); - zend_string *const_PRIVATE_TAG_name = zend_string_init_interned("PRIVATE_TAG", sizeof("PRIVATE_TAG") - 1, 1); + zend_string *const_PRIVATE_TAG_name = zend_string_init_interned("PRIVATE_TAG", sizeof("PRIVATE_TAG") - 1, true); zend_declare_typed_class_constant(class_entry, const_PRIVATE_TAG_name, &const_PRIVATE_TAG_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(const_PRIVATE_TAG_name); + zend_string_release_ex(const_PRIVATE_TAG_name, true); return class_entry; } diff --git a/ext/intl/locale/locale_class.c b/ext/intl/locale/locale_class.c deleted file mode 100644 index cbde2a5fb0701..0000000000000 --- a/ext/intl/locale/locale_class.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Kirti Velankar | - +----------------------------------------------------------------------+ -*/ - -#include -#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; - -/* - * 'Locale' class registration structures & functions - */ - -/* {{{ locale_register_Locale_class - * Initialize 'Locale' class - */ -void locale_register_Locale_class( void ) -{ - /* Create and register 'Locale' class. */ - Locale_ce_ptr = register_class_Locale(); - Locale_ce_ptr->create_object = NULL; -} -/* }}} */ diff --git a/ext/intl/locale/locale_class.cpp b/ext/intl/locale/locale_class.cpp new file mode 100644 index 0000000000000..75fde45d53d60 --- /dev/null +++ b/ext/intl/locale/locale_class.cpp @@ -0,0 +1,39 @@ +/* + +----------------------------------------------------------------------+ + | 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: Kirti Velankar | + +----------------------------------------------------------------------+ +*/ + +#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; + +/* + * 'Locale' class registration structures & functions + */ + +/* {{{ locale_register_Locale_class + * Initialize 'Locale' class + */ +U_CFUNC void locale_register_Locale_class( void ) +{ + /* Create and register 'Locale' class. */ + Locale_ce_ptr = register_class_Locale(); + Locale_ce_ptr->create_object = NULL; +} +/* }}} */ 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.c deleted file mode 100644 index 8b63007c5d820..0000000000000 --- a/ext/intl/locale/locale_methods.c +++ /dev/null @@ -1,1688 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Kirti Velankar | - +----------------------------------------------------------------------+ -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include "php_intl.h" -#include "locale.h" -#include "locale_class.h" -#include "intl_convert.h" -#include "intl_data.h" - -#include -#include -#include -#include "main/php_ini.h" -#include "zend_smart_str.h" - -ZEND_EXTERN_MODULE_GLOBALS( intl ) - -/* Sizes required for the strings "variant15" , "extlang11", "private12" etc. */ -#define SEPARATOR "_" -#define SEPARATOR1 "-" -#define DELIMITER "-_" -#define EXTLANG_PREFIX "a" -#define PRIVATE_PREFIX "x" -#define DISP_NAME "name" - -#define MAX_NO_VARIANT 15 -#define MAX_NO_EXTLANG 3 -#define MAX_NO_PRIVATE 15 -#define MAX_NO_LOOKUP_LANG_TAG 100 - -#define LOC_NOT_FOUND 1 - -/* Sizes required for the strings "variant15" , "extlang3", "private12" etc. */ -#define VARIANT_KEYNAME_LEN 11 -#define EXTLANG_KEYNAME_LEN 10 -#define PRIVATE_KEYNAME_LEN 11 - -/* Based on the IANA language subtag registry (File-Date: 2021-08-06) - * https://www.iana.org/assignments/language-subtag-registry - * - * This list includes all grandfathered tags, as well as redundant - * tags that have a Preferred-Value. - */ -static const char * const LOC_GRANDFATHERED[] = { - "art-lojban", - "cel-gaulish", - "en-GB-oed", - "i-ami", - "i-bnn", - "i-default", - "i-enochian", - "i-hak", - "i-klingon", - "i-lux", - "i-mingo", - "i-navajo", - "i-pwn", - "i-tao", - "i-tay", - "i-tsu", - "no-bok", - "no-nyn", - "sgn-BE-FR", - "sgn-BE-NL", - "sgn-BR", - "sgn-CH-DE", - "sgn-CO", - "sgn-DE", - "sgn-DK", - "sgn-ES", - "sgn-FR", - "sgn-GB", - "sgn-GR", - "sgn-IE", - "sgn-IT", - "sgn-JP", - "sgn-MX", - "sgn-NI", - "sgn-NL", - "sgn-NO", - "sgn-PT", - "sgn-SE", - "sgn-US", - "sgn-ZA", - "zh-cmn", - "zh-cmn-Hans", - "zh-cmn-Hant", - "zh-gan", - "zh-guoyu", - "zh-hakka", - "zh-min", - "zh-min-nan", - "zh-wuu", - "zh-xiang", - NULL -}; - -/* Based on the IANA language subtag registry (File-Date: 2021-08-06) - * - * This array lists the preferred values for the grandfathered and redundant - * tags listed in LOC_GRANDFATHERED. This is in sync with the array - * LOC_GRANDFATHERED, i.e., the offsets of the grandfathered tags match the - * offsets of the preferred value. If a value in LOC_PREFERRED_GRANDFATHERED is - * NULL, then the matching offset in LOC_GRANDFATHERED has no preferred value. - */ -static const char * const LOC_PREFERRED_GRANDFATHERED[] = { - "jbo", - NULL, - "en-GB-oxendict", - "ami", - "bnn", - NULL, - NULL, - "hak", - "tlh", - "lb", - NULL, - "nv", - "pwn", - "tao", - "tay", - "tsu", - "nb", - "nn", - "sfb", - "vgt", - "bzs", - "sgg", - "csn", - "gsg", - "dsl", - "ssp", - "fsl", - "bfi", - "gss", - "isg", - "ise", - "jsl", - "mfs", - "ncs", - "dse", - "nsl", - "psr", - "swl", - "ase", - "sfs", - "cmn", - "cmn-Hans", - "cmn-Hant", - "gan", - "cmn", - "hak", - NULL, - "nan", - "wuu", - "hsn", - NULL -}; - -/* returns true if a is an ID separator, false otherwise */ -#define isIDSeparator(a) (a == '_' || a == '-') -#define isKeywordSeparator(a) (a == '@' ) -#define isEndOfTag(a) (a == '\0' ) - -#define isPrefixLetter(a) ((a=='x')||(a=='X')||(a=='i')||(a=='I')) - -/*returns true if one of the special prefixes is here (s=string) - 'x-' or 'i-' */ -#define isIDPrefix(s) (isPrefixLetter(s[0])&&isIDSeparator(s[1])) -#define isKeywordPrefix(s) ( isKeywordSeparator(s[0]) ) - -/* Dot terminates it because of POSIX form where dot precedes the codepage - * except for variant */ -#define isTerminator(a) ((a==0)||(a=='.')||(a=='@')) - -/* {{{ return the offset of 'key' in the array 'list'. - * returns -1 if not present */ -static int16_t findOffset(const char* const* list, const char* key) -{ - const char* const* anchor = list; - while (*list != NULL) { - if (strcasecmp(key, *list) == 0) { - return (int16_t)(list - anchor); - } - list++; - } - - return -1; - -} -/*}}}*/ - -static char* getPreferredTag(const char* gf_tag) -{ - char* result = NULL; - zend_off_t grOffset = 0; - - grOffset = findOffset( LOC_GRANDFATHERED ,gf_tag); - if(grOffset < 0) { - return NULL; - } - if( LOC_PREFERRED_GRANDFATHERED[grOffset] != NULL ){ - /* return preferred tag */ - result = estrdup( LOC_PREFERRED_GRANDFATHERED[grOffset] ); - } else { - /* Return correct grandfathered language tag */ - result = estrdup( LOC_GRANDFATHERED[grOffset] ); - } - return result; -} - -/* {{{ -* returns the position of next token for lookup -* or -1 if no token -* strtokr equivalent search for token in reverse direction -*/ -static zend_off_t getStrrtokenPos(char* str, zend_off_t savedPos) -{ - zend_off_t result =-1; - zend_off_t i; - - for(i=savedPos-1; i>=0; i--) { - if(isIDSeparator(*(str+i)) || isKeywordSeparator(*(str+i))){ - /* delimiter found; check for singleton */ - if(i>=2 && isIDSeparator(*(str+i-2)) ){ - /* a singleton; so send the position of token before the singleton */ - result = i-2; - } else { - result = i; - } - break; - } - } - if(result < 1){ - /* Just in case inavlid locale e.g. '-x-xyz' or '-sl_Latn' */ - result =-1; - } - return result; -} -/* }}} */ - -/* {{{ -* returns the position of a singleton if present -* returns -1 if no singleton -* strtok equivalent search for singleton -*/ -static zend_off_t getSingletonPos(const char* str) -{ - zend_off_t result =-1; - size_t len = 0; - - if( str && ((len=strlen(str))>0) ){ - zend_off_t i = 0; - for( i=0; (size_t)i < len ; i++){ - if( isIDSeparator(*(str+i)) ){ - if( i==1){ - /* string is of the form x-avy or a-prv1 */ - result =0; - break; - } else { - /* delimiter found; check for singleton */ - if( isIDSeparator(*(str+i+2)) ){ - /* a singleton; so send the position of separator before singleton */ - result = i+1; - break; - } - } - } - }/* end of for */ - - } - return result; -} -/* }}} */ - -/* {{{ Get default locale */ -/* }}} */ -/* {{{ Get default locale */ -PHP_NAMED_FUNCTION(zif_locale_get_default) -{ - ZEND_PARSE_PARAMETERS_NONE(); - - RETURN_STRING( intl_locale_get_default( ) ); -} - -/* }}} */ - -/* {{{ Set default locale */ -/* }}} */ -/* {{{ Set default locale */ -PHP_NAMED_FUNCTION(zif_locale_set_default) -{ - zend_string* locale_name; - zend_string *ini_name; - char *default_locale = NULL; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_PATH_STR(locale_name) - ZEND_PARSE_PARAMETERS_END(); - - if (ZSTR_LEN(locale_name) == 0) { - default_locale = (char *)uloc_getDefault(); - locale_name = zend_string_init(default_locale, strlen(default_locale), 0); - } - - ini_name = zend_string_init(LOCALE_INI_NAME, sizeof(LOCALE_INI_NAME) - 1, 0); - zend_alter_ini_entry(ini_name, locale_name, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); - zend_string_release_ex(ini_name, 0); - if (default_locale != NULL) { - zend_string_release_ex(locale_name, 0); - } - - RETURN_TRUE; -} -/* }}} */ - -/* {{{ -* Gets the value from ICU -* common code shared by get_primary_language,get_script or get_region or get_variant -* result = 0 if error, 1 if successful , -1 if no value -*/ -static zend_string* get_icu_value_internal( const char* loc_name , char* tag_name, int* result , int fromParseLocale) -{ - zend_string* tag_value = NULL; - int32_t tag_value_len = 512; - - char* mod_loc_name = NULL; - - int32_t buflen = 512; - UErrorCode status = U_ZERO_ERROR; - - if (strlen(loc_name) > INTL_MAX_LOCALE_LEN) { - return NULL; - } - - if( strcmp(tag_name, LOC_CANONICALIZE_TAG) != 0 ){ - /* Handle grandfathered languages */ - zend_off_t grOffset = findOffset( LOC_GRANDFATHERED , loc_name ); - if( grOffset >= 0 ){ - if( strcmp(tag_name , LOC_LANG_TAG)==0 ){ - return zend_string_init(loc_name, strlen(loc_name), 0); - } else { - /* Since Grandfathered , no value , do nothing , retutn NULL */ - return NULL; - } - } - - if( fromParseLocale==1 ){ - zend_off_t singletonPos = 0; - - /* Handle singletons */ - if( strcmp(tag_name , LOC_LANG_TAG)==0 ){ - if( strlen(loc_name)>1 && (isIDPrefix(loc_name) == 1) ){ - return zend_string_init(loc_name, strlen(loc_name), 0); - } - } - - singletonPos = getSingletonPos( loc_name ); - if( singletonPos == 0){ - /* singleton at start of script, region , variant etc. - * or invalid singleton at start of language */ - return NULL; - } else if( singletonPos > 0 ){ - /* singleton at some position except at start - * strip off the singleton and rest of the loc_name */ - mod_loc_name = estrndup ( loc_name , singletonPos-1); - } - } /* end of if fromParse */ - - } /* end of if != LOC_CANONICAL_TAG */ - - if( mod_loc_name == NULL){ - mod_loc_name = estrdup(loc_name ); - } - - /* Proceed to ICU */ - do{ - if (tag_value) { - tag_value = zend_string_realloc( tag_value , buflen, 0); - } else { - tag_value = zend_string_alloc( buflen, 0); - } - tag_value_len = buflen; - - if( strcmp(tag_name , LOC_SCRIPT_TAG)==0 ){ - buflen = uloc_getScript ( mod_loc_name , tag_value->val , tag_value_len , &status); - } - if( strcmp(tag_name , LOC_LANG_TAG )==0 ){ - buflen = uloc_getLanguage ( mod_loc_name , tag_value->val , tag_value_len , &status); - } - if( strcmp(tag_name , LOC_REGION_TAG)==0 ){ - buflen = uloc_getCountry ( mod_loc_name , tag_value->val , tag_value_len , &status); - } - if( strcmp(tag_name , LOC_VARIANT_TAG)==0 ){ - buflen = uloc_getVariant ( mod_loc_name , tag_value->val , tag_value_len , &status); - } - if( strcmp(tag_name , LOC_CANONICALIZE_TAG)==0 ){ - buflen = uloc_canonicalize ( mod_loc_name , tag_value->val , tag_value_len , &status); - } - - if( U_FAILURE( status ) ) { - if( status == U_BUFFER_OVERFLOW_ERROR ) { - status = U_ZERO_ERROR; - buflen++; /* add space for \0 */ - continue; - } - - /* Error in retrieving data */ - *result = 0; - if( tag_value ){ - zend_string_release_ex( tag_value, 0 ); - } - if( mod_loc_name ){ - efree( mod_loc_name); - } - return NULL; - } - } while( buflen > tag_value_len ); - - if( buflen ==0 ){ - /* No value found */ - *result = -1; - if( tag_value ){ - zend_string_release_ex( tag_value, 0 ); - } - if( mod_loc_name ){ - efree( mod_loc_name); - } - return NULL; - } else { - *result = 1; - } - - if( mod_loc_name ){ - efree( mod_loc_name); - } - - tag_value->len = strlen(tag_value->val); - return tag_value; -} -/* }}} */ - -/* {{{ -* Gets the value from ICU , called when PHP userspace function is called -* common code shared by get_primary_language,get_script or get_region or get_variant -*/ -static void get_icu_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAMETERS) -{ - - char* loc_name = NULL; - size_t loc_name_len = 0; - - zend_string* tag_value = NULL; - char* empty_result = ""; - - int result = 0; - char* msg = NULL; - - UErrorCode status = U_ZERO_ERROR; - - intl_error_reset( NULL ); - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_PATH(loc_name, loc_name_len) - ZEND_PARSE_PARAMETERS_END(); - - if(loc_name_len == 0) { - loc_name = (char *)intl_locale_get_default(); - loc_name_len = strlen(loc_name); - } - - INTL_CHECK_LOCALE_LEN(loc_name_len); - - /* Call ICU get */ - tag_value = get_icu_value_internal( loc_name , tag_name , &result ,0); - - /* No value found */ - if( result == -1 ) { - if( tag_value){ - zend_string_release_ex( tag_value, 0 ); - } - RETURN_STRING( empty_result); - } - - /* value found */ - if( tag_value){ - RETVAL_STR( tag_value ); - return; - } - - /* 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 ); - efree(msg); - RETURN_NULL(); - } - -} -/* }}} */ - -/* {{{ gets the script for the $locale */ -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 ) -{ - 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 ) -{ - get_icu_value_src_php( LOC_LANG_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); -} -/* }}} */ - - -/* {{{ - * common code shared by display_xyz functions to get the value from ICU - }}} */ -static void get_icu_disp_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAMETERS) -{ - char* loc_name = NULL; - size_t loc_name_len = 0; - - char* disp_loc_name = NULL; - size_t disp_loc_name_len = 0; - int free_loc_name = 0; - - UChar* disp_name = NULL; - int32_t disp_name_len = 0; - - char* mod_loc_name = NULL; - - int32_t buflen = 512; - UErrorCode status = U_ZERO_ERROR; - - zend_string* u8str; - - char* msg = NULL; - - intl_error_reset( NULL ); - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_PATH(loc_name, loc_name_len) - Z_PARAM_OPTIONAL - Z_PARAM_PATH_OR_NULL(disp_loc_name, disp_loc_name_len) - ZEND_PARSE_PARAMETERS_END(); - - 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); - RETURN_FALSE; - } - - if(loc_name_len == 0) { - loc_name = (char *)intl_locale_get_default(); - } - - if( strcmp(tag_name, DISP_NAME) != 0 ){ - /* Handle grandfathered languages */ - int grOffset = findOffset( LOC_GRANDFATHERED , loc_name ); - if( grOffset >= 0 ){ - if( strcmp(tag_name , LOC_LANG_TAG)==0 ){ - mod_loc_name = getPreferredTag( loc_name ); - } else { - /* Since Grandfathered, no value, do nothing, return NULL */ - RETURN_FALSE; - } - } - } /* end of if != LOC_CANONICAL_TAG */ - - if( mod_loc_name==NULL ){ - mod_loc_name = estrdup( loc_name ); - } - - /* Check if disp_loc_name passed , if not use default locale */ - if( !disp_loc_name){ - disp_loc_name = estrdup(intl_locale_get_default()); - free_loc_name = 1; - } - - /* Get the disp_value for the given locale */ - do{ - disp_name = erealloc( disp_name , buflen * sizeof(UChar) ); - disp_name_len = buflen; - - if( strcmp(tag_name , LOC_LANG_TAG)==0 ){ - buflen = uloc_getDisplayLanguage ( mod_loc_name , disp_loc_name , disp_name , disp_name_len , &status); - } else if( strcmp(tag_name , LOC_SCRIPT_TAG)==0 ){ - buflen = uloc_getDisplayScript ( mod_loc_name , disp_loc_name , disp_name , disp_name_len , &status); - } else if( strcmp(tag_name , LOC_REGION_TAG)==0 ){ - buflen = uloc_getDisplayCountry ( mod_loc_name , disp_loc_name , disp_name , disp_name_len , &status); - } else if( strcmp(tag_name , LOC_VARIANT_TAG)==0 ){ - buflen = uloc_getDisplayVariant ( mod_loc_name , disp_loc_name , disp_name , disp_name_len , &status); - } else if( strcmp(tag_name , DISP_NAME)==0 ){ - buflen = uloc_getDisplayName ( mod_loc_name , disp_loc_name , disp_name , disp_name_len , &status); - } - - /* U_STRING_NOT_TERMINATED_WARNING is admissible here; don't look for it */ - if( U_FAILURE( status ) ) - { - if( status == U_BUFFER_OVERFLOW_ERROR ) - { - status = U_ZERO_ERROR; - continue; - } - - spprintf(&msg, 0, "locale_get_display_%s : unable to get locale %s", tag_name , tag_name ); - intl_error_set( NULL, status, msg , 1 ); - efree(msg); - if( disp_name){ - efree( disp_name ); - } - if( mod_loc_name){ - efree( mod_loc_name ); - } - if (free_loc_name) { - efree((void *)disp_loc_name); - disp_loc_name = NULL; - } - RETURN_FALSE; - } - } while( buflen > disp_name_len ); - - if( mod_loc_name){ - efree( mod_loc_name ); - } - if (free_loc_name) { - efree((void *)disp_loc_name); - disp_loc_name = NULL; - } - /* Convert display locale name from UTF-16 to UTF-8. */ - u8str = intl_convert_utf16_to_utf8(disp_name, buflen, &status ); - 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 ); - efree(msg); - RETURN_FALSE; - } - - RETVAL_NEW_STR( u8str ); -} -/* }}} */ - -/* {{{ gets the name for the $locale in $in_locale or default_locale */ -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) -{ - 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) -{ - 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) -{ - get_icu_disp_value_src_php( LOC_REGION_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); -} -/* }}} */ - -/* {{{ -* proto static string Locale::getDisplayVariant($locale, $in_locale = null) -* gets the variant for the $locale in $in_locale or default_locale - }}} */ -/* {{{ -* 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) -{ - get_icu_disp_value_src_php( LOC_VARIANT_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); -} -/* }}} */ - - /* {{{ return an associative array containing keyword-value - * pairs for this locale. The keys are keys to the array (doh!) - * }}}*/ - /* {{{ return an associative array containing keyword-value - * pairs for this locale. The keys are keys to the array (doh!) - */ -PHP_FUNCTION( locale_get_keywords ) -{ - UEnumeration* e = NULL; - UErrorCode status = U_ZERO_ERROR; - - const char* kw_key = NULL; - int32_t kw_key_len = 0; - - char* loc_name = NULL; - size_t loc_name_len = 0; - - intl_error_reset( NULL ); - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_PATH(loc_name, loc_name_len) - ZEND_PARSE_PARAMETERS_END(); - - INTL_CHECK_LOCALE_LEN(strlen(loc_name)); - - if(loc_name_len == 0) { - loc_name = (char *)intl_locale_get_default(); - } - - /* Get the keywords */ - e = uloc_openKeywords( loc_name, &status ); - if( e != NULL ) { - /* - ICU expects the buffer to be allocated before calling the function - and so the buffer size has been explicitly specified - ICU uloc.h #define ULOC_KEYWORD_AND_VALUES_CAPACITY 100 - hence the kw_value buffer size is 100 - */ - - /* Traverse it, filling the return array. */ - array_init( return_value ); - - while( ( kw_key = uenum_next( e, &kw_key_len, &status ) ) != NULL ){ - int32_t kw_value_len = 100; - zend_string *kw_value_str = zend_string_alloc(kw_value_len, 0); - - /* Get the keyword value for each keyword */ - kw_value_len=uloc_getKeywordValue( loc_name, kw_key, ZSTR_VAL(kw_value_str), kw_value_len, &status ); - if (status == U_BUFFER_OVERFLOW_ERROR) { - status = U_ZERO_ERROR; - kw_value_str = zend_string_extend(kw_value_str, kw_value_len, 0); - kw_value_len=uloc_getKeywordValue( loc_name,kw_key, ZSTR_VAL(kw_value_str), kw_value_len+1, &status ); - } else if(!U_FAILURE(status)) { - 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 ); - if( kw_value_str){ - zend_string_efree( kw_value_str ); - } - zend_array_destroy(Z_ARR_P(return_value)); - RETURN_FALSE; - } - - add_assoc_str( return_value, (char *)kw_key, kw_value_str); - } /* end of while */ - - } /* end of if e!=NULL */ - - uenum_close( e ); -} -/* }}} */ - - /* {{{ @return string the canonicalized locale - * }}} */ - /* {{{ @param string $locale The locale string to canonicalize */ -PHP_FUNCTION(locale_canonicalize) -{ - get_icu_value_src_php( LOC_CANONICALIZE_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); -} -/* }}} */ - -/* {{{ append_key_value -* Internal function which is called from locale_compose -* gets the value for the key_name and appends to the loc_name -* returns 1 if successful , -1 if not found , -* 0 if array element is not a string , -2 if buffer-overflow -*/ -static int append_key_value(smart_str* loc_name, HashTable* hash_arr, char* key_name) -{ - zval *ele_value; - - if ((ele_value = zend_hash_str_find_deref(hash_arr , key_name, strlen(key_name))) != NULL ) { - if(Z_TYPE_P(ele_value)!= IS_STRING ){ - /* element value is not a string */ - return FAILURE; - } - if(strcmp(key_name, LOC_LANG_TAG) != 0 && - strcmp(key_name, LOC_GRANDFATHERED_LANG_TAG)!=0 ) { - /* not lang or grandfathered tag */ - smart_str_appendl(loc_name, SEPARATOR , sizeof(SEPARATOR)-1); - } - smart_str_appendl(loc_name, Z_STRVAL_P(ele_value) , Z_STRLEN_P(ele_value)); - return SUCCESS; - } - - return LOC_NOT_FOUND; -} -/* }}} */ - -/* {{{ append_prefix , appends the prefix needed -* e.g. private adds 'x' -*/ -static void add_prefix(smart_str* loc_name, char* key_name) -{ - if( strncmp(key_name , LOC_PRIVATE_TAG , 7) == 0 ){ - smart_str_appendl(loc_name, SEPARATOR , sizeof(SEPARATOR)-1); - smart_str_appendl(loc_name, PRIVATE_PREFIX , sizeof(PRIVATE_PREFIX)-1); - } -} -/* }}} */ - -/* {{{ append_multiple_key_values -* Internal function which is called from locale_compose -* gets the multiple values for the key_name and appends to the loc_name -* used for 'variant','extlang','private' -* returns 1 if successful , -1 if not found , -* 0 if array element is not a string , -2 if buffer-overflow -*/ -static int append_multiple_key_values(smart_str* loc_name, HashTable* hash_arr, char* key_name) -{ - zval *ele_value; - int isFirstSubtag = 0; - - /* Variant/ Extlang/Private etc. */ - if ((ele_value = zend_hash_str_find_deref( hash_arr , key_name , strlen(key_name))) != NULL) { - if( Z_TYPE_P(ele_value) == IS_STRING ){ - add_prefix( loc_name , key_name); - - smart_str_appendl(loc_name, SEPARATOR , sizeof(SEPARATOR)-1); - smart_str_appendl(loc_name, Z_STRVAL_P(ele_value) , Z_STRLEN_P(ele_value)); - return SUCCESS; - } else if(Z_TYPE_P(ele_value) == IS_ARRAY ) { - HashTable *arr = Z_ARRVAL_P(ele_value); - zval *data; - - ZEND_HASH_FOREACH_VAL(arr, data) { - ZVAL_DEREF(data); - if(Z_TYPE_P(data) != IS_STRING) { - return FAILURE; - } - if (isFirstSubtag++ == 0){ - add_prefix(loc_name , key_name); - } - smart_str_appendl(loc_name, SEPARATOR , sizeof(SEPARATOR)-1); - smart_str_appendl(loc_name, Z_STRVAL_P(data) , Z_STRLEN_P(data)); - } ZEND_HASH_FOREACH_END(); - return SUCCESS; - } else { - return FAILURE; - } - } else { - char cur_key_name[31]; - int max_value = 0, i; - /* Decide the max_value: the max. no. of elements allowed */ - if( strcmp(key_name , LOC_VARIANT_TAG) ==0 ){ - max_value = MAX_NO_VARIANT; - } - if( strcmp(key_name , LOC_EXTLANG_TAG) ==0 ){ - max_value = MAX_NO_EXTLANG; - } - if( strcmp(key_name , LOC_PRIVATE_TAG) ==0 ){ - max_value = MAX_NO_PRIVATE; - } - - /* Multiple variant values as variant0, variant1 ,variant2 */ - isFirstSubtag = 0; - for( i=0 ; i< max_value; i++ ){ - snprintf( cur_key_name , 30, "%s%d", key_name , i); - if ((ele_value = zend_hash_str_find_deref( hash_arr , cur_key_name , strlen(cur_key_name))) != NULL) { - if( Z_TYPE_P(ele_value)!= IS_STRING ){ - /* variant is not a string */ - return FAILURE; - } - /* Add the contents */ - if (isFirstSubtag++ == 0){ - add_prefix(loc_name , cur_key_name); - } - smart_str_appendl(loc_name, SEPARATOR , sizeof(SEPARATOR)-1); - smart_str_appendl(loc_name, Z_STRVAL_P(ele_value) , Z_STRLEN_P(ele_value)); - } - } /* end of for */ - } /* end of else */ - - return SUCCESS; -} -/* }}} */ - -/*{{{ -* If applicable sets error message and aborts locale_compose gracefully -* returns 0 if locale_compose needs to be aborted -* otherwise returns 1 -*/ -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 ); - smart_str_free(loc_name); - return 0; - } - return 1; -} -/* }}} */ - -#define RETURN_SMART_STR(str) smart_str_0((str)); RETURN_NEW_STR((str)->s) -/* {{{ Creates a locale by combining the parts of locale-ID passed -* }}} */ -/* {{{ Creates a locale by combining the parts of locale-ID passed -* }}} */ -PHP_FUNCTION(locale_compose) -{ - smart_str loc_name_s = {0}; - smart_str *loc_name = &loc_name_s; - zval* arr = NULL; - HashTable* hash_arr = NULL; - int result = 0; - - intl_error_reset( NULL ); - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_ARRAY(arr) - ZEND_PARSE_PARAMETERS_END(); - - hash_arr = Z_ARRVAL_P( arr ); - - if( !hash_arr || zend_hash_num_elements( hash_arr ) == 0 ) - RETURN_FALSE; - - /* Check for grandfathered first */ - result = append_key_value(loc_name, hash_arr, LOC_GRANDFATHERED_LANG_TAG); - if( result == SUCCESS){ - RETURN_SMART_STR(loc_name); - } - if( !handleAppendResult( result, loc_name)){ - RETURN_FALSE; - } - - /* Not grandfathered */ - result = append_key_value(loc_name, hash_arr , LOC_LANG_TAG); - if( result == LOC_NOT_FOUND ){ - zend_argument_value_error(1, "must contain a \"%s\" key", LOC_LANG_TAG); - smart_str_free(loc_name); - RETURN_THROWS(); - } - if( !handleAppendResult( result, loc_name)){ - RETURN_FALSE; - } - - /* Extlang */ - result = append_multiple_key_values(loc_name, hash_arr , LOC_EXTLANG_TAG); - if( !handleAppendResult( result, loc_name)){ - RETURN_FALSE; - } - - /* Script */ - result = append_key_value(loc_name, hash_arr , LOC_SCRIPT_TAG); - if( !handleAppendResult( result, loc_name)){ - RETURN_FALSE; - } - - /* Region */ - result = append_key_value( loc_name, hash_arr , LOC_REGION_TAG); - if( !handleAppendResult( result, loc_name)){ - RETURN_FALSE; - } - - /* Variant */ - result = append_multiple_key_values( loc_name, hash_arr , LOC_VARIANT_TAG); - if( !handleAppendResult( result, loc_name)){ - RETURN_FALSE; - } - - /* Private */ - result = append_multiple_key_values( loc_name, hash_arr , LOC_PRIVATE_TAG); - if( !handleAppendResult( result, loc_name)){ - RETURN_FALSE; - } - - RETURN_SMART_STR(loc_name); -} -/* }}} */ - - -/*{{{ -* Parses the locale and returns private subtags if existing -* else returns NULL -* e.g. for locale='en_US-x-prv1-prv2-prv3' -* returns a pointer to the string 'prv1-prv2-prv3' -*/ -static zend_string* get_private_subtags(const char* loc_name) -{ - zend_string* result = NULL; - size_t len = 0; - const char* mod_loc_name =NULL; - - if( loc_name && (len = strlen(loc_name)) > 0 ){ - zend_off_t singletonPos = 0; - mod_loc_name = loc_name ; - while( (singletonPos = getSingletonPos(mod_loc_name)) > -1){ - if( (*(mod_loc_name+singletonPos)=='x') || (*(mod_loc_name+singletonPos)=='X') ){ - /* private subtag start found */ - if( singletonPos + 2 == len){ - /* loc_name ends with '-x-' ; return NULL */ - } - else{ - /* result = mod_loc_name + singletonPos +2; */ - result = zend_string_init(mod_loc_name + singletonPos+2 , (len -( singletonPos +2) ), 0); - } - break; - } - else{ - if((size_t)(singletonPos + 1) >= len){ - /* String end */ - break; - } else { - /* singleton found but not a private subtag , hence check further in the string for the private subtag */ - mod_loc_name = mod_loc_name + singletonPos +1; - len = strlen(mod_loc_name); - } - } - } /* end of while */ - } - - return result; -} -/* }}} */ - -/* {{{ code used by locale_parse */ -static int add_array_entry(const char* loc_name, zval* hash_arr, char* key_name) -{ - zend_string* key_value = NULL; - char* cur_key_name = NULL; - char* token = NULL; - char* last_ptr = NULL; - - int result = 0; - int cur_result = 0; - - - if( strcmp(key_name , LOC_PRIVATE_TAG)==0 ){ - key_value = get_private_subtags( loc_name ); - result = 1; - } else { - key_value = get_icu_value_internal( loc_name , key_name , &result,1 ); - } - if( (strcmp(key_name , LOC_PRIVATE_TAG)==0) || - ( strcmp(key_name , LOC_VARIANT_TAG)==0) ){ - if( result > 0 && key_value){ - int cnt = 0; - /* Tokenize on the "_" or "-" */ - token = php_strtok_r( key_value->val , DELIMITER ,&last_ptr); - if( cur_key_name ){ - efree( cur_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); - 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 */ - while( (token = php_strtok_r(NULL , DELIMITER , &last_ptr)) && (strlen(token)>1) ){ - snprintf( cur_key_name , cur_key_name_size, "%s%d", key_name , cnt++); - add_assoc_string( hash_arr, cur_key_name , token); - } -/* - if( strcmp(key_name, LOC_PRIVATE_TAG) == 0 ){ - } -*/ - } - if (key_value) { - zend_string_release_ex(key_value, 0); - } - } else { - if( result == 1 ){ - add_assoc_str( hash_arr, key_name , key_value); - cur_result = 1; - } else if (key_value) { - zend_string_release_ex(key_value, 0); - } - } - - if( cur_key_name ){ - efree( cur_key_name); - } - /*if( key_name != LOC_PRIVATE_TAG && key_value){*/ - return cur_result; -} -/* }}} */ - -/* {{{ parses a locale-id into an array the different parts of it */ -PHP_FUNCTION(locale_parse) -{ - char* loc_name = NULL; - size_t loc_name_len = 0; - int grOffset = 0; - - intl_error_reset( NULL ); - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_PATH(loc_name, loc_name_len) - ZEND_PARSE_PARAMETERS_END(); - - INTL_CHECK_LOCALE_LEN(strlen(loc_name)); - - if(loc_name_len == 0) { - loc_name = (char *)intl_locale_get_default(); - } - - array_init( return_value ); - - grOffset = findOffset( LOC_GRANDFATHERED , loc_name ); - if( grOffset >= 0 ){ - add_assoc_string( return_value , LOC_GRANDFATHERED_LANG_TAG, (char *)loc_name); - } - else{ - /* Not grandfathered */ - add_array_entry( loc_name , return_value , LOC_LANG_TAG); - add_array_entry( loc_name , return_value , LOC_SCRIPT_TAG); - add_array_entry( loc_name , return_value , LOC_REGION_TAG); - add_array_entry( loc_name , return_value , LOC_VARIANT_TAG); - add_array_entry( loc_name , return_value , LOC_PRIVATE_TAG); - } -} -/* }}} */ - -/* {{{ gets an array containing the list of variants, or null */ -PHP_FUNCTION(locale_get_all_variants) -{ - char* loc_name = NULL; - size_t loc_name_len = 0; - - int result = 0; - char* token = NULL; - zend_string* variant = NULL; - char* saved_ptr = NULL; - - intl_error_reset( NULL ); - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_PATH(loc_name, loc_name_len) - ZEND_PARSE_PARAMETERS_END(); - - if(loc_name_len == 0) { - loc_name = (char *)intl_locale_get_default(); - loc_name_len = strlen(loc_name); - } - - INTL_CHECK_LOCALE_LEN(loc_name_len); - - array_init( return_value ); - - /* If the locale is grandfathered, stop, no variants */ - if( findOffset( LOC_GRANDFATHERED , loc_name ) >= 0 ){ - /* ("Grandfathered Tag. No variants."); */ - } - else { - /* Call ICU variant */ - variant = get_icu_value_internal( loc_name , LOC_VARIANT_TAG , &result ,0); - if( result > 0 && variant){ - /* Tokenize on the "_" or "-" */ - token = php_strtok_r( variant->val , DELIMITER , &saved_ptr); - add_next_index_stringl( return_value, token , strlen(token)); - /* tokenize on the "_" or "-" and stop at singleton if any */ - while( (token = php_strtok_r(NULL , DELIMITER, &saved_ptr)) && (strlen(token)>1) ){ - add_next_index_stringl( return_value, token , strlen(token)); - } - } - if( variant ){ - zend_string_release_ex( variant, 0 ); - } - } - - -} -/* }}} */ - -/* {{{ Converts to lower case and also replaces all hyphens with the underscore */ -static int strToMatch(const char* str ,char *retstr) -{ - char* anchor = NULL; - const char* anchor1 = NULL; - int result = 0; - - if( (!str) || str[0] == '\0'){ - return result; - } else { - anchor = retstr; - anchor1 = str; - while( (*str)!='\0' ){ - if( *str == '-' ){ - *retstr = '_'; - } else { - *retstr = tolower(*str); - } - str++; - retstr++; - } - *retstr = '\0'; - retstr= anchor; - str= anchor1; - result = 1; - } - - return(result); -} -/* }}} */ - -/* {{{ 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) -{ - char* lang_tag = NULL; - size_t lang_tag_len = 0; - char* loc_range = NULL; - size_t loc_range_len = 0; - - int result = 0; - char* token = 0; - char* chrcheck = NULL; - - zend_string* can_lang_tag = NULL; - zend_string* can_loc_range = NULL; - - char* cur_lang_tag = NULL; - char* cur_loc_range = NULL; - - bool boolCanonical = 0; - UErrorCode status = U_ZERO_ERROR; - - intl_error_reset( NULL ); - - ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_PATH(lang_tag, lang_tag_len) - Z_PARAM_PATH(loc_range, loc_range_len) - Z_PARAM_OPTIONAL - Z_PARAM_BOOL(boolCanonical) - ZEND_PARSE_PARAMETERS_END(); - - if(loc_range_len == 0) { - loc_range = (char *)intl_locale_get_default(); - loc_range_len = strlen(loc_range); - } - - if( strcmp(loc_range,"*")==0){ - RETURN_TRUE; - } - - INTL_CHECK_LOCALE_LEN(loc_range_len); - INTL_CHECK_LOCALE_LEN(lang_tag_len); - - if( boolCanonical ){ - /* 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 ); - 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 ); - RETURN_FALSE; - } - - /* Convert to lower case for case-insensitive comparison */ - cur_lang_tag = ecalloc( 1, can_lang_tag->len + 1); - - /* Convert to lower case for case-insensitive comparison */ - result = strToMatch( can_lang_tag->val , cur_lang_tag); - if( result == 0) { - efree( cur_lang_tag ); - zend_string_release_ex( can_lang_tag, 0 ); - RETURN_FALSE; - } - - cur_loc_range = ecalloc( 1, can_loc_range->len + 1); - result = strToMatch( can_loc_range->val , cur_loc_range ); - if( result == 0) { - efree( cur_lang_tag ); - zend_string_release_ex( can_lang_tag, 0 ); - efree( cur_loc_range ); - zend_string_release_ex( can_loc_range, 0 ); - RETURN_FALSE; - } - - /* check if prefix */ - token = strstr( cur_lang_tag , cur_loc_range ); - - if( token && (token==cur_lang_tag) ){ - /* check if the char. after match is SEPARATOR */ - chrcheck = token + (strlen(cur_loc_range)); - if( isIDSeparator(*chrcheck) || isKeywordSeparator(*chrcheck) || isEndOfTag(*chrcheck) ){ - efree( cur_lang_tag ); - efree( cur_loc_range ); - if( can_lang_tag){ - zend_string_release_ex( can_lang_tag, 0 ); - } - if( can_loc_range){ - zend_string_release_ex( can_loc_range, 0 ); - } - RETURN_TRUE; - } - } - - /* No prefix as loc_range */ - if( cur_lang_tag){ - efree( cur_lang_tag ); - } - if( cur_loc_range){ - efree( cur_loc_range ); - } - if( can_lang_tag){ - zend_string_release_ex( can_lang_tag, 0 ); - } - if( can_loc_range){ - zend_string_release_ex( can_loc_range, 0 ); - } - RETURN_FALSE; - - } /* end of if isCanonical */ - else{ - /* Convert to lower case for case-insensitive comparison */ - cur_lang_tag = 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); - result = strToMatch( loc_range , cur_loc_range ); - if( result == 0) { - efree( cur_lang_tag ); - efree( cur_loc_range ); - RETURN_FALSE; - } - - /* check if prefix */ - token = strstr( cur_lang_tag , cur_loc_range ); - - if( token && (token==cur_lang_tag) ){ - /* check if the char. after match is SEPARATOR */ - chrcheck = token + (strlen(cur_loc_range)); - if( isIDSeparator(*chrcheck) || isEndOfTag(*chrcheck) ){ - efree( cur_lang_tag ); - efree( cur_loc_range ); - RETURN_TRUE; - } - } - - /* No prefix as loc_range */ - if( cur_lang_tag){ - efree( cur_lang_tag ); - } - if( cur_loc_range){ - efree( cur_loc_range ); - } - RETURN_FALSE; - - } -} -/* }}} */ - -static void array_cleanup( char* arr[] , int arr_size) -{ - int i=0; - for( i=0; i< arr_size; i++ ){ - if( arr[i*2] ){ - efree( arr[i*2]); - } - } - efree(arr); -} - -#define LOOKUP_CLEAN_RETURN(value) array_cleanup(cur_arr, cur_arr_len); return (value) -/* {{{ -* returns the lookup result to lookup_loc_range_src_php -* internal function -*/ -static zend_string* lookup_loc_range(const char* loc_range, HashTable* hash_arr, int canonicalize ) -{ - int i = 0; - int cur_arr_len = 0; - int result = 0; - - zend_string* lang_tag = NULL; - zval* ele_value = NULL; - - char* cur_loc_range = NULL; - zend_string* can_loc_range = NULL; - zend_off_t saved_pos = 0; - - zend_string* return_value = NULL; - - char **cur_arr = 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 */ - if(Z_TYPE_P(ele_value)!= IS_STRING) { - /* element value is not a string */ - zend_argument_type_error(2, "must only contain string values"); - LOOKUP_CLEAN_RETURN(NULL); - } - if (zend_str_has_nul_byte(Z_STR_P(ele_value))) { - zend_argument_value_error(2, "must not contain any null bytes"); - LOOKUP_CLEAN_RETURN(NULL); - } - 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); - LOOKUP_CLEAN_RETURN(NULL); - } - cur_arr[cur_arr_len*2+1] = Z_STRVAL_P(ele_value); - cur_arr_len++ ; - } ZEND_HASH_FOREACH_END(); /* end of for */ - - /* Canonicalize array elements */ - if(canonicalize) { - for(i=0; ival[0]) { - 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); - LOOKUP_CLEAN_RETURN(NULL); - } - cur_arr[i*2] = 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); - LOOKUP_CLEAN_RETURN(NULL); - } - } - - } - - if(canonicalize) { - /* Canonicalize the loc_range */ - 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 ); - if(can_loc_range) { - zend_string_release_ex(can_loc_range, 0); - } - LOOKUP_CLEAN_RETURN(NULL); - } else { - loc_range = can_loc_range->val; - } - } - - cur_loc_range = ecalloc(1, strlen(loc_range)+1); - /* convert to lower and replace hyphens */ - result = strToMatch(loc_range, cur_loc_range); - if(can_loc_range) { - zend_string_release_ex(can_loc_range, 0); - } - if(result == 0) { - efree(cur_loc_range); - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize lang_tag" , 0); - LOOKUP_CLEAN_RETURN(NULL); - } - - /* Lookup for the lang_tag match */ - saved_pos = strlen(cur_loc_range); - while(saved_pos > 0) { - for(i=0; i< cur_arr_len; i++){ - if(cur_arr[i*2] != NULL && strlen(cur_arr[i*2]) == saved_pos && strncmp(cur_loc_range, cur_arr[i*2], saved_pos) == 0) { - /* Match found */ - char *str = canonicalize ? cur_arr[i*2] : cur_arr[i*2+1]; - return_value = zend_string_init(str, strlen(str), 0); - efree(cur_loc_range); - LOOKUP_CLEAN_RETURN(return_value); - } - } - saved_pos = getStrrtokenPos(cur_loc_range, saved_pos); - } - - /* Match not found */ - efree(cur_loc_range); - LOOKUP_CLEAN_RETURN(NULL); -} -/* }}} */ - -/* {{{ Searches the items in $langtag for the best match to the language -* range -*/ -/* }}} */ -/* {{{ Searches the items in $langtag for the best match to the language -* range -*/ -PHP_FUNCTION(locale_lookup) -{ - zend_string* fallback_loc_str = NULL; - char* loc_range = NULL; - size_t loc_range_len = 0; - - zval* arr = NULL; - HashTable* hash_arr = NULL; - bool boolCanonical = 0; - zend_string* result_str = NULL; - - intl_error_reset( NULL ); - - ZEND_PARSE_PARAMETERS_START(2, 4) - Z_PARAM_ARRAY(arr) - Z_PARAM_PATH(loc_range, loc_range_len) - Z_PARAM_OPTIONAL - Z_PARAM_BOOL(boolCanonical) - Z_PARAM_PATH_STR_OR_NULL(fallback_loc_str) - ZEND_PARSE_PARAMETERS_END(); - - if(loc_range_len == 0) { - if(fallback_loc_str) { - loc_range = ZSTR_VAL(fallback_loc_str); - loc_range_len = ZSTR_LEN(fallback_loc_str); - } else { - loc_range = (char *)intl_locale_get_default(); - loc_range_len = strlen(loc_range); - } - } - - hash_arr = Z_ARRVAL_P(arr); - - INTL_CHECK_LOCALE_LEN(loc_range_len); - - if( !hash_arr || zend_hash_num_elements( hash_arr ) == 0 ) { - RETURN_EMPTY_STRING(); - } - - result_str = lookup_loc_range(loc_range, hash_arr, boolCanonical); - if(result_str == NULL || ZSTR_VAL(result_str)[0] == '\0') { - if( fallback_loc_str ) { - result_str = zend_string_copy(fallback_loc_str); - } else { - RETURN_EMPTY_STRING(); - } - } - - RETURN_STR(result_str); -} -/* }}} */ - -/* {{{ 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) -{ - UEnumeration *available; - char *http_accept = NULL; - size_t http_accept_len; - UErrorCode status = 0; - int len; - char resultLocale[INTL_MAX_LOCALE_LEN+1]; - UAcceptResult outResult; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(http_accept, http_accept_len) - ZEND_PARSE_PARAMETERS_END(); - if(http_accept_len > ULOC_FULLNAME_CAPACITY) { - /* check each fragment, if any bigger than capacity, can't do it due to bug #72533 */ - char *start = http_accept; - char *end; - size_t len; - do { - end = strchr(start, ','); - 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 ); - RETURN_FALSE; - } - if(end) { - start = end+1; - } - } while(end != NULL); - } - - available = ures_openAvailableLocales(NULL, &status); - INTL_CHECK_STATUS(status, "locale_accept_from_http: 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"); - if (len < 0 || outResult == ULOC_ACCEPT_FAILED) { - RETURN_FALSE; - } - RETURN_STRINGL(resultLocale, len); -} -/* }}} */ - -PHP_FUNCTION(locale_is_right_to_left) -{ - char *locale; - size_t locale_len; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_PATH(locale, locale_len) - ZEND_PARSE_PARAMETERS_END(); - - if (!locale_len) { - locale = (char *)intl_locale_get_default(); - } - - RETURN_BOOL(uloc_isRightToLeft(locale)); -} - -PHP_FUNCTION(locale_add_likely_subtags) -{ - char *locale, maximized_locale[ULOC_FULLNAME_CAPACITY]; - UErrorCode status = 0; - size_t locale_len; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_PATH(locale, locale_len) - ZEND_PARSE_PARAMETERS_END(); - - if (!locale_len) { - locale = (char *)intl_locale_get_default(); - } - - int32_t maximized_locale_len = uloc_addLikelySubtags(locale, maximized_locale, sizeof(maximized_locale), &status); - INTL_CHECK_STATUS(status, "locale_add_likely_subtags: invalid locale"); - if (maximized_locale_len < 0) { - RETURN_FALSE; - } - - RETURN_STRINGL(maximized_locale, maximized_locale_len); -} - -PHP_FUNCTION(locale_minimize_subtags) -{ - char *locale, minimized_locale[ULOC_FULLNAME_CAPACITY]; - UErrorCode status = 0; - size_t locale_len; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_PATH(locale, locale_len) - ZEND_PARSE_PARAMETERS_END(); - - if (!locale_len) { - locale = (char *)intl_locale_get_default(); - } - - int32_t minimized_locale_len = uloc_minimizeSubtags(locale, minimized_locale, sizeof(minimized_locale), &status); - INTL_CHECK_STATUS(status, "locale_minimize_subtags: invalid locale"); - if (minimized_locale_len < 0) { - RETURN_FALSE; - } - - RETURN_STRINGL(minimized_locale, minimized_locale_len); -} diff --git a/ext/intl/locale/locale_methods.cpp b/ext/intl/locale/locale_methods.cpp new file mode 100644 index 0000000000000..5cf6928a8cd3c --- /dev/null +++ b/ext/intl/locale/locale_methods.cpp @@ -0,0 +1,1683 @@ +/* + +----------------------------------------------------------------------+ + | 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: Kirti Velankar | + +----------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +extern "C" { +#include "php_intl.h" +#include "locale.h" +#include "locale_class.h" +#include "intl_convert.h" +#include "intl_data.h" + +#include +#include +#include +#include "main/php_ini.h" +#include "zend_smart_str.h" +} + +ZEND_EXTERN_MODULE_GLOBALS( intl ) + +/* Sizes required for the strings "variant15" , "extlang11", "private12" etc. */ +#define SEPARATOR "_" +#define SEPARATOR1 "-" +#define DELIMITER "-_" +#define EXTLANG_PREFIX "a" +#define PRIVATE_PREFIX "x" +#define DISP_NAME "name" + +#define MAX_NO_VARIANT 15 +#define MAX_NO_EXTLANG 3 +#define MAX_NO_PRIVATE 15 +#define MAX_NO_LOOKUP_LANG_TAG 100 + +#define LOC_NOT_FOUND 1 + +/* Sizes required for the strings "variant15" , "extlang3", "private12" etc. */ +#define VARIANT_KEYNAME_LEN 11 +#define EXTLANG_KEYNAME_LEN 10 +#define PRIVATE_KEYNAME_LEN 11 + +/* Based on the IANA language subtag registry (File-Date: 2021-08-06) + * https://www.iana.org/assignments/language-subtag-registry + * + * This list includes all grandfathered tags, as well as redundant + * tags that have a Preferred-Value. + */ +static const char * const LOC_GRANDFATHERED[] = { + "art-lojban", + "cel-gaulish", + "en-GB-oed", + "i-ami", + "i-bnn", + "i-default", + "i-enochian", + "i-hak", + "i-klingon", + "i-lux", + "i-mingo", + "i-navajo", + "i-pwn", + "i-tao", + "i-tay", + "i-tsu", + "no-bok", + "no-nyn", + "sgn-BE-FR", + "sgn-BE-NL", + "sgn-BR", + "sgn-CH-DE", + "sgn-CO", + "sgn-DE", + "sgn-DK", + "sgn-ES", + "sgn-FR", + "sgn-GB", + "sgn-GR", + "sgn-IE", + "sgn-IT", + "sgn-JP", + "sgn-MX", + "sgn-NI", + "sgn-NL", + "sgn-NO", + "sgn-PT", + "sgn-SE", + "sgn-US", + "sgn-ZA", + "zh-cmn", + "zh-cmn-Hans", + "zh-cmn-Hant", + "zh-gan", + "zh-guoyu", + "zh-hakka", + "zh-min", + "zh-min-nan", + "zh-wuu", + "zh-xiang", + NULL +}; + +/* Based on the IANA language subtag registry (File-Date: 2021-08-06) + * + * This array lists the preferred values for the grandfathered and redundant + * tags listed in LOC_GRANDFATHERED. This is in sync with the array + * LOC_GRANDFATHERED, i.e., the offsets of the grandfathered tags match the + * offsets of the preferred value. If a value in LOC_PREFERRED_GRANDFATHERED is + * NULL, then the matching offset in LOC_GRANDFATHERED has no preferred value. + */ +static const char * const LOC_PREFERRED_GRANDFATHERED[] = { + "jbo", + NULL, + "en-GB-oxendict", + "ami", + "bnn", + NULL, + NULL, + "hak", + "tlh", + "lb", + NULL, + "nv", + "pwn", + "tao", + "tay", + "tsu", + "nb", + "nn", + "sfb", + "vgt", + "bzs", + "sgg", + "csn", + "gsg", + "dsl", + "ssp", + "fsl", + "bfi", + "gss", + "isg", + "ise", + "jsl", + "mfs", + "ncs", + "dse", + "nsl", + "psr", + "swl", + "ase", + "sfs", + "cmn", + "cmn-Hans", + "cmn-Hant", + "gan", + "cmn", + "hak", + NULL, + "nan", + "wuu", + "hsn", + NULL +}; + +/* returns true if a is an ID separator, false otherwise */ +#define isIDSeparator(a) (a == '_' || a == '-') +#define isKeywordSeparator(a) (a == '@' ) +#define isEndOfTag(a) (a == '\0' ) + +#define isPrefixLetter(a) ((a=='x')||(a=='X')||(a=='i')||(a=='I')) + +/*returns true if one of the special prefixes is here (s=string) + 'x-' or 'i-' */ +#define isIDPrefix(s) (isPrefixLetter(s[0])&&isIDSeparator(s[1])) +#define isKeywordPrefix(s) ( isKeywordSeparator(s[0]) ) + +/* Dot terminates it because of POSIX form where dot precedes the codepage + * except for variant */ +#define isTerminator(a) ((a==0)||(a=='.')||(a=='@')) + +/* {{{ return the offset of 'key' in the array 'list'. + * returns -1 if not present */ +static int16_t findOffset(const char* const* list, const char* key) +{ + const char* const* anchor = list; + while (*list != NULL) { + if (strcasecmp(key, *list) == 0) { + return (int16_t)(list - anchor); + } + list++; + } + + return -1; + +} +/*}}}*/ + +static char* getPreferredTag(const char* gf_tag) +{ + char* result = NULL; + zend_off_t grOffset = 0; + + grOffset = findOffset( LOC_GRANDFATHERED ,gf_tag); + if(grOffset < 0) { + return NULL; + } + if( LOC_PREFERRED_GRANDFATHERED[grOffset] != NULL ){ + /* return preferred tag */ + result = estrdup( LOC_PREFERRED_GRANDFATHERED[grOffset] ); + } else { + /* Return correct grandfathered language tag */ + result = estrdup( LOC_GRANDFATHERED[grOffset] ); + } + return result; +} + +/* {{{ +* returns the position of next token for lookup +* or -1 if no token +* strtokr equivalent search for token in reverse direction +*/ +static zend_off_t getStrrtokenPos(char* str, zend_off_t savedPos) +{ + zend_off_t result =-1; + zend_off_t i; + + for(i=savedPos-1; i>=0; i--) { + if(isIDSeparator(*(str+i)) || isKeywordSeparator(*(str+i))){ + /* delimiter found; check for singleton */ + if(i>=2 && isIDSeparator(*(str+i-2)) ){ + /* a singleton; so send the position of token before the singleton */ + result = i-2; + } else { + result = i; + } + break; + } + } + if(result < 1){ + /* Just in case inavlid locale e.g. '-x-xyz' or '-sl_Latn' */ + result =-1; + } + return result; +} +/* }}} */ + +/* {{{ +* returns the position of a singleton if present +* returns -1 if no singleton +* strtok equivalent search for singleton +*/ +static zend_off_t getSingletonPos(const char* str) +{ + zend_off_t result =-1; + size_t len = 0; + + if( str && ((len=strlen(str))>0) ){ + zend_off_t i = 0; + for( i=0; (size_t)i < len ; i++){ + if( isIDSeparator(*(str+i)) ){ + if( i==1){ + /* string is of the form x-avy or a-prv1 */ + result =0; + break; + } else { + /* delimiter found; check for singleton */ + if( isIDSeparator(*(str+i+2)) ){ + /* a singleton; so send the position of separator before singleton */ + result = i+1; + break; + } + } + } + }/* end of for */ + + } + return result; +} +/* }}} */ + +/* {{{ Get default locale */ +/* }}} */ +/* {{{ Get default locale */ +U_CFUNC PHP_NAMED_FUNCTION(zif_locale_get_default) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + RETURN_STRING( intl_locale_get_default( ) ); +} + +/* }}} */ + +/* {{{ Set default locale */ +/* }}} */ +/* {{{ Set default locale */ +U_CFUNC PHP_NAMED_FUNCTION(zif_locale_set_default) +{ + zend_string* locale_name; + zend_string *ini_name; + char *default_locale = NULL; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_PATH_STR(locale_name) + ZEND_PARSE_PARAMETERS_END(); + + if (ZSTR_LEN(locale_name) == 0) { + default_locale = (char *)uloc_getDefault(); + locale_name = zend_string_init(default_locale, strlen(default_locale), 0); + } + + ini_name = zend_string_init(LOCALE_INI_NAME, sizeof(LOCALE_INI_NAME) - 1, 0); + zend_alter_ini_entry(ini_name, locale_name, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); + zend_string_release_ex(ini_name, 0); + if (default_locale != NULL) { + zend_string_release_ex(locale_name, 0); + } + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ +* Gets the value from ICU +* common code shared by get_primary_language,get_script or get_region or get_variant +* result = 0 if error, 1 if successful , -1 if no value +*/ +static zend_string* get_icu_value_internal( const char* loc_name , const char* tag_name, int* result , int fromParseLocale) +{ + zend_string* tag_value = NULL; + int32_t tag_value_len = 512; + + char* mod_loc_name = NULL; + + int32_t buflen = 512; + UErrorCode status = U_ZERO_ERROR; + + if (strlen(loc_name) > INTL_MAX_LOCALE_LEN) { + return NULL; + } + + if( strcmp(tag_name, LOC_CANONICALIZE_TAG) != 0 ){ + /* Handle grandfathered languages */ + zend_off_t grOffset = findOffset( LOC_GRANDFATHERED , loc_name ); + if( grOffset >= 0 ){ + if( strcmp(tag_name , LOC_LANG_TAG)==0 ){ + return zend_string_init(loc_name, strlen(loc_name), 0); + } else { + /* Since Grandfathered , no value , do nothing , retutn NULL */ + return NULL; + } + } + + if( fromParseLocale==1 ){ + zend_off_t singletonPos = 0; + + /* Handle singletons */ + if( strcmp(tag_name , LOC_LANG_TAG)==0 ){ + if( strlen(loc_name)>1 && (isIDPrefix(loc_name) == 1) ){ + return zend_string_init(loc_name, strlen(loc_name), 0); + } + } + + singletonPos = getSingletonPos( loc_name ); + if( singletonPos == 0){ + /* singleton at start of script, region , variant etc. + * or invalid singleton at start of language */ + return NULL; + } else if( singletonPos > 0 ){ + /* singleton at some position except at start + * strip off the singleton and rest of the loc_name */ + mod_loc_name = estrndup ( loc_name , singletonPos-1); + } + } /* end of if fromParse */ + + } /* end of if != LOC_CANONICAL_TAG */ + + if( mod_loc_name == NULL){ + mod_loc_name = estrdup(loc_name ); + } + + /* Proceed to ICU */ + do{ + if (tag_value) { + tag_value = zend_string_realloc( tag_value , buflen, 0); + } else { + tag_value = zend_string_alloc( buflen, 0); + } + tag_value_len = buflen; + + if( strcmp(tag_name , LOC_SCRIPT_TAG)==0 ){ + buflen = uloc_getScript ( mod_loc_name , tag_value->val , tag_value_len , &status); + } + if( strcmp(tag_name , LOC_LANG_TAG )==0 ){ + buflen = uloc_getLanguage ( mod_loc_name , tag_value->val , tag_value_len , &status); + } + if( strcmp(tag_name , LOC_REGION_TAG)==0 ){ + buflen = uloc_getCountry ( mod_loc_name , tag_value->val , tag_value_len , &status); + } + if( strcmp(tag_name , LOC_VARIANT_TAG)==0 ){ + buflen = uloc_getVariant ( mod_loc_name , tag_value->val , tag_value_len , &status); + } + if( strcmp(tag_name , LOC_CANONICALIZE_TAG)==0 ){ + buflen = uloc_canonicalize ( mod_loc_name , tag_value->val , tag_value_len , &status); + } + + if( U_FAILURE( status ) ) { + if( status == U_BUFFER_OVERFLOW_ERROR ) { + status = U_ZERO_ERROR; + buflen++; /* add space for \0 */ + continue; + } + + /* Error in retrieving data */ + *result = 0; + if( tag_value ){ + zend_string_release_ex( tag_value, 0 ); + } + if( mod_loc_name ){ + efree( mod_loc_name); + } + return NULL; + } + } while( buflen > tag_value_len ); + + if( buflen ==0 ){ + /* No value found */ + *result = -1; + if( tag_value ){ + zend_string_release_ex( tag_value, 0 ); + } + if( mod_loc_name ){ + efree( mod_loc_name); + } + return NULL; + } else { + *result = 1; + } + + if( mod_loc_name ){ + efree( mod_loc_name); + } + + tag_value->len = strlen(tag_value->val); + return tag_value; +} +/* }}} */ + +/* {{{ +* Gets the value from ICU , called when PHP userspace function is called +* common code shared by get_primary_language,get_script or get_region or get_variant +*/ +static void get_icu_value_src_php( const char* tag_name, INTERNAL_FUNCTION_PARAMETERS) +{ + + char* loc_name = NULL; + size_t loc_name_len = 0; + + zend_string* tag_value = NULL; + + int result = 0; + char* msg = NULL; + + UErrorCode status = U_ZERO_ERROR; + + intl_error_reset( NULL ); + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_PATH(loc_name, loc_name_len) + ZEND_PARSE_PARAMETERS_END(); + + if(loc_name_len == 0) { + loc_name = (char *)intl_locale_get_default(); + loc_name_len = strlen(loc_name); + } + + INTL_CHECK_LOCALE_LEN(loc_name_len); + + /* Call ICU get */ + tag_value = get_icu_value_internal( loc_name , tag_name , &result ,0); + + /* No value found */ + if( result == -1 ) { + if( tag_value){ + zend_string_release_ex( tag_value, 0 ); + } + RETURN_EMPTY_STRING(); + } + + /* value found */ + if( tag_value){ + RETURN_STR( tag_value ); + } + + /* Error encountered while fetching the value */ + if( result ==0) { + spprintf(&msg , 0, "unable to get locale %s", tag_name ); + intl_error_set( NULL, status, msg); + efree(msg); + RETURN_NULL(); + } + +} +/* }}} */ + +/* {{{ gets the script for the $locale */ +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 */ +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 */ +U_CFUNC PHP_FUNCTION(locale_get_primary_language ) +{ + get_icu_value_src_php( LOC_LANG_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); +} +/* }}} */ + + +/* {{{ + * common code shared by display_xyz functions to get the value from ICU + }}} */ +static void get_icu_disp_value_src_php( const char* tag_name, INTERNAL_FUNCTION_PARAMETERS) +{ + char* loc_name = NULL; + size_t loc_name_len = 0; + + char* disp_loc_name = NULL; + size_t disp_loc_name_len = 0; + int free_loc_name = 0; + + UChar* disp_name = NULL; + int32_t disp_name_len = 0; + + char* mod_loc_name = NULL; + + int32_t buflen = 512; + UErrorCode status = U_ZERO_ERROR; + + zend_string* u8str; + + char* msg = NULL; + + intl_error_reset( NULL ); + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_PATH(loc_name, loc_name_len) + Z_PARAM_OPTIONAL + Z_PARAM_PATH_OR_NULL(disp_loc_name, disp_loc_name_len) + ZEND_PARSE_PARAMETERS_END(); + + if(loc_name_len > ULOC_FULLNAME_CAPACITY) { + /* See bug 67397: overlong locale names cause trouble in uloc_getDisplayName */ + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "name too long"); + RETURN_FALSE; + } + + if(loc_name_len == 0) { + loc_name = (char *)intl_locale_get_default(); + } + + if( strcmp(tag_name, DISP_NAME) != 0 ){ + /* Handle grandfathered languages */ + int grOffset = findOffset( LOC_GRANDFATHERED , loc_name ); + if( grOffset >= 0 ){ + if( strcmp(tag_name , LOC_LANG_TAG)==0 ){ + mod_loc_name = getPreferredTag( loc_name ); + } else { + /* Since Grandfathered, no value, do nothing, return NULL */ + RETURN_FALSE; + } + } + } /* end of if != LOC_CANONICAL_TAG */ + + if( mod_loc_name==NULL ){ + mod_loc_name = estrdup( loc_name ); + } + + /* Check if disp_loc_name passed , if not use default locale */ + if( !disp_loc_name){ + disp_loc_name = estrdup(intl_locale_get_default()); + free_loc_name = 1; + } + + /* Get the disp_value for the given locale */ + do{ + disp_name = reinterpret_cast(erealloc( disp_name , buflen * sizeof(UChar) )); + disp_name_len = buflen; + + if( strcmp(tag_name , LOC_LANG_TAG)==0 ){ + buflen = uloc_getDisplayLanguage ( mod_loc_name , disp_loc_name , disp_name , disp_name_len , &status); + } else if( strcmp(tag_name , LOC_SCRIPT_TAG)==0 ){ + buflen = uloc_getDisplayScript ( mod_loc_name , disp_loc_name , disp_name , disp_name_len , &status); + } else if( strcmp(tag_name , LOC_REGION_TAG)==0 ){ + buflen = uloc_getDisplayCountry ( mod_loc_name , disp_loc_name , disp_name , disp_name_len , &status); + } else if( strcmp(tag_name , LOC_VARIANT_TAG)==0 ){ + buflen = uloc_getDisplayVariant ( mod_loc_name , disp_loc_name , disp_name , disp_name_len , &status); + } else if( strcmp(tag_name , DISP_NAME)==0 ){ + buflen = uloc_getDisplayName ( mod_loc_name , disp_loc_name , disp_name , disp_name_len , &status); + } + + /* U_STRING_NOT_TERMINATED_WARNING is admissible here; don't look for it */ + if( U_FAILURE( status ) ) + { + if( status == U_BUFFER_OVERFLOW_ERROR ) + { + status = U_ZERO_ERROR; + continue; + } + + spprintf(&msg, 0, "unable to get locale %s", tag_name ); + intl_error_set( NULL, status, msg); + efree(msg); + if( disp_name){ + efree( disp_name ); + } + if( mod_loc_name){ + efree( mod_loc_name ); + } + if (free_loc_name) { + efree((void *)disp_loc_name); + disp_loc_name = NULL; + } + RETURN_FALSE; + } + } while( buflen > disp_name_len ); + + if( mod_loc_name){ + efree( mod_loc_name ); + } + if (free_loc_name) { + efree((void *)disp_loc_name); + disp_loc_name = NULL; + } + /* Convert display locale name from UTF-16 to UTF-8. */ + u8str = intl_convert_utf16_to_utf8(disp_name, buflen, &status ); + efree( disp_name ); + if( !u8str ) + { + spprintf(&msg, 0, "error converting display name for %s to UTF-8", tag_name ); + intl_error_set( NULL, status, msg); + efree(msg); + RETURN_FALSE; + } + + RETVAL_NEW_STR( u8str ); +} +/* }}} */ + +/* {{{ gets the name for the $locale in $in_locale or default_locale */ +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 */ +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 */ +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 */ +U_CFUNC PHP_FUNCTION(locale_get_display_region) +{ + get_icu_disp_value_src_php( LOC_REGION_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); +} +/* }}} */ + +/* {{{ +* proto static string Locale::getDisplayVariant($locale, $in_locale = null) +* gets the variant for the $locale in $in_locale or default_locale + }}} */ +/* {{{ +* proto static string get_display_variant($locale, $in_locale = null) +* gets the variant for the $locale in $in_locale or default_locale +*/ +U_CFUNC PHP_FUNCTION(locale_get_display_variant) +{ + get_icu_disp_value_src_php( LOC_VARIANT_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); +} +/* }}} */ + + /* {{{ return an associative array containing keyword-value + * pairs for this locale. The keys are keys to the array (doh!) + * }}}*/ + /* {{{ return an associative array containing keyword-value + * pairs for this locale. The keys are keys to the array (doh!) + */ +U_CFUNC PHP_FUNCTION( locale_get_keywords ) +{ + UEnumeration* e = NULL; + UErrorCode status = U_ZERO_ERROR; + + const char* kw_key = NULL; + int32_t kw_key_len = 0; + + char* loc_name = NULL; + size_t loc_name_len = 0; + + intl_error_reset( NULL ); + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_PATH(loc_name, loc_name_len) + ZEND_PARSE_PARAMETERS_END(); + + INTL_CHECK_LOCALE_LEN(strlen(loc_name)); + + if(loc_name_len == 0) { + loc_name = (char *)intl_locale_get_default(); + } + + /* Get the keywords */ + e = uloc_openKeywords( loc_name, &status ); + if( e != NULL ) { + /* + ICU expects the buffer to be allocated before calling the function + and so the buffer size has been explicitly specified + ICU uloc.h #define ULOC_KEYWORD_AND_VALUES_CAPACITY 100 + hence the kw_value buffer size is 100 + */ + + /* Traverse it, filling the return array. */ + array_init( return_value ); + + while( ( kw_key = uenum_next( e, &kw_key_len, &status ) ) != NULL ){ + int32_t kw_value_len = 100; + zend_string *kw_value_str = zend_string_alloc(kw_value_len, 0); + + /* Get the keyword value for each keyword */ + kw_value_len=uloc_getKeywordValue( loc_name, kw_key, ZSTR_VAL(kw_value_str), kw_value_len, &status ); + if (status == U_BUFFER_OVERFLOW_ERROR) { + status = U_ZERO_ERROR; + kw_value_str = zend_string_extend(kw_value_str, kw_value_len, 0); + kw_value_len=uloc_getKeywordValue( loc_name,kw_key, ZSTR_VAL(kw_value_str), kw_value_len+1, &status ); + } else if(!U_FAILURE(status)) { + 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, "Error encountered while getting the keyword value for the keyword"); + if( kw_value_str){ + zend_string_efree( kw_value_str ); + } + zend_array_destroy(Z_ARR_P(return_value)); + RETURN_FALSE; + } + + add_assoc_str( return_value, (char *)kw_key, kw_value_str); + } /* end of while */ + + } /* end of if e!=NULL */ + + uenum_close( e ); +} +/* }}} */ + + /* {{{ @return string the canonicalized locale + * }}} */ + /* {{{ @param string $locale The locale string to canonicalize */ +U_CFUNC PHP_FUNCTION(locale_canonicalize) +{ + get_icu_value_src_php( LOC_CANONICALIZE_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); +} +/* }}} */ + +/* {{{ append_key_value +* Internal function which is called from locale_compose +* gets the value for the key_name and appends to the loc_name +* returns 1 if successful , -1 if not found , +* 0 if array element is not a string , -2 if buffer-overflow +*/ +static int append_key_value(smart_str* loc_name, HashTable* hash_arr, const char* key_name) +{ + zval *ele_value; + + if ((ele_value = zend_hash_str_find_deref(hash_arr , key_name, strlen(key_name))) != NULL ) { + if(Z_TYPE_P(ele_value)!= IS_STRING ){ + /* element value is not a string */ + return FAILURE; + } + if(strcmp(key_name, LOC_LANG_TAG) != 0 && + strcmp(key_name, LOC_GRANDFATHERED_LANG_TAG)!=0 ) { + /* not lang or grandfathered tag */ + smart_str_appendl(loc_name, SEPARATOR , sizeof(SEPARATOR)-1); + } + smart_str_appendl(loc_name, Z_STRVAL_P(ele_value) , Z_STRLEN_P(ele_value)); + return SUCCESS; + } + + return LOC_NOT_FOUND; +} +/* }}} */ + +/* {{{ append_prefix , appends the prefix needed +* e.g. private adds 'x' +*/ +static void add_prefix(smart_str* loc_name, const char* key_name) +{ + if( strncmp(key_name , LOC_PRIVATE_TAG , 7) == 0 ){ + smart_str_appendl(loc_name, SEPARATOR , sizeof(SEPARATOR)-1); + smart_str_appendl(loc_name, PRIVATE_PREFIX , sizeof(PRIVATE_PREFIX)-1); + } +} +/* }}} */ + +/* {{{ append_multiple_key_values +* Internal function which is called from locale_compose +* gets the multiple values for the key_name and appends to the loc_name +* used for 'variant','extlang','private' +* returns 1 if successful , -1 if not found , +* 0 if array element is not a string , -2 if buffer-overflow +*/ +static int append_multiple_key_values(smart_str* loc_name, HashTable* hash_arr, const char* key_name) +{ + zval *ele_value; + int isFirstSubtag = 0; + + /* Variant/ Extlang/Private etc. */ + if ((ele_value = zend_hash_str_find_deref( hash_arr , key_name , strlen(key_name))) != NULL) { + if( Z_TYPE_P(ele_value) == IS_STRING ){ + add_prefix( loc_name , key_name); + + smart_str_appendl(loc_name, SEPARATOR , sizeof(SEPARATOR)-1); + smart_str_appendl(loc_name, Z_STRVAL_P(ele_value) , Z_STRLEN_P(ele_value)); + return SUCCESS; + } else if(Z_TYPE_P(ele_value) == IS_ARRAY ) { + HashTable *arr = Z_ARRVAL_P(ele_value); + zval *data; + + ZEND_HASH_FOREACH_VAL(arr, data) { + ZVAL_DEREF(data); + if(Z_TYPE_P(data) != IS_STRING) { + return FAILURE; + } + if (isFirstSubtag++ == 0){ + add_prefix(loc_name , key_name); + } + smart_str_appendl(loc_name, SEPARATOR , sizeof(SEPARATOR)-1); + smart_str_appendl(loc_name, Z_STRVAL_P(data) , Z_STRLEN_P(data)); + } ZEND_HASH_FOREACH_END(); + return SUCCESS; + } else { + return FAILURE; + } + } else { + char cur_key_name[31]; + int max_value = 0, i; + /* Decide the max_value: the max. no. of elements allowed */ + if( strcmp(key_name , LOC_VARIANT_TAG) ==0 ){ + max_value = MAX_NO_VARIANT; + } + if( strcmp(key_name , LOC_EXTLANG_TAG) ==0 ){ + max_value = MAX_NO_EXTLANG; + } + if( strcmp(key_name , LOC_PRIVATE_TAG) ==0 ){ + max_value = MAX_NO_PRIVATE; + } + + /* Multiple variant values as variant0, variant1 ,variant2 */ + isFirstSubtag = 0; + for( i=0 ; i< max_value; i++ ){ + snprintf( cur_key_name , 30, "%s%d", key_name , i); + if ((ele_value = zend_hash_str_find_deref( hash_arr , cur_key_name , strlen(cur_key_name))) != NULL) { + if( Z_TYPE_P(ele_value)!= IS_STRING ){ + /* variant is not a string */ + return FAILURE; + } + /* Add the contents */ + if (isFirstSubtag++ == 0){ + add_prefix(loc_name , cur_key_name); + } + smart_str_appendl(loc_name, SEPARATOR , sizeof(SEPARATOR)-1); + smart_str_appendl(loc_name, Z_STRVAL_P(ele_value) , Z_STRLEN_P(ele_value)); + } + } /* end of for */ + } /* end of else */ + + return SUCCESS; +} +/* }}} */ + +/*{{{ +* If applicable sets error message and aborts locale_compose gracefully +* returns 0 if locale_compose needs to be aborted +* otherwise returns 1 +*/ +static int handleAppendResult( int result, smart_str* loc_name) +{ + intl_error_reset( NULL ); + if( result == FAILURE) { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "parameter array element is not a string"); + smart_str_free(loc_name); + return 0; + } + return 1; +} +/* }}} */ + +#define RETURN_SMART_STR(str) smart_str_0((str)); RETURN_NEW_STR((str)->s) +/* {{{ Creates a locale by combining the parts of locale-ID passed +* }}} */ +/* {{{ Creates a locale by combining the parts of locale-ID passed +* }}} */ +U_CFUNC PHP_FUNCTION(locale_compose) +{ + smart_str loc_name_s = {NULL, 0}; + smart_str *loc_name = &loc_name_s; + zval* arr = NULL; + HashTable* hash_arr = NULL; + int result = 0; + + intl_error_reset( NULL ); + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ARRAY(arr) + ZEND_PARSE_PARAMETERS_END(); + + hash_arr = Z_ARRVAL_P( arr ); + + if( !hash_arr || zend_hash_num_elements( hash_arr ) == 0 ) + RETURN_FALSE; + + /* Check for grandfathered first */ + result = append_key_value(loc_name, hash_arr, LOC_GRANDFATHERED_LANG_TAG); + if( result == SUCCESS){ + RETURN_SMART_STR(loc_name); + } + if( !handleAppendResult( result, loc_name)){ + RETURN_FALSE; + } + + /* Not grandfathered */ + result = append_key_value(loc_name, hash_arr , LOC_LANG_TAG); + if( result == LOC_NOT_FOUND ){ + zend_argument_value_error(1, "must contain a \"%s\" key", LOC_LANG_TAG); + smart_str_free(loc_name); + RETURN_THROWS(); + } + if( !handleAppendResult( result, loc_name)){ + RETURN_FALSE; + } + + /* Extlang */ + result = append_multiple_key_values(loc_name, hash_arr , LOC_EXTLANG_TAG); + if( !handleAppendResult( result, loc_name)){ + RETURN_FALSE; + } + + /* Script */ + result = append_key_value(loc_name, hash_arr , LOC_SCRIPT_TAG); + if( !handleAppendResult( result, loc_name)){ + RETURN_FALSE; + } + + /* Region */ + result = append_key_value( loc_name, hash_arr , LOC_REGION_TAG); + if( !handleAppendResult( result, loc_name)){ + RETURN_FALSE; + } + + /* Variant */ + result = append_multiple_key_values( loc_name, hash_arr , LOC_VARIANT_TAG); + if( !handleAppendResult( result, loc_name)){ + RETURN_FALSE; + } + + /* Private */ + result = append_multiple_key_values( loc_name, hash_arr , LOC_PRIVATE_TAG); + if( !handleAppendResult( result, loc_name)){ + RETURN_FALSE; + } + + RETURN_SMART_STR(loc_name); +} +/* }}} */ + + +/*{{{ +* Parses the locale and returns private subtags if existing +* else returns NULL +* e.g. for locale='en_US-x-prv1-prv2-prv3' +* returns a pointer to the string 'prv1-prv2-prv3' +*/ +static zend_string* get_private_subtags(const char* loc_name) +{ + zend_string* result = NULL; + size_t len = 0; + const char* mod_loc_name =NULL; + + if( loc_name && (len = strlen(loc_name)) > 0 ){ + zend_off_t singletonPos = 0; + mod_loc_name = loc_name ; + while( (singletonPos = getSingletonPos(mod_loc_name)) > -1){ + if( (*(mod_loc_name+singletonPos)=='x') || (*(mod_loc_name+singletonPos)=='X') ){ + /* private subtag start found */ + if( singletonPos + 2 == len){ + /* loc_name ends with '-x-' ; return NULL */ + } + else{ + /* result = mod_loc_name + singletonPos +2; */ + result = zend_string_init(mod_loc_name + singletonPos+2 , (len -( singletonPos +2) ), 0); + } + break; + } + else{ + if((size_t)(singletonPos + 1) >= len){ + /* String end */ + break; + } else { + /* singleton found but not a private subtag , hence check further in the string for the private subtag */ + mod_loc_name = mod_loc_name + singletonPos +1; + len = strlen(mod_loc_name); + } + } + } /* end of while */ + } + + return result; +} +/* }}} */ + +/* {{{ code used by locale_parse */ +static int add_array_entry(const char* loc_name, zval* hash_arr, const char* key_name) +{ + zend_string* key_value = NULL; + char* cur_key_name = NULL; + char* token = NULL; + char* last_ptr = NULL; + + int result = 0; + int cur_result = 0; + + + if( strcmp(key_name , LOC_PRIVATE_TAG)==0 ){ + key_value = get_private_subtags( loc_name ); + result = 1; + } else { + key_value = get_icu_value_internal( loc_name , key_name , &result,1 ); + } + if( (strcmp(key_name , LOC_PRIVATE_TAG)==0) || + ( strcmp(key_name , LOC_VARIANT_TAG)==0) ){ + if( result > 0 && key_value){ + int cnt = 0; + /* Tokenize on the "_" or "-" */ + token = php_strtok_r( key_value->val , DELIMITER ,&last_ptr); + if( cur_key_name ){ + efree( cur_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 = 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 */ + while( (token = php_strtok_r(NULL , DELIMITER , &last_ptr)) && (strlen(token)>1) ){ + snprintf( cur_key_name , cur_key_name_size, "%s%d", key_name , cnt++); + add_assoc_string( hash_arr, cur_key_name , token); + } +/* + if( strcmp(key_name, LOC_PRIVATE_TAG) == 0 ){ + } +*/ + } + if (key_value) { + zend_string_release_ex(key_value, 0); + } + } else { + if( result == 1 ){ + add_assoc_str( hash_arr, key_name , key_value); + cur_result = 1; + } else if (key_value) { + zend_string_release_ex(key_value, 0); + } + } + + if( cur_key_name ){ + efree( cur_key_name); + } + /*if( key_name != LOC_PRIVATE_TAG && key_value){*/ + return cur_result; +} +/* }}} */ + +/* {{{ parses a locale-id into an array the different parts of it */ +U_CFUNC PHP_FUNCTION(locale_parse) +{ + char* loc_name = NULL; + size_t loc_name_len = 0; + int grOffset = 0; + + intl_error_reset( NULL ); + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_PATH(loc_name, loc_name_len) + ZEND_PARSE_PARAMETERS_END(); + + INTL_CHECK_LOCALE_LEN(strlen(loc_name)); + + if(loc_name_len == 0) { + loc_name = (char *)intl_locale_get_default(); + } + + array_init( return_value ); + + grOffset = findOffset( LOC_GRANDFATHERED , loc_name ); + if( grOffset >= 0 ){ + add_assoc_string( return_value , LOC_GRANDFATHERED_LANG_TAG, (char *)loc_name); + } + else{ + /* Not grandfathered */ + add_array_entry( loc_name , return_value , LOC_LANG_TAG); + add_array_entry( loc_name , return_value , LOC_SCRIPT_TAG); + add_array_entry( loc_name , return_value , LOC_REGION_TAG); + add_array_entry( loc_name , return_value , LOC_VARIANT_TAG); + add_array_entry( loc_name , return_value , LOC_PRIVATE_TAG); + } +} +/* }}} */ + +/* {{{ gets an array containing the list of variants, or null */ +U_CFUNC PHP_FUNCTION(locale_get_all_variants) +{ + char* loc_name = NULL; + size_t loc_name_len = 0; + + int result = 0; + char* token = NULL; + zend_string* variant = NULL; + char* saved_ptr = NULL; + + intl_error_reset( NULL ); + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_PATH(loc_name, loc_name_len) + ZEND_PARSE_PARAMETERS_END(); + + if(loc_name_len == 0) { + loc_name = (char *)intl_locale_get_default(); + loc_name_len = strlen(loc_name); + } + + INTL_CHECK_LOCALE_LEN(loc_name_len); + + array_init( return_value ); + + /* If the locale is grandfathered, stop, no variants */ + if( findOffset( LOC_GRANDFATHERED , loc_name ) >= 0 ){ + /* ("Grandfathered Tag. No variants."); */ + } + else { + /* Call ICU variant */ + variant = get_icu_value_internal( loc_name , LOC_VARIANT_TAG , &result ,0); + if( result > 0 && variant){ + /* Tokenize on the "_" or "-" */ + token = php_strtok_r( variant->val , DELIMITER , &saved_ptr); + add_next_index_stringl( return_value, token , strlen(token)); + /* tokenize on the "_" or "-" and stop at singleton if any */ + while( (token = php_strtok_r(NULL , DELIMITER, &saved_ptr)) && (strlen(token)>1) ){ + add_next_index_stringl( return_value, token , strlen(token)); + } + } + if( variant ){ + zend_string_release_ex( variant, 0 ); + } + } + + +} +/* }}} */ + +/* {{{ Converts to lower case and also replaces all hyphens with the underscore */ +static int strToMatch(const char* str ,char *retstr) +{ + char* anchor = NULL; + const char* anchor1 = NULL; + int result = 0; + + if( (!str) || str[0] == '\0'){ + return result; + } else { + anchor = retstr; + anchor1 = str; + while( (*str)!='\0' ){ + if( *str == '-' ){ + *retstr = '_'; + } else { + *retstr = tolower(*str); + } + str++; + retstr++; + } + *retstr = '\0'; + retstr= anchor; + str= anchor1; + result = 1; + } + + return(result); +} +/* }}} */ + +/* {{{ 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 */ +U_CFUNC PHP_FUNCTION(locale_filter_matches) +{ + char* lang_tag = NULL; + size_t lang_tag_len = 0; + char* loc_range = NULL; + size_t loc_range_len = 0; + + int result = 0; + char* token = 0; + char* chrcheck = NULL; + + zend_string* can_lang_tag = NULL; + zend_string* can_loc_range = NULL; + + char* cur_lang_tag = NULL; + char* cur_loc_range = NULL; + + bool boolCanonical = 0; + UErrorCode status = U_ZERO_ERROR; + + intl_error_reset( NULL ); + + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_PATH(lang_tag, lang_tag_len) + Z_PARAM_PATH(loc_range, loc_range_len) + Z_PARAM_OPTIONAL + Z_PARAM_BOOL(boolCanonical) + ZEND_PARSE_PARAMETERS_END(); + + if(loc_range_len == 0) { + loc_range = (char *)intl_locale_get_default(); + loc_range_len = strlen(loc_range); + } + + if( strcmp(loc_range,"*")==0){ + RETURN_TRUE; + } + + INTL_CHECK_LOCALE_LEN(loc_range_len); + INTL_CHECK_LOCALE_LEN(lang_tag_len); + + if( boolCanonical ){ + /* 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, "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) { + zend_string_release_ex( can_loc_range, false ); + intl_error_set(NULL, status, "unable to canonicalize lang_tag"); + RETURN_FALSE; + } + + /* Convert to lower case for case-insensitive comparison */ + 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); + if( result == 0) { + efree( cur_lang_tag ); + zend_string_release_ex( can_lang_tag, 0 ); + RETURN_FALSE; + } + + 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 ); + zend_string_release_ex( can_lang_tag, 0 ); + efree( cur_loc_range ); + zend_string_release_ex( can_loc_range, 0 ); + RETURN_FALSE; + } + + /* check if prefix */ + token = strstr( cur_lang_tag , cur_loc_range ); + + if( token && (token==cur_lang_tag) ){ + /* check if the char. after match is SEPARATOR */ + chrcheck = token + (strlen(cur_loc_range)); + if( isIDSeparator(*chrcheck) || isKeywordSeparator(*chrcheck) || isEndOfTag(*chrcheck) ){ + efree( cur_lang_tag ); + efree( cur_loc_range ); + if( can_lang_tag){ + zend_string_release_ex( can_lang_tag, 0 ); + } + if( can_loc_range){ + zend_string_release_ex( can_loc_range, 0 ); + } + RETURN_TRUE; + } + } + + /* No prefix as loc_range */ + if( cur_lang_tag){ + efree( cur_lang_tag ); + } + if( cur_loc_range){ + efree( cur_loc_range ); + } + if( can_lang_tag){ + zend_string_release_ex( can_lang_tag, 0 ); + } + if( can_loc_range){ + zend_string_release_ex( can_loc_range, 0 ); + } + RETURN_FALSE; + + } /* end of if isCanonical */ + else{ + /* Convert to lower case for case-insensitive comparison */ + 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 = reinterpret_cast(ecalloc( 1, strlen(loc_range ) + 1)); + result = strToMatch( loc_range , cur_loc_range ); + if( result == 0) { + efree( cur_lang_tag ); + efree( cur_loc_range ); + RETURN_FALSE; + } + + /* check if prefix */ + token = strstr( cur_lang_tag , cur_loc_range ); + + if( token && (token==cur_lang_tag) ){ + /* check if the char. after match is SEPARATOR */ + chrcheck = token + (strlen(cur_loc_range)); + if( isIDSeparator(*chrcheck) || isEndOfTag(*chrcheck) ){ + efree( cur_lang_tag ); + efree( cur_loc_range ); + RETURN_TRUE; + } + } + + /* No prefix as loc_range */ + if( cur_lang_tag){ + efree( cur_lang_tag ); + } + if( cur_loc_range){ + efree( cur_loc_range ); + } + RETURN_FALSE; + + } +} +/* }}} */ + +static void array_cleanup( char* arr[] , int arr_size) +{ + int i=0; + for( i=0; i< arr_size; i++ ){ + if( arr[i*2] ){ + efree( arr[i*2]); + } + } + efree(arr); +} + +#define LOOKUP_CLEAN_RETURN(value) array_cleanup(cur_arr, cur_arr_len); return (value) +/* {{{ +* returns the lookup result to lookup_loc_range_src_php +* internal function +*/ +static zend_string* lookup_loc_range(const char* loc_range, HashTable* hash_arr, int canonicalize ) +{ + int i = 0; + int cur_arr_len = 0; + int result = 0; + + zend_string* lang_tag = NULL; + zval* ele_value = NULL; + + char* cur_loc_range = NULL; + zend_string* can_loc_range = NULL; + zend_off_t saved_pos = 0; + + zend_string* return_value = NULL; + + 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 */ + if(Z_TYPE_P(ele_value)!= IS_STRING) { + /* element value is not a string */ + zend_argument_type_error(2, "must only contain string values"); + LOOKUP_CLEAN_RETURN(NULL); + } + if (zend_str_has_nul_byte(Z_STR_P(ele_value))) { + zend_argument_value_error(2, "must not contain any null bytes"); + LOOKUP_CLEAN_RETURN(NULL); + } + 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, "unable to canonicalize lang_tag"); + LOOKUP_CLEAN_RETURN(NULL); + } + cur_arr[cur_arr_len*2+1] = Z_STRVAL_P(ele_value); + cur_arr_len++ ; + } ZEND_HASH_FOREACH_END(); /* end of for */ + + /* Canonicalize array elements */ + if(canonicalize) { + for(i=0; ival[0]) { + if(lang_tag) { + zend_string_release_ex(lang_tag, 0); + } + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "unable to canonicalize lang_tag"); + LOOKUP_CLEAN_RETURN(NULL); + } + 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, "unable to canonicalize lang_tag"); + LOOKUP_CLEAN_RETURN(NULL); + } + } + + } + + if(canonicalize) { + /* Canonicalize the loc_range */ + 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, "unable to canonicalize loc_range"); + if(can_loc_range) { + zend_string_release_ex(can_loc_range, 0); + } + LOOKUP_CLEAN_RETURN(NULL); + } else { + loc_range = can_loc_range->val; + } + } + + 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) { + zend_string_release_ex(can_loc_range, 0); + } + if(result == 0) { + efree(cur_loc_range); + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "unable to canonicalize lang_tag"); + LOOKUP_CLEAN_RETURN(NULL); + } + + /* Lookup for the lang_tag match */ + saved_pos = strlen(cur_loc_range); + while(saved_pos > 0) { + for(i=0; i< cur_arr_len; i++){ + if(cur_arr[i*2] != NULL && strlen(cur_arr[i*2]) == saved_pos && strncmp(cur_loc_range, cur_arr[i*2], saved_pos) == 0) { + /* Match found */ + char *str = canonicalize ? cur_arr[i*2] : cur_arr[i*2+1]; + return_value = zend_string_init(str, strlen(str), 0); + efree(cur_loc_range); + LOOKUP_CLEAN_RETURN(return_value); + } + } + saved_pos = getStrrtokenPos(cur_loc_range, saved_pos); + } + + /* Match not found */ + efree(cur_loc_range); + LOOKUP_CLEAN_RETURN(NULL); +} +/* }}} */ + +/* {{{ Searches the items in $langtag for the best match to the language +* range +*/ +/* }}} */ +/* {{{ Searches the items in $langtag for the best match to the language +* range +*/ +U_CFUNC PHP_FUNCTION(locale_lookup) +{ + zend_string* fallback_loc_str = NULL; + char* loc_range = NULL; + size_t loc_range_len = 0; + + zval* arr = NULL; + HashTable* hash_arr = NULL; + bool boolCanonical = 0; + zend_string* result_str = NULL; + + intl_error_reset( NULL ); + + ZEND_PARSE_PARAMETERS_START(2, 4) + Z_PARAM_ARRAY(arr) + Z_PARAM_PATH(loc_range, loc_range_len) + Z_PARAM_OPTIONAL + Z_PARAM_BOOL(boolCanonical) + Z_PARAM_PATH_STR_OR_NULL(fallback_loc_str) + ZEND_PARSE_PARAMETERS_END(); + + if(loc_range_len == 0) { + if(fallback_loc_str) { + loc_range = ZSTR_VAL(fallback_loc_str); + loc_range_len = ZSTR_LEN(fallback_loc_str); + } else { + loc_range = (char *)intl_locale_get_default(); + loc_range_len = strlen(loc_range); + } + } + + hash_arr = Z_ARRVAL_P(arr); + + INTL_CHECK_LOCALE_LEN(loc_range_len); + + if( !hash_arr || zend_hash_num_elements( hash_arr ) == 0 ) { + RETURN_EMPTY_STRING(); + } + + result_str = lookup_loc_range(loc_range, hash_arr, boolCanonical); + if(result_str == NULL || ZSTR_VAL(result_str)[0] == '\0') { + if( fallback_loc_str ) { + result_str = zend_string_copy(fallback_loc_str); + } else { + RETURN_EMPTY_STRING(); + } + } + + RETURN_STR(result_str); +} +/* }}} */ + +/* {{{ Tries to find out best available locale based on HTTP "Accept-Language" header */ +U_CFUNC PHP_FUNCTION(locale_accept_from_http) +{ + UEnumeration *available; + char *http_accept = NULL; + size_t http_accept_len; + UErrorCode status = U_ZERO_ERROR; + int len; + char resultLocale[INTL_MAX_LOCALE_LEN+1]; + UAcceptResult outResult; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STRING(http_accept, http_accept_len) + ZEND_PARSE_PARAMETERS_END(); + if(http_accept_len > ULOC_FULLNAME_CAPACITY) { + /* check each fragment, if any bigger than capacity, can't do it due to bug #72533 */ + char *start = http_accept; + char *end; + size_t len; + do { + end = strchr(start, ','); + len = end ? end-start : http_accept_len-(start-http_accept); + if(len > ULOC_FULLNAME_CAPACITY) { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "locale string too long"); + RETURN_FALSE; + } + if(end) { + start = end+1; + } + } while(end != NULL); + } + + available = ures_openAvailableLocales(NULL, &status); + 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, "failed to find acceptable locale"); + if (len < 0 || outResult == ULOC_ACCEPT_FAILED) { + RETURN_FALSE; + } + RETURN_STRINGL(resultLocale, len); +} +/* }}} */ + +U_CFUNC PHP_FUNCTION(locale_is_right_to_left) +{ + char *locale; + size_t locale_len; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_PATH(locale, locale_len) + ZEND_PARSE_PARAMETERS_END(); + + if (!locale_len) { + locale = (char *)intl_locale_get_default(); + } + + RETURN_BOOL(uloc_isRightToLeft(locale)); +} + +U_CFUNC PHP_FUNCTION(locale_add_likely_subtags) +{ + char *locale, maximized_locale[ULOC_FULLNAME_CAPACITY]; + UErrorCode status = U_ZERO_ERROR; + size_t locale_len; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_PATH(locale, locale_len) + ZEND_PARSE_PARAMETERS_END(); + + if (!locale_len) { + locale = (char *)intl_locale_get_default(); + } + + int32_t maximized_locale_len = uloc_addLikelySubtags(locale, maximized_locale, sizeof(maximized_locale), &status); + INTL_CHECK_STATUS(status, "invalid locale"); + if (maximized_locale_len < 0) { + RETURN_FALSE; + } + + RETURN_STRINGL(maximized_locale, maximized_locale_len); +} + +U_CFUNC PHP_FUNCTION(locale_minimize_subtags) +{ + char *locale, minimized_locale[ULOC_FULLNAME_CAPACITY]; + UErrorCode status = U_ZERO_ERROR; + size_t locale_len; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_PATH(locale, locale_len) + ZEND_PARSE_PARAMETERS_END(); + + if (!locale_len) { + locale = (char *)intl_locale_get_default(); + } + + int32_t minimized_locale_len = uloc_minimizeSubtags(locale, minimized_locale, sizeof(minimized_locale), &status); + INTL_CHECK_STATUS(status, "invalid locale"); + if (minimized_locale_len < 0) { + RETURN_FALSE; + } + + RETURN_STRINGL(minimized_locale, minimized_locale_len); +} diff --git a/ext/intl/msgformat/msgformat.c b/ext/intl/msgformat/msgformat.c deleted file mode 100644 index 51643d86d458a..0000000000000 --- a/ext/intl/msgformat/msgformat.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Stanislav Malyshev | - +----------------------------------------------------------------------+ - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#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) -{ - char* locale; - char* pattern; - size_t locale_len = 0, pattern_len = 0; - UChar* spattern = NULL; - int spattern_len = 0; - zval* object; - MessageFormatter_object* mfo; - UParseError parse_error; - intl_error_reset( NULL ); - - object = return_value; - ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_STRING(locale, locale_len) - 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"); - } else { - spattern_len = 0; - spattern = NULL; - } - - if(locale_len == 0) { - locale = (char *)intl_locale_get_default(); - } - -#ifdef MSG_FORMAT_QUOTE_APOS - if(msgformat_fix_quotes(&spattern, &spattern_len, &INTL_DATA_ERROR_CODE(mfo)) != SUCCESS) { - INTL_CTOR_CHECK_STATUS(mfo, "msgfmt_create: error converting pattern to quote-friendly format"); - } -#endif - - if ((mfo)->mf_data.orig_format) { - msgformat_data_free(&mfo->mf_data); - } - - (mfo)->mf_data.orig_format = estrndup(pattern, pattern_len); - (mfo)->mf_data.orig_format_len = pattern_len; - - /* Create an ICU message formatter. */ - MSG_FORMAT_OBJECT(mfo) = umsg_open(spattern, spattern_len, locale, &parse_error, &INTL_DATA_ERROR_CODE(mfo)); - - if(spattern) { - efree(spattern); - } - - if (INTL_DATA_ERROR_CODE( mfo ) == U_PATTERN_SYNTAX_ERROR) { - char *msg = NULL; - smart_str parse_error_str; - parse_error_str = intl_parse_error_to_string( &parse_error ); - spprintf( &msg, 0, "pattern syntax error (%s)", parse_error_str.s? ZSTR_VAL(parse_error_str.s) : "unknown parser 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 ); - - efree( msg ); - return FAILURE; - } - - INTL_CTOR_CHECK_STATUS(mfo, "msgfmt_create: message formatter creation failed"); - return SUCCESS; -} -/* }}} */ - -/* {{{ Create formatter. */ -PHP_FUNCTION( msgfmt_create ) -{ - object_init_ex( return_value, MessageFormatter_ce_ptr ); - if (msgfmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL, NULL) == FAILURE) { - zval_ptr_dtor(return_value); - RETURN_NULL(); - } -} -/* }}} */ - -/* {{{ MessageFormatter object constructor. */ -PHP_METHOD( MessageFormatter, __construct ) -{ - zend_error_handling error_handling; - bool error_handling_replaced = 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); - } -} -/* }}} */ - -/* {{{ Get formatter's last error code. */ -PHP_FUNCTION( msgfmt_get_error_code ) -{ - zval* object = NULL; - MessageFormatter_object* mfo = NULL; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", - &object, MessageFormatter_ce_ptr ) == FAILURE ) - { - RETURN_THROWS(); - } - - mfo = Z_INTL_MESSAGEFORMATTER_P( object ); - - /* Return formatter's last error code. */ - RETURN_LONG( INTL_DATA_ERROR_CODE(mfo) ); -} -/* }}} */ - -/* {{{ Get text description for formatter's last error code. */ -PHP_FUNCTION( msgfmt_get_error_message ) -{ - zend_string* message = NULL; - zval* object = NULL; - MessageFormatter_object* mfo = NULL; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", - &object, MessageFormatter_ce_ptr ) == FAILURE ) - { - RETURN_THROWS(); - } - - mfo = Z_INTL_MESSAGEFORMATTER_P( object ); - - /* Return last error message. */ - message = intl_error_get_message( &mfo->mf_data.error ); - RETURN_STR(message); -} -/* }}} */ diff --git a/ext/intl/msgformat/msgformat.cpp b/ext/intl/msgformat/msgformat.cpp new file mode 100644 index 0000000000000..a9e1f71bfc60a --- /dev/null +++ b/ext/intl/msgformat/msgformat.cpp @@ -0,0 +1,171 @@ +/* + +----------------------------------------------------------------------+ + | 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: Stanislav Malyshev | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#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) +{ + char* locale; + char* pattern; + size_t locale_len = 0, pattern_len = 0; + UChar* spattern = NULL; + int spattern_len = 0; + zval* object; + MessageFormatter_object* mfo; + UParseError parse_error; + intl_error_reset( NULL ); + + object = return_value; + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_STRING(locale, locale_len) + Z_PARAM_STRING(pattern, pattern_len) + ZEND_PARSE_PARAMETERS_END_EX(return FAILURE); + + 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, "error converting pattern to UTF-16"); + } else { + spattern_len = 0; + spattern = NULL; + } + + if(locale_len == 0) { + locale = (char *)intl_locale_get_default(); + } + +#ifdef MSG_FORMAT_QUOTE_APOS + if(msgformat_fix_quotes(&spattern, &spattern_len, &INTL_DATA_ERROR_CODE(mfo)) != SUCCESS) { + INTL_CTOR_CHECK_STATUS(mfo, "msgfmt_create: error converting pattern to quote-friendly format"); + } +#endif + + if ((mfo)->mf_data.orig_format) { + msgformat_data_free(&mfo->mf_data); + } + + (mfo)->mf_data.orig_format = estrndup(pattern, pattern_len); + (mfo)->mf_data.orig_format_len = pattern_len; + + /* Create an ICU message formatter. */ + MSG_FORMAT_OBJECT(mfo) = umsg_open(spattern, spattern_len, locale, &parse_error, &INTL_DATA_ERROR_CODE(mfo)); + + if(spattern) { + efree(spattern); + } + + if (INTL_DATA_ERROR_CODE( mfo ) == U_PATTERN_SYNTAX_ERROR) { + char *msg = NULL; + smart_str parse_error_str; + parse_error_str = intl_parse_error_to_string( &parse_error ); + spprintf( &msg, 0, "pattern syntax error (%s)", parse_error_str.s? ZSTR_VAL(parse_error_str.s) : "unknown parser 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); + + efree( msg ); + return FAILURE; + } + + INTL_CTOR_CHECK_STATUS(mfo, "message formatter creation failed"); + return SUCCESS; +} +/* }}} */ + +/* {{{ Create formatter. */ +U_CFUNC PHP_FUNCTION( msgfmt_create ) +{ + object_init_ex( return_value, MessageFormatter_ce_ptr ); + if (msgfmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU) == FAILURE) { + zval_ptr_dtor(return_value); + RETURN_NULL(); + } +} +/* }}} */ + +/* {{{ MessageFormatter object constructor. */ +U_CFUNC PHP_METHOD( MessageFormatter, __construct ) +{ + 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) == 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. */ +U_CFUNC PHP_FUNCTION( msgfmt_get_error_code ) +{ + zval* object = NULL; + MessageFormatter_object* mfo = NULL; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", + &object, MessageFormatter_ce_ptr ) == FAILURE ) + { + RETURN_THROWS(); + } + + mfo = Z_INTL_MESSAGEFORMATTER_P( object ); + + /* Return formatter's last error code. */ + RETURN_LONG( INTL_DATA_ERROR_CODE(mfo) ); +} +/* }}} */ + +/* {{{ Get text description for formatter's last error code. */ +U_CFUNC PHP_FUNCTION( msgfmt_get_error_message ) +{ + zend_string* message = NULL; + zval* object = NULL; + MessageFormatter_object* mfo = NULL; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", + &object, MessageFormatter_ce_ptr ) == FAILURE ) + { + RETURN_THROWS(); + } + + mfo = Z_INTL_MESSAGEFORMATTER_P( object ); + + /* Return last error message. */ + message = intl_error_get_message( &mfo->mf_data.error ); + RETURN_STR(message); +} +/* }}} */ diff --git a/ext/intl/msgformat/msgformat_attr.c b/ext/intl/msgformat/msgformat_attr.c deleted file mode 100644 index b56bf360d114d..0000000000000 --- a/ext/intl/msgformat/msgformat_attr.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Stanislav Malyshev | - +----------------------------------------------------------------------+ - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#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 ) -{ - MSG_FORMAT_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", &object, MessageFormatter_ce_ptr ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - MSG_FORMAT_METHOD_FETCH_OBJECT; - - if(mfo->mf_data.orig_format) { - RETURN_STRINGL(mfo->mf_data.orig_format, mfo->mf_data.orig_format_len); - } - - RETURN_FALSE; -} -/* }}} */ - -/* {{{ Set formatter pattern. */ -PHP_FUNCTION( msgfmt_set_pattern ) -{ - char* value = NULL; - size_t value_len = 0; - int32_t spattern_len = 0; - UChar* spattern = NULL; - UParseError spattern_error = {0}; - MSG_FORMAT_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Os", - &object, MessageFormatter_ce_ptr, &value, &value_len ) == FAILURE ) - { - RETURN_THROWS(); - } - - MSG_FORMAT_METHOD_FETCH_OBJECT; - - /* Convert given pattern to UTF-16. */ - intl_convert_utf8_to_utf16(&spattern, &spattern_len, value, value_len, &INTL_DATA_ERROR_CODE(mfo)); - INTL_METHOD_CHECK_STATUS(mfo, "Error converting pattern to UTF-16" ); - -#ifdef MSG_FORMAT_QUOTE_APOS - if(msgformat_fix_quotes(&spattern, &spattern_len, &INTL_DATA_ERROR_CODE(mfo)) != SUCCESS) { - intl_error_set( NULL, U_INVALID_FORMAT_ERROR, - "msgfmt_set_pattern: error converting pattern to quote-friendly format", 0 ); - RETURN_FALSE; - } -#endif - - umsg_applyPattern(MSG_FORMAT_OBJECT(mfo), spattern, spattern_len, &spattern_error, &INTL_DATA_ERROR_CODE(mfo)); - if (spattern) { - efree(spattern); - } - 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); - efree(msg); - RETURN_FALSE; - } - - if(mfo->mf_data.orig_format) { - efree(mfo->mf_data.orig_format); - } - mfo->mf_data.orig_format = estrndup(value, value_len); - mfo->mf_data.orig_format_len = value_len; - /* invalidate cached format types */ - if (mfo->mf_data.arg_types) { - zend_hash_destroy(mfo->mf_data.arg_types); - efree(mfo->mf_data.arg_types); - mfo->mf_data.arg_types = NULL; - } - - RETURN_TRUE; -} -/* }}} */ - -/* {{{ Get formatter locale. */ -PHP_FUNCTION( msgfmt_get_locale ) -{ - char *loc; - MSG_FORMAT_METHOD_INIT_VARS; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", - &object, MessageFormatter_ce_ptr ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - MSG_FORMAT_METHOD_FETCH_OBJECT; - - loc = (char *)umsg_getLocale(MSG_FORMAT_OBJECT(mfo)); - RETURN_STRING(loc); -} -/* }}} */ diff --git a/ext/intl/msgformat/msgformat_attr.cpp b/ext/intl/msgformat/msgformat_attr.cpp new file mode 100644 index 0000000000000..e7ec006e5e793 --- /dev/null +++ b/ext/intl/msgformat/msgformat_attr.cpp @@ -0,0 +1,128 @@ +/* + +----------------------------------------------------------------------+ + | 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: Stanislav Malyshev | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +extern "C" { +#include "php_intl.h" +#include "msgformat_class.h" +#include "msgformat_data.h" +#include "intl_convert.h" +} + +#include + +/* {{{ Get formatter pattern. */ +U_CFUNC PHP_FUNCTION( msgfmt_get_pattern ) +{ + MSG_FORMAT_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", &object, MessageFormatter_ce_ptr ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + MSG_FORMAT_METHOD_FETCH_OBJECT; + + if(mfo->mf_data.orig_format) { + RETURN_STRINGL(mfo->mf_data.orig_format, mfo->mf_data.orig_format_len); + } + + RETURN_FALSE; +} +/* }}} */ + +/* {{{ Set formatter pattern. */ +U_CFUNC PHP_FUNCTION( msgfmt_set_pattern ) +{ + char* value = NULL; + size_t value_len = 0; + int32_t spattern_len = 0; + UChar* spattern = NULL; + UParseError spattern_error = {0}; + MSG_FORMAT_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Os", + &object, MessageFormatter_ce_ptr, &value, &value_len ) == FAILURE ) + { + RETURN_THROWS(); + } + + MSG_FORMAT_METHOD_FETCH_OBJECT; + + /* Convert given pattern to UTF-16. */ + intl_convert_utf8_to_utf16(&spattern, &spattern_len, value, value_len, &INTL_DATA_ERROR_CODE(mfo)); + INTL_METHOD_CHECK_STATUS(mfo, "Error converting pattern to UTF-16" ); + +#ifdef MSG_FORMAT_QUOTE_APOS + if(msgformat_fix_quotes(&spattern, &spattern_len, &INTL_DATA_ERROR_CODE(mfo)) != SUCCESS) { + intl_error_set( NULL, U_INVALID_FORMAT_ERROR, + "msgfmt_set_pattern: error converting pattern to quote-friendly format", 0 ); + RETURN_FALSE; + } +#endif + + umsg_applyPattern(MSG_FORMAT_OBJECT(mfo), spattern, spattern_len, &spattern_error, &INTL_DATA_ERROR_CODE(mfo)); + if (spattern) { + efree(spattern); + } + 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); + efree(msg); + RETURN_FALSE; + } + + if(mfo->mf_data.orig_format) { + efree(mfo->mf_data.orig_format); + } + mfo->mf_data.orig_format = estrndup(value, value_len); + mfo->mf_data.orig_format_len = value_len; + /* invalidate cached format types */ + if (mfo->mf_data.arg_types) { + zend_hash_destroy(mfo->mf_data.arg_types); + efree(mfo->mf_data.arg_types); + mfo->mf_data.arg_types = NULL; + } + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ Get formatter locale. */ +U_CFUNC PHP_FUNCTION( msgfmt_get_locale ) +{ + char *loc; + MSG_FORMAT_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", + &object, MessageFormatter_ce_ptr ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + MSG_FORMAT_METHOD_FETCH_OBJECT; + + loc = (char *)umsg_getLocale(MSG_FORMAT_OBJECT(mfo)); + RETURN_STRING(loc); +} +/* }}} */ diff --git a/ext/intl/msgformat/msgformat_class.c b/ext/intl/msgformat/msgformat_class.c deleted file mode 100644 index 4e0766a911b9a..0000000000000 --- a/ext/intl/msgformat/msgformat_class.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Stanislav Malyshev | - +----------------------------------------------------------------------+ - */ - -#include - -#include "msgformat_class.h" -#include "php_intl.h" -#include "msgformat_data.h" -#include "msgformat_arginfo.h" - -#include - -zend_class_entry *MessageFormatter_ce_ptr = NULL; -static zend_object_handlers MessageFormatter_handlers; - -/* - * Auxiliary functions needed by objects of 'MessageFormatter' class - */ - -/* {{{ MessageFormatter_objects_free */ -void MessageFormatter_object_free( zend_object *object ) -{ - MessageFormatter_object* mfo = php_intl_messageformatter_fetch_object(object); - - zend_object_std_dtor( &mfo->zo ); - - msgformat_data_free( &mfo->mf_data ); -} -/* }}} */ - -/* {{{ MessageFormatter_object_create */ -zend_object *MessageFormatter_object_create(zend_class_entry *ce) -{ - MessageFormatter_object* intern; - - intern = 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); - - return &intern->zo; -} -/* }}} */ - -/* {{{ MessageFormatter_object_clone */ -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); - MessageFormatter_object *new_mfo = php_intl_messageformatter_fetch_object(new_obj); - - /* clone standard parts */ - zend_objects_clone_members(&new_mfo->zo, &mfo->zo); - - /* 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); - - if (U_FAILURE(error)) { - zend_throw_error(NULL, "Failed to clone MessageFormatter"); - } - } else { - zend_throw_error(NULL, "Cannot clone uninitialized MessageFormatter"); - } - return new_obj; -} -/* }}} */ - -/* - * 'MessageFormatter' class registration structures & functions - */ - -/* {{{ msgformat_register_class - * Initialize 'MessageFormatter' class - */ -void msgformat_register_class( void ) -{ - /* Create and register 'MessageFormatter' class. */ - MessageFormatter_ce_ptr = register_class_MessageFormatter(); - MessageFormatter_ce_ptr->create_object = MessageFormatter_object_create; - MessageFormatter_ce_ptr->default_object_handlers = &MessageFormatter_handlers; - - memcpy(&MessageFormatter_handlers, &std_object_handlers, - sizeof MessageFormatter_handlers); - MessageFormatter_handlers.offset = XtOffsetOf(MessageFormatter_object, zo); - MessageFormatter_handlers.clone_obj = MessageFormatter_object_clone; - MessageFormatter_handlers.free_obj = MessageFormatter_object_free; -} -/* }}} */ diff --git a/ext/intl/msgformat/msgformat_class.cpp b/ext/intl/msgformat/msgformat_class.cpp new file mode 100644 index 0000000000000..e762febf0d1b3 --- /dev/null +++ b/ext/intl/msgformat/msgformat_class.cpp @@ -0,0 +1,103 @@ +/* + +----------------------------------------------------------------------+ + | 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: Stanislav Malyshev | + +----------------------------------------------------------------------+ + */ + +#include + +extern "C" { +#include "msgformat_class.h" +#include "php_intl.h" +#include "msgformat_data.h" +#include "msgformat_arginfo.h" +} + +#include + +zend_class_entry *MessageFormatter_ce_ptr = NULL; +static zend_object_handlers MessageFormatter_handlers; + +/* + * Auxiliary functions needed by objects of 'MessageFormatter' class + */ + +/* {{{ MessageFormatter_objects_free */ +U_CFUNC void MessageFormatter_object_free( zend_object *object ) +{ + MessageFormatter_object* mfo = php_intl_messageformatter_fetch_object(object); + + zend_object_std_dtor( &mfo->zo ); + + msgformat_data_free( &mfo->mf_data ); +} +/* }}} */ + +/* {{{ MessageFormatter_object_create */ +U_CFUNC zend_object *MessageFormatter_object_create(zend_class_entry *ce) +{ + MessageFormatter_object* intern; + + 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); + + return &intern->zo; +} +/* }}} */ + +/* {{{ MessageFormatter_object_clone */ +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); + MessageFormatter_object *new_mfo = php_intl_messageformatter_fetch_object(new_obj); + + /* clone standard parts */ + zend_objects_clone_members(&new_mfo->zo, &mfo->zo); + + /* clone formatter object */ + if (MSG_FORMAT_OBJECT(mfo) != NULL) { + UErrorCode error = U_ZERO_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"); + } + } else { + zend_throw_error(NULL, "Cannot clone uninitialized MessageFormatter"); + } + return new_obj; +} +/* }}} */ + +/* + * 'MessageFormatter' class registration structures & functions + */ + +/* {{{ msgformat_register_class + * Initialize 'MessageFormatter' class + */ +void msgformat_register_class( void ) +{ + /* Create and register 'MessageFormatter' class. */ + MessageFormatter_ce_ptr = register_class_MessageFormatter(); + MessageFormatter_ce_ptr->create_object = MessageFormatter_object_create; + MessageFormatter_ce_ptr->default_object_handlers = &MessageFormatter_handlers; + + memcpy(&MessageFormatter_handlers, &std_object_handlers, + sizeof MessageFormatter_handlers); + MessageFormatter_handlers.offset = XtOffsetOf(MessageFormatter_object, zo); + MessageFormatter_handlers.clone_obj = MessageFormatter_object_clone; + MessageFormatter_handlers.free_obj = MessageFormatter_object_free; +} +/* }}} */ diff --git a/ext/intl/msgformat/msgformat_data.c b/ext/intl/msgformat/msgformat_data.c deleted file mode 100644 index 5d170d25945fa..0000000000000 --- a/ext/intl/msgformat/msgformat_data.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Stanislav Malyshev | - +----------------------------------------------------------------------+ - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include "msgformat_data.h" - -#include "msgformat_class.h" - -/* {{{ void msgformat_data_init( msgformat_data* mf_data ) - * Initialize internals of msgformat_data. - */ -void msgformat_data_init( msgformat_data* mf_data ) -{ - if( !mf_data ) - return; - - mf_data->umsgf = NULL; - mf_data->orig_format = NULL; - mf_data->arg_types = NULL; - mf_data->tz_set = 0; - intl_error_reset( &mf_data->error ); -} -/* }}} */ - -/* {{{ void msgformat_data_free( msgformat_data* mf_data ) - * Clean up memory allocated for msgformat_data - */ -void msgformat_data_free(msgformat_data* mf_data) -{ - if (!mf_data) - return; - - if (mf_data->umsgf) - umsg_close(mf_data->umsgf); - - if (mf_data->orig_format) { - efree(mf_data->orig_format); - mf_data->orig_format = NULL; - } - - if (mf_data->arg_types) { - zend_hash_destroy(mf_data->arg_types); - efree(mf_data->arg_types); - mf_data->arg_types = NULL; - } - - mf_data->umsgf = NULL; - intl_error_reset(&mf_data->error); -} -/* }}} */ - -/* {{{ msgformat_data* msgformat_data_create() - * Allocate memory for msgformat_data and initialize it with default values. - */ -msgformat_data* msgformat_data_create( void ) -{ - msgformat_data* mf_data = ecalloc( 1, sizeof(msgformat_data) ); - - msgformat_data_init( mf_data ); - - return mf_data; -} -/* }}} */ - -#ifdef MSG_FORMAT_QUOTE_APOS -int msgformat_fix_quotes(UChar **spattern, uint32_t *spattern_len, UErrorCode *ec) -{ - if(*spattern && *spattern_len && u_strchr(*spattern, (UChar)'\'')) { - UChar *npattern = safe_emalloc(sizeof(UChar)*2, *spattern_len, sizeof(UChar)); - uint32_t npattern_len; - npattern_len = umsg_autoQuoteApostrophe(*spattern, *spattern_len, npattern, 2*(*spattern_len)+1, ec); - efree(*spattern); - if( U_FAILURE(*ec) ) - { - return FAILURE; - } - npattern = erealloc(npattern, sizeof(UChar)*(npattern_len+1)); - *spattern = npattern; - *spattern_len = npattern_len; - } - return SUCCESS; -} -#endif diff --git a/ext/intl/msgformat/msgformat_data.cpp b/ext/intl/msgformat/msgformat_data.cpp new file mode 100644 index 0000000000000..f8b7ec39601eb --- /dev/null +++ b/ext/intl/msgformat/msgformat_data.cpp @@ -0,0 +1,98 @@ +/* + +----------------------------------------------------------------------+ + | 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: Stanislav Malyshev | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include "msgformat_data.h" + +#include "msgformat_class.h" + +/* {{{ void msgformat_data_init( msgformat_data* mf_data ) + * Initialize internals of msgformat_data. + */ +U_CFUNC void msgformat_data_init( msgformat_data* mf_data ) +{ + if( !mf_data ) + return; + + mf_data->umsgf = NULL; + mf_data->orig_format = NULL; + mf_data->arg_types = NULL; + mf_data->tz_set = 0; + intl_error_reset( &mf_data->error ); +} +/* }}} */ + +/* {{{ void msgformat_data_free( msgformat_data* mf_data ) + * Clean up memory allocated for msgformat_data + */ +U_CFUNC void msgformat_data_free(msgformat_data* mf_data) +{ + if (!mf_data) + return; + + if (mf_data->umsgf) + umsg_close(mf_data->umsgf); + + if (mf_data->orig_format) { + efree(mf_data->orig_format); + mf_data->orig_format = NULL; + } + + if (mf_data->arg_types) { + zend_hash_destroy(mf_data->arg_types); + efree(mf_data->arg_types); + mf_data->arg_types = NULL; + } + + mf_data->umsgf = NULL; + intl_error_reset(&mf_data->error); +} +/* }}} */ + +/* {{{ msgformat_data* msgformat_data_create() + * Allocate memory for msgformat_data and initialize it with default values. + */ +msgformat_data* msgformat_data_create( void ) +{ + msgformat_data* mf_data = reinterpret_cast(ecalloc( 1, sizeof(msgformat_data) )); + + msgformat_data_init( mf_data ); + + return mf_data; +} +/* }}} */ + +#ifdef MSG_FORMAT_QUOTE_APOS +int msgformat_fix_quotes(UChar **spattern, uint32_t *spattern_len, UErrorCode *ec) +{ + if(*spattern && *spattern_len && u_strchr(*spattern, (UChar)'\'')) { + UChar *npattern = safe_emalloc(sizeof(UChar)*2, *spattern_len, sizeof(UChar)); + uint32_t npattern_len; + npattern_len = umsg_autoQuoteApostrophe(*spattern, *spattern_len, npattern, 2*(*spattern_len)+1, ec); + efree(*spattern); + if( U_FAILURE(*ec) ) + { + return FAILURE; + } + npattern = erealloc(npattern, sizeof(UChar)*(npattern_len+1)); + *spattern = npattern; + *spattern_len = npattern_len; + } + return SUCCESS; +} +#endif 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.c deleted file mode 100644 index 46a364c5d3a21..0000000000000 --- a/ext/intl/msgformat/msgformat_format.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Stanislav Malyshev | - +----------------------------------------------------------------------+ - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#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++) -#endif - -/* {{{ */ -static void msgfmt_do_format(MessageFormatter_object *mfo, zval *args, zval *return_value) -{ - UChar* formatted = NULL; - int32_t formatted_len = 0; - - umsg_format_helper(mfo, Z_ARRVAL_P(args), &formatted, &formatted_len); - - if (U_FAILURE(INTL_DATA_ERROR_CODE(mfo))) { - if (formatted) { - efree(formatted); - } - RETURN_FALSE; - } else { - INTL_METHOD_RETVAL_UTF8(mfo, formatted, formatted_len, 1); - } -} -/* }}} */ - -/* {{{ Format a message. */ -PHP_FUNCTION( msgfmt_format ) -{ - zval *args; - MSG_FORMAT_METHOD_INIT_VARS; - - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Oa", - &object, MessageFormatter_ce_ptr, &args ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object. */ - MSG_FORMAT_METHOD_FETCH_OBJECT; - - msgfmt_do_format(mfo, args, return_value); -} -/* }}} */ - -/* {{{ Format a message. */ -PHP_FUNCTION( msgfmt_format_message ) -{ - zval *args; - UChar *spattern = NULL; - int spattern_len = 0; - char *pattern = NULL; - size_t pattern_len = 0; - const char *slocale = NULL; - size_t slocale_len = 0; - MessageFormatter_object mf; - MessageFormatter_object *mfo = &mf; - UParseError parse_error; - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "ssa", - &slocale, &slocale_len, &pattern, &pattern_len, &args ) == FAILURE ) - { - RETURN_THROWS(); - } - - INTL_CHECK_LOCALE_LEN(slocale_len); - - memset(mfo, 0, sizeof(*mfo)); - msgformat_data_init(&mfo->mf_data); - - if(pattern && pattern_len) { - intl_convert_utf8_to_utf16(&spattern, &spattern_len, pattern, pattern_len, &INTL_DATA_ERROR_CODE(mfo)); - 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 ); - RETURN_FALSE; - } - } else { - spattern_len = 0; - spattern = NULL; - } - - if(slocale_len == 0) { - slocale = intl_locale_get_default(); - } - -#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 ); - RETURN_FALSE; - } -#endif - - /* Create an ICU message formatter. */ - MSG_FORMAT_OBJECT(mfo) = umsg_open(spattern, spattern_len, slocale, &parse_error, &INTL_DATA_ERROR_CODE(mfo)); - if(spattern && spattern_len) { - efree(spattern); - } - - /* Cannot use INTL_METHOD_CHECK_STATUS() as we need to free the message object formatter */ - if (U_FAILURE(INTL_DATA_ERROR_CODE(mfo))) { - if (INTL_DATA_ERROR_CODE( mfo ) == U_PATTERN_SYNTAX_ERROR) { - char *msg = NULL; - smart_str parse_error_str; - parse_error_str = intl_parse_error_to_string( &parse_error ); - spprintf( &msg, 0, "pattern syntax error (%s)", parse_error_str.s? ZSTR_VAL(parse_error_str.s) : "unknown parser error" ); - smart_str_free( &parse_error_str ); - - /* 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 ); - - efree( msg ); - } else { - intl_errors_set_custom_msg(/* intl_error* */ NULL, "Creating message formatter failed", 0 ); - } - umsg_close(MSG_FORMAT_OBJECT(mfo)); - RETURN_FALSE; - } - - msgfmt_do_format(mfo, args, return_value); - - /* drop the temporary formatter */ - msgformat_data_free(&mfo->mf_data); -} -/* }}} */ diff --git a/ext/intl/msgformat/msgformat_format.cpp b/ext/intl/msgformat/msgformat_format.cpp new file mode 100644 index 0000000000000..8e3ec28b389e1 --- /dev/null +++ b/ext/intl/msgformat/msgformat_format.cpp @@ -0,0 +1,156 @@ +/* + +----------------------------------------------------------------------+ + | 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: Stanislav Malyshev | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#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++) +#endif + +/* {{{ */ +static void msgfmt_do_format(MessageFormatter_object *mfo, zval *args, zval *return_value) +{ + UChar* formatted = NULL; + int32_t formatted_len = 0; + + umsg_format_helper(mfo, Z_ARRVAL_P(args), &formatted, &formatted_len); + + if (U_FAILURE(INTL_DATA_ERROR_CODE(mfo))) { + if (formatted) { + efree(formatted); + } + RETURN_FALSE; + } else { + INTL_METHOD_RETVAL_UTF8(mfo, formatted, formatted_len, 1); + } +} +/* }}} */ + +/* {{{ Format a message. */ +U_CFUNC PHP_FUNCTION( msgfmt_format ) +{ + zval *args; + MSG_FORMAT_METHOD_INIT_VARS; + + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Oa", + &object, MessageFormatter_ce_ptr, &args ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object. */ + MSG_FORMAT_METHOD_FETCH_OBJECT; + + msgfmt_do_format(mfo, args, return_value); +} +/* }}} */ + +/* {{{ Format a message. */ +U_CFUNC PHP_FUNCTION( msgfmt_format_message ) +{ + zval *args; + UChar *spattern = NULL; + int spattern_len = 0; + char *pattern = NULL; + size_t pattern_len = 0; + const char *slocale = NULL; + size_t slocale_len = 0; + MessageFormatter_object mf; + MessageFormatter_object *mfo = &mf; + UParseError parse_error; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "ssa", + &slocale, &slocale_len, &pattern, &pattern_len, &args ) == FAILURE ) + { + RETURN_THROWS(); + } + + INTL_CHECK_LOCALE_LEN(slocale_len); + + memset(mfo, 0, sizeof(*mfo)); + msgformat_data_init(&mfo->mf_data); + + if(pattern && pattern_len) { + intl_convert_utf8_to_utf16(&spattern, &spattern_len, pattern, pattern_len, &INTL_DATA_ERROR_CODE(mfo)); + if( U_FAILURE(INTL_DATA_ERROR_CODE((mfo))) ) + { + intl_error_set(/* intl_error* */ NULL, U_ILLEGAL_ARGUMENT_ERROR, + "error converting pattern to UTF-16"); + RETURN_FALSE; + } + } else { + spattern_len = 0; + spattern = NULL; + } + + if(slocale_len == 0) { + slocale = intl_locale_get_default(); + } + +#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"); + RETURN_FALSE; + } +#endif + + /* Create an ICU message formatter. */ + MSG_FORMAT_OBJECT(mfo) = umsg_open(spattern, spattern_len, slocale, &parse_error, &INTL_DATA_ERROR_CODE(mfo)); + if(spattern && spattern_len) { + efree(spattern); + } + + /* Cannot use INTL_METHOD_CHECK_STATUS() as we need to free the message object formatter */ + if (U_FAILURE(INTL_DATA_ERROR_CODE(mfo))) { + if (INTL_DATA_ERROR_CODE( mfo ) == U_PATTERN_SYNTAX_ERROR) { + char *msg = NULL; + smart_str parse_error_str; + parse_error_str = intl_parse_error_to_string( &parse_error ); + spprintf( &msg, 0, "pattern syntax error (%s)", parse_error_str.s? ZSTR_VAL(parse_error_str.s) : "unknown parser error" ); + smart_str_free( &parse_error_str ); + + /* 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); + + efree( msg ); + } else { + intl_errors_set_custom_msg(/* intl_error* */ NULL, "Creating message formatter failed"); + } + umsg_close(MSG_FORMAT_OBJECT(mfo)); + RETURN_FALSE; + } + + msgfmt_do_format(mfo, args, return_value); + + /* drop the temporary formatter */ + msgformat_data_free(&mfo->mf_data); +} +/* }}} */ diff --git a/ext/intl/msgformat/msgformat_helpers.cpp b/ext/intl/msgformat/msgformat_helpers.cpp index fbd85b857f3bc..25e8dbf869685 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,8 @@ 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); + zend_tmp_string_release(tmp_str); + intl_errors_set(&err, err.code, message); efree(message); delete text; continue; @@ -481,7 +480,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 +489,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 +508,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 +523,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 +532,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 +543,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 +577,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 +600,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 +608,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.c deleted file mode 100644 index 80ede995c42e7..0000000000000 --- a/ext/intl/msgformat/msgformat_parse.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Stanislav Malyshev | - +----------------------------------------------------------------------+ - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#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) -{ - zval *fargs; - int count = 0; - int i; - UChar *usource = NULL; - int usrc_len = 0; - - intl_convert_utf8_to_utf16(&usource, &usrc_len, source, src_len, &INTL_DATA_ERROR_CODE(mfo)); - INTL_METHOD_CHECK_STATUS(mfo, "Converting parse string failed"); - - umsg_parse_helper(MSG_FORMAT_OBJECT(mfo), &count, &fargs, usource, usrc_len, &INTL_DATA_ERROR_CODE(mfo)); - if (usource) { - efree(usource); - } - INTL_METHOD_CHECK_STATUS(mfo, "Parsing failed"); - - array_init_size(return_value, count); - zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); - for(i=0;imf_data); - - if(pattern && pattern_len) { - intl_convert_utf8_to_utf16(&spattern, &spattern_len, pattern, pattern_len, &INTL_DATA_ERROR_CODE(mfo)); - 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 ); - RETURN_FALSE; - } - } else { - spattern_len = 0; - spattern = NULL; - } - - if(slocale_len == 0) { - slocale = (char *)intl_locale_get_default(); - } - -#ifdef MSG_FORMAT_QUOTE_APOS - if(msgformat_fix_quotes(&spattern, &spattern_len, &INTL_DATA_ERROR_CODE(mfo)) != SUCCESS) { - intl_error_set( NULL, U_INVALID_FORMAT_ERROR, - "msgfmt_parse_message: error converting pattern to quote-friendly format", 0 ); - RETURN_FALSE; - } -#endif - - /* Create an ICU message formatter. */ - MSG_FORMAT_OBJECT(mfo) = umsg_open(spattern, spattern_len, slocale, NULL, &INTL_DATA_ERROR_CODE(mfo)); - if(spattern && spattern_len) { - efree(spattern); - } - INTL_METHOD_CHECK_STATUS(mfo, "Creating message formatter failed"); - - msgfmt_do_parse(mfo, source, src_len, return_value); - - /* drop the temporary formatter */ - msgformat_data_free(&mfo->mf_data); -} -/* }}} */ diff --git a/ext/intl/msgformat/msgformat_parse.cpp b/ext/intl/msgformat/msgformat_parse.cpp new file mode 100644 index 0000000000000..28d7ce7108021 --- /dev/null +++ b/ext/intl/msgformat/msgformat_parse.cpp @@ -0,0 +1,140 @@ +/* + +----------------------------------------------------------------------+ + | 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: Stanislav Malyshev | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#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) +{ + zval *fargs; + int count = 0; + int i; + UChar *usource = NULL; + int usrc_len = 0; + + intl_convert_utf8_to_utf16(&usource, &usrc_len, source, src_len, &INTL_DATA_ERROR_CODE(mfo)); + INTL_METHOD_CHECK_STATUS(mfo, "Converting parse string failed"); + + umsg_parse_helper(MSG_FORMAT_OBJECT(mfo), &count, &fargs, usource, usrc_len, &INTL_DATA_ERROR_CODE(mfo)); + if (usource) { + efree(usource); + } + INTL_METHOD_CHECK_STATUS(mfo, "Parsing failed"); + + array_init_size(return_value, count); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); + for(i=0;imf_data); + + if(pattern && pattern_len) { + intl_convert_utf8_to_utf16(&spattern, &spattern_len, pattern, pattern_len, &INTL_DATA_ERROR_CODE(mfo)); + if( U_FAILURE(INTL_DATA_ERROR_CODE((mfo))) ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "error converting pattern to UTF-16"); + RETURN_FALSE; + } + } else { + spattern_len = 0; + spattern = NULL; + } + + if(slocale_len == 0) { + slocale = (char *)intl_locale_get_default(); + } + +#ifdef MSG_FORMAT_QUOTE_APOS + if(msgformat_fix_quotes(&spattern, &spattern_len, &INTL_DATA_ERROR_CODE(mfo)) != SUCCESS) { + intl_error_set( NULL, U_INVALID_FORMAT_ERROR, + "msgfmt_parse_message: error converting pattern to quote-friendly format", 0 ); + RETURN_FALSE; + } +#endif + + /* Create an ICU message formatter. */ + MSG_FORMAT_OBJECT(mfo) = umsg_open(spattern, spattern_len, slocale, NULL, &INTL_DATA_ERROR_CODE(mfo)); + if(spattern && spattern_len) { + efree(spattern); + } + 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_arginfo.h b/ext/intl/normalizer/normalizer_arginfo.h index e5ef152c0423a..23ce84b1c76e1 100644 --- a/ext/intl/normalizer/normalizer_arginfo.h +++ b/ext/intl/normalizer/normalizer_arginfo.h @@ -36,63 +36,63 @@ static zend_class_entry *register_class_Normalizer(void) zval const_FORM_D_value; ZVAL_LONG(&const_FORM_D_value, NORMALIZER_FORM_D); - zend_string *const_FORM_D_name = zend_string_init_interned("FORM_D", sizeof("FORM_D") - 1, 1); + zend_string *const_FORM_D_name = zend_string_init_interned("FORM_D", sizeof("FORM_D") - 1, true); zend_declare_typed_class_constant(class_entry, const_FORM_D_name, &const_FORM_D_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FORM_D_name); + zend_string_release_ex(const_FORM_D_name, true); zval const_NFD_value; ZVAL_LONG(&const_NFD_value, NORMALIZER_NFD); - zend_string *const_NFD_name = zend_string_init_interned("NFD", sizeof("NFD") - 1, 1); + zend_string *const_NFD_name = zend_string_init_interned("NFD", sizeof("NFD") - 1, true); zend_declare_typed_class_constant(class_entry, const_NFD_name, &const_NFD_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NFD_name); + zend_string_release_ex(const_NFD_name, true); zval const_FORM_KD_value; ZVAL_LONG(&const_FORM_KD_value, NORMALIZER_FORM_KD); - zend_string *const_FORM_KD_name = zend_string_init_interned("FORM_KD", sizeof("FORM_KD") - 1, 1); + zend_string *const_FORM_KD_name = zend_string_init_interned("FORM_KD", sizeof("FORM_KD") - 1, true); zend_declare_typed_class_constant(class_entry, const_FORM_KD_name, &const_FORM_KD_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FORM_KD_name); + zend_string_release_ex(const_FORM_KD_name, true); zval const_NFKD_value; ZVAL_LONG(&const_NFKD_value, NORMALIZER_NFKD); - zend_string *const_NFKD_name = zend_string_init_interned("NFKD", sizeof("NFKD") - 1, 1); + zend_string *const_NFKD_name = zend_string_init_interned("NFKD", sizeof("NFKD") - 1, true); zend_declare_typed_class_constant(class_entry, const_NFKD_name, &const_NFKD_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NFKD_name); + zend_string_release_ex(const_NFKD_name, true); zval const_FORM_C_value; ZVAL_LONG(&const_FORM_C_value, NORMALIZER_FORM_C); - zend_string *const_FORM_C_name = zend_string_init_interned("FORM_C", sizeof("FORM_C") - 1, 1); + zend_string *const_FORM_C_name = zend_string_init_interned("FORM_C", sizeof("FORM_C") - 1, true); zend_declare_typed_class_constant(class_entry, const_FORM_C_name, &const_FORM_C_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FORM_C_name); + zend_string_release_ex(const_FORM_C_name, true); zval const_NFC_value; ZVAL_LONG(&const_NFC_value, NORMALIZER_NFC); - zend_string *const_NFC_name = zend_string_init_interned("NFC", sizeof("NFC") - 1, 1); + zend_string *const_NFC_name = zend_string_init_interned("NFC", sizeof("NFC") - 1, true); zend_declare_typed_class_constant(class_entry, const_NFC_name, &const_NFC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NFC_name); + zend_string_release_ex(const_NFC_name, true); zval const_FORM_KC_value; ZVAL_LONG(&const_FORM_KC_value, NORMALIZER_FORM_KC); - zend_string *const_FORM_KC_name = zend_string_init_interned("FORM_KC", sizeof("FORM_KC") - 1, 1); + zend_string *const_FORM_KC_name = zend_string_init_interned("FORM_KC", sizeof("FORM_KC") - 1, true); zend_declare_typed_class_constant(class_entry, const_FORM_KC_name, &const_FORM_KC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FORM_KC_name); + zend_string_release_ex(const_FORM_KC_name, true); zval const_NFKC_value; ZVAL_LONG(&const_NFKC_value, NORMALIZER_NFKC); - zend_string *const_NFKC_name = zend_string_init_interned("NFKC", sizeof("NFKC") - 1, 1); + zend_string *const_NFKC_name = zend_string_init_interned("NFKC", sizeof("NFKC") - 1, true); zend_declare_typed_class_constant(class_entry, const_NFKC_name, &const_NFKC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NFKC_name); + zend_string_release_ex(const_NFKC_name, true); zval const_FORM_KC_CF_value; ZVAL_LONG(&const_FORM_KC_CF_value, NORMALIZER_FORM_KC_CF); - zend_string *const_FORM_KC_CF_name = zend_string_init_interned("FORM_KC_CF", sizeof("FORM_KC_CF") - 1, 1); + zend_string *const_FORM_KC_CF_name = zend_string_init_interned("FORM_KC_CF", sizeof("FORM_KC_CF") - 1, true); zend_declare_typed_class_constant(class_entry, const_FORM_KC_CF_name, &const_FORM_KC_CF_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FORM_KC_CF_name); + zend_string_release_ex(const_FORM_KC_CF_name, true); zval const_NFKC_CF_value; ZVAL_LONG(&const_NFKC_CF_value, NORMALIZER_NFKC_CF); - zend_string *const_NFKC_CF_name = zend_string_init_interned("NFKC_CF", sizeof("NFKC_CF") - 1, 1); + zend_string *const_NFKC_CF_name = zend_string_init_interned("NFKC_CF", sizeof("NFKC_CF") - 1, true); zend_declare_typed_class_constant(class_entry, const_NFKC_CF_name, &const_NFKC_CF_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NFKC_CF_name); + zend_string_release_ex(const_NFKC_CF_name, true); return class_entry; } diff --git a/ext/intl/normalizer/normalizer_class.c b/ext/intl/normalizer/normalizer_class.c deleted file mode 100644 index d9e413d5e5146..0000000000000 --- a/ext/intl/normalizer/normalizer_class.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Ed Batutis | - +----------------------------------------------------------------------+ - */ - -#include "normalizer.h" -#include "normalizer_class.h" -#include "php_intl.h" -#include "normalizer_arginfo.h" -#include "intl_error.h" - -#include - -zend_class_entry *Normalizer_ce_ptr = NULL; - -/* - * 'Normalizer' class registration structures & functions - */ - -/* {{{ normalizer_register_Normalizer_class - * Initialize 'Normalizer' class - */ -void normalizer_register_Normalizer_class( void ) -{ - /* Create and register 'Normalizer' class. */ - Normalizer_ce_ptr = register_class_Normalizer(); - Normalizer_ce_ptr->create_object = NULL; -} -/* }}} */ diff --git a/ext/intl/normalizer/normalizer_class.cpp b/ext/intl/normalizer/normalizer_class.cpp new file mode 100644 index 0000000000000..3838f7546325a --- /dev/null +++ b/ext/intl/normalizer/normalizer_class.cpp @@ -0,0 +1,49 @@ +/* + +----------------------------------------------------------------------+ + | 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: Ed Batutis | + +----------------------------------------------------------------------+ + */ + +#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 + +zend_class_entry *Normalizer_ce_ptr = NULL; + +/* + * 'Normalizer' class registration structures & functions + */ + +/* {{{ normalizer_register_Normalizer_class + * Initialize 'Normalizer' class + */ +U_CFUNC void normalizer_register_Normalizer_class( void ) +{ + /* Create and register 'Normalizer' class. */ + Normalizer_ce_ptr = register_class_Normalizer(); + Normalizer_ce_ptr->create_object = NULL; +} +/* }}} */ 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.c deleted file mode 100644 index 38f12134146a5..0000000000000 --- a/ext/intl/normalizer/normalizer_normalize.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Ed Batutis | - +----------------------------------------------------------------------+ - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "php_intl.h" -#include -#include "normalizer.h" -#include "normalizer_class.h" -#include "intl_convert.h" -#include - - -static const UNormalizer2 *intl_get_normalizer(zend_long form, UErrorCode *err) -{/*{{{*/ - switch (form) - { - case NORMALIZER_FORM_C: - return unorm2_getNFCInstance(err); - break; - case NORMALIZER_FORM_D: - return unorm2_getNFDInstance(err); - break; - case NORMALIZER_FORM_KC: - return unorm2_getNFKCInstance(err); - break; - case NORMALIZER_FORM_KD: - return unorm2_getNFKDInstance(err); - break; - case NORMALIZER_FORM_KC_CF: - return unorm2_getNFKCCasefoldInstance(err); - break; - } - - *err = U_ILLEGAL_ARGUMENT_ERROR; - return NULL; -}/*}}}*/ - -static int32_t intl_normalize(zend_long form, const UChar *src, int32_t src_len, UChar *dst, int32_t dst_len, UErrorCode *err) -{/*{{{*/ - const UNormalizer2 *norm = intl_get_normalizer(form, err); - if (U_FAILURE(*err)) { - return -1; - } - - return unorm2_normalize(norm, src, src_len, dst, dst_len, err); -}/*}}}*/ - -static UBool intl_is_normalized(zend_long form, const UChar *uinput, int32_t uinput_len, UErrorCode *err) -{/*{{{*/ - const UNormalizer2 *norm = intl_get_normalizer(form, err); - - if(U_FAILURE(*err)) { - return false; - } - - return unorm2_isNormalized(norm, uinput, uinput_len, err); -}/*}}}*/ - -/* {{{ Normalize a string. */ -PHP_FUNCTION( normalizer_normalize ) -{ - char* input = NULL; - /* form is optional, defaults to FORM_C */ - zend_long form = NORMALIZER_DEFAULT; - size_t input_len = 0; - - UChar* uinput = NULL; - int32_t uinput_len = 0; - int expansion_factor = 1; - UErrorCode status = U_ZERO_ERROR; - - UChar* uret_buf = NULL; - int32_t uret_len = 0; - - zend_string* u8str; - - int32_t size_needed; - - intl_error_reset( NULL ); - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "s|l", - &input, &input_len, &form ) == FAILURE ) - { - RETURN_THROWS(); - } - - expansion_factor = 1; - - switch(form) { - case NORMALIZER_FORM_D: - expansion_factor = 3; - break; - case NORMALIZER_FORM_KD: - expansion_factor = 3; - break; - case NORMALIZER_FORM_C: - case NORMALIZER_FORM_KC: - case NORMALIZER_FORM_KC_CF: - break; - default: - zend_argument_value_error(2, "must be a a valid normalization form"); - RETURN_THROWS(); - } - - /* - * Normalize string (converting it to UTF-16 first). - */ - - /* First convert the string to UTF-16. */ - intl_convert_utf8_to_utf16(&uinput, &uinput_len, input, input_len, &status ); - - if( U_FAILURE( status ) ) - { - /* Set global error code. */ - intl_error_set_code( NULL, status ); - - /* Set error messages. */ - intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16", 0 ); - if (uinput) { - efree( uinput ); - } - RETURN_FALSE; - } - - - /* Allocate memory for the destination buffer for normalization */ - uret_len = uinput_len * expansion_factor; - uret_buf = eumalloc( uret_len + 1 ); - - /* normalize */ - size_needed = intl_normalize(form, uinput, uinput_len, uret_buf, uret_len, &status); - - /* Bail out if an unexpected error occurred. - * (U_BUFFER_OVERFLOW_ERROR means that *target buffer is not large enough). - * (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 ); - efree( uret_buf ); - efree( uinput ); - RETURN_FALSE; - } - - if ( size_needed > uret_len ) { - /* realloc does not seem to work properly - memory is corrupted - * uret_buf = eurealloc(uret_buf, size_needed + 1); - */ - efree( uret_buf ); - uret_buf = eumalloc( size_needed + 1 ); - uret_len = size_needed; - - status = U_ZERO_ERROR; - - /* try normalize again */ - size_needed = intl_normalize(form, uinput, uinput_len, uret_buf, uret_len, &status); - - /* Bail out if an unexpected error occurred. */ - if( U_FAILURE(status) ) { - /* Set error messages. */ - intl_error_set_custom_msg( NULL,"Error normalizing string", 0 ); - efree( uret_buf ); - efree( uinput ); - RETURN_FALSE; - } - } - - efree( uinput ); - - /* the buffer we actually used */ - uret_len = size_needed; - - /* Convert normalized string from UTF-16 to UTF-8. */ - u8str = intl_convert_utf16_to_utf8(uret_buf, uret_len, &status ); - efree( uret_buf ); - if( !u8str ) - { - intl_error_set( NULL, status, - "normalizer_normalize: error converting normalized text UTF-8", 0 ); - RETURN_FALSE; - } - - /* Return it. */ - RETVAL_NEW_STR( u8str ); -} -/* }}} */ - -/* {{{ Test if a string is in a given normalization form. */ -PHP_FUNCTION( normalizer_is_normalized ) -{ - char* input = NULL; - /* form is optional, defaults to FORM_C */ - zend_long form = NORMALIZER_DEFAULT; - size_t input_len = 0; - - UChar* uinput = NULL; - int uinput_len = 0; - UErrorCode status = U_ZERO_ERROR; - - UBool uret = false; - - intl_error_reset( NULL ); - - /* Parse parameters. */ - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "s|l", - &input, &input_len, &form) == FAILURE ) - { - RETURN_THROWS(); - } - - switch(form) { - case NORMALIZER_FORM_D: - case NORMALIZER_FORM_KD: - case NORMALIZER_FORM_C: - case NORMALIZER_FORM_KC: - case NORMALIZER_FORM_KC_CF: - break; - default: - zend_argument_value_error(2, "must be a a valid normalization form"); - RETURN_THROWS(); - } - - - /* - * Test normalization of string (converting it to UTF-16 first). - */ - - /* First convert the string to UTF-16. */ - intl_convert_utf8_to_utf16(&uinput, &uinput_len, input, input_len, &status ); - - if( U_FAILURE( status ) ) - { - /* Set global error code. */ - intl_error_set_code( NULL, status ); - - /* Set error messages. */ - intl_error_set_custom_msg( NULL, "Error converting string to UTF-16.", 0 ); - if (uinput) { - efree( uinput ); - } - RETURN_FALSE; - } - - - /* test string */ - uret = intl_is_normalized(form, uinput, uinput_len, &status); - - efree( uinput ); - - /* 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 ); - RETURN_FALSE; - } - - if ( uret ) - RETURN_TRUE; - - RETURN_FALSE; -} -/* }}} */ - -/* {{{ Returns the Decomposition_Mapping property for the given UTF-8 encoded code point. */ -PHP_FUNCTION( normalizer_get_raw_decomposition ) -{ - char* input = NULL; - size_t input_length = 0; - - UChar32 codepoint = -1; - int32_t offset = 0; - - UErrorCode status = U_ZERO_ERROR; - const UNormalizer2 *norm; - UChar decomposition[32]; - int32_t decomposition_length; - - zend_long form = NORMALIZER_DEFAULT; - - intl_error_reset(NULL); - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_STRING(input, input_length) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(form) - ZEND_PARSE_PARAMETERS_END(); - - norm = intl_get_normalizer(form, &status); - - 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); - 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); - return; - } - - decomposition_length = unorm2_getRawDecomposition(norm, codepoint, decomposition, 32, &status); - if (decomposition_length == -1) { - RETURN_NULL(); - } - - RETVAL_NEW_STR(intl_convert_utf16_to_utf8(decomposition, decomposition_length, &status)); -} -/* }}} */ diff --git a/ext/intl/normalizer/normalizer_normalize.cpp b/ext/intl/normalizer/normalizer_normalize.cpp new file mode 100644 index 0000000000000..92e8f1166ad00 --- /dev/null +++ b/ext/intl/normalizer/normalizer_normalize.cpp @@ -0,0 +1,331 @@ +/* + +----------------------------------------------------------------------+ + | 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: Ed Batutis | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#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 + + +static const UNormalizer2 *intl_get_normalizer(zend_long form, UErrorCode *err) +{/*{{{*/ + switch (form) + { + case NORMALIZER_FORM_C: + return unorm2_getNFCInstance(err); + break; + case NORMALIZER_FORM_D: + return unorm2_getNFDInstance(err); + break; + case NORMALIZER_FORM_KC: + return unorm2_getNFKCInstance(err); + break; + case NORMALIZER_FORM_KD: + return unorm2_getNFKDInstance(err); + break; + case NORMALIZER_FORM_KC_CF: + return unorm2_getNFKCCasefoldInstance(err); + break; + } + + *err = U_ILLEGAL_ARGUMENT_ERROR; + return NULL; +}/*}}}*/ + +static int32_t intl_normalize(zend_long form, const UChar *src, int32_t src_len, UChar *dst, int32_t dst_len, UErrorCode *err) +{/*{{{*/ + const UNormalizer2 *norm = intl_get_normalizer(form, err); + if (U_FAILURE(*err)) { + return -1; + } + + return unorm2_normalize(norm, src, src_len, dst, dst_len, err); +}/*}}}*/ + +static UBool intl_is_normalized(zend_long form, const UChar *uinput, int32_t uinput_len, UErrorCode *err) +{/*{{{*/ + const UNormalizer2 *norm = intl_get_normalizer(form, err); + + if(U_FAILURE(*err)) { + return false; + } + + return unorm2_isNormalized(norm, uinput, uinput_len, err); +}/*}}}*/ + +/* {{{ Normalize a string. */ +U_CFUNC PHP_FUNCTION( normalizer_normalize ) +{ + char* input = NULL; + /* form is optional, defaults to FORM_C */ + zend_long form = NORMALIZER_DEFAULT; + size_t input_len = 0; + + UChar* uinput = NULL; + int32_t uinput_len = 0; + int expansion_factor = 1; + UErrorCode status = U_ZERO_ERROR; + + UChar* uret_buf = NULL; + int32_t uret_len = 0; + + zend_string* u8str; + + int32_t size_needed; + + intl_error_reset( NULL ); + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "s|l", + &input, &input_len, &form ) == FAILURE ) + { + RETURN_THROWS(); + } + + expansion_factor = 1; + + switch(form) { + case NORMALIZER_FORM_D: + expansion_factor = 3; + break; + case NORMALIZER_FORM_KD: + expansion_factor = 3; + break; + case NORMALIZER_FORM_C: + case NORMALIZER_FORM_KC: + case NORMALIZER_FORM_KC_CF: + break; + default: + zend_argument_value_error(2, "must be a a valid normalization form"); + RETURN_THROWS(); + } + + /* + * Normalize string (converting it to UTF-16 first). + */ + + /* First convert the string to UTF-16. */ + intl_convert_utf8_to_utf16(&uinput, &uinput_len, input, input_len, &status ); + + if( U_FAILURE( status ) ) + { + /* Set global error code. */ + intl_error_set_code( NULL, status ); + + /* Set error messages. */ + intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16"); + if (uinput) { + efree( uinput ); + } + RETURN_FALSE; + } + + + /* Allocate memory for the destination buffer for normalization */ + uret_len = uinput_len * expansion_factor; + uret_buf = eumalloc( uret_len + 1 ); + + /* normalize */ + size_needed = intl_normalize(form, uinput, uinput_len, uret_buf, uret_len, &status); + + /* Bail out if an unexpected error occurred. + * (U_BUFFER_OVERFLOW_ERROR means that *target buffer is not large enough). + * (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"); + efree( uret_buf ); + efree( uinput ); + RETURN_FALSE; + } + + if ( size_needed > uret_len ) { + /* realloc does not seem to work properly - memory is corrupted + * uret_buf = eurealloc(uret_buf, size_needed + 1); + */ + efree( uret_buf ); + uret_buf = eumalloc( size_needed + 1 ); + uret_len = size_needed; + + status = U_ZERO_ERROR; + + /* try normalize again */ + size_needed = intl_normalize(form, uinput, uinput_len, uret_buf, uret_len, &status); + + /* Bail out if an unexpected error occurred. */ + if( U_FAILURE(status) ) { + /* Set error messages. */ + intl_error_set_custom_msg( NULL,"Error normalizing string"); + efree( uret_buf ); + efree( uinput ); + RETURN_FALSE; + } + } + + efree( uinput ); + + /* the buffer we actually used */ + uret_len = size_needed; + + /* Convert normalized string from UTF-16 to UTF-8. */ + u8str = intl_convert_utf16_to_utf8(uret_buf, uret_len, &status ); + efree( uret_buf ); + if( !u8str ) + { + intl_error_set( NULL, status, + "error converting normalized text UTF-8"); + RETURN_FALSE; + } + + /* Return it. */ + RETVAL_NEW_STR( u8str ); +} +/* }}} */ + +/* {{{ Test if a string is in a given normalization form. */ +U_CFUNC PHP_FUNCTION( normalizer_is_normalized ) +{ + char* input = NULL; + /* form is optional, defaults to FORM_C */ + zend_long form = NORMALIZER_DEFAULT; + size_t input_len = 0; + + UChar* uinput = NULL; + int uinput_len = 0; + UErrorCode status = U_ZERO_ERROR; + + UBool uret = false; + + intl_error_reset( NULL ); + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "s|l", + &input, &input_len, &form) == FAILURE ) + { + RETURN_THROWS(); + } + + switch(form) { + case NORMALIZER_FORM_D: + case NORMALIZER_FORM_KD: + case NORMALIZER_FORM_C: + case NORMALIZER_FORM_KC: + case NORMALIZER_FORM_KC_CF: + break; + default: + zend_argument_value_error(2, "must be a a valid normalization form"); + RETURN_THROWS(); + } + + + /* + * Test normalization of string (converting it to UTF-16 first). + */ + + /* First convert the string to UTF-16. */ + intl_convert_utf8_to_utf16(&uinput, &uinput_len, input, input_len, &status ); + + if( U_FAILURE( status ) ) + { + /* Set global error code. */ + intl_error_set_code( NULL, status ); + + /* Set error messages. */ + intl_error_set_custom_msg( NULL, "Error converting string to UTF-16."); + if (uinput) { + efree( uinput ); + } + RETURN_FALSE; + } + + + /* test string */ + uret = intl_is_normalized(form, uinput, uinput_len, &status); + + efree( uinput ); + + /* 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."); + RETURN_FALSE; + } + + if ( uret ) + RETURN_TRUE; + + RETURN_FALSE; +} +/* }}} */ + +/* {{{ Returns the Decomposition_Mapping property for the given UTF-8 encoded code point. */ +U_CFUNC PHP_FUNCTION( normalizer_get_raw_decomposition ) +{ + char* input = NULL; + size_t input_length = 0; + + UChar32 codepoint = -1; + int32_t offset = 0; + + UErrorCode status = U_ZERO_ERROR; + const UNormalizer2 *norm; + UChar decomposition[32]; + int32_t decomposition_length; + + zend_long form = NORMALIZER_DEFAULT; + + intl_error_reset(NULL); + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STRING(input, input_length) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(form) + ZEND_PARSE_PARAMETERS_END(); + + norm = intl_get_normalizer(form, &status); + + 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."); + 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"); + return; + } + + decomposition_length = unorm2_getRawDecomposition(norm, codepoint, decomposition, 32, &status); + if (decomposition_length == -1) { + RETURN_NULL(); + } + + RETVAL_NEW_STR(intl_convert_utf16_to_utf8(decomposition, decomposition_length, &status)); +} +/* }}} */ diff --git a/ext/intl/php_intl.c b/ext/intl/php_intl.c index 68fd2dedfba85..00001e9985b7f 100644 --- a/ext/intl/php_intl.c +++ b/ext/intl/php_intl.c @@ -42,6 +42,7 @@ #include "locale/locale_class.h" #include "listformatter/listformatter_class.h" +#include "rangeformatter/rangeformatter_class.h" #include "dateformat/dateformat.h" #include "dateformat/dateformat_class.h" @@ -98,10 +99,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() /* }}} */ @@ -161,6 +190,10 @@ PHP_MINIT_FUNCTION( intl ) /* Register 'ListFormatter' PHP class */ listformatter_register_class( ); +#if U_ICU_VERSION_MAJOR_NUM >= 63 + /* Register 'NumberRangeFormatter' PHP class */ + rangeformatter_register_class( ); +#endif /* Register 'Normalizer' PHP class */ normalizer_register_Normalizer_class( ); 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 332e5caed676d..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) @@ -1225,19 +1229,15 @@ 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_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_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/rangeformatter/rangeformatter.stub.php b/ext/intl/rangeformatter/rangeformatter.stub.php new file mode 100644 index 0000000000000..eae40b5a56c23 --- /dev/null +++ b/ext/intl/rangeformatter/rangeformatter.stub.php @@ -0,0 +1,61 @@ += 63 + /** @cvalue UNUM_RANGE_COLLAPSE_AUTO */ + public const int COLLAPSE_AUTO = UNKNOWN; + + /** @cvalue UNUM_RANGE_COLLAPSE_NONE */ + public const int COLLAPSE_NONE = UNKNOWN; + + /** @cvalue UNUM_RANGE_COLLAPSE_UNIT */ + public const int COLLAPSE_UNIT = UNKNOWN; + + /** @cvalue UNUM_RANGE_COLLAPSE_ALL */ + public const int COLLAPSE_ALL = UNKNOWN; + + /** @cvalue UNUM_IDENTITY_FALLBACK_SINGLE_VALUE */ + public const int IDENTITY_FALLBACK_SINGLE_VALUE = UNKNOWN; + + /** @cvalue UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE */ + public const int IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE = UNKNOWN; + + /** @cvalue UNUM_IDENTITY_FALLBACK_APPROXIMATELY */ + public const int IDENTITY_FALLBACK_APPROXIMATELY = UNKNOWN; + + /** @cvalue UNUM_IDENTITY_FALLBACK_RANGE */ + public const int IDENTITY_FALLBACK_RANGE = UNKNOWN; +#else + public const int COLLAPSE_AUTO = 0; + + public const int COLLAPSE_NONE = 1; + + public const int COLLAPSE_UNIT = 2; + + public const int COLLAPSE_ALL = 3; + + public const int IDENTITY_FALLBACK_SINGLE_VALUE = 0; + + public const int IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE = 1; + + public const int IDENTITY_FALLBACK_APPROXIMATELY = 2; + + public const int IDENTITY_FALLBACK_RANGE = 3; +#endif + + private function __construct() {} + + public static function createFromSkeleton(string $skeleton, string $locale, int $collapse, int $identityFallback): IntlNumberRangeFormatter {} + + public function format(float|int $start, float|int $end): string {} + + public function getErrorCode(): int {} + + public function getErrorMessage(): string {} +} diff --git a/ext/intl/rangeformatter/rangeformatter_arginfo.h b/ext/intl/rangeformatter/rangeformatter_arginfo.h new file mode 100644 index 0000000000000..ef3255415d16a --- /dev/null +++ b/ext/intl/rangeformatter/rangeformatter_arginfo.h @@ -0,0 +1,148 @@ +/* This is a generated file, edit the .stub.php file instead. + * Stub hash: 7029642524e32984e893e1e050a5e0bbf275c416 */ + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_IntlNumberRangeFormatter___construct, 0, 0, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_IntlNumberRangeFormatter_createFromSkeleton, 0, 4, IntlNumberRangeFormatter, 0) + ZEND_ARG_TYPE_INFO(0, skeleton, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, collapse, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, identityFallback, IS_LONG, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_IntlNumberRangeFormatter_format, 0, 2, IS_STRING, 0) + ZEND_ARG_TYPE_MASK(0, start, MAY_BE_DOUBLE|MAY_BE_LONG, NULL) + ZEND_ARG_TYPE_MASK(0, end, MAY_BE_DOUBLE|MAY_BE_LONG, NULL) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_IntlNumberRangeFormatter_getErrorCode, 0, 0, IS_LONG, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_IntlNumberRangeFormatter_getErrorMessage, 0, 0, IS_STRING, 0) +ZEND_END_ARG_INFO() + +ZEND_METHOD(IntlNumberRangeFormatter, __construct); +ZEND_METHOD(IntlNumberRangeFormatter, createFromSkeleton); +ZEND_METHOD(IntlNumberRangeFormatter, format); +ZEND_METHOD(IntlNumberRangeFormatter, getErrorCode); +ZEND_METHOD(IntlNumberRangeFormatter, getErrorMessage); + +static const zend_function_entry class_IntlNumberRangeFormatter_methods[] = { + ZEND_ME(IntlNumberRangeFormatter, __construct, arginfo_class_IntlNumberRangeFormatter___construct, ZEND_ACC_PRIVATE) + ZEND_ME(IntlNumberRangeFormatter, createFromSkeleton, arginfo_class_IntlNumberRangeFormatter_createFromSkeleton, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + ZEND_ME(IntlNumberRangeFormatter, format, arginfo_class_IntlNumberRangeFormatter_format, ZEND_ACC_PUBLIC) + ZEND_ME(IntlNumberRangeFormatter, getErrorCode, arginfo_class_IntlNumberRangeFormatter_getErrorCode, ZEND_ACC_PUBLIC) + ZEND_ME(IntlNumberRangeFormatter, getErrorMessage, arginfo_class_IntlNumberRangeFormatter_getErrorMessage, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static zend_class_entry *register_class_IntlNumberRangeFormatter(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "IntlNumberRangeFormatter", class_IntlNumberRangeFormatter_methods); + class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES|ZEND_ACC_NOT_SERIALIZABLE); +#if U_ICU_VERSION_MAJOR_NUM >= 63 + + zval const_COLLAPSE_AUTO_value; + ZVAL_LONG(&const_COLLAPSE_AUTO_value, UNUM_RANGE_COLLAPSE_AUTO); + zend_string *const_COLLAPSE_AUTO_name = zend_string_init_interned("COLLAPSE_AUTO", sizeof("COLLAPSE_AUTO") - 1, true); + zend_declare_typed_class_constant(class_entry, const_COLLAPSE_AUTO_name, &const_COLLAPSE_AUTO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release_ex(const_COLLAPSE_AUTO_name, true); + + zval const_COLLAPSE_NONE_value; + ZVAL_LONG(&const_COLLAPSE_NONE_value, UNUM_RANGE_COLLAPSE_NONE); + zend_string *const_COLLAPSE_NONE_name = zend_string_init_interned("COLLAPSE_NONE", sizeof("COLLAPSE_NONE") - 1, true); + zend_declare_typed_class_constant(class_entry, const_COLLAPSE_NONE_name, &const_COLLAPSE_NONE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release_ex(const_COLLAPSE_NONE_name, true); + + zval const_COLLAPSE_UNIT_value; + ZVAL_LONG(&const_COLLAPSE_UNIT_value, UNUM_RANGE_COLLAPSE_UNIT); + zend_string *const_COLLAPSE_UNIT_name = zend_string_init_interned("COLLAPSE_UNIT", sizeof("COLLAPSE_UNIT") - 1, true); + zend_declare_typed_class_constant(class_entry, const_COLLAPSE_UNIT_name, &const_COLLAPSE_UNIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release_ex(const_COLLAPSE_UNIT_name, true); + + zval const_COLLAPSE_ALL_value; + ZVAL_LONG(&const_COLLAPSE_ALL_value, UNUM_RANGE_COLLAPSE_ALL); + zend_string *const_COLLAPSE_ALL_name = zend_string_init_interned("COLLAPSE_ALL", sizeof("COLLAPSE_ALL") - 1, true); + zend_declare_typed_class_constant(class_entry, const_COLLAPSE_ALL_name, &const_COLLAPSE_ALL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release_ex(const_COLLAPSE_ALL_name, true); + + zval const_IDENTITY_FALLBACK_SINGLE_VALUE_value; + ZVAL_LONG(&const_IDENTITY_FALLBACK_SINGLE_VALUE_value, UNUM_IDENTITY_FALLBACK_SINGLE_VALUE); + zend_string *const_IDENTITY_FALLBACK_SINGLE_VALUE_name = zend_string_init_interned("IDENTITY_FALLBACK_SINGLE_VALUE", sizeof("IDENTITY_FALLBACK_SINGLE_VALUE") - 1, true); + zend_declare_typed_class_constant(class_entry, const_IDENTITY_FALLBACK_SINGLE_VALUE_name, &const_IDENTITY_FALLBACK_SINGLE_VALUE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release_ex(const_IDENTITY_FALLBACK_SINGLE_VALUE_name, true); + + zval const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_value; + ZVAL_LONG(&const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_value, UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE); + zend_string *const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_name = zend_string_init_interned("IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE", sizeof("IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE") - 1, true); + zend_declare_typed_class_constant(class_entry, const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_name, &const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release_ex(const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_name, true); + + zval const_IDENTITY_FALLBACK_APPROXIMATELY_value; + ZVAL_LONG(&const_IDENTITY_FALLBACK_APPROXIMATELY_value, UNUM_IDENTITY_FALLBACK_APPROXIMATELY); + zend_string *const_IDENTITY_FALLBACK_APPROXIMATELY_name = zend_string_init_interned("IDENTITY_FALLBACK_APPROXIMATELY", sizeof("IDENTITY_FALLBACK_APPROXIMATELY") - 1, true); + zend_declare_typed_class_constant(class_entry, const_IDENTITY_FALLBACK_APPROXIMATELY_name, &const_IDENTITY_FALLBACK_APPROXIMATELY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release_ex(const_IDENTITY_FALLBACK_APPROXIMATELY_name, true); + + zval const_IDENTITY_FALLBACK_RANGE_value; + ZVAL_LONG(&const_IDENTITY_FALLBACK_RANGE_value, UNUM_IDENTITY_FALLBACK_RANGE); + zend_string *const_IDENTITY_FALLBACK_RANGE_name = zend_string_init_interned("IDENTITY_FALLBACK_RANGE", sizeof("IDENTITY_FALLBACK_RANGE") - 1, true); + zend_declare_typed_class_constant(class_entry, const_IDENTITY_FALLBACK_RANGE_name, &const_IDENTITY_FALLBACK_RANGE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release_ex(const_IDENTITY_FALLBACK_RANGE_name, true); +#endif +#if !(U_ICU_VERSION_MAJOR_NUM >= 63) + + zval const_COLLAPSE_AUTO_value; + ZVAL_LONG(&const_COLLAPSE_AUTO_value, 0); + zend_string *const_COLLAPSE_AUTO_name = zend_string_init_interned("COLLAPSE_AUTO", sizeof("COLLAPSE_AUTO") - 1, true); + zend_declare_typed_class_constant(class_entry, const_COLLAPSE_AUTO_name, &const_COLLAPSE_AUTO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release_ex(const_COLLAPSE_AUTO_name, true); + + zval const_COLLAPSE_NONE_value; + ZVAL_LONG(&const_COLLAPSE_NONE_value, 1); + zend_string *const_COLLAPSE_NONE_name = zend_string_init_interned("COLLAPSE_NONE", sizeof("COLLAPSE_NONE") - 1, true); + zend_declare_typed_class_constant(class_entry, const_COLLAPSE_NONE_name, &const_COLLAPSE_NONE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release_ex(const_COLLAPSE_NONE_name, true); + + zval const_COLLAPSE_UNIT_value; + ZVAL_LONG(&const_COLLAPSE_UNIT_value, 2); + zend_string *const_COLLAPSE_UNIT_name = zend_string_init_interned("COLLAPSE_UNIT", sizeof("COLLAPSE_UNIT") - 1, true); + zend_declare_typed_class_constant(class_entry, const_COLLAPSE_UNIT_name, &const_COLLAPSE_UNIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release_ex(const_COLLAPSE_UNIT_name, true); + + zval const_COLLAPSE_ALL_value; + ZVAL_LONG(&const_COLLAPSE_ALL_value, 3); + zend_string *const_COLLAPSE_ALL_name = zend_string_init_interned("COLLAPSE_ALL", sizeof("COLLAPSE_ALL") - 1, true); + zend_declare_typed_class_constant(class_entry, const_COLLAPSE_ALL_name, &const_COLLAPSE_ALL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release_ex(const_COLLAPSE_ALL_name, true); + + zval const_IDENTITY_FALLBACK_SINGLE_VALUE_value; + ZVAL_LONG(&const_IDENTITY_FALLBACK_SINGLE_VALUE_value, 0); + zend_string *const_IDENTITY_FALLBACK_SINGLE_VALUE_name = zend_string_init_interned("IDENTITY_FALLBACK_SINGLE_VALUE", sizeof("IDENTITY_FALLBACK_SINGLE_VALUE") - 1, true); + zend_declare_typed_class_constant(class_entry, const_IDENTITY_FALLBACK_SINGLE_VALUE_name, &const_IDENTITY_FALLBACK_SINGLE_VALUE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release_ex(const_IDENTITY_FALLBACK_SINGLE_VALUE_name, true); + + zval const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_value; + ZVAL_LONG(&const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_value, 1); + zend_string *const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_name = zend_string_init_interned("IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE", sizeof("IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE") - 1, true); + zend_declare_typed_class_constant(class_entry, const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_name, &const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release_ex(const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_name, true); + + zval const_IDENTITY_FALLBACK_APPROXIMATELY_value; + ZVAL_LONG(&const_IDENTITY_FALLBACK_APPROXIMATELY_value, 2); + zend_string *const_IDENTITY_FALLBACK_APPROXIMATELY_name = zend_string_init_interned("IDENTITY_FALLBACK_APPROXIMATELY", sizeof("IDENTITY_FALLBACK_APPROXIMATELY") - 1, true); + zend_declare_typed_class_constant(class_entry, const_IDENTITY_FALLBACK_APPROXIMATELY_name, &const_IDENTITY_FALLBACK_APPROXIMATELY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release_ex(const_IDENTITY_FALLBACK_APPROXIMATELY_name, true); + + zval const_IDENTITY_FALLBACK_RANGE_value; + ZVAL_LONG(&const_IDENTITY_FALLBACK_RANGE_value, 3); + zend_string *const_IDENTITY_FALLBACK_RANGE_name = zend_string_init_interned("IDENTITY_FALLBACK_RANGE", sizeof("IDENTITY_FALLBACK_RANGE") - 1, true); + zend_declare_typed_class_constant(class_entry, const_IDENTITY_FALLBACK_RANGE_name, &const_IDENTITY_FALLBACK_RANGE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release_ex(const_IDENTITY_FALLBACK_RANGE_name, true); +#endif + + return class_entry; +} diff --git a/ext/intl/rangeformatter/rangeformatter_class.cpp b/ext/intl/rangeformatter/rangeformatter_class.cpp new file mode 100644 index 0000000000000..2042966177cb2 --- /dev/null +++ b/ext/intl/rangeformatter/rangeformatter_class.cpp @@ -0,0 +1,226 @@ +/* + +----------------------------------------------------------------------+ + | 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: Bogdan Ungureanu | + +----------------------------------------------------------------------+ +*/ + +extern "C" { + #include "php.h" + #include "zend_API.h" + #include "../intl_common.h" +} + +#if U_ICU_VERSION_MAJOR_NUM >= 63 +#include +#include +#include +#include "../intl_convertcpp.h" + +extern "C" { + #include "../intl_error.h" + #include "../php_intl.h" + #include "../intl_data.h" + #include "rangeformatter_arginfo.h" + #include "rangeformatter_class.h" + #include "intl_convert.h" +} + +using icu::number::NumberRangeFormatter; +using icu::number::NumberFormatter; +using icu::number::UnlocalizedNumberFormatter; +using icu::number::LocalizedNumberRangeFormatter; +using icu::UnicodeString; +using icu::MeasureUnit; + +static zend_object_handlers rangeformatter_handlers; +zend_class_entry *class_entry_IntlNumberRangeFormatter; + +zend_object *IntlNumberRangeFormatter_object_create(zend_class_entry *ce) +{ + IntlNumberRangeFormatter_object* intern; + + intern = reinterpret_cast(zend_object_alloc(sizeof(IntlNumberRangeFormatter_object), ce)); + zend_object_std_init(&intern->zo, ce); + object_properties_init(&intern->zo, ce); + + // Initialize rangeformatter_data structure + intl_error_init(&intern->nrf_data.error); + intern->nrf_data.unumrf = nullptr; + + intern->zo.handlers = &rangeformatter_handlers; + + return &intern->zo; +} + +U_CFUNC PHP_METHOD(IntlNumberRangeFormatter, __construct) +{ + ZEND_PARSE_PARAMETERS_NONE(); + zend_throw_error(NULL, "Cannot directly construct %s, use createFromSkeleton method instead", ZSTR_VAL(Z_OBJCE_P(ZEND_THIS)->name)); +} + +U_CFUNC PHP_METHOD(IntlNumberRangeFormatter, createFromSkeleton) +{ + char* skeleton; + char* locale; + size_t locale_len; + size_t skeleton_len; + zend_long collapse; + zend_long identityFallback; + + ZEND_PARSE_PARAMETERS_START(4,4) + Z_PARAM_STRING(skeleton, skeleton_len) + Z_PARAM_STRING(locale, locale_len) + Z_PARAM_LONG(collapse) + Z_PARAM_LONG(identityFallback) + ZEND_PARSE_PARAMETERS_END(); + + if (locale_len == 0) { + locale = (char *)intl_locale_get_default(); + } + + if (locale_len > INTL_MAX_LOCALE_LEN) { + zend_argument_value_error(2, "must be no longer than %d characters", INTL_MAX_LOCALE_LEN); + RETURN_THROWS(); + } + + if (strlen(uloc_getISO3Language(locale)) == 0) { + zend_argument_value_error(2, "\"%s\" is invalid", locale); + RETURN_THROWS(); + } + + if (collapse != UNUM_RANGE_COLLAPSE_AUTO && collapse != UNUM_RANGE_COLLAPSE_NONE && collapse != UNUM_RANGE_COLLAPSE_UNIT && collapse != UNUM_RANGE_COLLAPSE_ALL) { + zend_argument_value_error(3, "must be one of IntlNumberRangeFormatter::COLLAPSE_AUTO, IntlNumberRangeFormatter::COLLAPSE_NONE, IntlNumberRangeFormatter::COLLAPSE_UNIT, or IntlNumberRangeFormatter::COLLAPSE_ALL"); + RETURN_THROWS(); + } + + if (identityFallback != UNUM_IDENTITY_FALLBACK_SINGLE_VALUE && identityFallback != UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE && identityFallback != UNUM_IDENTITY_FALLBACK_APPROXIMATELY && identityFallback != UNUM_IDENTITY_FALLBACK_RANGE) { + zend_argument_value_error(4, "must be one of IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE, IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE, IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY, or IntlNumberRangeFormatter::IDENTITY_FALLBACK_RANGE"); + RETURN_THROWS(); + } + + UErrorCode status = U_ZERO_ERROR; + + UnicodeString skeleton_ustr(skeleton, skeleton_len); + + UnlocalizedNumberFormatter nf = NumberFormatter::forSkeleton(skeleton_ustr, status); + + if (U_FAILURE(status)) { + // override error level and use exceptions + 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; + + intl_error_set(NULL, status, "Failed to create the number skeleton"); + + INTL_G(use_exceptions) = old_use_exception; + INTL_G(error_level) = old_error_level; + } + + LocalizedNumberRangeFormatter* nrf = new LocalizedNumberRangeFormatter( + NumberRangeFormatter::with() + .locale(locale) + .numberFormatterBoth(nf) + .collapse(static_cast(collapse)) + .identityFallback(static_cast(identityFallback)) + ); + + zend_object* obj = IntlNumberRangeFormatter_object_create(class_entry_IntlNumberRangeFormatter); + + RANGEFORMATTER_OBJECT(php_intl_numberrangeformatter_fetch_object(obj)) = nrf; + + RETURN_OBJ(obj); +} + +U_CFUNC PHP_METHOD(IntlNumberRangeFormatter, format) +{ + zval *start; + zval *end; + + IntlNumberRangeFormatter_object* obj = Z_INTL_RANGEFORMATTER_P(ZEND_THIS); + + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_NUMBER(start) + Z_PARAM_NUMBER(end) + ZEND_PARSE_PARAMETERS_END(); + + UErrorCode error = U_ZERO_ERROR; + + icu::Formattable start_formattable(Z_TYPE_P(start) == IS_DOUBLE ? Z_DVAL_P(start) : Z_LVAL_P(start)); + icu::Formattable end_formattable(Z_TYPE_P(end) == IS_DOUBLE ? Z_DVAL_P(end) : Z_LVAL_P(end)); + + UnicodeString result = RANGEFORMATTER_OBJECT(obj)->formatFormattableRange(start_formattable, end_formattable, error).toString(error); + + // override error level and use exceptions + 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 (U_FAILURE(error)) { + intl_error_set(NULL, error, "Failed to format number range"); + } + + zend_string *ret = intl_charFromString(result, &error); + + if (U_FAILURE(error)) { + intl_error_set(NULL, error, "Failed to convert result to UTF-8"); + } + + INTL_G(use_exceptions) = old_use_exception; + INTL_G(error_level) = old_error_level; + + RETVAL_NEW_STR(ret); +} + +U_CFUNC PHP_METHOD(IntlNumberRangeFormatter, getErrorCode) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + IntlNumberRangeFormatter_object* obj = Z_INTL_RANGEFORMATTER_P(ZEND_THIS); + + RETURN_LONG(intl_error_get_code(&obj->nrf_data.error)); +} + +U_CFUNC PHP_METHOD(IntlNumberRangeFormatter, getErrorMessage) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + IntlNumberRangeFormatter_object* obj = Z_INTL_RANGEFORMATTER_P(ZEND_THIS); + + RETURN_STR(intl_error_get_message(&obj->nrf_data.error)); +} + +void IntlNumberRangeFormatter_object_free(zend_object *object) +{ + IntlNumberRangeFormatter_object* nfo = php_intl_numberrangeformatter_fetch_object(object); + + if (nfo->nrf_data.unumrf) { + delete nfo->nrf_data.unumrf; + nfo->nrf_data.unumrf = nullptr; + } + + intl_error_reset(&nfo->nrf_data.error); + + zend_object_std_dtor(&nfo->zo); +} + +void rangeformatter_register_class(void) +{ + class_entry_IntlNumberRangeFormatter = register_class_IntlNumberRangeFormatter(); + class_entry_IntlNumberRangeFormatter->create_object = IntlNumberRangeFormatter_object_create; + + memcpy(&rangeformatter_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + rangeformatter_handlers.offset = XtOffsetOf(IntlNumberRangeFormatter_object, zo); + rangeformatter_handlers.free_obj = IntlNumberRangeFormatter_object_free; + rangeformatter_handlers.clone_obj = NULL; +} +#endif diff --git a/ext/intl/rangeformatter/rangeformatter_class.h b/ext/intl/rangeformatter/rangeformatter_class.h new file mode 100644 index 0000000000000..661641c2ce0f0 --- /dev/null +++ b/ext/intl/rangeformatter/rangeformatter_class.h @@ -0,0 +1,53 @@ +/* + +----------------------------------------------------------------------+ + | 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: Bogdan Ungureanu | + +----------------------------------------------------------------------+ +*/ + +#ifndef RANGEFORMATTER_CLASS_H +#define RANGEFORMATTER_CLASS_H + +#include + +#ifdef __cplusplus +using icu::number::LocalizedNumberRangeFormatter; +#else +typedef void LocalizedNumberRangeFormatter; +#endif + +typedef struct { + // error handling + intl_error error; + + // formatter handling + LocalizedNumberRangeFormatter* unumrf; +} rangeformatter_data; + +typedef struct { + rangeformatter_data nrf_data; + zend_object zo; +} IntlNumberRangeFormatter_object; + +static inline IntlNumberRangeFormatter_object *php_intl_numberrangeformatter_fetch_object(zend_object *obj) { + return (IntlNumberRangeFormatter_object *)((char*)(obj) - XtOffsetOf(IntlNumberRangeFormatter_object, zo)); +} + +#define Z_INTL_RANGEFORMATTER_P(zv) php_intl_numberrangeformatter_fetch_object(Z_OBJ_P(zv)) + +#define RANGEFORMATTER_ERROR(nfo) (nfo)->nrf_data.error +#define RANGEFORMATTER_ERROR_P(nfo) &(RANGEFORMATTER_ERROR(nfo)) + +#define RANGEFORMATTER_OBJECT(nfo) (nfo)->nrf_data.unumrf + + +void rangeformatter_register_class(void); + +#endif diff --git a/ext/intl/resourcebundle/resourcebundle.c b/ext/intl/resourcebundle/resourcebundle.c deleted file mode 100644 index e29596f01872e..0000000000000 --- a/ext/intl/resourcebundle/resourcebundle.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Hans-Peter Oeri (University of St.Gallen) | - +----------------------------------------------------------------------+ - */ - -#include - -#include -#include - -#include "intl_convert.h" -#include "intl_data.h" -#include "resourcebundle/resourcebundle_class.h" - -/* {{{ ResourceBundle_extract_value */ -void resourcebundle_extract_value( zval *return_value, ResourceBundle_object *source ) -{ - UResType restype; - const UChar* ufield; - const uint8_t* bfield; - const int32_t* vfield; - int32_t ilen; - int i; - zend_long lfield; - ResourceBundle_object* newrb; - - restype = ures_getType( source->child ); - switch (restype) - { - case URES_STRING: - ufield = ures_getString( source->child, &ilen, &INTL_DATA_ERROR_CODE(source) ); - INTL_METHOD_CHECK_STATUS(source, "Failed to retrieve string value"); - INTL_METHOD_RETVAL_UTF8(source, (UChar *)ufield, ilen, 0); - break; - - case URES_BINARY: - bfield = ures_getBinary( source->child, &ilen, &INTL_DATA_ERROR_CODE(source) ); - INTL_METHOD_CHECK_STATUS(source, "Failed to retrieve binary value"); - ZVAL_STRINGL( return_value, (char *) bfield, ilen ); - break; - - case URES_INT: - lfield = ures_getInt( source->child, &INTL_DATA_ERROR_CODE(source) ); - INTL_METHOD_CHECK_STATUS(source, "Failed to retrieve integer value"); - ZVAL_LONG( return_value, lfield ); - break; - - case URES_INT_VECTOR: - vfield = ures_getIntVector( source->child, &ilen, &INTL_DATA_ERROR_CODE(source) ); - INTL_METHOD_CHECK_STATUS(source, "Failed to retrieve vector value"); - array_init_size( return_value, ilen ); - zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); - for (i=0; ime = source->child; - source->child = NULL; - intl_errors_reset(INTL_DATA_ERROR_P(source)); - break; - EMPTY_SWITCH_DEFAULT_CASE(); - } -} -/* }}} */ diff --git a/ext/intl/resourcebundle/resourcebundle.cpp b/ext/intl/resourcebundle/resourcebundle.cpp new file mode 100644 index 0000000000000..b8c5c00efaba6 --- /dev/null +++ b/ext/intl/resourcebundle/resourcebundle.cpp @@ -0,0 +1,80 @@ +/* + +----------------------------------------------------------------------+ + | 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: Hans-Peter Oeri (University of St.Gallen) | + +----------------------------------------------------------------------+ + */ + +#include + +#include +#include + +extern "C" { +#include "intl_convert.h" +#include "intl_data.h" +#include "resourcebundle/resourcebundle_class.h" +} + +/* {{{ ResourceBundle_extract_value */ +U_CFUNC void resourcebundle_extract_value( zval *return_value, ResourceBundle_object *source ) +{ + UResType restype; + const UChar* ufield; + const uint8_t* bfield; + const int32_t* vfield; + int32_t ilen; + int i; + zend_long lfield; + ResourceBundle_object* newrb; + + restype = ures_getType( source->child ); + switch (restype) + { + case URES_STRING: + ufield = ures_getString( source->child, &ilen, &INTL_DATA_ERROR_CODE(source) ); + INTL_METHOD_CHECK_STATUS(source, "Failed to retrieve string value"); + INTL_METHOD_RETVAL_UTF8(source, (UChar *)ufield, ilen, 0); + break; + + case URES_BINARY: + bfield = ures_getBinary( source->child, &ilen, &INTL_DATA_ERROR_CODE(source) ); + INTL_METHOD_CHECK_STATUS(source, "Failed to retrieve binary value"); + ZVAL_STRINGL( return_value, (char *) bfield, ilen ); + break; + + case URES_INT: + lfield = ures_getInt( source->child, &INTL_DATA_ERROR_CODE(source) ); + INTL_METHOD_CHECK_STATUS(source, "Failed to retrieve integer value"); + ZVAL_LONG( return_value, lfield ); + break; + + case URES_INT_VECTOR: + vfield = ures_getIntVector( source->child, &ilen, &INTL_DATA_ERROR_CODE(source) ); + INTL_METHOD_CHECK_STATUS(source, "Failed to retrieve vector value"); + array_init_size( return_value, ilen ); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); + for (i=0; ime = source->child; + source->child = NULL; + intl_errors_reset(INTL_DATA_ERROR_P(source)); + break; + EMPTY_SWITCH_DEFAULT_CASE(); + } +} +/* }}} */ diff --git a/ext/intl/resourcebundle/resourcebundle.h b/ext/intl/resourcebundle/resourcebundle.h index ddcf75b8c50ac..c46908a8edff2 100644 --- a/ext/intl/resourcebundle/resourcebundle.h +++ b/ext/intl/resourcebundle/resourcebundle.h @@ -21,6 +21,12 @@ #include "resourcebundle/resourcebundle_class.h" +#ifdef __cplusplus +extern "C" { +#endif void resourcebundle_extract_value( zval *target, ResourceBundle_object *source); +#ifdef __cplusplus +} +#endif #endif // #ifndef RESOURCEBUNDLE_CLASS_H diff --git a/ext/intl/resourcebundle/resourcebundle_class.c b/ext/intl/resourcebundle/resourcebundle_class.c deleted file mode 100644 index c64bf1d451849..0000000000000 --- a/ext/intl/resourcebundle/resourcebundle_class.c +++ /dev/null @@ -1,434 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Hans-Peter Oeri (University of St.Gallen) | - +----------------------------------------------------------------------+ - */ - -#include -#include -#include - -#include -#include -#include -#include - -#include "php_intl.h" -#include "intl_data.h" -#include "intl_common.h" - -#include "resourcebundle/resourcebundle.h" -#include "resourcebundle/resourcebundle_iterator.h" -#include "resourcebundle/resourcebundle_class.h" -#include "resourcebundle/resourcebundle_arginfo.h" - -zend_class_entry *ResourceBundle_ce_ptr = NULL; - -static zend_object_handlers ResourceBundle_object_handlers; - -/* {{{ ResourceBundle_object_free */ -static void ResourceBundle_object_free( zend_object *object ) -{ - ResourceBundle_object *rb = php_intl_resourcebundle_fetch_object(object); - - // only free local errors - intl_error_reset( INTL_DATA_ERROR_P(rb) ); - - if (rb->me) { - ures_close( rb->me ); - } - if (rb->child) { - ures_close( rb->child ); - } - - zend_object_std_dtor( &rb->zend ); -} -/* }}} */ - -/* {{{ ResourceBundle_object_create */ -static zend_object *ResourceBundle_object_create( zend_class_entry *ce ) -{ - ResourceBundle_object *rb; - - rb = zend_object_alloc(sizeof(ResourceBundle_object), ce); - - zend_object_std_init( &rb->zend, ce ); - object_properties_init( &rb->zend, ce); - - intl_error_init( INTL_DATA_ERROR_P(rb) ); - rb->me = NULL; - rb->child = NULL; - - return &rb->zend; -} -/* }}} */ - -/* {{{ ResourceBundle_ctor */ -static int resourcebundle_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling *error_handling, bool *error_handling_replaced) -{ - char *bundlename; - size_t bundlename_len = 0; - char *locale; - size_t locale_len = 0; - bool fallback = true; - - zval *object = return_value; - ResourceBundle_object *rb = Z_INTL_RESOURCEBUNDLE_P( object ); - - intl_error_reset( NULL ); - - ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_STRING_OR_NULL(locale, locale_len) - Z_PARAM_STRING_OR_NULL(bundlename, bundlename_len) - Z_PARAM_OPTIONAL - 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; - } - - INTL_CHECK_LOCALE_LEN_OR_FAILURE(locale_len); - - if (locale == NULL) { - locale = (char *)intl_locale_get_default(); - } - - if (bundlename_len >= MAXPATHLEN) { - zend_argument_value_error(2, "is too long"); - return FAILURE; - } - - if (fallback) { - rb->me = ures_open(bundlename, locale, &INTL_DATA_ERROR_CODE(rb)); - } else { - rb->me = ures_openDirect(bundlename, locale, &INTL_DATA_ERROR_CODE(rb)); - } - - INTL_CTOR_CHECK_STATUS(rb, "resourcebundle_ctor: 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 " - "'%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); - efree(pbuf); - return FAILURE; - } - - return SUCCESS; -} -/* }}} */ - -/* {{{ ResourceBundle object constructor */ -PHP_METHOD( ResourceBundle, __construct ) -{ - zend_error_handling error_handling; - bool error_handling_replaced = 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); - } -} -/* }}} */ - -/* {{{ */ -PHP_FUNCTION( resourcebundle_create ) -{ - object_init_ex( return_value, ResourceBundle_ce_ptr ); - if (resourcebundle_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL, NULL) == FAILURE) { - zval_ptr_dtor(return_value); - RETURN_NULL(); - } -} -/* }}} */ - -/* {{{ resourcebundle_array_fetch */ -static zval *resource_bundle_array_fetch( - zend_object *object, zend_string *offset_str, zend_long offset_int, - zval *return_value, bool fallback, uint32_t offset_arg_num) -{ - int32_t index = 0; - char *key = NULL; - bool is_numeric = offset_str == NULL; - char *pbuf; - ResourceBundle_object *rb; - - rb = php_intl_resourcebundle_fetch_object(object); - intl_error_reset(NULL); - intl_error_reset(INTL_DATA_ERROR_P(rb)); - - if (offset_str) { - if (UNEXPECTED(ZSTR_LEN(offset_str) == 0)) { - if (offset_arg_num) { - zend_argument_must_not_be_empty_error(offset_arg_num); - } else { - zend_value_error("Offset must not be empty"); - } - return NULL; - } - key = ZSTR_VAL(offset_str); - rb->child = ures_getByKey(rb->me, key, rb->child, &INTL_DATA_ERROR_CODE(rb) ); - } else { - if (UNEXPECTED(offset_int < (zend_long)INT32_MIN || offset_int > (zend_long)INT32_MAX)) { - if (offset_arg_num) { - zend_argument_value_error(offset_arg_num, "index must be between %d and %d", INT32_MIN, INT32_MAX); - } else { - zend_value_error("Index must be between %d and %d", INT32_MIN, INT32_MAX); - } - return NULL; - } - index = (int32_t)offset_int; - rb->child = ures_getByIndex(rb->me, index, rb->child, &INTL_DATA_ERROR_CODE(rb)); - } - - intl_error_set_code( NULL, INTL_DATA_ERROR_CODE(rb) ); - if (U_FAILURE(INTL_DATA_ERROR_CODE(rb))) { - if (is_numeric) { - spprintf( &pbuf, 0, "Cannot load resource element %d", index ); - } else { - spprintf( &pbuf, 0, "Cannot load resource element '%s'", key ); - } - intl_errors_set_custom_msg( INTL_DATA_ERROR_P(rb), pbuf, 1 ); - efree(pbuf); - RETVAL_NULL(); - return return_value; - } - - if (!fallback && (INTL_DATA_ERROR_CODE(rb) == U_USING_FALLBACK_WARNING || INTL_DATA_ERROR_CODE(rb) == U_USING_DEFAULT_WARNING)) { - UErrorCode icuerror; - const char * locale = ures_getLocaleByType( rb->me, ULOC_ACTUAL_LOCALE, &icuerror ); - if (is_numeric) { - spprintf(&pbuf, 0, "Cannot load element %d without fallback from to %s", index, locale); - } 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); - efree(pbuf); - RETVAL_NULL(); - return return_value; - } - - resourcebundle_extract_value( return_value, rb ); - return return_value; -} -/* }}} */ - -/* {{{ resourcebundle_array_get */ -zval *resourcebundle_array_get(zend_object *object, zval *offset, int type, zval *rv) -{ - if (offset == NULL) { - zend_throw_error(NULL, "Cannot apply [] to ResourceBundle object"); - return NULL; - } - - ZVAL_DEREF(offset); - if (Z_TYPE_P(offset) == IS_LONG) { - return resource_bundle_array_fetch(object, /* offset_str */ NULL, Z_LVAL_P(offset), rv, /* fallback */ true, /* arg_num */ 0); - } else if (Z_TYPE_P(offset) == IS_STRING) { - return resource_bundle_array_fetch(object, Z_STR_P(offset), /* offset_int */ 0, rv, /* fallback */ true, /* arg_num */ 0); - } else { - zend_illegal_container_offset(object->ce->name, offset, type); - return NULL; - } -} -/* }}} */ - -/* {{{ Get resource identified by numerical index or key name. */ -PHP_FUNCTION( resourcebundle_get ) -{ - bool fallback = true; - zend_object *resource_bundle = NULL; - zend_string *offset_str = NULL; - zend_long offset_long = 0; - - ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_OBJ_OF_CLASS(resource_bundle, ResourceBundle_ce_ptr) - Z_PARAM_STR_OR_LONG(offset_str, offset_long) - Z_PARAM_OPTIONAL - Z_PARAM_BOOL(fallback) - ZEND_PARSE_PARAMETERS_END(); - - zval *retval = resource_bundle_array_fetch(resource_bundle, offset_str, offset_long, return_value, fallback, /* arg_num */ 2); - if (!retval) { - RETURN_THROWS(); - } -} -/* }}} */ - -PHP_METHOD(ResourceBundle , get) -{ - bool fallback = true; - zend_string *offset_str = NULL; - zend_long offset_long = 0; - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_STR_OR_LONG(offset_str, offset_long) - Z_PARAM_OPTIONAL - Z_PARAM_BOOL(fallback) - ZEND_PARSE_PARAMETERS_END(); - - zval *retval = resource_bundle_array_fetch(Z_OBJ_P(ZEND_THIS), offset_str, offset_long, return_value, fallback, /* arg_num */ 1); - if (!retval) { - RETURN_THROWS(); - } -} -/* }}} */ - -/* {{{ resourcebundle_array_count */ -static zend_result resourcebundle_array_count(zend_object *object, zend_long *count) -{ - ResourceBundle_object *rb = php_intl_resourcebundle_fetch_object(object); - - if (rb->me == NULL) { - intl_errors_set(&rb->error, U_ILLEGAL_ARGUMENT_ERROR, - "Found unconstructed ResourceBundle", 0); - return 0; - } - - *count = ures_getSize( rb->me ); - - return SUCCESS; -} -/* }}} */ - -/* {{{ Get resources count */ -PHP_FUNCTION( resourcebundle_count ) -{ - int32_t len; - RESOURCEBUNDLE_METHOD_INIT_VARS; - - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", &object, ResourceBundle_ce_ptr ) == FAILURE ) { - RETURN_THROWS(); - } - - RESOURCEBUNDLE_METHOD_FETCH_OBJECT; - - len = ures_getSize( rb->me ); - RETURN_LONG( len ); -} - -/* {{{ Get available locales from ResourceBundle name */ -PHP_FUNCTION( resourcebundle_locales ) -{ - char * bundlename; - size_t bundlename_len = 0; - const char * entry; - int entry_len; - UEnumeration *icuenum; - UErrorCode icuerror = U_ZERO_ERROR; - - intl_errors_reset( NULL ); - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(bundlename, bundlename_len) - ZEND_PARSE_PARAMETERS_END(); - - if (bundlename_len >= MAXPATHLEN) { - zend_argument_value_error(1, "is too long"); - RETURN_THROWS(); - } - - if(bundlename_len == 0) { - // fetch default locales list - bundlename = NULL; - } - - icuenum = ures_openAvailableLocales( bundlename, &icuerror ); - INTL_CHECK_STATUS(icuerror, "Cannot fetch locales list"); - - uenum_reset( icuenum, &icuerror ); - INTL_CHECK_STATUS(icuerror, "Cannot iterate locales list"); - - array_init( return_value ); - while ((entry = uenum_next( icuenum, &entry_len, &icuerror ))) { - add_next_index_stringl( return_value, (char *) entry, entry_len); - } - uenum_close( icuenum ); -} -/* }}} */ - -/* {{{ Get text description for ResourceBundle's last error code. */ -PHP_FUNCTION( resourcebundle_get_error_code ) -{ - RESOURCEBUNDLE_METHOD_INIT_VARS; - - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", - &object, ResourceBundle_ce_ptr ) == FAILURE ) - { - RETURN_THROWS(); - } - - rb = Z_INTL_RESOURCEBUNDLE_P( object ); - - RETURN_LONG(INTL_DATA_ERROR_CODE(rb)); -} -/* }}} */ - -/* {{{ Get text description for ResourceBundle's last error. */ -PHP_FUNCTION( resourcebundle_get_error_message ) -{ - zend_string* message = NULL; - RESOURCEBUNDLE_METHOD_INIT_VARS; - - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", - &object, ResourceBundle_ce_ptr ) == FAILURE ) - { - RETURN_THROWS(); - } - - rb = Z_INTL_RESOURCEBUNDLE_P( object ); - message = intl_error_get_message(INTL_DATA_ERROR_P(rb)); - RETURN_STR(message); -} -/* }}} */ - -PHP_METHOD(ResourceBundle, getIterator) { - ZEND_PARSE_PARAMETERS_NONE(); - - zend_create_internal_iterator_zval(return_value, ZEND_THIS); -} - -/* {{{ resourcebundle_register_class - * Initialize 'ResourceBundle' class - */ -void resourcebundle_register_class( void ) -{ - ResourceBundle_ce_ptr = register_class_ResourceBundle(zend_ce_aggregate, zend_ce_countable); - ResourceBundle_ce_ptr->create_object = ResourceBundle_object_create; - ResourceBundle_ce_ptr->default_object_handlers = &ResourceBundle_object_handlers; - ResourceBundle_ce_ptr->get_iterator = resourcebundle_get_iterator; - - ResourceBundle_object_handlers = std_object_handlers; - ResourceBundle_object_handlers.offset = XtOffsetOf(ResourceBundle_object, zend); - ResourceBundle_object_handlers.clone_obj = NULL; /* ICU ResourceBundle has no clone implementation */ - ResourceBundle_object_handlers.free_obj = ResourceBundle_object_free; - ResourceBundle_object_handlers.read_dimension = resourcebundle_array_get; - ResourceBundle_object_handlers.count_elements = resourcebundle_array_count; -} -/* }}} */ diff --git a/ext/intl/resourcebundle/resourcebundle_class.cpp b/ext/intl/resourcebundle/resourcebundle_class.cpp new file mode 100644 index 0000000000000..d88ba2ad13170 --- /dev/null +++ b/ext/intl/resourcebundle/resourcebundle_class.cpp @@ -0,0 +1,433 @@ +/* + +----------------------------------------------------------------------+ + | 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: Hans-Peter Oeri (University of St.Gallen) | + +----------------------------------------------------------------------+ + */ + +#include +#include +#include + + +extern "C" { +#include +#include +} + +#include +#include + +extern "C" { +#include "php_intl.h" +#include "intl_data.h" +#include "intl_common.h" +#include "resourcebundle/resourcebundle.h" +#include "resourcebundle/resourcebundle_iterator.h" +#include "resourcebundle/resourcebundle_class.h" +#include "resourcebundle/resourcebundle_arginfo.h" +} + +zend_class_entry *ResourceBundle_ce_ptr = NULL; + +static zend_object_handlers ResourceBundle_object_handlers; + +/* {{{ ResourceBundle_object_free */ +static void ResourceBundle_object_free( zend_object *object ) +{ + ResourceBundle_object *rb = php_intl_resourcebundle_fetch_object(object); + + // only free local errors + intl_error_reset( INTL_DATA_ERROR_P(rb) ); + + if (rb->me) { + ures_close( rb->me ); + } + if (rb->child) { + ures_close( rb->child ); + } + + zend_object_std_dtor( &rb->zend ); +} +/* }}} */ + +/* {{{ ResourceBundle_object_create */ +static zend_object *ResourceBundle_object_create( zend_class_entry *ce ) +{ + ResourceBundle_object *rb; + + rb = reinterpret_cast(zend_object_alloc(sizeof(ResourceBundle_object), ce)); + + zend_object_std_init( &rb->zend, ce ); + object_properties_init( &rb->zend, ce); + + intl_error_init( INTL_DATA_ERROR_P(rb) ); + rb->me = NULL; + rb->child = NULL; + + return &rb->zend; +} +/* }}} */ + +/* {{{ ResourceBundle_ctor */ +static zend_result resourcebundle_ctor(INTERNAL_FUNCTION_PARAMETERS) +{ + char *bundlename; + size_t bundlename_len = 0; + char *locale; + size_t locale_len = 0; + bool fallback = true; + + zval *object = return_value; + ResourceBundle_object *rb = Z_INTL_RESOURCEBUNDLE_P( object ); + + intl_error_reset( NULL ); + + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_STRING_OR_NULL(locale, locale_len) + Z_PARAM_STRING_OR_NULL(bundlename, bundlename_len) + Z_PARAM_OPTIONAL + Z_PARAM_BOOL(fallback) + ZEND_PARSE_PARAMETERS_END_EX(return FAILURE); + + if (rb->me) { + zend_throw_error(NULL, "ResourceBundle object is already constructed"); + return FAILURE; + } + + INTL_CHECK_LOCALE_LEN_OR_FAILURE(locale_len); + + if (locale == NULL) { + locale = (char *)intl_locale_get_default(); + } + + if (bundlename_len >= MAXPATHLEN) { + zend_argument_value_error(2, "is too long"); + return FAILURE; + } + + if (fallback) { + rb->me = ures_open(bundlename, locale, &INTL_DATA_ERROR_CODE(rb)); + } else { + rb->me = ures_openDirect(bundlename, locale, &INTL_DATA_ERROR_CODE(rb)); + } + + 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, "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); + efree(pbuf); + return FAILURE; + } + + return SUCCESS; +} +/* }}} */ + +/* {{{ ResourceBundle object constructor */ +PHP_METHOD( ResourceBundle, __construct ) +{ + 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) == FAILURE) { + ZEND_ASSERT(EG(exception)); + } + INTL_G(use_exceptions) = old_use_exception; + INTL_G(error_level) = old_error_level; +} +/* }}} */ + +/* {{{ */ +U_CFUNC PHP_FUNCTION( resourcebundle_create ) +{ + object_init_ex( return_value, ResourceBundle_ce_ptr ); + if (resourcebundle_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU) == FAILURE) { + zval_ptr_dtor(return_value); + RETURN_NULL(); + } +} +/* }}} */ + +/* {{{ resourcebundle_array_fetch */ +static zval *resource_bundle_array_fetch( + zend_object *object, zend_string *offset_str, zend_long offset_int, + zval *return_value, bool fallback, uint32_t offset_arg_num) +{ + int32_t index = 0; + char *key = NULL; + bool is_numeric = offset_str == NULL; + char *pbuf; + ResourceBundle_object *rb; + + rb = php_intl_resourcebundle_fetch_object(object); + intl_error_reset(NULL); + intl_error_reset(INTL_DATA_ERROR_P(rb)); + + if (offset_str) { + if (UNEXPECTED(ZSTR_LEN(offset_str) == 0)) { + if (offset_arg_num) { + zend_argument_must_not_be_empty_error(offset_arg_num); + } else { + zend_value_error("Offset must not be empty"); + } + return NULL; + } + key = ZSTR_VAL(offset_str); + rb->child = ures_getByKey(rb->me, key, rb->child, &INTL_DATA_ERROR_CODE(rb) ); + } else { + if (UNEXPECTED(offset_int < (zend_long)INT32_MIN || offset_int > (zend_long)INT32_MAX)) { + if (offset_arg_num) { + zend_argument_value_error(offset_arg_num, "index must be between %d and %d", INT32_MIN, INT32_MAX); + } else { + zend_value_error("Index must be between %d and %d", INT32_MIN, INT32_MAX); + } + return NULL; + } + index = (int32_t)offset_int; + rb->child = ures_getByIndex(rb->me, index, rb->child, &INTL_DATA_ERROR_CODE(rb)); + } + + intl_error_set_code( NULL, INTL_DATA_ERROR_CODE(rb) ); + if (U_FAILURE(INTL_DATA_ERROR_CODE(rb))) { + if (is_numeric) { + spprintf( &pbuf, 0, "Cannot load resource element %d", index ); + } else { + spprintf( &pbuf, 0, "Cannot load resource element '%s'", key ); + } + intl_errors_set_custom_msg( INTL_DATA_ERROR_P(rb), pbuf); + efree(pbuf); + RETVAL_NULL(); + return return_value; + } + + if (!fallback && (INTL_DATA_ERROR_CODE(rb) == U_USING_FALLBACK_WARNING || INTL_DATA_ERROR_CODE(rb) == U_USING_DEFAULT_WARNING)) { + UErrorCode icuerror; + const char * locale = ures_getLocaleByType( rb->me, ULOC_ACTUAL_LOCALE, &icuerror ); + if (is_numeric) { + spprintf(&pbuf, 0, "Cannot load element %d without fallback from to %s", index, locale); + } 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); + efree(pbuf); + RETVAL_NULL(); + return return_value; + } + + resourcebundle_extract_value( return_value, rb ); + return return_value; +} +/* }}} */ + +/* {{{ resourcebundle_array_get */ +U_CFUNC zval *resourcebundle_array_get(zend_object *object, zval *offset, int type, zval *rv) +{ + if (offset == NULL) { + zend_throw_error(NULL, "Cannot apply [] to ResourceBundle object"); + return NULL; + } + + ZVAL_DEREF(offset); + if (Z_TYPE_P(offset) == IS_LONG) { + return resource_bundle_array_fetch(object, /* offset_str */ NULL, Z_LVAL_P(offset), rv, /* fallback */ true, /* arg_num */ 0); + } else if (Z_TYPE_P(offset) == IS_STRING) { + return resource_bundle_array_fetch(object, Z_STR_P(offset), /* offset_int */ 0, rv, /* fallback */ true, /* arg_num */ 0); + } else { + zend_illegal_container_offset(object->ce->name, offset, type); + return NULL; + } +} +/* }}} */ + +/* {{{ Get resource identified by numerical index or key name. */ +U_CFUNC PHP_FUNCTION( resourcebundle_get ) +{ + bool fallback = true; + zend_object *resource_bundle = NULL; + zend_string *offset_str = NULL; + zend_long offset_long = 0; + + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_OBJ_OF_CLASS(resource_bundle, ResourceBundle_ce_ptr) + Z_PARAM_STR_OR_LONG(offset_str, offset_long) + Z_PARAM_OPTIONAL + Z_PARAM_BOOL(fallback) + ZEND_PARSE_PARAMETERS_END(); + + zval *retval = resource_bundle_array_fetch(resource_bundle, offset_str, offset_long, return_value, fallback, /* arg_num */ 2); + if (!retval) { + RETURN_THROWS(); + } +} +/* }}} */ + +PHP_METHOD(ResourceBundle , get) +{ + bool fallback = true; + zend_string *offset_str = NULL; + zend_long offset_long = 0; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STR_OR_LONG(offset_str, offset_long) + Z_PARAM_OPTIONAL + Z_PARAM_BOOL(fallback) + ZEND_PARSE_PARAMETERS_END(); + + zval *retval = resource_bundle_array_fetch(Z_OBJ_P(ZEND_THIS), offset_str, offset_long, return_value, fallback, /* arg_num */ 1); + if (!retval) { + RETURN_THROWS(); + } +} +/* }}} */ + +/* {{{ resourcebundle_array_count */ +static zend_result resourcebundle_array_count(zend_object *object, zend_long *count) +{ + ResourceBundle_object *rb = php_intl_resourcebundle_fetch_object(object); + + if (rb->me == NULL) { + intl_errors_set(&rb->error, U_ILLEGAL_ARGUMENT_ERROR, + "Found unconstructed ResourceBundle"); + return FAILURE; + } + + *count = ures_getSize( rb->me ); + + return SUCCESS; +} +/* }}} */ + +/* {{{ Get resources count */ +U_CFUNC PHP_FUNCTION( resourcebundle_count ) +{ + int32_t len; + RESOURCEBUNDLE_METHOD_INIT_VARS; + + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", &object, ResourceBundle_ce_ptr ) == FAILURE ) { + RETURN_THROWS(); + } + + RESOURCEBUNDLE_METHOD_FETCH_OBJECT; + + len = ures_getSize( rb->me ); + RETURN_LONG( len ); +} + +/* {{{ Get available locales from ResourceBundle name */ +U_CFUNC PHP_FUNCTION( resourcebundle_locales ) +{ + char * bundlename; + size_t bundlename_len = 0; + const char * entry; + int entry_len; + UEnumeration *icuenum; + UErrorCode icuerror = U_ZERO_ERROR; + + intl_errors_reset( NULL ); + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STRING(bundlename, bundlename_len) + ZEND_PARSE_PARAMETERS_END(); + + if (bundlename_len >= MAXPATHLEN) { + zend_argument_value_error(1, "is too long"); + RETURN_THROWS(); + } + + if(bundlename_len == 0) { + // fetch default locales list + bundlename = NULL; + } + + icuenum = ures_openAvailableLocales( bundlename, &icuerror ); + INTL_CHECK_STATUS(icuerror, "Cannot fetch locales list"); + + uenum_reset( icuenum, &icuerror ); + INTL_CHECK_STATUS(icuerror, "Cannot iterate locales list"); + + array_init( return_value ); + while ((entry = uenum_next( icuenum, &entry_len, &icuerror ))) { + add_next_index_stringl( return_value, (char *) entry, entry_len); + } + uenum_close( icuenum ); +} +/* }}} */ + +/* {{{ Get text description for ResourceBundle's last error code. */ +U_CFUNC PHP_FUNCTION( resourcebundle_get_error_code ) +{ + RESOURCEBUNDLE_METHOD_INIT_VARS; + + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", + &object, ResourceBundle_ce_ptr ) == FAILURE ) + { + RETURN_THROWS(); + } + + rb = Z_INTL_RESOURCEBUNDLE_P( object ); + + RETURN_LONG(INTL_DATA_ERROR_CODE(rb)); +} +/* }}} */ + +/* {{{ Get text description for ResourceBundle's last error. */ +U_CFUNC PHP_FUNCTION( resourcebundle_get_error_message ) +{ + zend_string* message = NULL; + RESOURCEBUNDLE_METHOD_INIT_VARS; + + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", + &object, ResourceBundle_ce_ptr ) == FAILURE ) + { + RETURN_THROWS(); + } + + rb = Z_INTL_RESOURCEBUNDLE_P( object ); + message = intl_error_get_message(INTL_DATA_ERROR_P(rb)); + RETURN_STR(message); +} +/* }}} */ + +PHP_METHOD(ResourceBundle, getIterator) { + ZEND_PARSE_PARAMETERS_NONE(); + + zend_create_internal_iterator_zval(return_value, ZEND_THIS); +} + +/* {{{ resourcebundle_register_class + * Initialize 'ResourceBundle' class + */ +U_CFUNC void resourcebundle_register_class( void ) +{ + ResourceBundle_ce_ptr = register_class_ResourceBundle(zend_ce_aggregate, zend_ce_countable); + ResourceBundle_ce_ptr->create_object = ResourceBundle_object_create; + ResourceBundle_ce_ptr->default_object_handlers = &ResourceBundle_object_handlers; + ResourceBundle_ce_ptr->get_iterator = resourcebundle_get_iterator; + + ResourceBundle_object_handlers = std_object_handlers; + ResourceBundle_object_handlers.offset = XtOffsetOf(ResourceBundle_object, zend); + ResourceBundle_object_handlers.clone_obj = NULL; /* ICU ResourceBundle has no clone implementation */ + ResourceBundle_object_handlers.free_obj = ResourceBundle_object_free; + ResourceBundle_object_handlers.read_dimension = resourcebundle_array_get; + ResourceBundle_object_handlers.count_elements = resourcebundle_array_count; +} +/* }}} */ diff --git a/ext/intl/resourcebundle/resourcebundle_class.h b/ext/intl/resourcebundle/resourcebundle_class.h index be397c8d47601..334532bde99b7 100644 --- a/ext/intl/resourcebundle/resourcebundle_class.h +++ b/ext/intl/resourcebundle/resourcebundle_class.h @@ -18,9 +18,14 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif #include "php.h" - #include "intl_error.h" +#ifdef __cplusplus +} +#endif typedef struct { intl_error error; @@ -46,7 +51,13 @@ static inline ResourceBundle_object *php_intl_resourcebundle_fetch_object(zend_o #define RESOURCEBUNDLE_OBJECT(rb) (rb)->me +#ifdef __cplusplus +extern "C" { +#endif void resourcebundle_register_class( void ); extern zend_class_entry *ResourceBundle_ce_ptr; +#ifdef __cplusplus +} +#endif #endif // #ifndef RESOURCEBUNDLE_CLASS_H diff --git a/ext/intl/resourcebundle/resourcebundle_iterator.c b/ext/intl/resourcebundle/resourcebundle_iterator.c deleted file mode 100644 index c79269e475070..0000000000000 --- a/ext/intl/resourcebundle/resourcebundle_iterator.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Hans-Peter Oeri (University of St.Gallen) | - +----------------------------------------------------------------------+ - */ - -#include -#include -#include - -#include "resourcebundle/resourcebundle.h" -#include "resourcebundle/resourcebundle_class.h" -#include "resourcebundle/resourcebundle_iterator.h" - -/* - * Although libicu offers iterator functions, they are not used here: libicu does iterate - * irrespective of array indices. Those cannot be recreated afterwards. Arrays as well as tables - * can however be accessed by numerical index, with table keys readable ex post. - */ - -/* {{{ resourcebundle_iterator_read */ -static void resourcebundle_iterator_read( ResourceBundle_iterator *iterator ) -{ - UErrorCode icuerror = U_ZERO_ERROR; - ResourceBundle_object *rb = iterator->subject; - - rb->child = ures_getByIndex( rb->me, iterator->i, rb->child, &icuerror ); - - if (U_SUCCESS(icuerror)) { - /* ATTN: key extraction must be the first thing to do... rb->child might be reset in read! */ - if (iterator->is_table) { - iterator->currentkey = estrdup( ures_getKey( rb->child ) ); - } - resourcebundle_extract_value( &iterator->current, rb ); - } - else { - ZVAL_UNDEF(&iterator->current); - } -} -/* }}} */ - -/* {{{ resourcebundle_iterator_invalidate */ -static void resourcebundle_iterator_invalidate( zend_object_iterator *iter ) -{ - ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter; - - if (!Z_ISUNDEF(iterator->current)) { - zval_ptr_dtor( &iterator->current ); - ZVAL_UNDEF(&iterator->current); - } - if (iterator->currentkey) { - efree( iterator->currentkey ); - iterator->currentkey = NULL; - } -} -/* }}} */ - -/* {{{ resourcebundle_iterator_dtor */ -static void resourcebundle_iterator_dtor( zend_object_iterator *iter ) -{ - ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter; - zval *object = &iterator->intern.data; - - resourcebundle_iterator_invalidate( iter ); - - zval_ptr_dtor(object); -} -/* }}} */ - -/* {{{ resourcebundle_iterator_has_more */ -static zend_result resourcebundle_iterator_has_more( zend_object_iterator *iter ) -{ - ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter; - return (iterator->i < iterator->length) ? SUCCESS : FAILURE; -} -/* }}} */ - -/* {{{ resourcebundle_iterator_current */ -static zval *resourcebundle_iterator_current( zend_object_iterator *iter ) -{ - ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter; - if (Z_ISUNDEF(iterator->current)) { - resourcebundle_iterator_read( iterator); - } - return &iterator->current; -} -/* }}} */ - -/* {{{ resourcebundle_iterator_key */ -static void resourcebundle_iterator_key( zend_object_iterator *iter, zval *key ) -{ - ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter; - - if (Z_ISUNDEF(iterator->current)) { - resourcebundle_iterator_read( iterator); - } - - if (iterator->is_table) { - ZVAL_STRING(key, iterator->currentkey); - } else { - ZVAL_LONG(key, iterator->i); - } -} -/* }}} */ - -/* {{{ resourcebundle_iterator_step */ -static void resourcebundle_iterator_step( zend_object_iterator *iter ) -{ - ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter; - - iterator->i++; - resourcebundle_iterator_invalidate( iter ); -} -/* }}} */ - -/* {{{ resourcebundle_iterator_has_reset */ -static void resourcebundle_iterator_reset( zend_object_iterator *iter ) -{ - ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter; - - iterator->i = 0; - resourcebundle_iterator_invalidate( iter ); -} -/* }}} */ - -/* {{{ resourcebundle_iterator_funcs */ -static const zend_object_iterator_funcs resourcebundle_iterator_funcs = { - resourcebundle_iterator_dtor, - resourcebundle_iterator_has_more, - resourcebundle_iterator_current, - resourcebundle_iterator_key, - resourcebundle_iterator_step, - resourcebundle_iterator_reset, - resourcebundle_iterator_invalidate, - NULL, /* get_gc */ -}; -/* }}} */ - -/* {{{ resourcebundle_get_iterator */ -zend_object_iterator *resourcebundle_get_iterator( zend_class_entry *ce, zval *object, int byref ) -{ - if (byref) { - zend_throw_error(NULL, "An iterator cannot be used with foreach by reference"); - return NULL; - } - - ResourceBundle_object *rb = Z_INTL_RESOURCEBUNDLE_P(object ); - ResourceBundle_iterator *iterator = emalloc( sizeof( ResourceBundle_iterator ) ); - - zend_iterator_init(&iterator->intern); - Z_ADDREF_P(object); - ZVAL_OBJ(&iterator->intern.data, Z_OBJ_P(object)); - iterator->intern.funcs = &resourcebundle_iterator_funcs; - - iterator->subject = rb; - - /* The iterated rb can only be either URES_TABLE or URES_ARRAY - * All other types are returned as php primitives! - */ - iterator->is_table = (ures_getType( rb->me ) == URES_TABLE); - iterator->length = ures_getSize( rb->me ); - - ZVAL_UNDEF(&iterator->current); - iterator->currentkey = NULL; - iterator->i = 0; - - return (zend_object_iterator *) iterator; -} -/* }}} */ diff --git a/ext/intl/resourcebundle/resourcebundle_iterator.cpp b/ext/intl/resourcebundle/resourcebundle_iterator.cpp new file mode 100644 index 0000000000000..7747b34adbd4c --- /dev/null +++ b/ext/intl/resourcebundle/resourcebundle_iterator.cpp @@ -0,0 +1,179 @@ +/* + +----------------------------------------------------------------------+ + | 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: Hans-Peter Oeri (University of St.Gallen) | + +----------------------------------------------------------------------+ + */ + +extern "C" { +#include +#include +#include +} + +#include "resourcebundle/resourcebundle.h" +#include "resourcebundle/resourcebundle_class.h" +#include "resourcebundle/resourcebundle_iterator.h" + +/* + * Although libicu offers iterator functions, they are not used here: libicu does iterate + * irrespective of array indices. Those cannot be recreated afterwards. Arrays as well as tables + * can however be accessed by numerical index, with table keys readable ex post. + */ + +/* {{{ resourcebundle_iterator_read */ +static void resourcebundle_iterator_read( ResourceBundle_iterator *iterator ) +{ + UErrorCode icuerror = U_ZERO_ERROR; + ResourceBundle_object *rb = iterator->subject; + + rb->child = ures_getByIndex( rb->me, iterator->i, rb->child, &icuerror ); + + if (U_SUCCESS(icuerror)) { + /* ATTN: key extraction must be the first thing to do... rb->child might be reset in read! */ + if (iterator->is_table) { + iterator->currentkey = estrdup( ures_getKey( rb->child ) ); + } + resourcebundle_extract_value( &iterator->current, rb ); + } + else { + ZVAL_UNDEF(&iterator->current); + } +} +/* }}} */ + +/* {{{ resourcebundle_iterator_invalidate */ +static void resourcebundle_iterator_invalidate( zend_object_iterator *iter ) +{ + ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter; + + if (!Z_ISUNDEF(iterator->current)) { + zval_ptr_dtor( &iterator->current ); + ZVAL_UNDEF(&iterator->current); + } + if (iterator->currentkey) { + efree( iterator->currentkey ); + iterator->currentkey = NULL; + } +} +/* }}} */ + +/* {{{ resourcebundle_iterator_dtor */ +static void resourcebundle_iterator_dtor( zend_object_iterator *iter ) +{ + ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter; + zval *object = &iterator->intern.data; + + resourcebundle_iterator_invalidate( iter ); + + zval_ptr_dtor(object); +} +/* }}} */ + +/* {{{ resourcebundle_iterator_has_more */ +static zend_result resourcebundle_iterator_has_more( zend_object_iterator *iter ) +{ + ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter; + return (iterator->i < iterator->length) ? SUCCESS : FAILURE; +} +/* }}} */ + +/* {{{ resourcebundle_iterator_current */ +static zval *resourcebundle_iterator_current( zend_object_iterator *iter ) +{ + ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter; + if (Z_ISUNDEF(iterator->current)) { + resourcebundle_iterator_read( iterator); + } + return &iterator->current; +} +/* }}} */ + +/* {{{ resourcebundle_iterator_key */ +static void resourcebundle_iterator_key( zend_object_iterator *iter, zval *key ) +{ + ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter; + + if (Z_ISUNDEF(iterator->current)) { + resourcebundle_iterator_read( iterator); + } + + if (iterator->is_table) { + ZVAL_STRING(key, iterator->currentkey); + } else { + ZVAL_LONG(key, iterator->i); + } +} +/* }}} */ + +/* {{{ resourcebundle_iterator_step */ +static void resourcebundle_iterator_step( zend_object_iterator *iter ) +{ + ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter; + + iterator->i++; + resourcebundle_iterator_invalidate( iter ); +} +/* }}} */ + +/* {{{ resourcebundle_iterator_has_reset */ +static void resourcebundle_iterator_reset( zend_object_iterator *iter ) +{ + ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter; + + iterator->i = 0; + resourcebundle_iterator_invalidate( iter ); +} +/* }}} */ + +/* {{{ resourcebundle_iterator_funcs */ +static const zend_object_iterator_funcs resourcebundle_iterator_funcs = { + resourcebundle_iterator_dtor, + resourcebundle_iterator_has_more, + resourcebundle_iterator_current, + resourcebundle_iterator_key, + resourcebundle_iterator_step, + resourcebundle_iterator_reset, + resourcebundle_iterator_invalidate, + NULL, /* get_gc */ +}; +/* }}} */ + +/* {{{ resourcebundle_get_iterator */ +U_CFUNC zend_object_iterator *resourcebundle_get_iterator( zend_class_entry *ce, zval *object, int byref ) +{ + if (byref) { + zend_throw_error(NULL, "An iterator cannot be used with foreach by reference"); + return NULL; + } + + ResourceBundle_object *rb = Z_INTL_RESOURCEBUNDLE_P(object ); + ResourceBundle_iterator *iterator = reinterpret_cast(emalloc( sizeof( ResourceBundle_iterator )) ); + + zend_iterator_init(&iterator->intern); + Z_ADDREF_P(object); + ZVAL_OBJ(&iterator->intern.data, Z_OBJ_P(object)); + iterator->intern.funcs = &resourcebundle_iterator_funcs; + + iterator->subject = rb; + + /* The iterated rb can only be either URES_TABLE or URES_ARRAY + * All other types are returned as php primitives! + */ + iterator->is_table = (ures_getType( rb->me ) == URES_TABLE); + iterator->length = ures_getSize( rb->me ); + + ZVAL_UNDEF(&iterator->current); + iterator->currentkey = NULL; + iterator->i = 0; + + return (zend_object_iterator *) iterator; +} +/* }}} */ diff --git a/ext/intl/resourcebundle/resourcebundle_iterator.h b/ext/intl/resourcebundle/resourcebundle_iterator.h index 1ad948723160f..c323d4e17b4c9 100644 --- a/ext/intl/resourcebundle/resourcebundle_iterator.h +++ b/ext/intl/resourcebundle/resourcebundle_iterator.h @@ -29,6 +29,12 @@ typedef struct { zend_long i; } ResourceBundle_iterator; +#ifdef __cplusplus +extern "C" { +#endif zend_object_iterator *resourcebundle_get_iterator( zend_class_entry *ce, zval *object, int byref ); +#ifdef __cplusplus +} +#endif #endif // #ifndef RESOURCEBUNDLE_ITERATOR_H diff --git a/ext/intl/spoofchecker/spoofchecker_arginfo.h b/ext/intl/spoofchecker/spoofchecker_arginfo.h index 6a3c0e55aa27d..fa8996b8f24eb 100644 --- a/ext/intl/spoofchecker/spoofchecker_arginfo.h +++ b/ext/intl/spoofchecker/spoofchecker_arginfo.h @@ -66,122 +66,122 @@ static zend_class_entry *register_class_Spoofchecker(void) zval const_SINGLE_SCRIPT_CONFUSABLE_value; ZVAL_LONG(&const_SINGLE_SCRIPT_CONFUSABLE_value, USPOOF_SINGLE_SCRIPT_CONFUSABLE); - zend_string *const_SINGLE_SCRIPT_CONFUSABLE_name = zend_string_init_interned("SINGLE_SCRIPT_CONFUSABLE", sizeof("SINGLE_SCRIPT_CONFUSABLE") - 1, 1); + zend_string *const_SINGLE_SCRIPT_CONFUSABLE_name = zend_string_init_interned("SINGLE_SCRIPT_CONFUSABLE", sizeof("SINGLE_SCRIPT_CONFUSABLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_SINGLE_SCRIPT_CONFUSABLE_name, &const_SINGLE_SCRIPT_CONFUSABLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SINGLE_SCRIPT_CONFUSABLE_name); + zend_string_release_ex(const_SINGLE_SCRIPT_CONFUSABLE_name, true); zval const_MIXED_SCRIPT_CONFUSABLE_value; ZVAL_LONG(&const_MIXED_SCRIPT_CONFUSABLE_value, USPOOF_MIXED_SCRIPT_CONFUSABLE); - zend_string *const_MIXED_SCRIPT_CONFUSABLE_name = zend_string_init_interned("MIXED_SCRIPT_CONFUSABLE", sizeof("MIXED_SCRIPT_CONFUSABLE") - 1, 1); + zend_string *const_MIXED_SCRIPT_CONFUSABLE_name = zend_string_init_interned("MIXED_SCRIPT_CONFUSABLE", sizeof("MIXED_SCRIPT_CONFUSABLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_MIXED_SCRIPT_CONFUSABLE_name, &const_MIXED_SCRIPT_CONFUSABLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_MIXED_SCRIPT_CONFUSABLE_name); + zend_string_release_ex(const_MIXED_SCRIPT_CONFUSABLE_name, true); zval const_WHOLE_SCRIPT_CONFUSABLE_value; ZVAL_LONG(&const_WHOLE_SCRIPT_CONFUSABLE_value, USPOOF_WHOLE_SCRIPT_CONFUSABLE); - zend_string *const_WHOLE_SCRIPT_CONFUSABLE_name = zend_string_init_interned("WHOLE_SCRIPT_CONFUSABLE", sizeof("WHOLE_SCRIPT_CONFUSABLE") - 1, 1); + zend_string *const_WHOLE_SCRIPT_CONFUSABLE_name = zend_string_init_interned("WHOLE_SCRIPT_CONFUSABLE", sizeof("WHOLE_SCRIPT_CONFUSABLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_WHOLE_SCRIPT_CONFUSABLE_name, &const_WHOLE_SCRIPT_CONFUSABLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WHOLE_SCRIPT_CONFUSABLE_name); + zend_string_release_ex(const_WHOLE_SCRIPT_CONFUSABLE_name, true); zval const_ANY_CASE_value; ZVAL_LONG(&const_ANY_CASE_value, USPOOF_ANY_CASE); - zend_string *const_ANY_CASE_name = zend_string_init_interned("ANY_CASE", sizeof("ANY_CASE") - 1, 1); + zend_string *const_ANY_CASE_name = zend_string_init_interned("ANY_CASE", sizeof("ANY_CASE") - 1, true); zend_declare_typed_class_constant(class_entry, const_ANY_CASE_name, &const_ANY_CASE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ANY_CASE_name); + zend_string_release_ex(const_ANY_CASE_name, true); zval const_SINGLE_SCRIPT_value; ZVAL_LONG(&const_SINGLE_SCRIPT_value, USPOOF_SINGLE_SCRIPT); - zend_string *const_SINGLE_SCRIPT_name = zend_string_init_interned("SINGLE_SCRIPT", sizeof("SINGLE_SCRIPT") - 1, 1); + zend_string *const_SINGLE_SCRIPT_name = zend_string_init_interned("SINGLE_SCRIPT", sizeof("SINGLE_SCRIPT") - 1, true); zend_declare_typed_class_constant(class_entry, const_SINGLE_SCRIPT_name, &const_SINGLE_SCRIPT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SINGLE_SCRIPT_name); + zend_string_release_ex(const_SINGLE_SCRIPT_name, true); zval const_INVISIBLE_value; ZVAL_LONG(&const_INVISIBLE_value, USPOOF_INVISIBLE); - zend_string *const_INVISIBLE_name = zend_string_init_interned("INVISIBLE", sizeof("INVISIBLE") - 1, 1); + zend_string *const_INVISIBLE_name = zend_string_init_interned("INVISIBLE", sizeof("INVISIBLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_INVISIBLE_name, &const_INVISIBLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_INVISIBLE_name); + zend_string_release_ex(const_INVISIBLE_name, true); zval const_CHAR_LIMIT_value; ZVAL_LONG(&const_CHAR_LIMIT_value, USPOOF_CHAR_LIMIT); - zend_string *const_CHAR_LIMIT_name = zend_string_init_interned("CHAR_LIMIT", sizeof("CHAR_LIMIT") - 1, 1); + zend_string *const_CHAR_LIMIT_name = zend_string_init_interned("CHAR_LIMIT", sizeof("CHAR_LIMIT") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_LIMIT_name, &const_CHAR_LIMIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_LIMIT_name); + zend_string_release_ex(const_CHAR_LIMIT_name, true); #if U_ICU_VERSION_MAJOR_NUM >= 58 zval const_ASCII_value; ZVAL_LONG(&const_ASCII_value, USPOOF_ASCII); - zend_string *const_ASCII_name = zend_string_init_interned("ASCII", sizeof("ASCII") - 1, 1); + zend_string *const_ASCII_name = zend_string_init_interned("ASCII", sizeof("ASCII") - 1, true); zend_declare_typed_class_constant(class_entry, const_ASCII_name, &const_ASCII_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ASCII_name); + zend_string_release_ex(const_ASCII_name, true); zval const_HIGHLY_RESTRICTIVE_value; ZVAL_LONG(&const_HIGHLY_RESTRICTIVE_value, USPOOF_HIGHLY_RESTRICTIVE); - zend_string *const_HIGHLY_RESTRICTIVE_name = zend_string_init_interned("HIGHLY_RESTRICTIVE", sizeof("HIGHLY_RESTRICTIVE") - 1, 1); + zend_string *const_HIGHLY_RESTRICTIVE_name = zend_string_init_interned("HIGHLY_RESTRICTIVE", sizeof("HIGHLY_RESTRICTIVE") - 1, true); zend_declare_typed_class_constant(class_entry, const_HIGHLY_RESTRICTIVE_name, &const_HIGHLY_RESTRICTIVE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_HIGHLY_RESTRICTIVE_name); + zend_string_release_ex(const_HIGHLY_RESTRICTIVE_name, true); zval const_MODERATELY_RESTRICTIVE_value; ZVAL_LONG(&const_MODERATELY_RESTRICTIVE_value, USPOOF_MODERATELY_RESTRICTIVE); - zend_string *const_MODERATELY_RESTRICTIVE_name = zend_string_init_interned("MODERATELY_RESTRICTIVE", sizeof("MODERATELY_RESTRICTIVE") - 1, 1); + zend_string *const_MODERATELY_RESTRICTIVE_name = zend_string_init_interned("MODERATELY_RESTRICTIVE", sizeof("MODERATELY_RESTRICTIVE") - 1, true); zend_declare_typed_class_constant(class_entry, const_MODERATELY_RESTRICTIVE_name, &const_MODERATELY_RESTRICTIVE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_MODERATELY_RESTRICTIVE_name); + zend_string_release_ex(const_MODERATELY_RESTRICTIVE_name, true); zval const_MINIMALLY_RESTRICTIVE_value; ZVAL_LONG(&const_MINIMALLY_RESTRICTIVE_value, USPOOF_MINIMALLY_RESTRICTIVE); - zend_string *const_MINIMALLY_RESTRICTIVE_name = zend_string_init_interned("MINIMALLY_RESTRICTIVE", sizeof("MINIMALLY_RESTRICTIVE") - 1, 1); + zend_string *const_MINIMALLY_RESTRICTIVE_name = zend_string_init_interned("MINIMALLY_RESTRICTIVE", sizeof("MINIMALLY_RESTRICTIVE") - 1, true); zend_declare_typed_class_constant(class_entry, const_MINIMALLY_RESTRICTIVE_name, &const_MINIMALLY_RESTRICTIVE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_MINIMALLY_RESTRICTIVE_name); + zend_string_release_ex(const_MINIMALLY_RESTRICTIVE_name, true); zval const_UNRESTRICTIVE_value; ZVAL_LONG(&const_UNRESTRICTIVE_value, USPOOF_UNRESTRICTIVE); - zend_string *const_UNRESTRICTIVE_name = zend_string_init_interned("UNRESTRICTIVE", sizeof("UNRESTRICTIVE") - 1, 1); + zend_string *const_UNRESTRICTIVE_name = zend_string_init_interned("UNRESTRICTIVE", sizeof("UNRESTRICTIVE") - 1, true); zend_declare_typed_class_constant(class_entry, const_UNRESTRICTIVE_name, &const_UNRESTRICTIVE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_UNRESTRICTIVE_name); + zend_string_release_ex(const_UNRESTRICTIVE_name, true); zval const_SINGLE_SCRIPT_RESTRICTIVE_value; ZVAL_LONG(&const_SINGLE_SCRIPT_RESTRICTIVE_value, USPOOF_SINGLE_SCRIPT_RESTRICTIVE); - zend_string *const_SINGLE_SCRIPT_RESTRICTIVE_name = zend_string_init_interned("SINGLE_SCRIPT_RESTRICTIVE", sizeof("SINGLE_SCRIPT_RESTRICTIVE") - 1, 1); + zend_string *const_SINGLE_SCRIPT_RESTRICTIVE_name = zend_string_init_interned("SINGLE_SCRIPT_RESTRICTIVE", sizeof("SINGLE_SCRIPT_RESTRICTIVE") - 1, true); zend_declare_typed_class_constant(class_entry, const_SINGLE_SCRIPT_RESTRICTIVE_name, &const_SINGLE_SCRIPT_RESTRICTIVE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SINGLE_SCRIPT_RESTRICTIVE_name); + zend_string_release_ex(const_SINGLE_SCRIPT_RESTRICTIVE_name, true); zval const_MIXED_NUMBERS_value; ZVAL_LONG(&const_MIXED_NUMBERS_value, USPOOF_MIXED_NUMBERS); - zend_string *const_MIXED_NUMBERS_name = zend_string_init_interned("MIXED_NUMBERS", sizeof("MIXED_NUMBERS") - 1, 1); + zend_string *const_MIXED_NUMBERS_name = zend_string_init_interned("MIXED_NUMBERS", sizeof("MIXED_NUMBERS") - 1, true); zend_declare_typed_class_constant(class_entry, const_MIXED_NUMBERS_name, &const_MIXED_NUMBERS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_MIXED_NUMBERS_name); + zend_string_release_ex(const_MIXED_NUMBERS_name, true); #endif #if U_ICU_VERSION_MAJOR_NUM >= 62 zval const_HIDDEN_OVERLAY_value; ZVAL_LONG(&const_HIDDEN_OVERLAY_value, USPOOF_HIDDEN_OVERLAY); - zend_string *const_HIDDEN_OVERLAY_name = zend_string_init_interned("HIDDEN_OVERLAY", sizeof("HIDDEN_OVERLAY") - 1, 1); + zend_string *const_HIDDEN_OVERLAY_name = zend_string_init_interned("HIDDEN_OVERLAY", sizeof("HIDDEN_OVERLAY") - 1, true); zend_declare_typed_class_constant(class_entry, const_HIDDEN_OVERLAY_name, &const_HIDDEN_OVERLAY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_HIDDEN_OVERLAY_name); + zend_string_release_ex(const_HIDDEN_OVERLAY_name, true); #endif zval const_IGNORE_SPACE_value; ZVAL_LONG(&const_IGNORE_SPACE_value, USET_IGNORE_SPACE); - zend_string *const_IGNORE_SPACE_name = zend_string_init_interned("IGNORE_SPACE", sizeof("IGNORE_SPACE") - 1, 1); + zend_string *const_IGNORE_SPACE_name = zend_string_init_interned("IGNORE_SPACE", sizeof("IGNORE_SPACE") - 1, true); zend_declare_typed_class_constant(class_entry, const_IGNORE_SPACE_name, &const_IGNORE_SPACE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IGNORE_SPACE_name); + zend_string_release_ex(const_IGNORE_SPACE_name, true); zval const_CASE_INSENSITIVE_value; ZVAL_LONG(&const_CASE_INSENSITIVE_value, USET_CASE_INSENSITIVE); - zend_string *const_CASE_INSENSITIVE_name = zend_string_init_interned("CASE_INSENSITIVE", sizeof("CASE_INSENSITIVE") - 1, 1); + zend_string *const_CASE_INSENSITIVE_name = zend_string_init_interned("CASE_INSENSITIVE", sizeof("CASE_INSENSITIVE") - 1, true); zend_declare_typed_class_constant(class_entry, const_CASE_INSENSITIVE_name, &const_CASE_INSENSITIVE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CASE_INSENSITIVE_name); + zend_string_release_ex(const_CASE_INSENSITIVE_name, true); zval const_ADD_CASE_MAPPINGS_value; ZVAL_LONG(&const_ADD_CASE_MAPPINGS_value, USET_ADD_CASE_MAPPINGS); - zend_string *const_ADD_CASE_MAPPINGS_name = zend_string_init_interned("ADD_CASE_MAPPINGS", sizeof("ADD_CASE_MAPPINGS") - 1, 1); + zend_string *const_ADD_CASE_MAPPINGS_name = zend_string_init_interned("ADD_CASE_MAPPINGS", sizeof("ADD_CASE_MAPPINGS") - 1, true); zend_declare_typed_class_constant(class_entry, const_ADD_CASE_MAPPINGS_name, &const_ADD_CASE_MAPPINGS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ADD_CASE_MAPPINGS_name); + zend_string_release_ex(const_ADD_CASE_MAPPINGS_name, true); #if U_ICU_VERSION_MAJOR_NUM >= 73 zval const_SIMPLE_CASE_INSENSITIVE_value; ZVAL_LONG(&const_SIMPLE_CASE_INSENSITIVE_value, USET_SIMPLE_CASE_INSENSITIVE); - zend_string *const_SIMPLE_CASE_INSENSITIVE_name = zend_string_init_interned("SIMPLE_CASE_INSENSITIVE", sizeof("SIMPLE_CASE_INSENSITIVE") - 1, 1); + zend_string *const_SIMPLE_CASE_INSENSITIVE_name = zend_string_init_interned("SIMPLE_CASE_INSENSITIVE", sizeof("SIMPLE_CASE_INSENSITIVE") - 1, true); zend_declare_typed_class_constant(class_entry, const_SIMPLE_CASE_INSENSITIVE_name, &const_SIMPLE_CASE_INSENSITIVE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SIMPLE_CASE_INSENSITIVE_name); + zend_string_release_ex(const_SIMPLE_CASE_INSENSITIVE_name, true); #endif return class_entry; diff --git a/ext/intl/spoofchecker/spoofchecker_class.c b/ext/intl/spoofchecker/spoofchecker_class.c deleted file mode 100644 index 6fa59edd47b00..0000000000000 --- a/ext/intl/spoofchecker/spoofchecker_class.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Scott MacVicar | - +----------------------------------------------------------------------+ - */ - -#include "spoofchecker_class.h" -#include "spoofchecker_arginfo.h" -#include "php_intl.h" -#include "intl_error.h" - -#include - -zend_class_entry *Spoofchecker_ce_ptr = NULL; -static zend_object_handlers Spoofchecker_handlers; - -/* - * Auxiliary functions needed by objects of 'Spoofchecker' class - */ - -/* {{{ Spoofchecker_objects_free */ -void Spoofchecker_objects_free(zend_object *object) -{ - Spoofchecker_object* co = php_intl_spoofchecker_fetch_object(object); - - zend_object_std_dtor(&co->zo); - - spoofchecker_object_destroy(co); -} -/* }}} */ - -/* {{{ Spoofchecker_object_create */ -zend_object *Spoofchecker_object_create(zend_class_entry *ce) -{ - Spoofchecker_object* intern; - - intern = zend_object_alloc(sizeof(Spoofchecker_object), ce); - intl_error_init(SPOOFCHECKER_ERROR_P(intern)); - zend_object_std_init(&intern->zo, ce); - object_properties_init(&intern->zo, ce); - - return &intern->zo; -} -/* }}} */ - -/* - * 'Spoofchecker' class registration structures & functions - */ - -/* {{{ Spoofchecker_class_functions - * Every 'Spoofchecker' class method has an entry in this table - */ - -static zend_object *spoofchecker_clone_obj(zend_object *object) /* {{{ */ -{ - Spoofchecker_object *spoofchecker_orig = php_intl_spoofchecker_fetch_object(object); - zend_object *new_obj_val = Spoofchecker_ce_ptr->create_object(object->ce); - Spoofchecker_object *spoofchecker_new = php_intl_spoofchecker_fetch_object(new_obj_val); - - zend_objects_clone_members(&spoofchecker_new->zo, &spoofchecker_orig->zo); - - if (spoofchecker_orig->uspoof != NULL) { - /* guaranteed to return NULL if it fails */ - UErrorCode error = U_ZERO_ERROR; - spoofchecker_new->uspoof = uspoof_clone(spoofchecker_orig->uspoof, &error); - if (U_FAILURE(error)) { - /* free new object */ - Spoofchecker_objects_free(&spoofchecker_new->zo); - zend_throw_error(NULL, "Failed to clone SpoofChecker"); - } - } else { - zend_throw_error(NULL, "Cannot clone uninitialized SpoofChecker"); - } - - return new_obj_val; -} -/* }}} */ - -/* {{{ spoofchecker_register_Spoofchecker_class - * Initialize 'Spoofchecker' class - */ -void spoofchecker_register_Spoofchecker_class(void) -{ - /* Create and register 'Spoofchecker' class. */ - Spoofchecker_ce_ptr = register_class_Spoofchecker(); - Spoofchecker_ce_ptr->create_object = Spoofchecker_object_create; - Spoofchecker_ce_ptr->default_object_handlers = &Spoofchecker_handlers; - - memcpy(&Spoofchecker_handlers, &std_object_handlers, - sizeof Spoofchecker_handlers); - Spoofchecker_handlers.offset = XtOffsetOf(Spoofchecker_object, zo); - Spoofchecker_handlers.clone_obj = spoofchecker_clone_obj; - Spoofchecker_handlers.free_obj = Spoofchecker_objects_free; -} -/* }}} */ - -/* {{{ void spoofchecker_object_init( Spoofchecker_object* co ) - * Initialize internals of Spoofchecker_object. - * Must be called before any other call to 'spoofchecker_object_...' functions. - */ -void spoofchecker_object_init(Spoofchecker_object* co) -{ - if (!co) { - return; - } - - intl_error_init(SPOOFCHECKER_ERROR_P(co)); -} -/* }}} */ - -/* {{{ void spoofchecker_object_destroy( Spoofchecker_object* co ) - * Clean up mem allocted by internals of Spoofchecker_object - */ -void spoofchecker_object_destroy(Spoofchecker_object* co) -{ - if (!co) { - return; - } - - if (co->uspoof) { - uspoof_close(co->uspoof); - co->uspoof = NULL; - } - -#if U_ICU_VERSION_MAJOR_NUM >= 58 - if (co->uspoofres) { - uspoof_closeCheckResult(co->uspoofres); - co->uspoofres = NULL; - } -#endif - - intl_error_reset(SPOOFCHECKER_ERROR_P(co)); -} -/* }}} */ diff --git a/ext/intl/spoofchecker/spoofchecker_class.cpp b/ext/intl/spoofchecker/spoofchecker_class.cpp new file mode 100644 index 0000000000000..ba4c64321f14e --- /dev/null +++ b/ext/intl/spoofchecker/spoofchecker_class.cpp @@ -0,0 +1,144 @@ +/* + +----------------------------------------------------------------------+ + | 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: Scott MacVicar | + +----------------------------------------------------------------------+ + */ + +#include "spoofchecker_class.h" +extern "C" { +#include "spoofchecker_arginfo.h" +#include "php_intl.h" +#include "intl_error.h" +} + +#include + +zend_class_entry *Spoofchecker_ce_ptr = NULL; +static zend_object_handlers Spoofchecker_handlers; + +/* + * Auxiliary functions needed by objects of 'Spoofchecker' class + */ + +/* {{{ Spoofchecker_objects_free */ +U_CFUNC void Spoofchecker_objects_free(zend_object *object) +{ + Spoofchecker_object* co = php_intl_spoofchecker_fetch_object(object); + + zend_object_std_dtor(&co->zo); + + spoofchecker_object_destroy(co); +} +/* }}} */ + +/* {{{ Spoofchecker_object_create */ +U_CFUNC zend_object *Spoofchecker_object_create(zend_class_entry *ce) +{ + Spoofchecker_object* intern; + + intern = reinterpret_cast(zend_object_alloc(sizeof(Spoofchecker_object), ce)); + intl_error_init(SPOOFCHECKER_ERROR_P(intern)); + zend_object_std_init(&intern->zo, ce); + object_properties_init(&intern->zo, ce); + + return &intern->zo; +} +/* }}} */ + +/* + * 'Spoofchecker' class registration structures & functions + */ + +/* {{{ Spoofchecker_class_functions + * Every 'Spoofchecker' class method has an entry in this table + */ + +static zend_object *spoofchecker_clone_obj(zend_object *object) /* {{{ */ +{ + Spoofchecker_object *spoofchecker_orig = php_intl_spoofchecker_fetch_object(object); + zend_object *new_obj_val = Spoofchecker_ce_ptr->create_object(object->ce); + Spoofchecker_object *spoofchecker_new = php_intl_spoofchecker_fetch_object(new_obj_val); + + zend_objects_clone_members(&spoofchecker_new->zo, &spoofchecker_orig->zo); + + if (spoofchecker_orig->uspoof != NULL) { + /* guaranteed to return NULL if it fails */ + UErrorCode error = U_ZERO_ERROR; + spoofchecker_new->uspoof = uspoof_clone(spoofchecker_orig->uspoof, &error); + if (U_FAILURE(error)) { + /* free new object */ + Spoofchecker_objects_free(&spoofchecker_new->zo); + zend_throw_error(NULL, "Failed to clone SpoofChecker"); + } + } else { + zend_throw_error(NULL, "Cannot clone uninitialized SpoofChecker"); + } + + return new_obj_val; +} +/* }}} */ + +/* {{{ spoofchecker_register_Spoofchecker_class + * Initialize 'Spoofchecker' class + */ +U_CFUNC void spoofchecker_register_Spoofchecker_class(void) +{ + /* Create and register 'Spoofchecker' class. */ + Spoofchecker_ce_ptr = register_class_Spoofchecker(); + Spoofchecker_ce_ptr->create_object = Spoofchecker_object_create; + Spoofchecker_ce_ptr->default_object_handlers = &Spoofchecker_handlers; + + memcpy(&Spoofchecker_handlers, &std_object_handlers, + sizeof Spoofchecker_handlers); + Spoofchecker_handlers.offset = XtOffsetOf(Spoofchecker_object, zo); + Spoofchecker_handlers.clone_obj = spoofchecker_clone_obj; + Spoofchecker_handlers.free_obj = Spoofchecker_objects_free; +} +/* }}} */ + +/* {{{ void spoofchecker_object_init( Spoofchecker_object* co ) + * Initialize internals of Spoofchecker_object. + * Must be called before any other call to 'spoofchecker_object_...' functions. + */ +U_CFUNC void spoofchecker_object_init(Spoofchecker_object* co) +{ + if (!co) { + return; + } + + intl_error_init(SPOOFCHECKER_ERROR_P(co)); +} +/* }}} */ + +/* {{{ void spoofchecker_object_destroy( Spoofchecker_object* co ) + * Clean up mem allocted by internals of Spoofchecker_object + */ +U_CFUNC void spoofchecker_object_destroy(Spoofchecker_object* co) +{ + if (!co) { + return; + } + + if (co->uspoof) { + uspoof_close(co->uspoof); + co->uspoof = NULL; + } + +#if U_ICU_VERSION_MAJOR_NUM >= 58 + if (co->uspoofres) { + uspoof_closeCheckResult(co->uspoofres); + co->uspoofres = NULL; + } +#endif + + intl_error_reset(SPOOFCHECKER_ERROR_P(co)); +} +/* }}} */ diff --git a/ext/intl/spoofchecker/spoofchecker_class.h b/ext/intl/spoofchecker/spoofchecker_class.h index 480eeeb476ffb..06701eb60e36e 100644 --- a/ext/intl/spoofchecker/spoofchecker_class.h +++ b/ext/intl/spoofchecker/spoofchecker_class.h @@ -17,9 +17,15 @@ #include +#ifdef __cplusplus +extern "C" { +#endif #include "intl_common.h" #include "intl_error.h" #include "intl_data.h" +#ifdef __cplusplus +} +#endif #include @@ -47,10 +53,16 @@ static inline Spoofchecker_object *php_intl_spoofchecker_fetch_object(zend_objec #define SPOOFCHECKER_ERROR_CODE(co) INTL_ERROR_CODE(SPOOFCHECKER_ERROR(co)) #define SPOOFCHECKER_ERROR_CODE_P(co) &(INTL_ERROR_CODE(SPOOFCHECKER_ERROR(co))) +#ifdef __cplusplus +extern "C" { +#endif void spoofchecker_register_Spoofchecker_class(void); void spoofchecker_object_init(Spoofchecker_object* co); void spoofchecker_object_destroy(Spoofchecker_object* co); +#ifdef __cplusplus +} +#endif extern zend_class_entry *Spoofchecker_ce_ptr; @@ -73,7 +85,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 deleted file mode 100644 index c1cecac8412a0..0000000000000 --- a/ext/intl/spoofchecker/spoofchecker_create.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Scott MacVicar | - +----------------------------------------------------------------------+ - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "php_intl.h" -#include "spoofchecker_class.h" -#include "intl_data.h" - -/* {{{ Spoofchecker object constructor. */ -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_ICU_VERSION_MAJOR_NUM >= 58 - /* TODO save it into the object for further suspiction check comparison. */ - /* ICU 58 removes WSC and MSC handling. However there are restriction - levels as defined in - http://www.unicode.org/reports/tr39/tr39-15.html#Restriction_Level_Detection - and the default is high restrictive. In further, we might want to utilize - uspoof_check2 APIs when it became stable, to use extended check result APIs. - Subsequent changes in the unicode security algos are to be watched.*/ - uspoof_setRestrictionLevel(co->uspoof, SPOOFCHECKER_DEFAULT_RESTRICTION_LEVEL); - co->uspoofres = uspoof_openCheckResult(SPOOFCHECKER_ERROR_CODE_P(co)); -#else - /* Single-script enforcement is on by default. This fails for languages - like Japanese that legally use multiple scripts within a single word, - so we turn it off. - */ - 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/spoofchecker/spoofchecker_create.cpp b/ext/intl/spoofchecker/spoofchecker_create.cpp new file mode 100644 index 0000000000000..1ed4055cccd10 --- /dev/null +++ b/ext/intl/spoofchecker/spoofchecker_create.cpp @@ -0,0 +1,67 @@ +/* + +----------------------------------------------------------------------+ + | 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: Scott MacVicar | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if __cplusplus >= 201703L +#include +#include +#endif + +extern "C" { +#include "php_intl.h" +#include "intl_data.h" +} +#include "spoofchecker_class.h" + +/* {{{ Spoofchecker object constructor. */ +U_CFUNC PHP_METHOD(Spoofchecker, __construct) +{ +#if U_ICU_VERSION_MAJOR_NUM < 58 + int checks; +#endif + SPOOFCHECKER_METHOD_INIT_VARS; + + ZEND_PARSE_PARAMETERS_NONE(); + + SPOOFCHECKER_METHOD_FETCH_OBJECT_NO_CHECK; + + co->uspoof = uspoof_open(SPOOFCHECKER_ERROR_CODE_P(co)); + 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. */ + /* ICU 58 removes WSC and MSC handling. However there are restriction + levels as defined in + http://www.unicode.org/reports/tr39/tr39-15.html#Restriction_Level_Detection + and the default is high restrictive. In further, we might want to utilize + uspoof_check2 APIs when it became stable, to use extended check result APIs. + Subsequent changes in the unicode security algos are to be watched.*/ + uspoof_setRestrictionLevel(co->uspoof, SPOOFCHECKER_DEFAULT_RESTRICTION_LEVEL); + co->uspoofres = uspoof_openCheckResult(SPOOFCHECKER_ERROR_CODE_P(co)); +#else + /* Single-script enforcement is on by default. This fails for languages + like Japanese that legally use multiple scripts within a single word, + so we turn it off. + */ + checks = uspoof_getChecks(co->uspoof, SPOOFCHECKER_ERROR_CODE_P(co)); + uspoof_setChecks(co->uspoof, checks & ~USPOOF_SINGLE_SCRIPT, SPOOFCHECKER_ERROR_CODE_P(co)); +#endif +} +/* }}} */ diff --git a/ext/intl/spoofchecker/spoofchecker_main.c b/ext/intl/spoofchecker/spoofchecker_main.c deleted file mode 100644 index afea503bc0e4b..0000000000000 --- a/ext/intl/spoofchecker/spoofchecker_main.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Scott MacVicar | - +----------------------------------------------------------------------+ - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "php_intl.h" -#include "intl_convert.h" -#include "spoofchecker_class.h" - -/* {{{ Checks if a given text contains any suspicious characters */ -PHP_METHOD(Spoofchecker, isSuspicious) -{ - int32_t ret, errmask; - zend_string *text; - zval *error_code = NULL; - SPOOFCHECKER_METHOD_INIT_VARS; - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_STR(text) - Z_PARAM_OPTIONAL - Z_PARAM_ZVAL(error_code) - ZEND_PARSE_PARAMETERS_END(); - - SPOOFCHECKER_METHOD_FETCH_OBJECT; - -#if U_ICU_VERSION_MAJOR_NUM >= 58 - ret = uspoof_check2UTF8(co->uspoof, ZSTR_VAL(text), ZSTR_LEN(text), co->uspoofres, SPOOFCHECKER_ERROR_CODE_P(co)); -#else - ret = uspoof_checkUTF8(co->uspoof, ZSTR_VAL(text), ZSTR_LEN(text), NULL, SPOOFCHECKER_ERROR_CODE_P(co)); -#endif - - if (U_FAILURE(SPOOFCHECKER_ERROR_CODE(co))) { - php_error_docref(NULL, E_WARNING, "(%d) %s", SPOOFCHECKER_ERROR_CODE(co), u_errorName(SPOOFCHECKER_ERROR_CODE(co))); -#if U_ICU_VERSION_MAJOR_NUM >= 58 - errmask = uspoof_getCheckResultChecks(co->uspoofres, SPOOFCHECKER_ERROR_CODE_P(co)); - - if (errmask != ret) { - php_error_docref(NULL, E_WARNING, "unexpected error (%d), does not relate to the flags passed to setChecks (%d)", ret, errmask); - } -#endif - RETURN_TRUE; - } - - if (error_code) { - ZEND_TRY_ASSIGN_REF_LONG(error_code, ret); - } - RETVAL_BOOL(ret != 0); -} -/* }}} */ - -/* {{{ Checks if a given text contains any confusable characters */ -PHP_METHOD(Spoofchecker, areConfusable) -{ - int ret; - zend_string *s1, *s2; - zval *error_code = NULL; - SPOOFCHECKER_METHOD_INIT_VARS; - - ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_STR(s1) - Z_PARAM_STR(s2) - Z_PARAM_OPTIONAL - Z_PARAM_ZVAL(error_code) - ZEND_PARSE_PARAMETERS_END(); - - SPOOFCHECKER_METHOD_FETCH_OBJECT; - if(ZSTR_LEN(s1) > INT32_MAX || ZSTR_LEN(s2) > INT32_MAX) { - SPOOFCHECKER_ERROR_CODE(co) = U_BUFFER_OVERFLOW_ERROR; - } else { - ret = uspoof_areConfusableUTF8(co->uspoof, ZSTR_VAL(s1), (int32_t)ZSTR_LEN(s1), ZSTR_VAL(s2), (int32_t)ZSTR_LEN(s2), SPOOFCHECKER_ERROR_CODE_P(co)); - } - if (U_FAILURE(SPOOFCHECKER_ERROR_CODE(co))) { - php_error_docref(NULL, E_WARNING, "(%d) %s", SPOOFCHECKER_ERROR_CODE(co), u_errorName(SPOOFCHECKER_ERROR_CODE(co))); - RETURN_TRUE; - } - - if (error_code) { - ZEND_TRY_ASSIGN_REF_LONG(error_code, ret); - } - RETVAL_BOOL(ret != 0); -} -/* }}} */ - -/* {{{ Locales to use when running checks */ -PHP_METHOD(Spoofchecker, setAllowedLocales) -{ - zend_string *locales; - SPOOFCHECKER_METHOD_INIT_VARS; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STR(locales) - ZEND_PARSE_PARAMETERS_END(); - - SPOOFCHECKER_METHOD_FETCH_OBJECT; - - uspoof_setAllowedLocales(co->uspoof, ZSTR_VAL(locales), SPOOFCHECKER_ERROR_CODE_P(co)); - - if (U_FAILURE(SPOOFCHECKER_ERROR_CODE(co))) { - php_error_docref(NULL, E_WARNING, "(%d) %s", SPOOFCHECKER_ERROR_CODE(co), u_errorName(SPOOFCHECKER_ERROR_CODE(co))); - return; - } -} -/* }}} */ - -/* {{{ Set the checks to run */ -PHP_METHOD(Spoofchecker, setChecks) -{ - zend_long checks; - SPOOFCHECKER_METHOD_INIT_VARS; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_LONG(checks) - ZEND_PARSE_PARAMETERS_END(); - - SPOOFCHECKER_METHOD_FETCH_OBJECT; - - uspoof_setChecks(co->uspoof, checks, SPOOFCHECKER_ERROR_CODE_P(co)); - - if (U_FAILURE(SPOOFCHECKER_ERROR_CODE(co))) { - php_error_docref(NULL, E_WARNING, "(%d) %s", SPOOFCHECKER_ERROR_CODE(co), u_errorName(SPOOFCHECKER_ERROR_CODE(co))); - } -} -/* }}} */ - -#if U_ICU_VERSION_MAJOR_NUM >= 58 -/* TODO Document this method on PHP.net */ -/* {{{ Set the loosest restriction level allowed for strings. */ -PHP_METHOD(Spoofchecker, setRestrictionLevel) -{ - zend_long level; - SPOOFCHECKER_METHOD_INIT_VARS; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_LONG(level) - ZEND_PARSE_PARAMETERS_END(); - - SPOOFCHECKER_METHOD_FETCH_OBJECT; - - if (USPOOF_ASCII != level && - USPOOF_SINGLE_SCRIPT_RESTRICTIVE != level && - USPOOF_HIGHLY_RESTRICTIVE != level && - USPOOF_MODERATELY_RESTRICTIVE != level && - USPOOF_MINIMALLY_RESTRICTIVE != level && - USPOOF_UNRESTRICTIVE != level) { - zend_argument_value_error(1, "must be one of Spoofchecker::ASCII, Spoofchecker::SINGLE_SCRIPT_RESTRICTIVE, " - "Spoofchecker::SINGLE_HIGHLY_RESTRICTIVE, Spoofchecker::SINGLE_MODERATELY_RESTRICTIVE, " - "Spoofchecker::SINGLE_MINIMALLY_RESTRICTIVE, or Spoofchecker::UNRESTRICTIVE"); - RETURN_THROWS(); - } - - uspoof_setRestrictionLevel(co->uspoof, (URestrictionLevel)level); -} -/* }}} */ -#endif - -PHP_METHOD(Spoofchecker, setAllowedChars) -{ - zend_string *pattern; - UChar *upattern = NULL; - int32_t upattern_len = 0; - zend_long pattern_option = 0; - SPOOFCHECKER_METHOD_INIT_VARS; - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_STR(pattern) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(pattern_option) - ZEND_PARSE_PARAMETERS_END(); - SPOOFCHECKER_METHOD_FETCH_OBJECT; - - if (ZSTR_LEN(pattern) > INT32_MAX) { - zend_argument_value_error(1, "must be less than or equal to " ZEND_LONG_FMT " bytes long", INT32_MAX); - RETURN_THROWS(); - } - - /* uset_applyPattern requires to start with a regex range char */ - if (ZSTR_VAL(pattern)[0] != '[' || ZSTR_VAL(pattern)[ZSTR_LEN(pattern) -1] != ']') { - zend_argument_value_error(1, "must be a valid regular expression character set pattern"); - RETURN_THROWS(); - } - - intl_convert_utf8_to_utf16(&upattern, &upattern_len, ZSTR_VAL(pattern), ZSTR_LEN(pattern), SPOOFCHECKER_ERROR_CODE_P(co)); - if (U_FAILURE(SPOOFCHECKER_ERROR_CODE(co))) { - zend_argument_value_error(1, "string conversion to unicode encoding failed (%d) %s", SPOOFCHECKER_ERROR_CODE(co), u_errorName(SPOOFCHECKER_ERROR_CODE(co))); - RETURN_THROWS(); - } - - USet *set = uset_openEmpty(); - - /* pattern is either USE_IGNORE_SPACE alone or in conjunction with the following flags (but mutually exclusive) */ - if (pattern_option && - pattern_option != USET_IGNORE_SPACE && -#if U_ICU_VERSION_MAJOR_NUM >= 73 - pattern_option != (USET_IGNORE_SPACE|USET_SIMPLE_CASE_INSENSITIVE) && -#endif - pattern_option != (USET_IGNORE_SPACE|USET_CASE_INSENSITIVE) && - pattern_option != (USET_IGNORE_SPACE|USET_ADD_CASE_MAPPINGS)) { - zend_argument_value_error(2, "must be a valid pattern option, 0 or (SpoofChecker::IGNORE_SPACE|( or SpoofChecker::USET_CASE_INSENSITIVE or SpoofChecker::USET_ADD_CASE_MAPPINGS" -#if U_ICU_VERSION_MAJOR_NUM >= 73 - " or SpoofChecker::USET_SIMPLE_CASE_INSENSITIVE" -#endif - "))" - ); - uset_close(set); - efree(upattern); - RETURN_THROWS(); - } - - uset_applyPattern(set, upattern, upattern_len, (uint32_t)pattern_option, SPOOFCHECKER_ERROR_CODE_P(co)); - if (U_FAILURE(SPOOFCHECKER_ERROR_CODE(co))) { - zend_argument_value_error(1, "must be a valid regular expression character set pattern (%d) %s", SPOOFCHECKER_ERROR_CODE(co), u_errorName(SPOOFCHECKER_ERROR_CODE(co))); - uset_close(set); - efree(upattern); - RETURN_THROWS(); - } - - uset_compact(set); - uspoof_setAllowedChars(co->uspoof, set, SPOOFCHECKER_ERROR_CODE_P(co)); - uset_close(set); - efree(upattern); - - if (U_FAILURE(SPOOFCHECKER_ERROR_CODE(co))) { - php_error_docref(NULL, E_WARNING, "(%d) %s", SPOOFCHECKER_ERROR_CODE(co), u_errorName(SPOOFCHECKER_ERROR_CODE(co))); - } -} diff --git a/ext/intl/spoofchecker/spoofchecker_main.cpp b/ext/intl/spoofchecker/spoofchecker_main.cpp new file mode 100644 index 0000000000000..e49ddec87a3cb --- /dev/null +++ b/ext/intl/spoofchecker/spoofchecker_main.cpp @@ -0,0 +1,244 @@ +/* + +----------------------------------------------------------------------+ + | 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: Scott MacVicar | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if __cplusplus >= 201703L +#include +#include +#endif + +extern "C" { +#include "php_intl.h" +#include "intl_convert.h" +} +#include "spoofchecker_class.h" + +/* {{{ Checks if a given text contains any suspicious characters */ +U_CFUNC PHP_METHOD(Spoofchecker, isSuspicious) +{ + int32_t ret, errmask; + zend_string *text; + zval *error_code = NULL; + SPOOFCHECKER_METHOD_INIT_VARS; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STR(text) + Z_PARAM_OPTIONAL + Z_PARAM_ZVAL(error_code) + ZEND_PARSE_PARAMETERS_END(); + + SPOOFCHECKER_METHOD_FETCH_OBJECT; + +#if U_ICU_VERSION_MAJOR_NUM >= 58 + ret = uspoof_check2UTF8(co->uspoof, ZSTR_VAL(text), ZSTR_LEN(text), co->uspoofres, SPOOFCHECKER_ERROR_CODE_P(co)); +#else + ret = uspoof_checkUTF8(co->uspoof, ZSTR_VAL(text), ZSTR_LEN(text), NULL, SPOOFCHECKER_ERROR_CODE_P(co)); +#endif + + if (U_FAILURE(SPOOFCHECKER_ERROR_CODE(co))) { + php_error_docref(NULL, E_WARNING, "(%d) %s", SPOOFCHECKER_ERROR_CODE(co), u_errorName(SPOOFCHECKER_ERROR_CODE(co))); +#if U_ICU_VERSION_MAJOR_NUM >= 58 + errmask = uspoof_getCheckResultChecks(co->uspoofres, SPOOFCHECKER_ERROR_CODE_P(co)); + + if (errmask != ret) { + php_error_docref(NULL, E_WARNING, "unexpected error (%d), does not relate to the flags passed to setChecks (%d)", ret, errmask); + } +#endif + RETURN_TRUE; + } + + if (error_code) { + ZEND_TRY_ASSIGN_REF_LONG(error_code, ret); + } + RETVAL_BOOL(ret != 0); +} +/* }}} */ + +/* {{{ Checks if a given text contains any confusable characters */ +U_CFUNC PHP_METHOD(Spoofchecker, areConfusable) +{ + int ret; + zend_string *s1, *s2; + zval *error_code = NULL; + SPOOFCHECKER_METHOD_INIT_VARS; + + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_STR(s1) + Z_PARAM_STR(s2) + Z_PARAM_OPTIONAL + Z_PARAM_ZVAL(error_code) + ZEND_PARSE_PARAMETERS_END(); + + SPOOFCHECKER_METHOD_FETCH_OBJECT; + if(ZSTR_LEN(s1) > INT32_MAX || ZSTR_LEN(s2) > INT32_MAX) { + SPOOFCHECKER_ERROR_CODE(co) = U_BUFFER_OVERFLOW_ERROR; + } else { + ret = uspoof_areConfusableUTF8(co->uspoof, ZSTR_VAL(s1), (int32_t)ZSTR_LEN(s1), ZSTR_VAL(s2), (int32_t)ZSTR_LEN(s2), SPOOFCHECKER_ERROR_CODE_P(co)); + } + if (U_FAILURE(SPOOFCHECKER_ERROR_CODE(co))) { + php_error_docref(NULL, E_WARNING, "(%d) %s", SPOOFCHECKER_ERROR_CODE(co), u_errorName(SPOOFCHECKER_ERROR_CODE(co))); + RETURN_TRUE; + } + + if (error_code) { + ZEND_TRY_ASSIGN_REF_LONG(error_code, ret); + } + RETVAL_BOOL(ret != 0); +} +/* }}} */ + +/* {{{ Locales to use when running checks */ +U_CFUNC PHP_METHOD(Spoofchecker, setAllowedLocales) +{ + zend_string *locales; + SPOOFCHECKER_METHOD_INIT_VARS; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STR(locales) + ZEND_PARSE_PARAMETERS_END(); + + SPOOFCHECKER_METHOD_FETCH_OBJECT; + + uspoof_setAllowedLocales(co->uspoof, ZSTR_VAL(locales), SPOOFCHECKER_ERROR_CODE_P(co)); + + if (U_FAILURE(SPOOFCHECKER_ERROR_CODE(co))) { + php_error_docref(NULL, E_WARNING, "(%d) %s", SPOOFCHECKER_ERROR_CODE(co), u_errorName(SPOOFCHECKER_ERROR_CODE(co))); + return; + } +} +/* }}} */ + +/* {{{ Set the checks to run */ +U_CFUNC PHP_METHOD(Spoofchecker, setChecks) +{ + zend_long checks; + SPOOFCHECKER_METHOD_INIT_VARS; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_LONG(checks) + ZEND_PARSE_PARAMETERS_END(); + + SPOOFCHECKER_METHOD_FETCH_OBJECT; + + uspoof_setChecks(co->uspoof, checks, SPOOFCHECKER_ERROR_CODE_P(co)); + + if (U_FAILURE(SPOOFCHECKER_ERROR_CODE(co))) { + php_error_docref(NULL, E_WARNING, "(%d) %s", SPOOFCHECKER_ERROR_CODE(co), u_errorName(SPOOFCHECKER_ERROR_CODE(co))); + } +} +/* }}} */ + +#if U_ICU_VERSION_MAJOR_NUM >= 58 +/* {{{ Set the loosest restriction level allowed for strings. */ +U_CFUNC PHP_METHOD(Spoofchecker, setRestrictionLevel) +{ + zend_long level; + SPOOFCHECKER_METHOD_INIT_VARS; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_LONG(level) + ZEND_PARSE_PARAMETERS_END(); + + SPOOFCHECKER_METHOD_FETCH_OBJECT; + + if (USPOOF_ASCII != level && + USPOOF_SINGLE_SCRIPT_RESTRICTIVE != level && + USPOOF_HIGHLY_RESTRICTIVE != level && + USPOOF_MODERATELY_RESTRICTIVE != level && + USPOOF_MINIMALLY_RESTRICTIVE != level && + USPOOF_UNRESTRICTIVE != level) { + zend_argument_value_error(1, "must be one of Spoofchecker::ASCII, Spoofchecker::SINGLE_SCRIPT_RESTRICTIVE, " + "Spoofchecker::HIGHLY_RESTRICTIVE, Spoofchecker::MODERATELY_RESTRICTIVE, " + "Spoofchecker::MINIMALLY_RESTRICTIVE, or Spoofchecker::UNRESTRICTIVE"); + RETURN_THROWS(); + } + + uspoof_setRestrictionLevel(co->uspoof, (URestrictionLevel)level); +} +/* }}} */ +#endif + +U_CFUNC PHP_METHOD(Spoofchecker, setAllowedChars) +{ + zend_string *pattern; + UChar *upattern = NULL; + int32_t upattern_len = 0; + zend_long pattern_option = 0; + SPOOFCHECKER_METHOD_INIT_VARS; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STR(pattern) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(pattern_option) + ZEND_PARSE_PARAMETERS_END(); + SPOOFCHECKER_METHOD_FETCH_OBJECT; + + if (ZSTR_LEN(pattern) > INT32_MAX) { + zend_argument_value_error(1, "must be less than or equal to " ZEND_LONG_FMT " bytes long", INT32_MAX); + RETURN_THROWS(); + } + + /* uset_applyPattern requires to start with a regex range char */ + if (ZSTR_VAL(pattern)[0] != '[' || ZSTR_VAL(pattern)[ZSTR_LEN(pattern) -1] != ']') { + zend_argument_value_error(1, "must be a valid regular expression character set pattern"); + RETURN_THROWS(); + } + + intl_convert_utf8_to_utf16(&upattern, &upattern_len, ZSTR_VAL(pattern), ZSTR_LEN(pattern), SPOOFCHECKER_ERROR_CODE_P(co)); + if (U_FAILURE(SPOOFCHECKER_ERROR_CODE(co))) { + zend_argument_value_error(1, "string conversion to unicode encoding failed (%d) %s", SPOOFCHECKER_ERROR_CODE(co), u_errorName(SPOOFCHECKER_ERROR_CODE(co))); + RETURN_THROWS(); + } + + USet *set = uset_openEmpty(); + + /* pattern is either USE_IGNORE_SPACE alone or in conjunction with the following flags (but mutually exclusive) */ + if (pattern_option && + pattern_option != USET_IGNORE_SPACE && +#if U_ICU_VERSION_MAJOR_NUM >= 73 + pattern_option != (USET_IGNORE_SPACE|USET_SIMPLE_CASE_INSENSITIVE) && +#endif + pattern_option != (USET_IGNORE_SPACE|USET_CASE_INSENSITIVE) && + pattern_option != (USET_IGNORE_SPACE|USET_ADD_CASE_MAPPINGS)) { + zend_argument_value_error(2, "must be a valid pattern option, 0 or (SpoofChecker::IGNORE_SPACE|( or SpoofChecker::USET_CASE_INSENSITIVE or SpoofChecker::USET_ADD_CASE_MAPPINGS" +#if U_ICU_VERSION_MAJOR_NUM >= 73 + " or SpoofChecker::USET_SIMPLE_CASE_INSENSITIVE" +#endif + "))" + ); + uset_close(set); + efree(upattern); + RETURN_THROWS(); + } + + uset_applyPattern(set, upattern, upattern_len, (uint32_t)pattern_option, SPOOFCHECKER_ERROR_CODE_P(co)); + if (U_FAILURE(SPOOFCHECKER_ERROR_CODE(co))) { + zend_argument_value_error(1, "must be a valid regular expression character set pattern (%d) %s", SPOOFCHECKER_ERROR_CODE(co), u_errorName(SPOOFCHECKER_ERROR_CODE(co))); + uset_close(set); + efree(upattern); + RETURN_THROWS(); + } + + uset_compact(set); + uspoof_setAllowedChars(co->uspoof, set, SPOOFCHECKER_ERROR_CODE_P(co)); + uset_close(set); + efree(upattern); + + if (U_FAILURE(SPOOFCHECKER_ERROR_CODE(co))) { + php_error_docref(NULL, E_WARNING, "(%d) %s", SPOOFCHECKER_ERROR_CODE(co), u_errorName(SPOOFCHECKER_ERROR_CODE(co))); + } +} 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/collation_customization.phpt b/ext/intl/tests/collation_customization.phpt deleted file mode 100644 index aeb14386fd217..0000000000000 --- a/ext/intl/tests/collation_customization.phpt +++ /dev/null @@ -1,70 +0,0 @@ ---TEST-- -Collation customization ---EXTENSIONS-- -intl ---FILE-- - 0 ? ">" : "=" ); - $res .= " $eq $i"; - } - - $prev = $i; - } - $res .= "\n"; - - return $res; -} - -function check_alternate_handling( &$coll ) -{ - $res = ''; - - ut_coll_set_strength( $coll, Collator::TERTIARY ); - ut_coll_set_attribute( $coll, Collator::ALTERNATE_HANDLING, Collator::NON_IGNORABLE ); - - $res .= cmp_array( $coll, array( 'di Silva', 'Di Silva', 'diSilva', 'U.S.A.', 'USA' ) ); - - ut_coll_set_attribute( $coll, Collator::ALTERNATE_HANDLING, Collator::SHIFTED ); - - $res .= cmp_array( $coll, array( 'di Silva', 'diSilva', 'Di Silva', 'U.S.A.', 'USA' ) ); - - ut_coll_set_strength( $coll, Collator::QUATERNARY ); - - $res .= cmp_array( $coll, array( 'di Silva', 'diSilva', 'Di Silva', 'U.S.A.', 'USA' ) ); - $res .= "\n"; - - return $res; -} - -function ut_main() -{ - $coll = ut_coll_create( 'en_US' ); - - return - check_alternate_handling( $coll ); -} - -include_once( 'ut_common.inc' ); -ut_run(); -?> ---EXPECT-- -di Silva < Di Silva < diSilva < U.S.A. < USA -di Silva = diSilva < Di Silva < U.S.A. = USA -di Silva < diSilva < Di Silva < U.S.A. < USA diff --git a/ext/intl/tests/collator_create.phpt b/ext/intl/tests/collator_create.phpt new file mode 100644 index 0000000000000..2554571ba355f --- /dev/null +++ b/ext/intl/tests/collator_create.phpt @@ -0,0 +1,74 @@ +--TEST-- +Collator creation tests +--EXTENSIONS-- +intl +--FILE-- + +--EXPECTF-- +Locale: 'EN-US-ODESSA' + ULOC_REQUESTED_LOCALE = 'EN-US-ODESSA' + ULOC_VALID_LOCALE = 'en_US' + ULOC_ACTUAL_LOCALE = 'root' +Locale: 'UK_UA_ODESSA' + ULOC_REQUESTED_LOCALE = 'UK_UA_ODESSA' + ULOC_VALID_LOCALE = 'uk' + ULOC_ACTUAL_LOCALE = 'uk' +Locale: '' + ULOC_REQUESTED_LOCALE = '' + ULOC_VALID_LOCALE = '%s' + ULOC_ACTUAL_LOCALE = '%s' +Locale: 'root' + ULOC_REQUESTED_LOCALE = 'root' + ULOC_VALID_LOCALE = 'root' + ULOC_ACTUAL_LOCALE = 'root' +Locale: 'uk@currency=EURO' + ULOC_REQUESTED_LOCALE = 'uk@currency=EURO' + ULOC_VALID_LOCALE = 'uk' + ULOC_ACTUAL_LOCALE = 'uk' diff --git a/ext/intl/tests/collator_create4.phpt b/ext/intl/tests/collator_create4.phpt deleted file mode 100644 index 5747d366dcfa4..0000000000000 --- a/ext/intl/tests/collator_create4.phpt +++ /dev/null @@ -1,78 +0,0 @@ ---TEST-- -create() icu >= 53.1 ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Locale: 'EN-US-ODESSA' - ULOC_REQUESTED_LOCALE = 'EN-US-ODESSA' - ULOC_VALID_LOCALE = 'en_US' - ULOC_ACTUAL_LOCALE = 'root' -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' - ULOC_ACTUAL_LOCALE = '%s' -Locale: 'root' - ULOC_REQUESTED_LOCALE = 'root' - ULOC_VALID_LOCALE = 'root' - ULOC_ACTUAL_LOCALE = 'root' -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/collator_customization.phpt b/ext/intl/tests/collator_customization.phpt new file mode 100644 index 0000000000000..befb2c129e2c2 --- /dev/null +++ b/ext/intl/tests/collator_customization.phpt @@ -0,0 +1,69 @@ +--TEST-- +Collation customization +--EXTENSIONS-- +intl +--FILE-- + 0 ? ">" : "=" ); + $res .= " $eq $i"; + } + + $prev = $i; + } + $res .= "\n"; + + return $res; +} + +function check_alternate_handling(Collator $coll) +{ + $res = ''; + + ut_coll_set_strength( $coll, Collator::TERTIARY ); + ut_coll_set_attribute( $coll, Collator::ALTERNATE_HANDLING, Collator::NON_IGNORABLE ); + + $res .= cmp_array( $coll, array( 'di Silva', 'Di Silva', 'diSilva', 'U.S.A.', 'USA' ) ); + + ut_coll_set_attribute( $coll, Collator::ALTERNATE_HANDLING, Collator::SHIFTED ); + + $res .= cmp_array( $coll, array( 'di Silva', 'diSilva', 'Di Silva', 'U.S.A.', 'USA' ) ); + + ut_coll_set_strength( $coll, Collator::QUATERNARY ); + + $res .= cmp_array( $coll, array( 'di Silva', 'diSilva', 'Di Silva', 'U.S.A.', 'USA' ) ); + $res .= "\n"; + + return $res; +} + +function ut_main() +{ + $coll = ut_coll_create( 'en_US' ); + + return + check_alternate_handling( $coll ); +} + +include_once( 'ut_common.inc' ); +ut_run(); +?> +--EXPECT-- +di Silva < Di Silva < diSilva < U.S.A. < USA +di Silva = diSilva < Di Silva < U.S.A. = USA +di Silva < diSilva < Di Silva < U.S.A. < USA diff --git a/ext/intl/tests/collator_get_error_message.phpt b/ext/intl/tests/collator_get_error_message.phpt deleted file mode 100644 index ad67bc89c5a20..0000000000000 --- a/ext/intl/tests/collator_get_error_message.phpt +++ /dev/null @@ -1,36 +0,0 @@ ---TEST-- -get_error_message() ---EXTENSIONS-- -intl ---FILE-- - ---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_variant.phpt b/ext/intl/tests/dateformat_calendars_variant.phpt new file mode 100644 index 0000000000000..48c44c58834a4 --- /dev/null +++ b/ext/intl/tests/dateformat_calendars_variant.phpt @@ -0,0 +1,35 @@ +--TEST-- +IntlDateFormatter, calendars and time zone +--INI-- +date.timezone=Atlantic/Azores +--EXTENSIONS-- +intl +--SKIPIF-- += 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'))); + +?> +--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" diff --git a/ext/intl/tests/dateformat_calendars_variant3.phpt b/ext/intl/tests/dateformat_calendars_variant3.phpt deleted file mode 100644 index 037d8066a0815..0000000000000 --- a/ext/intl/tests/dateformat_calendars_variant3.phpt +++ /dev/null @@ -1,48 +0,0 @@ ---TEST-- -IntlDateFormatter, calendars and time zone ---INI-- -date.timezone=Atlantic/Azores ---EXTENSIONS-- -intl ---SKIPIF-- -= 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-- -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/currencies.phpt b/ext/intl/tests/formatter/currencies.phpt index 01c64a0480d37..1293283e7fc2b 100644 --- a/ext/intl/tests/formatter/currencies.phpt +++ b/ext/intl/tests/formatter/currencies.phpt @@ -1,6 +1,6 @@ --TEST-- NumberFormatter: currency formatting -----DESCRIPTION-- +--DESCRIPTION-- Tests NumberFormatter with various currenct-related formatters. --EXTENSIONS-- intl 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/gh13766.phpt b/ext/intl/tests/gh13766.phpt index 70567fa860537..9ed8d985de470 100644 --- a/ext/intl/tests/gh13766.phpt +++ b/ext/intl/tests/gh13766.phpt @@ -32,4 +32,4 @@ int(%d) string(19) "America/Los_Angeles" IntlDateFormatter::parseToCalendar(): Argument #2 ($offset) must be of type int, string given -Deprecated: Implicit conversion from float %r(1\.4757395258967641E\+20|34359738352)%r to int loses precision in %s on line %d +Warning: The float %r(1\.4757395258967641E\+20|34359738352)%r is not representable as an int, cast occurred in %s on line %d 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..78dc27b4092e4 100644 --- a/ext/intl/tests/msgfmt_format_error4.phpt +++ b/ext/intl/tests/msgfmt_format_error4.phpt @@ -2,22 +2,45 @@ 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"))); -?> ---EXPECTF-- -Warning: MessageFormatter::format(): Invalid UTF-8 data in argument key: '�' in %s on line %d -bool(false) +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()); +} -Warning: MessageFormatter::format(): Invalid UTF-8 data in string argument: '�' in %s on line %d -bool(false) +try { + var_dump($mf->format(array("foo" => new class { + function __toString(): string { + return str_repeat("\x80", random_int(1, 1)); + } + }))); +} catch (Throwable $e) { + var_dump($e::class === 'IntlException'); + var_dump("MessageFormatter::format(): Invalid UTF-8 data in string argument: '\x80'" === $e->getMessage()); +} +?> +--EXPECT-- +bool(true) +bool(true) +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..9436a9e954386 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-- format(array($time, 'date')), " ", ?> --EXPECTF-- Deprecated: Calling IntlGregorianCalendar::__construct() with more than 2 arguments is deprecated, use either IntlGregorianCalendar::createFromDate() or IntlGregorianCalendar::createFromDateTime() instead in %s on line %d -quinta-feira, 17 de maio de 2012 5:35:36 da tarde ptlis +quinta-feira, 17 de maio de 2012 5:35:36 %r(da tarde|p.m.)%r ptlis diff --git a/ext/intl/tests/msgfmt_format_message_errors.phpt b/ext/intl/tests/msgfmt_format_message_errors.phpt new file mode 100644 index 0000000000000..8a5ee8ea2ea35 --- /dev/null +++ b/ext/intl/tests/msgfmt_format_message_errors.phpt @@ -0,0 +1,27 @@ +--TEST-- +MessageFormatter::parseMessage() with invalid locale +--EXTENSIONS-- +intl +--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/rangeformatter/basic.phpt b/ext/intl/tests/rangeformatter/basic.phpt new file mode 100644 index 0000000000000..0e76466bc09b7 --- /dev/null +++ b/ext/intl/tests/rangeformatter/basic.phpt @@ -0,0 +1,484 @@ +--TEST-- +Basic test for IntlNumberRangeFormatter +--EXTENSIONS-- +intl +--SKIPIF-- + +--FILE-- + IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE, + 'IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE' => IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE, + 'IDENTITY_FALLBACK_APPROXIMATELY' => IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY, + 'IDENTITY_FALLBACK_RANGE' => IntlNumberRangeFormatter::IDENTITY_FALLBACK_RANGE +]; + +$collapses = [ + 'COLLAPSE_AUTO' => IntlNumberRangeFormatter::COLLAPSE_AUTO, + 'COLLAPSE_NONE' => IntlNumberRangeFormatter::COLLAPSE_NONE, + 'COLLAPSE_UNIT' => IntlNumberRangeFormatter::COLLAPSE_UNIT, + 'COLLAPSE_ALL' => IntlNumberRangeFormatter::COLLAPSE_ALL +]; + +foreach ($languages as $language) { + foreach ($identityFallbacks as $iName => $identityFallback) { + foreach ($collapses as $cName => $collapse) { + echo PHP_EOL . $language . ' - ' . $cName . ' - ' . $iName . PHP_EOL; + $nrf = IntlNumberRangeFormatter::createFromSkeleton( + 'measure-unit/length-meter', + $language, + $collapse, + $identityFallback + ); + + var_dump($nrf->format(1.1, 2.2)); + var_dump($nrf->format(100, 200)); + var_dump($nrf->format(-5, 5)); + var_dump($nrf->format(5, 5)); + var_dump($nrf->format(5.0001, 5.0001)); + var_dump($nrf->format(5, 5.1)); + var_dump($nrf->format(5.1, 6)); + } + } +} + +?> +--EXPECT-- +en_US - COLLAPSE_AUTO - IDENTITY_FALLBACK_SINGLE_VALUE +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(3) "5 m" +string(8) "5.0001 m" +string(9) "5–5.1 m" +string(9) "5.1–6 m" + +en_US - COLLAPSE_NONE - IDENTITY_FALLBACK_SINGLE_VALUE +string(15) "1.1 m – 2.2 m" +string(15) "100 m – 200 m" +string(12) "-5 m – 5 m" +string(3) "5 m" +string(8) "5.0001 m" +string(13) "5 m – 5.1 m" +string(13) "5.1 m – 6 m" + +en_US - COLLAPSE_UNIT - IDENTITY_FALLBACK_SINGLE_VALUE +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(3) "5 m" +string(8) "5.0001 m" +string(9) "5–5.1 m" +string(9) "5.1–6 m" + +en_US - COLLAPSE_ALL - IDENTITY_FALLBACK_SINGLE_VALUE +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(3) "5 m" +string(8) "5.0001 m" +string(9) "5–5.1 m" +string(9) "5.1–6 m" + +en_US - COLLAPSE_AUTO - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(3) "5 m" +string(8) "5.0001 m" +string(9) "5–5.1 m" +string(9) "5.1–6 m" + +en_US - COLLAPSE_NONE - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(15) "1.1 m – 2.2 m" +string(15) "100 m – 200 m" +string(12) "-5 m – 5 m" +string(3) "5 m" +string(8) "5.0001 m" +string(13) "5 m – 5.1 m" +string(13) "5.1 m – 6 m" + +en_US - COLLAPSE_UNIT - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(3) "5 m" +string(8) "5.0001 m" +string(9) "5–5.1 m" +string(9) "5.1–6 m" + +en_US - COLLAPSE_ALL - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(3) "5 m" +string(8) "5.0001 m" +string(9) "5–5.1 m" +string(9) "5.1–6 m" + +en_US - COLLAPSE_AUTO - IDENTITY_FALLBACK_APPROXIMATELY +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(4) "~5 m" +string(9) "~5.0001 m" +string(9) "5–5.1 m" +string(9) "5.1–6 m" + +en_US - COLLAPSE_NONE - IDENTITY_FALLBACK_APPROXIMATELY +string(15) "1.1 m – 2.2 m" +string(15) "100 m – 200 m" +string(12) "-5 m – 5 m" +string(4) "~5 m" +string(9) "~5.0001 m" +string(13) "5 m – 5.1 m" +string(13) "5.1 m – 6 m" + +en_US - COLLAPSE_UNIT - IDENTITY_FALLBACK_APPROXIMATELY +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(4) "~5 m" +string(9) "~5.0001 m" +string(9) "5–5.1 m" +string(9) "5.1–6 m" + +en_US - COLLAPSE_ALL - IDENTITY_FALLBACK_APPROXIMATELY +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(4) "~5 m" +string(9) "~5.0001 m" +string(9) "5–5.1 m" +string(9) "5.1–6 m" + +en_US - COLLAPSE_AUTO - IDENTITY_FALLBACK_RANGE +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(7) "5–5 m" +string(17) "5.0001–5.0001 m" +string(9) "5–5.1 m" +string(9) "5.1–6 m" + +en_US - COLLAPSE_NONE - IDENTITY_FALLBACK_RANGE +string(15) "1.1 m – 2.2 m" +string(15) "100 m – 200 m" +string(12) "-5 m – 5 m" +string(11) "5 m – 5 m" +string(21) "5.0001 m – 5.0001 m" +string(13) "5 m – 5.1 m" +string(13) "5.1 m – 6 m" + +en_US - COLLAPSE_UNIT - IDENTITY_FALLBACK_RANGE +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(7) "5–5 m" +string(17) "5.0001–5.0001 m" +string(9) "5–5.1 m" +string(9) "5.1–6 m" + +en_US - COLLAPSE_ALL - IDENTITY_FALLBACK_RANGE +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(7) "5–5 m" +string(17) "5.0001–5.0001 m" +string(9) "5–5.1 m" +string(9) "5.1–6 m" + +RO - COLLAPSE_AUTO - IDENTITY_FALLBACK_SINGLE_VALUE +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(3) "5 m" +string(8) "5,0001 m" +string(9) "5 - 5,1 m" +string(9) "5,1 - 6 m" + +RO - COLLAPSE_NONE - IDENTITY_FALLBACK_SINGLE_VALUE +string(13) "1,1 m - 2,2 m" +string(13) "100 m - 200 m" +string(10) "-5 m - 5 m" +string(3) "5 m" +string(8) "5,0001 m" +string(11) "5 m - 5,1 m" +string(11) "5,1 m - 6 m" + +RO - COLLAPSE_UNIT - IDENTITY_FALLBACK_SINGLE_VALUE +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(3) "5 m" +string(8) "5,0001 m" +string(9) "5 - 5,1 m" +string(9) "5,1 - 6 m" + +RO - COLLAPSE_ALL - IDENTITY_FALLBACK_SINGLE_VALUE +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(3) "5 m" +string(8) "5,0001 m" +string(9) "5 - 5,1 m" +string(9) "5,1 - 6 m" + +RO - COLLAPSE_AUTO - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(3) "5 m" +string(8) "5,0001 m" +string(9) "5 - 5,1 m" +string(9) "5,1 - 6 m" + +RO - COLLAPSE_NONE - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(13) "1,1 m - 2,2 m" +string(13) "100 m - 200 m" +string(10) "-5 m - 5 m" +string(3) "5 m" +string(8) "5,0001 m" +string(11) "5 m - 5,1 m" +string(11) "5,1 m - 6 m" + +RO - COLLAPSE_UNIT - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(3) "5 m" +string(8) "5,0001 m" +string(9) "5 - 5,1 m" +string(9) "5,1 - 6 m" + +RO - COLLAPSE_ALL - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(3) "5 m" +string(8) "5,0001 m" +string(9) "5 - 5,1 m" +string(9) "5,1 - 6 m" + +RO - COLLAPSE_AUTO - IDENTITY_FALLBACK_APPROXIMATELY +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(4) "~5 m" +string(9) "~5,0001 m" +string(9) "5 - 5,1 m" +string(9) "5,1 - 6 m" + +RO - COLLAPSE_NONE - IDENTITY_FALLBACK_APPROXIMATELY +string(13) "1,1 m - 2,2 m" +string(13) "100 m - 200 m" +string(10) "-5 m - 5 m" +string(4) "~5 m" +string(9) "~5,0001 m" +string(11) "5 m - 5,1 m" +string(11) "5,1 m - 6 m" + +RO - COLLAPSE_UNIT - IDENTITY_FALLBACK_APPROXIMATELY +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(4) "~5 m" +string(9) "~5,0001 m" +string(9) "5 - 5,1 m" +string(9) "5,1 - 6 m" + +RO - COLLAPSE_ALL - IDENTITY_FALLBACK_APPROXIMATELY +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(4) "~5 m" +string(9) "~5,0001 m" +string(9) "5 - 5,1 m" +string(9) "5,1 - 6 m" + +RO - COLLAPSE_AUTO - IDENTITY_FALLBACK_RANGE +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(7) "5 - 5 m" +string(17) "5,0001 - 5,0001 m" +string(9) "5 - 5,1 m" +string(9) "5,1 - 6 m" + +RO - COLLAPSE_NONE - IDENTITY_FALLBACK_RANGE +string(13) "1,1 m - 2,2 m" +string(13) "100 m - 200 m" +string(10) "-5 m - 5 m" +string(9) "5 m - 5 m" +string(19) "5,0001 m - 5,0001 m" +string(11) "5 m - 5,1 m" +string(11) "5,1 m - 6 m" + +RO - COLLAPSE_UNIT - IDENTITY_FALLBACK_RANGE +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(7) "5 - 5 m" +string(17) "5,0001 - 5,0001 m" +string(9) "5 - 5,1 m" +string(9) "5,1 - 6 m" + +RO - COLLAPSE_ALL - IDENTITY_FALLBACK_RANGE +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(7) "5 - 5 m" +string(17) "5,0001 - 5,0001 m" +string(9) "5 - 5,1 m" +string(9) "5,1 - 6 m" + +JA - COLLAPSE_AUTO - IDENTITY_FALLBACK_SINGLE_VALUE +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(3) "5 m" +string(8) "5.0001 m" +string(9) "5~5.1 m" +string(9) "5.1~6 m" + +JA - COLLAPSE_NONE - IDENTITY_FALLBACK_SINGLE_VALUE +string(15) "1.1 m ~ 2.2 m" +string(15) "100 m ~ 200 m" +string(12) "-5 m ~ 5 m" +string(3) "5 m" +string(8) "5.0001 m" +string(13) "5 m ~ 5.1 m" +string(13) "5.1 m ~ 6 m" + +JA - COLLAPSE_UNIT - IDENTITY_FALLBACK_SINGLE_VALUE +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(3) "5 m" +string(8) "5.0001 m" +string(9) "5~5.1 m" +string(9) "5.1~6 m" + +JA - COLLAPSE_ALL - IDENTITY_FALLBACK_SINGLE_VALUE +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(3) "5 m" +string(8) "5.0001 m" +string(9) "5~5.1 m" +string(9) "5.1~6 m" + +JA - COLLAPSE_AUTO - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(3) "5 m" +string(8) "5.0001 m" +string(9) "5~5.1 m" +string(9) "5.1~6 m" + +JA - COLLAPSE_NONE - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(15) "1.1 m ~ 2.2 m" +string(15) "100 m ~ 200 m" +string(12) "-5 m ~ 5 m" +string(3) "5 m" +string(8) "5.0001 m" +string(13) "5 m ~ 5.1 m" +string(13) "5.1 m ~ 6 m" + +JA - COLLAPSE_UNIT - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(3) "5 m" +string(8) "5.0001 m" +string(9) "5~5.1 m" +string(9) "5.1~6 m" + +JA - COLLAPSE_ALL - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(3) "5 m" +string(8) "5.0001 m" +string(9) "5~5.1 m" +string(9) "5.1~6 m" + +JA - COLLAPSE_AUTO - IDENTITY_FALLBACK_APPROXIMATELY +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(6) "約5 m" +string(11) "約5.0001 m" +string(9) "5~5.1 m" +string(9) "5.1~6 m" + +JA - COLLAPSE_NONE - IDENTITY_FALLBACK_APPROXIMATELY +string(15) "1.1 m ~ 2.2 m" +string(15) "100 m ~ 200 m" +string(12) "-5 m ~ 5 m" +string(6) "約5 m" +string(11) "約5.0001 m" +string(13) "5 m ~ 5.1 m" +string(13) "5.1 m ~ 6 m" + +JA - COLLAPSE_UNIT - IDENTITY_FALLBACK_APPROXIMATELY +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(6) "約5 m" +string(11) "約5.0001 m" +string(9) "5~5.1 m" +string(9) "5.1~6 m" + +JA - COLLAPSE_ALL - IDENTITY_FALLBACK_APPROXIMATELY +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(6) "約5 m" +string(11) "約5.0001 m" +string(9) "5~5.1 m" +string(9) "5.1~6 m" + +JA - COLLAPSE_AUTO - IDENTITY_FALLBACK_RANGE +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(7) "5~5 m" +string(17) "5.0001~5.0001 m" +string(9) "5~5.1 m" +string(9) "5.1~6 m" + +JA - COLLAPSE_NONE - IDENTITY_FALLBACK_RANGE +string(15) "1.1 m ~ 2.2 m" +string(15) "100 m ~ 200 m" +string(12) "-5 m ~ 5 m" +string(11) "5 m ~ 5 m" +string(21) "5.0001 m ~ 5.0001 m" +string(13) "5 m ~ 5.1 m" +string(13) "5.1 m ~ 6 m" + +JA - COLLAPSE_UNIT - IDENTITY_FALLBACK_RANGE +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(7) "5~5 m" +string(17) "5.0001~5.0001 m" +string(9) "5~5.1 m" +string(9) "5.1~6 m" + +JA - COLLAPSE_ALL - IDENTITY_FALLBACK_RANGE +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(7) "5~5 m" +string(17) "5.0001~5.0001 m" +string(9) "5~5.1 m" +string(9) "5.1~6 m" diff --git a/ext/intl/tests/rangeformatter/rangeformatter_clone.phpt b/ext/intl/tests/rangeformatter/rangeformatter_clone.phpt new file mode 100644 index 0000000000000..31674ba6eea25 --- /dev/null +++ b/ext/intl/tests/rangeformatter/rangeformatter_clone.phpt @@ -0,0 +1,28 @@ +--TEST-- +Test IntlNumberRangeFormatter cannot be cloned +--EXTENSIONS-- +intl +--SKIPIF-- + +--FILE-- +getMessage(); +} +?> +--EXPECT-- +Trying to clone an uncloneable object of class IntlNumberRangeFormatter diff --git a/ext/intl/tests/rangeformatter/rangeformatter_errors.phpt b/ext/intl/tests/rangeformatter/rangeformatter_errors.phpt new file mode 100644 index 0000000000000..83c993d7fc98b --- /dev/null +++ b/ext/intl/tests/rangeformatter/rangeformatter_errors.phpt @@ -0,0 +1,87 @@ +--TEST-- +errors for IntlNumberRangeFormatter +--EXTENSIONS-- +intl +--SKIPIF-- + +--FILE-- +getMessage() . PHP_EOL; +} + +echo intl_get_error_code() . PHP_EOL; +echo intl_get_error_message() . PHP_EOL; + +try { + new IntlNumberRangeFormatter(); +} catch(Error $error) { + echo $error->getMessage() . PHP_EOL; +} + +try { + $nrf = IntlNumberRangeFormatter::createFromSkeleton( + 'invalid skeleton here', + 'ro', + 34, + IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE + ); +} catch (ValueError $exception) { + echo $exception->getMessage() . PHP_EOL; +} + +try { + $nrf = IntlNumberRangeFormatter::createFromSkeleton( + 'invalid skeleton here', + 'ro', + IntlNumberRangeFormatter::COLLAPSE_AUTO, + 343 + ); +} catch (ValueError $exception) { + echo $exception->getMessage() . PHP_EOL; +} + +try { + $nrf = IntlNumberRangeFormatter::createFromSkeleton( + 'invalid skeleton here', + 'invalid-language', + IntlNumberRangeFormatter::COLLAPSE_AUTO, + IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE + ); +} catch (ValueError $exception) { + echo $exception->getMessage() . PHP_EOL; +} + +try { + $nrf = IntlNumberRangeFormatter::createFromSkeleton( + 'invalid skeleton here', + 'ro_thisiswaytooooooooooooooooooooooooooooooooooooooooooooolongtobevaliditneedstobeatleast157characterstofailthevalidationinthelistformattercodeimplementation', + IntlNumberRangeFormatter::COLLAPSE_AUTO, + IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE + ); +} catch (ValueError $exception) { + echo $exception->getMessage() . PHP_EOL; +} + +?> +--EXPECT-- +IntlNumberRangeFormatter::createFromSkeleton(): Failed to create the number skeleton +65811 +IntlNumberRangeFormatter::createFromSkeleton(): Failed to create the number skeleton: U_NUMBER_SKELETON_SYNTAX_ERROR +Call to private IntlNumberRangeFormatter::__construct() from global scope +IntlNumberRangeFormatter::createFromSkeleton(): Argument #3 ($collapse) must be one of IntlNumberRangeFormatter::COLLAPSE_AUTO, IntlNumberRangeFormatter::COLLAPSE_NONE, IntlNumberRangeFormatter::COLLAPSE_UNIT, or IntlNumberRangeFormatter::COLLAPSE_ALL +IntlNumberRangeFormatter::createFromSkeleton(): Argument #4 ($identityFallback) must be one of IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE, IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE, IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY, or IntlNumberRangeFormatter::IDENTITY_FALLBACK_RANGE +IntlNumberRangeFormatter::createFromSkeleton(): Argument #2 ($locale) "invalid-language" is invalid +IntlNumberRangeFormatter::createFromSkeleton(): Argument #2 ($locale) must be no longer than 156 characters diff --git a/ext/intl/tests/rangeformatter/rangeformatter_fraction_skeleton.phpt b/ext/intl/tests/rangeformatter/rangeformatter_fraction_skeleton.phpt new file mode 100644 index 0000000000000..f054aea94b5fa --- /dev/null +++ b/ext/intl/tests/rangeformatter/rangeformatter_fraction_skeleton.phpt @@ -0,0 +1,39 @@ +--TEST-- +Test precision skeleton with IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY +--EXTENSIONS-- +intl +--SKIPIF-- + +--FILE-- +format(5.1, 5.2)); + var_dump($nrf->format(5.01, 5.02)); + var_dump($nrf->format(5.001, 5.002)); +} + +?> +--EXPECT-- +Approximate with .## +string(9) "5.1–5.2" +string(11) "5.01–5.02" +string(2) "~5" +Approximate with .# +string(9) "5.1–5.2" +string(2) "~5" +string(2) "~5" diff --git a/ext/intl/tests/rangeformatter/rangeformatter_icu63_compatibility.phpt b/ext/intl/tests/rangeformatter/rangeformatter_icu63_compatibility.phpt new file mode 100644 index 0000000000000..9b3867161d60b --- /dev/null +++ b/ext/intl/tests/rangeformatter/rangeformatter_icu63_compatibility.phpt @@ -0,0 +1,26 @@ +--TEST-- +Test IntlNumberRangeFormatter::createFromSkeleton throws error for ICU < 63 +--EXTENSIONS-- +intl +--SKIPIF-- += 0) { + die('skip for ICU > 63.0'); +} +?> +--FILE-- +getMessage(); +} +?> +--EXPECT-- +Class "IntlNumberRangeFormatter" not found \ No newline at end of file diff --git a/ext/intl/tests/rangeformatter/rangeformatter_with_empty_skeleton.phpt b/ext/intl/tests/rangeformatter/rangeformatter_with_empty_skeleton.phpt new file mode 100644 index 0000000000000..43afc85f2b5fa --- /dev/null +++ b/ext/intl/tests/rangeformatter/rangeformatter_with_empty_skeleton.phpt @@ -0,0 +1,24 @@ +--TEST-- +Test an empty skeleton with IntlNumberRangeFormatter +--EXTENSIONS-- +intl +--SKIPIF-- + +--FILE-- +format(5.1, 5.2)); + +?> +--EXPECT-- +string(9) "5.1–5.2" 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/spoofchecker_unknown_restriction_level.phpt b/ext/intl/tests/spoofchecker_unknown_restriction_level.phpt index e8ed48d60a3eb..6b7e9474755de 100644 --- a/ext/intl/tests/spoofchecker_unknown_restriction_level.phpt +++ b/ext/intl/tests/spoofchecker_unknown_restriction_level.phpt @@ -20,4 +20,4 @@ try { ?> --EXPECT-- -Spoofchecker::setRestrictionLevel(): Argument #1 ($level) must be one of Spoofchecker::ASCII, Spoofchecker::SINGLE_SCRIPT_RESTRICTIVE, Spoofchecker::SINGLE_HIGHLY_RESTRICTIVE, Spoofchecker::SINGLE_MODERATELY_RESTRICTIVE, Spoofchecker::SINGLE_MINIMALLY_RESTRICTIVE, or Spoofchecker::UNRESTRICTIVE +Spoofchecker::setRestrictionLevel(): Argument #1 ($level) must be one of Spoofchecker::ASCII, Spoofchecker::SINGLE_SCRIPT_RESTRICTIVE, Spoofchecker::HIGHLY_RESTRICTIVE, Spoofchecker::MODERATELY_RESTRICTIVE, Spoofchecker::MINIMALLY_RESTRICTIVE, or Spoofchecker::UNRESTRICTIVE 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_basic2.phpt deleted file mode 100644 index 600e21fa70c80..0000000000000 --- a/ext/intl/tests/timezone_IDforWindowsID_basic2.phpt +++ /dev/null @@ -1,45 +0,0 @@ ---TEST-- -IntlTimeZone::getIDForWindowsID basic test ---EXTENSIONS-- -intl ---SKIPIF-- -= 58.1'); ?> -= 0) die('skip for ICU <= 76.1'); ?> ---FILE-- - 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'), -); - -foreach ($tzs as $tz => $regions) { - echo "** $tz\n"; - foreach ($regions as $region) { - var_dump(IntlTimeZone::getIDForWindowsID($tz, $region)); - if (intl_get_error_code() != U_ZERO_ERROR) { - echo "Error: ", intl_get_error_message(), "\n"; - } - } -} -?> ---EXPECTF-- -** Gnomeregan -bool(false) -Error: unknown windows timezone: U_ILLEGAL_ARGUMENT_ERROR -** India Standard Time -string(13) "Asia/Calcutta" -** Pacific Standard Time -string(19) "America/Los_Angeles" -string(17) "America/Vancouver" -string(19) "America/Los_Angeles" -string(19) "America/Los_Angeles" -string(%d) "%r(PST8PDT|America\/Los_Angeles)%r" -** Romance Standard Time -string(12) "Europe/Paris" -string(15) "Europe/Brussels" -string(17) "Europe/Copenhagen" -string(13) "Europe/Madrid" -string(12) "Europe/Paris" diff --git a/ext/intl/tests/timezone_IDforWindowsID_basic_icu58_1.phpt b/ext/intl/tests/timezone_IDforWindowsID_basic_icu58_1.phpt new file mode 100644 index 0000000000000..b92ebb89ec207 --- /dev/null +++ b/ext/intl/tests/timezone_IDforWindowsID_basic_icu58_1.phpt @@ -0,0 +1,41 @@ +--TEST-- +IntlTimeZone::getIDForWindowsID basic test +--EXTENSIONS-- +intl +--SKIPIF-- += 58.1'); ?> += 0) die('skip for ICU <= 76.1'); ?> +--FILE-- + array(NULL), + 'Pacific Standard Time' => array('001', 'CA', 'MX', 'US', 'ZZ'), + 'Romance Standard Time' => array('001', 'BE', 'DK', 'ES', 'FR'), +); + +foreach ($tzs as $tz => $regions) { + echo "** $tz\n"; + foreach ($regions as $region) { + var_dump(IntlTimeZone::getIDForWindowsID($tz, $region)); + if (intl_get_error_code() != U_ZERO_ERROR) { + echo "Error: ", intl_get_error_message(), "\n"; + } + } +} +?> +--EXPECTF-- +** India Standard Time +string(13) "Asia/Calcutta" +** Pacific Standard Time +string(19) "America/Los_Angeles" +string(17) "America/Vancouver" +string(19) "America/Los_Angeles" +string(19) "America/Los_Angeles" +string(%d) "%r(PST8PDT|America\/Los_Angeles)%r" +** Romance Standard Time +string(12) "Europe/Paris" +string(15) "Europe/Brussels" +string(17) "Europe/Copenhagen" +string(13) "Europe/Madrid" +string(12) "Europe/Paris" 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..ccde7f8e0ea79 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)); @@ -21,12 +19,12 @@ var_dump($lsb->getDisplayName(false, IntlTimeZone::DISPLAY_SHORT_COMMONLY_USED)) var_dump($lsb->getDisplayName(false, IntlTimeZone::DISPLAY_GENERIC_LOCATION)); ?> ---EXPECT-- -string(3) "GMT" +--EXPECTF-- +string(%d) "%r(GMT|GMT\+0)%r" string(30) "Western European Standard Time" string(13) "Portugal Time" string(21) "Western European Time" string(5) "+0000" -string(3) "GMT" -string(3) "GMT" +string(%d) "%r(GMT|GMT\+00:00)%r" +string(%d) "%r(GMT|GMT\+0)%r" string(13) "Portugal Time" 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..418d2901fe935 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) @@ -168,69 +168,69 @@ static zend_class_entry *register_class_IntlTimeZone(void) zval const_DISPLAY_SHORT_value; ZVAL_LONG(&const_DISPLAY_SHORT_value, TimeZone::SHORT); - zend_string *const_DISPLAY_SHORT_name = zend_string_init_interned("DISPLAY_SHORT", sizeof("DISPLAY_SHORT") - 1, 1); + zend_string *const_DISPLAY_SHORT_name = zend_string_init_interned("DISPLAY_SHORT", sizeof("DISPLAY_SHORT") - 1, true); zend_declare_typed_class_constant(class_entry, const_DISPLAY_SHORT_name, &const_DISPLAY_SHORT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DISPLAY_SHORT_name); + zend_string_release_ex(const_DISPLAY_SHORT_name, true); zval const_DISPLAY_LONG_value; ZVAL_LONG(&const_DISPLAY_LONG_value, TimeZone::LONG); - zend_string *const_DISPLAY_LONG_name = zend_string_init_interned("DISPLAY_LONG", sizeof("DISPLAY_LONG") - 1, 1); + zend_string *const_DISPLAY_LONG_name = zend_string_init_interned("DISPLAY_LONG", sizeof("DISPLAY_LONG") - 1, true); zend_declare_typed_class_constant(class_entry, const_DISPLAY_LONG_name, &const_DISPLAY_LONG_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DISPLAY_LONG_name); + zend_string_release_ex(const_DISPLAY_LONG_name, true); zval const_DISPLAY_SHORT_GENERIC_value; ZVAL_LONG(&const_DISPLAY_SHORT_GENERIC_value, TimeZone::SHORT_GENERIC); - zend_string *const_DISPLAY_SHORT_GENERIC_name = zend_string_init_interned("DISPLAY_SHORT_GENERIC", sizeof("DISPLAY_SHORT_GENERIC") - 1, 1); + zend_string *const_DISPLAY_SHORT_GENERIC_name = zend_string_init_interned("DISPLAY_SHORT_GENERIC", sizeof("DISPLAY_SHORT_GENERIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_DISPLAY_SHORT_GENERIC_name, &const_DISPLAY_SHORT_GENERIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DISPLAY_SHORT_GENERIC_name); + zend_string_release_ex(const_DISPLAY_SHORT_GENERIC_name, true); zval const_DISPLAY_LONG_GENERIC_value; ZVAL_LONG(&const_DISPLAY_LONG_GENERIC_value, TimeZone::LONG_GENERIC); - zend_string *const_DISPLAY_LONG_GENERIC_name = zend_string_init_interned("DISPLAY_LONG_GENERIC", sizeof("DISPLAY_LONG_GENERIC") - 1, 1); + zend_string *const_DISPLAY_LONG_GENERIC_name = zend_string_init_interned("DISPLAY_LONG_GENERIC", sizeof("DISPLAY_LONG_GENERIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_DISPLAY_LONG_GENERIC_name, &const_DISPLAY_LONG_GENERIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DISPLAY_LONG_GENERIC_name); + zend_string_release_ex(const_DISPLAY_LONG_GENERIC_name, true); zval const_DISPLAY_SHORT_GMT_value; ZVAL_LONG(&const_DISPLAY_SHORT_GMT_value, TimeZone::SHORT_GMT); - zend_string *const_DISPLAY_SHORT_GMT_name = zend_string_init_interned("DISPLAY_SHORT_GMT", sizeof("DISPLAY_SHORT_GMT") - 1, 1); + zend_string *const_DISPLAY_SHORT_GMT_name = zend_string_init_interned("DISPLAY_SHORT_GMT", sizeof("DISPLAY_SHORT_GMT") - 1, true); zend_declare_typed_class_constant(class_entry, const_DISPLAY_SHORT_GMT_name, &const_DISPLAY_SHORT_GMT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DISPLAY_SHORT_GMT_name); + zend_string_release_ex(const_DISPLAY_SHORT_GMT_name, true); zval const_DISPLAY_LONG_GMT_value; ZVAL_LONG(&const_DISPLAY_LONG_GMT_value, TimeZone::LONG_GMT); - zend_string *const_DISPLAY_LONG_GMT_name = zend_string_init_interned("DISPLAY_LONG_GMT", sizeof("DISPLAY_LONG_GMT") - 1, 1); + zend_string *const_DISPLAY_LONG_GMT_name = zend_string_init_interned("DISPLAY_LONG_GMT", sizeof("DISPLAY_LONG_GMT") - 1, true); zend_declare_typed_class_constant(class_entry, const_DISPLAY_LONG_GMT_name, &const_DISPLAY_LONG_GMT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DISPLAY_LONG_GMT_name); + zend_string_release_ex(const_DISPLAY_LONG_GMT_name, true); zval const_DISPLAY_SHORT_COMMONLY_USED_value; ZVAL_LONG(&const_DISPLAY_SHORT_COMMONLY_USED_value, TimeZone::SHORT_COMMONLY_USED); - zend_string *const_DISPLAY_SHORT_COMMONLY_USED_name = zend_string_init_interned("DISPLAY_SHORT_COMMONLY_USED", sizeof("DISPLAY_SHORT_COMMONLY_USED") - 1, 1); + zend_string *const_DISPLAY_SHORT_COMMONLY_USED_name = zend_string_init_interned("DISPLAY_SHORT_COMMONLY_USED", sizeof("DISPLAY_SHORT_COMMONLY_USED") - 1, true); zend_declare_typed_class_constant(class_entry, const_DISPLAY_SHORT_COMMONLY_USED_name, &const_DISPLAY_SHORT_COMMONLY_USED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DISPLAY_SHORT_COMMONLY_USED_name); + zend_string_release_ex(const_DISPLAY_SHORT_COMMONLY_USED_name, true); zval const_DISPLAY_GENERIC_LOCATION_value; ZVAL_LONG(&const_DISPLAY_GENERIC_LOCATION_value, TimeZone::GENERIC_LOCATION); - zend_string *const_DISPLAY_GENERIC_LOCATION_name = zend_string_init_interned("DISPLAY_GENERIC_LOCATION", sizeof("DISPLAY_GENERIC_LOCATION") - 1, 1); + zend_string *const_DISPLAY_GENERIC_LOCATION_name = zend_string_init_interned("DISPLAY_GENERIC_LOCATION", sizeof("DISPLAY_GENERIC_LOCATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_DISPLAY_GENERIC_LOCATION_name, &const_DISPLAY_GENERIC_LOCATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DISPLAY_GENERIC_LOCATION_name); + zend_string_release_ex(const_DISPLAY_GENERIC_LOCATION_name, true); zval const_TYPE_ANY_value; ZVAL_LONG(&const_TYPE_ANY_value, UCAL_ZONE_TYPE_ANY); - zend_string *const_TYPE_ANY_name = zend_string_init_interned("TYPE_ANY", sizeof("TYPE_ANY") - 1, 1); + zend_string *const_TYPE_ANY_name = zend_string_init_interned("TYPE_ANY", sizeof("TYPE_ANY") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_ANY_name, &const_TYPE_ANY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_ANY_name); + zend_string_release_ex(const_TYPE_ANY_name, true); zval const_TYPE_CANONICAL_value; ZVAL_LONG(&const_TYPE_CANONICAL_value, UCAL_ZONE_TYPE_CANONICAL); - zend_string *const_TYPE_CANONICAL_name = zend_string_init_interned("TYPE_CANONICAL", sizeof("TYPE_CANONICAL") - 1, 1); + zend_string *const_TYPE_CANONICAL_name = zend_string_init_interned("TYPE_CANONICAL", sizeof("TYPE_CANONICAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_CANONICAL_name, &const_TYPE_CANONICAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_CANONICAL_name); + zend_string_release_ex(const_TYPE_CANONICAL_name, true); zval const_TYPE_CANONICAL_LOCATION_value; ZVAL_LONG(&const_TYPE_CANONICAL_LOCATION_value, UCAL_ZONE_TYPE_CANONICAL_LOCATION); - zend_string *const_TYPE_CANONICAL_LOCATION_name = zend_string_init_interned("TYPE_CANONICAL_LOCATION", sizeof("TYPE_CANONICAL_LOCATION") - 1, 1); + zend_string *const_TYPE_CANONICAL_LOCATION_name = zend_string_init_interned("TYPE_CANONICAL_LOCATION", sizeof("TYPE_CANONICAL_LOCATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_TYPE_CANONICAL_LOCATION_name, &const_TYPE_CANONICAL_LOCATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TYPE_CANONICAL_LOCATION_name); + zend_string_release_ex(const_TYPE_CANONICAL_LOCATION_name, true); return class_entry; } 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_arginfo.h b/ext/intl/transliterator/transliterator_arginfo.h index 6f74b55521df3..c5a5bcc6090dd 100644 --- a/ext/intl/transliterator/transliterator_arginfo.h +++ b/ext/intl/transliterator/transliterator_arginfo.h @@ -62,21 +62,21 @@ static zend_class_entry *register_class_Transliterator(void) zval const_FORWARD_value; ZVAL_LONG(&const_FORWARD_value, TRANSLITERATOR_FORWARD); - zend_string *const_FORWARD_name = zend_string_init_interned("FORWARD", sizeof("FORWARD") - 1, 1); + zend_string *const_FORWARD_name = zend_string_init_interned("FORWARD", sizeof("FORWARD") - 1, true); zend_declare_typed_class_constant(class_entry, const_FORWARD_name, &const_FORWARD_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FORWARD_name); + zend_string_release_ex(const_FORWARD_name, true); zval const_REVERSE_value; ZVAL_LONG(&const_REVERSE_value, TRANSLITERATOR_REVERSE); - zend_string *const_REVERSE_name = zend_string_init_interned("REVERSE", sizeof("REVERSE") - 1, 1); + zend_string *const_REVERSE_name = zend_string_init_interned("REVERSE", sizeof("REVERSE") - 1, true); zend_declare_typed_class_constant(class_entry, const_REVERSE_name, &const_REVERSE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_REVERSE_name); + zend_string_release_ex(const_REVERSE_name, true); 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_string *property_id_name = zend_string_init("id", sizeof("id") - 1, true); zend_declare_typed_property(class_entry, property_id_name, &property_id_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_id_name); + zend_string_release_ex(property_id_name, true); return class_entry; } diff --git a/ext/intl/transliterator/transliterator_class.c b/ext/intl/transliterator/transliterator_class.c deleted file mode 100644 index 438b71c2c417a..0000000000000 --- a/ext/intl/transliterator/transliterator_class.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Gustavo Lopes | - +----------------------------------------------------------------------+ - */ - -#include "transliterator_class.h" -#include "php_intl.h" -#include "transliterator_arginfo.h" -#include "intl_error.h" -#include "intl_convert.h" -#include "intl_data.h" - -#include - -zend_class_entry *Transliterator_ce_ptr = NULL; - -zend_object_handlers Transliterator_handlers; - -/* {{{ int transliterator_object_construct( zval *object, UTransliterator *utrans, UErrorCode *status ) - * Initialize internals of Transliterator_object. - */ -int transliterator_object_construct( zval *object, - UTransliterator *utrans, - UErrorCode *status ) -{ - const UChar *ustr_id; - int32_t ustr_id_len; - zend_string *u8str; - zval tmp; - Transliterator_object *to; - - TRANSLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK; - - assert( to->utrans == NULL ); - /* this assignment must happen before any return with failure because the - * caller relies on it always being made (so it can just destroy the object - * to close the transliterator) */ - to->utrans = utrans; - - ustr_id = utrans_getUnicodeID( utrans, &ustr_id_len ); - u8str = intl_convert_utf16_to_utf8(ustr_id, (int ) ustr_id_len, status ); - if( !u8str ) - { - return FAILURE; - } - - ZVAL_NEW_STR(&tmp, u8str); - zend_update_property(Transliterator_ce_ptr, Z_OBJ_P(object), - "id", sizeof( "id" ) - 1, &tmp ); - GC_DELREF(u8str); - return SUCCESS; -} -/* }}} */ - -/* - * Auxiliary functions needed by objects of 'Transliterator' class - */ - -/* {{{ void transliterator_object_init( Transliterator_object* to ) - * Initialize internals of Transliterator_object. - */ -static void transliterator_object_init( Transliterator_object* to ) -{ - if( !to ) - return; - - intl_error_init( TRANSLITERATOR_ERROR_P( to ) ); -} -/* }}} */ - -/* {{{ void transliterator_object_destroy( Transliterator_object* to ) - * Clean up mem allocted by internals of Transliterator_object - */ -static void transliterator_object_destroy( Transliterator_object* to ) -{ - if( !to ) - return; - - if( to->utrans ) - { - utrans_close( to->utrans ); - to->utrans = NULL; - } - - intl_error_reset( TRANSLITERATOR_ERROR_P( to ) ); -} -/* }}} */ - -/* {{{ Transliterator_objects_free */ -static void Transliterator_objects_free( zend_object *object ) -{ - Transliterator_object* to = php_intl_transliterator_fetch_object(object); - - zend_object_std_dtor( &to->zo ); - - transliterator_object_destroy( to ); -} -/* }}} */ - -/* {{{ Transliterator_object_create */ -static zend_object *Transliterator_object_create( zend_class_entry *ce ) -{ - Transliterator_object* intern; - - intern = zend_object_alloc(sizeof(Transliterator_object), ce); - - zend_object_std_init( &intern->zo, ce ); - object_properties_init( &intern->zo, ce ); - transliterator_object_init( intern ); - - return &intern->zo; -} -/* }}} */ - -/* - * Object handlers for Transliterator class (and subclasses) - */ - -/* {{{ clone handler for Transliterator */ -static zend_object *Transliterator_clone_obj( zend_object *object ) -{ - Transliterator_object *to_orig = php_intl_transliterator_fetch_object(object); - zend_object *ret_val = Transliterator_ce_ptr->create_object(object->ce); - Transliterator_object *to_new = php_intl_transliterator_fetch_object(ret_val); - - zend_objects_clone_members( &to_new->zo, &to_orig->zo ); - if (to_orig->utrans != NULL) { - /* guaranteed to return NULL if it fails */ - UErrorCode error = U_ZERO_ERROR; - UTransliterator *utrans = utrans_clone( to_orig->utrans, &error); - - if (U_FAILURE(error)) { - if (utrans != NULL) { - transliterator_object_destroy(to_new); - } - zend_throw_error(NULL, "Failed to clone Transliterator"); - } else { - to_new->utrans = utrans; - } - } else { - /* We shouldn't have unconstructed objects in the first place */ - zend_throw_error(NULL, "Cannot clone uninitialized Transliterator"); - } - - return ret_val; -} -/* }}} */ - -/* {{{ transliterator_register_Transliterator_class - * Initialize 'Transliterator' class - */ -void transliterator_register_Transliterator_class( void ) -{ - /* Create and register 'Transliterator' class. */ - Transliterator_ce_ptr = register_class_Transliterator(); - Transliterator_ce_ptr->create_object = Transliterator_object_create; - Transliterator_ce_ptr->default_object_handlers = &Transliterator_handlers; - memcpy( &Transliterator_handlers, &std_object_handlers, sizeof Transliterator_handlers ); - Transliterator_handlers.offset = XtOffsetOf(Transliterator_object, zo); - Transliterator_handlers.free_obj = Transliterator_objects_free; - Transliterator_handlers.clone_obj = Transliterator_clone_obj; -} -/* }}} */ diff --git a/ext/intl/transliterator/transliterator_class.cpp b/ext/intl/transliterator/transliterator_class.cpp new file mode 100644 index 0000000000000..fd0cd4f3c3e64 --- /dev/null +++ b/ext/intl/transliterator/transliterator_class.cpp @@ -0,0 +1,174 @@ +/* + +----------------------------------------------------------------------+ + | 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: Gustavo Lopes | + +----------------------------------------------------------------------+ + */ + +#include "transliterator_class.h" +extern "C" { +#include "php_intl.h" +#include "intl_error.h" +#include "intl_convert.h" +#include "intl_data.h" +#include "transliterator_arginfo.h" +} + +#include + +zend_class_entry *Transliterator_ce_ptr = nullptr; + +zend_object_handlers Transliterator_handlers; + +/* {{{ int transliterator_object_construct( zval *object, UTransliterator *utrans, UErrorCode *status ) + * Initialize internals of Transliterator_object. + */ +U_CFUNC int transliterator_object_construct( zval *object, + UTransliterator *utrans, + UErrorCode *status ) +{ + const UChar *ustr_id; + int32_t ustr_id_len; + zend_string *u8str; + zval tmp; + Transliterator_object *to; + + TRANSLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK; + + assert( to->utrans == nullptr ); + /* this assignment must happen before any return with failure because the + * caller relies on it always being made (so it can just destroy the object + * to close the transliterator) */ + to->utrans = utrans; + + ustr_id = utrans_getUnicodeID( utrans, &ustr_id_len ); + u8str = intl_convert_utf16_to_utf8(ustr_id, (int ) ustr_id_len, status ); + if( !u8str ) + { + return FAILURE; + } + + ZVAL_NEW_STR(&tmp, u8str); + zend_update_property(Transliterator_ce_ptr, Z_OBJ_P(object), + "id", sizeof( "id" ) - 1, &tmp ); + GC_DELREF(u8str); + return SUCCESS; +} +/* }}} */ + +/* + * Auxiliary functions needed by objects of 'Transliterator' class + */ + +/* {{{ void transliterator_object_init( Transliterator_object* to ) + * Initialize internals of Transliterator_object. + */ +static void transliterator_object_init( Transliterator_object* to ) +{ + if( !to ) + return; + + intl_error_init( TRANSLITERATOR_ERROR_P( to ) ); +} +/* }}} */ + +/* {{{ void transliterator_object_destroy( Transliterator_object* to ) + * Clean up mem allocted by internals of Transliterator_object + */ +static void transliterator_object_destroy( Transliterator_object* to ) +{ + if( !to ) + return; + + if( to->utrans ) + { + utrans_close( to->utrans ); + to->utrans = nullptr; + } + + intl_error_reset( TRANSLITERATOR_ERROR_P( to ) ); +} +/* }}} */ + +/* {{{ Transliterator_objects_free */ +static void Transliterator_objects_free( zend_object *object ) +{ + Transliterator_object* to = php_intl_transliterator_fetch_object(object); + + zend_object_std_dtor( &to->zo ); + + transliterator_object_destroy( to ); +} +/* }}} */ + +/* {{{ Transliterator_object_create */ +static zend_object *Transliterator_object_create( zend_class_entry *ce ) +{ + Transliterator_object* intern; + + intern = reinterpret_cast(zend_object_alloc(sizeof(Transliterator_object), ce)); + + zend_object_std_init( &intern->zo, ce ); + object_properties_init( &intern->zo, ce ); + transliterator_object_init( intern ); + + return &intern->zo; +} +/* }}} */ + +/* + * Object handlers for Transliterator class (and subclasses) + */ + +/* {{{ clone handler for Transliterator */ +static zend_object *Transliterator_clone_obj( zend_object *object ) +{ + Transliterator_object *to_orig = php_intl_transliterator_fetch_object(object); + zend_object *ret_val = Transliterator_ce_ptr->create_object(object->ce); + Transliterator_object *to_new = php_intl_transliterator_fetch_object(ret_val); + + zend_objects_clone_members( &to_new->zo, &to_orig->zo ); + if (to_orig->utrans != nullptr) { + /* guaranteed to return nullptr if it fails */ + UErrorCode error = U_ZERO_ERROR; + UTransliterator *utrans = utrans_clone( to_orig->utrans, &error); + + if (U_FAILURE(error)) { + if (utrans != nullptr) { + transliterator_object_destroy(to_new); + } + zend_throw_error(nullptr, "Failed to clone Transliterator"); + } else { + to_new->utrans = utrans; + } + } else { + /* We shouldn't have unconstructed objects in the first place */ + zend_throw_error(nullptr, "Cannot clone uninitialized Transliterator"); + } + + return ret_val; +} +/* }}} */ + +/* {{{ transliterator_register_Transliterator_class + * Initialize 'Transliterator' class + */ +U_CFUNC void transliterator_register_Transliterator_class( void ) +{ + /* Create and register 'Transliterator' class. */ + Transliterator_ce_ptr = register_class_Transliterator(); + Transliterator_ce_ptr->create_object = Transliterator_object_create; + Transliterator_ce_ptr->default_object_handlers = &Transliterator_handlers; + memcpy( &Transliterator_handlers, &std_object_handlers, sizeof Transliterator_handlers ); + Transliterator_handlers.offset = XtOffsetOf(Transliterator_object, zo); + Transliterator_handlers.free_obj = Transliterator_objects_free; + Transliterator_handlers.clone_obj = Transliterator_clone_obj; +} +/* }}} */ diff --git a/ext/intl/transliterator/transliterator_class.h b/ext/intl/transliterator/transliterator_class.h index 2ce85d6cfdb74..7e02d6fa5e287 100644 --- a/ext/intl/transliterator/transliterator_class.h +++ b/ext/intl/transliterator/transliterator_class.h @@ -17,8 +17,14 @@ #include +#ifdef __cplusplus +extern "C" { +#endif #include "intl_common.h" #include "intl_error.h" +#ifdef __cplusplus +} +#endif #include @@ -56,6 +62,9 @@ static inline Transliterator_object *php_intl_transliterator_fetch_object(zend_o RETURN_THROWS(); \ } +#ifdef __cplusplus +extern "C" { +#endif int transliterator_object_construct( zval *object, UTransliterator *utrans, UErrorCode *status ); @@ -64,5 +73,8 @@ void transliterator_register_Transliterator_class( void ); extern zend_class_entry *Transliterator_ce_ptr; extern zend_object_handlers Transliterator_handlers; +#ifdef __cplusplus +} +#endif #endif /* #ifndef TRANSLITERATOR_CLASS_H */ diff --git a/ext/intl/transliterator/transliterator_methods.c b/ext/intl/transliterator/transliterator_methods.c deleted file mode 100644 index ff3ddf5161377..0000000000000 --- a/ext/intl/transliterator/transliterator_methods.c +++ /dev/null @@ -1,466 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Gustavo Lopes | - +----------------------------------------------------------------------+ - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "php_intl.h" -#include "transliterator.h" -#include "transliterator_class.h" -#include "intl_data.h" -#include "intl_convert.h" - -#include - -static int create_transliterator( char *str_id, size_t str_id_len, zend_long direction, zval *object ) -{ - Transliterator_object *to; - UChar *ustr_id = NULL; - int32_t ustr_id_len = 0; - UTransliterator *utrans; - UParseError parse_error; - - intl_error_reset( NULL ); - - if( ( direction != TRANSLITERATOR_FORWARD ) && (direction != TRANSLITERATOR_REVERSE ) ) - { - zend_argument_value_error(2, "must be either Transliterator::FORWARD or Transliterator::REVERSE"); - return FAILURE; - } - - object_init_ex( object, Transliterator_ce_ptr ); - TRANSLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK; /* fetch zend object from zval "object" into "to" */ - - /* Convert transliterator id to UTF-16 */ - intl_convert_utf8_to_utf16( &ustr_id, &ustr_id_len, str_id, str_id_len, TRANSLITERATOR_ERROR_CODE_P( to ) ); - 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 ); - zval_ptr_dtor( object ); - return FAILURE; - } - - /* Open ICU Transliterator. */ - utrans = utrans_openU( ustr_id, ustr_id_len, (UTransDirection ) direction, - NULL, -1, &parse_error, TRANSLITERATOR_ERROR_CODE_P( to ) ); - if (ustr_id) { - efree( ustr_id ); - } - - if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to ) ) ) - { - char *buf = NULL; - intl_error_set_code( NULL, TRANSLITERATOR_ERROR_CODE( to ) ); - spprintf( &buf, 0, "transliterator_create: 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 ); - } - else - { - intl_error_set_custom_msg( NULL, buf, /* copy message */ 1 ); - efree( buf ); - } - zval_ptr_dtor( object ); - return FAILURE; - } - - transliterator_object_construct( object, utrans, TRANSLITERATOR_ERROR_CODE_P( to ) ); - /* no need to close the transliterator manually on construction error */ - 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 ); - zval_ptr_dtor( object ); - return FAILURE; - } - - return SUCCESS; -} - -/* {{{ Opens a transliterator by id. */ -PHP_FUNCTION( transliterator_create ) -{ - char *str_id; - size_t str_id_len; - zend_long direction = TRANSLITERATOR_FORWARD; - int res; - - TRANSLITERATOR_METHOD_INIT_VARS; - - (void) to; /* unused */ - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_STRING(str_id, str_id_len) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(direction) - ZEND_PARSE_PARAMETERS_END(); - - object = return_value; - res = create_transliterator( str_id, str_id_len, direction, object ); - if( res == FAILURE ) - RETURN_NULL(); - - /* success, leave return_value as it is (set by create_transliterator) */ -} -/* }}} */ - -/* {{{ Opens a transliterator by id. */ -PHP_FUNCTION( transliterator_create_from_rules ) -{ - char *str_rules; - size_t str_rules_len; - UChar *ustr_rules = NULL; - int32_t ustr_rules_len = 0; - zend_long direction = TRANSLITERATOR_FORWARD; - UParseError parse_error; - UTransliterator *utrans; - UChar id[] = {0x52, 0x75, 0x6C, 0x65, 0x73, 0x54, 0x72, - 0x61, 0x6E, 0x73, 0x50, 0x48, 0x50, 0}; /* RulesTransPHP */ - TRANSLITERATOR_METHOD_INIT_VARS; - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_STRING(str_rules, str_rules_len) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(direction) - ZEND_PARSE_PARAMETERS_END(); - - if( ( direction != TRANSLITERATOR_FORWARD ) && (direction != TRANSLITERATOR_REVERSE ) ) - { - zend_argument_value_error(2, "must be either Transliterator::FORWARD or Transliterator::REVERSE"); - RETURN_THROWS(); - } - - object = return_value; - object_init_ex( object, Transliterator_ce_ptr ); - TRANSLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK; - - intl_convert_utf8_to_utf16( &ustr_rules, &ustr_rules_len, - str_rules, str_rules_len, TRANSLITERATOR_ERROR_CODE_P( to ) ); - /* (I'm not a big fan of non-obvious flow control macros ). - * This one checks the error value, destroys object and returns false */ - INTL_METHOD_CHECK_STATUS_OR_NULL( to, "String conversion of rules to UTF-16 failed" ); - - /* Open ICU Transliterator. */ - utrans = utrans_openU( id, ( sizeof( id ) - 1 ) / ( sizeof( *id ) ), (UTransDirection ) direction, - ustr_rules, ustr_rules_len, &parse_error, TRANSLITERATOR_ERROR_CODE_P( to ) ); - if (ustr_rules) { - efree( ustr_rules ); - } - - intl_error_set_code( NULL, INTL_DATA_ERROR_CODE( to ) ); - if( U_FAILURE( INTL_DATA_ERROR_CODE( to ) ) ) - { - 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 " - "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 ); - efree( msg ); - } - zval_ptr_dtor( return_value ); - RETURN_NULL(); - } - 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" ); -} -/* }}} */ - -/* {{{ Opens the inverse transliterator transliterator. */ -PHP_FUNCTION( transliterator_create_inverse ) -{ - Transliterator_object *to_orig; - UTransliterator *utrans; - TRANSLITERATOR_METHOD_INIT_VARS; - - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", - &object, Transliterator_ce_ptr ) == FAILURE ) - { - RETURN_THROWS(); - } - - TRANSLITERATOR_METHOD_FETCH_OBJECT; - to_orig = to; - - object = return_value; - object_init_ex( object, Transliterator_ce_ptr ); - 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 " - "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" ); -} -/* }}} */ - -/* {{{ Return an array with the registered transliterator IDs. */ -PHP_FUNCTION( transliterator_list_ids ) -{ - UEnumeration *en; - const UChar *elem; - int32_t elem_len; - UErrorCode status = U_ZERO_ERROR; - - intl_error_reset( NULL ); - - ZEND_PARSE_PARAMETERS_NONE(); - - en = utrans_openIDs( &status ); - INTL_CHECK_STATUS( status, - "transliterator_list_ids: Failed to obtain registered transliterators" ); - - array_init( return_value ); - while( (elem = uenum_unext( en, &elem_len, &status )) ) - { - zend_string *el = intl_convert_utf16_to_utf8(elem, elem_len, &status ); - - if( !el ) - { - break; - } - else - { - add_next_index_str( return_value, el); - } - } - uenum_close( en ); - - intl_error_set_code( NULL, status ); - if( U_FAILURE( status ) ) - { - 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 ); - } -} -/* }}} */ - -/* {{{ Transliterate a string. */ -PHP_FUNCTION( transliterator_transliterate ) -{ - char *str; - UChar *ustr = NULL, - *uresult = NULL; - size_t str_len; - int32_t ustr_len = 0, - capacity, - uresult_len; - zend_long start = 0, - limit = -1; - int success = 0; - zval tmp_object; - TRANSLITERATOR_METHOD_INIT_VARS; - - object = getThis(); - - ZVAL_UNDEF(&tmp_object); - - if (object == NULL) { - /* in non-OOP version, accept both a transliterator and a string */ - zend_string *arg1_str; - zend_object *arg1_obj; - - ZEND_PARSE_PARAMETERS_START(2, 4) - Z_PARAM_OBJ_OF_CLASS_OR_STR(arg1_obj, Transliterator_ce_ptr, arg1_str) - Z_PARAM_STRING(str, str_len) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(start) - Z_PARAM_LONG(limit) - ZEND_PARSE_PARAMETERS_END(); - - if (arg1_str) { /* not a transliterator object as first argument */ - int res; - object = &tmp_object; - res = create_transliterator(ZSTR_VAL(arg1_str), ZSTR_LEN(arg1_str), TRANSLITERATOR_FORWARD, object); - if( res == FAILURE ) - { - if (!EG(exception)) { - zend_string *message = intl_error_get_message( NULL ); - php_error_docref(NULL, E_WARNING, "Could not create transliterator with ID \"%s\" (%s)", ZSTR_VAL(arg1_str), ZSTR_VAL(message) ); - zend_string_free( message ); - } - ZVAL_UNDEF(&tmp_object); - /* don't set U_ILLEGAL_ARGUMENT_ERROR to allow fetching of inner error */ - goto cleanup; - } - } else { - ZVAL_OBJ_COPY(&tmp_object, arg1_obj); - object = &tmp_object; - } - } else if(zend_parse_parameters( ZEND_NUM_ARGS(), "s|ll", &str, &str_len, &start, &limit) == FAILURE) { - RETURN_THROWS(); - } - - if (limit < -1) { - zend_argument_value_error(object ? 3 : 4, "must be greater than or equal to -1"); - goto cleanup_object; - } - - if (start < 0) { - zend_argument_value_error(object ? 2 : 3, "must be greater than or equal to 0"); - goto cleanup_object; - } - - if (limit != -1 && start > limit) { - zend_argument_value_error(object ? 2 : 3, "must be less than or equal to argument #%d ($end)", object ? 3 : 4); - goto cleanup_object; - } - - /* end argument parsing/validation */ - - TRANSLITERATOR_METHOD_FETCH_OBJECT; - - intl_convert_utf8_to_utf16(&ustr, &ustr_len, str, str_len, TRANSLITERATOR_ERROR_CODE_P(to)); - INTL_METHOD_CHECK_STATUS_OR_GOTO(to, "String conversion of string to UTF-16 failed", cleanup_object); - - /* we've started allocating resources, goto from now on */ - - if( ( start > ustr_len ) || (( limit != -1 ) && (limit > ustr_len ) ) ) - { - char *msg; - spprintf( &msg, 0, - "transliterator_transliterate: 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 ); - efree( msg ); - } - goto cleanup; - } - - uresult = safe_emalloc( ustr_len, sizeof( UChar ), 1 * sizeof( UChar ) ); - capacity = ustr_len + 1; - - while( 1 ) - { - int32_t temp_limit = ( limit == -1 ? ustr_len : (int32_t) limit ); - memcpy( uresult, ustr, ustr_len * sizeof( UChar ) ); - uresult_len = ustr_len; - - utrans_transUChars( to->utrans, uresult, &uresult_len, capacity, (int32_t) start, - &temp_limit, TRANSLITERATOR_ERROR_CODE_P( to ) ); - if( TRANSLITERATOR_ERROR_CODE( to ) == U_BUFFER_OVERFLOW_ERROR ) - { - efree( uresult ); - - uresult = safe_emalloc( uresult_len, sizeof( UChar ), 1 * sizeof( UChar ) ); - capacity = uresult_len + 1; - - intl_error_reset( TRANSLITERATOR_ERROR_P( to ) ); - } - else if(TRANSLITERATOR_ERROR_CODE( to ) == U_STRING_NOT_TERMINATED_WARNING ) - { - uresult = safe_erealloc( uresult, uresult_len, sizeof( UChar ), 1 * sizeof( UChar ) ); - - intl_error_reset( TRANSLITERATOR_ERROR_P( to ) ); - break; - } - 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 ); - goto cleanup; - } - else - break; - } - - uresult[uresult_len] = (UChar) 0; - - success = 1; - -cleanup: - if( ustr ) - efree( ustr ); - - if( success ) { - /* frees uresult even on error */ - INTL_METHOD_RETVAL_UTF8( to, uresult, uresult_len, 1 ); - } - else - { - if( uresult ) - efree( uresult ); - RETVAL_FALSE; - } - -cleanup_object: - zval_ptr_dtor( &tmp_object ); -} -/* }}} */ - -PHP_METHOD( Transliterator, __construct ) -{ - /* this constructor shouldn't be called as it's private */ - zend_throw_exception( NULL, - "An object of this type cannot be created with the new operator.", - 0 ); -} - -/* {{{ Get the last error code for this transliterator. */ -PHP_FUNCTION( transliterator_get_error_code ) -{ - TRANSLITERATOR_METHOD_INIT_VARS - - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", - &object, Transliterator_ce_ptr ) == FAILURE ) - { - RETURN_THROWS(); - } - - /* Fetch the object (without resetting its last error code ). */ - to = Z_INTL_TRANSLITERATOR_P( object ); - - RETURN_LONG( (zend_long) TRANSLITERATOR_ERROR_CODE( to ) ); -} -/* }}} */ - - -/* {{{ Get the last error message for this transliterator. */ -PHP_FUNCTION( transliterator_get_error_message ) -{ - zend_string* message = NULL; - TRANSLITERATOR_METHOD_INIT_VARS - - if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", - &object, Transliterator_ce_ptr ) == FAILURE ) - { - RETURN_THROWS(); - } - - - /* Fetch the object (without resetting its last error code ). */ - to = Z_INTL_TRANSLITERATOR_P( object ); - - /* Return last error message. */ - message = intl_error_get_message( TRANSLITERATOR_ERROR_P( to ) ); - RETURN_STR( message ); -} -/* }}} */ diff --git a/ext/intl/transliterator/transliterator_methods.cpp b/ext/intl/transliterator/transliterator_methods.cpp new file mode 100644 index 0000000000000..d8a8cbb7a49ec --- /dev/null +++ b/ext/intl/transliterator/transliterator_methods.cpp @@ -0,0 +1,469 @@ +/* + +----------------------------------------------------------------------+ + | 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: Gustavo Lopes | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if __cplusplus >= 201703L +#include +#include +#endif + +extern "C" { +#include "php_intl.h" +#include "intl_data.h" +#include "intl_convert.h" +} +#include "transliterator.h" +#include "transliterator_class.h" + +#include + +static int create_transliterator( char *str_id, size_t str_id_len, zend_long direction, zval *object ) +{ + Transliterator_object *to; + UChar *ustr_id = nullptr; + int32_t ustr_id_len = 0; + UTransliterator *utrans; + UParseError parse_error; + + intl_error_reset( nullptr ); + + if( ( direction != TRANSLITERATOR_FORWARD ) && (direction != TRANSLITERATOR_REVERSE ) ) + { + zend_argument_value_error(2, "must be either Transliterator::FORWARD or Transliterator::REVERSE"); + return FAILURE; + } + + object_init_ex( object, Transliterator_ce_ptr ); + TRANSLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK; /* fetch zend object from zval "object" into "to" */ + + /* Convert transliterator id to UTF-16 */ + intl_convert_utf8_to_utf16( &ustr_id, &ustr_id_len, str_id, str_id_len, TRANSLITERATOR_ERROR_CODE_P( to ) ); + if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to ) ) ) + { + intl_error_set_code( nullptr, TRANSLITERATOR_ERROR_CODE( to ) ); + intl_error_set_custom_msg( nullptr, "String conversion of id to UTF-16 failed"); + zval_ptr_dtor( object ); + return FAILURE; + } + + /* Open ICU Transliterator. */ + utrans = utrans_openU( ustr_id, ustr_id_len, (UTransDirection ) direction, + nullptr, -1, &parse_error, TRANSLITERATOR_ERROR_CODE_P( to ) ); + if (ustr_id) { + efree( ustr_id ); + } + + if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to ) ) ) + { + char *buf = nullptr; + intl_error_set_code( nullptr, TRANSLITERATOR_ERROR_CODE( to ) ); + spprintf( &buf, 0, "unable to open ICU transliterator" + " with id \"%s\"", str_id ); + if( buf == nullptr ) { + intl_error_set_custom_msg(nullptr, "unable to open ICU transliterator"); + } + else + { + intl_error_set_custom_msg(nullptr, buf); + efree( buf ); + } + zval_ptr_dtor( object ); + return FAILURE; + } + + transliterator_object_construct( object, utrans, TRANSLITERATOR_ERROR_CODE_P( to ) ); + /* no need to close the transliterator manually on construction error */ + if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to ) ) ) + { + intl_error_set_code( nullptr, TRANSLITERATOR_ERROR_CODE( to ) ); + intl_error_set_custom_msg(nullptr, "internal constructor call failed"); + zval_ptr_dtor( object ); + return FAILURE; + } + + return SUCCESS; +} + +/* {{{ Opens a transliterator by id. */ +U_CFUNC PHP_FUNCTION( transliterator_create ) +{ + char *str_id; + size_t str_id_len; + zend_long direction = TRANSLITERATOR_FORWARD; + int res; + + TRANSLITERATOR_METHOD_INIT_VARS; + + (void) to; /* unused */ + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STRING(str_id, str_id_len) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(direction) + ZEND_PARSE_PARAMETERS_END(); + + object = return_value; + res = create_transliterator( str_id, str_id_len, direction, object ); + if( res == FAILURE ) + RETURN_NULL(); + + /* success, leave return_value as it is (set by create_transliterator) */ +} +/* }}} */ + +/* {{{ Opens a transliterator by id. */ +U_CFUNC PHP_FUNCTION( transliterator_create_from_rules ) +{ + char *str_rules; + size_t str_rules_len; + UChar *ustr_rules = nullptr; + int32_t ustr_rules_len = 0; + zend_long direction = TRANSLITERATOR_FORWARD; + UParseError parse_error; + UTransliterator *utrans; + UChar id[] = {0x52, 0x75, 0x6C, 0x65, 0x73, 0x54, 0x72, + 0x61, 0x6E, 0x73, 0x50, 0x48, 0x50, 0}; /* RulesTransPHP */ + TRANSLITERATOR_METHOD_INIT_VARS; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STRING(str_rules, str_rules_len) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(direction) + ZEND_PARSE_PARAMETERS_END(); + + if( ( direction != TRANSLITERATOR_FORWARD ) && (direction != TRANSLITERATOR_REVERSE ) ) + { + zend_argument_value_error(2, "must be either Transliterator::FORWARD or Transliterator::REVERSE"); + RETURN_THROWS(); + } + + object = return_value; + object_init_ex( object, Transliterator_ce_ptr ); + TRANSLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK; + + intl_convert_utf8_to_utf16( &ustr_rules, &ustr_rules_len, + str_rules, str_rules_len, TRANSLITERATOR_ERROR_CODE_P( to ) ); + /* (I'm not a big fan of non-obvious flow control macros ). + * This one checks the error value, destroys object and returns false */ + INTL_METHOD_CHECK_STATUS_OR_NULL( to, "String conversion of rules to UTF-16 failed" ); + + /* Open ICU Transliterator. */ + utrans = utrans_openU( id, ( sizeof( id ) - 1 ) / ( sizeof( *id ) ), (UTransDirection ) direction, + ustr_rules, ustr_rules_len, &parse_error, TRANSLITERATOR_ERROR_CODE_P( to ) ); + if (ustr_rules) { + efree( ustr_rules ); + } + + intl_error_set_code( nullptr, INTL_DATA_ERROR_CODE( to ) ); + if( U_FAILURE( INTL_DATA_ERROR_CODE( to ) ) ) + { + char *msg = nullptr; + smart_str parse_error_str; + parse_error_str = intl_parse_error_to_string( &parse_error ); + 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 != nullptr ) + { + intl_errors_set_custom_msg( INTL_DATA_ERROR_P( to ), msg); + efree( msg ); + } + zval_ptr_dtor( return_value ); + RETURN_NULL(); + } + 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, "internal constructor call failed" ); +} +/* }}} */ + +/* {{{ Opens the inverse transliterator transliterator. */ +U_CFUNC PHP_FUNCTION( transliterator_create_inverse ) +{ + Transliterator_object *to_orig; + UTransliterator *utrans; + TRANSLITERATOR_METHOD_INIT_VARS; + + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", + &object, Transliterator_ce_ptr ) == FAILURE ) + { + RETURN_THROWS(); + } + + TRANSLITERATOR_METHOD_FETCH_OBJECT; + to_orig = to; + + object = return_value; + object_init_ex( object, Transliterator_ce_ptr ); + 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, "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, "internal constructor call failed" ); +} +/* }}} */ + +/* {{{ Return an array with the registered transliterator IDs. */ +U_CFUNC PHP_FUNCTION( transliterator_list_ids ) +{ + UEnumeration *en; + const UChar *elem; + int32_t elem_len; + UErrorCode status = U_ZERO_ERROR; + + intl_error_reset( nullptr ); + + ZEND_PARSE_PARAMETERS_NONE(); + + en = utrans_openIDs( &status ); + INTL_CHECK_STATUS( status, + "Failed to obtain registered transliterators" ); + + array_init( return_value ); + while( (elem = uenum_unext( en, &elem_len, &status )) ) + { + zend_string *el = intl_convert_utf16_to_utf8(elem, elem_len, &status ); + + if( !el ) + { + break; + } + else + { + add_next_index_str( return_value, el); + } + } + uenum_close( en ); + + intl_error_set_code( nullptr, status ); + if( U_FAILURE( status ) ) + { + zend_array_destroy( Z_ARR_P(return_value) ); + RETVAL_FALSE; + intl_error_set_custom_msg( nullptr, + "Failed to build array of registered transliterators"); + } +} +/* }}} */ + +/* {{{ Transliterate a string. */ +U_CFUNC PHP_FUNCTION( transliterator_transliterate ) +{ + char *str; + UChar *ustr = nullptr, + *uresult = nullptr; + size_t str_len; + int32_t ustr_len = 0, + capacity, + uresult_len; + zend_long start = 0, + limit = -1; + int success = 0; + zval tmp_object; + TRANSLITERATOR_METHOD_INIT_VARS; + + object = getThis(); + + ZVAL_UNDEF(&tmp_object); + + if (object == nullptr) { + /* in non-OOP version, accept both a transliterator and a string */ + zend_string *arg1_str; + zend_object *arg1_obj; + + ZEND_PARSE_PARAMETERS_START(2, 4) + Z_PARAM_OBJ_OF_CLASS_OR_STR(arg1_obj, Transliterator_ce_ptr, arg1_str) + Z_PARAM_STRING(str, str_len) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(start) + Z_PARAM_LONG(limit) + ZEND_PARSE_PARAMETERS_END(); + + if (arg1_str) { /* not a transliterator object as first argument */ + int res; + object = &tmp_object; + res = create_transliterator(ZSTR_VAL(arg1_str), ZSTR_LEN(arg1_str), TRANSLITERATOR_FORWARD, object); + if( res == FAILURE ) + { + if (!EG(exception)) { + zend_string *message = intl_error_get_message( nullptr ); + php_error_docref(nullptr, E_WARNING, "Could not create transliterator with ID \"%s\" (%s)", ZSTR_VAL(arg1_str), ZSTR_VAL(message) ); + zend_string_free( message ); + } + ZVAL_UNDEF(&tmp_object); + /* don't set U_ILLEGAL_ARGUMENT_ERROR to allow fetching of inner error */ + goto cleanup; + } + } else { + ZVAL_OBJ_COPY(&tmp_object, arg1_obj); + object = &tmp_object; + } + } else if(zend_parse_parameters( ZEND_NUM_ARGS(), "s|ll", &str, &str_len, &start, &limit) == FAILURE) { + RETURN_THROWS(); + } + + if (limit < -1) { + zend_argument_value_error(object ? 3 : 4, "must be greater than or equal to -1"); + goto cleanup_object; + } + + if (start < 0) { + zend_argument_value_error(object ? 2 : 3, "must be greater than or equal to 0"); + goto cleanup_object; + } + + if (limit != -1 && start > limit) { + zend_argument_value_error(object ? 2 : 3, "must be less than or equal to argument #%d ($end)", object ? 3 : 4); + goto cleanup_object; + } + + /* end argument parsing/validation */ + + TRANSLITERATOR_METHOD_FETCH_OBJECT; + + intl_convert_utf8_to_utf16(&ustr, &ustr_len, str, str_len, TRANSLITERATOR_ERROR_CODE_P(to)); + INTL_METHOD_CHECK_STATUS_OR_GOTO(to, "String conversion of string to UTF-16 failed", cleanup_object); + + /* we've started allocating resources, goto from now on */ + + if( ( start > ustr_len ) || (( limit != -1 ) && (limit > ustr_len ) ) ) + { + char *msg; + spprintf( &msg, 0, + "Neither \"start\" nor the \"end\" " + "arguments can exceed the number of UTF-16 code units " + "(in this case, %d)", (int) ustr_len ); + if(msg != nullptr ) + { + intl_errors_set(TRANSLITERATOR_ERROR_P(to), U_ILLEGAL_ARGUMENT_ERROR, msg); + efree( msg ); + } + goto cleanup; + } + + uresult = reinterpret_cast(safe_emalloc( ustr_len, sizeof( UChar ), 1 * sizeof( UChar ) )); + capacity = ustr_len + 1; + + while( 1 ) + { + int32_t temp_limit = ( limit == -1 ? ustr_len : (int32_t) limit ); + memcpy( uresult, ustr, ustr_len * sizeof( UChar ) ); + uresult_len = ustr_len; + + utrans_transUChars( to->utrans, uresult, &uresult_len, capacity, (int32_t) start, + &temp_limit, TRANSLITERATOR_ERROR_CODE_P( to ) ); + if( TRANSLITERATOR_ERROR_CODE( to ) == U_BUFFER_OVERFLOW_ERROR ) + { + efree( uresult ); + + uresult = reinterpret_cast(safe_emalloc( uresult_len, sizeof( UChar ), 1 * sizeof( UChar ) )); + capacity = uresult_len + 1; + + intl_error_reset( TRANSLITERATOR_ERROR_P( to ) ); + } + else if(TRANSLITERATOR_ERROR_CODE( to ) == U_STRING_NOT_TERMINATED_WARNING ) + { + uresult = reinterpret_cast(safe_erealloc( uresult, uresult_len, sizeof( UChar ), 1 * sizeof( UChar ) )); + + intl_error_reset( TRANSLITERATOR_ERROR_P( to ) ); + break; + } + else if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to ) ) ) + { + intl_error_set_code( nullptr, TRANSLITERATOR_ERROR_CODE( to ) ); + intl_errors_set_custom_msg( TRANSLITERATOR_ERROR_P( to ), "transliteration failed"); + goto cleanup; + } + else + break; + } + + uresult[uresult_len] = (UChar) 0; + + success = 1; + +cleanup: + if( ustr ) + efree( ustr ); + + if( success ) { + /* frees uresult even on error */ + INTL_METHOD_RETVAL_UTF8( to, uresult, uresult_len, 1 ); + } + else + { + if( uresult ) + efree( uresult ); + RETVAL_FALSE; + } + +cleanup_object: + zval_ptr_dtor( &tmp_object ); +} +/* }}} */ + +U_CFUNC PHP_METHOD( Transliterator, __construct ) +{ + /* this constructor shouldn't be called as it's private */ + zend_throw_exception( nullptr, + "An object of this type cannot be created with the new operator.", + 0 ); +} + +/* {{{ Get the last error code for this transliterator. */ +U_CFUNC PHP_FUNCTION( transliterator_get_error_code ) +{ + TRANSLITERATOR_METHOD_INIT_VARS + + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", + &object, Transliterator_ce_ptr ) == FAILURE ) + { + RETURN_THROWS(); + } + + /* Fetch the object (without resetting its last error code ). */ + to = Z_INTL_TRANSLITERATOR_P( object ); + + RETURN_LONG( (zend_long) TRANSLITERATOR_ERROR_CODE( to ) ); +} +/* }}} */ + + +/* {{{ Get the last error message for this transliterator. */ +U_CFUNC PHP_FUNCTION( transliterator_get_error_message ) +{ + zend_string* message = nullptr; + TRANSLITERATOR_METHOD_INIT_VARS + + if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "O", + &object, Transliterator_ce_ptr ) == FAILURE ) + { + RETURN_THROWS(); + } + + + /* Fetch the object (without resetting its last error code ). */ + to = Z_INTL_TRANSLITERATOR_P( object ); + + /* Return last error message. */ + message = intl_error_get_message( TRANSLITERATOR_ERROR_P( to ) ); + RETURN_STR( message ); +} +/* }}} */ diff --git a/ext/intl/uchar/uchar.c b/ext/intl/uchar/uchar.c deleted file mode 100644 index ecfcd8fbe624a..0000000000000 --- a/ext/intl/uchar/uchar.c +++ /dev/null @@ -1,627 +0,0 @@ -#include "uchar.h" -#include "intl_data.h" -#include "intl_convert.h" - -#include -#include - -#include "uchar_arginfo.h" - -#define IC_METHOD(mname) PHP_METHOD(IntlChar, mname) - -static inline int convert_cp(UChar32* pcp, zend_string *string_codepoint, zend_long int_codepoint) { - if (string_codepoint != NULL) { - int32_t i = 0; - size_t string_codepoint_length = ZSTR_LEN(string_codepoint); - - 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); - 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); - 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); - return FAILURE; - } - *pcp = (UChar32)int_codepoint; - return SUCCESS; -} - -static zend_never_inline int parse_code_point_param(INTERNAL_FUNCTION_PARAMETERS, UChar32 *cp) { - zend_string *string_codepoint; - zend_long int_codepoint = 0; - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint) - ZEND_PARSE_PARAMETERS_END_EX(return FAILURE); - return convert_cp(cp, string_codepoint, int_codepoint); -} - -/* {{{ Converts a numeric codepoint to UTF-8 - * Acts as an identify function when given a valid UTF-8 encoded codepoint - */ -IC_METHOD(chr) { - UChar32 cp; - char buffer[5]; - int buffer_len = 0; - - if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) { - RETURN_NULL(); - } - - /* We can use unsafe because we know the codepoint is in valid range - * and that 4 bytes is enough for any unicode point - */ - U8_APPEND_UNSAFE(buffer, buffer_len, cp); - buffer[buffer_len] = 0; - RETURN_STRINGL(buffer, buffer_len); -} -/* }}} */ - -/* {{{ Converts a UTf-8 encoded codepoint to its integer U32 value - * Acts as an identity function when passed a valid integer codepoint - */ -IC_METHOD(ord) { - UChar32 cp; - - if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) { - RETURN_NULL(); - } - - RETURN_LONG(cp); -} -/* }}} */ - -/* {{{ */ -IC_METHOD(hasBinaryProperty) { - UChar32 cp; - zend_long prop; - zend_string *string_codepoint; - zend_long int_codepoint = 0; - - ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint) - Z_PARAM_LONG(prop) - ZEND_PARSE_PARAMETERS_END(); - - if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) { - RETURN_NULL(); - } - - RETURN_BOOL(u_hasBinaryProperty(cp, (UProperty)prop)); -} -/* }}} */ - -/* {{{ */ -IC_METHOD(getIntPropertyValue) { - UChar32 cp; - zend_long prop; - zend_string *string_codepoint; - zend_long int_codepoint = 0; - - ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint) - Z_PARAM_LONG(prop) - ZEND_PARSE_PARAMETERS_END(); - - if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) { - RETURN_NULL(); - } - - RETURN_LONG(u_getIntPropertyValue(cp, (UProperty)prop)); -} -/* }}} */ - -/* {{{ */ -IC_METHOD(getIntPropertyMinValue) { - zend_long prop; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_LONG(prop) - ZEND_PARSE_PARAMETERS_END(); - - RETURN_LONG(u_getIntPropertyMinValue((UProperty)prop)); -} -/* }}} */ - -/* {{{ */ -IC_METHOD(getIntPropertyMaxValue) { - zend_long prop; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_LONG(prop) - ZEND_PARSE_PARAMETERS_END(); - - RETURN_LONG(u_getIntPropertyMaxValue((UProperty)prop)); -} -/* }}} */ - -/* {{{ */ -IC_METHOD(getNumericValue) { - UChar32 cp; - - if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) { - RETURN_NULL(); - } - - RETURN_DOUBLE(u_getNumericValue(cp)); -} -/* }}} */ - -/* {{{ */ -typedef struct _enumCharType_data { - zend_fcall_info fci; - zend_fcall_info_cache fci_cache; -} enumCharType_data; -static UBool enumCharType_callback(enumCharType_data *context, - UChar32 start, UChar32 limit, UCharCategory type) { - zval retval; - zval args[3]; - - ZVAL_NULL(&retval); - /* Note that $start is INclusive, while $limit is EXclusive - * Therefore (0, 32, 15) means CPs 0..31 are of type 15 - */ - ZVAL_LONG(&args[0], start); - ZVAL_LONG(&args[1], limit); - ZVAL_LONG(&args[2], type); - - context->fci.retval = &retval; - context->fci.param_count = 3; - context->fci.params = args; - - 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); - zval_ptr_dtor(&retval); - return 0; - } - zval_ptr_dtor(&retval); - return 1; -} -IC_METHOD(enumCharTypes) { - enumCharType_data context; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_FUNC(context.fci, context.fci_cache) - ZEND_PARSE_PARAMETERS_END(); - u_enumCharTypes((UCharEnumTypeRange*)enumCharType_callback, &context); -} -/* }}} */ - -/* {{{ */ -IC_METHOD(getBlockCode) { - UChar32 cp; - - if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) { - RETURN_NULL(); - } - - RETURN_LONG(ublock_getCode(cp)); -} -/* }}} */ - -/* {{{ */ -IC_METHOD(charName) { - UChar32 cp; - zend_string *string_codepoint; - zend_long int_codepoint = 0; - UErrorCode error = U_ZERO_ERROR; - zend_long nameChoice = U_UNICODE_CHAR_NAME; - zend_string *buffer = NULL; - int32_t buffer_len; - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(nameChoice) - ZEND_PARSE_PARAMETERS_END(); - - if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) { - RETURN_NULL(); - } - - buffer_len = u_charName(cp, (UCharNameChoice)nameChoice, NULL, 0, &error); - buffer = zend_string_alloc(buffer_len, 0); - error = U_ZERO_ERROR; - buffer_len = u_charName(cp, (UCharNameChoice)nameChoice, ZSTR_VAL(buffer), ZSTR_LEN(buffer) + 1, &error); - if (U_FAILURE(error)) { - zend_string_efree(buffer); - INTL_CHECK_STATUS_OR_NULL(error, "Failure getting character name"); - } - RETURN_NEW_STR(buffer); -} -/* }}} */ - -/* {{{ */ -IC_METHOD(charFromName) { - char *name; - size_t name_len; - zend_long nameChoice = U_UNICODE_CHAR_NAME; - UChar32 ret; - UErrorCode error = U_ZERO_ERROR; - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_STRING(name, name_len) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(nameChoice) - ZEND_PARSE_PARAMETERS_END(); - - ret = u_charFromName((UCharNameChoice)nameChoice, name, &error); - INTL_CHECK_STATUS_OR_NULL(error, NULL); - RETURN_LONG(ret); -} -/* }}} */ - -/* {{{ void void IntlChar::enumCharNames(int|string $start, int|string $limit, callable $callback, int $nameChoice = IntlChar::UNICODE_CHAR_NAME) */ -typedef struct _enumCharNames_data { - zend_fcall_info fci; - zend_fcall_info_cache fci_cache; -} enumCharNames_data; -static UBool enumCharNames_callback(enumCharNames_data *context, - UChar32 code, UCharNameChoice nameChoice, - const char *name, int32_t length) { - zval retval; - zval args[3]; - - ZVAL_NULL(&retval); - ZVAL_LONG(&args[0], code); - ZVAL_LONG(&args[1], nameChoice); - ZVAL_STRINGL(&args[2], name, length); - - context->fci.retval = &retval; - context->fci.param_count = 3; - context->fci.params = args; - - 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); - zval_ptr_dtor(&retval); - zval_ptr_dtor_str(&args[2]); - return 0; - } - zval_ptr_dtor(&retval); - zval_ptr_dtor_str(&args[2]); - return 1; -} -IC_METHOD(enumCharNames) { - UChar32 start, limit; - zend_string *string_start, *string_limit; - zend_long int_start = 0, int_limit = 0; - enumCharNames_data context; - zend_long nameChoice = U_UNICODE_CHAR_NAME; - UErrorCode error = U_ZERO_ERROR; - - - ZEND_PARSE_PARAMETERS_START(3, 4) - Z_PARAM_STR_OR_LONG(string_start, int_start) - Z_PARAM_STR_OR_LONG(string_limit, int_limit) - Z_PARAM_FUNC(context.fci, context.fci_cache) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(nameChoice) - ZEND_PARSE_PARAMETERS_END(); - - if (convert_cp(&start, string_start, int_start) == FAILURE || convert_cp(&limit, string_limit, int_limit) == FAILURE) { - RETURN_FALSE; - } - - u_enumCharNames(start, limit, (UEnumCharNamesFn*)enumCharNames_callback, &context, nameChoice, &error); - INTL_CHECK_STATUS(error, NULL); - RETURN_TRUE; -} -/* }}} */ - -/* {{{ */ -IC_METHOD(getPropertyName) { - zend_long property; - zend_long nameChoice = U_LONG_PROPERTY_NAME; - const char *ret; - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_LONG(property) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(nameChoice) - ZEND_PARSE_PARAMETERS_END(); - - ret = u_getPropertyName((UProperty)property, (UPropertyNameChoice)nameChoice); - if (ret) { - 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); - RETURN_FALSE; - } -} -/* }}} */ - -/* {{{ */ -IC_METHOD(getPropertyEnum) { - char *alias; - size_t alias_len; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(alias, alias_len) - ZEND_PARSE_PARAMETERS_END(); - - RETURN_LONG(u_getPropertyEnum(alias)); -} -/* }}} */ - -/* {{{ */ -IC_METHOD(getPropertyValueName) { - zend_long property, value, nameChoice = U_LONG_PROPERTY_NAME; - const char *ret; - - ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_LONG(property) - Z_PARAM_LONG(value) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(nameChoice) - ZEND_PARSE_PARAMETERS_END(); - - ret = u_getPropertyValueName((UProperty)property, value, (UPropertyNameChoice)nameChoice); - if (ret) { - 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); - RETURN_FALSE; - } -} -/* }}} */ - -/* {{{ */ -IC_METHOD(getPropertyValueEnum) { - zend_long property; - char *name; - size_t name_len; - - ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_LONG(property) - Z_PARAM_STRING(name, name_len) - ZEND_PARSE_PARAMETERS_END(); - - RETURN_LONG(u_getPropertyValueEnum((UProperty)property, name)); -} -/* }}} */ - -/* {{{ */ -IC_METHOD(foldCase) { - UChar32 cp, ret; - zend_long options = U_FOLD_CASE_DEFAULT; - zend_string *string_codepoint; - zend_long int_codepoint = 0; - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(options) - ZEND_PARSE_PARAMETERS_END(); - - if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) { - RETURN_NULL(); - } - - ret = u_foldCase(cp, options); - if (string_codepoint != NULL) { - char buffer[5]; - int buffer_len = 0; - U8_APPEND_UNSAFE(buffer, buffer_len, ret); - buffer[buffer_len] = 0; - RETURN_STRINGL(buffer, buffer_len); - } else { - RETURN_LONG(ret); - } -} -/* }}} */ - -/* {{{ */ -IC_METHOD(digit) { - UChar32 cp; - zend_long radix = 10; - int ret; - zend_string *string_codepoint; - zend_long int_codepoint = 0; - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(radix) - ZEND_PARSE_PARAMETERS_END(); - - if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) { - RETURN_NULL(); - } - - 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); - RETURN_FALSE; - } - RETURN_LONG(ret); -} -/* }}} */ - -/* {{{ */ -IC_METHOD(forDigit) { - zend_long digit, radix = 10; - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_LONG(digit) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(radix) - ZEND_PARSE_PARAMETERS_END(); - - RETURN_LONG(u_forDigit(digit, radix)); -} -/* }}} */ - -/* {{{ */ -IC_METHOD(charAge) { - UChar32 cp; - UVersionInfo version; - int i; - - if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) { - RETURN_NULL(); - } - - u_charAge(cp, version); - array_init(return_value); - for(i = 0; i < U_MAX_VERSION_LENGTH; ++i) { - add_next_index_long(return_value, version[i]); - } -} -/* }}} */ - -/* {{{ */ -IC_METHOD(getUnicodeVersion) { - UVersionInfo version; - int i; - - ZEND_PARSE_PARAMETERS_NONE(); - - u_getUnicodeVersion(version); - array_init(return_value); - for(i = 0; i < U_MAX_VERSION_LENGTH; ++i) { - add_next_index_long(return_value, version[i]); - } -} -/* }}} */ - -/* {{{ */ -IC_METHOD(getFC_NFKC_Closure) { - UChar32 cp; - UChar *closure; - zend_string *u8str; - int32_t closure_len; - UErrorCode error = U_ZERO_ERROR; - - if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) { - RETURN_NULL(); - } - - closure_len = u_getFC_NFKC_Closure(cp, NULL, 0, &error); - if (closure_len == 0) { - RETURN_EMPTY_STRING(); - } - closure = 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)) { - efree(closure); - INTL_CHECK_STATUS(error, "Failed getting closure"); - } - - error = U_ZERO_ERROR; - u8str = intl_convert_utf16_to_utf8(closure, closure_len, &error); - INTL_CHECK_STATUS(error, "Failed converting output to UTF8"); - efree(closure); - RETVAL_NEW_STR(u8str); -} -/* }}} */ - -/* {{{ */ -#define IC_BOOL_METHOD_CHAR(name) \ -IC_METHOD(name) { \ - UChar32 cp; \ - if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) { \ - RETURN_NULL(); \ - } \ - RETURN_BOOL(u_##name(cp)); \ -} -IC_BOOL_METHOD_CHAR(isUAlphabetic) -IC_BOOL_METHOD_CHAR(isULowercase) -IC_BOOL_METHOD_CHAR(isUUppercase) -IC_BOOL_METHOD_CHAR(isUWhiteSpace) -IC_BOOL_METHOD_CHAR(islower) -IC_BOOL_METHOD_CHAR(isupper) -IC_BOOL_METHOD_CHAR(istitle) -IC_BOOL_METHOD_CHAR(isdigit) -IC_BOOL_METHOD_CHAR(isalpha) -IC_BOOL_METHOD_CHAR(isalnum) -IC_BOOL_METHOD_CHAR(isxdigit) -IC_BOOL_METHOD_CHAR(ispunct) -IC_BOOL_METHOD_CHAR(isgraph) -IC_BOOL_METHOD_CHAR(isblank) -IC_BOOL_METHOD_CHAR(isdefined) -IC_BOOL_METHOD_CHAR(isspace) -IC_BOOL_METHOD_CHAR(isJavaSpaceChar) -IC_BOOL_METHOD_CHAR(isWhitespace) -IC_BOOL_METHOD_CHAR(iscntrl) -IC_BOOL_METHOD_CHAR(isISOControl) -IC_BOOL_METHOD_CHAR(isprint) -IC_BOOL_METHOD_CHAR(isbase) -IC_BOOL_METHOD_CHAR(isMirrored) -IC_BOOL_METHOD_CHAR(isIDStart) -IC_BOOL_METHOD_CHAR(isIDPart) -IC_BOOL_METHOD_CHAR(isIDIgnorable) -IC_BOOL_METHOD_CHAR(isJavaIDStart) -IC_BOOL_METHOD_CHAR(isJavaIDPart) -#undef IC_BOOL_METHOD_CHAR -/* }}} */ - -/* {{{ */ -#define IC_INT_METHOD_CHAR(name) \ -IC_METHOD(name) { \ - UChar32 cp; \ - if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) { \ - RETURN_NULL(); \ - } \ - RETURN_LONG(u_##name(cp)); \ -} -IC_INT_METHOD_CHAR(charDirection) -IC_INT_METHOD_CHAR(charType) -IC_INT_METHOD_CHAR(getCombiningClass) -IC_INT_METHOD_CHAR(charDigitValue) -#undef IC_INT_METHOD_CHAR -/* }}} */ - -/* {{{ Returns a utf-8 character if codepoint was passed as a utf-8 sequence - * Returns an int otherwise - */ -#define IC_CHAR_METHOD_CHAR(name) \ -IC_METHOD(name) { \ - UChar32 cp, ret; \ - zend_string *string_codepoint; \ - zend_long int_codepoint = -1; \ - ZEND_PARSE_PARAMETERS_START(1, 1) \ - Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint) \ - ZEND_PARSE_PARAMETERS_END(); \ - if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) { \ - RETURN_NULL(); \ - } \ - ret = u_##name(cp); \ - if (string_codepoint != NULL) { \ - char buffer[5]; \ - int buffer_len = 0; \ - U8_APPEND_UNSAFE(buffer, buffer_len, ret); \ - buffer[buffer_len] = 0; \ - RETURN_STRINGL(buffer, buffer_len); \ - } else { \ - RETURN_LONG(ret); \ - } \ -} -IC_CHAR_METHOD_CHAR(charMirror) -IC_CHAR_METHOD_CHAR(tolower) -IC_CHAR_METHOD_CHAR(toupper) -IC_CHAR_METHOD_CHAR(totitle) -IC_CHAR_METHOD_CHAR(getBidiPairedBracket) -#undef IC_CHAR_METHOD_CHAR -/* }}} */ - -int php_uchar_minit(INIT_FUNC_ARGS) { - register_class_IntlChar(); - - return SUCCESS; -} diff --git a/ext/intl/uchar/uchar.cpp b/ext/intl/uchar/uchar.cpp new file mode 100644 index 0000000000000..f1f777f0ea3eb --- /dev/null +++ b/ext/intl/uchar/uchar.cpp @@ -0,0 +1,629 @@ +extern "C" { +#include "uchar.h" +#include "intl_data.h" +#include "intl_convert.h" + +#include +#include + +#include "uchar_arginfo.h" +} + +#define IC_METHOD(mname) PHP_METHOD(IntlChar, mname) + +static inline int convert_cp(UChar32* pcp, zend_string *string_codepoint, zend_long int_codepoint) { + if (string_codepoint != NULL) { + int32_t i = 0; + size_t string_codepoint_length = ZSTR_LEN(string_codepoint); + + 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."); + 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."); + 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"); + return FAILURE; + } + *pcp = (UChar32)int_codepoint; + return SUCCESS; +} + +static zend_never_inline int parse_code_point_param(INTERNAL_FUNCTION_PARAMETERS, UChar32 *cp) { + zend_string *string_codepoint; + zend_long int_codepoint = 0; + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint) + ZEND_PARSE_PARAMETERS_END_EX(return FAILURE); + return convert_cp(cp, string_codepoint, int_codepoint); +} + +/* {{{ Converts a numeric codepoint to UTF-8 + * Acts as an identify function when given a valid UTF-8 encoded codepoint + */ +IC_METHOD(chr) { + UChar32 cp; + char buffer[5]; + int buffer_len = 0; + + if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) { + RETURN_NULL(); + } + + /* We can use unsafe because we know the codepoint is in valid range + * and that 4 bytes is enough for any unicode point + */ + U8_APPEND_UNSAFE(buffer, buffer_len, cp); + buffer[buffer_len] = 0; + RETURN_STRINGL(buffer, buffer_len); +} +/* }}} */ + +/* {{{ Converts a UTf-8 encoded codepoint to its integer U32 value + * Acts as an identity function when passed a valid integer codepoint + */ +IC_METHOD(ord) { + UChar32 cp; + + if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) { + RETURN_NULL(); + } + + RETURN_LONG(cp); +} +/* }}} */ + +/* {{{ */ +IC_METHOD(hasBinaryProperty) { + UChar32 cp; + zend_long prop; + zend_string *string_codepoint; + zend_long int_codepoint = 0; + + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint) + Z_PARAM_LONG(prop) + ZEND_PARSE_PARAMETERS_END(); + + if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) { + RETURN_NULL(); + } + + RETURN_BOOL(u_hasBinaryProperty(cp, (UProperty)prop)); +} +/* }}} */ + +/* {{{ */ +IC_METHOD(getIntPropertyValue) { + UChar32 cp; + zend_long prop; + zend_string *string_codepoint; + zend_long int_codepoint = 0; + + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint) + Z_PARAM_LONG(prop) + ZEND_PARSE_PARAMETERS_END(); + + if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) { + RETURN_NULL(); + } + + RETURN_LONG(u_getIntPropertyValue(cp, (UProperty)prop)); +} +/* }}} */ + +/* {{{ */ +IC_METHOD(getIntPropertyMinValue) { + zend_long prop; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_LONG(prop) + ZEND_PARSE_PARAMETERS_END(); + + RETURN_LONG(u_getIntPropertyMinValue((UProperty)prop)); +} +/* }}} */ + +/* {{{ */ +IC_METHOD(getIntPropertyMaxValue) { + zend_long prop; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_LONG(prop) + ZEND_PARSE_PARAMETERS_END(); + + RETURN_LONG(u_getIntPropertyMaxValue((UProperty)prop)); +} +/* }}} */ + +/* {{{ */ +IC_METHOD(getNumericValue) { + UChar32 cp; + + if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) { + RETURN_NULL(); + } + + RETURN_DOUBLE(u_getNumericValue(cp)); +} +/* }}} */ + +/* {{{ */ +typedef struct _enumCharType_data { + zend_fcall_info fci; + zend_fcall_info_cache fci_cache; +} enumCharType_data; +static UBool enumCharType_callback(enumCharType_data *context, + UChar32 start, UChar32 limit, UCharCategory type) { + zval retval; + zval args[3]; + + ZVAL_NULL(&retval); + /* Note that $start is INclusive, while $limit is EXclusive + * Therefore (0, 32, 15) means CPs 0..31 are of type 15 + */ + ZVAL_LONG(&args[0], start); + ZVAL_LONG(&args[1], limit); + ZVAL_LONG(&args[2], type); + + context->fci.retval = &retval; + context->fci.param_count = 3; + context->fci.params = args; + + 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"); + zval_ptr_dtor(&retval); + return 0; + } + zval_ptr_dtor(&retval); + return 1; +} +IC_METHOD(enumCharTypes) { + enumCharType_data context; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_FUNC(context.fci, context.fci_cache) + ZEND_PARSE_PARAMETERS_END(); + u_enumCharTypes((UCharEnumTypeRange*)enumCharType_callback, &context); +} +/* }}} */ + +/* {{{ */ +IC_METHOD(getBlockCode) { + UChar32 cp; + + if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) { + RETURN_NULL(); + } + + RETURN_LONG(ublock_getCode(cp)); +} +/* }}} */ + +/* {{{ */ +IC_METHOD(charName) { + UChar32 cp; + zend_string *string_codepoint; + zend_long int_codepoint = 0; + UErrorCode error = U_ZERO_ERROR; + zend_long nameChoice = U_UNICODE_CHAR_NAME; + zend_string *buffer = NULL; + int32_t buffer_len; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(nameChoice) + ZEND_PARSE_PARAMETERS_END(); + + if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) { + RETURN_NULL(); + } + + buffer_len = u_charName(cp, (UCharNameChoice)nameChoice, NULL, 0, &error); + buffer = zend_string_alloc(buffer_len, 0); + error = U_ZERO_ERROR; + buffer_len = u_charName(cp, (UCharNameChoice)nameChoice, ZSTR_VAL(buffer), ZSTR_LEN(buffer) + 1, &error); + if (U_FAILURE(error)) { + zend_string_efree(buffer); + INTL_CHECK_STATUS_OR_NULL(error, "Failure getting character name"); + } + RETURN_NEW_STR(buffer); +} +/* }}} */ + +/* {{{ */ +IC_METHOD(charFromName) { + char *name; + size_t name_len; + zend_long nameChoice = U_UNICODE_CHAR_NAME; + UChar32 ret; + UErrorCode error = U_ZERO_ERROR; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STRING(name, name_len) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(nameChoice) + ZEND_PARSE_PARAMETERS_END(); + + ret = u_charFromName((UCharNameChoice)nameChoice, name, &error); + INTL_CHECK_STATUS_OR_NULL(error, NULL); + RETURN_LONG(ret); +} +/* }}} */ + +/* {{{ void void IntlChar::enumCharNames(int|string $start, int|string $limit, callable $callback, int $nameChoice = IntlChar::UNICODE_CHAR_NAME) */ +typedef struct _enumCharNames_data { + zend_fcall_info fci; + zend_fcall_info_cache fci_cache; +} enumCharNames_data; +static UBool enumCharNames_callback(enumCharNames_data *context, + UChar32 code, UCharNameChoice nameChoice, + const char *name, int32_t length) { + zval retval; + zval args[3]; + + ZVAL_NULL(&retval); + ZVAL_LONG(&args[0], code); + ZVAL_LONG(&args[1], nameChoice); + ZVAL_STRINGL(&args[2], name, length); + + context->fci.retval = &retval; + context->fci.param_count = 3; + context->fci.params = args; + + 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"); + zval_ptr_dtor(&retval); + zval_ptr_dtor_str(&args[2]); + return 0; + } + zval_ptr_dtor(&retval); + zval_ptr_dtor_str(&args[2]); + return 1; +} +IC_METHOD(enumCharNames) { + UChar32 start, limit; + zend_string *string_start, *string_limit; + zend_long int_start = 0, int_limit = 0; + enumCharNames_data context; + zend_long nameChoice = U_UNICODE_CHAR_NAME; + UErrorCode error = U_ZERO_ERROR; + + + ZEND_PARSE_PARAMETERS_START(3, 4) + Z_PARAM_STR_OR_LONG(string_start, int_start) + Z_PARAM_STR_OR_LONG(string_limit, int_limit) + Z_PARAM_FUNC(context.fci, context.fci_cache) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(nameChoice) + ZEND_PARSE_PARAMETERS_END(); + + if (convert_cp(&start, string_start, int_start) == FAILURE || convert_cp(&limit, string_limit, int_limit) == FAILURE) { + RETURN_FALSE; + } + + u_enumCharNames(start, limit, (UEnumCharNamesFn*)enumCharNames_callback, &context, static_cast(nameChoice), &error); + INTL_CHECK_STATUS(error, NULL); + RETURN_TRUE; +} +/* }}} */ + +/* {{{ */ +IC_METHOD(getPropertyName) { + zend_long property; + zend_long nameChoice = U_LONG_PROPERTY_NAME; + const char *ret; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_LONG(property) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(nameChoice) + ZEND_PARSE_PARAMETERS_END(); + + ret = u_getPropertyName((UProperty)property, (UPropertyNameChoice)nameChoice); + if (ret) { + RETURN_STRING(ret); + } else { + intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR); + intl_error_set_custom_msg(NULL, "Failed to get property name"); + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ */ +IC_METHOD(getPropertyEnum) { + char *alias; + size_t alias_len; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STRING(alias, alias_len) + ZEND_PARSE_PARAMETERS_END(); + + RETURN_LONG(u_getPropertyEnum(alias)); +} +/* }}} */ + +/* {{{ */ +IC_METHOD(getPropertyValueName) { + zend_long property, value, nameChoice = U_LONG_PROPERTY_NAME; + const char *ret; + + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_LONG(property) + Z_PARAM_LONG(value) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(nameChoice) + ZEND_PARSE_PARAMETERS_END(); + + ret = u_getPropertyValueName((UProperty)property, value, (UPropertyNameChoice)nameChoice); + if (ret) { + RETURN_STRING(ret); + } else { + intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR); + intl_error_set_custom_msg(NULL, "Failed to get property name"); + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ */ +IC_METHOD(getPropertyValueEnum) { + zend_long property; + char *name; + size_t name_len; + + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_LONG(property) + Z_PARAM_STRING(name, name_len) + ZEND_PARSE_PARAMETERS_END(); + + RETURN_LONG(u_getPropertyValueEnum((UProperty)property, name)); +} +/* }}} */ + +/* {{{ */ +IC_METHOD(foldCase) { + UChar32 cp, ret; + zend_long options = U_FOLD_CASE_DEFAULT; + zend_string *string_codepoint; + zend_long int_codepoint = 0; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(options) + ZEND_PARSE_PARAMETERS_END(); + + if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) { + RETURN_NULL(); + } + + ret = u_foldCase(cp, options); + if (string_codepoint != NULL) { + char buffer[5]; + int buffer_len = 0; + U8_APPEND_UNSAFE(buffer, buffer_len, ret); + buffer[buffer_len] = 0; + RETURN_STRINGL(buffer, buffer_len); + } else { + RETURN_LONG(ret); + } +} +/* }}} */ + +/* {{{ */ +IC_METHOD(digit) { + UChar32 cp; + zend_long radix = 10; + int ret; + zend_string *string_codepoint; + zend_long int_codepoint = 0; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(radix) + ZEND_PARSE_PARAMETERS_END(); + + if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) { + RETURN_NULL(); + } + + 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"); + RETURN_FALSE; + } + RETURN_LONG(ret); +} +/* }}} */ + +/* {{{ */ +IC_METHOD(forDigit) { + zend_long digit, radix = 10; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_LONG(digit) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(radix) + ZEND_PARSE_PARAMETERS_END(); + + RETURN_LONG(u_forDigit(digit, radix)); +} +/* }}} */ + +/* {{{ */ +IC_METHOD(charAge) { + UChar32 cp; + UVersionInfo version; + int i; + + if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) { + RETURN_NULL(); + } + + u_charAge(cp, version); + array_init(return_value); + for(i = 0; i < U_MAX_VERSION_LENGTH; ++i) { + add_next_index_long(return_value, version[i]); + } +} +/* }}} */ + +/* {{{ */ +IC_METHOD(getUnicodeVersion) { + UVersionInfo version; + int i; + + ZEND_PARSE_PARAMETERS_NONE(); + + u_getUnicodeVersion(version); + array_init(return_value); + for(i = 0; i < U_MAX_VERSION_LENGTH; ++i) { + add_next_index_long(return_value, version[i]); + } +} +/* }}} */ + +/* {{{ */ +IC_METHOD(getFC_NFKC_Closure) { + UChar32 cp; + UChar *closure; + zend_string *u8str; + int32_t closure_len; + UErrorCode error = U_ZERO_ERROR; + + if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) { + RETURN_NULL(); + } + + closure_len = u_getFC_NFKC_Closure(cp, NULL, 0, &error); + if (closure_len == 0) { + RETURN_EMPTY_STRING(); + } + 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)) { + efree(closure); + INTL_CHECK_STATUS(error, "Failed getting closure"); + } + + error = U_ZERO_ERROR; + u8str = intl_convert_utf16_to_utf8(closure, closure_len, &error); + INTL_CHECK_STATUS(error, "Failed converting output to UTF8"); + efree(closure); + RETVAL_NEW_STR(u8str); +} +/* }}} */ + +/* {{{ */ +#define IC_BOOL_METHOD_CHAR(name) \ +IC_METHOD(name) { \ + UChar32 cp; \ + if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) { \ + RETURN_NULL(); \ + } \ + RETURN_BOOL(u_##name(cp)); \ +} +IC_BOOL_METHOD_CHAR(isUAlphabetic) +IC_BOOL_METHOD_CHAR(isULowercase) +IC_BOOL_METHOD_CHAR(isUUppercase) +IC_BOOL_METHOD_CHAR(isUWhiteSpace) +IC_BOOL_METHOD_CHAR(islower) +IC_BOOL_METHOD_CHAR(isupper) +IC_BOOL_METHOD_CHAR(istitle) +IC_BOOL_METHOD_CHAR(isdigit) +IC_BOOL_METHOD_CHAR(isalpha) +IC_BOOL_METHOD_CHAR(isalnum) +IC_BOOL_METHOD_CHAR(isxdigit) +IC_BOOL_METHOD_CHAR(ispunct) +IC_BOOL_METHOD_CHAR(isgraph) +IC_BOOL_METHOD_CHAR(isblank) +IC_BOOL_METHOD_CHAR(isdefined) +IC_BOOL_METHOD_CHAR(isspace) +IC_BOOL_METHOD_CHAR(isJavaSpaceChar) +IC_BOOL_METHOD_CHAR(isWhitespace) +IC_BOOL_METHOD_CHAR(iscntrl) +IC_BOOL_METHOD_CHAR(isISOControl) +IC_BOOL_METHOD_CHAR(isprint) +IC_BOOL_METHOD_CHAR(isbase) +IC_BOOL_METHOD_CHAR(isMirrored) +IC_BOOL_METHOD_CHAR(isIDStart) +IC_BOOL_METHOD_CHAR(isIDPart) +IC_BOOL_METHOD_CHAR(isIDIgnorable) +IC_BOOL_METHOD_CHAR(isJavaIDStart) +IC_BOOL_METHOD_CHAR(isJavaIDPart) +#undef IC_BOOL_METHOD_CHAR +/* }}} */ + +/* {{{ */ +#define IC_INT_METHOD_CHAR(name) \ +IC_METHOD(name) { \ + UChar32 cp; \ + if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) { \ + RETURN_NULL(); \ + } \ + RETURN_LONG(u_##name(cp)); \ +} +IC_INT_METHOD_CHAR(charDirection) +IC_INT_METHOD_CHAR(charType) +IC_INT_METHOD_CHAR(getCombiningClass) +IC_INT_METHOD_CHAR(charDigitValue) +#undef IC_INT_METHOD_CHAR +/* }}} */ + +/* {{{ Returns a utf-8 character if codepoint was passed as a utf-8 sequence + * Returns an int otherwise + */ +#define IC_CHAR_METHOD_CHAR(name) \ +IC_METHOD(name) { \ + UChar32 cp, ret; \ + zend_string *string_codepoint; \ + zend_long int_codepoint = -1; \ + ZEND_PARSE_PARAMETERS_START(1, 1) \ + Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint) \ + ZEND_PARSE_PARAMETERS_END(); \ + if (convert_cp(&cp, string_codepoint, int_codepoint) == FAILURE) { \ + RETURN_NULL(); \ + } \ + ret = u_##name(cp); \ + if (string_codepoint != NULL) { \ + char buffer[5]; \ + int buffer_len = 0; \ + U8_APPEND_UNSAFE(buffer, buffer_len, ret); \ + buffer[buffer_len] = 0; \ + RETURN_STRINGL(buffer, buffer_len); \ + } else { \ + RETURN_LONG(ret); \ + } \ +} +IC_CHAR_METHOD_CHAR(charMirror) +IC_CHAR_METHOD_CHAR(tolower) +IC_CHAR_METHOD_CHAR(toupper) +IC_CHAR_METHOD_CHAR(totitle) +IC_CHAR_METHOD_CHAR(getBidiPairedBracket) +#undef IC_CHAR_METHOD_CHAR +/* }}} */ + +int php_uchar_minit(INIT_FUNC_ARGS) { + register_class_IntlChar(); + + return SUCCESS; +} diff --git a/ext/intl/uchar/uchar_arginfo.h b/ext/intl/uchar/uchar_arginfo.h index f290fb2b958ec..9f69dc597c219 100644 --- a/ext/intl/uchar/uchar_arginfo.h +++ b/ext/intl/uchar/uchar_arginfo.h @@ -311,4001 +311,4001 @@ static zend_class_entry *register_class_IntlChar(void) zval const_UNICODE_VERSION_value; zend_string *const_UNICODE_VERSION_value_str = zend_string_init(U_UNICODE_VERSION, strlen(U_UNICODE_VERSION), 1); ZVAL_STR(&const_UNICODE_VERSION_value, const_UNICODE_VERSION_value_str); - zend_string *const_UNICODE_VERSION_name = zend_string_init_interned("UNICODE_VERSION", sizeof("UNICODE_VERSION") - 1, 1); + zend_string *const_UNICODE_VERSION_name = zend_string_init_interned("UNICODE_VERSION", sizeof("UNICODE_VERSION") - 1, true); zend_declare_typed_class_constant(class_entry, const_UNICODE_VERSION_name, &const_UNICODE_VERSION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(const_UNICODE_VERSION_name); + zend_string_release_ex(const_UNICODE_VERSION_name, true); zval const_CODEPOINT_MIN_value; ZVAL_LONG(&const_CODEPOINT_MIN_value, UCHAR_MIN_VALUE); - zend_string *const_CODEPOINT_MIN_name = zend_string_init_interned("CODEPOINT_MIN", sizeof("CODEPOINT_MIN") - 1, 1); + zend_string *const_CODEPOINT_MIN_name = zend_string_init_interned("CODEPOINT_MIN", sizeof("CODEPOINT_MIN") - 1, true); zend_declare_typed_class_constant(class_entry, const_CODEPOINT_MIN_name, &const_CODEPOINT_MIN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CODEPOINT_MIN_name); + zend_string_release_ex(const_CODEPOINT_MIN_name, true); zval const_CODEPOINT_MAX_value; ZVAL_LONG(&const_CODEPOINT_MAX_value, UCHAR_MAX_VALUE); - zend_string *const_CODEPOINT_MAX_name = zend_string_init_interned("CODEPOINT_MAX", sizeof("CODEPOINT_MAX") - 1, 1); + zend_string *const_CODEPOINT_MAX_name = zend_string_init_interned("CODEPOINT_MAX", sizeof("CODEPOINT_MAX") - 1, true); zend_declare_typed_class_constant(class_entry, const_CODEPOINT_MAX_name, &const_CODEPOINT_MAX_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CODEPOINT_MAX_name); + zend_string_release_ex(const_CODEPOINT_MAX_name, true); zval const_NO_NUMERIC_VALUE_value; ZVAL_DOUBLE(&const_NO_NUMERIC_VALUE_value, U_NO_NUMERIC_VALUE); - zend_string *const_NO_NUMERIC_VALUE_name = zend_string_init_interned("NO_NUMERIC_VALUE", sizeof("NO_NUMERIC_VALUE") - 1, 1); + zend_string *const_NO_NUMERIC_VALUE_name = zend_string_init_interned("NO_NUMERIC_VALUE", sizeof("NO_NUMERIC_VALUE") - 1, true); zend_declare_typed_class_constant(class_entry, const_NO_NUMERIC_VALUE_name, &const_NO_NUMERIC_VALUE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_DOUBLE)); - zend_string_release(const_NO_NUMERIC_VALUE_name); + zend_string_release_ex(const_NO_NUMERIC_VALUE_name, true); zval const_PROPERTY_ALPHABETIC_value; ZVAL_LONG(&const_PROPERTY_ALPHABETIC_value, UCHAR_ALPHABETIC); - zend_string *const_PROPERTY_ALPHABETIC_name = zend_string_init_interned("PROPERTY_ALPHABETIC", sizeof("PROPERTY_ALPHABETIC") - 1, 1); + zend_string *const_PROPERTY_ALPHABETIC_name = zend_string_init_interned("PROPERTY_ALPHABETIC", sizeof("PROPERTY_ALPHABETIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_ALPHABETIC_name, &const_PROPERTY_ALPHABETIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_ALPHABETIC_name); + zend_string_release_ex(const_PROPERTY_ALPHABETIC_name, true); zval const_PROPERTY_BINARY_START_value; ZVAL_LONG(&const_PROPERTY_BINARY_START_value, UCHAR_BINARY_START); - zend_string *const_PROPERTY_BINARY_START_name = zend_string_init_interned("PROPERTY_BINARY_START", sizeof("PROPERTY_BINARY_START") - 1, 1); + zend_string *const_PROPERTY_BINARY_START_name = zend_string_init_interned("PROPERTY_BINARY_START", sizeof("PROPERTY_BINARY_START") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_BINARY_START_name, &const_PROPERTY_BINARY_START_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_BINARY_START_name); + zend_string_release_ex(const_PROPERTY_BINARY_START_name, true); zval const_PROPERTY_ASCII_HEX_DIGIT_value; ZVAL_LONG(&const_PROPERTY_ASCII_HEX_DIGIT_value, UCHAR_ASCII_HEX_DIGIT); - zend_string *const_PROPERTY_ASCII_HEX_DIGIT_name = zend_string_init_interned("PROPERTY_ASCII_HEX_DIGIT", sizeof("PROPERTY_ASCII_HEX_DIGIT") - 1, 1); + zend_string *const_PROPERTY_ASCII_HEX_DIGIT_name = zend_string_init_interned("PROPERTY_ASCII_HEX_DIGIT", sizeof("PROPERTY_ASCII_HEX_DIGIT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_ASCII_HEX_DIGIT_name, &const_PROPERTY_ASCII_HEX_DIGIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_ASCII_HEX_DIGIT_name); + zend_string_release_ex(const_PROPERTY_ASCII_HEX_DIGIT_name, true); zval const_PROPERTY_BIDI_CONTROL_value; ZVAL_LONG(&const_PROPERTY_BIDI_CONTROL_value, UCHAR_BIDI_CONTROL); - zend_string *const_PROPERTY_BIDI_CONTROL_name = zend_string_init_interned("PROPERTY_BIDI_CONTROL", sizeof("PROPERTY_BIDI_CONTROL") - 1, 1); + zend_string *const_PROPERTY_BIDI_CONTROL_name = zend_string_init_interned("PROPERTY_BIDI_CONTROL", sizeof("PROPERTY_BIDI_CONTROL") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_BIDI_CONTROL_name, &const_PROPERTY_BIDI_CONTROL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_BIDI_CONTROL_name); + zend_string_release_ex(const_PROPERTY_BIDI_CONTROL_name, true); zval const_PROPERTY_BIDI_MIRRORED_value; ZVAL_LONG(&const_PROPERTY_BIDI_MIRRORED_value, UCHAR_BIDI_MIRRORED); - zend_string *const_PROPERTY_BIDI_MIRRORED_name = zend_string_init_interned("PROPERTY_BIDI_MIRRORED", sizeof("PROPERTY_BIDI_MIRRORED") - 1, 1); + zend_string *const_PROPERTY_BIDI_MIRRORED_name = zend_string_init_interned("PROPERTY_BIDI_MIRRORED", sizeof("PROPERTY_BIDI_MIRRORED") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_BIDI_MIRRORED_name, &const_PROPERTY_BIDI_MIRRORED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_BIDI_MIRRORED_name); + zend_string_release_ex(const_PROPERTY_BIDI_MIRRORED_name, true); zval const_PROPERTY_DASH_value; ZVAL_LONG(&const_PROPERTY_DASH_value, UCHAR_DASH); - zend_string *const_PROPERTY_DASH_name = zend_string_init_interned("PROPERTY_DASH", sizeof("PROPERTY_DASH") - 1, 1); + zend_string *const_PROPERTY_DASH_name = zend_string_init_interned("PROPERTY_DASH", sizeof("PROPERTY_DASH") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_DASH_name, &const_PROPERTY_DASH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_DASH_name); + zend_string_release_ex(const_PROPERTY_DASH_name, true); zval const_PROPERTY_DEFAULT_IGNORABLE_CODE_POINT_value; ZVAL_LONG(&const_PROPERTY_DEFAULT_IGNORABLE_CODE_POINT_value, UCHAR_DEFAULT_IGNORABLE_CODE_POINT); - zend_string *const_PROPERTY_DEFAULT_IGNORABLE_CODE_POINT_name = zend_string_init_interned("PROPERTY_DEFAULT_IGNORABLE_CODE_POINT", sizeof("PROPERTY_DEFAULT_IGNORABLE_CODE_POINT") - 1, 1); + zend_string *const_PROPERTY_DEFAULT_IGNORABLE_CODE_POINT_name = zend_string_init_interned("PROPERTY_DEFAULT_IGNORABLE_CODE_POINT", sizeof("PROPERTY_DEFAULT_IGNORABLE_CODE_POINT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_DEFAULT_IGNORABLE_CODE_POINT_name, &const_PROPERTY_DEFAULT_IGNORABLE_CODE_POINT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_DEFAULT_IGNORABLE_CODE_POINT_name); + zend_string_release_ex(const_PROPERTY_DEFAULT_IGNORABLE_CODE_POINT_name, true); zval const_PROPERTY_DEPRECATED_value; ZVAL_LONG(&const_PROPERTY_DEPRECATED_value, UCHAR_DEPRECATED); - zend_string *const_PROPERTY_DEPRECATED_name = zend_string_init_interned("PROPERTY_DEPRECATED", sizeof("PROPERTY_DEPRECATED") - 1, 1); + zend_string *const_PROPERTY_DEPRECATED_name = zend_string_init_interned("PROPERTY_DEPRECATED", sizeof("PROPERTY_DEPRECATED") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_DEPRECATED_name, &const_PROPERTY_DEPRECATED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_DEPRECATED_name); + zend_string_release_ex(const_PROPERTY_DEPRECATED_name, true); zval const_PROPERTY_DIACRITIC_value; ZVAL_LONG(&const_PROPERTY_DIACRITIC_value, UCHAR_DIACRITIC); - zend_string *const_PROPERTY_DIACRITIC_name = zend_string_init_interned("PROPERTY_DIACRITIC", sizeof("PROPERTY_DIACRITIC") - 1, 1); + zend_string *const_PROPERTY_DIACRITIC_name = zend_string_init_interned("PROPERTY_DIACRITIC", sizeof("PROPERTY_DIACRITIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_DIACRITIC_name, &const_PROPERTY_DIACRITIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_DIACRITIC_name); + zend_string_release_ex(const_PROPERTY_DIACRITIC_name, true); zval const_PROPERTY_EXTENDER_value; ZVAL_LONG(&const_PROPERTY_EXTENDER_value, UCHAR_EXTENDER); - zend_string *const_PROPERTY_EXTENDER_name = zend_string_init_interned("PROPERTY_EXTENDER", sizeof("PROPERTY_EXTENDER") - 1, 1); + zend_string *const_PROPERTY_EXTENDER_name = zend_string_init_interned("PROPERTY_EXTENDER", sizeof("PROPERTY_EXTENDER") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_EXTENDER_name, &const_PROPERTY_EXTENDER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_EXTENDER_name); + zend_string_release_ex(const_PROPERTY_EXTENDER_name, true); zval const_PROPERTY_FULL_COMPOSITION_EXCLUSION_value; ZVAL_LONG(&const_PROPERTY_FULL_COMPOSITION_EXCLUSION_value, UCHAR_FULL_COMPOSITION_EXCLUSION); - zend_string *const_PROPERTY_FULL_COMPOSITION_EXCLUSION_name = zend_string_init_interned("PROPERTY_FULL_COMPOSITION_EXCLUSION", sizeof("PROPERTY_FULL_COMPOSITION_EXCLUSION") - 1, 1); + zend_string *const_PROPERTY_FULL_COMPOSITION_EXCLUSION_name = zend_string_init_interned("PROPERTY_FULL_COMPOSITION_EXCLUSION", sizeof("PROPERTY_FULL_COMPOSITION_EXCLUSION") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_FULL_COMPOSITION_EXCLUSION_name, &const_PROPERTY_FULL_COMPOSITION_EXCLUSION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_FULL_COMPOSITION_EXCLUSION_name); + zend_string_release_ex(const_PROPERTY_FULL_COMPOSITION_EXCLUSION_name, true); zval const_PROPERTY_GRAPHEME_BASE_value; ZVAL_LONG(&const_PROPERTY_GRAPHEME_BASE_value, UCHAR_GRAPHEME_BASE); - zend_string *const_PROPERTY_GRAPHEME_BASE_name = zend_string_init_interned("PROPERTY_GRAPHEME_BASE", sizeof("PROPERTY_GRAPHEME_BASE") - 1, 1); + zend_string *const_PROPERTY_GRAPHEME_BASE_name = zend_string_init_interned("PROPERTY_GRAPHEME_BASE", sizeof("PROPERTY_GRAPHEME_BASE") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_GRAPHEME_BASE_name, &const_PROPERTY_GRAPHEME_BASE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_GRAPHEME_BASE_name); + zend_string_release_ex(const_PROPERTY_GRAPHEME_BASE_name, true); zval const_PROPERTY_GRAPHEME_EXTEND_value; ZVAL_LONG(&const_PROPERTY_GRAPHEME_EXTEND_value, UCHAR_GRAPHEME_EXTEND); - zend_string *const_PROPERTY_GRAPHEME_EXTEND_name = zend_string_init_interned("PROPERTY_GRAPHEME_EXTEND", sizeof("PROPERTY_GRAPHEME_EXTEND") - 1, 1); + zend_string *const_PROPERTY_GRAPHEME_EXTEND_name = zend_string_init_interned("PROPERTY_GRAPHEME_EXTEND", sizeof("PROPERTY_GRAPHEME_EXTEND") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_GRAPHEME_EXTEND_name, &const_PROPERTY_GRAPHEME_EXTEND_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_GRAPHEME_EXTEND_name); + zend_string_release_ex(const_PROPERTY_GRAPHEME_EXTEND_name, true); zval const_PROPERTY_GRAPHEME_LINK_value; ZVAL_LONG(&const_PROPERTY_GRAPHEME_LINK_value, UCHAR_GRAPHEME_LINK); - zend_string *const_PROPERTY_GRAPHEME_LINK_name = zend_string_init_interned("PROPERTY_GRAPHEME_LINK", sizeof("PROPERTY_GRAPHEME_LINK") - 1, 1); + zend_string *const_PROPERTY_GRAPHEME_LINK_name = zend_string_init_interned("PROPERTY_GRAPHEME_LINK", sizeof("PROPERTY_GRAPHEME_LINK") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_GRAPHEME_LINK_name, &const_PROPERTY_GRAPHEME_LINK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_GRAPHEME_LINK_name); + zend_string_release_ex(const_PROPERTY_GRAPHEME_LINK_name, true); zval const_PROPERTY_HEX_DIGIT_value; ZVAL_LONG(&const_PROPERTY_HEX_DIGIT_value, UCHAR_HEX_DIGIT); - zend_string *const_PROPERTY_HEX_DIGIT_name = zend_string_init_interned("PROPERTY_HEX_DIGIT", sizeof("PROPERTY_HEX_DIGIT") - 1, 1); + zend_string *const_PROPERTY_HEX_DIGIT_name = zend_string_init_interned("PROPERTY_HEX_DIGIT", sizeof("PROPERTY_HEX_DIGIT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_HEX_DIGIT_name, &const_PROPERTY_HEX_DIGIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_HEX_DIGIT_name); + zend_string_release_ex(const_PROPERTY_HEX_DIGIT_name, true); zval const_PROPERTY_HYPHEN_value; ZVAL_LONG(&const_PROPERTY_HYPHEN_value, UCHAR_HYPHEN); - zend_string *const_PROPERTY_HYPHEN_name = zend_string_init_interned("PROPERTY_HYPHEN", sizeof("PROPERTY_HYPHEN") - 1, 1); + zend_string *const_PROPERTY_HYPHEN_name = zend_string_init_interned("PROPERTY_HYPHEN", sizeof("PROPERTY_HYPHEN") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_HYPHEN_name, &const_PROPERTY_HYPHEN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_HYPHEN_name); + zend_string_release_ex(const_PROPERTY_HYPHEN_name, true); zval const_PROPERTY_ID_CONTINUE_value; ZVAL_LONG(&const_PROPERTY_ID_CONTINUE_value, UCHAR_ID_CONTINUE); - zend_string *const_PROPERTY_ID_CONTINUE_name = zend_string_init_interned("PROPERTY_ID_CONTINUE", sizeof("PROPERTY_ID_CONTINUE") - 1, 1); + zend_string *const_PROPERTY_ID_CONTINUE_name = zend_string_init_interned("PROPERTY_ID_CONTINUE", sizeof("PROPERTY_ID_CONTINUE") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_ID_CONTINUE_name, &const_PROPERTY_ID_CONTINUE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_ID_CONTINUE_name); + zend_string_release_ex(const_PROPERTY_ID_CONTINUE_name, true); zval const_PROPERTY_ID_START_value; ZVAL_LONG(&const_PROPERTY_ID_START_value, UCHAR_ID_START); - zend_string *const_PROPERTY_ID_START_name = zend_string_init_interned("PROPERTY_ID_START", sizeof("PROPERTY_ID_START") - 1, 1); + zend_string *const_PROPERTY_ID_START_name = zend_string_init_interned("PROPERTY_ID_START", sizeof("PROPERTY_ID_START") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_ID_START_name, &const_PROPERTY_ID_START_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_ID_START_name); + zend_string_release_ex(const_PROPERTY_ID_START_name, true); zval const_PROPERTY_IDEOGRAPHIC_value; ZVAL_LONG(&const_PROPERTY_IDEOGRAPHIC_value, UCHAR_IDEOGRAPHIC); - zend_string *const_PROPERTY_IDEOGRAPHIC_name = zend_string_init_interned("PROPERTY_IDEOGRAPHIC", sizeof("PROPERTY_IDEOGRAPHIC") - 1, 1); + zend_string *const_PROPERTY_IDEOGRAPHIC_name = zend_string_init_interned("PROPERTY_IDEOGRAPHIC", sizeof("PROPERTY_IDEOGRAPHIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_IDEOGRAPHIC_name, &const_PROPERTY_IDEOGRAPHIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_IDEOGRAPHIC_name); + zend_string_release_ex(const_PROPERTY_IDEOGRAPHIC_name, true); zval const_PROPERTY_IDS_BINARY_OPERATOR_value; ZVAL_LONG(&const_PROPERTY_IDS_BINARY_OPERATOR_value, UCHAR_IDS_BINARY_OPERATOR); - zend_string *const_PROPERTY_IDS_BINARY_OPERATOR_name = zend_string_init_interned("PROPERTY_IDS_BINARY_OPERATOR", sizeof("PROPERTY_IDS_BINARY_OPERATOR") - 1, 1); + zend_string *const_PROPERTY_IDS_BINARY_OPERATOR_name = zend_string_init_interned("PROPERTY_IDS_BINARY_OPERATOR", sizeof("PROPERTY_IDS_BINARY_OPERATOR") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_IDS_BINARY_OPERATOR_name, &const_PROPERTY_IDS_BINARY_OPERATOR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_IDS_BINARY_OPERATOR_name); + zend_string_release_ex(const_PROPERTY_IDS_BINARY_OPERATOR_name, true); zval const_PROPERTY_IDS_TRINARY_OPERATOR_value; ZVAL_LONG(&const_PROPERTY_IDS_TRINARY_OPERATOR_value, UCHAR_IDS_TRINARY_OPERATOR); - zend_string *const_PROPERTY_IDS_TRINARY_OPERATOR_name = zend_string_init_interned("PROPERTY_IDS_TRINARY_OPERATOR", sizeof("PROPERTY_IDS_TRINARY_OPERATOR") - 1, 1); + zend_string *const_PROPERTY_IDS_TRINARY_OPERATOR_name = zend_string_init_interned("PROPERTY_IDS_TRINARY_OPERATOR", sizeof("PROPERTY_IDS_TRINARY_OPERATOR") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_IDS_TRINARY_OPERATOR_name, &const_PROPERTY_IDS_TRINARY_OPERATOR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_IDS_TRINARY_OPERATOR_name); + zend_string_release_ex(const_PROPERTY_IDS_TRINARY_OPERATOR_name, true); #if U_ICU_VERSION_MAJOR_NUM >= 74 zval const_PROPERTY_IDS_UNARY_OPERATOR_value; ZVAL_LONG(&const_PROPERTY_IDS_UNARY_OPERATOR_value, UCHAR_IDS_UNARY_OPERATOR); - zend_string *const_PROPERTY_IDS_UNARY_OPERATOR_name = zend_string_init_interned("PROPERTY_IDS_UNARY_OPERATOR", sizeof("PROPERTY_IDS_UNARY_OPERATOR") - 1, 1); + zend_string *const_PROPERTY_IDS_UNARY_OPERATOR_name = zend_string_init_interned("PROPERTY_IDS_UNARY_OPERATOR", sizeof("PROPERTY_IDS_UNARY_OPERATOR") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_IDS_UNARY_OPERATOR_name, &const_PROPERTY_IDS_UNARY_OPERATOR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_IDS_UNARY_OPERATOR_name); + zend_string_release_ex(const_PROPERTY_IDS_UNARY_OPERATOR_name, true); zval const_PROPERTY_ID_COMPAT_MATH_START_value; ZVAL_LONG(&const_PROPERTY_ID_COMPAT_MATH_START_value, UCHAR_ID_COMPAT_MATH_START); - zend_string *const_PROPERTY_ID_COMPAT_MATH_START_name = zend_string_init_interned("PROPERTY_ID_COMPAT_MATH_START", sizeof("PROPERTY_ID_COMPAT_MATH_START") - 1, 1); + zend_string *const_PROPERTY_ID_COMPAT_MATH_START_name = zend_string_init_interned("PROPERTY_ID_COMPAT_MATH_START", sizeof("PROPERTY_ID_COMPAT_MATH_START") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_ID_COMPAT_MATH_START_name, &const_PROPERTY_ID_COMPAT_MATH_START_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_ID_COMPAT_MATH_START_name); + zend_string_release_ex(const_PROPERTY_ID_COMPAT_MATH_START_name, true); zval const_PROPERTY_ID_COMPAT_MATH_CONTINUE_value; ZVAL_LONG(&const_PROPERTY_ID_COMPAT_MATH_CONTINUE_value, UCHAR_ID_COMPAT_MATH_CONTINUE); - zend_string *const_PROPERTY_ID_COMPAT_MATH_CONTINUE_name = zend_string_init_interned("PROPERTY_ID_COMPAT_MATH_CONTINUE", sizeof("PROPERTY_ID_COMPAT_MATH_CONTINUE") - 1, 1); + zend_string *const_PROPERTY_ID_COMPAT_MATH_CONTINUE_name = zend_string_init_interned("PROPERTY_ID_COMPAT_MATH_CONTINUE", sizeof("PROPERTY_ID_COMPAT_MATH_CONTINUE") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_ID_COMPAT_MATH_CONTINUE_name, &const_PROPERTY_ID_COMPAT_MATH_CONTINUE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_ID_COMPAT_MATH_CONTINUE_name); + zend_string_release_ex(const_PROPERTY_ID_COMPAT_MATH_CONTINUE_name, true); #endif zval const_PROPERTY_JOIN_CONTROL_value; ZVAL_LONG(&const_PROPERTY_JOIN_CONTROL_value, UCHAR_JOIN_CONTROL); - zend_string *const_PROPERTY_JOIN_CONTROL_name = zend_string_init_interned("PROPERTY_JOIN_CONTROL", sizeof("PROPERTY_JOIN_CONTROL") - 1, 1); + zend_string *const_PROPERTY_JOIN_CONTROL_name = zend_string_init_interned("PROPERTY_JOIN_CONTROL", sizeof("PROPERTY_JOIN_CONTROL") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_JOIN_CONTROL_name, &const_PROPERTY_JOIN_CONTROL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_JOIN_CONTROL_name); + zend_string_release_ex(const_PROPERTY_JOIN_CONTROL_name, true); zval const_PROPERTY_LOGICAL_ORDER_EXCEPTION_value; ZVAL_LONG(&const_PROPERTY_LOGICAL_ORDER_EXCEPTION_value, UCHAR_LOGICAL_ORDER_EXCEPTION); - zend_string *const_PROPERTY_LOGICAL_ORDER_EXCEPTION_name = zend_string_init_interned("PROPERTY_LOGICAL_ORDER_EXCEPTION", sizeof("PROPERTY_LOGICAL_ORDER_EXCEPTION") - 1, 1); + zend_string *const_PROPERTY_LOGICAL_ORDER_EXCEPTION_name = zend_string_init_interned("PROPERTY_LOGICAL_ORDER_EXCEPTION", sizeof("PROPERTY_LOGICAL_ORDER_EXCEPTION") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_LOGICAL_ORDER_EXCEPTION_name, &const_PROPERTY_LOGICAL_ORDER_EXCEPTION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_LOGICAL_ORDER_EXCEPTION_name); + zend_string_release_ex(const_PROPERTY_LOGICAL_ORDER_EXCEPTION_name, true); zval const_PROPERTY_LOWERCASE_value; ZVAL_LONG(&const_PROPERTY_LOWERCASE_value, UCHAR_LOWERCASE); - zend_string *const_PROPERTY_LOWERCASE_name = zend_string_init_interned("PROPERTY_LOWERCASE", sizeof("PROPERTY_LOWERCASE") - 1, 1); + zend_string *const_PROPERTY_LOWERCASE_name = zend_string_init_interned("PROPERTY_LOWERCASE", sizeof("PROPERTY_LOWERCASE") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_LOWERCASE_name, &const_PROPERTY_LOWERCASE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_LOWERCASE_name); + zend_string_release_ex(const_PROPERTY_LOWERCASE_name, true); zval const_PROPERTY_MATH_value; ZVAL_LONG(&const_PROPERTY_MATH_value, UCHAR_MATH); - zend_string *const_PROPERTY_MATH_name = zend_string_init_interned("PROPERTY_MATH", sizeof("PROPERTY_MATH") - 1, 1); + zend_string *const_PROPERTY_MATH_name = zend_string_init_interned("PROPERTY_MATH", sizeof("PROPERTY_MATH") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_MATH_name, &const_PROPERTY_MATH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_MATH_name); + zend_string_release_ex(const_PROPERTY_MATH_name, true); zval const_PROPERTY_NONCHARACTER_CODE_POINT_value; ZVAL_LONG(&const_PROPERTY_NONCHARACTER_CODE_POINT_value, UCHAR_NONCHARACTER_CODE_POINT); - zend_string *const_PROPERTY_NONCHARACTER_CODE_POINT_name = zend_string_init_interned("PROPERTY_NONCHARACTER_CODE_POINT", sizeof("PROPERTY_NONCHARACTER_CODE_POINT") - 1, 1); + zend_string *const_PROPERTY_NONCHARACTER_CODE_POINT_name = zend_string_init_interned("PROPERTY_NONCHARACTER_CODE_POINT", sizeof("PROPERTY_NONCHARACTER_CODE_POINT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_NONCHARACTER_CODE_POINT_name, &const_PROPERTY_NONCHARACTER_CODE_POINT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_NONCHARACTER_CODE_POINT_name); + zend_string_release_ex(const_PROPERTY_NONCHARACTER_CODE_POINT_name, true); zval const_PROPERTY_QUOTATION_MARK_value; ZVAL_LONG(&const_PROPERTY_QUOTATION_MARK_value, UCHAR_QUOTATION_MARK); - zend_string *const_PROPERTY_QUOTATION_MARK_name = zend_string_init_interned("PROPERTY_QUOTATION_MARK", sizeof("PROPERTY_QUOTATION_MARK") - 1, 1); + zend_string *const_PROPERTY_QUOTATION_MARK_name = zend_string_init_interned("PROPERTY_QUOTATION_MARK", sizeof("PROPERTY_QUOTATION_MARK") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_QUOTATION_MARK_name, &const_PROPERTY_QUOTATION_MARK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_QUOTATION_MARK_name); + zend_string_release_ex(const_PROPERTY_QUOTATION_MARK_name, true); zval const_PROPERTY_RADICAL_value; ZVAL_LONG(&const_PROPERTY_RADICAL_value, UCHAR_RADICAL); - zend_string *const_PROPERTY_RADICAL_name = zend_string_init_interned("PROPERTY_RADICAL", sizeof("PROPERTY_RADICAL") - 1, 1); + zend_string *const_PROPERTY_RADICAL_name = zend_string_init_interned("PROPERTY_RADICAL", sizeof("PROPERTY_RADICAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_RADICAL_name, &const_PROPERTY_RADICAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_RADICAL_name); + zend_string_release_ex(const_PROPERTY_RADICAL_name, true); zval const_PROPERTY_SOFT_DOTTED_value; ZVAL_LONG(&const_PROPERTY_SOFT_DOTTED_value, UCHAR_SOFT_DOTTED); - zend_string *const_PROPERTY_SOFT_DOTTED_name = zend_string_init_interned("PROPERTY_SOFT_DOTTED", sizeof("PROPERTY_SOFT_DOTTED") - 1, 1); + zend_string *const_PROPERTY_SOFT_DOTTED_name = zend_string_init_interned("PROPERTY_SOFT_DOTTED", sizeof("PROPERTY_SOFT_DOTTED") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_SOFT_DOTTED_name, &const_PROPERTY_SOFT_DOTTED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_SOFT_DOTTED_name); + zend_string_release_ex(const_PROPERTY_SOFT_DOTTED_name, true); zval const_PROPERTY_TERMINAL_PUNCTUATION_value; ZVAL_LONG(&const_PROPERTY_TERMINAL_PUNCTUATION_value, UCHAR_TERMINAL_PUNCTUATION); - zend_string *const_PROPERTY_TERMINAL_PUNCTUATION_name = zend_string_init_interned("PROPERTY_TERMINAL_PUNCTUATION", sizeof("PROPERTY_TERMINAL_PUNCTUATION") - 1, 1); + zend_string *const_PROPERTY_TERMINAL_PUNCTUATION_name = zend_string_init_interned("PROPERTY_TERMINAL_PUNCTUATION", sizeof("PROPERTY_TERMINAL_PUNCTUATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_TERMINAL_PUNCTUATION_name, &const_PROPERTY_TERMINAL_PUNCTUATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_TERMINAL_PUNCTUATION_name); + zend_string_release_ex(const_PROPERTY_TERMINAL_PUNCTUATION_name, true); zval const_PROPERTY_UNIFIED_IDEOGRAPH_value; ZVAL_LONG(&const_PROPERTY_UNIFIED_IDEOGRAPH_value, UCHAR_UNIFIED_IDEOGRAPH); - zend_string *const_PROPERTY_UNIFIED_IDEOGRAPH_name = zend_string_init_interned("PROPERTY_UNIFIED_IDEOGRAPH", sizeof("PROPERTY_UNIFIED_IDEOGRAPH") - 1, 1); + zend_string *const_PROPERTY_UNIFIED_IDEOGRAPH_name = zend_string_init_interned("PROPERTY_UNIFIED_IDEOGRAPH", sizeof("PROPERTY_UNIFIED_IDEOGRAPH") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_UNIFIED_IDEOGRAPH_name, &const_PROPERTY_UNIFIED_IDEOGRAPH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_UNIFIED_IDEOGRAPH_name); + zend_string_release_ex(const_PROPERTY_UNIFIED_IDEOGRAPH_name, true); zval const_PROPERTY_UPPERCASE_value; ZVAL_LONG(&const_PROPERTY_UPPERCASE_value, UCHAR_UPPERCASE); - zend_string *const_PROPERTY_UPPERCASE_name = zend_string_init_interned("PROPERTY_UPPERCASE", sizeof("PROPERTY_UPPERCASE") - 1, 1); + zend_string *const_PROPERTY_UPPERCASE_name = zend_string_init_interned("PROPERTY_UPPERCASE", sizeof("PROPERTY_UPPERCASE") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_UPPERCASE_name, &const_PROPERTY_UPPERCASE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_UPPERCASE_name); + zend_string_release_ex(const_PROPERTY_UPPERCASE_name, true); zval const_PROPERTY_WHITE_SPACE_value; ZVAL_LONG(&const_PROPERTY_WHITE_SPACE_value, UCHAR_WHITE_SPACE); - zend_string *const_PROPERTY_WHITE_SPACE_name = zend_string_init_interned("PROPERTY_WHITE_SPACE", sizeof("PROPERTY_WHITE_SPACE") - 1, 1); + zend_string *const_PROPERTY_WHITE_SPACE_name = zend_string_init_interned("PROPERTY_WHITE_SPACE", sizeof("PROPERTY_WHITE_SPACE") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_WHITE_SPACE_name, &const_PROPERTY_WHITE_SPACE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_WHITE_SPACE_name); + zend_string_release_ex(const_PROPERTY_WHITE_SPACE_name, true); zval const_PROPERTY_XID_CONTINUE_value; ZVAL_LONG(&const_PROPERTY_XID_CONTINUE_value, UCHAR_XID_CONTINUE); - zend_string *const_PROPERTY_XID_CONTINUE_name = zend_string_init_interned("PROPERTY_XID_CONTINUE", sizeof("PROPERTY_XID_CONTINUE") - 1, 1); + zend_string *const_PROPERTY_XID_CONTINUE_name = zend_string_init_interned("PROPERTY_XID_CONTINUE", sizeof("PROPERTY_XID_CONTINUE") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_XID_CONTINUE_name, &const_PROPERTY_XID_CONTINUE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_XID_CONTINUE_name); + zend_string_release_ex(const_PROPERTY_XID_CONTINUE_name, true); zval const_PROPERTY_XID_START_value; ZVAL_LONG(&const_PROPERTY_XID_START_value, UCHAR_XID_START); - zend_string *const_PROPERTY_XID_START_name = zend_string_init_interned("PROPERTY_XID_START", sizeof("PROPERTY_XID_START") - 1, 1); + zend_string *const_PROPERTY_XID_START_name = zend_string_init_interned("PROPERTY_XID_START", sizeof("PROPERTY_XID_START") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_XID_START_name, &const_PROPERTY_XID_START_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_XID_START_name); + zend_string_release_ex(const_PROPERTY_XID_START_name, true); zval const_PROPERTY_CASE_SENSITIVE_value; ZVAL_LONG(&const_PROPERTY_CASE_SENSITIVE_value, UCHAR_CASE_SENSITIVE); - zend_string *const_PROPERTY_CASE_SENSITIVE_name = zend_string_init_interned("PROPERTY_CASE_SENSITIVE", sizeof("PROPERTY_CASE_SENSITIVE") - 1, 1); + zend_string *const_PROPERTY_CASE_SENSITIVE_name = zend_string_init_interned("PROPERTY_CASE_SENSITIVE", sizeof("PROPERTY_CASE_SENSITIVE") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_CASE_SENSITIVE_name, &const_PROPERTY_CASE_SENSITIVE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_CASE_SENSITIVE_name); + zend_string_release_ex(const_PROPERTY_CASE_SENSITIVE_name, true); zval const_PROPERTY_S_TERM_value; ZVAL_LONG(&const_PROPERTY_S_TERM_value, UCHAR_S_TERM); - zend_string *const_PROPERTY_S_TERM_name = zend_string_init_interned("PROPERTY_S_TERM", sizeof("PROPERTY_S_TERM") - 1, 1); + zend_string *const_PROPERTY_S_TERM_name = zend_string_init_interned("PROPERTY_S_TERM", sizeof("PROPERTY_S_TERM") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_S_TERM_name, &const_PROPERTY_S_TERM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_S_TERM_name); + zend_string_release_ex(const_PROPERTY_S_TERM_name, true); zval const_PROPERTY_VARIATION_SELECTOR_value; ZVAL_LONG(&const_PROPERTY_VARIATION_SELECTOR_value, UCHAR_VARIATION_SELECTOR); - zend_string *const_PROPERTY_VARIATION_SELECTOR_name = zend_string_init_interned("PROPERTY_VARIATION_SELECTOR", sizeof("PROPERTY_VARIATION_SELECTOR") - 1, 1); + zend_string *const_PROPERTY_VARIATION_SELECTOR_name = zend_string_init_interned("PROPERTY_VARIATION_SELECTOR", sizeof("PROPERTY_VARIATION_SELECTOR") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_VARIATION_SELECTOR_name, &const_PROPERTY_VARIATION_SELECTOR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_VARIATION_SELECTOR_name); + zend_string_release_ex(const_PROPERTY_VARIATION_SELECTOR_name, true); zval const_PROPERTY_NFD_INERT_value; ZVAL_LONG(&const_PROPERTY_NFD_INERT_value, UCHAR_NFD_INERT); - zend_string *const_PROPERTY_NFD_INERT_name = zend_string_init_interned("PROPERTY_NFD_INERT", sizeof("PROPERTY_NFD_INERT") - 1, 1); + zend_string *const_PROPERTY_NFD_INERT_name = zend_string_init_interned("PROPERTY_NFD_INERT", sizeof("PROPERTY_NFD_INERT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_NFD_INERT_name, &const_PROPERTY_NFD_INERT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_NFD_INERT_name); + zend_string_release_ex(const_PROPERTY_NFD_INERT_name, true); zval const_PROPERTY_NFKD_INERT_value; ZVAL_LONG(&const_PROPERTY_NFKD_INERT_value, UCHAR_NFKD_INERT); - zend_string *const_PROPERTY_NFKD_INERT_name = zend_string_init_interned("PROPERTY_NFKD_INERT", sizeof("PROPERTY_NFKD_INERT") - 1, 1); + zend_string *const_PROPERTY_NFKD_INERT_name = zend_string_init_interned("PROPERTY_NFKD_INERT", sizeof("PROPERTY_NFKD_INERT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_NFKD_INERT_name, &const_PROPERTY_NFKD_INERT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_NFKD_INERT_name); + zend_string_release_ex(const_PROPERTY_NFKD_INERT_name, true); zval const_PROPERTY_NFC_INERT_value; ZVAL_LONG(&const_PROPERTY_NFC_INERT_value, UCHAR_NFC_INERT); - zend_string *const_PROPERTY_NFC_INERT_name = zend_string_init_interned("PROPERTY_NFC_INERT", sizeof("PROPERTY_NFC_INERT") - 1, 1); + zend_string *const_PROPERTY_NFC_INERT_name = zend_string_init_interned("PROPERTY_NFC_INERT", sizeof("PROPERTY_NFC_INERT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_NFC_INERT_name, &const_PROPERTY_NFC_INERT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_NFC_INERT_name); + zend_string_release_ex(const_PROPERTY_NFC_INERT_name, true); zval const_PROPERTY_NFKC_INERT_value; ZVAL_LONG(&const_PROPERTY_NFKC_INERT_value, UCHAR_NFKC_INERT); - zend_string *const_PROPERTY_NFKC_INERT_name = zend_string_init_interned("PROPERTY_NFKC_INERT", sizeof("PROPERTY_NFKC_INERT") - 1, 1); + zend_string *const_PROPERTY_NFKC_INERT_name = zend_string_init_interned("PROPERTY_NFKC_INERT", sizeof("PROPERTY_NFKC_INERT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_NFKC_INERT_name, &const_PROPERTY_NFKC_INERT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_NFKC_INERT_name); + zend_string_release_ex(const_PROPERTY_NFKC_INERT_name, true); zval const_PROPERTY_SEGMENT_STARTER_value; ZVAL_LONG(&const_PROPERTY_SEGMENT_STARTER_value, UCHAR_SEGMENT_STARTER); - zend_string *const_PROPERTY_SEGMENT_STARTER_name = zend_string_init_interned("PROPERTY_SEGMENT_STARTER", sizeof("PROPERTY_SEGMENT_STARTER") - 1, 1); + zend_string *const_PROPERTY_SEGMENT_STARTER_name = zend_string_init_interned("PROPERTY_SEGMENT_STARTER", sizeof("PROPERTY_SEGMENT_STARTER") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_SEGMENT_STARTER_name, &const_PROPERTY_SEGMENT_STARTER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_SEGMENT_STARTER_name); + zend_string_release_ex(const_PROPERTY_SEGMENT_STARTER_name, true); zval const_PROPERTY_PATTERN_SYNTAX_value; ZVAL_LONG(&const_PROPERTY_PATTERN_SYNTAX_value, UCHAR_PATTERN_SYNTAX); - zend_string *const_PROPERTY_PATTERN_SYNTAX_name = zend_string_init_interned("PROPERTY_PATTERN_SYNTAX", sizeof("PROPERTY_PATTERN_SYNTAX") - 1, 1); + zend_string *const_PROPERTY_PATTERN_SYNTAX_name = zend_string_init_interned("PROPERTY_PATTERN_SYNTAX", sizeof("PROPERTY_PATTERN_SYNTAX") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_PATTERN_SYNTAX_name, &const_PROPERTY_PATTERN_SYNTAX_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_PATTERN_SYNTAX_name); + zend_string_release_ex(const_PROPERTY_PATTERN_SYNTAX_name, true); zval const_PROPERTY_PATTERN_WHITE_SPACE_value; ZVAL_LONG(&const_PROPERTY_PATTERN_WHITE_SPACE_value, UCHAR_PATTERN_WHITE_SPACE); - zend_string *const_PROPERTY_PATTERN_WHITE_SPACE_name = zend_string_init_interned("PROPERTY_PATTERN_WHITE_SPACE", sizeof("PROPERTY_PATTERN_WHITE_SPACE") - 1, 1); + zend_string *const_PROPERTY_PATTERN_WHITE_SPACE_name = zend_string_init_interned("PROPERTY_PATTERN_WHITE_SPACE", sizeof("PROPERTY_PATTERN_WHITE_SPACE") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_PATTERN_WHITE_SPACE_name, &const_PROPERTY_PATTERN_WHITE_SPACE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_PATTERN_WHITE_SPACE_name); + zend_string_release_ex(const_PROPERTY_PATTERN_WHITE_SPACE_name, true); zval const_PROPERTY_POSIX_ALNUM_value; ZVAL_LONG(&const_PROPERTY_POSIX_ALNUM_value, UCHAR_POSIX_ALNUM); - zend_string *const_PROPERTY_POSIX_ALNUM_name = zend_string_init_interned("PROPERTY_POSIX_ALNUM", sizeof("PROPERTY_POSIX_ALNUM") - 1, 1); + zend_string *const_PROPERTY_POSIX_ALNUM_name = zend_string_init_interned("PROPERTY_POSIX_ALNUM", sizeof("PROPERTY_POSIX_ALNUM") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_POSIX_ALNUM_name, &const_PROPERTY_POSIX_ALNUM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_POSIX_ALNUM_name); + zend_string_release_ex(const_PROPERTY_POSIX_ALNUM_name, true); zval const_PROPERTY_POSIX_BLANK_value; ZVAL_LONG(&const_PROPERTY_POSIX_BLANK_value, UCHAR_POSIX_BLANK); - zend_string *const_PROPERTY_POSIX_BLANK_name = zend_string_init_interned("PROPERTY_POSIX_BLANK", sizeof("PROPERTY_POSIX_BLANK") - 1, 1); + zend_string *const_PROPERTY_POSIX_BLANK_name = zend_string_init_interned("PROPERTY_POSIX_BLANK", sizeof("PROPERTY_POSIX_BLANK") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_POSIX_BLANK_name, &const_PROPERTY_POSIX_BLANK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_POSIX_BLANK_name); + zend_string_release_ex(const_PROPERTY_POSIX_BLANK_name, true); zval const_PROPERTY_POSIX_GRAPH_value; ZVAL_LONG(&const_PROPERTY_POSIX_GRAPH_value, UCHAR_POSIX_GRAPH); - zend_string *const_PROPERTY_POSIX_GRAPH_name = zend_string_init_interned("PROPERTY_POSIX_GRAPH", sizeof("PROPERTY_POSIX_GRAPH") - 1, 1); + zend_string *const_PROPERTY_POSIX_GRAPH_name = zend_string_init_interned("PROPERTY_POSIX_GRAPH", sizeof("PROPERTY_POSIX_GRAPH") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_POSIX_GRAPH_name, &const_PROPERTY_POSIX_GRAPH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_POSIX_GRAPH_name); + zend_string_release_ex(const_PROPERTY_POSIX_GRAPH_name, true); zval const_PROPERTY_POSIX_PRINT_value; ZVAL_LONG(&const_PROPERTY_POSIX_PRINT_value, UCHAR_POSIX_PRINT); - zend_string *const_PROPERTY_POSIX_PRINT_name = zend_string_init_interned("PROPERTY_POSIX_PRINT", sizeof("PROPERTY_POSIX_PRINT") - 1, 1); + zend_string *const_PROPERTY_POSIX_PRINT_name = zend_string_init_interned("PROPERTY_POSIX_PRINT", sizeof("PROPERTY_POSIX_PRINT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_POSIX_PRINT_name, &const_PROPERTY_POSIX_PRINT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_POSIX_PRINT_name); + zend_string_release_ex(const_PROPERTY_POSIX_PRINT_name, true); zval const_PROPERTY_POSIX_XDIGIT_value; ZVAL_LONG(&const_PROPERTY_POSIX_XDIGIT_value, UCHAR_POSIX_XDIGIT); - zend_string *const_PROPERTY_POSIX_XDIGIT_name = zend_string_init_interned("PROPERTY_POSIX_XDIGIT", sizeof("PROPERTY_POSIX_XDIGIT") - 1, 1); + zend_string *const_PROPERTY_POSIX_XDIGIT_name = zend_string_init_interned("PROPERTY_POSIX_XDIGIT", sizeof("PROPERTY_POSIX_XDIGIT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_POSIX_XDIGIT_name, &const_PROPERTY_POSIX_XDIGIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_POSIX_XDIGIT_name); + zend_string_release_ex(const_PROPERTY_POSIX_XDIGIT_name, true); zval const_PROPERTY_CASED_value; ZVAL_LONG(&const_PROPERTY_CASED_value, UCHAR_CASED); - zend_string *const_PROPERTY_CASED_name = zend_string_init_interned("PROPERTY_CASED", sizeof("PROPERTY_CASED") - 1, 1); + zend_string *const_PROPERTY_CASED_name = zend_string_init_interned("PROPERTY_CASED", sizeof("PROPERTY_CASED") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_CASED_name, &const_PROPERTY_CASED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_CASED_name); + zend_string_release_ex(const_PROPERTY_CASED_name, true); zval const_PROPERTY_CASE_IGNORABLE_value; ZVAL_LONG(&const_PROPERTY_CASE_IGNORABLE_value, UCHAR_CASE_IGNORABLE); - zend_string *const_PROPERTY_CASE_IGNORABLE_name = zend_string_init_interned("PROPERTY_CASE_IGNORABLE", sizeof("PROPERTY_CASE_IGNORABLE") - 1, 1); + zend_string *const_PROPERTY_CASE_IGNORABLE_name = zend_string_init_interned("PROPERTY_CASE_IGNORABLE", sizeof("PROPERTY_CASE_IGNORABLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_CASE_IGNORABLE_name, &const_PROPERTY_CASE_IGNORABLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_CASE_IGNORABLE_name); + zend_string_release_ex(const_PROPERTY_CASE_IGNORABLE_name, true); zval const_PROPERTY_CHANGES_WHEN_LOWERCASED_value; ZVAL_LONG(&const_PROPERTY_CHANGES_WHEN_LOWERCASED_value, UCHAR_CHANGES_WHEN_LOWERCASED); - zend_string *const_PROPERTY_CHANGES_WHEN_LOWERCASED_name = zend_string_init_interned("PROPERTY_CHANGES_WHEN_LOWERCASED", sizeof("PROPERTY_CHANGES_WHEN_LOWERCASED") - 1, 1); + zend_string *const_PROPERTY_CHANGES_WHEN_LOWERCASED_name = zend_string_init_interned("PROPERTY_CHANGES_WHEN_LOWERCASED", sizeof("PROPERTY_CHANGES_WHEN_LOWERCASED") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_CHANGES_WHEN_LOWERCASED_name, &const_PROPERTY_CHANGES_WHEN_LOWERCASED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_CHANGES_WHEN_LOWERCASED_name); + zend_string_release_ex(const_PROPERTY_CHANGES_WHEN_LOWERCASED_name, true); zval const_PROPERTY_CHANGES_WHEN_UPPERCASED_value; ZVAL_LONG(&const_PROPERTY_CHANGES_WHEN_UPPERCASED_value, UCHAR_CHANGES_WHEN_UPPERCASED); - zend_string *const_PROPERTY_CHANGES_WHEN_UPPERCASED_name = zend_string_init_interned("PROPERTY_CHANGES_WHEN_UPPERCASED", sizeof("PROPERTY_CHANGES_WHEN_UPPERCASED") - 1, 1); + zend_string *const_PROPERTY_CHANGES_WHEN_UPPERCASED_name = zend_string_init_interned("PROPERTY_CHANGES_WHEN_UPPERCASED", sizeof("PROPERTY_CHANGES_WHEN_UPPERCASED") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_CHANGES_WHEN_UPPERCASED_name, &const_PROPERTY_CHANGES_WHEN_UPPERCASED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_CHANGES_WHEN_UPPERCASED_name); + zend_string_release_ex(const_PROPERTY_CHANGES_WHEN_UPPERCASED_name, true); zval const_PROPERTY_CHANGES_WHEN_TITLECASED_value; ZVAL_LONG(&const_PROPERTY_CHANGES_WHEN_TITLECASED_value, UCHAR_CHANGES_WHEN_TITLECASED); - zend_string *const_PROPERTY_CHANGES_WHEN_TITLECASED_name = zend_string_init_interned("PROPERTY_CHANGES_WHEN_TITLECASED", sizeof("PROPERTY_CHANGES_WHEN_TITLECASED") - 1, 1); + zend_string *const_PROPERTY_CHANGES_WHEN_TITLECASED_name = zend_string_init_interned("PROPERTY_CHANGES_WHEN_TITLECASED", sizeof("PROPERTY_CHANGES_WHEN_TITLECASED") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_CHANGES_WHEN_TITLECASED_name, &const_PROPERTY_CHANGES_WHEN_TITLECASED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_CHANGES_WHEN_TITLECASED_name); + zend_string_release_ex(const_PROPERTY_CHANGES_WHEN_TITLECASED_name, true); zval const_PROPERTY_CHANGES_WHEN_CASEFOLDED_value; ZVAL_LONG(&const_PROPERTY_CHANGES_WHEN_CASEFOLDED_value, UCHAR_CHANGES_WHEN_CASEFOLDED); - zend_string *const_PROPERTY_CHANGES_WHEN_CASEFOLDED_name = zend_string_init_interned("PROPERTY_CHANGES_WHEN_CASEFOLDED", sizeof("PROPERTY_CHANGES_WHEN_CASEFOLDED") - 1, 1); + zend_string *const_PROPERTY_CHANGES_WHEN_CASEFOLDED_name = zend_string_init_interned("PROPERTY_CHANGES_WHEN_CASEFOLDED", sizeof("PROPERTY_CHANGES_WHEN_CASEFOLDED") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_CHANGES_WHEN_CASEFOLDED_name, &const_PROPERTY_CHANGES_WHEN_CASEFOLDED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_CHANGES_WHEN_CASEFOLDED_name); + zend_string_release_ex(const_PROPERTY_CHANGES_WHEN_CASEFOLDED_name, true); zval const_PROPERTY_CHANGES_WHEN_CASEMAPPED_value; ZVAL_LONG(&const_PROPERTY_CHANGES_WHEN_CASEMAPPED_value, UCHAR_CHANGES_WHEN_CASEMAPPED); - zend_string *const_PROPERTY_CHANGES_WHEN_CASEMAPPED_name = zend_string_init_interned("PROPERTY_CHANGES_WHEN_CASEMAPPED", sizeof("PROPERTY_CHANGES_WHEN_CASEMAPPED") - 1, 1); + zend_string *const_PROPERTY_CHANGES_WHEN_CASEMAPPED_name = zend_string_init_interned("PROPERTY_CHANGES_WHEN_CASEMAPPED", sizeof("PROPERTY_CHANGES_WHEN_CASEMAPPED") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_CHANGES_WHEN_CASEMAPPED_name, &const_PROPERTY_CHANGES_WHEN_CASEMAPPED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_CHANGES_WHEN_CASEMAPPED_name); + zend_string_release_ex(const_PROPERTY_CHANGES_WHEN_CASEMAPPED_name, true); zval const_PROPERTY_CHANGES_WHEN_NFKC_CASEFOLDED_value; ZVAL_LONG(&const_PROPERTY_CHANGES_WHEN_NFKC_CASEFOLDED_value, UCHAR_CHANGES_WHEN_NFKC_CASEFOLDED); - zend_string *const_PROPERTY_CHANGES_WHEN_NFKC_CASEFOLDED_name = zend_string_init_interned("PROPERTY_CHANGES_WHEN_NFKC_CASEFOLDED", sizeof("PROPERTY_CHANGES_WHEN_NFKC_CASEFOLDED") - 1, 1); + zend_string *const_PROPERTY_CHANGES_WHEN_NFKC_CASEFOLDED_name = zend_string_init_interned("PROPERTY_CHANGES_WHEN_NFKC_CASEFOLDED", sizeof("PROPERTY_CHANGES_WHEN_NFKC_CASEFOLDED") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_CHANGES_WHEN_NFKC_CASEFOLDED_name, &const_PROPERTY_CHANGES_WHEN_NFKC_CASEFOLDED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_CHANGES_WHEN_NFKC_CASEFOLDED_name); + zend_string_release_ex(const_PROPERTY_CHANGES_WHEN_NFKC_CASEFOLDED_name, true); zval const_PROPERTY_BINARY_LIMIT_value; ZVAL_LONG(&const_PROPERTY_BINARY_LIMIT_value, UCHAR_BINARY_LIMIT); - zend_string *const_PROPERTY_BINARY_LIMIT_name = zend_string_init_interned("PROPERTY_BINARY_LIMIT", sizeof("PROPERTY_BINARY_LIMIT") - 1, 1); + zend_string *const_PROPERTY_BINARY_LIMIT_name = zend_string_init_interned("PROPERTY_BINARY_LIMIT", sizeof("PROPERTY_BINARY_LIMIT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_BINARY_LIMIT_name, &const_PROPERTY_BINARY_LIMIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_BINARY_LIMIT_name); + zend_string_release_ex(const_PROPERTY_BINARY_LIMIT_name, true); zval const_PROPERTY_BIDI_CLASS_value; ZVAL_LONG(&const_PROPERTY_BIDI_CLASS_value, UCHAR_BIDI_CLASS); - zend_string *const_PROPERTY_BIDI_CLASS_name = zend_string_init_interned("PROPERTY_BIDI_CLASS", sizeof("PROPERTY_BIDI_CLASS") - 1, 1); + zend_string *const_PROPERTY_BIDI_CLASS_name = zend_string_init_interned("PROPERTY_BIDI_CLASS", sizeof("PROPERTY_BIDI_CLASS") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_BIDI_CLASS_name, &const_PROPERTY_BIDI_CLASS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_BIDI_CLASS_name); + zend_string_release_ex(const_PROPERTY_BIDI_CLASS_name, true); zval const_PROPERTY_INT_START_value; ZVAL_LONG(&const_PROPERTY_INT_START_value, UCHAR_INT_START); - zend_string *const_PROPERTY_INT_START_name = zend_string_init_interned("PROPERTY_INT_START", sizeof("PROPERTY_INT_START") - 1, 1); + zend_string *const_PROPERTY_INT_START_name = zend_string_init_interned("PROPERTY_INT_START", sizeof("PROPERTY_INT_START") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_INT_START_name, &const_PROPERTY_INT_START_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_INT_START_name); + zend_string_release_ex(const_PROPERTY_INT_START_name, true); zval const_PROPERTY_BLOCK_value; ZVAL_LONG(&const_PROPERTY_BLOCK_value, UCHAR_BLOCK); - zend_string *const_PROPERTY_BLOCK_name = zend_string_init_interned("PROPERTY_BLOCK", sizeof("PROPERTY_BLOCK") - 1, 1); + zend_string *const_PROPERTY_BLOCK_name = zend_string_init_interned("PROPERTY_BLOCK", sizeof("PROPERTY_BLOCK") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_BLOCK_name, &const_PROPERTY_BLOCK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_BLOCK_name); + zend_string_release_ex(const_PROPERTY_BLOCK_name, true); zval const_PROPERTY_CANONICAL_COMBINING_CLASS_value; ZVAL_LONG(&const_PROPERTY_CANONICAL_COMBINING_CLASS_value, UCHAR_CANONICAL_COMBINING_CLASS); - zend_string *const_PROPERTY_CANONICAL_COMBINING_CLASS_name = zend_string_init_interned("PROPERTY_CANONICAL_COMBINING_CLASS", sizeof("PROPERTY_CANONICAL_COMBINING_CLASS") - 1, 1); + zend_string *const_PROPERTY_CANONICAL_COMBINING_CLASS_name = zend_string_init_interned("PROPERTY_CANONICAL_COMBINING_CLASS", sizeof("PROPERTY_CANONICAL_COMBINING_CLASS") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_CANONICAL_COMBINING_CLASS_name, &const_PROPERTY_CANONICAL_COMBINING_CLASS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_CANONICAL_COMBINING_CLASS_name); + zend_string_release_ex(const_PROPERTY_CANONICAL_COMBINING_CLASS_name, true); zval const_PROPERTY_DECOMPOSITION_TYPE_value; ZVAL_LONG(&const_PROPERTY_DECOMPOSITION_TYPE_value, UCHAR_DECOMPOSITION_TYPE); - zend_string *const_PROPERTY_DECOMPOSITION_TYPE_name = zend_string_init_interned("PROPERTY_DECOMPOSITION_TYPE", sizeof("PROPERTY_DECOMPOSITION_TYPE") - 1, 1); + zend_string *const_PROPERTY_DECOMPOSITION_TYPE_name = zend_string_init_interned("PROPERTY_DECOMPOSITION_TYPE", sizeof("PROPERTY_DECOMPOSITION_TYPE") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_DECOMPOSITION_TYPE_name, &const_PROPERTY_DECOMPOSITION_TYPE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_DECOMPOSITION_TYPE_name); + zend_string_release_ex(const_PROPERTY_DECOMPOSITION_TYPE_name, true); zval const_PROPERTY_EAST_ASIAN_WIDTH_value; ZVAL_LONG(&const_PROPERTY_EAST_ASIAN_WIDTH_value, UCHAR_EAST_ASIAN_WIDTH); - zend_string *const_PROPERTY_EAST_ASIAN_WIDTH_name = zend_string_init_interned("PROPERTY_EAST_ASIAN_WIDTH", sizeof("PROPERTY_EAST_ASIAN_WIDTH") - 1, 1); + zend_string *const_PROPERTY_EAST_ASIAN_WIDTH_name = zend_string_init_interned("PROPERTY_EAST_ASIAN_WIDTH", sizeof("PROPERTY_EAST_ASIAN_WIDTH") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_EAST_ASIAN_WIDTH_name, &const_PROPERTY_EAST_ASIAN_WIDTH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_EAST_ASIAN_WIDTH_name); + zend_string_release_ex(const_PROPERTY_EAST_ASIAN_WIDTH_name, true); zval const_PROPERTY_GENERAL_CATEGORY_value; ZVAL_LONG(&const_PROPERTY_GENERAL_CATEGORY_value, UCHAR_GENERAL_CATEGORY); - zend_string *const_PROPERTY_GENERAL_CATEGORY_name = zend_string_init_interned("PROPERTY_GENERAL_CATEGORY", sizeof("PROPERTY_GENERAL_CATEGORY") - 1, 1); + zend_string *const_PROPERTY_GENERAL_CATEGORY_name = zend_string_init_interned("PROPERTY_GENERAL_CATEGORY", sizeof("PROPERTY_GENERAL_CATEGORY") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_GENERAL_CATEGORY_name, &const_PROPERTY_GENERAL_CATEGORY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_GENERAL_CATEGORY_name); + zend_string_release_ex(const_PROPERTY_GENERAL_CATEGORY_name, true); zval const_PROPERTY_JOINING_GROUP_value; ZVAL_LONG(&const_PROPERTY_JOINING_GROUP_value, UCHAR_JOINING_GROUP); - zend_string *const_PROPERTY_JOINING_GROUP_name = zend_string_init_interned("PROPERTY_JOINING_GROUP", sizeof("PROPERTY_JOINING_GROUP") - 1, 1); + zend_string *const_PROPERTY_JOINING_GROUP_name = zend_string_init_interned("PROPERTY_JOINING_GROUP", sizeof("PROPERTY_JOINING_GROUP") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_JOINING_GROUP_name, &const_PROPERTY_JOINING_GROUP_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_JOINING_GROUP_name); + zend_string_release_ex(const_PROPERTY_JOINING_GROUP_name, true); zval const_PROPERTY_JOINING_TYPE_value; ZVAL_LONG(&const_PROPERTY_JOINING_TYPE_value, UCHAR_JOINING_TYPE); - zend_string *const_PROPERTY_JOINING_TYPE_name = zend_string_init_interned("PROPERTY_JOINING_TYPE", sizeof("PROPERTY_JOINING_TYPE") - 1, 1); + zend_string *const_PROPERTY_JOINING_TYPE_name = zend_string_init_interned("PROPERTY_JOINING_TYPE", sizeof("PROPERTY_JOINING_TYPE") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_JOINING_TYPE_name, &const_PROPERTY_JOINING_TYPE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_JOINING_TYPE_name); + zend_string_release_ex(const_PROPERTY_JOINING_TYPE_name, true); zval const_PROPERTY_LINE_BREAK_value; ZVAL_LONG(&const_PROPERTY_LINE_BREAK_value, UCHAR_LINE_BREAK); - zend_string *const_PROPERTY_LINE_BREAK_name = zend_string_init_interned("PROPERTY_LINE_BREAK", sizeof("PROPERTY_LINE_BREAK") - 1, 1); + zend_string *const_PROPERTY_LINE_BREAK_name = zend_string_init_interned("PROPERTY_LINE_BREAK", sizeof("PROPERTY_LINE_BREAK") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_LINE_BREAK_name, &const_PROPERTY_LINE_BREAK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_LINE_BREAK_name); + zend_string_release_ex(const_PROPERTY_LINE_BREAK_name, true); zval const_PROPERTY_NUMERIC_TYPE_value; ZVAL_LONG(&const_PROPERTY_NUMERIC_TYPE_value, UCHAR_NUMERIC_TYPE); - zend_string *const_PROPERTY_NUMERIC_TYPE_name = zend_string_init_interned("PROPERTY_NUMERIC_TYPE", sizeof("PROPERTY_NUMERIC_TYPE") - 1, 1); + zend_string *const_PROPERTY_NUMERIC_TYPE_name = zend_string_init_interned("PROPERTY_NUMERIC_TYPE", sizeof("PROPERTY_NUMERIC_TYPE") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_NUMERIC_TYPE_name, &const_PROPERTY_NUMERIC_TYPE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_NUMERIC_TYPE_name); + zend_string_release_ex(const_PROPERTY_NUMERIC_TYPE_name, true); zval const_PROPERTY_SCRIPT_value; ZVAL_LONG(&const_PROPERTY_SCRIPT_value, UCHAR_SCRIPT); - zend_string *const_PROPERTY_SCRIPT_name = zend_string_init_interned("PROPERTY_SCRIPT", sizeof("PROPERTY_SCRIPT") - 1, 1); + zend_string *const_PROPERTY_SCRIPT_name = zend_string_init_interned("PROPERTY_SCRIPT", sizeof("PROPERTY_SCRIPT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_SCRIPT_name, &const_PROPERTY_SCRIPT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_SCRIPT_name); + zend_string_release_ex(const_PROPERTY_SCRIPT_name, true); zval const_PROPERTY_HANGUL_SYLLABLE_TYPE_value; ZVAL_LONG(&const_PROPERTY_HANGUL_SYLLABLE_TYPE_value, UCHAR_HANGUL_SYLLABLE_TYPE); - zend_string *const_PROPERTY_HANGUL_SYLLABLE_TYPE_name = zend_string_init_interned("PROPERTY_HANGUL_SYLLABLE_TYPE", sizeof("PROPERTY_HANGUL_SYLLABLE_TYPE") - 1, 1); + zend_string *const_PROPERTY_HANGUL_SYLLABLE_TYPE_name = zend_string_init_interned("PROPERTY_HANGUL_SYLLABLE_TYPE", sizeof("PROPERTY_HANGUL_SYLLABLE_TYPE") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_HANGUL_SYLLABLE_TYPE_name, &const_PROPERTY_HANGUL_SYLLABLE_TYPE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_HANGUL_SYLLABLE_TYPE_name); + zend_string_release_ex(const_PROPERTY_HANGUL_SYLLABLE_TYPE_name, true); zval const_PROPERTY_NFD_QUICK_CHECK_value; ZVAL_LONG(&const_PROPERTY_NFD_QUICK_CHECK_value, UCHAR_NFD_QUICK_CHECK); - zend_string *const_PROPERTY_NFD_QUICK_CHECK_name = zend_string_init_interned("PROPERTY_NFD_QUICK_CHECK", sizeof("PROPERTY_NFD_QUICK_CHECK") - 1, 1); + zend_string *const_PROPERTY_NFD_QUICK_CHECK_name = zend_string_init_interned("PROPERTY_NFD_QUICK_CHECK", sizeof("PROPERTY_NFD_QUICK_CHECK") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_NFD_QUICK_CHECK_name, &const_PROPERTY_NFD_QUICK_CHECK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_NFD_QUICK_CHECK_name); + zend_string_release_ex(const_PROPERTY_NFD_QUICK_CHECK_name, true); zval const_PROPERTY_NFKD_QUICK_CHECK_value; ZVAL_LONG(&const_PROPERTY_NFKD_QUICK_CHECK_value, UCHAR_NFKD_QUICK_CHECK); - zend_string *const_PROPERTY_NFKD_QUICK_CHECK_name = zend_string_init_interned("PROPERTY_NFKD_QUICK_CHECK", sizeof("PROPERTY_NFKD_QUICK_CHECK") - 1, 1); + zend_string *const_PROPERTY_NFKD_QUICK_CHECK_name = zend_string_init_interned("PROPERTY_NFKD_QUICK_CHECK", sizeof("PROPERTY_NFKD_QUICK_CHECK") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_NFKD_QUICK_CHECK_name, &const_PROPERTY_NFKD_QUICK_CHECK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_NFKD_QUICK_CHECK_name); + zend_string_release_ex(const_PROPERTY_NFKD_QUICK_CHECK_name, true); zval const_PROPERTY_NFC_QUICK_CHECK_value; ZVAL_LONG(&const_PROPERTY_NFC_QUICK_CHECK_value, UCHAR_NFC_QUICK_CHECK); - zend_string *const_PROPERTY_NFC_QUICK_CHECK_name = zend_string_init_interned("PROPERTY_NFC_QUICK_CHECK", sizeof("PROPERTY_NFC_QUICK_CHECK") - 1, 1); + zend_string *const_PROPERTY_NFC_QUICK_CHECK_name = zend_string_init_interned("PROPERTY_NFC_QUICK_CHECK", sizeof("PROPERTY_NFC_QUICK_CHECK") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_NFC_QUICK_CHECK_name, &const_PROPERTY_NFC_QUICK_CHECK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_NFC_QUICK_CHECK_name); + zend_string_release_ex(const_PROPERTY_NFC_QUICK_CHECK_name, true); zval const_PROPERTY_NFKC_QUICK_CHECK_value; ZVAL_LONG(&const_PROPERTY_NFKC_QUICK_CHECK_value, UCHAR_NFKC_QUICK_CHECK); - zend_string *const_PROPERTY_NFKC_QUICK_CHECK_name = zend_string_init_interned("PROPERTY_NFKC_QUICK_CHECK", sizeof("PROPERTY_NFKC_QUICK_CHECK") - 1, 1); + zend_string *const_PROPERTY_NFKC_QUICK_CHECK_name = zend_string_init_interned("PROPERTY_NFKC_QUICK_CHECK", sizeof("PROPERTY_NFKC_QUICK_CHECK") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_NFKC_QUICK_CHECK_name, &const_PROPERTY_NFKC_QUICK_CHECK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_NFKC_QUICK_CHECK_name); + zend_string_release_ex(const_PROPERTY_NFKC_QUICK_CHECK_name, true); zval const_PROPERTY_LEAD_CANONICAL_COMBINING_CLASS_value; ZVAL_LONG(&const_PROPERTY_LEAD_CANONICAL_COMBINING_CLASS_value, UCHAR_LEAD_CANONICAL_COMBINING_CLASS); - zend_string *const_PROPERTY_LEAD_CANONICAL_COMBINING_CLASS_name = zend_string_init_interned("PROPERTY_LEAD_CANONICAL_COMBINING_CLASS", sizeof("PROPERTY_LEAD_CANONICAL_COMBINING_CLASS") - 1, 1); + zend_string *const_PROPERTY_LEAD_CANONICAL_COMBINING_CLASS_name = zend_string_init_interned("PROPERTY_LEAD_CANONICAL_COMBINING_CLASS", sizeof("PROPERTY_LEAD_CANONICAL_COMBINING_CLASS") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_LEAD_CANONICAL_COMBINING_CLASS_name, &const_PROPERTY_LEAD_CANONICAL_COMBINING_CLASS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_LEAD_CANONICAL_COMBINING_CLASS_name); + zend_string_release_ex(const_PROPERTY_LEAD_CANONICAL_COMBINING_CLASS_name, true); zval const_PROPERTY_TRAIL_CANONICAL_COMBINING_CLASS_value; ZVAL_LONG(&const_PROPERTY_TRAIL_CANONICAL_COMBINING_CLASS_value, UCHAR_TRAIL_CANONICAL_COMBINING_CLASS); - zend_string *const_PROPERTY_TRAIL_CANONICAL_COMBINING_CLASS_name = zend_string_init_interned("PROPERTY_TRAIL_CANONICAL_COMBINING_CLASS", sizeof("PROPERTY_TRAIL_CANONICAL_COMBINING_CLASS") - 1, 1); + zend_string *const_PROPERTY_TRAIL_CANONICAL_COMBINING_CLASS_name = zend_string_init_interned("PROPERTY_TRAIL_CANONICAL_COMBINING_CLASS", sizeof("PROPERTY_TRAIL_CANONICAL_COMBINING_CLASS") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_TRAIL_CANONICAL_COMBINING_CLASS_name, &const_PROPERTY_TRAIL_CANONICAL_COMBINING_CLASS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_TRAIL_CANONICAL_COMBINING_CLASS_name); + zend_string_release_ex(const_PROPERTY_TRAIL_CANONICAL_COMBINING_CLASS_name, true); zval const_PROPERTY_GRAPHEME_CLUSTER_BREAK_value; ZVAL_LONG(&const_PROPERTY_GRAPHEME_CLUSTER_BREAK_value, UCHAR_GRAPHEME_CLUSTER_BREAK); - zend_string *const_PROPERTY_GRAPHEME_CLUSTER_BREAK_name = zend_string_init_interned("PROPERTY_GRAPHEME_CLUSTER_BREAK", sizeof("PROPERTY_GRAPHEME_CLUSTER_BREAK") - 1, 1); + zend_string *const_PROPERTY_GRAPHEME_CLUSTER_BREAK_name = zend_string_init_interned("PROPERTY_GRAPHEME_CLUSTER_BREAK", sizeof("PROPERTY_GRAPHEME_CLUSTER_BREAK") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_GRAPHEME_CLUSTER_BREAK_name, &const_PROPERTY_GRAPHEME_CLUSTER_BREAK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_GRAPHEME_CLUSTER_BREAK_name); + zend_string_release_ex(const_PROPERTY_GRAPHEME_CLUSTER_BREAK_name, true); zval const_PROPERTY_SENTENCE_BREAK_value; ZVAL_LONG(&const_PROPERTY_SENTENCE_BREAK_value, UCHAR_SENTENCE_BREAK); - zend_string *const_PROPERTY_SENTENCE_BREAK_name = zend_string_init_interned("PROPERTY_SENTENCE_BREAK", sizeof("PROPERTY_SENTENCE_BREAK") - 1, 1); + zend_string *const_PROPERTY_SENTENCE_BREAK_name = zend_string_init_interned("PROPERTY_SENTENCE_BREAK", sizeof("PROPERTY_SENTENCE_BREAK") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_SENTENCE_BREAK_name, &const_PROPERTY_SENTENCE_BREAK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_SENTENCE_BREAK_name); + zend_string_release_ex(const_PROPERTY_SENTENCE_BREAK_name, true); zval const_PROPERTY_WORD_BREAK_value; ZVAL_LONG(&const_PROPERTY_WORD_BREAK_value, UCHAR_WORD_BREAK); - zend_string *const_PROPERTY_WORD_BREAK_name = zend_string_init_interned("PROPERTY_WORD_BREAK", sizeof("PROPERTY_WORD_BREAK") - 1, 1); + zend_string *const_PROPERTY_WORD_BREAK_name = zend_string_init_interned("PROPERTY_WORD_BREAK", sizeof("PROPERTY_WORD_BREAK") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_WORD_BREAK_name, &const_PROPERTY_WORD_BREAK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_WORD_BREAK_name); + zend_string_release_ex(const_PROPERTY_WORD_BREAK_name, true); zval const_PROPERTY_BIDI_PAIRED_BRACKET_TYPE_value; ZVAL_LONG(&const_PROPERTY_BIDI_PAIRED_BRACKET_TYPE_value, UCHAR_BIDI_PAIRED_BRACKET_TYPE); - zend_string *const_PROPERTY_BIDI_PAIRED_BRACKET_TYPE_name = zend_string_init_interned("PROPERTY_BIDI_PAIRED_BRACKET_TYPE", sizeof("PROPERTY_BIDI_PAIRED_BRACKET_TYPE") - 1, 1); + zend_string *const_PROPERTY_BIDI_PAIRED_BRACKET_TYPE_name = zend_string_init_interned("PROPERTY_BIDI_PAIRED_BRACKET_TYPE", sizeof("PROPERTY_BIDI_PAIRED_BRACKET_TYPE") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_BIDI_PAIRED_BRACKET_TYPE_name, &const_PROPERTY_BIDI_PAIRED_BRACKET_TYPE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_BIDI_PAIRED_BRACKET_TYPE_name); + zend_string_release_ex(const_PROPERTY_BIDI_PAIRED_BRACKET_TYPE_name, true); zval const_PROPERTY_INT_LIMIT_value; ZVAL_LONG(&const_PROPERTY_INT_LIMIT_value, UCHAR_INT_LIMIT); - zend_string *const_PROPERTY_INT_LIMIT_name = zend_string_init_interned("PROPERTY_INT_LIMIT", sizeof("PROPERTY_INT_LIMIT") - 1, 1); + zend_string *const_PROPERTY_INT_LIMIT_name = zend_string_init_interned("PROPERTY_INT_LIMIT", sizeof("PROPERTY_INT_LIMIT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_INT_LIMIT_name, &const_PROPERTY_INT_LIMIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_INT_LIMIT_name); + zend_string_release_ex(const_PROPERTY_INT_LIMIT_name, true); zval const_PROPERTY_GENERAL_CATEGORY_MASK_value; ZVAL_LONG(&const_PROPERTY_GENERAL_CATEGORY_MASK_value, UCHAR_GENERAL_CATEGORY_MASK); - zend_string *const_PROPERTY_GENERAL_CATEGORY_MASK_name = zend_string_init_interned("PROPERTY_GENERAL_CATEGORY_MASK", sizeof("PROPERTY_GENERAL_CATEGORY_MASK") - 1, 1); + zend_string *const_PROPERTY_GENERAL_CATEGORY_MASK_name = zend_string_init_interned("PROPERTY_GENERAL_CATEGORY_MASK", sizeof("PROPERTY_GENERAL_CATEGORY_MASK") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_GENERAL_CATEGORY_MASK_name, &const_PROPERTY_GENERAL_CATEGORY_MASK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_GENERAL_CATEGORY_MASK_name); + zend_string_release_ex(const_PROPERTY_GENERAL_CATEGORY_MASK_name, true); zval const_PROPERTY_MASK_START_value; ZVAL_LONG(&const_PROPERTY_MASK_START_value, UCHAR_MASK_START); - zend_string *const_PROPERTY_MASK_START_name = zend_string_init_interned("PROPERTY_MASK_START", sizeof("PROPERTY_MASK_START") - 1, 1); + zend_string *const_PROPERTY_MASK_START_name = zend_string_init_interned("PROPERTY_MASK_START", sizeof("PROPERTY_MASK_START") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_MASK_START_name, &const_PROPERTY_MASK_START_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_MASK_START_name); + zend_string_release_ex(const_PROPERTY_MASK_START_name, true); zval const_PROPERTY_MASK_LIMIT_value; ZVAL_LONG(&const_PROPERTY_MASK_LIMIT_value, UCHAR_MASK_LIMIT); - zend_string *const_PROPERTY_MASK_LIMIT_name = zend_string_init_interned("PROPERTY_MASK_LIMIT", sizeof("PROPERTY_MASK_LIMIT") - 1, 1); + zend_string *const_PROPERTY_MASK_LIMIT_name = zend_string_init_interned("PROPERTY_MASK_LIMIT", sizeof("PROPERTY_MASK_LIMIT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_MASK_LIMIT_name, &const_PROPERTY_MASK_LIMIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_MASK_LIMIT_name); + zend_string_release_ex(const_PROPERTY_MASK_LIMIT_name, true); zval const_PROPERTY_NUMERIC_VALUE_value; ZVAL_LONG(&const_PROPERTY_NUMERIC_VALUE_value, UCHAR_NUMERIC_VALUE); - zend_string *const_PROPERTY_NUMERIC_VALUE_name = zend_string_init_interned("PROPERTY_NUMERIC_VALUE", sizeof("PROPERTY_NUMERIC_VALUE") - 1, 1); + zend_string *const_PROPERTY_NUMERIC_VALUE_name = zend_string_init_interned("PROPERTY_NUMERIC_VALUE", sizeof("PROPERTY_NUMERIC_VALUE") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_NUMERIC_VALUE_name, &const_PROPERTY_NUMERIC_VALUE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_NUMERIC_VALUE_name); + zend_string_release_ex(const_PROPERTY_NUMERIC_VALUE_name, true); zval const_PROPERTY_DOUBLE_START_value; ZVAL_LONG(&const_PROPERTY_DOUBLE_START_value, UCHAR_DOUBLE_START); - zend_string *const_PROPERTY_DOUBLE_START_name = zend_string_init_interned("PROPERTY_DOUBLE_START", sizeof("PROPERTY_DOUBLE_START") - 1, 1); + zend_string *const_PROPERTY_DOUBLE_START_name = zend_string_init_interned("PROPERTY_DOUBLE_START", sizeof("PROPERTY_DOUBLE_START") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_DOUBLE_START_name, &const_PROPERTY_DOUBLE_START_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_DOUBLE_START_name); + zend_string_release_ex(const_PROPERTY_DOUBLE_START_name, true); zval const_PROPERTY_DOUBLE_LIMIT_value; ZVAL_LONG(&const_PROPERTY_DOUBLE_LIMIT_value, UCHAR_DOUBLE_LIMIT); - zend_string *const_PROPERTY_DOUBLE_LIMIT_name = zend_string_init_interned("PROPERTY_DOUBLE_LIMIT", sizeof("PROPERTY_DOUBLE_LIMIT") - 1, 1); + zend_string *const_PROPERTY_DOUBLE_LIMIT_name = zend_string_init_interned("PROPERTY_DOUBLE_LIMIT", sizeof("PROPERTY_DOUBLE_LIMIT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_DOUBLE_LIMIT_name, &const_PROPERTY_DOUBLE_LIMIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_DOUBLE_LIMIT_name); + zend_string_release_ex(const_PROPERTY_DOUBLE_LIMIT_name, true); zval const_PROPERTY_AGE_value; ZVAL_LONG(&const_PROPERTY_AGE_value, UCHAR_AGE); - zend_string *const_PROPERTY_AGE_name = zend_string_init_interned("PROPERTY_AGE", sizeof("PROPERTY_AGE") - 1, 1); + zend_string *const_PROPERTY_AGE_name = zend_string_init_interned("PROPERTY_AGE", sizeof("PROPERTY_AGE") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_AGE_name, &const_PROPERTY_AGE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_AGE_name); + zend_string_release_ex(const_PROPERTY_AGE_name, true); zval const_PROPERTY_STRING_START_value; ZVAL_LONG(&const_PROPERTY_STRING_START_value, UCHAR_STRING_START); - zend_string *const_PROPERTY_STRING_START_name = zend_string_init_interned("PROPERTY_STRING_START", sizeof("PROPERTY_STRING_START") - 1, 1); + zend_string *const_PROPERTY_STRING_START_name = zend_string_init_interned("PROPERTY_STRING_START", sizeof("PROPERTY_STRING_START") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_STRING_START_name, &const_PROPERTY_STRING_START_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_STRING_START_name); + zend_string_release_ex(const_PROPERTY_STRING_START_name, true); zval const_PROPERTY_BIDI_MIRRORING_GLYPH_value; ZVAL_LONG(&const_PROPERTY_BIDI_MIRRORING_GLYPH_value, UCHAR_BIDI_MIRRORING_GLYPH); - zend_string *const_PROPERTY_BIDI_MIRRORING_GLYPH_name = zend_string_init_interned("PROPERTY_BIDI_MIRRORING_GLYPH", sizeof("PROPERTY_BIDI_MIRRORING_GLYPH") - 1, 1); + zend_string *const_PROPERTY_BIDI_MIRRORING_GLYPH_name = zend_string_init_interned("PROPERTY_BIDI_MIRRORING_GLYPH", sizeof("PROPERTY_BIDI_MIRRORING_GLYPH") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_BIDI_MIRRORING_GLYPH_name, &const_PROPERTY_BIDI_MIRRORING_GLYPH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_BIDI_MIRRORING_GLYPH_name); + zend_string_release_ex(const_PROPERTY_BIDI_MIRRORING_GLYPH_name, true); zval const_PROPERTY_CASE_FOLDING_value; ZVAL_LONG(&const_PROPERTY_CASE_FOLDING_value, UCHAR_CASE_FOLDING); - zend_string *const_PROPERTY_CASE_FOLDING_name = zend_string_init_interned("PROPERTY_CASE_FOLDING", sizeof("PROPERTY_CASE_FOLDING") - 1, 1); + zend_string *const_PROPERTY_CASE_FOLDING_name = zend_string_init_interned("PROPERTY_CASE_FOLDING", sizeof("PROPERTY_CASE_FOLDING") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_CASE_FOLDING_name, &const_PROPERTY_CASE_FOLDING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_CASE_FOLDING_name); + zend_string_release_ex(const_PROPERTY_CASE_FOLDING_name, true); zval const_PROPERTY_ISO_COMMENT_value; ZVAL_LONG(&const_PROPERTY_ISO_COMMENT_value, UCHAR_ISO_COMMENT); - zend_string *const_PROPERTY_ISO_COMMENT_name = zend_string_init_interned("PROPERTY_ISO_COMMENT", sizeof("PROPERTY_ISO_COMMENT") - 1, 1); + zend_string *const_PROPERTY_ISO_COMMENT_name = zend_string_init_interned("PROPERTY_ISO_COMMENT", sizeof("PROPERTY_ISO_COMMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_ISO_COMMENT_name, &const_PROPERTY_ISO_COMMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_ISO_COMMENT_name); + zend_string_release_ex(const_PROPERTY_ISO_COMMENT_name, true); zval const_PROPERTY_LOWERCASE_MAPPING_value; ZVAL_LONG(&const_PROPERTY_LOWERCASE_MAPPING_value, UCHAR_LOWERCASE_MAPPING); - zend_string *const_PROPERTY_LOWERCASE_MAPPING_name = zend_string_init_interned("PROPERTY_LOWERCASE_MAPPING", sizeof("PROPERTY_LOWERCASE_MAPPING") - 1, 1); + zend_string *const_PROPERTY_LOWERCASE_MAPPING_name = zend_string_init_interned("PROPERTY_LOWERCASE_MAPPING", sizeof("PROPERTY_LOWERCASE_MAPPING") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_LOWERCASE_MAPPING_name, &const_PROPERTY_LOWERCASE_MAPPING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_LOWERCASE_MAPPING_name); + zend_string_release_ex(const_PROPERTY_LOWERCASE_MAPPING_name, true); zval const_PROPERTY_NAME_value; ZVAL_LONG(&const_PROPERTY_NAME_value, UCHAR_NAME); - zend_string *const_PROPERTY_NAME_name = zend_string_init_interned("PROPERTY_NAME", sizeof("PROPERTY_NAME") - 1, 1); + zend_string *const_PROPERTY_NAME_name = zend_string_init_interned("PROPERTY_NAME", sizeof("PROPERTY_NAME") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_NAME_name, &const_PROPERTY_NAME_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_NAME_name); + zend_string_release_ex(const_PROPERTY_NAME_name, true); zval const_PROPERTY_SIMPLE_CASE_FOLDING_value; ZVAL_LONG(&const_PROPERTY_SIMPLE_CASE_FOLDING_value, UCHAR_SIMPLE_CASE_FOLDING); - zend_string *const_PROPERTY_SIMPLE_CASE_FOLDING_name = zend_string_init_interned("PROPERTY_SIMPLE_CASE_FOLDING", sizeof("PROPERTY_SIMPLE_CASE_FOLDING") - 1, 1); + zend_string *const_PROPERTY_SIMPLE_CASE_FOLDING_name = zend_string_init_interned("PROPERTY_SIMPLE_CASE_FOLDING", sizeof("PROPERTY_SIMPLE_CASE_FOLDING") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_SIMPLE_CASE_FOLDING_name, &const_PROPERTY_SIMPLE_CASE_FOLDING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_SIMPLE_CASE_FOLDING_name); + zend_string_release_ex(const_PROPERTY_SIMPLE_CASE_FOLDING_name, true); zval const_PROPERTY_SIMPLE_LOWERCASE_MAPPING_value; ZVAL_LONG(&const_PROPERTY_SIMPLE_LOWERCASE_MAPPING_value, UCHAR_SIMPLE_LOWERCASE_MAPPING); - zend_string *const_PROPERTY_SIMPLE_LOWERCASE_MAPPING_name = zend_string_init_interned("PROPERTY_SIMPLE_LOWERCASE_MAPPING", sizeof("PROPERTY_SIMPLE_LOWERCASE_MAPPING") - 1, 1); + zend_string *const_PROPERTY_SIMPLE_LOWERCASE_MAPPING_name = zend_string_init_interned("PROPERTY_SIMPLE_LOWERCASE_MAPPING", sizeof("PROPERTY_SIMPLE_LOWERCASE_MAPPING") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_SIMPLE_LOWERCASE_MAPPING_name, &const_PROPERTY_SIMPLE_LOWERCASE_MAPPING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_SIMPLE_LOWERCASE_MAPPING_name); + zend_string_release_ex(const_PROPERTY_SIMPLE_LOWERCASE_MAPPING_name, true); zval const_PROPERTY_SIMPLE_TITLECASE_MAPPING_value; ZVAL_LONG(&const_PROPERTY_SIMPLE_TITLECASE_MAPPING_value, UCHAR_SIMPLE_TITLECASE_MAPPING); - zend_string *const_PROPERTY_SIMPLE_TITLECASE_MAPPING_name = zend_string_init_interned("PROPERTY_SIMPLE_TITLECASE_MAPPING", sizeof("PROPERTY_SIMPLE_TITLECASE_MAPPING") - 1, 1); + zend_string *const_PROPERTY_SIMPLE_TITLECASE_MAPPING_name = zend_string_init_interned("PROPERTY_SIMPLE_TITLECASE_MAPPING", sizeof("PROPERTY_SIMPLE_TITLECASE_MAPPING") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_SIMPLE_TITLECASE_MAPPING_name, &const_PROPERTY_SIMPLE_TITLECASE_MAPPING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_SIMPLE_TITLECASE_MAPPING_name); + zend_string_release_ex(const_PROPERTY_SIMPLE_TITLECASE_MAPPING_name, true); zval const_PROPERTY_SIMPLE_UPPERCASE_MAPPING_value; ZVAL_LONG(&const_PROPERTY_SIMPLE_UPPERCASE_MAPPING_value, UCHAR_SIMPLE_UPPERCASE_MAPPING); - zend_string *const_PROPERTY_SIMPLE_UPPERCASE_MAPPING_name = zend_string_init_interned("PROPERTY_SIMPLE_UPPERCASE_MAPPING", sizeof("PROPERTY_SIMPLE_UPPERCASE_MAPPING") - 1, 1); + zend_string *const_PROPERTY_SIMPLE_UPPERCASE_MAPPING_name = zend_string_init_interned("PROPERTY_SIMPLE_UPPERCASE_MAPPING", sizeof("PROPERTY_SIMPLE_UPPERCASE_MAPPING") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_SIMPLE_UPPERCASE_MAPPING_name, &const_PROPERTY_SIMPLE_UPPERCASE_MAPPING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_SIMPLE_UPPERCASE_MAPPING_name); + zend_string_release_ex(const_PROPERTY_SIMPLE_UPPERCASE_MAPPING_name, true); zval const_PROPERTY_TITLECASE_MAPPING_value; ZVAL_LONG(&const_PROPERTY_TITLECASE_MAPPING_value, UCHAR_TITLECASE_MAPPING); - zend_string *const_PROPERTY_TITLECASE_MAPPING_name = zend_string_init_interned("PROPERTY_TITLECASE_MAPPING", sizeof("PROPERTY_TITLECASE_MAPPING") - 1, 1); + zend_string *const_PROPERTY_TITLECASE_MAPPING_name = zend_string_init_interned("PROPERTY_TITLECASE_MAPPING", sizeof("PROPERTY_TITLECASE_MAPPING") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_TITLECASE_MAPPING_name, &const_PROPERTY_TITLECASE_MAPPING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_TITLECASE_MAPPING_name); + zend_string_release_ex(const_PROPERTY_TITLECASE_MAPPING_name, true); zval const_PROPERTY_UNICODE_1_NAME_value; ZVAL_LONG(&const_PROPERTY_UNICODE_1_NAME_value, UCHAR_UNICODE_1_NAME); - zend_string *const_PROPERTY_UNICODE_1_NAME_name = zend_string_init_interned("PROPERTY_UNICODE_1_NAME", sizeof("PROPERTY_UNICODE_1_NAME") - 1, 1); + zend_string *const_PROPERTY_UNICODE_1_NAME_name = zend_string_init_interned("PROPERTY_UNICODE_1_NAME", sizeof("PROPERTY_UNICODE_1_NAME") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_UNICODE_1_NAME_name, &const_PROPERTY_UNICODE_1_NAME_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_UNICODE_1_NAME_name); + zend_string_release_ex(const_PROPERTY_UNICODE_1_NAME_name, true); zval const_PROPERTY_UPPERCASE_MAPPING_value; ZVAL_LONG(&const_PROPERTY_UPPERCASE_MAPPING_value, UCHAR_UPPERCASE_MAPPING); - zend_string *const_PROPERTY_UPPERCASE_MAPPING_name = zend_string_init_interned("PROPERTY_UPPERCASE_MAPPING", sizeof("PROPERTY_UPPERCASE_MAPPING") - 1, 1); + zend_string *const_PROPERTY_UPPERCASE_MAPPING_name = zend_string_init_interned("PROPERTY_UPPERCASE_MAPPING", sizeof("PROPERTY_UPPERCASE_MAPPING") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_UPPERCASE_MAPPING_name, &const_PROPERTY_UPPERCASE_MAPPING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_UPPERCASE_MAPPING_name); + zend_string_release_ex(const_PROPERTY_UPPERCASE_MAPPING_name, true); zval const_PROPERTY_BIDI_PAIRED_BRACKET_value; ZVAL_LONG(&const_PROPERTY_BIDI_PAIRED_BRACKET_value, UCHAR_BIDI_PAIRED_BRACKET); - zend_string *const_PROPERTY_BIDI_PAIRED_BRACKET_name = zend_string_init_interned("PROPERTY_BIDI_PAIRED_BRACKET", sizeof("PROPERTY_BIDI_PAIRED_BRACKET") - 1, 1); + zend_string *const_PROPERTY_BIDI_PAIRED_BRACKET_name = zend_string_init_interned("PROPERTY_BIDI_PAIRED_BRACKET", sizeof("PROPERTY_BIDI_PAIRED_BRACKET") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_BIDI_PAIRED_BRACKET_name, &const_PROPERTY_BIDI_PAIRED_BRACKET_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_BIDI_PAIRED_BRACKET_name); + zend_string_release_ex(const_PROPERTY_BIDI_PAIRED_BRACKET_name, true); zval const_PROPERTY_STRING_LIMIT_value; ZVAL_LONG(&const_PROPERTY_STRING_LIMIT_value, UCHAR_STRING_LIMIT); - zend_string *const_PROPERTY_STRING_LIMIT_name = zend_string_init_interned("PROPERTY_STRING_LIMIT", sizeof("PROPERTY_STRING_LIMIT") - 1, 1); + zend_string *const_PROPERTY_STRING_LIMIT_name = zend_string_init_interned("PROPERTY_STRING_LIMIT", sizeof("PROPERTY_STRING_LIMIT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_STRING_LIMIT_name, &const_PROPERTY_STRING_LIMIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_STRING_LIMIT_name); + zend_string_release_ex(const_PROPERTY_STRING_LIMIT_name, true); zval const_PROPERTY_SCRIPT_EXTENSIONS_value; ZVAL_LONG(&const_PROPERTY_SCRIPT_EXTENSIONS_value, UCHAR_SCRIPT_EXTENSIONS); - zend_string *const_PROPERTY_SCRIPT_EXTENSIONS_name = zend_string_init_interned("PROPERTY_SCRIPT_EXTENSIONS", sizeof("PROPERTY_SCRIPT_EXTENSIONS") - 1, 1); + zend_string *const_PROPERTY_SCRIPT_EXTENSIONS_name = zend_string_init_interned("PROPERTY_SCRIPT_EXTENSIONS", sizeof("PROPERTY_SCRIPT_EXTENSIONS") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_SCRIPT_EXTENSIONS_name, &const_PROPERTY_SCRIPT_EXTENSIONS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_SCRIPT_EXTENSIONS_name); + zend_string_release_ex(const_PROPERTY_SCRIPT_EXTENSIONS_name, true); zval const_PROPERTY_OTHER_PROPERTY_START_value; ZVAL_LONG(&const_PROPERTY_OTHER_PROPERTY_START_value, UCHAR_OTHER_PROPERTY_START); - zend_string *const_PROPERTY_OTHER_PROPERTY_START_name = zend_string_init_interned("PROPERTY_OTHER_PROPERTY_START", sizeof("PROPERTY_OTHER_PROPERTY_START") - 1, 1); + zend_string *const_PROPERTY_OTHER_PROPERTY_START_name = zend_string_init_interned("PROPERTY_OTHER_PROPERTY_START", sizeof("PROPERTY_OTHER_PROPERTY_START") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_OTHER_PROPERTY_START_name, &const_PROPERTY_OTHER_PROPERTY_START_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_OTHER_PROPERTY_START_name); + zend_string_release_ex(const_PROPERTY_OTHER_PROPERTY_START_name, true); zval const_PROPERTY_OTHER_PROPERTY_LIMIT_value; ZVAL_LONG(&const_PROPERTY_OTHER_PROPERTY_LIMIT_value, UCHAR_OTHER_PROPERTY_LIMIT); - zend_string *const_PROPERTY_OTHER_PROPERTY_LIMIT_name = zend_string_init_interned("PROPERTY_OTHER_PROPERTY_LIMIT", sizeof("PROPERTY_OTHER_PROPERTY_LIMIT") - 1, 1); + zend_string *const_PROPERTY_OTHER_PROPERTY_LIMIT_name = zend_string_init_interned("PROPERTY_OTHER_PROPERTY_LIMIT", sizeof("PROPERTY_OTHER_PROPERTY_LIMIT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_OTHER_PROPERTY_LIMIT_name, &const_PROPERTY_OTHER_PROPERTY_LIMIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_OTHER_PROPERTY_LIMIT_name); + zend_string_release_ex(const_PROPERTY_OTHER_PROPERTY_LIMIT_name, true); zval const_PROPERTY_INVALID_CODE_value; ZVAL_LONG(&const_PROPERTY_INVALID_CODE_value, UCHAR_INVALID_CODE); - zend_string *const_PROPERTY_INVALID_CODE_name = zend_string_init_interned("PROPERTY_INVALID_CODE", sizeof("PROPERTY_INVALID_CODE") - 1, 1); + zend_string *const_PROPERTY_INVALID_CODE_name = zend_string_init_interned("PROPERTY_INVALID_CODE", sizeof("PROPERTY_INVALID_CODE") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_INVALID_CODE_name, &const_PROPERTY_INVALID_CODE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_INVALID_CODE_name); + zend_string_release_ex(const_PROPERTY_INVALID_CODE_name, true); zval const_CHAR_CATEGORY_UNASSIGNED_value; ZVAL_LONG(&const_CHAR_CATEGORY_UNASSIGNED_value, U_UNASSIGNED); - zend_string *const_CHAR_CATEGORY_UNASSIGNED_name = zend_string_init_interned("CHAR_CATEGORY_UNASSIGNED", sizeof("CHAR_CATEGORY_UNASSIGNED") - 1, 1); + zend_string *const_CHAR_CATEGORY_UNASSIGNED_name = zend_string_init_interned("CHAR_CATEGORY_UNASSIGNED", sizeof("CHAR_CATEGORY_UNASSIGNED") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_UNASSIGNED_name, &const_CHAR_CATEGORY_UNASSIGNED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_UNASSIGNED_name); + zend_string_release_ex(const_CHAR_CATEGORY_UNASSIGNED_name, true); zval const_CHAR_CATEGORY_GENERAL_OTHER_TYPES_value; ZVAL_LONG(&const_CHAR_CATEGORY_GENERAL_OTHER_TYPES_value, U_GENERAL_OTHER_TYPES); - zend_string *const_CHAR_CATEGORY_GENERAL_OTHER_TYPES_name = zend_string_init_interned("CHAR_CATEGORY_GENERAL_OTHER_TYPES", sizeof("CHAR_CATEGORY_GENERAL_OTHER_TYPES") - 1, 1); + zend_string *const_CHAR_CATEGORY_GENERAL_OTHER_TYPES_name = zend_string_init_interned("CHAR_CATEGORY_GENERAL_OTHER_TYPES", sizeof("CHAR_CATEGORY_GENERAL_OTHER_TYPES") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_GENERAL_OTHER_TYPES_name, &const_CHAR_CATEGORY_GENERAL_OTHER_TYPES_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_GENERAL_OTHER_TYPES_name); + zend_string_release_ex(const_CHAR_CATEGORY_GENERAL_OTHER_TYPES_name, true); zval const_CHAR_CATEGORY_UPPERCASE_LETTER_value; ZVAL_LONG(&const_CHAR_CATEGORY_UPPERCASE_LETTER_value, U_UPPERCASE_LETTER); - zend_string *const_CHAR_CATEGORY_UPPERCASE_LETTER_name = zend_string_init_interned("CHAR_CATEGORY_UPPERCASE_LETTER", sizeof("CHAR_CATEGORY_UPPERCASE_LETTER") - 1, 1); + zend_string *const_CHAR_CATEGORY_UPPERCASE_LETTER_name = zend_string_init_interned("CHAR_CATEGORY_UPPERCASE_LETTER", sizeof("CHAR_CATEGORY_UPPERCASE_LETTER") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_UPPERCASE_LETTER_name, &const_CHAR_CATEGORY_UPPERCASE_LETTER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_UPPERCASE_LETTER_name); + zend_string_release_ex(const_CHAR_CATEGORY_UPPERCASE_LETTER_name, true); zval const_CHAR_CATEGORY_LOWERCASE_LETTER_value; ZVAL_LONG(&const_CHAR_CATEGORY_LOWERCASE_LETTER_value, U_LOWERCASE_LETTER); - zend_string *const_CHAR_CATEGORY_LOWERCASE_LETTER_name = zend_string_init_interned("CHAR_CATEGORY_LOWERCASE_LETTER", sizeof("CHAR_CATEGORY_LOWERCASE_LETTER") - 1, 1); + zend_string *const_CHAR_CATEGORY_LOWERCASE_LETTER_name = zend_string_init_interned("CHAR_CATEGORY_LOWERCASE_LETTER", sizeof("CHAR_CATEGORY_LOWERCASE_LETTER") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_LOWERCASE_LETTER_name, &const_CHAR_CATEGORY_LOWERCASE_LETTER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_LOWERCASE_LETTER_name); + zend_string_release_ex(const_CHAR_CATEGORY_LOWERCASE_LETTER_name, true); zval const_CHAR_CATEGORY_TITLECASE_LETTER_value; ZVAL_LONG(&const_CHAR_CATEGORY_TITLECASE_LETTER_value, U_TITLECASE_LETTER); - zend_string *const_CHAR_CATEGORY_TITLECASE_LETTER_name = zend_string_init_interned("CHAR_CATEGORY_TITLECASE_LETTER", sizeof("CHAR_CATEGORY_TITLECASE_LETTER") - 1, 1); + zend_string *const_CHAR_CATEGORY_TITLECASE_LETTER_name = zend_string_init_interned("CHAR_CATEGORY_TITLECASE_LETTER", sizeof("CHAR_CATEGORY_TITLECASE_LETTER") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_TITLECASE_LETTER_name, &const_CHAR_CATEGORY_TITLECASE_LETTER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_TITLECASE_LETTER_name); + zend_string_release_ex(const_CHAR_CATEGORY_TITLECASE_LETTER_name, true); zval const_CHAR_CATEGORY_MODIFIER_LETTER_value; ZVAL_LONG(&const_CHAR_CATEGORY_MODIFIER_LETTER_value, U_MODIFIER_LETTER); - zend_string *const_CHAR_CATEGORY_MODIFIER_LETTER_name = zend_string_init_interned("CHAR_CATEGORY_MODIFIER_LETTER", sizeof("CHAR_CATEGORY_MODIFIER_LETTER") - 1, 1); + zend_string *const_CHAR_CATEGORY_MODIFIER_LETTER_name = zend_string_init_interned("CHAR_CATEGORY_MODIFIER_LETTER", sizeof("CHAR_CATEGORY_MODIFIER_LETTER") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_MODIFIER_LETTER_name, &const_CHAR_CATEGORY_MODIFIER_LETTER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_MODIFIER_LETTER_name); + zend_string_release_ex(const_CHAR_CATEGORY_MODIFIER_LETTER_name, true); zval const_CHAR_CATEGORY_OTHER_LETTER_value; ZVAL_LONG(&const_CHAR_CATEGORY_OTHER_LETTER_value, U_OTHER_LETTER); - zend_string *const_CHAR_CATEGORY_OTHER_LETTER_name = zend_string_init_interned("CHAR_CATEGORY_OTHER_LETTER", sizeof("CHAR_CATEGORY_OTHER_LETTER") - 1, 1); + zend_string *const_CHAR_CATEGORY_OTHER_LETTER_name = zend_string_init_interned("CHAR_CATEGORY_OTHER_LETTER", sizeof("CHAR_CATEGORY_OTHER_LETTER") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_OTHER_LETTER_name, &const_CHAR_CATEGORY_OTHER_LETTER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_OTHER_LETTER_name); + zend_string_release_ex(const_CHAR_CATEGORY_OTHER_LETTER_name, true); zval const_CHAR_CATEGORY_NON_SPACING_MARK_value; ZVAL_LONG(&const_CHAR_CATEGORY_NON_SPACING_MARK_value, U_NON_SPACING_MARK); - zend_string *const_CHAR_CATEGORY_NON_SPACING_MARK_name = zend_string_init_interned("CHAR_CATEGORY_NON_SPACING_MARK", sizeof("CHAR_CATEGORY_NON_SPACING_MARK") - 1, 1); + zend_string *const_CHAR_CATEGORY_NON_SPACING_MARK_name = zend_string_init_interned("CHAR_CATEGORY_NON_SPACING_MARK", sizeof("CHAR_CATEGORY_NON_SPACING_MARK") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_NON_SPACING_MARK_name, &const_CHAR_CATEGORY_NON_SPACING_MARK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_NON_SPACING_MARK_name); + zend_string_release_ex(const_CHAR_CATEGORY_NON_SPACING_MARK_name, true); zval const_CHAR_CATEGORY_ENCLOSING_MARK_value; ZVAL_LONG(&const_CHAR_CATEGORY_ENCLOSING_MARK_value, U_ENCLOSING_MARK); - zend_string *const_CHAR_CATEGORY_ENCLOSING_MARK_name = zend_string_init_interned("CHAR_CATEGORY_ENCLOSING_MARK", sizeof("CHAR_CATEGORY_ENCLOSING_MARK") - 1, 1); + zend_string *const_CHAR_CATEGORY_ENCLOSING_MARK_name = zend_string_init_interned("CHAR_CATEGORY_ENCLOSING_MARK", sizeof("CHAR_CATEGORY_ENCLOSING_MARK") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_ENCLOSING_MARK_name, &const_CHAR_CATEGORY_ENCLOSING_MARK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_ENCLOSING_MARK_name); + zend_string_release_ex(const_CHAR_CATEGORY_ENCLOSING_MARK_name, true); zval const_CHAR_CATEGORY_COMBINING_SPACING_MARK_value; ZVAL_LONG(&const_CHAR_CATEGORY_COMBINING_SPACING_MARK_value, U_COMBINING_SPACING_MARK); - zend_string *const_CHAR_CATEGORY_COMBINING_SPACING_MARK_name = zend_string_init_interned("CHAR_CATEGORY_COMBINING_SPACING_MARK", sizeof("CHAR_CATEGORY_COMBINING_SPACING_MARK") - 1, 1); + zend_string *const_CHAR_CATEGORY_COMBINING_SPACING_MARK_name = zend_string_init_interned("CHAR_CATEGORY_COMBINING_SPACING_MARK", sizeof("CHAR_CATEGORY_COMBINING_SPACING_MARK") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_COMBINING_SPACING_MARK_name, &const_CHAR_CATEGORY_COMBINING_SPACING_MARK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_COMBINING_SPACING_MARK_name); + zend_string_release_ex(const_CHAR_CATEGORY_COMBINING_SPACING_MARK_name, true); zval const_CHAR_CATEGORY_DECIMAL_DIGIT_NUMBER_value; ZVAL_LONG(&const_CHAR_CATEGORY_DECIMAL_DIGIT_NUMBER_value, U_DECIMAL_DIGIT_NUMBER); - zend_string *const_CHAR_CATEGORY_DECIMAL_DIGIT_NUMBER_name = zend_string_init_interned("CHAR_CATEGORY_DECIMAL_DIGIT_NUMBER", sizeof("CHAR_CATEGORY_DECIMAL_DIGIT_NUMBER") - 1, 1); + zend_string *const_CHAR_CATEGORY_DECIMAL_DIGIT_NUMBER_name = zend_string_init_interned("CHAR_CATEGORY_DECIMAL_DIGIT_NUMBER", sizeof("CHAR_CATEGORY_DECIMAL_DIGIT_NUMBER") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_DECIMAL_DIGIT_NUMBER_name, &const_CHAR_CATEGORY_DECIMAL_DIGIT_NUMBER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_DECIMAL_DIGIT_NUMBER_name); + zend_string_release_ex(const_CHAR_CATEGORY_DECIMAL_DIGIT_NUMBER_name, true); zval const_CHAR_CATEGORY_LETTER_NUMBER_value; ZVAL_LONG(&const_CHAR_CATEGORY_LETTER_NUMBER_value, U_LETTER_NUMBER); - zend_string *const_CHAR_CATEGORY_LETTER_NUMBER_name = zend_string_init_interned("CHAR_CATEGORY_LETTER_NUMBER", sizeof("CHAR_CATEGORY_LETTER_NUMBER") - 1, 1); + zend_string *const_CHAR_CATEGORY_LETTER_NUMBER_name = zend_string_init_interned("CHAR_CATEGORY_LETTER_NUMBER", sizeof("CHAR_CATEGORY_LETTER_NUMBER") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_LETTER_NUMBER_name, &const_CHAR_CATEGORY_LETTER_NUMBER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_LETTER_NUMBER_name); + zend_string_release_ex(const_CHAR_CATEGORY_LETTER_NUMBER_name, true); zval const_CHAR_CATEGORY_OTHER_NUMBER_value; ZVAL_LONG(&const_CHAR_CATEGORY_OTHER_NUMBER_value, U_OTHER_NUMBER); - zend_string *const_CHAR_CATEGORY_OTHER_NUMBER_name = zend_string_init_interned("CHAR_CATEGORY_OTHER_NUMBER", sizeof("CHAR_CATEGORY_OTHER_NUMBER") - 1, 1); + zend_string *const_CHAR_CATEGORY_OTHER_NUMBER_name = zend_string_init_interned("CHAR_CATEGORY_OTHER_NUMBER", sizeof("CHAR_CATEGORY_OTHER_NUMBER") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_OTHER_NUMBER_name, &const_CHAR_CATEGORY_OTHER_NUMBER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_OTHER_NUMBER_name); + zend_string_release_ex(const_CHAR_CATEGORY_OTHER_NUMBER_name, true); zval const_CHAR_CATEGORY_SPACE_SEPARATOR_value; ZVAL_LONG(&const_CHAR_CATEGORY_SPACE_SEPARATOR_value, U_SPACE_SEPARATOR); - zend_string *const_CHAR_CATEGORY_SPACE_SEPARATOR_name = zend_string_init_interned("CHAR_CATEGORY_SPACE_SEPARATOR", sizeof("CHAR_CATEGORY_SPACE_SEPARATOR") - 1, 1); + zend_string *const_CHAR_CATEGORY_SPACE_SEPARATOR_name = zend_string_init_interned("CHAR_CATEGORY_SPACE_SEPARATOR", sizeof("CHAR_CATEGORY_SPACE_SEPARATOR") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_SPACE_SEPARATOR_name, &const_CHAR_CATEGORY_SPACE_SEPARATOR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_SPACE_SEPARATOR_name); + zend_string_release_ex(const_CHAR_CATEGORY_SPACE_SEPARATOR_name, true); zval const_CHAR_CATEGORY_LINE_SEPARATOR_value; ZVAL_LONG(&const_CHAR_CATEGORY_LINE_SEPARATOR_value, U_LINE_SEPARATOR); - zend_string *const_CHAR_CATEGORY_LINE_SEPARATOR_name = zend_string_init_interned("CHAR_CATEGORY_LINE_SEPARATOR", sizeof("CHAR_CATEGORY_LINE_SEPARATOR") - 1, 1); + zend_string *const_CHAR_CATEGORY_LINE_SEPARATOR_name = zend_string_init_interned("CHAR_CATEGORY_LINE_SEPARATOR", sizeof("CHAR_CATEGORY_LINE_SEPARATOR") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_LINE_SEPARATOR_name, &const_CHAR_CATEGORY_LINE_SEPARATOR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_LINE_SEPARATOR_name); + zend_string_release_ex(const_CHAR_CATEGORY_LINE_SEPARATOR_name, true); zval const_CHAR_CATEGORY_PARAGRAPH_SEPARATOR_value; ZVAL_LONG(&const_CHAR_CATEGORY_PARAGRAPH_SEPARATOR_value, U_PARAGRAPH_SEPARATOR); - zend_string *const_CHAR_CATEGORY_PARAGRAPH_SEPARATOR_name = zend_string_init_interned("CHAR_CATEGORY_PARAGRAPH_SEPARATOR", sizeof("CHAR_CATEGORY_PARAGRAPH_SEPARATOR") - 1, 1); + zend_string *const_CHAR_CATEGORY_PARAGRAPH_SEPARATOR_name = zend_string_init_interned("CHAR_CATEGORY_PARAGRAPH_SEPARATOR", sizeof("CHAR_CATEGORY_PARAGRAPH_SEPARATOR") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_PARAGRAPH_SEPARATOR_name, &const_CHAR_CATEGORY_PARAGRAPH_SEPARATOR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_PARAGRAPH_SEPARATOR_name); + zend_string_release_ex(const_CHAR_CATEGORY_PARAGRAPH_SEPARATOR_name, true); zval const_CHAR_CATEGORY_CONTROL_CHAR_value; ZVAL_LONG(&const_CHAR_CATEGORY_CONTROL_CHAR_value, U_CONTROL_CHAR); - zend_string *const_CHAR_CATEGORY_CONTROL_CHAR_name = zend_string_init_interned("CHAR_CATEGORY_CONTROL_CHAR", sizeof("CHAR_CATEGORY_CONTROL_CHAR") - 1, 1); + zend_string *const_CHAR_CATEGORY_CONTROL_CHAR_name = zend_string_init_interned("CHAR_CATEGORY_CONTROL_CHAR", sizeof("CHAR_CATEGORY_CONTROL_CHAR") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_CONTROL_CHAR_name, &const_CHAR_CATEGORY_CONTROL_CHAR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_CONTROL_CHAR_name); + zend_string_release_ex(const_CHAR_CATEGORY_CONTROL_CHAR_name, true); zval const_CHAR_CATEGORY_FORMAT_CHAR_value; ZVAL_LONG(&const_CHAR_CATEGORY_FORMAT_CHAR_value, U_FORMAT_CHAR); - zend_string *const_CHAR_CATEGORY_FORMAT_CHAR_name = zend_string_init_interned("CHAR_CATEGORY_FORMAT_CHAR", sizeof("CHAR_CATEGORY_FORMAT_CHAR") - 1, 1); + zend_string *const_CHAR_CATEGORY_FORMAT_CHAR_name = zend_string_init_interned("CHAR_CATEGORY_FORMAT_CHAR", sizeof("CHAR_CATEGORY_FORMAT_CHAR") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_FORMAT_CHAR_name, &const_CHAR_CATEGORY_FORMAT_CHAR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_FORMAT_CHAR_name); + zend_string_release_ex(const_CHAR_CATEGORY_FORMAT_CHAR_name, true); zval const_CHAR_CATEGORY_PRIVATE_USE_CHAR_value; ZVAL_LONG(&const_CHAR_CATEGORY_PRIVATE_USE_CHAR_value, U_PRIVATE_USE_CHAR); - zend_string *const_CHAR_CATEGORY_PRIVATE_USE_CHAR_name = zend_string_init_interned("CHAR_CATEGORY_PRIVATE_USE_CHAR", sizeof("CHAR_CATEGORY_PRIVATE_USE_CHAR") - 1, 1); + zend_string *const_CHAR_CATEGORY_PRIVATE_USE_CHAR_name = zend_string_init_interned("CHAR_CATEGORY_PRIVATE_USE_CHAR", sizeof("CHAR_CATEGORY_PRIVATE_USE_CHAR") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_PRIVATE_USE_CHAR_name, &const_CHAR_CATEGORY_PRIVATE_USE_CHAR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_PRIVATE_USE_CHAR_name); + zend_string_release_ex(const_CHAR_CATEGORY_PRIVATE_USE_CHAR_name, true); zval const_CHAR_CATEGORY_SURROGATE_value; ZVAL_LONG(&const_CHAR_CATEGORY_SURROGATE_value, U_SURROGATE); - zend_string *const_CHAR_CATEGORY_SURROGATE_name = zend_string_init_interned("CHAR_CATEGORY_SURROGATE", sizeof("CHAR_CATEGORY_SURROGATE") - 1, 1); + zend_string *const_CHAR_CATEGORY_SURROGATE_name = zend_string_init_interned("CHAR_CATEGORY_SURROGATE", sizeof("CHAR_CATEGORY_SURROGATE") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_SURROGATE_name, &const_CHAR_CATEGORY_SURROGATE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_SURROGATE_name); + zend_string_release_ex(const_CHAR_CATEGORY_SURROGATE_name, true); zval const_CHAR_CATEGORY_DASH_PUNCTUATION_value; ZVAL_LONG(&const_CHAR_CATEGORY_DASH_PUNCTUATION_value, U_DASH_PUNCTUATION); - zend_string *const_CHAR_CATEGORY_DASH_PUNCTUATION_name = zend_string_init_interned("CHAR_CATEGORY_DASH_PUNCTUATION", sizeof("CHAR_CATEGORY_DASH_PUNCTUATION") - 1, 1); + zend_string *const_CHAR_CATEGORY_DASH_PUNCTUATION_name = zend_string_init_interned("CHAR_CATEGORY_DASH_PUNCTUATION", sizeof("CHAR_CATEGORY_DASH_PUNCTUATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_DASH_PUNCTUATION_name, &const_CHAR_CATEGORY_DASH_PUNCTUATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_DASH_PUNCTUATION_name); + zend_string_release_ex(const_CHAR_CATEGORY_DASH_PUNCTUATION_name, true); zval const_CHAR_CATEGORY_START_PUNCTUATION_value; ZVAL_LONG(&const_CHAR_CATEGORY_START_PUNCTUATION_value, U_START_PUNCTUATION); - zend_string *const_CHAR_CATEGORY_START_PUNCTUATION_name = zend_string_init_interned("CHAR_CATEGORY_START_PUNCTUATION", sizeof("CHAR_CATEGORY_START_PUNCTUATION") - 1, 1); + zend_string *const_CHAR_CATEGORY_START_PUNCTUATION_name = zend_string_init_interned("CHAR_CATEGORY_START_PUNCTUATION", sizeof("CHAR_CATEGORY_START_PUNCTUATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_START_PUNCTUATION_name, &const_CHAR_CATEGORY_START_PUNCTUATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_START_PUNCTUATION_name); + zend_string_release_ex(const_CHAR_CATEGORY_START_PUNCTUATION_name, true); zval const_CHAR_CATEGORY_END_PUNCTUATION_value; ZVAL_LONG(&const_CHAR_CATEGORY_END_PUNCTUATION_value, U_END_PUNCTUATION); - zend_string *const_CHAR_CATEGORY_END_PUNCTUATION_name = zend_string_init_interned("CHAR_CATEGORY_END_PUNCTUATION", sizeof("CHAR_CATEGORY_END_PUNCTUATION") - 1, 1); + zend_string *const_CHAR_CATEGORY_END_PUNCTUATION_name = zend_string_init_interned("CHAR_CATEGORY_END_PUNCTUATION", sizeof("CHAR_CATEGORY_END_PUNCTUATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_END_PUNCTUATION_name, &const_CHAR_CATEGORY_END_PUNCTUATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_END_PUNCTUATION_name); + zend_string_release_ex(const_CHAR_CATEGORY_END_PUNCTUATION_name, true); zval const_CHAR_CATEGORY_CONNECTOR_PUNCTUATION_value; ZVAL_LONG(&const_CHAR_CATEGORY_CONNECTOR_PUNCTUATION_value, U_CONNECTOR_PUNCTUATION); - zend_string *const_CHAR_CATEGORY_CONNECTOR_PUNCTUATION_name = zend_string_init_interned("CHAR_CATEGORY_CONNECTOR_PUNCTUATION", sizeof("CHAR_CATEGORY_CONNECTOR_PUNCTUATION") - 1, 1); + zend_string *const_CHAR_CATEGORY_CONNECTOR_PUNCTUATION_name = zend_string_init_interned("CHAR_CATEGORY_CONNECTOR_PUNCTUATION", sizeof("CHAR_CATEGORY_CONNECTOR_PUNCTUATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_CONNECTOR_PUNCTUATION_name, &const_CHAR_CATEGORY_CONNECTOR_PUNCTUATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_CONNECTOR_PUNCTUATION_name); + zend_string_release_ex(const_CHAR_CATEGORY_CONNECTOR_PUNCTUATION_name, true); zval const_CHAR_CATEGORY_OTHER_PUNCTUATION_value; ZVAL_LONG(&const_CHAR_CATEGORY_OTHER_PUNCTUATION_value, U_OTHER_PUNCTUATION); - zend_string *const_CHAR_CATEGORY_OTHER_PUNCTUATION_name = zend_string_init_interned("CHAR_CATEGORY_OTHER_PUNCTUATION", sizeof("CHAR_CATEGORY_OTHER_PUNCTUATION") - 1, 1); + zend_string *const_CHAR_CATEGORY_OTHER_PUNCTUATION_name = zend_string_init_interned("CHAR_CATEGORY_OTHER_PUNCTUATION", sizeof("CHAR_CATEGORY_OTHER_PUNCTUATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_OTHER_PUNCTUATION_name, &const_CHAR_CATEGORY_OTHER_PUNCTUATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_OTHER_PUNCTUATION_name); + zend_string_release_ex(const_CHAR_CATEGORY_OTHER_PUNCTUATION_name, true); zval const_CHAR_CATEGORY_MATH_SYMBOL_value; ZVAL_LONG(&const_CHAR_CATEGORY_MATH_SYMBOL_value, U_MATH_SYMBOL); - zend_string *const_CHAR_CATEGORY_MATH_SYMBOL_name = zend_string_init_interned("CHAR_CATEGORY_MATH_SYMBOL", sizeof("CHAR_CATEGORY_MATH_SYMBOL") - 1, 1); + zend_string *const_CHAR_CATEGORY_MATH_SYMBOL_name = zend_string_init_interned("CHAR_CATEGORY_MATH_SYMBOL", sizeof("CHAR_CATEGORY_MATH_SYMBOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_MATH_SYMBOL_name, &const_CHAR_CATEGORY_MATH_SYMBOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_MATH_SYMBOL_name); + zend_string_release_ex(const_CHAR_CATEGORY_MATH_SYMBOL_name, true); zval const_CHAR_CATEGORY_CURRENCY_SYMBOL_value; ZVAL_LONG(&const_CHAR_CATEGORY_CURRENCY_SYMBOL_value, U_CURRENCY_SYMBOL); - zend_string *const_CHAR_CATEGORY_CURRENCY_SYMBOL_name = zend_string_init_interned("CHAR_CATEGORY_CURRENCY_SYMBOL", sizeof("CHAR_CATEGORY_CURRENCY_SYMBOL") - 1, 1); + zend_string *const_CHAR_CATEGORY_CURRENCY_SYMBOL_name = zend_string_init_interned("CHAR_CATEGORY_CURRENCY_SYMBOL", sizeof("CHAR_CATEGORY_CURRENCY_SYMBOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_CURRENCY_SYMBOL_name, &const_CHAR_CATEGORY_CURRENCY_SYMBOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_CURRENCY_SYMBOL_name); + zend_string_release_ex(const_CHAR_CATEGORY_CURRENCY_SYMBOL_name, true); zval const_CHAR_CATEGORY_MODIFIER_SYMBOL_value; ZVAL_LONG(&const_CHAR_CATEGORY_MODIFIER_SYMBOL_value, U_MODIFIER_SYMBOL); - zend_string *const_CHAR_CATEGORY_MODIFIER_SYMBOL_name = zend_string_init_interned("CHAR_CATEGORY_MODIFIER_SYMBOL", sizeof("CHAR_CATEGORY_MODIFIER_SYMBOL") - 1, 1); + zend_string *const_CHAR_CATEGORY_MODIFIER_SYMBOL_name = zend_string_init_interned("CHAR_CATEGORY_MODIFIER_SYMBOL", sizeof("CHAR_CATEGORY_MODIFIER_SYMBOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_MODIFIER_SYMBOL_name, &const_CHAR_CATEGORY_MODIFIER_SYMBOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_MODIFIER_SYMBOL_name); + zend_string_release_ex(const_CHAR_CATEGORY_MODIFIER_SYMBOL_name, true); zval const_CHAR_CATEGORY_OTHER_SYMBOL_value; ZVAL_LONG(&const_CHAR_CATEGORY_OTHER_SYMBOL_value, U_OTHER_SYMBOL); - zend_string *const_CHAR_CATEGORY_OTHER_SYMBOL_name = zend_string_init_interned("CHAR_CATEGORY_OTHER_SYMBOL", sizeof("CHAR_CATEGORY_OTHER_SYMBOL") - 1, 1); + zend_string *const_CHAR_CATEGORY_OTHER_SYMBOL_name = zend_string_init_interned("CHAR_CATEGORY_OTHER_SYMBOL", sizeof("CHAR_CATEGORY_OTHER_SYMBOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_OTHER_SYMBOL_name, &const_CHAR_CATEGORY_OTHER_SYMBOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_OTHER_SYMBOL_name); + zend_string_release_ex(const_CHAR_CATEGORY_OTHER_SYMBOL_name, true); zval const_CHAR_CATEGORY_INITIAL_PUNCTUATION_value; ZVAL_LONG(&const_CHAR_CATEGORY_INITIAL_PUNCTUATION_value, U_INITIAL_PUNCTUATION); - zend_string *const_CHAR_CATEGORY_INITIAL_PUNCTUATION_name = zend_string_init_interned("CHAR_CATEGORY_INITIAL_PUNCTUATION", sizeof("CHAR_CATEGORY_INITIAL_PUNCTUATION") - 1, 1); + zend_string *const_CHAR_CATEGORY_INITIAL_PUNCTUATION_name = zend_string_init_interned("CHAR_CATEGORY_INITIAL_PUNCTUATION", sizeof("CHAR_CATEGORY_INITIAL_PUNCTUATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_INITIAL_PUNCTUATION_name, &const_CHAR_CATEGORY_INITIAL_PUNCTUATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_INITIAL_PUNCTUATION_name); + zend_string_release_ex(const_CHAR_CATEGORY_INITIAL_PUNCTUATION_name, true); zval const_CHAR_CATEGORY_FINAL_PUNCTUATION_value; ZVAL_LONG(&const_CHAR_CATEGORY_FINAL_PUNCTUATION_value, U_FINAL_PUNCTUATION); - zend_string *const_CHAR_CATEGORY_FINAL_PUNCTUATION_name = zend_string_init_interned("CHAR_CATEGORY_FINAL_PUNCTUATION", sizeof("CHAR_CATEGORY_FINAL_PUNCTUATION") - 1, 1); + zend_string *const_CHAR_CATEGORY_FINAL_PUNCTUATION_name = zend_string_init_interned("CHAR_CATEGORY_FINAL_PUNCTUATION", sizeof("CHAR_CATEGORY_FINAL_PUNCTUATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_FINAL_PUNCTUATION_name, &const_CHAR_CATEGORY_FINAL_PUNCTUATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_FINAL_PUNCTUATION_name); + zend_string_release_ex(const_CHAR_CATEGORY_FINAL_PUNCTUATION_name, true); zval const_CHAR_CATEGORY_CHAR_CATEGORY_COUNT_value; ZVAL_LONG(&const_CHAR_CATEGORY_CHAR_CATEGORY_COUNT_value, U_CHAR_CATEGORY_COUNT); - zend_string *const_CHAR_CATEGORY_CHAR_CATEGORY_COUNT_name = zend_string_init_interned("CHAR_CATEGORY_CHAR_CATEGORY_COUNT", sizeof("CHAR_CATEGORY_CHAR_CATEGORY_COUNT") - 1, 1); + zend_string *const_CHAR_CATEGORY_CHAR_CATEGORY_COUNT_name = zend_string_init_interned("CHAR_CATEGORY_CHAR_CATEGORY_COUNT", sizeof("CHAR_CATEGORY_CHAR_CATEGORY_COUNT") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_CATEGORY_CHAR_CATEGORY_COUNT_name, &const_CHAR_CATEGORY_CHAR_CATEGORY_COUNT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_CATEGORY_CHAR_CATEGORY_COUNT_name); + zend_string_release_ex(const_CHAR_CATEGORY_CHAR_CATEGORY_COUNT_name, true); zval const_CHAR_DIRECTION_LEFT_TO_RIGHT_value; ZVAL_LONG(&const_CHAR_DIRECTION_LEFT_TO_RIGHT_value, U_LEFT_TO_RIGHT); - zend_string *const_CHAR_DIRECTION_LEFT_TO_RIGHT_name = zend_string_init_interned("CHAR_DIRECTION_LEFT_TO_RIGHT", sizeof("CHAR_DIRECTION_LEFT_TO_RIGHT") - 1, 1); + zend_string *const_CHAR_DIRECTION_LEFT_TO_RIGHT_name = zend_string_init_interned("CHAR_DIRECTION_LEFT_TO_RIGHT", sizeof("CHAR_DIRECTION_LEFT_TO_RIGHT") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_LEFT_TO_RIGHT_name, &const_CHAR_DIRECTION_LEFT_TO_RIGHT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_LEFT_TO_RIGHT_name); + zend_string_release_ex(const_CHAR_DIRECTION_LEFT_TO_RIGHT_name, true); zval const_CHAR_DIRECTION_RIGHT_TO_LEFT_value; ZVAL_LONG(&const_CHAR_DIRECTION_RIGHT_TO_LEFT_value, U_RIGHT_TO_LEFT); - zend_string *const_CHAR_DIRECTION_RIGHT_TO_LEFT_name = zend_string_init_interned("CHAR_DIRECTION_RIGHT_TO_LEFT", sizeof("CHAR_DIRECTION_RIGHT_TO_LEFT") - 1, 1); + zend_string *const_CHAR_DIRECTION_RIGHT_TO_LEFT_name = zend_string_init_interned("CHAR_DIRECTION_RIGHT_TO_LEFT", sizeof("CHAR_DIRECTION_RIGHT_TO_LEFT") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_RIGHT_TO_LEFT_name, &const_CHAR_DIRECTION_RIGHT_TO_LEFT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_RIGHT_TO_LEFT_name); + zend_string_release_ex(const_CHAR_DIRECTION_RIGHT_TO_LEFT_name, true); zval const_CHAR_DIRECTION_EUROPEAN_NUMBER_value; ZVAL_LONG(&const_CHAR_DIRECTION_EUROPEAN_NUMBER_value, U_EUROPEAN_NUMBER); - zend_string *const_CHAR_DIRECTION_EUROPEAN_NUMBER_name = zend_string_init_interned("CHAR_DIRECTION_EUROPEAN_NUMBER", sizeof("CHAR_DIRECTION_EUROPEAN_NUMBER") - 1, 1); + zend_string *const_CHAR_DIRECTION_EUROPEAN_NUMBER_name = zend_string_init_interned("CHAR_DIRECTION_EUROPEAN_NUMBER", sizeof("CHAR_DIRECTION_EUROPEAN_NUMBER") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_EUROPEAN_NUMBER_name, &const_CHAR_DIRECTION_EUROPEAN_NUMBER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_EUROPEAN_NUMBER_name); + zend_string_release_ex(const_CHAR_DIRECTION_EUROPEAN_NUMBER_name, true); zval const_CHAR_DIRECTION_EUROPEAN_NUMBER_SEPARATOR_value; ZVAL_LONG(&const_CHAR_DIRECTION_EUROPEAN_NUMBER_SEPARATOR_value, U_EUROPEAN_NUMBER_SEPARATOR); - zend_string *const_CHAR_DIRECTION_EUROPEAN_NUMBER_SEPARATOR_name = zend_string_init_interned("CHAR_DIRECTION_EUROPEAN_NUMBER_SEPARATOR", sizeof("CHAR_DIRECTION_EUROPEAN_NUMBER_SEPARATOR") - 1, 1); + zend_string *const_CHAR_DIRECTION_EUROPEAN_NUMBER_SEPARATOR_name = zend_string_init_interned("CHAR_DIRECTION_EUROPEAN_NUMBER_SEPARATOR", sizeof("CHAR_DIRECTION_EUROPEAN_NUMBER_SEPARATOR") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_EUROPEAN_NUMBER_SEPARATOR_name, &const_CHAR_DIRECTION_EUROPEAN_NUMBER_SEPARATOR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_EUROPEAN_NUMBER_SEPARATOR_name); + zend_string_release_ex(const_CHAR_DIRECTION_EUROPEAN_NUMBER_SEPARATOR_name, true); zval const_CHAR_DIRECTION_EUROPEAN_NUMBER_TERMINATOR_value; ZVAL_LONG(&const_CHAR_DIRECTION_EUROPEAN_NUMBER_TERMINATOR_value, U_EUROPEAN_NUMBER_TERMINATOR); - zend_string *const_CHAR_DIRECTION_EUROPEAN_NUMBER_TERMINATOR_name = zend_string_init_interned("CHAR_DIRECTION_EUROPEAN_NUMBER_TERMINATOR", sizeof("CHAR_DIRECTION_EUROPEAN_NUMBER_TERMINATOR") - 1, 1); + zend_string *const_CHAR_DIRECTION_EUROPEAN_NUMBER_TERMINATOR_name = zend_string_init_interned("CHAR_DIRECTION_EUROPEAN_NUMBER_TERMINATOR", sizeof("CHAR_DIRECTION_EUROPEAN_NUMBER_TERMINATOR") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_EUROPEAN_NUMBER_TERMINATOR_name, &const_CHAR_DIRECTION_EUROPEAN_NUMBER_TERMINATOR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_EUROPEAN_NUMBER_TERMINATOR_name); + zend_string_release_ex(const_CHAR_DIRECTION_EUROPEAN_NUMBER_TERMINATOR_name, true); zval const_CHAR_DIRECTION_ARABIC_NUMBER_value; ZVAL_LONG(&const_CHAR_DIRECTION_ARABIC_NUMBER_value, U_ARABIC_NUMBER); - zend_string *const_CHAR_DIRECTION_ARABIC_NUMBER_name = zend_string_init_interned("CHAR_DIRECTION_ARABIC_NUMBER", sizeof("CHAR_DIRECTION_ARABIC_NUMBER") - 1, 1); + zend_string *const_CHAR_DIRECTION_ARABIC_NUMBER_name = zend_string_init_interned("CHAR_DIRECTION_ARABIC_NUMBER", sizeof("CHAR_DIRECTION_ARABIC_NUMBER") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_ARABIC_NUMBER_name, &const_CHAR_DIRECTION_ARABIC_NUMBER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_ARABIC_NUMBER_name); + zend_string_release_ex(const_CHAR_DIRECTION_ARABIC_NUMBER_name, true); zval const_CHAR_DIRECTION_COMMON_NUMBER_SEPARATOR_value; ZVAL_LONG(&const_CHAR_DIRECTION_COMMON_NUMBER_SEPARATOR_value, U_COMMON_NUMBER_SEPARATOR); - zend_string *const_CHAR_DIRECTION_COMMON_NUMBER_SEPARATOR_name = zend_string_init_interned("CHAR_DIRECTION_COMMON_NUMBER_SEPARATOR", sizeof("CHAR_DIRECTION_COMMON_NUMBER_SEPARATOR") - 1, 1); + zend_string *const_CHAR_DIRECTION_COMMON_NUMBER_SEPARATOR_name = zend_string_init_interned("CHAR_DIRECTION_COMMON_NUMBER_SEPARATOR", sizeof("CHAR_DIRECTION_COMMON_NUMBER_SEPARATOR") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_COMMON_NUMBER_SEPARATOR_name, &const_CHAR_DIRECTION_COMMON_NUMBER_SEPARATOR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_COMMON_NUMBER_SEPARATOR_name); + zend_string_release_ex(const_CHAR_DIRECTION_COMMON_NUMBER_SEPARATOR_name, true); zval const_CHAR_DIRECTION_BLOCK_SEPARATOR_value; ZVAL_LONG(&const_CHAR_DIRECTION_BLOCK_SEPARATOR_value, U_BLOCK_SEPARATOR); - zend_string *const_CHAR_DIRECTION_BLOCK_SEPARATOR_name = zend_string_init_interned("CHAR_DIRECTION_BLOCK_SEPARATOR", sizeof("CHAR_DIRECTION_BLOCK_SEPARATOR") - 1, 1); + zend_string *const_CHAR_DIRECTION_BLOCK_SEPARATOR_name = zend_string_init_interned("CHAR_DIRECTION_BLOCK_SEPARATOR", sizeof("CHAR_DIRECTION_BLOCK_SEPARATOR") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_BLOCK_SEPARATOR_name, &const_CHAR_DIRECTION_BLOCK_SEPARATOR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_BLOCK_SEPARATOR_name); + zend_string_release_ex(const_CHAR_DIRECTION_BLOCK_SEPARATOR_name, true); zval const_CHAR_DIRECTION_SEGMENT_SEPARATOR_value; ZVAL_LONG(&const_CHAR_DIRECTION_SEGMENT_SEPARATOR_value, U_SEGMENT_SEPARATOR); - zend_string *const_CHAR_DIRECTION_SEGMENT_SEPARATOR_name = zend_string_init_interned("CHAR_DIRECTION_SEGMENT_SEPARATOR", sizeof("CHAR_DIRECTION_SEGMENT_SEPARATOR") - 1, 1); + zend_string *const_CHAR_DIRECTION_SEGMENT_SEPARATOR_name = zend_string_init_interned("CHAR_DIRECTION_SEGMENT_SEPARATOR", sizeof("CHAR_DIRECTION_SEGMENT_SEPARATOR") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_SEGMENT_SEPARATOR_name, &const_CHAR_DIRECTION_SEGMENT_SEPARATOR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_SEGMENT_SEPARATOR_name); + zend_string_release_ex(const_CHAR_DIRECTION_SEGMENT_SEPARATOR_name, true); zval const_CHAR_DIRECTION_WHITE_SPACE_NEUTRAL_value; ZVAL_LONG(&const_CHAR_DIRECTION_WHITE_SPACE_NEUTRAL_value, U_WHITE_SPACE_NEUTRAL); - zend_string *const_CHAR_DIRECTION_WHITE_SPACE_NEUTRAL_name = zend_string_init_interned("CHAR_DIRECTION_WHITE_SPACE_NEUTRAL", sizeof("CHAR_DIRECTION_WHITE_SPACE_NEUTRAL") - 1, 1); + zend_string *const_CHAR_DIRECTION_WHITE_SPACE_NEUTRAL_name = zend_string_init_interned("CHAR_DIRECTION_WHITE_SPACE_NEUTRAL", sizeof("CHAR_DIRECTION_WHITE_SPACE_NEUTRAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_WHITE_SPACE_NEUTRAL_name, &const_CHAR_DIRECTION_WHITE_SPACE_NEUTRAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_WHITE_SPACE_NEUTRAL_name); + zend_string_release_ex(const_CHAR_DIRECTION_WHITE_SPACE_NEUTRAL_name, true); zval const_CHAR_DIRECTION_OTHER_NEUTRAL_value; ZVAL_LONG(&const_CHAR_DIRECTION_OTHER_NEUTRAL_value, U_OTHER_NEUTRAL); - zend_string *const_CHAR_DIRECTION_OTHER_NEUTRAL_name = zend_string_init_interned("CHAR_DIRECTION_OTHER_NEUTRAL", sizeof("CHAR_DIRECTION_OTHER_NEUTRAL") - 1, 1); + zend_string *const_CHAR_DIRECTION_OTHER_NEUTRAL_name = zend_string_init_interned("CHAR_DIRECTION_OTHER_NEUTRAL", sizeof("CHAR_DIRECTION_OTHER_NEUTRAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_OTHER_NEUTRAL_name, &const_CHAR_DIRECTION_OTHER_NEUTRAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_OTHER_NEUTRAL_name); + zend_string_release_ex(const_CHAR_DIRECTION_OTHER_NEUTRAL_name, true); zval const_CHAR_DIRECTION_LEFT_TO_RIGHT_EMBEDDING_value; ZVAL_LONG(&const_CHAR_DIRECTION_LEFT_TO_RIGHT_EMBEDDING_value, U_LEFT_TO_RIGHT_EMBEDDING); - zend_string *const_CHAR_DIRECTION_LEFT_TO_RIGHT_EMBEDDING_name = zend_string_init_interned("CHAR_DIRECTION_LEFT_TO_RIGHT_EMBEDDING", sizeof("CHAR_DIRECTION_LEFT_TO_RIGHT_EMBEDDING") - 1, 1); + zend_string *const_CHAR_DIRECTION_LEFT_TO_RIGHT_EMBEDDING_name = zend_string_init_interned("CHAR_DIRECTION_LEFT_TO_RIGHT_EMBEDDING", sizeof("CHAR_DIRECTION_LEFT_TO_RIGHT_EMBEDDING") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_LEFT_TO_RIGHT_EMBEDDING_name, &const_CHAR_DIRECTION_LEFT_TO_RIGHT_EMBEDDING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_LEFT_TO_RIGHT_EMBEDDING_name); + zend_string_release_ex(const_CHAR_DIRECTION_LEFT_TO_RIGHT_EMBEDDING_name, true); zval const_CHAR_DIRECTION_LEFT_TO_RIGHT_OVERRIDE_value; ZVAL_LONG(&const_CHAR_DIRECTION_LEFT_TO_RIGHT_OVERRIDE_value, U_LEFT_TO_RIGHT_OVERRIDE); - zend_string *const_CHAR_DIRECTION_LEFT_TO_RIGHT_OVERRIDE_name = zend_string_init_interned("CHAR_DIRECTION_LEFT_TO_RIGHT_OVERRIDE", sizeof("CHAR_DIRECTION_LEFT_TO_RIGHT_OVERRIDE") - 1, 1); + zend_string *const_CHAR_DIRECTION_LEFT_TO_RIGHT_OVERRIDE_name = zend_string_init_interned("CHAR_DIRECTION_LEFT_TO_RIGHT_OVERRIDE", sizeof("CHAR_DIRECTION_LEFT_TO_RIGHT_OVERRIDE") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_LEFT_TO_RIGHT_OVERRIDE_name, &const_CHAR_DIRECTION_LEFT_TO_RIGHT_OVERRIDE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_LEFT_TO_RIGHT_OVERRIDE_name); + zend_string_release_ex(const_CHAR_DIRECTION_LEFT_TO_RIGHT_OVERRIDE_name, true); zval const_CHAR_DIRECTION_RIGHT_TO_LEFT_ARABIC_value; ZVAL_LONG(&const_CHAR_DIRECTION_RIGHT_TO_LEFT_ARABIC_value, U_RIGHT_TO_LEFT_ARABIC); - zend_string *const_CHAR_DIRECTION_RIGHT_TO_LEFT_ARABIC_name = zend_string_init_interned("CHAR_DIRECTION_RIGHT_TO_LEFT_ARABIC", sizeof("CHAR_DIRECTION_RIGHT_TO_LEFT_ARABIC") - 1, 1); + zend_string *const_CHAR_DIRECTION_RIGHT_TO_LEFT_ARABIC_name = zend_string_init_interned("CHAR_DIRECTION_RIGHT_TO_LEFT_ARABIC", sizeof("CHAR_DIRECTION_RIGHT_TO_LEFT_ARABIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_RIGHT_TO_LEFT_ARABIC_name, &const_CHAR_DIRECTION_RIGHT_TO_LEFT_ARABIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_RIGHT_TO_LEFT_ARABIC_name); + zend_string_release_ex(const_CHAR_DIRECTION_RIGHT_TO_LEFT_ARABIC_name, true); zval const_CHAR_DIRECTION_RIGHT_TO_LEFT_EMBEDDING_value; ZVAL_LONG(&const_CHAR_DIRECTION_RIGHT_TO_LEFT_EMBEDDING_value, U_RIGHT_TO_LEFT_EMBEDDING); - zend_string *const_CHAR_DIRECTION_RIGHT_TO_LEFT_EMBEDDING_name = zend_string_init_interned("CHAR_DIRECTION_RIGHT_TO_LEFT_EMBEDDING", sizeof("CHAR_DIRECTION_RIGHT_TO_LEFT_EMBEDDING") - 1, 1); + zend_string *const_CHAR_DIRECTION_RIGHT_TO_LEFT_EMBEDDING_name = zend_string_init_interned("CHAR_DIRECTION_RIGHT_TO_LEFT_EMBEDDING", sizeof("CHAR_DIRECTION_RIGHT_TO_LEFT_EMBEDDING") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_RIGHT_TO_LEFT_EMBEDDING_name, &const_CHAR_DIRECTION_RIGHT_TO_LEFT_EMBEDDING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_RIGHT_TO_LEFT_EMBEDDING_name); + zend_string_release_ex(const_CHAR_DIRECTION_RIGHT_TO_LEFT_EMBEDDING_name, true); zval const_CHAR_DIRECTION_RIGHT_TO_LEFT_OVERRIDE_value; ZVAL_LONG(&const_CHAR_DIRECTION_RIGHT_TO_LEFT_OVERRIDE_value, U_RIGHT_TO_LEFT_OVERRIDE); - zend_string *const_CHAR_DIRECTION_RIGHT_TO_LEFT_OVERRIDE_name = zend_string_init_interned("CHAR_DIRECTION_RIGHT_TO_LEFT_OVERRIDE", sizeof("CHAR_DIRECTION_RIGHT_TO_LEFT_OVERRIDE") - 1, 1); + zend_string *const_CHAR_DIRECTION_RIGHT_TO_LEFT_OVERRIDE_name = zend_string_init_interned("CHAR_DIRECTION_RIGHT_TO_LEFT_OVERRIDE", sizeof("CHAR_DIRECTION_RIGHT_TO_LEFT_OVERRIDE") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_RIGHT_TO_LEFT_OVERRIDE_name, &const_CHAR_DIRECTION_RIGHT_TO_LEFT_OVERRIDE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_RIGHT_TO_LEFT_OVERRIDE_name); + zend_string_release_ex(const_CHAR_DIRECTION_RIGHT_TO_LEFT_OVERRIDE_name, true); zval const_CHAR_DIRECTION_POP_DIRECTIONAL_FORMAT_value; ZVAL_LONG(&const_CHAR_DIRECTION_POP_DIRECTIONAL_FORMAT_value, U_POP_DIRECTIONAL_FORMAT); - zend_string *const_CHAR_DIRECTION_POP_DIRECTIONAL_FORMAT_name = zend_string_init_interned("CHAR_DIRECTION_POP_DIRECTIONAL_FORMAT", sizeof("CHAR_DIRECTION_POP_DIRECTIONAL_FORMAT") - 1, 1); + zend_string *const_CHAR_DIRECTION_POP_DIRECTIONAL_FORMAT_name = zend_string_init_interned("CHAR_DIRECTION_POP_DIRECTIONAL_FORMAT", sizeof("CHAR_DIRECTION_POP_DIRECTIONAL_FORMAT") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_POP_DIRECTIONAL_FORMAT_name, &const_CHAR_DIRECTION_POP_DIRECTIONAL_FORMAT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_POP_DIRECTIONAL_FORMAT_name); + zend_string_release_ex(const_CHAR_DIRECTION_POP_DIRECTIONAL_FORMAT_name, true); zval const_CHAR_DIRECTION_DIR_NON_SPACING_MARK_value; ZVAL_LONG(&const_CHAR_DIRECTION_DIR_NON_SPACING_MARK_value, U_DIR_NON_SPACING_MARK); - zend_string *const_CHAR_DIRECTION_DIR_NON_SPACING_MARK_name = zend_string_init_interned("CHAR_DIRECTION_DIR_NON_SPACING_MARK", sizeof("CHAR_DIRECTION_DIR_NON_SPACING_MARK") - 1, 1); + zend_string *const_CHAR_DIRECTION_DIR_NON_SPACING_MARK_name = zend_string_init_interned("CHAR_DIRECTION_DIR_NON_SPACING_MARK", sizeof("CHAR_DIRECTION_DIR_NON_SPACING_MARK") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_DIR_NON_SPACING_MARK_name, &const_CHAR_DIRECTION_DIR_NON_SPACING_MARK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_DIR_NON_SPACING_MARK_name); + zend_string_release_ex(const_CHAR_DIRECTION_DIR_NON_SPACING_MARK_name, true); zval const_CHAR_DIRECTION_BOUNDARY_NEUTRAL_value; ZVAL_LONG(&const_CHAR_DIRECTION_BOUNDARY_NEUTRAL_value, U_BOUNDARY_NEUTRAL); - zend_string *const_CHAR_DIRECTION_BOUNDARY_NEUTRAL_name = zend_string_init_interned("CHAR_DIRECTION_BOUNDARY_NEUTRAL", sizeof("CHAR_DIRECTION_BOUNDARY_NEUTRAL") - 1, 1); + zend_string *const_CHAR_DIRECTION_BOUNDARY_NEUTRAL_name = zend_string_init_interned("CHAR_DIRECTION_BOUNDARY_NEUTRAL", sizeof("CHAR_DIRECTION_BOUNDARY_NEUTRAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_BOUNDARY_NEUTRAL_name, &const_CHAR_DIRECTION_BOUNDARY_NEUTRAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_BOUNDARY_NEUTRAL_name); + zend_string_release_ex(const_CHAR_DIRECTION_BOUNDARY_NEUTRAL_name, true); zval const_CHAR_DIRECTION_FIRST_STRONG_ISOLATE_value; ZVAL_LONG(&const_CHAR_DIRECTION_FIRST_STRONG_ISOLATE_value, U_FIRST_STRONG_ISOLATE); - zend_string *const_CHAR_DIRECTION_FIRST_STRONG_ISOLATE_name = zend_string_init_interned("CHAR_DIRECTION_FIRST_STRONG_ISOLATE", sizeof("CHAR_DIRECTION_FIRST_STRONG_ISOLATE") - 1, 1); + zend_string *const_CHAR_DIRECTION_FIRST_STRONG_ISOLATE_name = zend_string_init_interned("CHAR_DIRECTION_FIRST_STRONG_ISOLATE", sizeof("CHAR_DIRECTION_FIRST_STRONG_ISOLATE") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_FIRST_STRONG_ISOLATE_name, &const_CHAR_DIRECTION_FIRST_STRONG_ISOLATE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_FIRST_STRONG_ISOLATE_name); + zend_string_release_ex(const_CHAR_DIRECTION_FIRST_STRONG_ISOLATE_name, true); zval const_CHAR_DIRECTION_LEFT_TO_RIGHT_ISOLATE_value; ZVAL_LONG(&const_CHAR_DIRECTION_LEFT_TO_RIGHT_ISOLATE_value, U_LEFT_TO_RIGHT_ISOLATE); - zend_string *const_CHAR_DIRECTION_LEFT_TO_RIGHT_ISOLATE_name = zend_string_init_interned("CHAR_DIRECTION_LEFT_TO_RIGHT_ISOLATE", sizeof("CHAR_DIRECTION_LEFT_TO_RIGHT_ISOLATE") - 1, 1); + zend_string *const_CHAR_DIRECTION_LEFT_TO_RIGHT_ISOLATE_name = zend_string_init_interned("CHAR_DIRECTION_LEFT_TO_RIGHT_ISOLATE", sizeof("CHAR_DIRECTION_LEFT_TO_RIGHT_ISOLATE") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_LEFT_TO_RIGHT_ISOLATE_name, &const_CHAR_DIRECTION_LEFT_TO_RIGHT_ISOLATE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_LEFT_TO_RIGHT_ISOLATE_name); + zend_string_release_ex(const_CHAR_DIRECTION_LEFT_TO_RIGHT_ISOLATE_name, true); zval const_CHAR_DIRECTION_RIGHT_TO_LEFT_ISOLATE_value; ZVAL_LONG(&const_CHAR_DIRECTION_RIGHT_TO_LEFT_ISOLATE_value, U_RIGHT_TO_LEFT_ISOLATE); - zend_string *const_CHAR_DIRECTION_RIGHT_TO_LEFT_ISOLATE_name = zend_string_init_interned("CHAR_DIRECTION_RIGHT_TO_LEFT_ISOLATE", sizeof("CHAR_DIRECTION_RIGHT_TO_LEFT_ISOLATE") - 1, 1); + zend_string *const_CHAR_DIRECTION_RIGHT_TO_LEFT_ISOLATE_name = zend_string_init_interned("CHAR_DIRECTION_RIGHT_TO_LEFT_ISOLATE", sizeof("CHAR_DIRECTION_RIGHT_TO_LEFT_ISOLATE") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_RIGHT_TO_LEFT_ISOLATE_name, &const_CHAR_DIRECTION_RIGHT_TO_LEFT_ISOLATE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_RIGHT_TO_LEFT_ISOLATE_name); + zend_string_release_ex(const_CHAR_DIRECTION_RIGHT_TO_LEFT_ISOLATE_name, true); zval const_CHAR_DIRECTION_POP_DIRECTIONAL_ISOLATE_value; ZVAL_LONG(&const_CHAR_DIRECTION_POP_DIRECTIONAL_ISOLATE_value, U_POP_DIRECTIONAL_ISOLATE); - zend_string *const_CHAR_DIRECTION_POP_DIRECTIONAL_ISOLATE_name = zend_string_init_interned("CHAR_DIRECTION_POP_DIRECTIONAL_ISOLATE", sizeof("CHAR_DIRECTION_POP_DIRECTIONAL_ISOLATE") - 1, 1); + zend_string *const_CHAR_DIRECTION_POP_DIRECTIONAL_ISOLATE_name = zend_string_init_interned("CHAR_DIRECTION_POP_DIRECTIONAL_ISOLATE", sizeof("CHAR_DIRECTION_POP_DIRECTIONAL_ISOLATE") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_POP_DIRECTIONAL_ISOLATE_name, &const_CHAR_DIRECTION_POP_DIRECTIONAL_ISOLATE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_POP_DIRECTIONAL_ISOLATE_name); + zend_string_release_ex(const_CHAR_DIRECTION_POP_DIRECTIONAL_ISOLATE_name, true); zval const_CHAR_DIRECTION_CHAR_DIRECTION_COUNT_value; ZVAL_LONG(&const_CHAR_DIRECTION_CHAR_DIRECTION_COUNT_value, U_CHAR_DIRECTION_COUNT); - zend_string *const_CHAR_DIRECTION_CHAR_DIRECTION_COUNT_name = zend_string_init_interned("CHAR_DIRECTION_CHAR_DIRECTION_COUNT", sizeof("CHAR_DIRECTION_CHAR_DIRECTION_COUNT") - 1, 1); + zend_string *const_CHAR_DIRECTION_CHAR_DIRECTION_COUNT_name = zend_string_init_interned("CHAR_DIRECTION_CHAR_DIRECTION_COUNT", sizeof("CHAR_DIRECTION_CHAR_DIRECTION_COUNT") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_DIRECTION_CHAR_DIRECTION_COUNT_name, &const_CHAR_DIRECTION_CHAR_DIRECTION_COUNT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_DIRECTION_CHAR_DIRECTION_COUNT_name); + zend_string_release_ex(const_CHAR_DIRECTION_CHAR_DIRECTION_COUNT_name, true); zval const_BLOCK_CODE_NO_BLOCK_value; ZVAL_LONG(&const_BLOCK_CODE_NO_BLOCK_value, UBLOCK_NO_BLOCK); - zend_string *const_BLOCK_CODE_NO_BLOCK_name = zend_string_init_interned("BLOCK_CODE_NO_BLOCK", sizeof("BLOCK_CODE_NO_BLOCK") - 1, 1); + zend_string *const_BLOCK_CODE_NO_BLOCK_name = zend_string_init_interned("BLOCK_CODE_NO_BLOCK", sizeof("BLOCK_CODE_NO_BLOCK") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_NO_BLOCK_name, &const_BLOCK_CODE_NO_BLOCK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_NO_BLOCK_name); + zend_string_release_ex(const_BLOCK_CODE_NO_BLOCK_name, true); zval const_BLOCK_CODE_BASIC_LATIN_value; ZVAL_LONG(&const_BLOCK_CODE_BASIC_LATIN_value, UBLOCK_BASIC_LATIN); - zend_string *const_BLOCK_CODE_BASIC_LATIN_name = zend_string_init_interned("BLOCK_CODE_BASIC_LATIN", sizeof("BLOCK_CODE_BASIC_LATIN") - 1, 1); + zend_string *const_BLOCK_CODE_BASIC_LATIN_name = zend_string_init_interned("BLOCK_CODE_BASIC_LATIN", sizeof("BLOCK_CODE_BASIC_LATIN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_BASIC_LATIN_name, &const_BLOCK_CODE_BASIC_LATIN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_BASIC_LATIN_name); + zend_string_release_ex(const_BLOCK_CODE_BASIC_LATIN_name, true); zval const_BLOCK_CODE_LATIN_1_SUPPLEMENT_value; ZVAL_LONG(&const_BLOCK_CODE_LATIN_1_SUPPLEMENT_value, UBLOCK_LATIN_1_SUPPLEMENT); - zend_string *const_BLOCK_CODE_LATIN_1_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_LATIN_1_SUPPLEMENT", sizeof("BLOCK_CODE_LATIN_1_SUPPLEMENT") - 1, 1); + zend_string *const_BLOCK_CODE_LATIN_1_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_LATIN_1_SUPPLEMENT", sizeof("BLOCK_CODE_LATIN_1_SUPPLEMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_LATIN_1_SUPPLEMENT_name, &const_BLOCK_CODE_LATIN_1_SUPPLEMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_LATIN_1_SUPPLEMENT_name); + zend_string_release_ex(const_BLOCK_CODE_LATIN_1_SUPPLEMENT_name, true); zval const_BLOCK_CODE_LATIN_EXTENDED_A_value; ZVAL_LONG(&const_BLOCK_CODE_LATIN_EXTENDED_A_value, UBLOCK_LATIN_EXTENDED_A); - zend_string *const_BLOCK_CODE_LATIN_EXTENDED_A_name = zend_string_init_interned("BLOCK_CODE_LATIN_EXTENDED_A", sizeof("BLOCK_CODE_LATIN_EXTENDED_A") - 1, 1); + zend_string *const_BLOCK_CODE_LATIN_EXTENDED_A_name = zend_string_init_interned("BLOCK_CODE_LATIN_EXTENDED_A", sizeof("BLOCK_CODE_LATIN_EXTENDED_A") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_LATIN_EXTENDED_A_name, &const_BLOCK_CODE_LATIN_EXTENDED_A_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_LATIN_EXTENDED_A_name); + zend_string_release_ex(const_BLOCK_CODE_LATIN_EXTENDED_A_name, true); zval const_BLOCK_CODE_LATIN_EXTENDED_B_value; ZVAL_LONG(&const_BLOCK_CODE_LATIN_EXTENDED_B_value, UBLOCK_LATIN_EXTENDED_B); - zend_string *const_BLOCK_CODE_LATIN_EXTENDED_B_name = zend_string_init_interned("BLOCK_CODE_LATIN_EXTENDED_B", sizeof("BLOCK_CODE_LATIN_EXTENDED_B") - 1, 1); + zend_string *const_BLOCK_CODE_LATIN_EXTENDED_B_name = zend_string_init_interned("BLOCK_CODE_LATIN_EXTENDED_B", sizeof("BLOCK_CODE_LATIN_EXTENDED_B") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_LATIN_EXTENDED_B_name, &const_BLOCK_CODE_LATIN_EXTENDED_B_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_LATIN_EXTENDED_B_name); + zend_string_release_ex(const_BLOCK_CODE_LATIN_EXTENDED_B_name, true); zval const_BLOCK_CODE_IPA_EXTENSIONS_value; ZVAL_LONG(&const_BLOCK_CODE_IPA_EXTENSIONS_value, UBLOCK_IPA_EXTENSIONS); - zend_string *const_BLOCK_CODE_IPA_EXTENSIONS_name = zend_string_init_interned("BLOCK_CODE_IPA_EXTENSIONS", sizeof("BLOCK_CODE_IPA_EXTENSIONS") - 1, 1); + zend_string *const_BLOCK_CODE_IPA_EXTENSIONS_name = zend_string_init_interned("BLOCK_CODE_IPA_EXTENSIONS", sizeof("BLOCK_CODE_IPA_EXTENSIONS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_IPA_EXTENSIONS_name, &const_BLOCK_CODE_IPA_EXTENSIONS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_IPA_EXTENSIONS_name); + zend_string_release_ex(const_BLOCK_CODE_IPA_EXTENSIONS_name, true); zval const_BLOCK_CODE_SPACING_MODIFIER_LETTERS_value; ZVAL_LONG(&const_BLOCK_CODE_SPACING_MODIFIER_LETTERS_value, UBLOCK_SPACING_MODIFIER_LETTERS); - zend_string *const_BLOCK_CODE_SPACING_MODIFIER_LETTERS_name = zend_string_init_interned("BLOCK_CODE_SPACING_MODIFIER_LETTERS", sizeof("BLOCK_CODE_SPACING_MODIFIER_LETTERS") - 1, 1); + zend_string *const_BLOCK_CODE_SPACING_MODIFIER_LETTERS_name = zend_string_init_interned("BLOCK_CODE_SPACING_MODIFIER_LETTERS", sizeof("BLOCK_CODE_SPACING_MODIFIER_LETTERS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SPACING_MODIFIER_LETTERS_name, &const_BLOCK_CODE_SPACING_MODIFIER_LETTERS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SPACING_MODIFIER_LETTERS_name); + zend_string_release_ex(const_BLOCK_CODE_SPACING_MODIFIER_LETTERS_name, true); zval const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_value; ZVAL_LONG(&const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_value, UBLOCK_COMBINING_DIACRITICAL_MARKS); - zend_string *const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_name = zend_string_init_interned("BLOCK_CODE_COMBINING_DIACRITICAL_MARKS", sizeof("BLOCK_CODE_COMBINING_DIACRITICAL_MARKS") - 1, 1); + zend_string *const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_name = zend_string_init_interned("BLOCK_CODE_COMBINING_DIACRITICAL_MARKS", sizeof("BLOCK_CODE_COMBINING_DIACRITICAL_MARKS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_name, &const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_name); + zend_string_release_ex(const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_name, true); zval const_BLOCK_CODE_GREEK_value; ZVAL_LONG(&const_BLOCK_CODE_GREEK_value, UBLOCK_GREEK); - zend_string *const_BLOCK_CODE_GREEK_name = zend_string_init_interned("BLOCK_CODE_GREEK", sizeof("BLOCK_CODE_GREEK") - 1, 1); + zend_string *const_BLOCK_CODE_GREEK_name = zend_string_init_interned("BLOCK_CODE_GREEK", sizeof("BLOCK_CODE_GREEK") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_GREEK_name, &const_BLOCK_CODE_GREEK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_GREEK_name); + zend_string_release_ex(const_BLOCK_CODE_GREEK_name, true); zval const_BLOCK_CODE_CYRILLIC_value; ZVAL_LONG(&const_BLOCK_CODE_CYRILLIC_value, UBLOCK_CYRILLIC); - zend_string *const_BLOCK_CODE_CYRILLIC_name = zend_string_init_interned("BLOCK_CODE_CYRILLIC", sizeof("BLOCK_CODE_CYRILLIC") - 1, 1); + zend_string *const_BLOCK_CODE_CYRILLIC_name = zend_string_init_interned("BLOCK_CODE_CYRILLIC", sizeof("BLOCK_CODE_CYRILLIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CYRILLIC_name, &const_BLOCK_CODE_CYRILLIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CYRILLIC_name); + zend_string_release_ex(const_BLOCK_CODE_CYRILLIC_name, true); zval const_BLOCK_CODE_ARMENIAN_value; ZVAL_LONG(&const_BLOCK_CODE_ARMENIAN_value, UBLOCK_ARMENIAN); - zend_string *const_BLOCK_CODE_ARMENIAN_name = zend_string_init_interned("BLOCK_CODE_ARMENIAN", sizeof("BLOCK_CODE_ARMENIAN") - 1, 1); + zend_string *const_BLOCK_CODE_ARMENIAN_name = zend_string_init_interned("BLOCK_CODE_ARMENIAN", sizeof("BLOCK_CODE_ARMENIAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ARMENIAN_name, &const_BLOCK_CODE_ARMENIAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ARMENIAN_name); + zend_string_release_ex(const_BLOCK_CODE_ARMENIAN_name, true); zval const_BLOCK_CODE_HEBREW_value; ZVAL_LONG(&const_BLOCK_CODE_HEBREW_value, UBLOCK_HEBREW); - zend_string *const_BLOCK_CODE_HEBREW_name = zend_string_init_interned("BLOCK_CODE_HEBREW", sizeof("BLOCK_CODE_HEBREW") - 1, 1); + zend_string *const_BLOCK_CODE_HEBREW_name = zend_string_init_interned("BLOCK_CODE_HEBREW", sizeof("BLOCK_CODE_HEBREW") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_HEBREW_name, &const_BLOCK_CODE_HEBREW_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_HEBREW_name); + zend_string_release_ex(const_BLOCK_CODE_HEBREW_name, true); zval const_BLOCK_CODE_ARABIC_value; ZVAL_LONG(&const_BLOCK_CODE_ARABIC_value, UBLOCK_ARABIC); - zend_string *const_BLOCK_CODE_ARABIC_name = zend_string_init_interned("BLOCK_CODE_ARABIC", sizeof("BLOCK_CODE_ARABIC") - 1, 1); + zend_string *const_BLOCK_CODE_ARABIC_name = zend_string_init_interned("BLOCK_CODE_ARABIC", sizeof("BLOCK_CODE_ARABIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ARABIC_name, &const_BLOCK_CODE_ARABIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ARABIC_name); + zend_string_release_ex(const_BLOCK_CODE_ARABIC_name, true); zval const_BLOCK_CODE_SYRIAC_value; ZVAL_LONG(&const_BLOCK_CODE_SYRIAC_value, UBLOCK_SYRIAC); - zend_string *const_BLOCK_CODE_SYRIAC_name = zend_string_init_interned("BLOCK_CODE_SYRIAC", sizeof("BLOCK_CODE_SYRIAC") - 1, 1); + zend_string *const_BLOCK_CODE_SYRIAC_name = zend_string_init_interned("BLOCK_CODE_SYRIAC", sizeof("BLOCK_CODE_SYRIAC") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SYRIAC_name, &const_BLOCK_CODE_SYRIAC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SYRIAC_name); + zend_string_release_ex(const_BLOCK_CODE_SYRIAC_name, true); zval const_BLOCK_CODE_THAANA_value; ZVAL_LONG(&const_BLOCK_CODE_THAANA_value, UBLOCK_THAANA); - zend_string *const_BLOCK_CODE_THAANA_name = zend_string_init_interned("BLOCK_CODE_THAANA", sizeof("BLOCK_CODE_THAANA") - 1, 1); + zend_string *const_BLOCK_CODE_THAANA_name = zend_string_init_interned("BLOCK_CODE_THAANA", sizeof("BLOCK_CODE_THAANA") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_THAANA_name, &const_BLOCK_CODE_THAANA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_THAANA_name); + zend_string_release_ex(const_BLOCK_CODE_THAANA_name, true); zval const_BLOCK_CODE_DEVANAGARI_value; ZVAL_LONG(&const_BLOCK_CODE_DEVANAGARI_value, UBLOCK_DEVANAGARI); - zend_string *const_BLOCK_CODE_DEVANAGARI_name = zend_string_init_interned("BLOCK_CODE_DEVANAGARI", sizeof("BLOCK_CODE_DEVANAGARI") - 1, 1); + zend_string *const_BLOCK_CODE_DEVANAGARI_name = zend_string_init_interned("BLOCK_CODE_DEVANAGARI", sizeof("BLOCK_CODE_DEVANAGARI") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_DEVANAGARI_name, &const_BLOCK_CODE_DEVANAGARI_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_DEVANAGARI_name); + zend_string_release_ex(const_BLOCK_CODE_DEVANAGARI_name, true); zval const_BLOCK_CODE_BENGALI_value; ZVAL_LONG(&const_BLOCK_CODE_BENGALI_value, UBLOCK_BENGALI); - zend_string *const_BLOCK_CODE_BENGALI_name = zend_string_init_interned("BLOCK_CODE_BENGALI", sizeof("BLOCK_CODE_BENGALI") - 1, 1); + zend_string *const_BLOCK_CODE_BENGALI_name = zend_string_init_interned("BLOCK_CODE_BENGALI", sizeof("BLOCK_CODE_BENGALI") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_BENGALI_name, &const_BLOCK_CODE_BENGALI_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_BENGALI_name); + zend_string_release_ex(const_BLOCK_CODE_BENGALI_name, true); zval const_BLOCK_CODE_GURMUKHI_value; ZVAL_LONG(&const_BLOCK_CODE_GURMUKHI_value, UBLOCK_GURMUKHI); - zend_string *const_BLOCK_CODE_GURMUKHI_name = zend_string_init_interned("BLOCK_CODE_GURMUKHI", sizeof("BLOCK_CODE_GURMUKHI") - 1, 1); + zend_string *const_BLOCK_CODE_GURMUKHI_name = zend_string_init_interned("BLOCK_CODE_GURMUKHI", sizeof("BLOCK_CODE_GURMUKHI") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_GURMUKHI_name, &const_BLOCK_CODE_GURMUKHI_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_GURMUKHI_name); + zend_string_release_ex(const_BLOCK_CODE_GURMUKHI_name, true); zval const_BLOCK_CODE_GUJARATI_value; ZVAL_LONG(&const_BLOCK_CODE_GUJARATI_value, UBLOCK_GUJARATI); - zend_string *const_BLOCK_CODE_GUJARATI_name = zend_string_init_interned("BLOCK_CODE_GUJARATI", sizeof("BLOCK_CODE_GUJARATI") - 1, 1); + zend_string *const_BLOCK_CODE_GUJARATI_name = zend_string_init_interned("BLOCK_CODE_GUJARATI", sizeof("BLOCK_CODE_GUJARATI") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_GUJARATI_name, &const_BLOCK_CODE_GUJARATI_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_GUJARATI_name); + zend_string_release_ex(const_BLOCK_CODE_GUJARATI_name, true); zval const_BLOCK_CODE_ORIYA_value; ZVAL_LONG(&const_BLOCK_CODE_ORIYA_value, UBLOCK_ORIYA); - zend_string *const_BLOCK_CODE_ORIYA_name = zend_string_init_interned("BLOCK_CODE_ORIYA", sizeof("BLOCK_CODE_ORIYA") - 1, 1); + zend_string *const_BLOCK_CODE_ORIYA_name = zend_string_init_interned("BLOCK_CODE_ORIYA", sizeof("BLOCK_CODE_ORIYA") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ORIYA_name, &const_BLOCK_CODE_ORIYA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ORIYA_name); + zend_string_release_ex(const_BLOCK_CODE_ORIYA_name, true); zval const_BLOCK_CODE_TAMIL_value; ZVAL_LONG(&const_BLOCK_CODE_TAMIL_value, UBLOCK_TAMIL); - zend_string *const_BLOCK_CODE_TAMIL_name = zend_string_init_interned("BLOCK_CODE_TAMIL", sizeof("BLOCK_CODE_TAMIL") - 1, 1); + zend_string *const_BLOCK_CODE_TAMIL_name = zend_string_init_interned("BLOCK_CODE_TAMIL", sizeof("BLOCK_CODE_TAMIL") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_TAMIL_name, &const_BLOCK_CODE_TAMIL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_TAMIL_name); + zend_string_release_ex(const_BLOCK_CODE_TAMIL_name, true); zval const_BLOCK_CODE_TELUGU_value; ZVAL_LONG(&const_BLOCK_CODE_TELUGU_value, UBLOCK_TELUGU); - zend_string *const_BLOCK_CODE_TELUGU_name = zend_string_init_interned("BLOCK_CODE_TELUGU", sizeof("BLOCK_CODE_TELUGU") - 1, 1); + zend_string *const_BLOCK_CODE_TELUGU_name = zend_string_init_interned("BLOCK_CODE_TELUGU", sizeof("BLOCK_CODE_TELUGU") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_TELUGU_name, &const_BLOCK_CODE_TELUGU_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_TELUGU_name); + zend_string_release_ex(const_BLOCK_CODE_TELUGU_name, true); zval const_BLOCK_CODE_KANNADA_value; ZVAL_LONG(&const_BLOCK_CODE_KANNADA_value, UBLOCK_KANNADA); - zend_string *const_BLOCK_CODE_KANNADA_name = zend_string_init_interned("BLOCK_CODE_KANNADA", sizeof("BLOCK_CODE_KANNADA") - 1, 1); + zend_string *const_BLOCK_CODE_KANNADA_name = zend_string_init_interned("BLOCK_CODE_KANNADA", sizeof("BLOCK_CODE_KANNADA") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_KANNADA_name, &const_BLOCK_CODE_KANNADA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_KANNADA_name); + zend_string_release_ex(const_BLOCK_CODE_KANNADA_name, true); zval const_BLOCK_CODE_MALAYALAM_value; ZVAL_LONG(&const_BLOCK_CODE_MALAYALAM_value, UBLOCK_MALAYALAM); - zend_string *const_BLOCK_CODE_MALAYALAM_name = zend_string_init_interned("BLOCK_CODE_MALAYALAM", sizeof("BLOCK_CODE_MALAYALAM") - 1, 1); + zend_string *const_BLOCK_CODE_MALAYALAM_name = zend_string_init_interned("BLOCK_CODE_MALAYALAM", sizeof("BLOCK_CODE_MALAYALAM") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MALAYALAM_name, &const_BLOCK_CODE_MALAYALAM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MALAYALAM_name); + zend_string_release_ex(const_BLOCK_CODE_MALAYALAM_name, true); zval const_BLOCK_CODE_SINHALA_value; ZVAL_LONG(&const_BLOCK_CODE_SINHALA_value, UBLOCK_SINHALA); - zend_string *const_BLOCK_CODE_SINHALA_name = zend_string_init_interned("BLOCK_CODE_SINHALA", sizeof("BLOCK_CODE_SINHALA") - 1, 1); + zend_string *const_BLOCK_CODE_SINHALA_name = zend_string_init_interned("BLOCK_CODE_SINHALA", sizeof("BLOCK_CODE_SINHALA") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SINHALA_name, &const_BLOCK_CODE_SINHALA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SINHALA_name); + zend_string_release_ex(const_BLOCK_CODE_SINHALA_name, true); zval const_BLOCK_CODE_THAI_value; ZVAL_LONG(&const_BLOCK_CODE_THAI_value, UBLOCK_THAI); - zend_string *const_BLOCK_CODE_THAI_name = zend_string_init_interned("BLOCK_CODE_THAI", sizeof("BLOCK_CODE_THAI") - 1, 1); + zend_string *const_BLOCK_CODE_THAI_name = zend_string_init_interned("BLOCK_CODE_THAI", sizeof("BLOCK_CODE_THAI") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_THAI_name, &const_BLOCK_CODE_THAI_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_THAI_name); + zend_string_release_ex(const_BLOCK_CODE_THAI_name, true); zval const_BLOCK_CODE_LAO_value; ZVAL_LONG(&const_BLOCK_CODE_LAO_value, UBLOCK_LAO); - zend_string *const_BLOCK_CODE_LAO_name = zend_string_init_interned("BLOCK_CODE_LAO", sizeof("BLOCK_CODE_LAO") - 1, 1); + zend_string *const_BLOCK_CODE_LAO_name = zend_string_init_interned("BLOCK_CODE_LAO", sizeof("BLOCK_CODE_LAO") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_LAO_name, &const_BLOCK_CODE_LAO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_LAO_name); + zend_string_release_ex(const_BLOCK_CODE_LAO_name, true); zval const_BLOCK_CODE_TIBETAN_value; ZVAL_LONG(&const_BLOCK_CODE_TIBETAN_value, UBLOCK_TIBETAN); - zend_string *const_BLOCK_CODE_TIBETAN_name = zend_string_init_interned("BLOCK_CODE_TIBETAN", sizeof("BLOCK_CODE_TIBETAN") - 1, 1); + zend_string *const_BLOCK_CODE_TIBETAN_name = zend_string_init_interned("BLOCK_CODE_TIBETAN", sizeof("BLOCK_CODE_TIBETAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_TIBETAN_name, &const_BLOCK_CODE_TIBETAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_TIBETAN_name); + zend_string_release_ex(const_BLOCK_CODE_TIBETAN_name, true); zval const_BLOCK_CODE_MYANMAR_value; ZVAL_LONG(&const_BLOCK_CODE_MYANMAR_value, UBLOCK_MYANMAR); - zend_string *const_BLOCK_CODE_MYANMAR_name = zend_string_init_interned("BLOCK_CODE_MYANMAR", sizeof("BLOCK_CODE_MYANMAR") - 1, 1); + zend_string *const_BLOCK_CODE_MYANMAR_name = zend_string_init_interned("BLOCK_CODE_MYANMAR", sizeof("BLOCK_CODE_MYANMAR") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MYANMAR_name, &const_BLOCK_CODE_MYANMAR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MYANMAR_name); + zend_string_release_ex(const_BLOCK_CODE_MYANMAR_name, true); zval const_BLOCK_CODE_GEORGIAN_value; ZVAL_LONG(&const_BLOCK_CODE_GEORGIAN_value, UBLOCK_GEORGIAN); - zend_string *const_BLOCK_CODE_GEORGIAN_name = zend_string_init_interned("BLOCK_CODE_GEORGIAN", sizeof("BLOCK_CODE_GEORGIAN") - 1, 1); + zend_string *const_BLOCK_CODE_GEORGIAN_name = zend_string_init_interned("BLOCK_CODE_GEORGIAN", sizeof("BLOCK_CODE_GEORGIAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_GEORGIAN_name, &const_BLOCK_CODE_GEORGIAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_GEORGIAN_name); + zend_string_release_ex(const_BLOCK_CODE_GEORGIAN_name, true); zval const_BLOCK_CODE_HANGUL_JAMO_value; ZVAL_LONG(&const_BLOCK_CODE_HANGUL_JAMO_value, UBLOCK_HANGUL_JAMO); - zend_string *const_BLOCK_CODE_HANGUL_JAMO_name = zend_string_init_interned("BLOCK_CODE_HANGUL_JAMO", sizeof("BLOCK_CODE_HANGUL_JAMO") - 1, 1); + zend_string *const_BLOCK_CODE_HANGUL_JAMO_name = zend_string_init_interned("BLOCK_CODE_HANGUL_JAMO", sizeof("BLOCK_CODE_HANGUL_JAMO") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_HANGUL_JAMO_name, &const_BLOCK_CODE_HANGUL_JAMO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_HANGUL_JAMO_name); + zend_string_release_ex(const_BLOCK_CODE_HANGUL_JAMO_name, true); zval const_BLOCK_CODE_ETHIOPIC_value; ZVAL_LONG(&const_BLOCK_CODE_ETHIOPIC_value, UBLOCK_ETHIOPIC); - zend_string *const_BLOCK_CODE_ETHIOPIC_name = zend_string_init_interned("BLOCK_CODE_ETHIOPIC", sizeof("BLOCK_CODE_ETHIOPIC") - 1, 1); + zend_string *const_BLOCK_CODE_ETHIOPIC_name = zend_string_init_interned("BLOCK_CODE_ETHIOPIC", sizeof("BLOCK_CODE_ETHIOPIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ETHIOPIC_name, &const_BLOCK_CODE_ETHIOPIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ETHIOPIC_name); + zend_string_release_ex(const_BLOCK_CODE_ETHIOPIC_name, true); zval const_BLOCK_CODE_CHEROKEE_value; ZVAL_LONG(&const_BLOCK_CODE_CHEROKEE_value, UBLOCK_CHEROKEE); - zend_string *const_BLOCK_CODE_CHEROKEE_name = zend_string_init_interned("BLOCK_CODE_CHEROKEE", sizeof("BLOCK_CODE_CHEROKEE") - 1, 1); + zend_string *const_BLOCK_CODE_CHEROKEE_name = zend_string_init_interned("BLOCK_CODE_CHEROKEE", sizeof("BLOCK_CODE_CHEROKEE") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CHEROKEE_name, &const_BLOCK_CODE_CHEROKEE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CHEROKEE_name); + zend_string_release_ex(const_BLOCK_CODE_CHEROKEE_name, true); zval const_BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_value; ZVAL_LONG(&const_BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_value, UBLOCK_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS); - zend_string *const_BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_name = zend_string_init_interned("BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS", sizeof("BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS") - 1, 1); + zend_string *const_BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_name = zend_string_init_interned("BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS", sizeof("BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_name, &const_BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_name); + zend_string_release_ex(const_BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_name, true); zval const_BLOCK_CODE_OGHAM_value; ZVAL_LONG(&const_BLOCK_CODE_OGHAM_value, UBLOCK_OGHAM); - zend_string *const_BLOCK_CODE_OGHAM_name = zend_string_init_interned("BLOCK_CODE_OGHAM", sizeof("BLOCK_CODE_OGHAM") - 1, 1); + zend_string *const_BLOCK_CODE_OGHAM_name = zend_string_init_interned("BLOCK_CODE_OGHAM", sizeof("BLOCK_CODE_OGHAM") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_OGHAM_name, &const_BLOCK_CODE_OGHAM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_OGHAM_name); + zend_string_release_ex(const_BLOCK_CODE_OGHAM_name, true); zval const_BLOCK_CODE_RUNIC_value; ZVAL_LONG(&const_BLOCK_CODE_RUNIC_value, UBLOCK_RUNIC); - zend_string *const_BLOCK_CODE_RUNIC_name = zend_string_init_interned("BLOCK_CODE_RUNIC", sizeof("BLOCK_CODE_RUNIC") - 1, 1); + zend_string *const_BLOCK_CODE_RUNIC_name = zend_string_init_interned("BLOCK_CODE_RUNIC", sizeof("BLOCK_CODE_RUNIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_RUNIC_name, &const_BLOCK_CODE_RUNIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_RUNIC_name); + zend_string_release_ex(const_BLOCK_CODE_RUNIC_name, true); zval const_BLOCK_CODE_KHMER_value; ZVAL_LONG(&const_BLOCK_CODE_KHMER_value, UBLOCK_KHMER); - zend_string *const_BLOCK_CODE_KHMER_name = zend_string_init_interned("BLOCK_CODE_KHMER", sizeof("BLOCK_CODE_KHMER") - 1, 1); + zend_string *const_BLOCK_CODE_KHMER_name = zend_string_init_interned("BLOCK_CODE_KHMER", sizeof("BLOCK_CODE_KHMER") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_KHMER_name, &const_BLOCK_CODE_KHMER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_KHMER_name); + zend_string_release_ex(const_BLOCK_CODE_KHMER_name, true); zval const_BLOCK_CODE_MONGOLIAN_value; ZVAL_LONG(&const_BLOCK_CODE_MONGOLIAN_value, UBLOCK_MONGOLIAN); - zend_string *const_BLOCK_CODE_MONGOLIAN_name = zend_string_init_interned("BLOCK_CODE_MONGOLIAN", sizeof("BLOCK_CODE_MONGOLIAN") - 1, 1); + zend_string *const_BLOCK_CODE_MONGOLIAN_name = zend_string_init_interned("BLOCK_CODE_MONGOLIAN", sizeof("BLOCK_CODE_MONGOLIAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MONGOLIAN_name, &const_BLOCK_CODE_MONGOLIAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MONGOLIAN_name); + zend_string_release_ex(const_BLOCK_CODE_MONGOLIAN_name, true); zval const_BLOCK_CODE_LATIN_EXTENDED_ADDITIONAL_value; ZVAL_LONG(&const_BLOCK_CODE_LATIN_EXTENDED_ADDITIONAL_value, UBLOCK_LATIN_EXTENDED_ADDITIONAL); - zend_string *const_BLOCK_CODE_LATIN_EXTENDED_ADDITIONAL_name = zend_string_init_interned("BLOCK_CODE_LATIN_EXTENDED_ADDITIONAL", sizeof("BLOCK_CODE_LATIN_EXTENDED_ADDITIONAL") - 1, 1); + zend_string *const_BLOCK_CODE_LATIN_EXTENDED_ADDITIONAL_name = zend_string_init_interned("BLOCK_CODE_LATIN_EXTENDED_ADDITIONAL", sizeof("BLOCK_CODE_LATIN_EXTENDED_ADDITIONAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_LATIN_EXTENDED_ADDITIONAL_name, &const_BLOCK_CODE_LATIN_EXTENDED_ADDITIONAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_LATIN_EXTENDED_ADDITIONAL_name); + zend_string_release_ex(const_BLOCK_CODE_LATIN_EXTENDED_ADDITIONAL_name, true); zval const_BLOCK_CODE_GREEK_EXTENDED_value; ZVAL_LONG(&const_BLOCK_CODE_GREEK_EXTENDED_value, UBLOCK_GREEK_EXTENDED); - zend_string *const_BLOCK_CODE_GREEK_EXTENDED_name = zend_string_init_interned("BLOCK_CODE_GREEK_EXTENDED", sizeof("BLOCK_CODE_GREEK_EXTENDED") - 1, 1); + zend_string *const_BLOCK_CODE_GREEK_EXTENDED_name = zend_string_init_interned("BLOCK_CODE_GREEK_EXTENDED", sizeof("BLOCK_CODE_GREEK_EXTENDED") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_GREEK_EXTENDED_name, &const_BLOCK_CODE_GREEK_EXTENDED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_GREEK_EXTENDED_name); + zend_string_release_ex(const_BLOCK_CODE_GREEK_EXTENDED_name, true); zval const_BLOCK_CODE_GENERAL_PUNCTUATION_value; ZVAL_LONG(&const_BLOCK_CODE_GENERAL_PUNCTUATION_value, UBLOCK_GENERAL_PUNCTUATION); - zend_string *const_BLOCK_CODE_GENERAL_PUNCTUATION_name = zend_string_init_interned("BLOCK_CODE_GENERAL_PUNCTUATION", sizeof("BLOCK_CODE_GENERAL_PUNCTUATION") - 1, 1); + zend_string *const_BLOCK_CODE_GENERAL_PUNCTUATION_name = zend_string_init_interned("BLOCK_CODE_GENERAL_PUNCTUATION", sizeof("BLOCK_CODE_GENERAL_PUNCTUATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_GENERAL_PUNCTUATION_name, &const_BLOCK_CODE_GENERAL_PUNCTUATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_GENERAL_PUNCTUATION_name); + zend_string_release_ex(const_BLOCK_CODE_GENERAL_PUNCTUATION_name, true); zval const_BLOCK_CODE_SUPERSCRIPTS_AND_SUBSCRIPTS_value; ZVAL_LONG(&const_BLOCK_CODE_SUPERSCRIPTS_AND_SUBSCRIPTS_value, UBLOCK_SUPERSCRIPTS_AND_SUBSCRIPTS); - zend_string *const_BLOCK_CODE_SUPERSCRIPTS_AND_SUBSCRIPTS_name = zend_string_init_interned("BLOCK_CODE_SUPERSCRIPTS_AND_SUBSCRIPTS", sizeof("BLOCK_CODE_SUPERSCRIPTS_AND_SUBSCRIPTS") - 1, 1); + zend_string *const_BLOCK_CODE_SUPERSCRIPTS_AND_SUBSCRIPTS_name = zend_string_init_interned("BLOCK_CODE_SUPERSCRIPTS_AND_SUBSCRIPTS", sizeof("BLOCK_CODE_SUPERSCRIPTS_AND_SUBSCRIPTS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SUPERSCRIPTS_AND_SUBSCRIPTS_name, &const_BLOCK_CODE_SUPERSCRIPTS_AND_SUBSCRIPTS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SUPERSCRIPTS_AND_SUBSCRIPTS_name); + zend_string_release_ex(const_BLOCK_CODE_SUPERSCRIPTS_AND_SUBSCRIPTS_name, true); zval const_BLOCK_CODE_CURRENCY_SYMBOLS_value; ZVAL_LONG(&const_BLOCK_CODE_CURRENCY_SYMBOLS_value, UBLOCK_CURRENCY_SYMBOLS); - zend_string *const_BLOCK_CODE_CURRENCY_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_CURRENCY_SYMBOLS", sizeof("BLOCK_CODE_CURRENCY_SYMBOLS") - 1, 1); + zend_string *const_BLOCK_CODE_CURRENCY_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_CURRENCY_SYMBOLS", sizeof("BLOCK_CODE_CURRENCY_SYMBOLS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CURRENCY_SYMBOLS_name, &const_BLOCK_CODE_CURRENCY_SYMBOLS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CURRENCY_SYMBOLS_name); + zend_string_release_ex(const_BLOCK_CODE_CURRENCY_SYMBOLS_name, true); zval const_BLOCK_CODE_COMBINING_MARKS_FOR_SYMBOLS_value; ZVAL_LONG(&const_BLOCK_CODE_COMBINING_MARKS_FOR_SYMBOLS_value, UBLOCK_COMBINING_MARKS_FOR_SYMBOLS); - zend_string *const_BLOCK_CODE_COMBINING_MARKS_FOR_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_COMBINING_MARKS_FOR_SYMBOLS", sizeof("BLOCK_CODE_COMBINING_MARKS_FOR_SYMBOLS") - 1, 1); + zend_string *const_BLOCK_CODE_COMBINING_MARKS_FOR_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_COMBINING_MARKS_FOR_SYMBOLS", sizeof("BLOCK_CODE_COMBINING_MARKS_FOR_SYMBOLS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_COMBINING_MARKS_FOR_SYMBOLS_name, &const_BLOCK_CODE_COMBINING_MARKS_FOR_SYMBOLS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_COMBINING_MARKS_FOR_SYMBOLS_name); + zend_string_release_ex(const_BLOCK_CODE_COMBINING_MARKS_FOR_SYMBOLS_name, true); zval const_BLOCK_CODE_LETTERLIKE_SYMBOLS_value; ZVAL_LONG(&const_BLOCK_CODE_LETTERLIKE_SYMBOLS_value, UBLOCK_LETTERLIKE_SYMBOLS); - zend_string *const_BLOCK_CODE_LETTERLIKE_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_LETTERLIKE_SYMBOLS", sizeof("BLOCK_CODE_LETTERLIKE_SYMBOLS") - 1, 1); + zend_string *const_BLOCK_CODE_LETTERLIKE_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_LETTERLIKE_SYMBOLS", sizeof("BLOCK_CODE_LETTERLIKE_SYMBOLS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_LETTERLIKE_SYMBOLS_name, &const_BLOCK_CODE_LETTERLIKE_SYMBOLS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_LETTERLIKE_SYMBOLS_name); + zend_string_release_ex(const_BLOCK_CODE_LETTERLIKE_SYMBOLS_name, true); zval const_BLOCK_CODE_NUMBER_FORMS_value; ZVAL_LONG(&const_BLOCK_CODE_NUMBER_FORMS_value, UBLOCK_NUMBER_FORMS); - zend_string *const_BLOCK_CODE_NUMBER_FORMS_name = zend_string_init_interned("BLOCK_CODE_NUMBER_FORMS", sizeof("BLOCK_CODE_NUMBER_FORMS") - 1, 1); + zend_string *const_BLOCK_CODE_NUMBER_FORMS_name = zend_string_init_interned("BLOCK_CODE_NUMBER_FORMS", sizeof("BLOCK_CODE_NUMBER_FORMS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_NUMBER_FORMS_name, &const_BLOCK_CODE_NUMBER_FORMS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_NUMBER_FORMS_name); + zend_string_release_ex(const_BLOCK_CODE_NUMBER_FORMS_name, true); zval const_BLOCK_CODE_ARROWS_value; ZVAL_LONG(&const_BLOCK_CODE_ARROWS_value, UBLOCK_ARROWS); - zend_string *const_BLOCK_CODE_ARROWS_name = zend_string_init_interned("BLOCK_CODE_ARROWS", sizeof("BLOCK_CODE_ARROWS") - 1, 1); + zend_string *const_BLOCK_CODE_ARROWS_name = zend_string_init_interned("BLOCK_CODE_ARROWS", sizeof("BLOCK_CODE_ARROWS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ARROWS_name, &const_BLOCK_CODE_ARROWS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ARROWS_name); + zend_string_release_ex(const_BLOCK_CODE_ARROWS_name, true); zval const_BLOCK_CODE_MATHEMATICAL_OPERATORS_value; ZVAL_LONG(&const_BLOCK_CODE_MATHEMATICAL_OPERATORS_value, UBLOCK_MATHEMATICAL_OPERATORS); - zend_string *const_BLOCK_CODE_MATHEMATICAL_OPERATORS_name = zend_string_init_interned("BLOCK_CODE_MATHEMATICAL_OPERATORS", sizeof("BLOCK_CODE_MATHEMATICAL_OPERATORS") - 1, 1); + zend_string *const_BLOCK_CODE_MATHEMATICAL_OPERATORS_name = zend_string_init_interned("BLOCK_CODE_MATHEMATICAL_OPERATORS", sizeof("BLOCK_CODE_MATHEMATICAL_OPERATORS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MATHEMATICAL_OPERATORS_name, &const_BLOCK_CODE_MATHEMATICAL_OPERATORS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MATHEMATICAL_OPERATORS_name); + zend_string_release_ex(const_BLOCK_CODE_MATHEMATICAL_OPERATORS_name, true); zval const_BLOCK_CODE_MISCELLANEOUS_TECHNICAL_value; ZVAL_LONG(&const_BLOCK_CODE_MISCELLANEOUS_TECHNICAL_value, UBLOCK_MISCELLANEOUS_TECHNICAL); - zend_string *const_BLOCK_CODE_MISCELLANEOUS_TECHNICAL_name = zend_string_init_interned("BLOCK_CODE_MISCELLANEOUS_TECHNICAL", sizeof("BLOCK_CODE_MISCELLANEOUS_TECHNICAL") - 1, 1); + zend_string *const_BLOCK_CODE_MISCELLANEOUS_TECHNICAL_name = zend_string_init_interned("BLOCK_CODE_MISCELLANEOUS_TECHNICAL", sizeof("BLOCK_CODE_MISCELLANEOUS_TECHNICAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MISCELLANEOUS_TECHNICAL_name, &const_BLOCK_CODE_MISCELLANEOUS_TECHNICAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MISCELLANEOUS_TECHNICAL_name); + zend_string_release_ex(const_BLOCK_CODE_MISCELLANEOUS_TECHNICAL_name, true); zval const_BLOCK_CODE_CONTROL_PICTURES_value; ZVAL_LONG(&const_BLOCK_CODE_CONTROL_PICTURES_value, UBLOCK_CONTROL_PICTURES); - zend_string *const_BLOCK_CODE_CONTROL_PICTURES_name = zend_string_init_interned("BLOCK_CODE_CONTROL_PICTURES", sizeof("BLOCK_CODE_CONTROL_PICTURES") - 1, 1); + zend_string *const_BLOCK_CODE_CONTROL_PICTURES_name = zend_string_init_interned("BLOCK_CODE_CONTROL_PICTURES", sizeof("BLOCK_CODE_CONTROL_PICTURES") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CONTROL_PICTURES_name, &const_BLOCK_CODE_CONTROL_PICTURES_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CONTROL_PICTURES_name); + zend_string_release_ex(const_BLOCK_CODE_CONTROL_PICTURES_name, true); zval const_BLOCK_CODE_OPTICAL_CHARACTER_RECOGNITION_value; ZVAL_LONG(&const_BLOCK_CODE_OPTICAL_CHARACTER_RECOGNITION_value, UBLOCK_OPTICAL_CHARACTER_RECOGNITION); - zend_string *const_BLOCK_CODE_OPTICAL_CHARACTER_RECOGNITION_name = zend_string_init_interned("BLOCK_CODE_OPTICAL_CHARACTER_RECOGNITION", sizeof("BLOCK_CODE_OPTICAL_CHARACTER_RECOGNITION") - 1, 1); + zend_string *const_BLOCK_CODE_OPTICAL_CHARACTER_RECOGNITION_name = zend_string_init_interned("BLOCK_CODE_OPTICAL_CHARACTER_RECOGNITION", sizeof("BLOCK_CODE_OPTICAL_CHARACTER_RECOGNITION") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_OPTICAL_CHARACTER_RECOGNITION_name, &const_BLOCK_CODE_OPTICAL_CHARACTER_RECOGNITION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_OPTICAL_CHARACTER_RECOGNITION_name); + zend_string_release_ex(const_BLOCK_CODE_OPTICAL_CHARACTER_RECOGNITION_name, true); zval const_BLOCK_CODE_ENCLOSED_ALPHANUMERICS_value; ZVAL_LONG(&const_BLOCK_CODE_ENCLOSED_ALPHANUMERICS_value, UBLOCK_ENCLOSED_ALPHANUMERICS); - zend_string *const_BLOCK_CODE_ENCLOSED_ALPHANUMERICS_name = zend_string_init_interned("BLOCK_CODE_ENCLOSED_ALPHANUMERICS", sizeof("BLOCK_CODE_ENCLOSED_ALPHANUMERICS") - 1, 1); + zend_string *const_BLOCK_CODE_ENCLOSED_ALPHANUMERICS_name = zend_string_init_interned("BLOCK_CODE_ENCLOSED_ALPHANUMERICS", sizeof("BLOCK_CODE_ENCLOSED_ALPHANUMERICS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ENCLOSED_ALPHANUMERICS_name, &const_BLOCK_CODE_ENCLOSED_ALPHANUMERICS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ENCLOSED_ALPHANUMERICS_name); + zend_string_release_ex(const_BLOCK_CODE_ENCLOSED_ALPHANUMERICS_name, true); zval const_BLOCK_CODE_BOX_DRAWING_value; ZVAL_LONG(&const_BLOCK_CODE_BOX_DRAWING_value, UBLOCK_BOX_DRAWING); - zend_string *const_BLOCK_CODE_BOX_DRAWING_name = zend_string_init_interned("BLOCK_CODE_BOX_DRAWING", sizeof("BLOCK_CODE_BOX_DRAWING") - 1, 1); + zend_string *const_BLOCK_CODE_BOX_DRAWING_name = zend_string_init_interned("BLOCK_CODE_BOX_DRAWING", sizeof("BLOCK_CODE_BOX_DRAWING") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_BOX_DRAWING_name, &const_BLOCK_CODE_BOX_DRAWING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_BOX_DRAWING_name); + zend_string_release_ex(const_BLOCK_CODE_BOX_DRAWING_name, true); zval const_BLOCK_CODE_BLOCK_ELEMENTS_value; ZVAL_LONG(&const_BLOCK_CODE_BLOCK_ELEMENTS_value, UBLOCK_BLOCK_ELEMENTS); - zend_string *const_BLOCK_CODE_BLOCK_ELEMENTS_name = zend_string_init_interned("BLOCK_CODE_BLOCK_ELEMENTS", sizeof("BLOCK_CODE_BLOCK_ELEMENTS") - 1, 1); + zend_string *const_BLOCK_CODE_BLOCK_ELEMENTS_name = zend_string_init_interned("BLOCK_CODE_BLOCK_ELEMENTS", sizeof("BLOCK_CODE_BLOCK_ELEMENTS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_BLOCK_ELEMENTS_name, &const_BLOCK_CODE_BLOCK_ELEMENTS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_BLOCK_ELEMENTS_name); + zend_string_release_ex(const_BLOCK_CODE_BLOCK_ELEMENTS_name, true); zval const_BLOCK_CODE_GEOMETRIC_SHAPES_value; ZVAL_LONG(&const_BLOCK_CODE_GEOMETRIC_SHAPES_value, UBLOCK_GEOMETRIC_SHAPES); - zend_string *const_BLOCK_CODE_GEOMETRIC_SHAPES_name = zend_string_init_interned("BLOCK_CODE_GEOMETRIC_SHAPES", sizeof("BLOCK_CODE_GEOMETRIC_SHAPES") - 1, 1); + zend_string *const_BLOCK_CODE_GEOMETRIC_SHAPES_name = zend_string_init_interned("BLOCK_CODE_GEOMETRIC_SHAPES", sizeof("BLOCK_CODE_GEOMETRIC_SHAPES") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_GEOMETRIC_SHAPES_name, &const_BLOCK_CODE_GEOMETRIC_SHAPES_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_GEOMETRIC_SHAPES_name); + zend_string_release_ex(const_BLOCK_CODE_GEOMETRIC_SHAPES_name, true); zval const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_value; ZVAL_LONG(&const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_value, UBLOCK_MISCELLANEOUS_SYMBOLS); - zend_string *const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_MISCELLANEOUS_SYMBOLS", sizeof("BLOCK_CODE_MISCELLANEOUS_SYMBOLS") - 1, 1); + zend_string *const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_MISCELLANEOUS_SYMBOLS", sizeof("BLOCK_CODE_MISCELLANEOUS_SYMBOLS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_name, &const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_name); + zend_string_release_ex(const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_name, true); zval const_BLOCK_CODE_DINGBATS_value; ZVAL_LONG(&const_BLOCK_CODE_DINGBATS_value, UBLOCK_DINGBATS); - zend_string *const_BLOCK_CODE_DINGBATS_name = zend_string_init_interned("BLOCK_CODE_DINGBATS", sizeof("BLOCK_CODE_DINGBATS") - 1, 1); + zend_string *const_BLOCK_CODE_DINGBATS_name = zend_string_init_interned("BLOCK_CODE_DINGBATS", sizeof("BLOCK_CODE_DINGBATS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_DINGBATS_name, &const_BLOCK_CODE_DINGBATS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_DINGBATS_name); + zend_string_release_ex(const_BLOCK_CODE_DINGBATS_name, true); zval const_BLOCK_CODE_BRAILLE_PATTERNS_value; ZVAL_LONG(&const_BLOCK_CODE_BRAILLE_PATTERNS_value, UBLOCK_BRAILLE_PATTERNS); - zend_string *const_BLOCK_CODE_BRAILLE_PATTERNS_name = zend_string_init_interned("BLOCK_CODE_BRAILLE_PATTERNS", sizeof("BLOCK_CODE_BRAILLE_PATTERNS") - 1, 1); + zend_string *const_BLOCK_CODE_BRAILLE_PATTERNS_name = zend_string_init_interned("BLOCK_CODE_BRAILLE_PATTERNS", sizeof("BLOCK_CODE_BRAILLE_PATTERNS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_BRAILLE_PATTERNS_name, &const_BLOCK_CODE_BRAILLE_PATTERNS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_BRAILLE_PATTERNS_name); + zend_string_release_ex(const_BLOCK_CODE_BRAILLE_PATTERNS_name, true); zval const_BLOCK_CODE_CJK_RADICALS_SUPPLEMENT_value; ZVAL_LONG(&const_BLOCK_CODE_CJK_RADICALS_SUPPLEMENT_value, UBLOCK_CJK_RADICALS_SUPPLEMENT); - zend_string *const_BLOCK_CODE_CJK_RADICALS_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_CJK_RADICALS_SUPPLEMENT", sizeof("BLOCK_CODE_CJK_RADICALS_SUPPLEMENT") - 1, 1); + zend_string *const_BLOCK_CODE_CJK_RADICALS_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_CJK_RADICALS_SUPPLEMENT", sizeof("BLOCK_CODE_CJK_RADICALS_SUPPLEMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CJK_RADICALS_SUPPLEMENT_name, &const_BLOCK_CODE_CJK_RADICALS_SUPPLEMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CJK_RADICALS_SUPPLEMENT_name); + zend_string_release_ex(const_BLOCK_CODE_CJK_RADICALS_SUPPLEMENT_name, true); zval const_BLOCK_CODE_KANGXI_RADICALS_value; ZVAL_LONG(&const_BLOCK_CODE_KANGXI_RADICALS_value, UBLOCK_KANGXI_RADICALS); - zend_string *const_BLOCK_CODE_KANGXI_RADICALS_name = zend_string_init_interned("BLOCK_CODE_KANGXI_RADICALS", sizeof("BLOCK_CODE_KANGXI_RADICALS") - 1, 1); + zend_string *const_BLOCK_CODE_KANGXI_RADICALS_name = zend_string_init_interned("BLOCK_CODE_KANGXI_RADICALS", sizeof("BLOCK_CODE_KANGXI_RADICALS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_KANGXI_RADICALS_name, &const_BLOCK_CODE_KANGXI_RADICALS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_KANGXI_RADICALS_name); + zend_string_release_ex(const_BLOCK_CODE_KANGXI_RADICALS_name, true); zval const_BLOCK_CODE_IDEOGRAPHIC_DESCRIPTION_CHARACTERS_value; ZVAL_LONG(&const_BLOCK_CODE_IDEOGRAPHIC_DESCRIPTION_CHARACTERS_value, UBLOCK_IDEOGRAPHIC_DESCRIPTION_CHARACTERS); - zend_string *const_BLOCK_CODE_IDEOGRAPHIC_DESCRIPTION_CHARACTERS_name = zend_string_init_interned("BLOCK_CODE_IDEOGRAPHIC_DESCRIPTION_CHARACTERS", sizeof("BLOCK_CODE_IDEOGRAPHIC_DESCRIPTION_CHARACTERS") - 1, 1); + zend_string *const_BLOCK_CODE_IDEOGRAPHIC_DESCRIPTION_CHARACTERS_name = zend_string_init_interned("BLOCK_CODE_IDEOGRAPHIC_DESCRIPTION_CHARACTERS", sizeof("BLOCK_CODE_IDEOGRAPHIC_DESCRIPTION_CHARACTERS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_IDEOGRAPHIC_DESCRIPTION_CHARACTERS_name, &const_BLOCK_CODE_IDEOGRAPHIC_DESCRIPTION_CHARACTERS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_IDEOGRAPHIC_DESCRIPTION_CHARACTERS_name); + zend_string_release_ex(const_BLOCK_CODE_IDEOGRAPHIC_DESCRIPTION_CHARACTERS_name, true); zval const_BLOCK_CODE_CJK_SYMBOLS_AND_PUNCTUATION_value; ZVAL_LONG(&const_BLOCK_CODE_CJK_SYMBOLS_AND_PUNCTUATION_value, UBLOCK_CJK_SYMBOLS_AND_PUNCTUATION); - zend_string *const_BLOCK_CODE_CJK_SYMBOLS_AND_PUNCTUATION_name = zend_string_init_interned("BLOCK_CODE_CJK_SYMBOLS_AND_PUNCTUATION", sizeof("BLOCK_CODE_CJK_SYMBOLS_AND_PUNCTUATION") - 1, 1); + zend_string *const_BLOCK_CODE_CJK_SYMBOLS_AND_PUNCTUATION_name = zend_string_init_interned("BLOCK_CODE_CJK_SYMBOLS_AND_PUNCTUATION", sizeof("BLOCK_CODE_CJK_SYMBOLS_AND_PUNCTUATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CJK_SYMBOLS_AND_PUNCTUATION_name, &const_BLOCK_CODE_CJK_SYMBOLS_AND_PUNCTUATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CJK_SYMBOLS_AND_PUNCTUATION_name); + zend_string_release_ex(const_BLOCK_CODE_CJK_SYMBOLS_AND_PUNCTUATION_name, true); zval const_BLOCK_CODE_HIRAGANA_value; ZVAL_LONG(&const_BLOCK_CODE_HIRAGANA_value, UBLOCK_HIRAGANA); - zend_string *const_BLOCK_CODE_HIRAGANA_name = zend_string_init_interned("BLOCK_CODE_HIRAGANA", sizeof("BLOCK_CODE_HIRAGANA") - 1, 1); + zend_string *const_BLOCK_CODE_HIRAGANA_name = zend_string_init_interned("BLOCK_CODE_HIRAGANA", sizeof("BLOCK_CODE_HIRAGANA") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_HIRAGANA_name, &const_BLOCK_CODE_HIRAGANA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_HIRAGANA_name); + zend_string_release_ex(const_BLOCK_CODE_HIRAGANA_name, true); zval const_BLOCK_CODE_KATAKANA_value; ZVAL_LONG(&const_BLOCK_CODE_KATAKANA_value, UBLOCK_KATAKANA); - zend_string *const_BLOCK_CODE_KATAKANA_name = zend_string_init_interned("BLOCK_CODE_KATAKANA", sizeof("BLOCK_CODE_KATAKANA") - 1, 1); + zend_string *const_BLOCK_CODE_KATAKANA_name = zend_string_init_interned("BLOCK_CODE_KATAKANA", sizeof("BLOCK_CODE_KATAKANA") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_KATAKANA_name, &const_BLOCK_CODE_KATAKANA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_KATAKANA_name); + zend_string_release_ex(const_BLOCK_CODE_KATAKANA_name, true); zval const_BLOCK_CODE_BOPOMOFO_value; ZVAL_LONG(&const_BLOCK_CODE_BOPOMOFO_value, UBLOCK_BOPOMOFO); - zend_string *const_BLOCK_CODE_BOPOMOFO_name = zend_string_init_interned("BLOCK_CODE_BOPOMOFO", sizeof("BLOCK_CODE_BOPOMOFO") - 1, 1); + zend_string *const_BLOCK_CODE_BOPOMOFO_name = zend_string_init_interned("BLOCK_CODE_BOPOMOFO", sizeof("BLOCK_CODE_BOPOMOFO") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_BOPOMOFO_name, &const_BLOCK_CODE_BOPOMOFO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_BOPOMOFO_name); + zend_string_release_ex(const_BLOCK_CODE_BOPOMOFO_name, true); zval const_BLOCK_CODE_HANGUL_COMPATIBILITY_JAMO_value; ZVAL_LONG(&const_BLOCK_CODE_HANGUL_COMPATIBILITY_JAMO_value, UBLOCK_HANGUL_COMPATIBILITY_JAMO); - zend_string *const_BLOCK_CODE_HANGUL_COMPATIBILITY_JAMO_name = zend_string_init_interned("BLOCK_CODE_HANGUL_COMPATIBILITY_JAMO", sizeof("BLOCK_CODE_HANGUL_COMPATIBILITY_JAMO") - 1, 1); + zend_string *const_BLOCK_CODE_HANGUL_COMPATIBILITY_JAMO_name = zend_string_init_interned("BLOCK_CODE_HANGUL_COMPATIBILITY_JAMO", sizeof("BLOCK_CODE_HANGUL_COMPATIBILITY_JAMO") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_HANGUL_COMPATIBILITY_JAMO_name, &const_BLOCK_CODE_HANGUL_COMPATIBILITY_JAMO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_HANGUL_COMPATIBILITY_JAMO_name); + zend_string_release_ex(const_BLOCK_CODE_HANGUL_COMPATIBILITY_JAMO_name, true); zval const_BLOCK_CODE_KANBUN_value; ZVAL_LONG(&const_BLOCK_CODE_KANBUN_value, UBLOCK_KANBUN); - zend_string *const_BLOCK_CODE_KANBUN_name = zend_string_init_interned("BLOCK_CODE_KANBUN", sizeof("BLOCK_CODE_KANBUN") - 1, 1); + zend_string *const_BLOCK_CODE_KANBUN_name = zend_string_init_interned("BLOCK_CODE_KANBUN", sizeof("BLOCK_CODE_KANBUN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_KANBUN_name, &const_BLOCK_CODE_KANBUN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_KANBUN_name); + zend_string_release_ex(const_BLOCK_CODE_KANBUN_name, true); zval const_BLOCK_CODE_BOPOMOFO_EXTENDED_value; ZVAL_LONG(&const_BLOCK_CODE_BOPOMOFO_EXTENDED_value, UBLOCK_BOPOMOFO_EXTENDED); - zend_string *const_BLOCK_CODE_BOPOMOFO_EXTENDED_name = zend_string_init_interned("BLOCK_CODE_BOPOMOFO_EXTENDED", sizeof("BLOCK_CODE_BOPOMOFO_EXTENDED") - 1, 1); + zend_string *const_BLOCK_CODE_BOPOMOFO_EXTENDED_name = zend_string_init_interned("BLOCK_CODE_BOPOMOFO_EXTENDED", sizeof("BLOCK_CODE_BOPOMOFO_EXTENDED") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_BOPOMOFO_EXTENDED_name, &const_BLOCK_CODE_BOPOMOFO_EXTENDED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_BOPOMOFO_EXTENDED_name); + zend_string_release_ex(const_BLOCK_CODE_BOPOMOFO_EXTENDED_name, true); zval const_BLOCK_CODE_ENCLOSED_CJK_LETTERS_AND_MONTHS_value; ZVAL_LONG(&const_BLOCK_CODE_ENCLOSED_CJK_LETTERS_AND_MONTHS_value, UBLOCK_ENCLOSED_CJK_LETTERS_AND_MONTHS); - zend_string *const_BLOCK_CODE_ENCLOSED_CJK_LETTERS_AND_MONTHS_name = zend_string_init_interned("BLOCK_CODE_ENCLOSED_CJK_LETTERS_AND_MONTHS", sizeof("BLOCK_CODE_ENCLOSED_CJK_LETTERS_AND_MONTHS") - 1, 1); + zend_string *const_BLOCK_CODE_ENCLOSED_CJK_LETTERS_AND_MONTHS_name = zend_string_init_interned("BLOCK_CODE_ENCLOSED_CJK_LETTERS_AND_MONTHS", sizeof("BLOCK_CODE_ENCLOSED_CJK_LETTERS_AND_MONTHS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ENCLOSED_CJK_LETTERS_AND_MONTHS_name, &const_BLOCK_CODE_ENCLOSED_CJK_LETTERS_AND_MONTHS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ENCLOSED_CJK_LETTERS_AND_MONTHS_name); + zend_string_release_ex(const_BLOCK_CODE_ENCLOSED_CJK_LETTERS_AND_MONTHS_name, true); zval const_BLOCK_CODE_CJK_COMPATIBILITY_value; ZVAL_LONG(&const_BLOCK_CODE_CJK_COMPATIBILITY_value, UBLOCK_CJK_COMPATIBILITY); - zend_string *const_BLOCK_CODE_CJK_COMPATIBILITY_name = zend_string_init_interned("BLOCK_CODE_CJK_COMPATIBILITY", sizeof("BLOCK_CODE_CJK_COMPATIBILITY") - 1, 1); + zend_string *const_BLOCK_CODE_CJK_COMPATIBILITY_name = zend_string_init_interned("BLOCK_CODE_CJK_COMPATIBILITY", sizeof("BLOCK_CODE_CJK_COMPATIBILITY") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CJK_COMPATIBILITY_name, &const_BLOCK_CODE_CJK_COMPATIBILITY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CJK_COMPATIBILITY_name); + zend_string_release_ex(const_BLOCK_CODE_CJK_COMPATIBILITY_name, true); zval const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A_value; ZVAL_LONG(&const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A_value, UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A); - zend_string *const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A_name = zend_string_init_interned("BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A", sizeof("BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A") - 1, 1); + zend_string *const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A_name = zend_string_init_interned("BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A", sizeof("BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A_name, &const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A_name); + zend_string_release_ex(const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A_name, true); zval const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_value; ZVAL_LONG(&const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_value, UBLOCK_CJK_UNIFIED_IDEOGRAPHS); - zend_string *const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_name = zend_string_init_interned("BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS", sizeof("BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS") - 1, 1); + zend_string *const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_name = zend_string_init_interned("BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS", sizeof("BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_name, &const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_name); + zend_string_release_ex(const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_name, true); zval const_BLOCK_CODE_YI_SYLLABLES_value; ZVAL_LONG(&const_BLOCK_CODE_YI_SYLLABLES_value, UBLOCK_YI_SYLLABLES); - zend_string *const_BLOCK_CODE_YI_SYLLABLES_name = zend_string_init_interned("BLOCK_CODE_YI_SYLLABLES", sizeof("BLOCK_CODE_YI_SYLLABLES") - 1, 1); + zend_string *const_BLOCK_CODE_YI_SYLLABLES_name = zend_string_init_interned("BLOCK_CODE_YI_SYLLABLES", sizeof("BLOCK_CODE_YI_SYLLABLES") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_YI_SYLLABLES_name, &const_BLOCK_CODE_YI_SYLLABLES_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_YI_SYLLABLES_name); + zend_string_release_ex(const_BLOCK_CODE_YI_SYLLABLES_name, true); zval const_BLOCK_CODE_YI_RADICALS_value; ZVAL_LONG(&const_BLOCK_CODE_YI_RADICALS_value, UBLOCK_YI_RADICALS); - zend_string *const_BLOCK_CODE_YI_RADICALS_name = zend_string_init_interned("BLOCK_CODE_YI_RADICALS", sizeof("BLOCK_CODE_YI_RADICALS") - 1, 1); + zend_string *const_BLOCK_CODE_YI_RADICALS_name = zend_string_init_interned("BLOCK_CODE_YI_RADICALS", sizeof("BLOCK_CODE_YI_RADICALS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_YI_RADICALS_name, &const_BLOCK_CODE_YI_RADICALS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_YI_RADICALS_name); + zend_string_release_ex(const_BLOCK_CODE_YI_RADICALS_name, true); zval const_BLOCK_CODE_HANGUL_SYLLABLES_value; ZVAL_LONG(&const_BLOCK_CODE_HANGUL_SYLLABLES_value, UBLOCK_HANGUL_SYLLABLES); - zend_string *const_BLOCK_CODE_HANGUL_SYLLABLES_name = zend_string_init_interned("BLOCK_CODE_HANGUL_SYLLABLES", sizeof("BLOCK_CODE_HANGUL_SYLLABLES") - 1, 1); + zend_string *const_BLOCK_CODE_HANGUL_SYLLABLES_name = zend_string_init_interned("BLOCK_CODE_HANGUL_SYLLABLES", sizeof("BLOCK_CODE_HANGUL_SYLLABLES") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_HANGUL_SYLLABLES_name, &const_BLOCK_CODE_HANGUL_SYLLABLES_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_HANGUL_SYLLABLES_name); + zend_string_release_ex(const_BLOCK_CODE_HANGUL_SYLLABLES_name, true); zval const_BLOCK_CODE_HIGH_SURROGATES_value; ZVAL_LONG(&const_BLOCK_CODE_HIGH_SURROGATES_value, UBLOCK_HIGH_SURROGATES); - zend_string *const_BLOCK_CODE_HIGH_SURROGATES_name = zend_string_init_interned("BLOCK_CODE_HIGH_SURROGATES", sizeof("BLOCK_CODE_HIGH_SURROGATES") - 1, 1); + zend_string *const_BLOCK_CODE_HIGH_SURROGATES_name = zend_string_init_interned("BLOCK_CODE_HIGH_SURROGATES", sizeof("BLOCK_CODE_HIGH_SURROGATES") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_HIGH_SURROGATES_name, &const_BLOCK_CODE_HIGH_SURROGATES_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_HIGH_SURROGATES_name); + zend_string_release_ex(const_BLOCK_CODE_HIGH_SURROGATES_name, true); zval const_BLOCK_CODE_HIGH_PRIVATE_USE_SURROGATES_value; ZVAL_LONG(&const_BLOCK_CODE_HIGH_PRIVATE_USE_SURROGATES_value, UBLOCK_HIGH_PRIVATE_USE_SURROGATES); - zend_string *const_BLOCK_CODE_HIGH_PRIVATE_USE_SURROGATES_name = zend_string_init_interned("BLOCK_CODE_HIGH_PRIVATE_USE_SURROGATES", sizeof("BLOCK_CODE_HIGH_PRIVATE_USE_SURROGATES") - 1, 1); + zend_string *const_BLOCK_CODE_HIGH_PRIVATE_USE_SURROGATES_name = zend_string_init_interned("BLOCK_CODE_HIGH_PRIVATE_USE_SURROGATES", sizeof("BLOCK_CODE_HIGH_PRIVATE_USE_SURROGATES") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_HIGH_PRIVATE_USE_SURROGATES_name, &const_BLOCK_CODE_HIGH_PRIVATE_USE_SURROGATES_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_HIGH_PRIVATE_USE_SURROGATES_name); + zend_string_release_ex(const_BLOCK_CODE_HIGH_PRIVATE_USE_SURROGATES_name, true); zval const_BLOCK_CODE_LOW_SURROGATES_value; ZVAL_LONG(&const_BLOCK_CODE_LOW_SURROGATES_value, UBLOCK_LOW_SURROGATES); - zend_string *const_BLOCK_CODE_LOW_SURROGATES_name = zend_string_init_interned("BLOCK_CODE_LOW_SURROGATES", sizeof("BLOCK_CODE_LOW_SURROGATES") - 1, 1); + zend_string *const_BLOCK_CODE_LOW_SURROGATES_name = zend_string_init_interned("BLOCK_CODE_LOW_SURROGATES", sizeof("BLOCK_CODE_LOW_SURROGATES") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_LOW_SURROGATES_name, &const_BLOCK_CODE_LOW_SURROGATES_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_LOW_SURROGATES_name); + zend_string_release_ex(const_BLOCK_CODE_LOW_SURROGATES_name, true); zval const_BLOCK_CODE_PRIVATE_USE_AREA_value; ZVAL_LONG(&const_BLOCK_CODE_PRIVATE_USE_AREA_value, UBLOCK_PRIVATE_USE_AREA); - zend_string *const_BLOCK_CODE_PRIVATE_USE_AREA_name = zend_string_init_interned("BLOCK_CODE_PRIVATE_USE_AREA", sizeof("BLOCK_CODE_PRIVATE_USE_AREA") - 1, 1); + zend_string *const_BLOCK_CODE_PRIVATE_USE_AREA_name = zend_string_init_interned("BLOCK_CODE_PRIVATE_USE_AREA", sizeof("BLOCK_CODE_PRIVATE_USE_AREA") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_PRIVATE_USE_AREA_name, &const_BLOCK_CODE_PRIVATE_USE_AREA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_PRIVATE_USE_AREA_name); + zend_string_release_ex(const_BLOCK_CODE_PRIVATE_USE_AREA_name, true); zval const_BLOCK_CODE_PRIVATE_USE_value; ZVAL_LONG(&const_BLOCK_CODE_PRIVATE_USE_value, UBLOCK_PRIVATE_USE); - zend_string *const_BLOCK_CODE_PRIVATE_USE_name = zend_string_init_interned("BLOCK_CODE_PRIVATE_USE", sizeof("BLOCK_CODE_PRIVATE_USE") - 1, 1); + zend_string *const_BLOCK_CODE_PRIVATE_USE_name = zend_string_init_interned("BLOCK_CODE_PRIVATE_USE", sizeof("BLOCK_CODE_PRIVATE_USE") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_PRIVATE_USE_name, &const_BLOCK_CODE_PRIVATE_USE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_PRIVATE_USE_name); + zend_string_release_ex(const_BLOCK_CODE_PRIVATE_USE_name, true); zval const_BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS_value; ZVAL_LONG(&const_BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS_value, UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS); - zend_string *const_BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS_name = zend_string_init_interned("BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS", sizeof("BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS") - 1, 1); + zend_string *const_BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS_name = zend_string_init_interned("BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS", sizeof("BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS_name, &const_BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS_name); + zend_string_release_ex(const_BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS_name, true); zval const_BLOCK_CODE_ALPHABETIC_PRESENTATION_FORMS_value; ZVAL_LONG(&const_BLOCK_CODE_ALPHABETIC_PRESENTATION_FORMS_value, UBLOCK_ALPHABETIC_PRESENTATION_FORMS); - zend_string *const_BLOCK_CODE_ALPHABETIC_PRESENTATION_FORMS_name = zend_string_init_interned("BLOCK_CODE_ALPHABETIC_PRESENTATION_FORMS", sizeof("BLOCK_CODE_ALPHABETIC_PRESENTATION_FORMS") - 1, 1); + zend_string *const_BLOCK_CODE_ALPHABETIC_PRESENTATION_FORMS_name = zend_string_init_interned("BLOCK_CODE_ALPHABETIC_PRESENTATION_FORMS", sizeof("BLOCK_CODE_ALPHABETIC_PRESENTATION_FORMS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ALPHABETIC_PRESENTATION_FORMS_name, &const_BLOCK_CODE_ALPHABETIC_PRESENTATION_FORMS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ALPHABETIC_PRESENTATION_FORMS_name); + zend_string_release_ex(const_BLOCK_CODE_ALPHABETIC_PRESENTATION_FORMS_name, true); zval const_BLOCK_CODE_ARABIC_PRESENTATION_FORMS_A_value; ZVAL_LONG(&const_BLOCK_CODE_ARABIC_PRESENTATION_FORMS_A_value, UBLOCK_ARABIC_PRESENTATION_FORMS_A); - zend_string *const_BLOCK_CODE_ARABIC_PRESENTATION_FORMS_A_name = zend_string_init_interned("BLOCK_CODE_ARABIC_PRESENTATION_FORMS_A", sizeof("BLOCK_CODE_ARABIC_PRESENTATION_FORMS_A") - 1, 1); + zend_string *const_BLOCK_CODE_ARABIC_PRESENTATION_FORMS_A_name = zend_string_init_interned("BLOCK_CODE_ARABIC_PRESENTATION_FORMS_A", sizeof("BLOCK_CODE_ARABIC_PRESENTATION_FORMS_A") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ARABIC_PRESENTATION_FORMS_A_name, &const_BLOCK_CODE_ARABIC_PRESENTATION_FORMS_A_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ARABIC_PRESENTATION_FORMS_A_name); + zend_string_release_ex(const_BLOCK_CODE_ARABIC_PRESENTATION_FORMS_A_name, true); zval const_BLOCK_CODE_COMBINING_HALF_MARKS_value; ZVAL_LONG(&const_BLOCK_CODE_COMBINING_HALF_MARKS_value, UBLOCK_COMBINING_HALF_MARKS); - zend_string *const_BLOCK_CODE_COMBINING_HALF_MARKS_name = zend_string_init_interned("BLOCK_CODE_COMBINING_HALF_MARKS", sizeof("BLOCK_CODE_COMBINING_HALF_MARKS") - 1, 1); + zend_string *const_BLOCK_CODE_COMBINING_HALF_MARKS_name = zend_string_init_interned("BLOCK_CODE_COMBINING_HALF_MARKS", sizeof("BLOCK_CODE_COMBINING_HALF_MARKS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_COMBINING_HALF_MARKS_name, &const_BLOCK_CODE_COMBINING_HALF_MARKS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_COMBINING_HALF_MARKS_name); + zend_string_release_ex(const_BLOCK_CODE_COMBINING_HALF_MARKS_name, true); zval const_BLOCK_CODE_CJK_COMPATIBILITY_FORMS_value; ZVAL_LONG(&const_BLOCK_CODE_CJK_COMPATIBILITY_FORMS_value, UBLOCK_CJK_COMPATIBILITY_FORMS); - zend_string *const_BLOCK_CODE_CJK_COMPATIBILITY_FORMS_name = zend_string_init_interned("BLOCK_CODE_CJK_COMPATIBILITY_FORMS", sizeof("BLOCK_CODE_CJK_COMPATIBILITY_FORMS") - 1, 1); + zend_string *const_BLOCK_CODE_CJK_COMPATIBILITY_FORMS_name = zend_string_init_interned("BLOCK_CODE_CJK_COMPATIBILITY_FORMS", sizeof("BLOCK_CODE_CJK_COMPATIBILITY_FORMS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CJK_COMPATIBILITY_FORMS_name, &const_BLOCK_CODE_CJK_COMPATIBILITY_FORMS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CJK_COMPATIBILITY_FORMS_name); + zend_string_release_ex(const_BLOCK_CODE_CJK_COMPATIBILITY_FORMS_name, true); zval const_BLOCK_CODE_SMALL_FORM_VARIANTS_value; ZVAL_LONG(&const_BLOCK_CODE_SMALL_FORM_VARIANTS_value, UBLOCK_SMALL_FORM_VARIANTS); - zend_string *const_BLOCK_CODE_SMALL_FORM_VARIANTS_name = zend_string_init_interned("BLOCK_CODE_SMALL_FORM_VARIANTS", sizeof("BLOCK_CODE_SMALL_FORM_VARIANTS") - 1, 1); + zend_string *const_BLOCK_CODE_SMALL_FORM_VARIANTS_name = zend_string_init_interned("BLOCK_CODE_SMALL_FORM_VARIANTS", sizeof("BLOCK_CODE_SMALL_FORM_VARIANTS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SMALL_FORM_VARIANTS_name, &const_BLOCK_CODE_SMALL_FORM_VARIANTS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SMALL_FORM_VARIANTS_name); + zend_string_release_ex(const_BLOCK_CODE_SMALL_FORM_VARIANTS_name, true); zval const_BLOCK_CODE_ARABIC_PRESENTATION_FORMS_B_value; ZVAL_LONG(&const_BLOCK_CODE_ARABIC_PRESENTATION_FORMS_B_value, UBLOCK_ARABIC_PRESENTATION_FORMS_B); - zend_string *const_BLOCK_CODE_ARABIC_PRESENTATION_FORMS_B_name = zend_string_init_interned("BLOCK_CODE_ARABIC_PRESENTATION_FORMS_B", sizeof("BLOCK_CODE_ARABIC_PRESENTATION_FORMS_B") - 1, 1); + zend_string *const_BLOCK_CODE_ARABIC_PRESENTATION_FORMS_B_name = zend_string_init_interned("BLOCK_CODE_ARABIC_PRESENTATION_FORMS_B", sizeof("BLOCK_CODE_ARABIC_PRESENTATION_FORMS_B") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ARABIC_PRESENTATION_FORMS_B_name, &const_BLOCK_CODE_ARABIC_PRESENTATION_FORMS_B_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ARABIC_PRESENTATION_FORMS_B_name); + zend_string_release_ex(const_BLOCK_CODE_ARABIC_PRESENTATION_FORMS_B_name, true); zval const_BLOCK_CODE_SPECIALS_value; ZVAL_LONG(&const_BLOCK_CODE_SPECIALS_value, UBLOCK_SPECIALS); - zend_string *const_BLOCK_CODE_SPECIALS_name = zend_string_init_interned("BLOCK_CODE_SPECIALS", sizeof("BLOCK_CODE_SPECIALS") - 1, 1); + zend_string *const_BLOCK_CODE_SPECIALS_name = zend_string_init_interned("BLOCK_CODE_SPECIALS", sizeof("BLOCK_CODE_SPECIALS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SPECIALS_name, &const_BLOCK_CODE_SPECIALS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SPECIALS_name); + zend_string_release_ex(const_BLOCK_CODE_SPECIALS_name, true); zval const_BLOCK_CODE_HALFWIDTH_AND_FULLWIDTH_FORMS_value; ZVAL_LONG(&const_BLOCK_CODE_HALFWIDTH_AND_FULLWIDTH_FORMS_value, UBLOCK_HALFWIDTH_AND_FULLWIDTH_FORMS); - zend_string *const_BLOCK_CODE_HALFWIDTH_AND_FULLWIDTH_FORMS_name = zend_string_init_interned("BLOCK_CODE_HALFWIDTH_AND_FULLWIDTH_FORMS", sizeof("BLOCK_CODE_HALFWIDTH_AND_FULLWIDTH_FORMS") - 1, 1); + zend_string *const_BLOCK_CODE_HALFWIDTH_AND_FULLWIDTH_FORMS_name = zend_string_init_interned("BLOCK_CODE_HALFWIDTH_AND_FULLWIDTH_FORMS", sizeof("BLOCK_CODE_HALFWIDTH_AND_FULLWIDTH_FORMS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_HALFWIDTH_AND_FULLWIDTH_FORMS_name, &const_BLOCK_CODE_HALFWIDTH_AND_FULLWIDTH_FORMS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_HALFWIDTH_AND_FULLWIDTH_FORMS_name); + zend_string_release_ex(const_BLOCK_CODE_HALFWIDTH_AND_FULLWIDTH_FORMS_name, true); zval const_BLOCK_CODE_OLD_ITALIC_value; ZVAL_LONG(&const_BLOCK_CODE_OLD_ITALIC_value, UBLOCK_OLD_ITALIC); - zend_string *const_BLOCK_CODE_OLD_ITALIC_name = zend_string_init_interned("BLOCK_CODE_OLD_ITALIC", sizeof("BLOCK_CODE_OLD_ITALIC") - 1, 1); + zend_string *const_BLOCK_CODE_OLD_ITALIC_name = zend_string_init_interned("BLOCK_CODE_OLD_ITALIC", sizeof("BLOCK_CODE_OLD_ITALIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_OLD_ITALIC_name, &const_BLOCK_CODE_OLD_ITALIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_OLD_ITALIC_name); + zend_string_release_ex(const_BLOCK_CODE_OLD_ITALIC_name, true); zval const_BLOCK_CODE_GOTHIC_value; ZVAL_LONG(&const_BLOCK_CODE_GOTHIC_value, UBLOCK_GOTHIC); - zend_string *const_BLOCK_CODE_GOTHIC_name = zend_string_init_interned("BLOCK_CODE_GOTHIC", sizeof("BLOCK_CODE_GOTHIC") - 1, 1); + zend_string *const_BLOCK_CODE_GOTHIC_name = zend_string_init_interned("BLOCK_CODE_GOTHIC", sizeof("BLOCK_CODE_GOTHIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_GOTHIC_name, &const_BLOCK_CODE_GOTHIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_GOTHIC_name); + zend_string_release_ex(const_BLOCK_CODE_GOTHIC_name, true); zval const_BLOCK_CODE_DESERET_value; ZVAL_LONG(&const_BLOCK_CODE_DESERET_value, UBLOCK_DESERET); - zend_string *const_BLOCK_CODE_DESERET_name = zend_string_init_interned("BLOCK_CODE_DESERET", sizeof("BLOCK_CODE_DESERET") - 1, 1); + zend_string *const_BLOCK_CODE_DESERET_name = zend_string_init_interned("BLOCK_CODE_DESERET", sizeof("BLOCK_CODE_DESERET") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_DESERET_name, &const_BLOCK_CODE_DESERET_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_DESERET_name); + zend_string_release_ex(const_BLOCK_CODE_DESERET_name, true); zval const_BLOCK_CODE_BYZANTINE_MUSICAL_SYMBOLS_value; ZVAL_LONG(&const_BLOCK_CODE_BYZANTINE_MUSICAL_SYMBOLS_value, UBLOCK_BYZANTINE_MUSICAL_SYMBOLS); - zend_string *const_BLOCK_CODE_BYZANTINE_MUSICAL_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_BYZANTINE_MUSICAL_SYMBOLS", sizeof("BLOCK_CODE_BYZANTINE_MUSICAL_SYMBOLS") - 1, 1); + zend_string *const_BLOCK_CODE_BYZANTINE_MUSICAL_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_BYZANTINE_MUSICAL_SYMBOLS", sizeof("BLOCK_CODE_BYZANTINE_MUSICAL_SYMBOLS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_BYZANTINE_MUSICAL_SYMBOLS_name, &const_BLOCK_CODE_BYZANTINE_MUSICAL_SYMBOLS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_BYZANTINE_MUSICAL_SYMBOLS_name); + zend_string_release_ex(const_BLOCK_CODE_BYZANTINE_MUSICAL_SYMBOLS_name, true); zval const_BLOCK_CODE_MUSICAL_SYMBOLS_value; ZVAL_LONG(&const_BLOCK_CODE_MUSICAL_SYMBOLS_value, UBLOCK_MUSICAL_SYMBOLS); - zend_string *const_BLOCK_CODE_MUSICAL_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_MUSICAL_SYMBOLS", sizeof("BLOCK_CODE_MUSICAL_SYMBOLS") - 1, 1); + zend_string *const_BLOCK_CODE_MUSICAL_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_MUSICAL_SYMBOLS", sizeof("BLOCK_CODE_MUSICAL_SYMBOLS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MUSICAL_SYMBOLS_name, &const_BLOCK_CODE_MUSICAL_SYMBOLS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MUSICAL_SYMBOLS_name); + zend_string_release_ex(const_BLOCK_CODE_MUSICAL_SYMBOLS_name, true); zval const_BLOCK_CODE_MATHEMATICAL_ALPHANUMERIC_SYMBOLS_value; ZVAL_LONG(&const_BLOCK_CODE_MATHEMATICAL_ALPHANUMERIC_SYMBOLS_value, UBLOCK_MATHEMATICAL_ALPHANUMERIC_SYMBOLS); - zend_string *const_BLOCK_CODE_MATHEMATICAL_ALPHANUMERIC_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_MATHEMATICAL_ALPHANUMERIC_SYMBOLS", sizeof("BLOCK_CODE_MATHEMATICAL_ALPHANUMERIC_SYMBOLS") - 1, 1); + zend_string *const_BLOCK_CODE_MATHEMATICAL_ALPHANUMERIC_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_MATHEMATICAL_ALPHANUMERIC_SYMBOLS", sizeof("BLOCK_CODE_MATHEMATICAL_ALPHANUMERIC_SYMBOLS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MATHEMATICAL_ALPHANUMERIC_SYMBOLS_name, &const_BLOCK_CODE_MATHEMATICAL_ALPHANUMERIC_SYMBOLS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MATHEMATICAL_ALPHANUMERIC_SYMBOLS_name); + zend_string_release_ex(const_BLOCK_CODE_MATHEMATICAL_ALPHANUMERIC_SYMBOLS_name, true); zval const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B_value; ZVAL_LONG(&const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B_value, UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B); - zend_string *const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B_name = zend_string_init_interned("BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B", sizeof("BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B") - 1, 1); + zend_string *const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B_name = zend_string_init_interned("BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B", sizeof("BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B_name, &const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B_name); + zend_string_release_ex(const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B_name, true); zval const_BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT_value; ZVAL_LONG(&const_BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT_value, UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT); - zend_string *const_BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT", sizeof("BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT") - 1, 1); + zend_string *const_BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT", sizeof("BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT_name, &const_BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT_name); + zend_string_release_ex(const_BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT_name, true); zval const_BLOCK_CODE_TAGS_value; ZVAL_LONG(&const_BLOCK_CODE_TAGS_value, UBLOCK_TAGS); - zend_string *const_BLOCK_CODE_TAGS_name = zend_string_init_interned("BLOCK_CODE_TAGS", sizeof("BLOCK_CODE_TAGS") - 1, 1); + zend_string *const_BLOCK_CODE_TAGS_name = zend_string_init_interned("BLOCK_CODE_TAGS", sizeof("BLOCK_CODE_TAGS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_TAGS_name, &const_BLOCK_CODE_TAGS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_TAGS_name); + zend_string_release_ex(const_BLOCK_CODE_TAGS_name, true); zval const_BLOCK_CODE_CYRILLIC_SUPPLEMENT_value; ZVAL_LONG(&const_BLOCK_CODE_CYRILLIC_SUPPLEMENT_value, UBLOCK_CYRILLIC_SUPPLEMENT); - zend_string *const_BLOCK_CODE_CYRILLIC_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_CYRILLIC_SUPPLEMENT", sizeof("BLOCK_CODE_CYRILLIC_SUPPLEMENT") - 1, 1); + zend_string *const_BLOCK_CODE_CYRILLIC_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_CYRILLIC_SUPPLEMENT", sizeof("BLOCK_CODE_CYRILLIC_SUPPLEMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CYRILLIC_SUPPLEMENT_name, &const_BLOCK_CODE_CYRILLIC_SUPPLEMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CYRILLIC_SUPPLEMENT_name); + zend_string_release_ex(const_BLOCK_CODE_CYRILLIC_SUPPLEMENT_name, true); zval const_BLOCK_CODE_CYRILLIC_SUPPLEMENTARY_value; ZVAL_LONG(&const_BLOCK_CODE_CYRILLIC_SUPPLEMENTARY_value, UBLOCK_CYRILLIC_SUPPLEMENTARY); - zend_string *const_BLOCK_CODE_CYRILLIC_SUPPLEMENTARY_name = zend_string_init_interned("BLOCK_CODE_CYRILLIC_SUPPLEMENTARY", sizeof("BLOCK_CODE_CYRILLIC_SUPPLEMENTARY") - 1, 1); + zend_string *const_BLOCK_CODE_CYRILLIC_SUPPLEMENTARY_name = zend_string_init_interned("BLOCK_CODE_CYRILLIC_SUPPLEMENTARY", sizeof("BLOCK_CODE_CYRILLIC_SUPPLEMENTARY") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CYRILLIC_SUPPLEMENTARY_name, &const_BLOCK_CODE_CYRILLIC_SUPPLEMENTARY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CYRILLIC_SUPPLEMENTARY_name); + zend_string_release_ex(const_BLOCK_CODE_CYRILLIC_SUPPLEMENTARY_name, true); zval const_BLOCK_CODE_TAGALOG_value; ZVAL_LONG(&const_BLOCK_CODE_TAGALOG_value, UBLOCK_TAGALOG); - zend_string *const_BLOCK_CODE_TAGALOG_name = zend_string_init_interned("BLOCK_CODE_TAGALOG", sizeof("BLOCK_CODE_TAGALOG") - 1, 1); + zend_string *const_BLOCK_CODE_TAGALOG_name = zend_string_init_interned("BLOCK_CODE_TAGALOG", sizeof("BLOCK_CODE_TAGALOG") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_TAGALOG_name, &const_BLOCK_CODE_TAGALOG_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_TAGALOG_name); + zend_string_release_ex(const_BLOCK_CODE_TAGALOG_name, true); zval const_BLOCK_CODE_HANUNOO_value; ZVAL_LONG(&const_BLOCK_CODE_HANUNOO_value, UBLOCK_HANUNOO); - zend_string *const_BLOCK_CODE_HANUNOO_name = zend_string_init_interned("BLOCK_CODE_HANUNOO", sizeof("BLOCK_CODE_HANUNOO") - 1, 1); + zend_string *const_BLOCK_CODE_HANUNOO_name = zend_string_init_interned("BLOCK_CODE_HANUNOO", sizeof("BLOCK_CODE_HANUNOO") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_HANUNOO_name, &const_BLOCK_CODE_HANUNOO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_HANUNOO_name); + zend_string_release_ex(const_BLOCK_CODE_HANUNOO_name, true); zval const_BLOCK_CODE_BUHID_value; ZVAL_LONG(&const_BLOCK_CODE_BUHID_value, UBLOCK_BUHID); - zend_string *const_BLOCK_CODE_BUHID_name = zend_string_init_interned("BLOCK_CODE_BUHID", sizeof("BLOCK_CODE_BUHID") - 1, 1); + zend_string *const_BLOCK_CODE_BUHID_name = zend_string_init_interned("BLOCK_CODE_BUHID", sizeof("BLOCK_CODE_BUHID") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_BUHID_name, &const_BLOCK_CODE_BUHID_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_BUHID_name); + zend_string_release_ex(const_BLOCK_CODE_BUHID_name, true); zval const_BLOCK_CODE_TAGBANWA_value; ZVAL_LONG(&const_BLOCK_CODE_TAGBANWA_value, UBLOCK_TAGBANWA); - zend_string *const_BLOCK_CODE_TAGBANWA_name = zend_string_init_interned("BLOCK_CODE_TAGBANWA", sizeof("BLOCK_CODE_TAGBANWA") - 1, 1); + zend_string *const_BLOCK_CODE_TAGBANWA_name = zend_string_init_interned("BLOCK_CODE_TAGBANWA", sizeof("BLOCK_CODE_TAGBANWA") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_TAGBANWA_name, &const_BLOCK_CODE_TAGBANWA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_TAGBANWA_name); + zend_string_release_ex(const_BLOCK_CODE_TAGBANWA_name, true); zval const_BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A_value; ZVAL_LONG(&const_BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A_value, UBLOCK_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A); - zend_string *const_BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A_name = zend_string_init_interned("BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A", sizeof("BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A") - 1, 1); + zend_string *const_BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A_name = zend_string_init_interned("BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A", sizeof("BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A_name, &const_BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A_name); + zend_string_release_ex(const_BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A_name, true); zval const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_A_value; ZVAL_LONG(&const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_A_value, UBLOCK_SUPPLEMENTAL_ARROWS_A); - zend_string *const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_A_name = zend_string_init_interned("BLOCK_CODE_SUPPLEMENTAL_ARROWS_A", sizeof("BLOCK_CODE_SUPPLEMENTAL_ARROWS_A") - 1, 1); + zend_string *const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_A_name = zend_string_init_interned("BLOCK_CODE_SUPPLEMENTAL_ARROWS_A", sizeof("BLOCK_CODE_SUPPLEMENTAL_ARROWS_A") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_A_name, &const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_A_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_A_name); + zend_string_release_ex(const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_A_name, true); zval const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_B_value; ZVAL_LONG(&const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_B_value, UBLOCK_SUPPLEMENTAL_ARROWS_B); - zend_string *const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_B_name = zend_string_init_interned("BLOCK_CODE_SUPPLEMENTAL_ARROWS_B", sizeof("BLOCK_CODE_SUPPLEMENTAL_ARROWS_B") - 1, 1); + zend_string *const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_B_name = zend_string_init_interned("BLOCK_CODE_SUPPLEMENTAL_ARROWS_B", sizeof("BLOCK_CODE_SUPPLEMENTAL_ARROWS_B") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_B_name, &const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_B_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_B_name); + zend_string_release_ex(const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_B_name, true); zval const_BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B_value; ZVAL_LONG(&const_BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B_value, UBLOCK_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B); - zend_string *const_BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B_name = zend_string_init_interned("BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B", sizeof("BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B") - 1, 1); + zend_string *const_BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B_name = zend_string_init_interned("BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B", sizeof("BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B_name, &const_BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B_name); + zend_string_release_ex(const_BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B_name, true); zval const_BLOCK_CODE_SUPPLEMENTAL_MATHEMATICAL_OPERATORS_value; ZVAL_LONG(&const_BLOCK_CODE_SUPPLEMENTAL_MATHEMATICAL_OPERATORS_value, UBLOCK_SUPPLEMENTAL_MATHEMATICAL_OPERATORS); - zend_string *const_BLOCK_CODE_SUPPLEMENTAL_MATHEMATICAL_OPERATORS_name = zend_string_init_interned("BLOCK_CODE_SUPPLEMENTAL_MATHEMATICAL_OPERATORS", sizeof("BLOCK_CODE_SUPPLEMENTAL_MATHEMATICAL_OPERATORS") - 1, 1); + zend_string *const_BLOCK_CODE_SUPPLEMENTAL_MATHEMATICAL_OPERATORS_name = zend_string_init_interned("BLOCK_CODE_SUPPLEMENTAL_MATHEMATICAL_OPERATORS", sizeof("BLOCK_CODE_SUPPLEMENTAL_MATHEMATICAL_OPERATORS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SUPPLEMENTAL_MATHEMATICAL_OPERATORS_name, &const_BLOCK_CODE_SUPPLEMENTAL_MATHEMATICAL_OPERATORS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SUPPLEMENTAL_MATHEMATICAL_OPERATORS_name); + zend_string_release_ex(const_BLOCK_CODE_SUPPLEMENTAL_MATHEMATICAL_OPERATORS_name, true); zval const_BLOCK_CODE_KATAKANA_PHONETIC_EXTENSIONS_value; ZVAL_LONG(&const_BLOCK_CODE_KATAKANA_PHONETIC_EXTENSIONS_value, UBLOCK_KATAKANA_PHONETIC_EXTENSIONS); - zend_string *const_BLOCK_CODE_KATAKANA_PHONETIC_EXTENSIONS_name = zend_string_init_interned("BLOCK_CODE_KATAKANA_PHONETIC_EXTENSIONS", sizeof("BLOCK_CODE_KATAKANA_PHONETIC_EXTENSIONS") - 1, 1); + zend_string *const_BLOCK_CODE_KATAKANA_PHONETIC_EXTENSIONS_name = zend_string_init_interned("BLOCK_CODE_KATAKANA_PHONETIC_EXTENSIONS", sizeof("BLOCK_CODE_KATAKANA_PHONETIC_EXTENSIONS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_KATAKANA_PHONETIC_EXTENSIONS_name, &const_BLOCK_CODE_KATAKANA_PHONETIC_EXTENSIONS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_KATAKANA_PHONETIC_EXTENSIONS_name); + zend_string_release_ex(const_BLOCK_CODE_KATAKANA_PHONETIC_EXTENSIONS_name, true); zval const_BLOCK_CODE_VARIATION_SELECTORS_value; ZVAL_LONG(&const_BLOCK_CODE_VARIATION_SELECTORS_value, UBLOCK_VARIATION_SELECTORS); - zend_string *const_BLOCK_CODE_VARIATION_SELECTORS_name = zend_string_init_interned("BLOCK_CODE_VARIATION_SELECTORS", sizeof("BLOCK_CODE_VARIATION_SELECTORS") - 1, 1); + zend_string *const_BLOCK_CODE_VARIATION_SELECTORS_name = zend_string_init_interned("BLOCK_CODE_VARIATION_SELECTORS", sizeof("BLOCK_CODE_VARIATION_SELECTORS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_VARIATION_SELECTORS_name, &const_BLOCK_CODE_VARIATION_SELECTORS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_VARIATION_SELECTORS_name); + zend_string_release_ex(const_BLOCK_CODE_VARIATION_SELECTORS_name, true); zval const_BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_A_value; ZVAL_LONG(&const_BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_A_value, UBLOCK_SUPPLEMENTARY_PRIVATE_USE_AREA_A); - zend_string *const_BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_A_name = zend_string_init_interned("BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_A", sizeof("BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_A") - 1, 1); + zend_string *const_BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_A_name = zend_string_init_interned("BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_A", sizeof("BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_A") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_A_name, &const_BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_A_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_A_name); + zend_string_release_ex(const_BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_A_name, true); zval const_BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_B_value; ZVAL_LONG(&const_BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_B_value, UBLOCK_SUPPLEMENTARY_PRIVATE_USE_AREA_B); - zend_string *const_BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_B_name = zend_string_init_interned("BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_B", sizeof("BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_B") - 1, 1); + zend_string *const_BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_B_name = zend_string_init_interned("BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_B", sizeof("BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_B") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_B_name, &const_BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_B_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_B_name); + zend_string_release_ex(const_BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_B_name, true); zval const_BLOCK_CODE_LIMBU_value; ZVAL_LONG(&const_BLOCK_CODE_LIMBU_value, UBLOCK_LIMBU); - zend_string *const_BLOCK_CODE_LIMBU_name = zend_string_init_interned("BLOCK_CODE_LIMBU", sizeof("BLOCK_CODE_LIMBU") - 1, 1); + zend_string *const_BLOCK_CODE_LIMBU_name = zend_string_init_interned("BLOCK_CODE_LIMBU", sizeof("BLOCK_CODE_LIMBU") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_LIMBU_name, &const_BLOCK_CODE_LIMBU_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_LIMBU_name); + zend_string_release_ex(const_BLOCK_CODE_LIMBU_name, true); zval const_BLOCK_CODE_TAI_LE_value; ZVAL_LONG(&const_BLOCK_CODE_TAI_LE_value, UBLOCK_TAI_LE); - zend_string *const_BLOCK_CODE_TAI_LE_name = zend_string_init_interned("BLOCK_CODE_TAI_LE", sizeof("BLOCK_CODE_TAI_LE") - 1, 1); + zend_string *const_BLOCK_CODE_TAI_LE_name = zend_string_init_interned("BLOCK_CODE_TAI_LE", sizeof("BLOCK_CODE_TAI_LE") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_TAI_LE_name, &const_BLOCK_CODE_TAI_LE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_TAI_LE_name); + zend_string_release_ex(const_BLOCK_CODE_TAI_LE_name, true); zval const_BLOCK_CODE_KHMER_SYMBOLS_value; ZVAL_LONG(&const_BLOCK_CODE_KHMER_SYMBOLS_value, UBLOCK_KHMER_SYMBOLS); - zend_string *const_BLOCK_CODE_KHMER_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_KHMER_SYMBOLS", sizeof("BLOCK_CODE_KHMER_SYMBOLS") - 1, 1); + zend_string *const_BLOCK_CODE_KHMER_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_KHMER_SYMBOLS", sizeof("BLOCK_CODE_KHMER_SYMBOLS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_KHMER_SYMBOLS_name, &const_BLOCK_CODE_KHMER_SYMBOLS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_KHMER_SYMBOLS_name); + zend_string_release_ex(const_BLOCK_CODE_KHMER_SYMBOLS_name, true); zval const_BLOCK_CODE_PHONETIC_EXTENSIONS_value; ZVAL_LONG(&const_BLOCK_CODE_PHONETIC_EXTENSIONS_value, UBLOCK_PHONETIC_EXTENSIONS); - zend_string *const_BLOCK_CODE_PHONETIC_EXTENSIONS_name = zend_string_init_interned("BLOCK_CODE_PHONETIC_EXTENSIONS", sizeof("BLOCK_CODE_PHONETIC_EXTENSIONS") - 1, 1); + zend_string *const_BLOCK_CODE_PHONETIC_EXTENSIONS_name = zend_string_init_interned("BLOCK_CODE_PHONETIC_EXTENSIONS", sizeof("BLOCK_CODE_PHONETIC_EXTENSIONS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_PHONETIC_EXTENSIONS_name, &const_BLOCK_CODE_PHONETIC_EXTENSIONS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_PHONETIC_EXTENSIONS_name); + zend_string_release_ex(const_BLOCK_CODE_PHONETIC_EXTENSIONS_name, true); zval const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_ARROWS_value; ZVAL_LONG(&const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_ARROWS_value, UBLOCK_MISCELLANEOUS_SYMBOLS_AND_ARROWS); - zend_string *const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_ARROWS_name = zend_string_init_interned("BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_ARROWS", sizeof("BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_ARROWS") - 1, 1); + zend_string *const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_ARROWS_name = zend_string_init_interned("BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_ARROWS", sizeof("BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_ARROWS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_ARROWS_name, &const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_ARROWS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_ARROWS_name); + zend_string_release_ex(const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_ARROWS_name, true); zval const_BLOCK_CODE_YIJING_HEXAGRAM_SYMBOLS_value; ZVAL_LONG(&const_BLOCK_CODE_YIJING_HEXAGRAM_SYMBOLS_value, UBLOCK_YIJING_HEXAGRAM_SYMBOLS); - zend_string *const_BLOCK_CODE_YIJING_HEXAGRAM_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_YIJING_HEXAGRAM_SYMBOLS", sizeof("BLOCK_CODE_YIJING_HEXAGRAM_SYMBOLS") - 1, 1); + zend_string *const_BLOCK_CODE_YIJING_HEXAGRAM_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_YIJING_HEXAGRAM_SYMBOLS", sizeof("BLOCK_CODE_YIJING_HEXAGRAM_SYMBOLS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_YIJING_HEXAGRAM_SYMBOLS_name, &const_BLOCK_CODE_YIJING_HEXAGRAM_SYMBOLS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_YIJING_HEXAGRAM_SYMBOLS_name); + zend_string_release_ex(const_BLOCK_CODE_YIJING_HEXAGRAM_SYMBOLS_name, true); zval const_BLOCK_CODE_LINEAR_B_SYLLABARY_value; ZVAL_LONG(&const_BLOCK_CODE_LINEAR_B_SYLLABARY_value, UBLOCK_LINEAR_B_SYLLABARY); - zend_string *const_BLOCK_CODE_LINEAR_B_SYLLABARY_name = zend_string_init_interned("BLOCK_CODE_LINEAR_B_SYLLABARY", sizeof("BLOCK_CODE_LINEAR_B_SYLLABARY") - 1, 1); + zend_string *const_BLOCK_CODE_LINEAR_B_SYLLABARY_name = zend_string_init_interned("BLOCK_CODE_LINEAR_B_SYLLABARY", sizeof("BLOCK_CODE_LINEAR_B_SYLLABARY") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_LINEAR_B_SYLLABARY_name, &const_BLOCK_CODE_LINEAR_B_SYLLABARY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_LINEAR_B_SYLLABARY_name); + zend_string_release_ex(const_BLOCK_CODE_LINEAR_B_SYLLABARY_name, true); zval const_BLOCK_CODE_LINEAR_B_IDEOGRAMS_value; ZVAL_LONG(&const_BLOCK_CODE_LINEAR_B_IDEOGRAMS_value, UBLOCK_LINEAR_B_IDEOGRAMS); - zend_string *const_BLOCK_CODE_LINEAR_B_IDEOGRAMS_name = zend_string_init_interned("BLOCK_CODE_LINEAR_B_IDEOGRAMS", sizeof("BLOCK_CODE_LINEAR_B_IDEOGRAMS") - 1, 1); + zend_string *const_BLOCK_CODE_LINEAR_B_IDEOGRAMS_name = zend_string_init_interned("BLOCK_CODE_LINEAR_B_IDEOGRAMS", sizeof("BLOCK_CODE_LINEAR_B_IDEOGRAMS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_LINEAR_B_IDEOGRAMS_name, &const_BLOCK_CODE_LINEAR_B_IDEOGRAMS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_LINEAR_B_IDEOGRAMS_name); + zend_string_release_ex(const_BLOCK_CODE_LINEAR_B_IDEOGRAMS_name, true); zval const_BLOCK_CODE_AEGEAN_NUMBERS_value; ZVAL_LONG(&const_BLOCK_CODE_AEGEAN_NUMBERS_value, UBLOCK_AEGEAN_NUMBERS); - zend_string *const_BLOCK_CODE_AEGEAN_NUMBERS_name = zend_string_init_interned("BLOCK_CODE_AEGEAN_NUMBERS", sizeof("BLOCK_CODE_AEGEAN_NUMBERS") - 1, 1); + zend_string *const_BLOCK_CODE_AEGEAN_NUMBERS_name = zend_string_init_interned("BLOCK_CODE_AEGEAN_NUMBERS", sizeof("BLOCK_CODE_AEGEAN_NUMBERS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_AEGEAN_NUMBERS_name, &const_BLOCK_CODE_AEGEAN_NUMBERS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_AEGEAN_NUMBERS_name); + zend_string_release_ex(const_BLOCK_CODE_AEGEAN_NUMBERS_name, true); zval const_BLOCK_CODE_UGARITIC_value; ZVAL_LONG(&const_BLOCK_CODE_UGARITIC_value, UBLOCK_UGARITIC); - zend_string *const_BLOCK_CODE_UGARITIC_name = zend_string_init_interned("BLOCK_CODE_UGARITIC", sizeof("BLOCK_CODE_UGARITIC") - 1, 1); + zend_string *const_BLOCK_CODE_UGARITIC_name = zend_string_init_interned("BLOCK_CODE_UGARITIC", sizeof("BLOCK_CODE_UGARITIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_UGARITIC_name, &const_BLOCK_CODE_UGARITIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_UGARITIC_name); + zend_string_release_ex(const_BLOCK_CODE_UGARITIC_name, true); zval const_BLOCK_CODE_SHAVIAN_value; ZVAL_LONG(&const_BLOCK_CODE_SHAVIAN_value, UBLOCK_SHAVIAN); - zend_string *const_BLOCK_CODE_SHAVIAN_name = zend_string_init_interned("BLOCK_CODE_SHAVIAN", sizeof("BLOCK_CODE_SHAVIAN") - 1, 1); + zend_string *const_BLOCK_CODE_SHAVIAN_name = zend_string_init_interned("BLOCK_CODE_SHAVIAN", sizeof("BLOCK_CODE_SHAVIAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SHAVIAN_name, &const_BLOCK_CODE_SHAVIAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SHAVIAN_name); + zend_string_release_ex(const_BLOCK_CODE_SHAVIAN_name, true); zval const_BLOCK_CODE_OSMANYA_value; ZVAL_LONG(&const_BLOCK_CODE_OSMANYA_value, UBLOCK_OSMANYA); - zend_string *const_BLOCK_CODE_OSMANYA_name = zend_string_init_interned("BLOCK_CODE_OSMANYA", sizeof("BLOCK_CODE_OSMANYA") - 1, 1); + zend_string *const_BLOCK_CODE_OSMANYA_name = zend_string_init_interned("BLOCK_CODE_OSMANYA", sizeof("BLOCK_CODE_OSMANYA") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_OSMANYA_name, &const_BLOCK_CODE_OSMANYA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_OSMANYA_name); + zend_string_release_ex(const_BLOCK_CODE_OSMANYA_name, true); zval const_BLOCK_CODE_CYPRIOT_SYLLABARY_value; ZVAL_LONG(&const_BLOCK_CODE_CYPRIOT_SYLLABARY_value, UBLOCK_CYPRIOT_SYLLABARY); - zend_string *const_BLOCK_CODE_CYPRIOT_SYLLABARY_name = zend_string_init_interned("BLOCK_CODE_CYPRIOT_SYLLABARY", sizeof("BLOCK_CODE_CYPRIOT_SYLLABARY") - 1, 1); + zend_string *const_BLOCK_CODE_CYPRIOT_SYLLABARY_name = zend_string_init_interned("BLOCK_CODE_CYPRIOT_SYLLABARY", sizeof("BLOCK_CODE_CYPRIOT_SYLLABARY") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CYPRIOT_SYLLABARY_name, &const_BLOCK_CODE_CYPRIOT_SYLLABARY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CYPRIOT_SYLLABARY_name); + zend_string_release_ex(const_BLOCK_CODE_CYPRIOT_SYLLABARY_name, true); zval const_BLOCK_CODE_TAI_XUAN_JING_SYMBOLS_value; ZVAL_LONG(&const_BLOCK_CODE_TAI_XUAN_JING_SYMBOLS_value, UBLOCK_TAI_XUAN_JING_SYMBOLS); - zend_string *const_BLOCK_CODE_TAI_XUAN_JING_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_TAI_XUAN_JING_SYMBOLS", sizeof("BLOCK_CODE_TAI_XUAN_JING_SYMBOLS") - 1, 1); + zend_string *const_BLOCK_CODE_TAI_XUAN_JING_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_TAI_XUAN_JING_SYMBOLS", sizeof("BLOCK_CODE_TAI_XUAN_JING_SYMBOLS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_TAI_XUAN_JING_SYMBOLS_name, &const_BLOCK_CODE_TAI_XUAN_JING_SYMBOLS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_TAI_XUAN_JING_SYMBOLS_name); + zend_string_release_ex(const_BLOCK_CODE_TAI_XUAN_JING_SYMBOLS_name, true); zval const_BLOCK_CODE_VARIATION_SELECTORS_SUPPLEMENT_value; ZVAL_LONG(&const_BLOCK_CODE_VARIATION_SELECTORS_SUPPLEMENT_value, UBLOCK_VARIATION_SELECTORS_SUPPLEMENT); - zend_string *const_BLOCK_CODE_VARIATION_SELECTORS_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_VARIATION_SELECTORS_SUPPLEMENT", sizeof("BLOCK_CODE_VARIATION_SELECTORS_SUPPLEMENT") - 1, 1); + zend_string *const_BLOCK_CODE_VARIATION_SELECTORS_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_VARIATION_SELECTORS_SUPPLEMENT", sizeof("BLOCK_CODE_VARIATION_SELECTORS_SUPPLEMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_VARIATION_SELECTORS_SUPPLEMENT_name, &const_BLOCK_CODE_VARIATION_SELECTORS_SUPPLEMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_VARIATION_SELECTORS_SUPPLEMENT_name); + zend_string_release_ex(const_BLOCK_CODE_VARIATION_SELECTORS_SUPPLEMENT_name, true); zval const_BLOCK_CODE_ANCIENT_GREEK_MUSICAL_NOTATION_value; ZVAL_LONG(&const_BLOCK_CODE_ANCIENT_GREEK_MUSICAL_NOTATION_value, UBLOCK_ANCIENT_GREEK_MUSICAL_NOTATION); - zend_string *const_BLOCK_CODE_ANCIENT_GREEK_MUSICAL_NOTATION_name = zend_string_init_interned("BLOCK_CODE_ANCIENT_GREEK_MUSICAL_NOTATION", sizeof("BLOCK_CODE_ANCIENT_GREEK_MUSICAL_NOTATION") - 1, 1); + zend_string *const_BLOCK_CODE_ANCIENT_GREEK_MUSICAL_NOTATION_name = zend_string_init_interned("BLOCK_CODE_ANCIENT_GREEK_MUSICAL_NOTATION", sizeof("BLOCK_CODE_ANCIENT_GREEK_MUSICAL_NOTATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ANCIENT_GREEK_MUSICAL_NOTATION_name, &const_BLOCK_CODE_ANCIENT_GREEK_MUSICAL_NOTATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ANCIENT_GREEK_MUSICAL_NOTATION_name); + zend_string_release_ex(const_BLOCK_CODE_ANCIENT_GREEK_MUSICAL_NOTATION_name, true); zval const_BLOCK_CODE_ANCIENT_GREEK_NUMBERS_value; ZVAL_LONG(&const_BLOCK_CODE_ANCIENT_GREEK_NUMBERS_value, UBLOCK_ANCIENT_GREEK_NUMBERS); - zend_string *const_BLOCK_CODE_ANCIENT_GREEK_NUMBERS_name = zend_string_init_interned("BLOCK_CODE_ANCIENT_GREEK_NUMBERS", sizeof("BLOCK_CODE_ANCIENT_GREEK_NUMBERS") - 1, 1); + zend_string *const_BLOCK_CODE_ANCIENT_GREEK_NUMBERS_name = zend_string_init_interned("BLOCK_CODE_ANCIENT_GREEK_NUMBERS", sizeof("BLOCK_CODE_ANCIENT_GREEK_NUMBERS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ANCIENT_GREEK_NUMBERS_name, &const_BLOCK_CODE_ANCIENT_GREEK_NUMBERS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ANCIENT_GREEK_NUMBERS_name); + zend_string_release_ex(const_BLOCK_CODE_ANCIENT_GREEK_NUMBERS_name, true); zval const_BLOCK_CODE_ARABIC_SUPPLEMENT_value; ZVAL_LONG(&const_BLOCK_CODE_ARABIC_SUPPLEMENT_value, UBLOCK_ARABIC_SUPPLEMENT); - zend_string *const_BLOCK_CODE_ARABIC_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_ARABIC_SUPPLEMENT", sizeof("BLOCK_CODE_ARABIC_SUPPLEMENT") - 1, 1); + zend_string *const_BLOCK_CODE_ARABIC_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_ARABIC_SUPPLEMENT", sizeof("BLOCK_CODE_ARABIC_SUPPLEMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ARABIC_SUPPLEMENT_name, &const_BLOCK_CODE_ARABIC_SUPPLEMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ARABIC_SUPPLEMENT_name); + zend_string_release_ex(const_BLOCK_CODE_ARABIC_SUPPLEMENT_name, true); zval const_BLOCK_CODE_BUGINESE_value; ZVAL_LONG(&const_BLOCK_CODE_BUGINESE_value, UBLOCK_BUGINESE); - zend_string *const_BLOCK_CODE_BUGINESE_name = zend_string_init_interned("BLOCK_CODE_BUGINESE", sizeof("BLOCK_CODE_BUGINESE") - 1, 1); + zend_string *const_BLOCK_CODE_BUGINESE_name = zend_string_init_interned("BLOCK_CODE_BUGINESE", sizeof("BLOCK_CODE_BUGINESE") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_BUGINESE_name, &const_BLOCK_CODE_BUGINESE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_BUGINESE_name); + zend_string_release_ex(const_BLOCK_CODE_BUGINESE_name, true); zval const_BLOCK_CODE_CJK_STROKES_value; ZVAL_LONG(&const_BLOCK_CODE_CJK_STROKES_value, UBLOCK_CJK_STROKES); - zend_string *const_BLOCK_CODE_CJK_STROKES_name = zend_string_init_interned("BLOCK_CODE_CJK_STROKES", sizeof("BLOCK_CODE_CJK_STROKES") - 1, 1); + zend_string *const_BLOCK_CODE_CJK_STROKES_name = zend_string_init_interned("BLOCK_CODE_CJK_STROKES", sizeof("BLOCK_CODE_CJK_STROKES") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CJK_STROKES_name, &const_BLOCK_CODE_CJK_STROKES_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CJK_STROKES_name); + zend_string_release_ex(const_BLOCK_CODE_CJK_STROKES_name, true); zval const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_SUPPLEMENT_value; ZVAL_LONG(&const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_SUPPLEMENT_value, UBLOCK_COMBINING_DIACRITICAL_MARKS_SUPPLEMENT); - zend_string *const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_SUPPLEMENT", sizeof("BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_SUPPLEMENT") - 1, 1); + zend_string *const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_SUPPLEMENT", sizeof("BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_SUPPLEMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_SUPPLEMENT_name, &const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_SUPPLEMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_SUPPLEMENT_name); + zend_string_release_ex(const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_SUPPLEMENT_name, true); zval const_BLOCK_CODE_COPTIC_value; ZVAL_LONG(&const_BLOCK_CODE_COPTIC_value, UBLOCK_COPTIC); - zend_string *const_BLOCK_CODE_COPTIC_name = zend_string_init_interned("BLOCK_CODE_COPTIC", sizeof("BLOCK_CODE_COPTIC") - 1, 1); + zend_string *const_BLOCK_CODE_COPTIC_name = zend_string_init_interned("BLOCK_CODE_COPTIC", sizeof("BLOCK_CODE_COPTIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_COPTIC_name, &const_BLOCK_CODE_COPTIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_COPTIC_name); + zend_string_release_ex(const_BLOCK_CODE_COPTIC_name, true); zval const_BLOCK_CODE_ETHIOPIC_EXTENDED_value; ZVAL_LONG(&const_BLOCK_CODE_ETHIOPIC_EXTENDED_value, UBLOCK_ETHIOPIC_EXTENDED); - zend_string *const_BLOCK_CODE_ETHIOPIC_EXTENDED_name = zend_string_init_interned("BLOCK_CODE_ETHIOPIC_EXTENDED", sizeof("BLOCK_CODE_ETHIOPIC_EXTENDED") - 1, 1); + zend_string *const_BLOCK_CODE_ETHIOPIC_EXTENDED_name = zend_string_init_interned("BLOCK_CODE_ETHIOPIC_EXTENDED", sizeof("BLOCK_CODE_ETHIOPIC_EXTENDED") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ETHIOPIC_EXTENDED_name, &const_BLOCK_CODE_ETHIOPIC_EXTENDED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ETHIOPIC_EXTENDED_name); + zend_string_release_ex(const_BLOCK_CODE_ETHIOPIC_EXTENDED_name, true); zval const_BLOCK_CODE_ETHIOPIC_SUPPLEMENT_value; ZVAL_LONG(&const_BLOCK_CODE_ETHIOPIC_SUPPLEMENT_value, UBLOCK_ETHIOPIC_SUPPLEMENT); - zend_string *const_BLOCK_CODE_ETHIOPIC_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_ETHIOPIC_SUPPLEMENT", sizeof("BLOCK_CODE_ETHIOPIC_SUPPLEMENT") - 1, 1); + zend_string *const_BLOCK_CODE_ETHIOPIC_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_ETHIOPIC_SUPPLEMENT", sizeof("BLOCK_CODE_ETHIOPIC_SUPPLEMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ETHIOPIC_SUPPLEMENT_name, &const_BLOCK_CODE_ETHIOPIC_SUPPLEMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ETHIOPIC_SUPPLEMENT_name); + zend_string_release_ex(const_BLOCK_CODE_ETHIOPIC_SUPPLEMENT_name, true); zval const_BLOCK_CODE_GEORGIAN_SUPPLEMENT_value; ZVAL_LONG(&const_BLOCK_CODE_GEORGIAN_SUPPLEMENT_value, UBLOCK_GEORGIAN_SUPPLEMENT); - zend_string *const_BLOCK_CODE_GEORGIAN_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_GEORGIAN_SUPPLEMENT", sizeof("BLOCK_CODE_GEORGIAN_SUPPLEMENT") - 1, 1); + zend_string *const_BLOCK_CODE_GEORGIAN_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_GEORGIAN_SUPPLEMENT", sizeof("BLOCK_CODE_GEORGIAN_SUPPLEMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_GEORGIAN_SUPPLEMENT_name, &const_BLOCK_CODE_GEORGIAN_SUPPLEMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_GEORGIAN_SUPPLEMENT_name); + zend_string_release_ex(const_BLOCK_CODE_GEORGIAN_SUPPLEMENT_name, true); zval const_BLOCK_CODE_GLAGOLITIC_value; ZVAL_LONG(&const_BLOCK_CODE_GLAGOLITIC_value, UBLOCK_GLAGOLITIC); - zend_string *const_BLOCK_CODE_GLAGOLITIC_name = zend_string_init_interned("BLOCK_CODE_GLAGOLITIC", sizeof("BLOCK_CODE_GLAGOLITIC") - 1, 1); + zend_string *const_BLOCK_CODE_GLAGOLITIC_name = zend_string_init_interned("BLOCK_CODE_GLAGOLITIC", sizeof("BLOCK_CODE_GLAGOLITIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_GLAGOLITIC_name, &const_BLOCK_CODE_GLAGOLITIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_GLAGOLITIC_name); + zend_string_release_ex(const_BLOCK_CODE_GLAGOLITIC_name, true); zval const_BLOCK_CODE_KHAROSHTHI_value; ZVAL_LONG(&const_BLOCK_CODE_KHAROSHTHI_value, UBLOCK_KHAROSHTHI); - zend_string *const_BLOCK_CODE_KHAROSHTHI_name = zend_string_init_interned("BLOCK_CODE_KHAROSHTHI", sizeof("BLOCK_CODE_KHAROSHTHI") - 1, 1); + zend_string *const_BLOCK_CODE_KHAROSHTHI_name = zend_string_init_interned("BLOCK_CODE_KHAROSHTHI", sizeof("BLOCK_CODE_KHAROSHTHI") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_KHAROSHTHI_name, &const_BLOCK_CODE_KHAROSHTHI_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_KHAROSHTHI_name); + zend_string_release_ex(const_BLOCK_CODE_KHAROSHTHI_name, true); zval const_BLOCK_CODE_MODIFIER_TONE_LETTERS_value; ZVAL_LONG(&const_BLOCK_CODE_MODIFIER_TONE_LETTERS_value, UBLOCK_MODIFIER_TONE_LETTERS); - zend_string *const_BLOCK_CODE_MODIFIER_TONE_LETTERS_name = zend_string_init_interned("BLOCK_CODE_MODIFIER_TONE_LETTERS", sizeof("BLOCK_CODE_MODIFIER_TONE_LETTERS") - 1, 1); + zend_string *const_BLOCK_CODE_MODIFIER_TONE_LETTERS_name = zend_string_init_interned("BLOCK_CODE_MODIFIER_TONE_LETTERS", sizeof("BLOCK_CODE_MODIFIER_TONE_LETTERS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MODIFIER_TONE_LETTERS_name, &const_BLOCK_CODE_MODIFIER_TONE_LETTERS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MODIFIER_TONE_LETTERS_name); + zend_string_release_ex(const_BLOCK_CODE_MODIFIER_TONE_LETTERS_name, true); zval const_BLOCK_CODE_NEW_TAI_LUE_value; ZVAL_LONG(&const_BLOCK_CODE_NEW_TAI_LUE_value, UBLOCK_NEW_TAI_LUE); - zend_string *const_BLOCK_CODE_NEW_TAI_LUE_name = zend_string_init_interned("BLOCK_CODE_NEW_TAI_LUE", sizeof("BLOCK_CODE_NEW_TAI_LUE") - 1, 1); + zend_string *const_BLOCK_CODE_NEW_TAI_LUE_name = zend_string_init_interned("BLOCK_CODE_NEW_TAI_LUE", sizeof("BLOCK_CODE_NEW_TAI_LUE") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_NEW_TAI_LUE_name, &const_BLOCK_CODE_NEW_TAI_LUE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_NEW_TAI_LUE_name); + zend_string_release_ex(const_BLOCK_CODE_NEW_TAI_LUE_name, true); zval const_BLOCK_CODE_OLD_PERSIAN_value; ZVAL_LONG(&const_BLOCK_CODE_OLD_PERSIAN_value, UBLOCK_OLD_PERSIAN); - zend_string *const_BLOCK_CODE_OLD_PERSIAN_name = zend_string_init_interned("BLOCK_CODE_OLD_PERSIAN", sizeof("BLOCK_CODE_OLD_PERSIAN") - 1, 1); + zend_string *const_BLOCK_CODE_OLD_PERSIAN_name = zend_string_init_interned("BLOCK_CODE_OLD_PERSIAN", sizeof("BLOCK_CODE_OLD_PERSIAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_OLD_PERSIAN_name, &const_BLOCK_CODE_OLD_PERSIAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_OLD_PERSIAN_name); + zend_string_release_ex(const_BLOCK_CODE_OLD_PERSIAN_name, true); zval const_BLOCK_CODE_PHONETIC_EXTENSIONS_SUPPLEMENT_value; ZVAL_LONG(&const_BLOCK_CODE_PHONETIC_EXTENSIONS_SUPPLEMENT_value, UBLOCK_PHONETIC_EXTENSIONS_SUPPLEMENT); - zend_string *const_BLOCK_CODE_PHONETIC_EXTENSIONS_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_PHONETIC_EXTENSIONS_SUPPLEMENT", sizeof("BLOCK_CODE_PHONETIC_EXTENSIONS_SUPPLEMENT") - 1, 1); + zend_string *const_BLOCK_CODE_PHONETIC_EXTENSIONS_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_PHONETIC_EXTENSIONS_SUPPLEMENT", sizeof("BLOCK_CODE_PHONETIC_EXTENSIONS_SUPPLEMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_PHONETIC_EXTENSIONS_SUPPLEMENT_name, &const_BLOCK_CODE_PHONETIC_EXTENSIONS_SUPPLEMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_PHONETIC_EXTENSIONS_SUPPLEMENT_name); + zend_string_release_ex(const_BLOCK_CODE_PHONETIC_EXTENSIONS_SUPPLEMENT_name, true); zval const_BLOCK_CODE_SUPPLEMENTAL_PUNCTUATION_value; ZVAL_LONG(&const_BLOCK_CODE_SUPPLEMENTAL_PUNCTUATION_value, UBLOCK_SUPPLEMENTAL_PUNCTUATION); - zend_string *const_BLOCK_CODE_SUPPLEMENTAL_PUNCTUATION_name = zend_string_init_interned("BLOCK_CODE_SUPPLEMENTAL_PUNCTUATION", sizeof("BLOCK_CODE_SUPPLEMENTAL_PUNCTUATION") - 1, 1); + zend_string *const_BLOCK_CODE_SUPPLEMENTAL_PUNCTUATION_name = zend_string_init_interned("BLOCK_CODE_SUPPLEMENTAL_PUNCTUATION", sizeof("BLOCK_CODE_SUPPLEMENTAL_PUNCTUATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SUPPLEMENTAL_PUNCTUATION_name, &const_BLOCK_CODE_SUPPLEMENTAL_PUNCTUATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SUPPLEMENTAL_PUNCTUATION_name); + zend_string_release_ex(const_BLOCK_CODE_SUPPLEMENTAL_PUNCTUATION_name, true); zval const_BLOCK_CODE_SYLOTI_NAGRI_value; ZVAL_LONG(&const_BLOCK_CODE_SYLOTI_NAGRI_value, UBLOCK_SYLOTI_NAGRI); - zend_string *const_BLOCK_CODE_SYLOTI_NAGRI_name = zend_string_init_interned("BLOCK_CODE_SYLOTI_NAGRI", sizeof("BLOCK_CODE_SYLOTI_NAGRI") - 1, 1); + zend_string *const_BLOCK_CODE_SYLOTI_NAGRI_name = zend_string_init_interned("BLOCK_CODE_SYLOTI_NAGRI", sizeof("BLOCK_CODE_SYLOTI_NAGRI") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SYLOTI_NAGRI_name, &const_BLOCK_CODE_SYLOTI_NAGRI_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SYLOTI_NAGRI_name); + zend_string_release_ex(const_BLOCK_CODE_SYLOTI_NAGRI_name, true); zval const_BLOCK_CODE_TIFINAGH_value; ZVAL_LONG(&const_BLOCK_CODE_TIFINAGH_value, UBLOCK_TIFINAGH); - zend_string *const_BLOCK_CODE_TIFINAGH_name = zend_string_init_interned("BLOCK_CODE_TIFINAGH", sizeof("BLOCK_CODE_TIFINAGH") - 1, 1); + zend_string *const_BLOCK_CODE_TIFINAGH_name = zend_string_init_interned("BLOCK_CODE_TIFINAGH", sizeof("BLOCK_CODE_TIFINAGH") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_TIFINAGH_name, &const_BLOCK_CODE_TIFINAGH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_TIFINAGH_name); + zend_string_release_ex(const_BLOCK_CODE_TIFINAGH_name, true); zval const_BLOCK_CODE_VERTICAL_FORMS_value; ZVAL_LONG(&const_BLOCK_CODE_VERTICAL_FORMS_value, UBLOCK_VERTICAL_FORMS); - zend_string *const_BLOCK_CODE_VERTICAL_FORMS_name = zend_string_init_interned("BLOCK_CODE_VERTICAL_FORMS", sizeof("BLOCK_CODE_VERTICAL_FORMS") - 1, 1); + zend_string *const_BLOCK_CODE_VERTICAL_FORMS_name = zend_string_init_interned("BLOCK_CODE_VERTICAL_FORMS", sizeof("BLOCK_CODE_VERTICAL_FORMS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_VERTICAL_FORMS_name, &const_BLOCK_CODE_VERTICAL_FORMS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_VERTICAL_FORMS_name); + zend_string_release_ex(const_BLOCK_CODE_VERTICAL_FORMS_name, true); zval const_BLOCK_CODE_NKO_value; ZVAL_LONG(&const_BLOCK_CODE_NKO_value, UBLOCK_NKO); - zend_string *const_BLOCK_CODE_NKO_name = zend_string_init_interned("BLOCK_CODE_NKO", sizeof("BLOCK_CODE_NKO") - 1, 1); + zend_string *const_BLOCK_CODE_NKO_name = zend_string_init_interned("BLOCK_CODE_NKO", sizeof("BLOCK_CODE_NKO") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_NKO_name, &const_BLOCK_CODE_NKO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_NKO_name); + zend_string_release_ex(const_BLOCK_CODE_NKO_name, true); zval const_BLOCK_CODE_BALINESE_value; ZVAL_LONG(&const_BLOCK_CODE_BALINESE_value, UBLOCK_BALINESE); - zend_string *const_BLOCK_CODE_BALINESE_name = zend_string_init_interned("BLOCK_CODE_BALINESE", sizeof("BLOCK_CODE_BALINESE") - 1, 1); + zend_string *const_BLOCK_CODE_BALINESE_name = zend_string_init_interned("BLOCK_CODE_BALINESE", sizeof("BLOCK_CODE_BALINESE") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_BALINESE_name, &const_BLOCK_CODE_BALINESE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_BALINESE_name); + zend_string_release_ex(const_BLOCK_CODE_BALINESE_name, true); zval const_BLOCK_CODE_LATIN_EXTENDED_C_value; ZVAL_LONG(&const_BLOCK_CODE_LATIN_EXTENDED_C_value, UBLOCK_LATIN_EXTENDED_C); - zend_string *const_BLOCK_CODE_LATIN_EXTENDED_C_name = zend_string_init_interned("BLOCK_CODE_LATIN_EXTENDED_C", sizeof("BLOCK_CODE_LATIN_EXTENDED_C") - 1, 1); + zend_string *const_BLOCK_CODE_LATIN_EXTENDED_C_name = zend_string_init_interned("BLOCK_CODE_LATIN_EXTENDED_C", sizeof("BLOCK_CODE_LATIN_EXTENDED_C") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_LATIN_EXTENDED_C_name, &const_BLOCK_CODE_LATIN_EXTENDED_C_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_LATIN_EXTENDED_C_name); + zend_string_release_ex(const_BLOCK_CODE_LATIN_EXTENDED_C_name, true); zval const_BLOCK_CODE_LATIN_EXTENDED_D_value; ZVAL_LONG(&const_BLOCK_CODE_LATIN_EXTENDED_D_value, UBLOCK_LATIN_EXTENDED_D); - zend_string *const_BLOCK_CODE_LATIN_EXTENDED_D_name = zend_string_init_interned("BLOCK_CODE_LATIN_EXTENDED_D", sizeof("BLOCK_CODE_LATIN_EXTENDED_D") - 1, 1); + zend_string *const_BLOCK_CODE_LATIN_EXTENDED_D_name = zend_string_init_interned("BLOCK_CODE_LATIN_EXTENDED_D", sizeof("BLOCK_CODE_LATIN_EXTENDED_D") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_LATIN_EXTENDED_D_name, &const_BLOCK_CODE_LATIN_EXTENDED_D_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_LATIN_EXTENDED_D_name); + zend_string_release_ex(const_BLOCK_CODE_LATIN_EXTENDED_D_name, true); zval const_BLOCK_CODE_PHAGS_PA_value; ZVAL_LONG(&const_BLOCK_CODE_PHAGS_PA_value, UBLOCK_PHAGS_PA); - zend_string *const_BLOCK_CODE_PHAGS_PA_name = zend_string_init_interned("BLOCK_CODE_PHAGS_PA", sizeof("BLOCK_CODE_PHAGS_PA") - 1, 1); + zend_string *const_BLOCK_CODE_PHAGS_PA_name = zend_string_init_interned("BLOCK_CODE_PHAGS_PA", sizeof("BLOCK_CODE_PHAGS_PA") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_PHAGS_PA_name, &const_BLOCK_CODE_PHAGS_PA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_PHAGS_PA_name); + zend_string_release_ex(const_BLOCK_CODE_PHAGS_PA_name, true); zval const_BLOCK_CODE_PHOENICIAN_value; ZVAL_LONG(&const_BLOCK_CODE_PHOENICIAN_value, UBLOCK_PHOENICIAN); - zend_string *const_BLOCK_CODE_PHOENICIAN_name = zend_string_init_interned("BLOCK_CODE_PHOENICIAN", sizeof("BLOCK_CODE_PHOENICIAN") - 1, 1); + zend_string *const_BLOCK_CODE_PHOENICIAN_name = zend_string_init_interned("BLOCK_CODE_PHOENICIAN", sizeof("BLOCK_CODE_PHOENICIAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_PHOENICIAN_name, &const_BLOCK_CODE_PHOENICIAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_PHOENICIAN_name); + zend_string_release_ex(const_BLOCK_CODE_PHOENICIAN_name, true); zval const_BLOCK_CODE_CUNEIFORM_value; ZVAL_LONG(&const_BLOCK_CODE_CUNEIFORM_value, UBLOCK_CUNEIFORM); - zend_string *const_BLOCK_CODE_CUNEIFORM_name = zend_string_init_interned("BLOCK_CODE_CUNEIFORM", sizeof("BLOCK_CODE_CUNEIFORM") - 1, 1); + zend_string *const_BLOCK_CODE_CUNEIFORM_name = zend_string_init_interned("BLOCK_CODE_CUNEIFORM", sizeof("BLOCK_CODE_CUNEIFORM") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CUNEIFORM_name, &const_BLOCK_CODE_CUNEIFORM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CUNEIFORM_name); + zend_string_release_ex(const_BLOCK_CODE_CUNEIFORM_name, true); zval const_BLOCK_CODE_CUNEIFORM_NUMBERS_AND_PUNCTUATION_value; ZVAL_LONG(&const_BLOCK_CODE_CUNEIFORM_NUMBERS_AND_PUNCTUATION_value, UBLOCK_CUNEIFORM_NUMBERS_AND_PUNCTUATION); - zend_string *const_BLOCK_CODE_CUNEIFORM_NUMBERS_AND_PUNCTUATION_name = zend_string_init_interned("BLOCK_CODE_CUNEIFORM_NUMBERS_AND_PUNCTUATION", sizeof("BLOCK_CODE_CUNEIFORM_NUMBERS_AND_PUNCTUATION") - 1, 1); + zend_string *const_BLOCK_CODE_CUNEIFORM_NUMBERS_AND_PUNCTUATION_name = zend_string_init_interned("BLOCK_CODE_CUNEIFORM_NUMBERS_AND_PUNCTUATION", sizeof("BLOCK_CODE_CUNEIFORM_NUMBERS_AND_PUNCTUATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CUNEIFORM_NUMBERS_AND_PUNCTUATION_name, &const_BLOCK_CODE_CUNEIFORM_NUMBERS_AND_PUNCTUATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CUNEIFORM_NUMBERS_AND_PUNCTUATION_name); + zend_string_release_ex(const_BLOCK_CODE_CUNEIFORM_NUMBERS_AND_PUNCTUATION_name, true); zval const_BLOCK_CODE_COUNTING_ROD_NUMERALS_value; ZVAL_LONG(&const_BLOCK_CODE_COUNTING_ROD_NUMERALS_value, UBLOCK_COUNTING_ROD_NUMERALS); - zend_string *const_BLOCK_CODE_COUNTING_ROD_NUMERALS_name = zend_string_init_interned("BLOCK_CODE_COUNTING_ROD_NUMERALS", sizeof("BLOCK_CODE_COUNTING_ROD_NUMERALS") - 1, 1); + zend_string *const_BLOCK_CODE_COUNTING_ROD_NUMERALS_name = zend_string_init_interned("BLOCK_CODE_COUNTING_ROD_NUMERALS", sizeof("BLOCK_CODE_COUNTING_ROD_NUMERALS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_COUNTING_ROD_NUMERALS_name, &const_BLOCK_CODE_COUNTING_ROD_NUMERALS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_COUNTING_ROD_NUMERALS_name); + zend_string_release_ex(const_BLOCK_CODE_COUNTING_ROD_NUMERALS_name, true); zval const_BLOCK_CODE_SUNDANESE_value; ZVAL_LONG(&const_BLOCK_CODE_SUNDANESE_value, UBLOCK_SUNDANESE); - zend_string *const_BLOCK_CODE_SUNDANESE_name = zend_string_init_interned("BLOCK_CODE_SUNDANESE", sizeof("BLOCK_CODE_SUNDANESE") - 1, 1); + zend_string *const_BLOCK_CODE_SUNDANESE_name = zend_string_init_interned("BLOCK_CODE_SUNDANESE", sizeof("BLOCK_CODE_SUNDANESE") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SUNDANESE_name, &const_BLOCK_CODE_SUNDANESE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SUNDANESE_name); + zend_string_release_ex(const_BLOCK_CODE_SUNDANESE_name, true); zval const_BLOCK_CODE_LEPCHA_value; ZVAL_LONG(&const_BLOCK_CODE_LEPCHA_value, UBLOCK_LEPCHA); - zend_string *const_BLOCK_CODE_LEPCHA_name = zend_string_init_interned("BLOCK_CODE_LEPCHA", sizeof("BLOCK_CODE_LEPCHA") - 1, 1); + zend_string *const_BLOCK_CODE_LEPCHA_name = zend_string_init_interned("BLOCK_CODE_LEPCHA", sizeof("BLOCK_CODE_LEPCHA") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_LEPCHA_name, &const_BLOCK_CODE_LEPCHA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_LEPCHA_name); + zend_string_release_ex(const_BLOCK_CODE_LEPCHA_name, true); zval const_BLOCK_CODE_OL_CHIKI_value; ZVAL_LONG(&const_BLOCK_CODE_OL_CHIKI_value, UBLOCK_OL_CHIKI); - zend_string *const_BLOCK_CODE_OL_CHIKI_name = zend_string_init_interned("BLOCK_CODE_OL_CHIKI", sizeof("BLOCK_CODE_OL_CHIKI") - 1, 1); + zend_string *const_BLOCK_CODE_OL_CHIKI_name = zend_string_init_interned("BLOCK_CODE_OL_CHIKI", sizeof("BLOCK_CODE_OL_CHIKI") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_OL_CHIKI_name, &const_BLOCK_CODE_OL_CHIKI_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_OL_CHIKI_name); + zend_string_release_ex(const_BLOCK_CODE_OL_CHIKI_name, true); zval const_BLOCK_CODE_CYRILLIC_EXTENDED_A_value; ZVAL_LONG(&const_BLOCK_CODE_CYRILLIC_EXTENDED_A_value, UBLOCK_CYRILLIC_EXTENDED_A); - zend_string *const_BLOCK_CODE_CYRILLIC_EXTENDED_A_name = zend_string_init_interned("BLOCK_CODE_CYRILLIC_EXTENDED_A", sizeof("BLOCK_CODE_CYRILLIC_EXTENDED_A") - 1, 1); + zend_string *const_BLOCK_CODE_CYRILLIC_EXTENDED_A_name = zend_string_init_interned("BLOCK_CODE_CYRILLIC_EXTENDED_A", sizeof("BLOCK_CODE_CYRILLIC_EXTENDED_A") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CYRILLIC_EXTENDED_A_name, &const_BLOCK_CODE_CYRILLIC_EXTENDED_A_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CYRILLIC_EXTENDED_A_name); + zend_string_release_ex(const_BLOCK_CODE_CYRILLIC_EXTENDED_A_name, true); zval const_BLOCK_CODE_VAI_value; ZVAL_LONG(&const_BLOCK_CODE_VAI_value, UBLOCK_VAI); - zend_string *const_BLOCK_CODE_VAI_name = zend_string_init_interned("BLOCK_CODE_VAI", sizeof("BLOCK_CODE_VAI") - 1, 1); + zend_string *const_BLOCK_CODE_VAI_name = zend_string_init_interned("BLOCK_CODE_VAI", sizeof("BLOCK_CODE_VAI") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_VAI_name, &const_BLOCK_CODE_VAI_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_VAI_name); + zend_string_release_ex(const_BLOCK_CODE_VAI_name, true); zval const_BLOCK_CODE_CYRILLIC_EXTENDED_B_value; ZVAL_LONG(&const_BLOCK_CODE_CYRILLIC_EXTENDED_B_value, UBLOCK_CYRILLIC_EXTENDED_B); - zend_string *const_BLOCK_CODE_CYRILLIC_EXTENDED_B_name = zend_string_init_interned("BLOCK_CODE_CYRILLIC_EXTENDED_B", sizeof("BLOCK_CODE_CYRILLIC_EXTENDED_B") - 1, 1); + zend_string *const_BLOCK_CODE_CYRILLIC_EXTENDED_B_name = zend_string_init_interned("BLOCK_CODE_CYRILLIC_EXTENDED_B", sizeof("BLOCK_CODE_CYRILLIC_EXTENDED_B") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CYRILLIC_EXTENDED_B_name, &const_BLOCK_CODE_CYRILLIC_EXTENDED_B_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CYRILLIC_EXTENDED_B_name); + zend_string_release_ex(const_BLOCK_CODE_CYRILLIC_EXTENDED_B_name, true); zval const_BLOCK_CODE_SAURASHTRA_value; ZVAL_LONG(&const_BLOCK_CODE_SAURASHTRA_value, UBLOCK_SAURASHTRA); - zend_string *const_BLOCK_CODE_SAURASHTRA_name = zend_string_init_interned("BLOCK_CODE_SAURASHTRA", sizeof("BLOCK_CODE_SAURASHTRA") - 1, 1); + zend_string *const_BLOCK_CODE_SAURASHTRA_name = zend_string_init_interned("BLOCK_CODE_SAURASHTRA", sizeof("BLOCK_CODE_SAURASHTRA") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SAURASHTRA_name, &const_BLOCK_CODE_SAURASHTRA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SAURASHTRA_name); + zend_string_release_ex(const_BLOCK_CODE_SAURASHTRA_name, true); zval const_BLOCK_CODE_KAYAH_LI_value; ZVAL_LONG(&const_BLOCK_CODE_KAYAH_LI_value, UBLOCK_KAYAH_LI); - zend_string *const_BLOCK_CODE_KAYAH_LI_name = zend_string_init_interned("BLOCK_CODE_KAYAH_LI", sizeof("BLOCK_CODE_KAYAH_LI") - 1, 1); + zend_string *const_BLOCK_CODE_KAYAH_LI_name = zend_string_init_interned("BLOCK_CODE_KAYAH_LI", sizeof("BLOCK_CODE_KAYAH_LI") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_KAYAH_LI_name, &const_BLOCK_CODE_KAYAH_LI_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_KAYAH_LI_name); + zend_string_release_ex(const_BLOCK_CODE_KAYAH_LI_name, true); zval const_BLOCK_CODE_REJANG_value; ZVAL_LONG(&const_BLOCK_CODE_REJANG_value, UBLOCK_REJANG); - zend_string *const_BLOCK_CODE_REJANG_name = zend_string_init_interned("BLOCK_CODE_REJANG", sizeof("BLOCK_CODE_REJANG") - 1, 1); + zend_string *const_BLOCK_CODE_REJANG_name = zend_string_init_interned("BLOCK_CODE_REJANG", sizeof("BLOCK_CODE_REJANG") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_REJANG_name, &const_BLOCK_CODE_REJANG_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_REJANG_name); + zend_string_release_ex(const_BLOCK_CODE_REJANG_name, true); zval const_BLOCK_CODE_CHAM_value; ZVAL_LONG(&const_BLOCK_CODE_CHAM_value, UBLOCK_CHAM); - zend_string *const_BLOCK_CODE_CHAM_name = zend_string_init_interned("BLOCK_CODE_CHAM", sizeof("BLOCK_CODE_CHAM") - 1, 1); + zend_string *const_BLOCK_CODE_CHAM_name = zend_string_init_interned("BLOCK_CODE_CHAM", sizeof("BLOCK_CODE_CHAM") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CHAM_name, &const_BLOCK_CODE_CHAM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CHAM_name); + zend_string_release_ex(const_BLOCK_CODE_CHAM_name, true); zval const_BLOCK_CODE_ANCIENT_SYMBOLS_value; ZVAL_LONG(&const_BLOCK_CODE_ANCIENT_SYMBOLS_value, UBLOCK_ANCIENT_SYMBOLS); - zend_string *const_BLOCK_CODE_ANCIENT_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_ANCIENT_SYMBOLS", sizeof("BLOCK_CODE_ANCIENT_SYMBOLS") - 1, 1); + zend_string *const_BLOCK_CODE_ANCIENT_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_ANCIENT_SYMBOLS", sizeof("BLOCK_CODE_ANCIENT_SYMBOLS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ANCIENT_SYMBOLS_name, &const_BLOCK_CODE_ANCIENT_SYMBOLS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ANCIENT_SYMBOLS_name); + zend_string_release_ex(const_BLOCK_CODE_ANCIENT_SYMBOLS_name, true); zval const_BLOCK_CODE_PHAISTOS_DISC_value; ZVAL_LONG(&const_BLOCK_CODE_PHAISTOS_DISC_value, UBLOCK_PHAISTOS_DISC); - zend_string *const_BLOCK_CODE_PHAISTOS_DISC_name = zend_string_init_interned("BLOCK_CODE_PHAISTOS_DISC", sizeof("BLOCK_CODE_PHAISTOS_DISC") - 1, 1); + zend_string *const_BLOCK_CODE_PHAISTOS_DISC_name = zend_string_init_interned("BLOCK_CODE_PHAISTOS_DISC", sizeof("BLOCK_CODE_PHAISTOS_DISC") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_PHAISTOS_DISC_name, &const_BLOCK_CODE_PHAISTOS_DISC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_PHAISTOS_DISC_name); + zend_string_release_ex(const_BLOCK_CODE_PHAISTOS_DISC_name, true); zval const_BLOCK_CODE_LYCIAN_value; ZVAL_LONG(&const_BLOCK_CODE_LYCIAN_value, UBLOCK_LYCIAN); - zend_string *const_BLOCK_CODE_LYCIAN_name = zend_string_init_interned("BLOCK_CODE_LYCIAN", sizeof("BLOCK_CODE_LYCIAN") - 1, 1); + zend_string *const_BLOCK_CODE_LYCIAN_name = zend_string_init_interned("BLOCK_CODE_LYCIAN", sizeof("BLOCK_CODE_LYCIAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_LYCIAN_name, &const_BLOCK_CODE_LYCIAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_LYCIAN_name); + zend_string_release_ex(const_BLOCK_CODE_LYCIAN_name, true); zval const_BLOCK_CODE_CARIAN_value; ZVAL_LONG(&const_BLOCK_CODE_CARIAN_value, UBLOCK_CARIAN); - zend_string *const_BLOCK_CODE_CARIAN_name = zend_string_init_interned("BLOCK_CODE_CARIAN", sizeof("BLOCK_CODE_CARIAN") - 1, 1); + zend_string *const_BLOCK_CODE_CARIAN_name = zend_string_init_interned("BLOCK_CODE_CARIAN", sizeof("BLOCK_CODE_CARIAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CARIAN_name, &const_BLOCK_CODE_CARIAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CARIAN_name); + zend_string_release_ex(const_BLOCK_CODE_CARIAN_name, true); zval const_BLOCK_CODE_LYDIAN_value; ZVAL_LONG(&const_BLOCK_CODE_LYDIAN_value, UBLOCK_LYDIAN); - zend_string *const_BLOCK_CODE_LYDIAN_name = zend_string_init_interned("BLOCK_CODE_LYDIAN", sizeof("BLOCK_CODE_LYDIAN") - 1, 1); + zend_string *const_BLOCK_CODE_LYDIAN_name = zend_string_init_interned("BLOCK_CODE_LYDIAN", sizeof("BLOCK_CODE_LYDIAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_LYDIAN_name, &const_BLOCK_CODE_LYDIAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_LYDIAN_name); + zend_string_release_ex(const_BLOCK_CODE_LYDIAN_name, true); zval const_BLOCK_CODE_MAHJONG_TILES_value; ZVAL_LONG(&const_BLOCK_CODE_MAHJONG_TILES_value, UBLOCK_MAHJONG_TILES); - zend_string *const_BLOCK_CODE_MAHJONG_TILES_name = zend_string_init_interned("BLOCK_CODE_MAHJONG_TILES", sizeof("BLOCK_CODE_MAHJONG_TILES") - 1, 1); + zend_string *const_BLOCK_CODE_MAHJONG_TILES_name = zend_string_init_interned("BLOCK_CODE_MAHJONG_TILES", sizeof("BLOCK_CODE_MAHJONG_TILES") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MAHJONG_TILES_name, &const_BLOCK_CODE_MAHJONG_TILES_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MAHJONG_TILES_name); + zend_string_release_ex(const_BLOCK_CODE_MAHJONG_TILES_name, true); zval const_BLOCK_CODE_DOMINO_TILES_value; ZVAL_LONG(&const_BLOCK_CODE_DOMINO_TILES_value, UBLOCK_DOMINO_TILES); - zend_string *const_BLOCK_CODE_DOMINO_TILES_name = zend_string_init_interned("BLOCK_CODE_DOMINO_TILES", sizeof("BLOCK_CODE_DOMINO_TILES") - 1, 1); + zend_string *const_BLOCK_CODE_DOMINO_TILES_name = zend_string_init_interned("BLOCK_CODE_DOMINO_TILES", sizeof("BLOCK_CODE_DOMINO_TILES") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_DOMINO_TILES_name, &const_BLOCK_CODE_DOMINO_TILES_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_DOMINO_TILES_name); + zend_string_release_ex(const_BLOCK_CODE_DOMINO_TILES_name, true); zval const_BLOCK_CODE_SAMARITAN_value; ZVAL_LONG(&const_BLOCK_CODE_SAMARITAN_value, UBLOCK_SAMARITAN); - zend_string *const_BLOCK_CODE_SAMARITAN_name = zend_string_init_interned("BLOCK_CODE_SAMARITAN", sizeof("BLOCK_CODE_SAMARITAN") - 1, 1); + zend_string *const_BLOCK_CODE_SAMARITAN_name = zend_string_init_interned("BLOCK_CODE_SAMARITAN", sizeof("BLOCK_CODE_SAMARITAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SAMARITAN_name, &const_BLOCK_CODE_SAMARITAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SAMARITAN_name); + zend_string_release_ex(const_BLOCK_CODE_SAMARITAN_name, true); zval const_BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED_value; ZVAL_LONG(&const_BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED_value, UBLOCK_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED); - zend_string *const_BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED_name = zend_string_init_interned("BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED", sizeof("BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED") - 1, 1); + zend_string *const_BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED_name = zend_string_init_interned("BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED", sizeof("BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED_name, &const_BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED_name); + zend_string_release_ex(const_BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED_name, true); zval const_BLOCK_CODE_TAI_THAM_value; ZVAL_LONG(&const_BLOCK_CODE_TAI_THAM_value, UBLOCK_TAI_THAM); - zend_string *const_BLOCK_CODE_TAI_THAM_name = zend_string_init_interned("BLOCK_CODE_TAI_THAM", sizeof("BLOCK_CODE_TAI_THAM") - 1, 1); + zend_string *const_BLOCK_CODE_TAI_THAM_name = zend_string_init_interned("BLOCK_CODE_TAI_THAM", sizeof("BLOCK_CODE_TAI_THAM") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_TAI_THAM_name, &const_BLOCK_CODE_TAI_THAM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_TAI_THAM_name); + zend_string_release_ex(const_BLOCK_CODE_TAI_THAM_name, true); zval const_BLOCK_CODE_VEDIC_EXTENSIONS_value; ZVAL_LONG(&const_BLOCK_CODE_VEDIC_EXTENSIONS_value, UBLOCK_VEDIC_EXTENSIONS); - zend_string *const_BLOCK_CODE_VEDIC_EXTENSIONS_name = zend_string_init_interned("BLOCK_CODE_VEDIC_EXTENSIONS", sizeof("BLOCK_CODE_VEDIC_EXTENSIONS") - 1, 1); + zend_string *const_BLOCK_CODE_VEDIC_EXTENSIONS_name = zend_string_init_interned("BLOCK_CODE_VEDIC_EXTENSIONS", sizeof("BLOCK_CODE_VEDIC_EXTENSIONS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_VEDIC_EXTENSIONS_name, &const_BLOCK_CODE_VEDIC_EXTENSIONS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_VEDIC_EXTENSIONS_name); + zend_string_release_ex(const_BLOCK_CODE_VEDIC_EXTENSIONS_name, true); zval const_BLOCK_CODE_LISU_value; ZVAL_LONG(&const_BLOCK_CODE_LISU_value, UBLOCK_LISU); - zend_string *const_BLOCK_CODE_LISU_name = zend_string_init_interned("BLOCK_CODE_LISU", sizeof("BLOCK_CODE_LISU") - 1, 1); + zend_string *const_BLOCK_CODE_LISU_name = zend_string_init_interned("BLOCK_CODE_LISU", sizeof("BLOCK_CODE_LISU") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_LISU_name, &const_BLOCK_CODE_LISU_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_LISU_name); + zend_string_release_ex(const_BLOCK_CODE_LISU_name, true); zval const_BLOCK_CODE_BAMUM_value; ZVAL_LONG(&const_BLOCK_CODE_BAMUM_value, UBLOCK_BAMUM); - zend_string *const_BLOCK_CODE_BAMUM_name = zend_string_init_interned("BLOCK_CODE_BAMUM", sizeof("BLOCK_CODE_BAMUM") - 1, 1); + zend_string *const_BLOCK_CODE_BAMUM_name = zend_string_init_interned("BLOCK_CODE_BAMUM", sizeof("BLOCK_CODE_BAMUM") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_BAMUM_name, &const_BLOCK_CODE_BAMUM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_BAMUM_name); + zend_string_release_ex(const_BLOCK_CODE_BAMUM_name, true); zval const_BLOCK_CODE_COMMON_INDIC_NUMBER_FORMS_value; ZVAL_LONG(&const_BLOCK_CODE_COMMON_INDIC_NUMBER_FORMS_value, UBLOCK_COMMON_INDIC_NUMBER_FORMS); - zend_string *const_BLOCK_CODE_COMMON_INDIC_NUMBER_FORMS_name = zend_string_init_interned("BLOCK_CODE_COMMON_INDIC_NUMBER_FORMS", sizeof("BLOCK_CODE_COMMON_INDIC_NUMBER_FORMS") - 1, 1); + zend_string *const_BLOCK_CODE_COMMON_INDIC_NUMBER_FORMS_name = zend_string_init_interned("BLOCK_CODE_COMMON_INDIC_NUMBER_FORMS", sizeof("BLOCK_CODE_COMMON_INDIC_NUMBER_FORMS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_COMMON_INDIC_NUMBER_FORMS_name, &const_BLOCK_CODE_COMMON_INDIC_NUMBER_FORMS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_COMMON_INDIC_NUMBER_FORMS_name); + zend_string_release_ex(const_BLOCK_CODE_COMMON_INDIC_NUMBER_FORMS_name, true); zval const_BLOCK_CODE_DEVANAGARI_EXTENDED_value; ZVAL_LONG(&const_BLOCK_CODE_DEVANAGARI_EXTENDED_value, UBLOCK_DEVANAGARI_EXTENDED); - zend_string *const_BLOCK_CODE_DEVANAGARI_EXTENDED_name = zend_string_init_interned("BLOCK_CODE_DEVANAGARI_EXTENDED", sizeof("BLOCK_CODE_DEVANAGARI_EXTENDED") - 1, 1); + zend_string *const_BLOCK_CODE_DEVANAGARI_EXTENDED_name = zend_string_init_interned("BLOCK_CODE_DEVANAGARI_EXTENDED", sizeof("BLOCK_CODE_DEVANAGARI_EXTENDED") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_DEVANAGARI_EXTENDED_name, &const_BLOCK_CODE_DEVANAGARI_EXTENDED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_DEVANAGARI_EXTENDED_name); + zend_string_release_ex(const_BLOCK_CODE_DEVANAGARI_EXTENDED_name, true); zval const_BLOCK_CODE_HANGUL_JAMO_EXTENDED_A_value; ZVAL_LONG(&const_BLOCK_CODE_HANGUL_JAMO_EXTENDED_A_value, UBLOCK_HANGUL_JAMO_EXTENDED_A); - zend_string *const_BLOCK_CODE_HANGUL_JAMO_EXTENDED_A_name = zend_string_init_interned("BLOCK_CODE_HANGUL_JAMO_EXTENDED_A", sizeof("BLOCK_CODE_HANGUL_JAMO_EXTENDED_A") - 1, 1); + zend_string *const_BLOCK_CODE_HANGUL_JAMO_EXTENDED_A_name = zend_string_init_interned("BLOCK_CODE_HANGUL_JAMO_EXTENDED_A", sizeof("BLOCK_CODE_HANGUL_JAMO_EXTENDED_A") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_HANGUL_JAMO_EXTENDED_A_name, &const_BLOCK_CODE_HANGUL_JAMO_EXTENDED_A_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_HANGUL_JAMO_EXTENDED_A_name); + zend_string_release_ex(const_BLOCK_CODE_HANGUL_JAMO_EXTENDED_A_name, true); zval const_BLOCK_CODE_JAVANESE_value; ZVAL_LONG(&const_BLOCK_CODE_JAVANESE_value, UBLOCK_JAVANESE); - zend_string *const_BLOCK_CODE_JAVANESE_name = zend_string_init_interned("BLOCK_CODE_JAVANESE", sizeof("BLOCK_CODE_JAVANESE") - 1, 1); + zend_string *const_BLOCK_CODE_JAVANESE_name = zend_string_init_interned("BLOCK_CODE_JAVANESE", sizeof("BLOCK_CODE_JAVANESE") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_JAVANESE_name, &const_BLOCK_CODE_JAVANESE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_JAVANESE_name); + zend_string_release_ex(const_BLOCK_CODE_JAVANESE_name, true); zval const_BLOCK_CODE_MYANMAR_EXTENDED_A_value; ZVAL_LONG(&const_BLOCK_CODE_MYANMAR_EXTENDED_A_value, UBLOCK_MYANMAR_EXTENDED_A); - zend_string *const_BLOCK_CODE_MYANMAR_EXTENDED_A_name = zend_string_init_interned("BLOCK_CODE_MYANMAR_EXTENDED_A", sizeof("BLOCK_CODE_MYANMAR_EXTENDED_A") - 1, 1); + zend_string *const_BLOCK_CODE_MYANMAR_EXTENDED_A_name = zend_string_init_interned("BLOCK_CODE_MYANMAR_EXTENDED_A", sizeof("BLOCK_CODE_MYANMAR_EXTENDED_A") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MYANMAR_EXTENDED_A_name, &const_BLOCK_CODE_MYANMAR_EXTENDED_A_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MYANMAR_EXTENDED_A_name); + zend_string_release_ex(const_BLOCK_CODE_MYANMAR_EXTENDED_A_name, true); zval const_BLOCK_CODE_TAI_VIET_value; ZVAL_LONG(&const_BLOCK_CODE_TAI_VIET_value, UBLOCK_TAI_VIET); - zend_string *const_BLOCK_CODE_TAI_VIET_name = zend_string_init_interned("BLOCK_CODE_TAI_VIET", sizeof("BLOCK_CODE_TAI_VIET") - 1, 1); + zend_string *const_BLOCK_CODE_TAI_VIET_name = zend_string_init_interned("BLOCK_CODE_TAI_VIET", sizeof("BLOCK_CODE_TAI_VIET") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_TAI_VIET_name, &const_BLOCK_CODE_TAI_VIET_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_TAI_VIET_name); + zend_string_release_ex(const_BLOCK_CODE_TAI_VIET_name, true); zval const_BLOCK_CODE_MEETEI_MAYEK_value; ZVAL_LONG(&const_BLOCK_CODE_MEETEI_MAYEK_value, UBLOCK_MEETEI_MAYEK); - zend_string *const_BLOCK_CODE_MEETEI_MAYEK_name = zend_string_init_interned("BLOCK_CODE_MEETEI_MAYEK", sizeof("BLOCK_CODE_MEETEI_MAYEK") - 1, 1); + zend_string *const_BLOCK_CODE_MEETEI_MAYEK_name = zend_string_init_interned("BLOCK_CODE_MEETEI_MAYEK", sizeof("BLOCK_CODE_MEETEI_MAYEK") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MEETEI_MAYEK_name, &const_BLOCK_CODE_MEETEI_MAYEK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MEETEI_MAYEK_name); + zend_string_release_ex(const_BLOCK_CODE_MEETEI_MAYEK_name, true); zval const_BLOCK_CODE_HANGUL_JAMO_EXTENDED_B_value; ZVAL_LONG(&const_BLOCK_CODE_HANGUL_JAMO_EXTENDED_B_value, UBLOCK_HANGUL_JAMO_EXTENDED_B); - zend_string *const_BLOCK_CODE_HANGUL_JAMO_EXTENDED_B_name = zend_string_init_interned("BLOCK_CODE_HANGUL_JAMO_EXTENDED_B", sizeof("BLOCK_CODE_HANGUL_JAMO_EXTENDED_B") - 1, 1); + zend_string *const_BLOCK_CODE_HANGUL_JAMO_EXTENDED_B_name = zend_string_init_interned("BLOCK_CODE_HANGUL_JAMO_EXTENDED_B", sizeof("BLOCK_CODE_HANGUL_JAMO_EXTENDED_B") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_HANGUL_JAMO_EXTENDED_B_name, &const_BLOCK_CODE_HANGUL_JAMO_EXTENDED_B_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_HANGUL_JAMO_EXTENDED_B_name); + zend_string_release_ex(const_BLOCK_CODE_HANGUL_JAMO_EXTENDED_B_name, true); zval const_BLOCK_CODE_IMPERIAL_ARAMAIC_value; ZVAL_LONG(&const_BLOCK_CODE_IMPERIAL_ARAMAIC_value, UBLOCK_IMPERIAL_ARAMAIC); - zend_string *const_BLOCK_CODE_IMPERIAL_ARAMAIC_name = zend_string_init_interned("BLOCK_CODE_IMPERIAL_ARAMAIC", sizeof("BLOCK_CODE_IMPERIAL_ARAMAIC") - 1, 1); + zend_string *const_BLOCK_CODE_IMPERIAL_ARAMAIC_name = zend_string_init_interned("BLOCK_CODE_IMPERIAL_ARAMAIC", sizeof("BLOCK_CODE_IMPERIAL_ARAMAIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_IMPERIAL_ARAMAIC_name, &const_BLOCK_CODE_IMPERIAL_ARAMAIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_IMPERIAL_ARAMAIC_name); + zend_string_release_ex(const_BLOCK_CODE_IMPERIAL_ARAMAIC_name, true); zval const_BLOCK_CODE_OLD_SOUTH_ARABIAN_value; ZVAL_LONG(&const_BLOCK_CODE_OLD_SOUTH_ARABIAN_value, UBLOCK_OLD_SOUTH_ARABIAN); - zend_string *const_BLOCK_CODE_OLD_SOUTH_ARABIAN_name = zend_string_init_interned("BLOCK_CODE_OLD_SOUTH_ARABIAN", sizeof("BLOCK_CODE_OLD_SOUTH_ARABIAN") - 1, 1); + zend_string *const_BLOCK_CODE_OLD_SOUTH_ARABIAN_name = zend_string_init_interned("BLOCK_CODE_OLD_SOUTH_ARABIAN", sizeof("BLOCK_CODE_OLD_SOUTH_ARABIAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_OLD_SOUTH_ARABIAN_name, &const_BLOCK_CODE_OLD_SOUTH_ARABIAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_OLD_SOUTH_ARABIAN_name); + zend_string_release_ex(const_BLOCK_CODE_OLD_SOUTH_ARABIAN_name, true); zval const_BLOCK_CODE_AVESTAN_value; ZVAL_LONG(&const_BLOCK_CODE_AVESTAN_value, UBLOCK_AVESTAN); - zend_string *const_BLOCK_CODE_AVESTAN_name = zend_string_init_interned("BLOCK_CODE_AVESTAN", sizeof("BLOCK_CODE_AVESTAN") - 1, 1); + zend_string *const_BLOCK_CODE_AVESTAN_name = zend_string_init_interned("BLOCK_CODE_AVESTAN", sizeof("BLOCK_CODE_AVESTAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_AVESTAN_name, &const_BLOCK_CODE_AVESTAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_AVESTAN_name); + zend_string_release_ex(const_BLOCK_CODE_AVESTAN_name, true); zval const_BLOCK_CODE_INSCRIPTIONAL_PARTHIAN_value; ZVAL_LONG(&const_BLOCK_CODE_INSCRIPTIONAL_PARTHIAN_value, UBLOCK_INSCRIPTIONAL_PARTHIAN); - zend_string *const_BLOCK_CODE_INSCRIPTIONAL_PARTHIAN_name = zend_string_init_interned("BLOCK_CODE_INSCRIPTIONAL_PARTHIAN", sizeof("BLOCK_CODE_INSCRIPTIONAL_PARTHIAN") - 1, 1); + zend_string *const_BLOCK_CODE_INSCRIPTIONAL_PARTHIAN_name = zend_string_init_interned("BLOCK_CODE_INSCRIPTIONAL_PARTHIAN", sizeof("BLOCK_CODE_INSCRIPTIONAL_PARTHIAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_INSCRIPTIONAL_PARTHIAN_name, &const_BLOCK_CODE_INSCRIPTIONAL_PARTHIAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_INSCRIPTIONAL_PARTHIAN_name); + zend_string_release_ex(const_BLOCK_CODE_INSCRIPTIONAL_PARTHIAN_name, true); zval const_BLOCK_CODE_INSCRIPTIONAL_PAHLAVI_value; ZVAL_LONG(&const_BLOCK_CODE_INSCRIPTIONAL_PAHLAVI_value, UBLOCK_INSCRIPTIONAL_PAHLAVI); - zend_string *const_BLOCK_CODE_INSCRIPTIONAL_PAHLAVI_name = zend_string_init_interned("BLOCK_CODE_INSCRIPTIONAL_PAHLAVI", sizeof("BLOCK_CODE_INSCRIPTIONAL_PAHLAVI") - 1, 1); + zend_string *const_BLOCK_CODE_INSCRIPTIONAL_PAHLAVI_name = zend_string_init_interned("BLOCK_CODE_INSCRIPTIONAL_PAHLAVI", sizeof("BLOCK_CODE_INSCRIPTIONAL_PAHLAVI") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_INSCRIPTIONAL_PAHLAVI_name, &const_BLOCK_CODE_INSCRIPTIONAL_PAHLAVI_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_INSCRIPTIONAL_PAHLAVI_name); + zend_string_release_ex(const_BLOCK_CODE_INSCRIPTIONAL_PAHLAVI_name, true); zval const_BLOCK_CODE_OLD_TURKIC_value; ZVAL_LONG(&const_BLOCK_CODE_OLD_TURKIC_value, UBLOCK_OLD_TURKIC); - zend_string *const_BLOCK_CODE_OLD_TURKIC_name = zend_string_init_interned("BLOCK_CODE_OLD_TURKIC", sizeof("BLOCK_CODE_OLD_TURKIC") - 1, 1); + zend_string *const_BLOCK_CODE_OLD_TURKIC_name = zend_string_init_interned("BLOCK_CODE_OLD_TURKIC", sizeof("BLOCK_CODE_OLD_TURKIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_OLD_TURKIC_name, &const_BLOCK_CODE_OLD_TURKIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_OLD_TURKIC_name); + zend_string_release_ex(const_BLOCK_CODE_OLD_TURKIC_name, true); zval const_BLOCK_CODE_RUMI_NUMERAL_SYMBOLS_value; ZVAL_LONG(&const_BLOCK_CODE_RUMI_NUMERAL_SYMBOLS_value, UBLOCK_RUMI_NUMERAL_SYMBOLS); - zend_string *const_BLOCK_CODE_RUMI_NUMERAL_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_RUMI_NUMERAL_SYMBOLS", sizeof("BLOCK_CODE_RUMI_NUMERAL_SYMBOLS") - 1, 1); + zend_string *const_BLOCK_CODE_RUMI_NUMERAL_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_RUMI_NUMERAL_SYMBOLS", sizeof("BLOCK_CODE_RUMI_NUMERAL_SYMBOLS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_RUMI_NUMERAL_SYMBOLS_name, &const_BLOCK_CODE_RUMI_NUMERAL_SYMBOLS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_RUMI_NUMERAL_SYMBOLS_name); + zend_string_release_ex(const_BLOCK_CODE_RUMI_NUMERAL_SYMBOLS_name, true); zval const_BLOCK_CODE_KAITHI_value; ZVAL_LONG(&const_BLOCK_CODE_KAITHI_value, UBLOCK_KAITHI); - zend_string *const_BLOCK_CODE_KAITHI_name = zend_string_init_interned("BLOCK_CODE_KAITHI", sizeof("BLOCK_CODE_KAITHI") - 1, 1); + zend_string *const_BLOCK_CODE_KAITHI_name = zend_string_init_interned("BLOCK_CODE_KAITHI", sizeof("BLOCK_CODE_KAITHI") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_KAITHI_name, &const_BLOCK_CODE_KAITHI_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_KAITHI_name); + zend_string_release_ex(const_BLOCK_CODE_KAITHI_name, true); zval const_BLOCK_CODE_EGYPTIAN_HIEROGLYPHS_value; ZVAL_LONG(&const_BLOCK_CODE_EGYPTIAN_HIEROGLYPHS_value, UBLOCK_EGYPTIAN_HIEROGLYPHS); - zend_string *const_BLOCK_CODE_EGYPTIAN_HIEROGLYPHS_name = zend_string_init_interned("BLOCK_CODE_EGYPTIAN_HIEROGLYPHS", sizeof("BLOCK_CODE_EGYPTIAN_HIEROGLYPHS") - 1, 1); + zend_string *const_BLOCK_CODE_EGYPTIAN_HIEROGLYPHS_name = zend_string_init_interned("BLOCK_CODE_EGYPTIAN_HIEROGLYPHS", sizeof("BLOCK_CODE_EGYPTIAN_HIEROGLYPHS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_EGYPTIAN_HIEROGLYPHS_name, &const_BLOCK_CODE_EGYPTIAN_HIEROGLYPHS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_EGYPTIAN_HIEROGLYPHS_name); + zend_string_release_ex(const_BLOCK_CODE_EGYPTIAN_HIEROGLYPHS_name, true); zval const_BLOCK_CODE_ENCLOSED_ALPHANUMERIC_SUPPLEMENT_value; ZVAL_LONG(&const_BLOCK_CODE_ENCLOSED_ALPHANUMERIC_SUPPLEMENT_value, UBLOCK_ENCLOSED_ALPHANUMERIC_SUPPLEMENT); - zend_string *const_BLOCK_CODE_ENCLOSED_ALPHANUMERIC_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_ENCLOSED_ALPHANUMERIC_SUPPLEMENT", sizeof("BLOCK_CODE_ENCLOSED_ALPHANUMERIC_SUPPLEMENT") - 1, 1); + zend_string *const_BLOCK_CODE_ENCLOSED_ALPHANUMERIC_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_ENCLOSED_ALPHANUMERIC_SUPPLEMENT", sizeof("BLOCK_CODE_ENCLOSED_ALPHANUMERIC_SUPPLEMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ENCLOSED_ALPHANUMERIC_SUPPLEMENT_name, &const_BLOCK_CODE_ENCLOSED_ALPHANUMERIC_SUPPLEMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ENCLOSED_ALPHANUMERIC_SUPPLEMENT_name); + zend_string_release_ex(const_BLOCK_CODE_ENCLOSED_ALPHANUMERIC_SUPPLEMENT_name, true); zval const_BLOCK_CODE_ENCLOSED_IDEOGRAPHIC_SUPPLEMENT_value; ZVAL_LONG(&const_BLOCK_CODE_ENCLOSED_IDEOGRAPHIC_SUPPLEMENT_value, UBLOCK_ENCLOSED_IDEOGRAPHIC_SUPPLEMENT); - zend_string *const_BLOCK_CODE_ENCLOSED_IDEOGRAPHIC_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_ENCLOSED_IDEOGRAPHIC_SUPPLEMENT", sizeof("BLOCK_CODE_ENCLOSED_IDEOGRAPHIC_SUPPLEMENT") - 1, 1); + zend_string *const_BLOCK_CODE_ENCLOSED_IDEOGRAPHIC_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_ENCLOSED_IDEOGRAPHIC_SUPPLEMENT", sizeof("BLOCK_CODE_ENCLOSED_IDEOGRAPHIC_SUPPLEMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ENCLOSED_IDEOGRAPHIC_SUPPLEMENT_name, &const_BLOCK_CODE_ENCLOSED_IDEOGRAPHIC_SUPPLEMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ENCLOSED_IDEOGRAPHIC_SUPPLEMENT_name); + zend_string_release_ex(const_BLOCK_CODE_ENCLOSED_IDEOGRAPHIC_SUPPLEMENT_name, true); zval const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C_value; ZVAL_LONG(&const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C_value, UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C); - zend_string *const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C_name = zend_string_init_interned("BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C", sizeof("BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C") - 1, 1); + zend_string *const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C_name = zend_string_init_interned("BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C", sizeof("BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C_name, &const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C_name); + zend_string_release_ex(const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C_name, true); zval const_BLOCK_CODE_MANDAIC_value; ZVAL_LONG(&const_BLOCK_CODE_MANDAIC_value, UBLOCK_MANDAIC); - zend_string *const_BLOCK_CODE_MANDAIC_name = zend_string_init_interned("BLOCK_CODE_MANDAIC", sizeof("BLOCK_CODE_MANDAIC") - 1, 1); + zend_string *const_BLOCK_CODE_MANDAIC_name = zend_string_init_interned("BLOCK_CODE_MANDAIC", sizeof("BLOCK_CODE_MANDAIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MANDAIC_name, &const_BLOCK_CODE_MANDAIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MANDAIC_name); + zend_string_release_ex(const_BLOCK_CODE_MANDAIC_name, true); zval const_BLOCK_CODE_BATAK_value; ZVAL_LONG(&const_BLOCK_CODE_BATAK_value, UBLOCK_BATAK); - zend_string *const_BLOCK_CODE_BATAK_name = zend_string_init_interned("BLOCK_CODE_BATAK", sizeof("BLOCK_CODE_BATAK") - 1, 1); + zend_string *const_BLOCK_CODE_BATAK_name = zend_string_init_interned("BLOCK_CODE_BATAK", sizeof("BLOCK_CODE_BATAK") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_BATAK_name, &const_BLOCK_CODE_BATAK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_BATAK_name); + zend_string_release_ex(const_BLOCK_CODE_BATAK_name, true); zval const_BLOCK_CODE_ETHIOPIC_EXTENDED_A_value; ZVAL_LONG(&const_BLOCK_CODE_ETHIOPIC_EXTENDED_A_value, UBLOCK_ETHIOPIC_EXTENDED_A); - zend_string *const_BLOCK_CODE_ETHIOPIC_EXTENDED_A_name = zend_string_init_interned("BLOCK_CODE_ETHIOPIC_EXTENDED_A", sizeof("BLOCK_CODE_ETHIOPIC_EXTENDED_A") - 1, 1); + zend_string *const_BLOCK_CODE_ETHIOPIC_EXTENDED_A_name = zend_string_init_interned("BLOCK_CODE_ETHIOPIC_EXTENDED_A", sizeof("BLOCK_CODE_ETHIOPIC_EXTENDED_A") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ETHIOPIC_EXTENDED_A_name, &const_BLOCK_CODE_ETHIOPIC_EXTENDED_A_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ETHIOPIC_EXTENDED_A_name); + zend_string_release_ex(const_BLOCK_CODE_ETHIOPIC_EXTENDED_A_name, true); zval const_BLOCK_CODE_BRAHMI_value; ZVAL_LONG(&const_BLOCK_CODE_BRAHMI_value, UBLOCK_BRAHMI); - zend_string *const_BLOCK_CODE_BRAHMI_name = zend_string_init_interned("BLOCK_CODE_BRAHMI", sizeof("BLOCK_CODE_BRAHMI") - 1, 1); + zend_string *const_BLOCK_CODE_BRAHMI_name = zend_string_init_interned("BLOCK_CODE_BRAHMI", sizeof("BLOCK_CODE_BRAHMI") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_BRAHMI_name, &const_BLOCK_CODE_BRAHMI_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_BRAHMI_name); + zend_string_release_ex(const_BLOCK_CODE_BRAHMI_name, true); zval const_BLOCK_CODE_BAMUM_SUPPLEMENT_value; ZVAL_LONG(&const_BLOCK_CODE_BAMUM_SUPPLEMENT_value, UBLOCK_BAMUM_SUPPLEMENT); - zend_string *const_BLOCK_CODE_BAMUM_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_BAMUM_SUPPLEMENT", sizeof("BLOCK_CODE_BAMUM_SUPPLEMENT") - 1, 1); + zend_string *const_BLOCK_CODE_BAMUM_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_BAMUM_SUPPLEMENT", sizeof("BLOCK_CODE_BAMUM_SUPPLEMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_BAMUM_SUPPLEMENT_name, &const_BLOCK_CODE_BAMUM_SUPPLEMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_BAMUM_SUPPLEMENT_name); + zend_string_release_ex(const_BLOCK_CODE_BAMUM_SUPPLEMENT_name, true); zval const_BLOCK_CODE_KANA_SUPPLEMENT_value; ZVAL_LONG(&const_BLOCK_CODE_KANA_SUPPLEMENT_value, UBLOCK_KANA_SUPPLEMENT); - zend_string *const_BLOCK_CODE_KANA_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_KANA_SUPPLEMENT", sizeof("BLOCK_CODE_KANA_SUPPLEMENT") - 1, 1); + zend_string *const_BLOCK_CODE_KANA_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_KANA_SUPPLEMENT", sizeof("BLOCK_CODE_KANA_SUPPLEMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_KANA_SUPPLEMENT_name, &const_BLOCK_CODE_KANA_SUPPLEMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_KANA_SUPPLEMENT_name); + zend_string_release_ex(const_BLOCK_CODE_KANA_SUPPLEMENT_name, true); zval const_BLOCK_CODE_PLAYING_CARDS_value; ZVAL_LONG(&const_BLOCK_CODE_PLAYING_CARDS_value, UBLOCK_PLAYING_CARDS); - zend_string *const_BLOCK_CODE_PLAYING_CARDS_name = zend_string_init_interned("BLOCK_CODE_PLAYING_CARDS", sizeof("BLOCK_CODE_PLAYING_CARDS") - 1, 1); + zend_string *const_BLOCK_CODE_PLAYING_CARDS_name = zend_string_init_interned("BLOCK_CODE_PLAYING_CARDS", sizeof("BLOCK_CODE_PLAYING_CARDS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_PLAYING_CARDS_name, &const_BLOCK_CODE_PLAYING_CARDS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_PLAYING_CARDS_name); + zend_string_release_ex(const_BLOCK_CODE_PLAYING_CARDS_name, true); zval const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS_value; ZVAL_LONG(&const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS_value, UBLOCK_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS); - zend_string *const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS_name = zend_string_init_interned("BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS", sizeof("BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS") - 1, 1); + zend_string *const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS_name = zend_string_init_interned("BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS", sizeof("BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS_name, &const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS_name); + zend_string_release_ex(const_BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS_name, true); zval const_BLOCK_CODE_EMOTICONS_value; ZVAL_LONG(&const_BLOCK_CODE_EMOTICONS_value, UBLOCK_EMOTICONS); - zend_string *const_BLOCK_CODE_EMOTICONS_name = zend_string_init_interned("BLOCK_CODE_EMOTICONS", sizeof("BLOCK_CODE_EMOTICONS") - 1, 1); + zend_string *const_BLOCK_CODE_EMOTICONS_name = zend_string_init_interned("BLOCK_CODE_EMOTICONS", sizeof("BLOCK_CODE_EMOTICONS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_EMOTICONS_name, &const_BLOCK_CODE_EMOTICONS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_EMOTICONS_name); + zend_string_release_ex(const_BLOCK_CODE_EMOTICONS_name, true); zval const_BLOCK_CODE_TRANSPORT_AND_MAP_SYMBOLS_value; ZVAL_LONG(&const_BLOCK_CODE_TRANSPORT_AND_MAP_SYMBOLS_value, UBLOCK_TRANSPORT_AND_MAP_SYMBOLS); - zend_string *const_BLOCK_CODE_TRANSPORT_AND_MAP_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_TRANSPORT_AND_MAP_SYMBOLS", sizeof("BLOCK_CODE_TRANSPORT_AND_MAP_SYMBOLS") - 1, 1); + zend_string *const_BLOCK_CODE_TRANSPORT_AND_MAP_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_TRANSPORT_AND_MAP_SYMBOLS", sizeof("BLOCK_CODE_TRANSPORT_AND_MAP_SYMBOLS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_TRANSPORT_AND_MAP_SYMBOLS_name, &const_BLOCK_CODE_TRANSPORT_AND_MAP_SYMBOLS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_TRANSPORT_AND_MAP_SYMBOLS_name); + zend_string_release_ex(const_BLOCK_CODE_TRANSPORT_AND_MAP_SYMBOLS_name, true); zval const_BLOCK_CODE_ALCHEMICAL_SYMBOLS_value; ZVAL_LONG(&const_BLOCK_CODE_ALCHEMICAL_SYMBOLS_value, UBLOCK_ALCHEMICAL_SYMBOLS); - zend_string *const_BLOCK_CODE_ALCHEMICAL_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_ALCHEMICAL_SYMBOLS", sizeof("BLOCK_CODE_ALCHEMICAL_SYMBOLS") - 1, 1); + zend_string *const_BLOCK_CODE_ALCHEMICAL_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_ALCHEMICAL_SYMBOLS", sizeof("BLOCK_CODE_ALCHEMICAL_SYMBOLS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ALCHEMICAL_SYMBOLS_name, &const_BLOCK_CODE_ALCHEMICAL_SYMBOLS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ALCHEMICAL_SYMBOLS_name); + zend_string_release_ex(const_BLOCK_CODE_ALCHEMICAL_SYMBOLS_name, true); zval const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D_value; ZVAL_LONG(&const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D_value, UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D); - zend_string *const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D_name = zend_string_init_interned("BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D", sizeof("BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D") - 1, 1); + zend_string *const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D_name = zend_string_init_interned("BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D", sizeof("BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D_name, &const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D_name); + zend_string_release_ex(const_BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D_name, true); zval const_BLOCK_CODE_ARABIC_EXTENDED_A_value; ZVAL_LONG(&const_BLOCK_CODE_ARABIC_EXTENDED_A_value, UBLOCK_ARABIC_EXTENDED_A); - zend_string *const_BLOCK_CODE_ARABIC_EXTENDED_A_name = zend_string_init_interned("BLOCK_CODE_ARABIC_EXTENDED_A", sizeof("BLOCK_CODE_ARABIC_EXTENDED_A") - 1, 1); + zend_string *const_BLOCK_CODE_ARABIC_EXTENDED_A_name = zend_string_init_interned("BLOCK_CODE_ARABIC_EXTENDED_A", sizeof("BLOCK_CODE_ARABIC_EXTENDED_A") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ARABIC_EXTENDED_A_name, &const_BLOCK_CODE_ARABIC_EXTENDED_A_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ARABIC_EXTENDED_A_name); + zend_string_release_ex(const_BLOCK_CODE_ARABIC_EXTENDED_A_name, true); zval const_BLOCK_CODE_ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS_value; ZVAL_LONG(&const_BLOCK_CODE_ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS_value, UBLOCK_ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS); - zend_string *const_BLOCK_CODE_ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS", sizeof("BLOCK_CODE_ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS") - 1, 1); + zend_string *const_BLOCK_CODE_ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS_name = zend_string_init_interned("BLOCK_CODE_ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS", sizeof("BLOCK_CODE_ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS_name, &const_BLOCK_CODE_ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS_name); + zend_string_release_ex(const_BLOCK_CODE_ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS_name, true); zval const_BLOCK_CODE_CHAKMA_value; ZVAL_LONG(&const_BLOCK_CODE_CHAKMA_value, UBLOCK_CHAKMA); - zend_string *const_BLOCK_CODE_CHAKMA_name = zend_string_init_interned("BLOCK_CODE_CHAKMA", sizeof("BLOCK_CODE_CHAKMA") - 1, 1); + zend_string *const_BLOCK_CODE_CHAKMA_name = zend_string_init_interned("BLOCK_CODE_CHAKMA", sizeof("BLOCK_CODE_CHAKMA") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CHAKMA_name, &const_BLOCK_CODE_CHAKMA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CHAKMA_name); + zend_string_release_ex(const_BLOCK_CODE_CHAKMA_name, true); zval const_BLOCK_CODE_MEETEI_MAYEK_EXTENSIONS_value; ZVAL_LONG(&const_BLOCK_CODE_MEETEI_MAYEK_EXTENSIONS_value, UBLOCK_MEETEI_MAYEK_EXTENSIONS); - zend_string *const_BLOCK_CODE_MEETEI_MAYEK_EXTENSIONS_name = zend_string_init_interned("BLOCK_CODE_MEETEI_MAYEK_EXTENSIONS", sizeof("BLOCK_CODE_MEETEI_MAYEK_EXTENSIONS") - 1, 1); + zend_string *const_BLOCK_CODE_MEETEI_MAYEK_EXTENSIONS_name = zend_string_init_interned("BLOCK_CODE_MEETEI_MAYEK_EXTENSIONS", sizeof("BLOCK_CODE_MEETEI_MAYEK_EXTENSIONS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MEETEI_MAYEK_EXTENSIONS_name, &const_BLOCK_CODE_MEETEI_MAYEK_EXTENSIONS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MEETEI_MAYEK_EXTENSIONS_name); + zend_string_release_ex(const_BLOCK_CODE_MEETEI_MAYEK_EXTENSIONS_name, true); zval const_BLOCK_CODE_MEROITIC_CURSIVE_value; ZVAL_LONG(&const_BLOCK_CODE_MEROITIC_CURSIVE_value, UBLOCK_MEROITIC_CURSIVE); - zend_string *const_BLOCK_CODE_MEROITIC_CURSIVE_name = zend_string_init_interned("BLOCK_CODE_MEROITIC_CURSIVE", sizeof("BLOCK_CODE_MEROITIC_CURSIVE") - 1, 1); + zend_string *const_BLOCK_CODE_MEROITIC_CURSIVE_name = zend_string_init_interned("BLOCK_CODE_MEROITIC_CURSIVE", sizeof("BLOCK_CODE_MEROITIC_CURSIVE") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MEROITIC_CURSIVE_name, &const_BLOCK_CODE_MEROITIC_CURSIVE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MEROITIC_CURSIVE_name); + zend_string_release_ex(const_BLOCK_CODE_MEROITIC_CURSIVE_name, true); zval const_BLOCK_CODE_MEROITIC_HIEROGLYPHS_value; ZVAL_LONG(&const_BLOCK_CODE_MEROITIC_HIEROGLYPHS_value, UBLOCK_MEROITIC_HIEROGLYPHS); - zend_string *const_BLOCK_CODE_MEROITIC_HIEROGLYPHS_name = zend_string_init_interned("BLOCK_CODE_MEROITIC_HIEROGLYPHS", sizeof("BLOCK_CODE_MEROITIC_HIEROGLYPHS") - 1, 1); + zend_string *const_BLOCK_CODE_MEROITIC_HIEROGLYPHS_name = zend_string_init_interned("BLOCK_CODE_MEROITIC_HIEROGLYPHS", sizeof("BLOCK_CODE_MEROITIC_HIEROGLYPHS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MEROITIC_HIEROGLYPHS_name, &const_BLOCK_CODE_MEROITIC_HIEROGLYPHS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MEROITIC_HIEROGLYPHS_name); + zend_string_release_ex(const_BLOCK_CODE_MEROITIC_HIEROGLYPHS_name, true); zval const_BLOCK_CODE_MIAO_value; ZVAL_LONG(&const_BLOCK_CODE_MIAO_value, UBLOCK_MIAO); - zend_string *const_BLOCK_CODE_MIAO_name = zend_string_init_interned("BLOCK_CODE_MIAO", sizeof("BLOCK_CODE_MIAO") - 1, 1); + zend_string *const_BLOCK_CODE_MIAO_name = zend_string_init_interned("BLOCK_CODE_MIAO", sizeof("BLOCK_CODE_MIAO") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MIAO_name, &const_BLOCK_CODE_MIAO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MIAO_name); + zend_string_release_ex(const_BLOCK_CODE_MIAO_name, true); zval const_BLOCK_CODE_SHARADA_value; ZVAL_LONG(&const_BLOCK_CODE_SHARADA_value, UBLOCK_SHARADA); - zend_string *const_BLOCK_CODE_SHARADA_name = zend_string_init_interned("BLOCK_CODE_SHARADA", sizeof("BLOCK_CODE_SHARADA") - 1, 1); + zend_string *const_BLOCK_CODE_SHARADA_name = zend_string_init_interned("BLOCK_CODE_SHARADA", sizeof("BLOCK_CODE_SHARADA") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SHARADA_name, &const_BLOCK_CODE_SHARADA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SHARADA_name); + zend_string_release_ex(const_BLOCK_CODE_SHARADA_name, true); zval const_BLOCK_CODE_SORA_SOMPENG_value; ZVAL_LONG(&const_BLOCK_CODE_SORA_SOMPENG_value, UBLOCK_SORA_SOMPENG); - zend_string *const_BLOCK_CODE_SORA_SOMPENG_name = zend_string_init_interned("BLOCK_CODE_SORA_SOMPENG", sizeof("BLOCK_CODE_SORA_SOMPENG") - 1, 1); + zend_string *const_BLOCK_CODE_SORA_SOMPENG_name = zend_string_init_interned("BLOCK_CODE_SORA_SOMPENG", sizeof("BLOCK_CODE_SORA_SOMPENG") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SORA_SOMPENG_name, &const_BLOCK_CODE_SORA_SOMPENG_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SORA_SOMPENG_name); + zend_string_release_ex(const_BLOCK_CODE_SORA_SOMPENG_name, true); zval const_BLOCK_CODE_SUNDANESE_SUPPLEMENT_value; ZVAL_LONG(&const_BLOCK_CODE_SUNDANESE_SUPPLEMENT_value, UBLOCK_SUNDANESE_SUPPLEMENT); - zend_string *const_BLOCK_CODE_SUNDANESE_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_SUNDANESE_SUPPLEMENT", sizeof("BLOCK_CODE_SUNDANESE_SUPPLEMENT") - 1, 1); + zend_string *const_BLOCK_CODE_SUNDANESE_SUPPLEMENT_name = zend_string_init_interned("BLOCK_CODE_SUNDANESE_SUPPLEMENT", sizeof("BLOCK_CODE_SUNDANESE_SUPPLEMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SUNDANESE_SUPPLEMENT_name, &const_BLOCK_CODE_SUNDANESE_SUPPLEMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SUNDANESE_SUPPLEMENT_name); + zend_string_release_ex(const_BLOCK_CODE_SUNDANESE_SUPPLEMENT_name, true); zval const_BLOCK_CODE_TAKRI_value; ZVAL_LONG(&const_BLOCK_CODE_TAKRI_value, UBLOCK_TAKRI); - zend_string *const_BLOCK_CODE_TAKRI_name = zend_string_init_interned("BLOCK_CODE_TAKRI", sizeof("BLOCK_CODE_TAKRI") - 1, 1); + zend_string *const_BLOCK_CODE_TAKRI_name = zend_string_init_interned("BLOCK_CODE_TAKRI", sizeof("BLOCK_CODE_TAKRI") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_TAKRI_name, &const_BLOCK_CODE_TAKRI_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_TAKRI_name); + zend_string_release_ex(const_BLOCK_CODE_TAKRI_name, true); zval const_BLOCK_CODE_BASSA_VAH_value; ZVAL_LONG(&const_BLOCK_CODE_BASSA_VAH_value, UBLOCK_BASSA_VAH); - zend_string *const_BLOCK_CODE_BASSA_VAH_name = zend_string_init_interned("BLOCK_CODE_BASSA_VAH", sizeof("BLOCK_CODE_BASSA_VAH") - 1, 1); + zend_string *const_BLOCK_CODE_BASSA_VAH_name = zend_string_init_interned("BLOCK_CODE_BASSA_VAH", sizeof("BLOCK_CODE_BASSA_VAH") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_BASSA_VAH_name, &const_BLOCK_CODE_BASSA_VAH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_BASSA_VAH_name); + zend_string_release_ex(const_BLOCK_CODE_BASSA_VAH_name, true); zval const_BLOCK_CODE_CAUCASIAN_ALBANIAN_value; ZVAL_LONG(&const_BLOCK_CODE_CAUCASIAN_ALBANIAN_value, UBLOCK_CAUCASIAN_ALBANIAN); - zend_string *const_BLOCK_CODE_CAUCASIAN_ALBANIAN_name = zend_string_init_interned("BLOCK_CODE_CAUCASIAN_ALBANIAN", sizeof("BLOCK_CODE_CAUCASIAN_ALBANIAN") - 1, 1); + zend_string *const_BLOCK_CODE_CAUCASIAN_ALBANIAN_name = zend_string_init_interned("BLOCK_CODE_CAUCASIAN_ALBANIAN", sizeof("BLOCK_CODE_CAUCASIAN_ALBANIAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_CAUCASIAN_ALBANIAN_name, &const_BLOCK_CODE_CAUCASIAN_ALBANIAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_CAUCASIAN_ALBANIAN_name); + zend_string_release_ex(const_BLOCK_CODE_CAUCASIAN_ALBANIAN_name, true); zval const_BLOCK_CODE_COPTIC_EPACT_NUMBERS_value; ZVAL_LONG(&const_BLOCK_CODE_COPTIC_EPACT_NUMBERS_value, UBLOCK_COPTIC_EPACT_NUMBERS); - zend_string *const_BLOCK_CODE_COPTIC_EPACT_NUMBERS_name = zend_string_init_interned("BLOCK_CODE_COPTIC_EPACT_NUMBERS", sizeof("BLOCK_CODE_COPTIC_EPACT_NUMBERS") - 1, 1); + zend_string *const_BLOCK_CODE_COPTIC_EPACT_NUMBERS_name = zend_string_init_interned("BLOCK_CODE_COPTIC_EPACT_NUMBERS", sizeof("BLOCK_CODE_COPTIC_EPACT_NUMBERS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_COPTIC_EPACT_NUMBERS_name, &const_BLOCK_CODE_COPTIC_EPACT_NUMBERS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_COPTIC_EPACT_NUMBERS_name); + zend_string_release_ex(const_BLOCK_CODE_COPTIC_EPACT_NUMBERS_name, true); zval const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_EXTENDED_value; ZVAL_LONG(&const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_EXTENDED_value, UBLOCK_COMBINING_DIACRITICAL_MARKS_EXTENDED); - zend_string *const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_EXTENDED_name = zend_string_init_interned("BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_EXTENDED", sizeof("BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_EXTENDED") - 1, 1); + zend_string *const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_EXTENDED_name = zend_string_init_interned("BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_EXTENDED", sizeof("BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_EXTENDED") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_EXTENDED_name, &const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_EXTENDED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_EXTENDED_name); + zend_string_release_ex(const_BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_EXTENDED_name, true); zval const_BLOCK_CODE_DUPLOYAN_value; ZVAL_LONG(&const_BLOCK_CODE_DUPLOYAN_value, UBLOCK_DUPLOYAN); - zend_string *const_BLOCK_CODE_DUPLOYAN_name = zend_string_init_interned("BLOCK_CODE_DUPLOYAN", sizeof("BLOCK_CODE_DUPLOYAN") - 1, 1); + zend_string *const_BLOCK_CODE_DUPLOYAN_name = zend_string_init_interned("BLOCK_CODE_DUPLOYAN", sizeof("BLOCK_CODE_DUPLOYAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_DUPLOYAN_name, &const_BLOCK_CODE_DUPLOYAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_DUPLOYAN_name); + zend_string_release_ex(const_BLOCK_CODE_DUPLOYAN_name, true); zval const_BLOCK_CODE_ELBASAN_value; ZVAL_LONG(&const_BLOCK_CODE_ELBASAN_value, UBLOCK_ELBASAN); - zend_string *const_BLOCK_CODE_ELBASAN_name = zend_string_init_interned("BLOCK_CODE_ELBASAN", sizeof("BLOCK_CODE_ELBASAN") - 1, 1); + zend_string *const_BLOCK_CODE_ELBASAN_name = zend_string_init_interned("BLOCK_CODE_ELBASAN", sizeof("BLOCK_CODE_ELBASAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ELBASAN_name, &const_BLOCK_CODE_ELBASAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ELBASAN_name); + zend_string_release_ex(const_BLOCK_CODE_ELBASAN_name, true); zval const_BLOCK_CODE_GEOMETRIC_SHAPES_EXTENDED_value; ZVAL_LONG(&const_BLOCK_CODE_GEOMETRIC_SHAPES_EXTENDED_value, UBLOCK_GEOMETRIC_SHAPES_EXTENDED); - zend_string *const_BLOCK_CODE_GEOMETRIC_SHAPES_EXTENDED_name = zend_string_init_interned("BLOCK_CODE_GEOMETRIC_SHAPES_EXTENDED", sizeof("BLOCK_CODE_GEOMETRIC_SHAPES_EXTENDED") - 1, 1); + zend_string *const_BLOCK_CODE_GEOMETRIC_SHAPES_EXTENDED_name = zend_string_init_interned("BLOCK_CODE_GEOMETRIC_SHAPES_EXTENDED", sizeof("BLOCK_CODE_GEOMETRIC_SHAPES_EXTENDED") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_GEOMETRIC_SHAPES_EXTENDED_name, &const_BLOCK_CODE_GEOMETRIC_SHAPES_EXTENDED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_GEOMETRIC_SHAPES_EXTENDED_name); + zend_string_release_ex(const_BLOCK_CODE_GEOMETRIC_SHAPES_EXTENDED_name, true); zval const_BLOCK_CODE_GRANTHA_value; ZVAL_LONG(&const_BLOCK_CODE_GRANTHA_value, UBLOCK_GRANTHA); - zend_string *const_BLOCK_CODE_GRANTHA_name = zend_string_init_interned("BLOCK_CODE_GRANTHA", sizeof("BLOCK_CODE_GRANTHA") - 1, 1); + zend_string *const_BLOCK_CODE_GRANTHA_name = zend_string_init_interned("BLOCK_CODE_GRANTHA", sizeof("BLOCK_CODE_GRANTHA") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_GRANTHA_name, &const_BLOCK_CODE_GRANTHA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_GRANTHA_name); + zend_string_release_ex(const_BLOCK_CODE_GRANTHA_name, true); zval const_BLOCK_CODE_KHOJKI_value; ZVAL_LONG(&const_BLOCK_CODE_KHOJKI_value, UBLOCK_KHOJKI); - zend_string *const_BLOCK_CODE_KHOJKI_name = zend_string_init_interned("BLOCK_CODE_KHOJKI", sizeof("BLOCK_CODE_KHOJKI") - 1, 1); + zend_string *const_BLOCK_CODE_KHOJKI_name = zend_string_init_interned("BLOCK_CODE_KHOJKI", sizeof("BLOCK_CODE_KHOJKI") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_KHOJKI_name, &const_BLOCK_CODE_KHOJKI_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_KHOJKI_name); + zend_string_release_ex(const_BLOCK_CODE_KHOJKI_name, true); zval const_BLOCK_CODE_KHUDAWADI_value; ZVAL_LONG(&const_BLOCK_CODE_KHUDAWADI_value, UBLOCK_KHUDAWADI); - zend_string *const_BLOCK_CODE_KHUDAWADI_name = zend_string_init_interned("BLOCK_CODE_KHUDAWADI", sizeof("BLOCK_CODE_KHUDAWADI") - 1, 1); + zend_string *const_BLOCK_CODE_KHUDAWADI_name = zend_string_init_interned("BLOCK_CODE_KHUDAWADI", sizeof("BLOCK_CODE_KHUDAWADI") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_KHUDAWADI_name, &const_BLOCK_CODE_KHUDAWADI_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_KHUDAWADI_name); + zend_string_release_ex(const_BLOCK_CODE_KHUDAWADI_name, true); zval const_BLOCK_CODE_LATIN_EXTENDED_E_value; ZVAL_LONG(&const_BLOCK_CODE_LATIN_EXTENDED_E_value, UBLOCK_LATIN_EXTENDED_E); - zend_string *const_BLOCK_CODE_LATIN_EXTENDED_E_name = zend_string_init_interned("BLOCK_CODE_LATIN_EXTENDED_E", sizeof("BLOCK_CODE_LATIN_EXTENDED_E") - 1, 1); + zend_string *const_BLOCK_CODE_LATIN_EXTENDED_E_name = zend_string_init_interned("BLOCK_CODE_LATIN_EXTENDED_E", sizeof("BLOCK_CODE_LATIN_EXTENDED_E") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_LATIN_EXTENDED_E_name, &const_BLOCK_CODE_LATIN_EXTENDED_E_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_LATIN_EXTENDED_E_name); + zend_string_release_ex(const_BLOCK_CODE_LATIN_EXTENDED_E_name, true); zval const_BLOCK_CODE_LINEAR_A_value; ZVAL_LONG(&const_BLOCK_CODE_LINEAR_A_value, UBLOCK_LINEAR_A); - zend_string *const_BLOCK_CODE_LINEAR_A_name = zend_string_init_interned("BLOCK_CODE_LINEAR_A", sizeof("BLOCK_CODE_LINEAR_A") - 1, 1); + zend_string *const_BLOCK_CODE_LINEAR_A_name = zend_string_init_interned("BLOCK_CODE_LINEAR_A", sizeof("BLOCK_CODE_LINEAR_A") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_LINEAR_A_name, &const_BLOCK_CODE_LINEAR_A_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_LINEAR_A_name); + zend_string_release_ex(const_BLOCK_CODE_LINEAR_A_name, true); zval const_BLOCK_CODE_MAHAJANI_value; ZVAL_LONG(&const_BLOCK_CODE_MAHAJANI_value, UBLOCK_MAHAJANI); - zend_string *const_BLOCK_CODE_MAHAJANI_name = zend_string_init_interned("BLOCK_CODE_MAHAJANI", sizeof("BLOCK_CODE_MAHAJANI") - 1, 1); + zend_string *const_BLOCK_CODE_MAHAJANI_name = zend_string_init_interned("BLOCK_CODE_MAHAJANI", sizeof("BLOCK_CODE_MAHAJANI") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MAHAJANI_name, &const_BLOCK_CODE_MAHAJANI_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MAHAJANI_name); + zend_string_release_ex(const_BLOCK_CODE_MAHAJANI_name, true); zval const_BLOCK_CODE_MANICHAEAN_value; ZVAL_LONG(&const_BLOCK_CODE_MANICHAEAN_value, UBLOCK_MANICHAEAN); - zend_string *const_BLOCK_CODE_MANICHAEAN_name = zend_string_init_interned("BLOCK_CODE_MANICHAEAN", sizeof("BLOCK_CODE_MANICHAEAN") - 1, 1); + zend_string *const_BLOCK_CODE_MANICHAEAN_name = zend_string_init_interned("BLOCK_CODE_MANICHAEAN", sizeof("BLOCK_CODE_MANICHAEAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MANICHAEAN_name, &const_BLOCK_CODE_MANICHAEAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MANICHAEAN_name); + zend_string_release_ex(const_BLOCK_CODE_MANICHAEAN_name, true); zval const_BLOCK_CODE_MENDE_KIKAKUI_value; ZVAL_LONG(&const_BLOCK_CODE_MENDE_KIKAKUI_value, UBLOCK_MENDE_KIKAKUI); - zend_string *const_BLOCK_CODE_MENDE_KIKAKUI_name = zend_string_init_interned("BLOCK_CODE_MENDE_KIKAKUI", sizeof("BLOCK_CODE_MENDE_KIKAKUI") - 1, 1); + zend_string *const_BLOCK_CODE_MENDE_KIKAKUI_name = zend_string_init_interned("BLOCK_CODE_MENDE_KIKAKUI", sizeof("BLOCK_CODE_MENDE_KIKAKUI") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MENDE_KIKAKUI_name, &const_BLOCK_CODE_MENDE_KIKAKUI_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MENDE_KIKAKUI_name); + zend_string_release_ex(const_BLOCK_CODE_MENDE_KIKAKUI_name, true); zval const_BLOCK_CODE_MODI_value; ZVAL_LONG(&const_BLOCK_CODE_MODI_value, UBLOCK_MODI); - zend_string *const_BLOCK_CODE_MODI_name = zend_string_init_interned("BLOCK_CODE_MODI", sizeof("BLOCK_CODE_MODI") - 1, 1); + zend_string *const_BLOCK_CODE_MODI_name = zend_string_init_interned("BLOCK_CODE_MODI", sizeof("BLOCK_CODE_MODI") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MODI_name, &const_BLOCK_CODE_MODI_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MODI_name); + zend_string_release_ex(const_BLOCK_CODE_MODI_name, true); zval const_BLOCK_CODE_MRO_value; ZVAL_LONG(&const_BLOCK_CODE_MRO_value, UBLOCK_MRO); - zend_string *const_BLOCK_CODE_MRO_name = zend_string_init_interned("BLOCK_CODE_MRO", sizeof("BLOCK_CODE_MRO") - 1, 1); + zend_string *const_BLOCK_CODE_MRO_name = zend_string_init_interned("BLOCK_CODE_MRO", sizeof("BLOCK_CODE_MRO") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MRO_name, &const_BLOCK_CODE_MRO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MRO_name); + zend_string_release_ex(const_BLOCK_CODE_MRO_name, true); zval const_BLOCK_CODE_MYANMAR_EXTENDED_B_value; ZVAL_LONG(&const_BLOCK_CODE_MYANMAR_EXTENDED_B_value, UBLOCK_MYANMAR_EXTENDED_B); - zend_string *const_BLOCK_CODE_MYANMAR_EXTENDED_B_name = zend_string_init_interned("BLOCK_CODE_MYANMAR_EXTENDED_B", sizeof("BLOCK_CODE_MYANMAR_EXTENDED_B") - 1, 1); + zend_string *const_BLOCK_CODE_MYANMAR_EXTENDED_B_name = zend_string_init_interned("BLOCK_CODE_MYANMAR_EXTENDED_B", sizeof("BLOCK_CODE_MYANMAR_EXTENDED_B") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_MYANMAR_EXTENDED_B_name, &const_BLOCK_CODE_MYANMAR_EXTENDED_B_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_MYANMAR_EXTENDED_B_name); + zend_string_release_ex(const_BLOCK_CODE_MYANMAR_EXTENDED_B_name, true); zval const_BLOCK_CODE_NABATAEAN_value; ZVAL_LONG(&const_BLOCK_CODE_NABATAEAN_value, UBLOCK_NABATAEAN); - zend_string *const_BLOCK_CODE_NABATAEAN_name = zend_string_init_interned("BLOCK_CODE_NABATAEAN", sizeof("BLOCK_CODE_NABATAEAN") - 1, 1); + zend_string *const_BLOCK_CODE_NABATAEAN_name = zend_string_init_interned("BLOCK_CODE_NABATAEAN", sizeof("BLOCK_CODE_NABATAEAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_NABATAEAN_name, &const_BLOCK_CODE_NABATAEAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_NABATAEAN_name); + zend_string_release_ex(const_BLOCK_CODE_NABATAEAN_name, true); zval const_BLOCK_CODE_OLD_NORTH_ARABIAN_value; ZVAL_LONG(&const_BLOCK_CODE_OLD_NORTH_ARABIAN_value, UBLOCK_OLD_NORTH_ARABIAN); - zend_string *const_BLOCK_CODE_OLD_NORTH_ARABIAN_name = zend_string_init_interned("BLOCK_CODE_OLD_NORTH_ARABIAN", sizeof("BLOCK_CODE_OLD_NORTH_ARABIAN") - 1, 1); + zend_string *const_BLOCK_CODE_OLD_NORTH_ARABIAN_name = zend_string_init_interned("BLOCK_CODE_OLD_NORTH_ARABIAN", sizeof("BLOCK_CODE_OLD_NORTH_ARABIAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_OLD_NORTH_ARABIAN_name, &const_BLOCK_CODE_OLD_NORTH_ARABIAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_OLD_NORTH_ARABIAN_name); + zend_string_release_ex(const_BLOCK_CODE_OLD_NORTH_ARABIAN_name, true); zval const_BLOCK_CODE_OLD_PERMIC_value; ZVAL_LONG(&const_BLOCK_CODE_OLD_PERMIC_value, UBLOCK_OLD_PERMIC); - zend_string *const_BLOCK_CODE_OLD_PERMIC_name = zend_string_init_interned("BLOCK_CODE_OLD_PERMIC", sizeof("BLOCK_CODE_OLD_PERMIC") - 1, 1); + zend_string *const_BLOCK_CODE_OLD_PERMIC_name = zend_string_init_interned("BLOCK_CODE_OLD_PERMIC", sizeof("BLOCK_CODE_OLD_PERMIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_OLD_PERMIC_name, &const_BLOCK_CODE_OLD_PERMIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_OLD_PERMIC_name); + zend_string_release_ex(const_BLOCK_CODE_OLD_PERMIC_name, true); zval const_BLOCK_CODE_ORNAMENTAL_DINGBATS_value; ZVAL_LONG(&const_BLOCK_CODE_ORNAMENTAL_DINGBATS_value, UBLOCK_ORNAMENTAL_DINGBATS); - zend_string *const_BLOCK_CODE_ORNAMENTAL_DINGBATS_name = zend_string_init_interned("BLOCK_CODE_ORNAMENTAL_DINGBATS", sizeof("BLOCK_CODE_ORNAMENTAL_DINGBATS") - 1, 1); + zend_string *const_BLOCK_CODE_ORNAMENTAL_DINGBATS_name = zend_string_init_interned("BLOCK_CODE_ORNAMENTAL_DINGBATS", sizeof("BLOCK_CODE_ORNAMENTAL_DINGBATS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_ORNAMENTAL_DINGBATS_name, &const_BLOCK_CODE_ORNAMENTAL_DINGBATS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_ORNAMENTAL_DINGBATS_name); + zend_string_release_ex(const_BLOCK_CODE_ORNAMENTAL_DINGBATS_name, true); zval const_BLOCK_CODE_PAHAWH_HMONG_value; ZVAL_LONG(&const_BLOCK_CODE_PAHAWH_HMONG_value, UBLOCK_PAHAWH_HMONG); - zend_string *const_BLOCK_CODE_PAHAWH_HMONG_name = zend_string_init_interned("BLOCK_CODE_PAHAWH_HMONG", sizeof("BLOCK_CODE_PAHAWH_HMONG") - 1, 1); + zend_string *const_BLOCK_CODE_PAHAWH_HMONG_name = zend_string_init_interned("BLOCK_CODE_PAHAWH_HMONG", sizeof("BLOCK_CODE_PAHAWH_HMONG") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_PAHAWH_HMONG_name, &const_BLOCK_CODE_PAHAWH_HMONG_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_PAHAWH_HMONG_name); + zend_string_release_ex(const_BLOCK_CODE_PAHAWH_HMONG_name, true); zval const_BLOCK_CODE_PALMYRENE_value; ZVAL_LONG(&const_BLOCK_CODE_PALMYRENE_value, UBLOCK_PALMYRENE); - zend_string *const_BLOCK_CODE_PALMYRENE_name = zend_string_init_interned("BLOCK_CODE_PALMYRENE", sizeof("BLOCK_CODE_PALMYRENE") - 1, 1); + zend_string *const_BLOCK_CODE_PALMYRENE_name = zend_string_init_interned("BLOCK_CODE_PALMYRENE", sizeof("BLOCK_CODE_PALMYRENE") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_PALMYRENE_name, &const_BLOCK_CODE_PALMYRENE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_PALMYRENE_name); + zend_string_release_ex(const_BLOCK_CODE_PALMYRENE_name, true); zval const_BLOCK_CODE_PAU_CIN_HAU_value; ZVAL_LONG(&const_BLOCK_CODE_PAU_CIN_HAU_value, UBLOCK_PAU_CIN_HAU); - zend_string *const_BLOCK_CODE_PAU_CIN_HAU_name = zend_string_init_interned("BLOCK_CODE_PAU_CIN_HAU", sizeof("BLOCK_CODE_PAU_CIN_HAU") - 1, 1); + zend_string *const_BLOCK_CODE_PAU_CIN_HAU_name = zend_string_init_interned("BLOCK_CODE_PAU_CIN_HAU", sizeof("BLOCK_CODE_PAU_CIN_HAU") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_PAU_CIN_HAU_name, &const_BLOCK_CODE_PAU_CIN_HAU_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_PAU_CIN_HAU_name); + zend_string_release_ex(const_BLOCK_CODE_PAU_CIN_HAU_name, true); zval const_BLOCK_CODE_PSALTER_PAHLAVI_value; ZVAL_LONG(&const_BLOCK_CODE_PSALTER_PAHLAVI_value, UBLOCK_PSALTER_PAHLAVI); - zend_string *const_BLOCK_CODE_PSALTER_PAHLAVI_name = zend_string_init_interned("BLOCK_CODE_PSALTER_PAHLAVI", sizeof("BLOCK_CODE_PSALTER_PAHLAVI") - 1, 1); + zend_string *const_BLOCK_CODE_PSALTER_PAHLAVI_name = zend_string_init_interned("BLOCK_CODE_PSALTER_PAHLAVI", sizeof("BLOCK_CODE_PSALTER_PAHLAVI") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_PSALTER_PAHLAVI_name, &const_BLOCK_CODE_PSALTER_PAHLAVI_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_PSALTER_PAHLAVI_name); + zend_string_release_ex(const_BLOCK_CODE_PSALTER_PAHLAVI_name, true); zval const_BLOCK_CODE_SHORTHAND_FORMAT_CONTROLS_value; ZVAL_LONG(&const_BLOCK_CODE_SHORTHAND_FORMAT_CONTROLS_value, UBLOCK_SHORTHAND_FORMAT_CONTROLS); - zend_string *const_BLOCK_CODE_SHORTHAND_FORMAT_CONTROLS_name = zend_string_init_interned("BLOCK_CODE_SHORTHAND_FORMAT_CONTROLS", sizeof("BLOCK_CODE_SHORTHAND_FORMAT_CONTROLS") - 1, 1); + zend_string *const_BLOCK_CODE_SHORTHAND_FORMAT_CONTROLS_name = zend_string_init_interned("BLOCK_CODE_SHORTHAND_FORMAT_CONTROLS", sizeof("BLOCK_CODE_SHORTHAND_FORMAT_CONTROLS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SHORTHAND_FORMAT_CONTROLS_name, &const_BLOCK_CODE_SHORTHAND_FORMAT_CONTROLS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SHORTHAND_FORMAT_CONTROLS_name); + zend_string_release_ex(const_BLOCK_CODE_SHORTHAND_FORMAT_CONTROLS_name, true); zval const_BLOCK_CODE_SIDDHAM_value; ZVAL_LONG(&const_BLOCK_CODE_SIDDHAM_value, UBLOCK_SIDDHAM); - zend_string *const_BLOCK_CODE_SIDDHAM_name = zend_string_init_interned("BLOCK_CODE_SIDDHAM", sizeof("BLOCK_CODE_SIDDHAM") - 1, 1); + zend_string *const_BLOCK_CODE_SIDDHAM_name = zend_string_init_interned("BLOCK_CODE_SIDDHAM", sizeof("BLOCK_CODE_SIDDHAM") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SIDDHAM_name, &const_BLOCK_CODE_SIDDHAM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SIDDHAM_name); + zend_string_release_ex(const_BLOCK_CODE_SIDDHAM_name, true); zval const_BLOCK_CODE_SINHALA_ARCHAIC_NUMBERS_value; ZVAL_LONG(&const_BLOCK_CODE_SINHALA_ARCHAIC_NUMBERS_value, UBLOCK_SINHALA_ARCHAIC_NUMBERS); - zend_string *const_BLOCK_CODE_SINHALA_ARCHAIC_NUMBERS_name = zend_string_init_interned("BLOCK_CODE_SINHALA_ARCHAIC_NUMBERS", sizeof("BLOCK_CODE_SINHALA_ARCHAIC_NUMBERS") - 1, 1); + zend_string *const_BLOCK_CODE_SINHALA_ARCHAIC_NUMBERS_name = zend_string_init_interned("BLOCK_CODE_SINHALA_ARCHAIC_NUMBERS", sizeof("BLOCK_CODE_SINHALA_ARCHAIC_NUMBERS") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SINHALA_ARCHAIC_NUMBERS_name, &const_BLOCK_CODE_SINHALA_ARCHAIC_NUMBERS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SINHALA_ARCHAIC_NUMBERS_name); + zend_string_release_ex(const_BLOCK_CODE_SINHALA_ARCHAIC_NUMBERS_name, true); zval const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_C_value; ZVAL_LONG(&const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_C_value, UBLOCK_SUPPLEMENTAL_ARROWS_C); - zend_string *const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_C_name = zend_string_init_interned("BLOCK_CODE_SUPPLEMENTAL_ARROWS_C", sizeof("BLOCK_CODE_SUPPLEMENTAL_ARROWS_C") - 1, 1); + zend_string *const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_C_name = zend_string_init_interned("BLOCK_CODE_SUPPLEMENTAL_ARROWS_C", sizeof("BLOCK_CODE_SUPPLEMENTAL_ARROWS_C") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_C_name, &const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_C_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_C_name); + zend_string_release_ex(const_BLOCK_CODE_SUPPLEMENTAL_ARROWS_C_name, true); zval const_BLOCK_CODE_TIRHUTA_value; ZVAL_LONG(&const_BLOCK_CODE_TIRHUTA_value, UBLOCK_TIRHUTA); - zend_string *const_BLOCK_CODE_TIRHUTA_name = zend_string_init_interned("BLOCK_CODE_TIRHUTA", sizeof("BLOCK_CODE_TIRHUTA") - 1, 1); + zend_string *const_BLOCK_CODE_TIRHUTA_name = zend_string_init_interned("BLOCK_CODE_TIRHUTA", sizeof("BLOCK_CODE_TIRHUTA") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_TIRHUTA_name, &const_BLOCK_CODE_TIRHUTA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_TIRHUTA_name); + zend_string_release_ex(const_BLOCK_CODE_TIRHUTA_name, true); zval const_BLOCK_CODE_WARANG_CITI_value; ZVAL_LONG(&const_BLOCK_CODE_WARANG_CITI_value, UBLOCK_WARANG_CITI); - zend_string *const_BLOCK_CODE_WARANG_CITI_name = zend_string_init_interned("BLOCK_CODE_WARANG_CITI", sizeof("BLOCK_CODE_WARANG_CITI") - 1, 1); + zend_string *const_BLOCK_CODE_WARANG_CITI_name = zend_string_init_interned("BLOCK_CODE_WARANG_CITI", sizeof("BLOCK_CODE_WARANG_CITI") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_WARANG_CITI_name, &const_BLOCK_CODE_WARANG_CITI_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_WARANG_CITI_name); + zend_string_release_ex(const_BLOCK_CODE_WARANG_CITI_name, true); zval const_BLOCK_CODE_COUNT_value; ZVAL_LONG(&const_BLOCK_CODE_COUNT_value, UBLOCK_COUNT); - zend_string *const_BLOCK_CODE_COUNT_name = zend_string_init_interned("BLOCK_CODE_COUNT", sizeof("BLOCK_CODE_COUNT") - 1, 1); + zend_string *const_BLOCK_CODE_COUNT_name = zend_string_init_interned("BLOCK_CODE_COUNT", sizeof("BLOCK_CODE_COUNT") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_COUNT_name, &const_BLOCK_CODE_COUNT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_COUNT_name); + zend_string_release_ex(const_BLOCK_CODE_COUNT_name, true); zval const_BLOCK_CODE_INVALID_CODE_value; ZVAL_LONG(&const_BLOCK_CODE_INVALID_CODE_value, UBLOCK_INVALID_CODE); - zend_string *const_BLOCK_CODE_INVALID_CODE_name = zend_string_init_interned("BLOCK_CODE_INVALID_CODE", sizeof("BLOCK_CODE_INVALID_CODE") - 1, 1); + zend_string *const_BLOCK_CODE_INVALID_CODE_name = zend_string_init_interned("BLOCK_CODE_INVALID_CODE", sizeof("BLOCK_CODE_INVALID_CODE") - 1, true); zend_declare_typed_class_constant(class_entry, const_BLOCK_CODE_INVALID_CODE_name, &const_BLOCK_CODE_INVALID_CODE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BLOCK_CODE_INVALID_CODE_name); + zend_string_release_ex(const_BLOCK_CODE_INVALID_CODE_name, true); zval const_BPT_NONE_value; ZVAL_LONG(&const_BPT_NONE_value, U_BPT_NONE); - zend_string *const_BPT_NONE_name = zend_string_init_interned("BPT_NONE", sizeof("BPT_NONE") - 1, 1); + zend_string *const_BPT_NONE_name = zend_string_init_interned("BPT_NONE", sizeof("BPT_NONE") - 1, true); zend_declare_typed_class_constant(class_entry, const_BPT_NONE_name, &const_BPT_NONE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BPT_NONE_name); + zend_string_release_ex(const_BPT_NONE_name, true); zval const_BPT_OPEN_value; ZVAL_LONG(&const_BPT_OPEN_value, U_BPT_OPEN); - zend_string *const_BPT_OPEN_name = zend_string_init_interned("BPT_OPEN", sizeof("BPT_OPEN") - 1, 1); + zend_string *const_BPT_OPEN_name = zend_string_init_interned("BPT_OPEN", sizeof("BPT_OPEN") - 1, true); zend_declare_typed_class_constant(class_entry, const_BPT_OPEN_name, &const_BPT_OPEN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BPT_OPEN_name); + zend_string_release_ex(const_BPT_OPEN_name, true); zval const_BPT_CLOSE_value; ZVAL_LONG(&const_BPT_CLOSE_value, U_BPT_CLOSE); - zend_string *const_BPT_CLOSE_name = zend_string_init_interned("BPT_CLOSE", sizeof("BPT_CLOSE") - 1, 1); + zend_string *const_BPT_CLOSE_name = zend_string_init_interned("BPT_CLOSE", sizeof("BPT_CLOSE") - 1, true); zend_declare_typed_class_constant(class_entry, const_BPT_CLOSE_name, &const_BPT_CLOSE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BPT_CLOSE_name); + zend_string_release_ex(const_BPT_CLOSE_name, true); zval const_BPT_COUNT_value; ZVAL_LONG(&const_BPT_COUNT_value, U_BPT_COUNT); - zend_string *const_BPT_COUNT_name = zend_string_init_interned("BPT_COUNT", sizeof("BPT_COUNT") - 1, 1); + zend_string *const_BPT_COUNT_name = zend_string_init_interned("BPT_COUNT", sizeof("BPT_COUNT") - 1, true); zend_declare_typed_class_constant(class_entry, const_BPT_COUNT_name, &const_BPT_COUNT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BPT_COUNT_name); + zend_string_release_ex(const_BPT_COUNT_name, true); zval const_EA_NEUTRAL_value; ZVAL_LONG(&const_EA_NEUTRAL_value, U_EA_NEUTRAL); - zend_string *const_EA_NEUTRAL_name = zend_string_init_interned("EA_NEUTRAL", sizeof("EA_NEUTRAL") - 1, 1); + zend_string *const_EA_NEUTRAL_name = zend_string_init_interned("EA_NEUTRAL", sizeof("EA_NEUTRAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_EA_NEUTRAL_name, &const_EA_NEUTRAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EA_NEUTRAL_name); + zend_string_release_ex(const_EA_NEUTRAL_name, true); zval const_EA_AMBIGUOUS_value; ZVAL_LONG(&const_EA_AMBIGUOUS_value, U_EA_AMBIGUOUS); - zend_string *const_EA_AMBIGUOUS_name = zend_string_init_interned("EA_AMBIGUOUS", sizeof("EA_AMBIGUOUS") - 1, 1); + zend_string *const_EA_AMBIGUOUS_name = zend_string_init_interned("EA_AMBIGUOUS", sizeof("EA_AMBIGUOUS") - 1, true); zend_declare_typed_class_constant(class_entry, const_EA_AMBIGUOUS_name, &const_EA_AMBIGUOUS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EA_AMBIGUOUS_name); + zend_string_release_ex(const_EA_AMBIGUOUS_name, true); zval const_EA_HALFWIDTH_value; ZVAL_LONG(&const_EA_HALFWIDTH_value, U_EA_HALFWIDTH); - zend_string *const_EA_HALFWIDTH_name = zend_string_init_interned("EA_HALFWIDTH", sizeof("EA_HALFWIDTH") - 1, 1); + zend_string *const_EA_HALFWIDTH_name = zend_string_init_interned("EA_HALFWIDTH", sizeof("EA_HALFWIDTH") - 1, true); zend_declare_typed_class_constant(class_entry, const_EA_HALFWIDTH_name, &const_EA_HALFWIDTH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EA_HALFWIDTH_name); + zend_string_release_ex(const_EA_HALFWIDTH_name, true); zval const_EA_FULLWIDTH_value; ZVAL_LONG(&const_EA_FULLWIDTH_value, U_EA_FULLWIDTH); - zend_string *const_EA_FULLWIDTH_name = zend_string_init_interned("EA_FULLWIDTH", sizeof("EA_FULLWIDTH") - 1, 1); + zend_string *const_EA_FULLWIDTH_name = zend_string_init_interned("EA_FULLWIDTH", sizeof("EA_FULLWIDTH") - 1, true); zend_declare_typed_class_constant(class_entry, const_EA_FULLWIDTH_name, &const_EA_FULLWIDTH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EA_FULLWIDTH_name); + zend_string_release_ex(const_EA_FULLWIDTH_name, true); zval const_EA_NARROW_value; ZVAL_LONG(&const_EA_NARROW_value, U_EA_NARROW); - zend_string *const_EA_NARROW_name = zend_string_init_interned("EA_NARROW", sizeof("EA_NARROW") - 1, 1); + zend_string *const_EA_NARROW_name = zend_string_init_interned("EA_NARROW", sizeof("EA_NARROW") - 1, true); zend_declare_typed_class_constant(class_entry, const_EA_NARROW_name, &const_EA_NARROW_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EA_NARROW_name); + zend_string_release_ex(const_EA_NARROW_name, true); zval const_EA_WIDE_value; ZVAL_LONG(&const_EA_WIDE_value, U_EA_WIDE); - zend_string *const_EA_WIDE_name = zend_string_init_interned("EA_WIDE", sizeof("EA_WIDE") - 1, 1); + zend_string *const_EA_WIDE_name = zend_string_init_interned("EA_WIDE", sizeof("EA_WIDE") - 1, true); zend_declare_typed_class_constant(class_entry, const_EA_WIDE_name, &const_EA_WIDE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EA_WIDE_name); + zend_string_release_ex(const_EA_WIDE_name, true); zval const_EA_COUNT_value; ZVAL_LONG(&const_EA_COUNT_value, U_EA_COUNT); - zend_string *const_EA_COUNT_name = zend_string_init_interned("EA_COUNT", sizeof("EA_COUNT") - 1, 1); + zend_string *const_EA_COUNT_name = zend_string_init_interned("EA_COUNT", sizeof("EA_COUNT") - 1, true); zend_declare_typed_class_constant(class_entry, const_EA_COUNT_name, &const_EA_COUNT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EA_COUNT_name); + zend_string_release_ex(const_EA_COUNT_name, true); zval const_UNICODE_CHAR_NAME_value; ZVAL_LONG(&const_UNICODE_CHAR_NAME_value, U_UNICODE_CHAR_NAME); - zend_string *const_UNICODE_CHAR_NAME_name = zend_string_init_interned("UNICODE_CHAR_NAME", sizeof("UNICODE_CHAR_NAME") - 1, 1); + zend_string *const_UNICODE_CHAR_NAME_name = zend_string_init_interned("UNICODE_CHAR_NAME", sizeof("UNICODE_CHAR_NAME") - 1, true); zend_declare_typed_class_constant(class_entry, const_UNICODE_CHAR_NAME_name, &const_UNICODE_CHAR_NAME_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_UNICODE_CHAR_NAME_name); + zend_string_release_ex(const_UNICODE_CHAR_NAME_name, true); zval const_UNICODE_10_CHAR_NAME_value; ZVAL_LONG(&const_UNICODE_10_CHAR_NAME_value, U_UNICODE_10_CHAR_NAME); - zend_string *const_UNICODE_10_CHAR_NAME_name = zend_string_init_interned("UNICODE_10_CHAR_NAME", sizeof("UNICODE_10_CHAR_NAME") - 1, 1); + zend_string *const_UNICODE_10_CHAR_NAME_name = zend_string_init_interned("UNICODE_10_CHAR_NAME", sizeof("UNICODE_10_CHAR_NAME") - 1, true); zend_declare_typed_class_constant(class_entry, const_UNICODE_10_CHAR_NAME_name, &const_UNICODE_10_CHAR_NAME_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_UNICODE_10_CHAR_NAME_name); + zend_string_release_ex(const_UNICODE_10_CHAR_NAME_name, true); zval const_EXTENDED_CHAR_NAME_value; ZVAL_LONG(&const_EXTENDED_CHAR_NAME_value, U_EXTENDED_CHAR_NAME); - zend_string *const_EXTENDED_CHAR_NAME_name = zend_string_init_interned("EXTENDED_CHAR_NAME", sizeof("EXTENDED_CHAR_NAME") - 1, 1); + zend_string *const_EXTENDED_CHAR_NAME_name = zend_string_init_interned("EXTENDED_CHAR_NAME", sizeof("EXTENDED_CHAR_NAME") - 1, true); zend_declare_typed_class_constant(class_entry, const_EXTENDED_CHAR_NAME_name, &const_EXTENDED_CHAR_NAME_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EXTENDED_CHAR_NAME_name); + zend_string_release_ex(const_EXTENDED_CHAR_NAME_name, true); zval const_CHAR_NAME_ALIAS_value; ZVAL_LONG(&const_CHAR_NAME_ALIAS_value, U_CHAR_NAME_ALIAS); - zend_string *const_CHAR_NAME_ALIAS_name = zend_string_init_interned("CHAR_NAME_ALIAS", sizeof("CHAR_NAME_ALIAS") - 1, 1); + zend_string *const_CHAR_NAME_ALIAS_name = zend_string_init_interned("CHAR_NAME_ALIAS", sizeof("CHAR_NAME_ALIAS") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_NAME_ALIAS_name, &const_CHAR_NAME_ALIAS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_NAME_ALIAS_name); + zend_string_release_ex(const_CHAR_NAME_ALIAS_name, true); zval const_CHAR_NAME_CHOICE_COUNT_value; ZVAL_LONG(&const_CHAR_NAME_CHOICE_COUNT_value, U_CHAR_NAME_CHOICE_COUNT); - zend_string *const_CHAR_NAME_CHOICE_COUNT_name = zend_string_init_interned("CHAR_NAME_CHOICE_COUNT", sizeof("CHAR_NAME_CHOICE_COUNT") - 1, 1); + zend_string *const_CHAR_NAME_CHOICE_COUNT_name = zend_string_init_interned("CHAR_NAME_CHOICE_COUNT", sizeof("CHAR_NAME_CHOICE_COUNT") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHAR_NAME_CHOICE_COUNT_name, &const_CHAR_NAME_CHOICE_COUNT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHAR_NAME_CHOICE_COUNT_name); + zend_string_release_ex(const_CHAR_NAME_CHOICE_COUNT_name, true); zval const_SHORT_PROPERTY_NAME_value; ZVAL_LONG(&const_SHORT_PROPERTY_NAME_value, U_SHORT_PROPERTY_NAME); - zend_string *const_SHORT_PROPERTY_NAME_name = zend_string_init_interned("SHORT_PROPERTY_NAME", sizeof("SHORT_PROPERTY_NAME") - 1, 1); + zend_string *const_SHORT_PROPERTY_NAME_name = zend_string_init_interned("SHORT_PROPERTY_NAME", sizeof("SHORT_PROPERTY_NAME") - 1, true); zend_declare_typed_class_constant(class_entry, const_SHORT_PROPERTY_NAME_name, &const_SHORT_PROPERTY_NAME_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SHORT_PROPERTY_NAME_name); + zend_string_release_ex(const_SHORT_PROPERTY_NAME_name, true); zval const_LONG_PROPERTY_NAME_value; ZVAL_LONG(&const_LONG_PROPERTY_NAME_value, U_LONG_PROPERTY_NAME); - zend_string *const_LONG_PROPERTY_NAME_name = zend_string_init_interned("LONG_PROPERTY_NAME", sizeof("LONG_PROPERTY_NAME") - 1, 1); + zend_string *const_LONG_PROPERTY_NAME_name = zend_string_init_interned("LONG_PROPERTY_NAME", sizeof("LONG_PROPERTY_NAME") - 1, true); zend_declare_typed_class_constant(class_entry, const_LONG_PROPERTY_NAME_name, &const_LONG_PROPERTY_NAME_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LONG_PROPERTY_NAME_name); + zend_string_release_ex(const_LONG_PROPERTY_NAME_name, true); zval const_PROPERTY_NAME_CHOICE_COUNT_value; ZVAL_LONG(&const_PROPERTY_NAME_CHOICE_COUNT_value, U_PROPERTY_NAME_CHOICE_COUNT); - zend_string *const_PROPERTY_NAME_CHOICE_COUNT_name = zend_string_init_interned("PROPERTY_NAME_CHOICE_COUNT", sizeof("PROPERTY_NAME_CHOICE_COUNT") - 1, 1); + zend_string *const_PROPERTY_NAME_CHOICE_COUNT_name = zend_string_init_interned("PROPERTY_NAME_CHOICE_COUNT", sizeof("PROPERTY_NAME_CHOICE_COUNT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PROPERTY_NAME_CHOICE_COUNT_name, &const_PROPERTY_NAME_CHOICE_COUNT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PROPERTY_NAME_CHOICE_COUNT_name); + zend_string_release_ex(const_PROPERTY_NAME_CHOICE_COUNT_name, true); zval const_DT_NONE_value; ZVAL_LONG(&const_DT_NONE_value, U_DT_NONE); - zend_string *const_DT_NONE_name = zend_string_init_interned("DT_NONE", sizeof("DT_NONE") - 1, 1); + zend_string *const_DT_NONE_name = zend_string_init_interned("DT_NONE", sizeof("DT_NONE") - 1, true); zend_declare_typed_class_constant(class_entry, const_DT_NONE_name, &const_DT_NONE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DT_NONE_name); + zend_string_release_ex(const_DT_NONE_name, true); zval const_DT_CANONICAL_value; ZVAL_LONG(&const_DT_CANONICAL_value, U_DT_CANONICAL); - zend_string *const_DT_CANONICAL_name = zend_string_init_interned("DT_CANONICAL", sizeof("DT_CANONICAL") - 1, 1); + zend_string *const_DT_CANONICAL_name = zend_string_init_interned("DT_CANONICAL", sizeof("DT_CANONICAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_DT_CANONICAL_name, &const_DT_CANONICAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DT_CANONICAL_name); + zend_string_release_ex(const_DT_CANONICAL_name, true); zval const_DT_COMPAT_value; ZVAL_LONG(&const_DT_COMPAT_value, U_DT_COMPAT); - zend_string *const_DT_COMPAT_name = zend_string_init_interned("DT_COMPAT", sizeof("DT_COMPAT") - 1, 1); + zend_string *const_DT_COMPAT_name = zend_string_init_interned("DT_COMPAT", sizeof("DT_COMPAT") - 1, true); zend_declare_typed_class_constant(class_entry, const_DT_COMPAT_name, &const_DT_COMPAT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DT_COMPAT_name); + zend_string_release_ex(const_DT_COMPAT_name, true); zval const_DT_CIRCLE_value; ZVAL_LONG(&const_DT_CIRCLE_value, U_DT_CIRCLE); - zend_string *const_DT_CIRCLE_name = zend_string_init_interned("DT_CIRCLE", sizeof("DT_CIRCLE") - 1, 1); + zend_string *const_DT_CIRCLE_name = zend_string_init_interned("DT_CIRCLE", sizeof("DT_CIRCLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_DT_CIRCLE_name, &const_DT_CIRCLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DT_CIRCLE_name); + zend_string_release_ex(const_DT_CIRCLE_name, true); zval const_DT_FINAL_value; ZVAL_LONG(&const_DT_FINAL_value, U_DT_FINAL); - zend_string *const_DT_FINAL_name = zend_string_init_interned("DT_FINAL", sizeof("DT_FINAL") - 1, 1); + zend_string *const_DT_FINAL_name = zend_string_init_interned("DT_FINAL", sizeof("DT_FINAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_DT_FINAL_name, &const_DT_FINAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DT_FINAL_name); + zend_string_release_ex(const_DT_FINAL_name, true); zval const_DT_FONT_value; ZVAL_LONG(&const_DT_FONT_value, U_DT_FONT); - zend_string *const_DT_FONT_name = zend_string_init_interned("DT_FONT", sizeof("DT_FONT") - 1, 1); + zend_string *const_DT_FONT_name = zend_string_init_interned("DT_FONT", sizeof("DT_FONT") - 1, true); zend_declare_typed_class_constant(class_entry, const_DT_FONT_name, &const_DT_FONT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DT_FONT_name); + zend_string_release_ex(const_DT_FONT_name, true); zval const_DT_FRACTION_value; ZVAL_LONG(&const_DT_FRACTION_value, U_DT_FRACTION); - zend_string *const_DT_FRACTION_name = zend_string_init_interned("DT_FRACTION", sizeof("DT_FRACTION") - 1, 1); + zend_string *const_DT_FRACTION_name = zend_string_init_interned("DT_FRACTION", sizeof("DT_FRACTION") - 1, true); zend_declare_typed_class_constant(class_entry, const_DT_FRACTION_name, &const_DT_FRACTION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DT_FRACTION_name); + zend_string_release_ex(const_DT_FRACTION_name, true); zval const_DT_INITIAL_value; ZVAL_LONG(&const_DT_INITIAL_value, U_DT_INITIAL); - zend_string *const_DT_INITIAL_name = zend_string_init_interned("DT_INITIAL", sizeof("DT_INITIAL") - 1, 1); + zend_string *const_DT_INITIAL_name = zend_string_init_interned("DT_INITIAL", sizeof("DT_INITIAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_DT_INITIAL_name, &const_DT_INITIAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DT_INITIAL_name); + zend_string_release_ex(const_DT_INITIAL_name, true); zval const_DT_ISOLATED_value; ZVAL_LONG(&const_DT_ISOLATED_value, U_DT_ISOLATED); - zend_string *const_DT_ISOLATED_name = zend_string_init_interned("DT_ISOLATED", sizeof("DT_ISOLATED") - 1, 1); + zend_string *const_DT_ISOLATED_name = zend_string_init_interned("DT_ISOLATED", sizeof("DT_ISOLATED") - 1, true); zend_declare_typed_class_constant(class_entry, const_DT_ISOLATED_name, &const_DT_ISOLATED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DT_ISOLATED_name); + zend_string_release_ex(const_DT_ISOLATED_name, true); zval const_DT_MEDIAL_value; ZVAL_LONG(&const_DT_MEDIAL_value, U_DT_MEDIAL); - zend_string *const_DT_MEDIAL_name = zend_string_init_interned("DT_MEDIAL", sizeof("DT_MEDIAL") - 1, 1); + zend_string *const_DT_MEDIAL_name = zend_string_init_interned("DT_MEDIAL", sizeof("DT_MEDIAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_DT_MEDIAL_name, &const_DT_MEDIAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DT_MEDIAL_name); + zend_string_release_ex(const_DT_MEDIAL_name, true); zval const_DT_NARROW_value; ZVAL_LONG(&const_DT_NARROW_value, U_DT_NARROW); - zend_string *const_DT_NARROW_name = zend_string_init_interned("DT_NARROW", sizeof("DT_NARROW") - 1, 1); + zend_string *const_DT_NARROW_name = zend_string_init_interned("DT_NARROW", sizeof("DT_NARROW") - 1, true); zend_declare_typed_class_constant(class_entry, const_DT_NARROW_name, &const_DT_NARROW_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DT_NARROW_name); + zend_string_release_ex(const_DT_NARROW_name, true); zval const_DT_NOBREAK_value; ZVAL_LONG(&const_DT_NOBREAK_value, U_DT_NOBREAK); - zend_string *const_DT_NOBREAK_name = zend_string_init_interned("DT_NOBREAK", sizeof("DT_NOBREAK") - 1, 1); + zend_string *const_DT_NOBREAK_name = zend_string_init_interned("DT_NOBREAK", sizeof("DT_NOBREAK") - 1, true); zend_declare_typed_class_constant(class_entry, const_DT_NOBREAK_name, &const_DT_NOBREAK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DT_NOBREAK_name); + zend_string_release_ex(const_DT_NOBREAK_name, true); zval const_DT_SMALL_value; ZVAL_LONG(&const_DT_SMALL_value, U_DT_SMALL); - zend_string *const_DT_SMALL_name = zend_string_init_interned("DT_SMALL", sizeof("DT_SMALL") - 1, 1); + zend_string *const_DT_SMALL_name = zend_string_init_interned("DT_SMALL", sizeof("DT_SMALL") - 1, true); zend_declare_typed_class_constant(class_entry, const_DT_SMALL_name, &const_DT_SMALL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DT_SMALL_name); + zend_string_release_ex(const_DT_SMALL_name, true); zval const_DT_SQUARE_value; ZVAL_LONG(&const_DT_SQUARE_value, U_DT_SQUARE); - zend_string *const_DT_SQUARE_name = zend_string_init_interned("DT_SQUARE", sizeof("DT_SQUARE") - 1, 1); + zend_string *const_DT_SQUARE_name = zend_string_init_interned("DT_SQUARE", sizeof("DT_SQUARE") - 1, true); zend_declare_typed_class_constant(class_entry, const_DT_SQUARE_name, &const_DT_SQUARE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DT_SQUARE_name); + zend_string_release_ex(const_DT_SQUARE_name, true); zval const_DT_SUB_value; ZVAL_LONG(&const_DT_SUB_value, U_DT_SUB); - zend_string *const_DT_SUB_name = zend_string_init_interned("DT_SUB", sizeof("DT_SUB") - 1, 1); + zend_string *const_DT_SUB_name = zend_string_init_interned("DT_SUB", sizeof("DT_SUB") - 1, true); zend_declare_typed_class_constant(class_entry, const_DT_SUB_name, &const_DT_SUB_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DT_SUB_name); + zend_string_release_ex(const_DT_SUB_name, true); zval const_DT_SUPER_value; ZVAL_LONG(&const_DT_SUPER_value, U_DT_SUPER); - zend_string *const_DT_SUPER_name = zend_string_init_interned("DT_SUPER", sizeof("DT_SUPER") - 1, 1); + zend_string *const_DT_SUPER_name = zend_string_init_interned("DT_SUPER", sizeof("DT_SUPER") - 1, true); zend_declare_typed_class_constant(class_entry, const_DT_SUPER_name, &const_DT_SUPER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DT_SUPER_name); + zend_string_release_ex(const_DT_SUPER_name, true); zval const_DT_VERTICAL_value; ZVAL_LONG(&const_DT_VERTICAL_value, U_DT_VERTICAL); - zend_string *const_DT_VERTICAL_name = zend_string_init_interned("DT_VERTICAL", sizeof("DT_VERTICAL") - 1, 1); + zend_string *const_DT_VERTICAL_name = zend_string_init_interned("DT_VERTICAL", sizeof("DT_VERTICAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_DT_VERTICAL_name, &const_DT_VERTICAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DT_VERTICAL_name); + zend_string_release_ex(const_DT_VERTICAL_name, true); zval const_DT_WIDE_value; ZVAL_LONG(&const_DT_WIDE_value, U_DT_WIDE); - zend_string *const_DT_WIDE_name = zend_string_init_interned("DT_WIDE", sizeof("DT_WIDE") - 1, 1); + zend_string *const_DT_WIDE_name = zend_string_init_interned("DT_WIDE", sizeof("DT_WIDE") - 1, true); zend_declare_typed_class_constant(class_entry, const_DT_WIDE_name, &const_DT_WIDE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DT_WIDE_name); + zend_string_release_ex(const_DT_WIDE_name, true); zval const_DT_COUNT_value; ZVAL_LONG(&const_DT_COUNT_value, U_DT_COUNT); - zend_string *const_DT_COUNT_name = zend_string_init_interned("DT_COUNT", sizeof("DT_COUNT") - 1, 1); + zend_string *const_DT_COUNT_name = zend_string_init_interned("DT_COUNT", sizeof("DT_COUNT") - 1, true); zend_declare_typed_class_constant(class_entry, const_DT_COUNT_name, &const_DT_COUNT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DT_COUNT_name); + zend_string_release_ex(const_DT_COUNT_name, true); zval const_JT_NON_JOINING_value; ZVAL_LONG(&const_JT_NON_JOINING_value, U_JT_NON_JOINING); - zend_string *const_JT_NON_JOINING_name = zend_string_init_interned("JT_NON_JOINING", sizeof("JT_NON_JOINING") - 1, 1); + zend_string *const_JT_NON_JOINING_name = zend_string_init_interned("JT_NON_JOINING", sizeof("JT_NON_JOINING") - 1, true); zend_declare_typed_class_constant(class_entry, const_JT_NON_JOINING_name, &const_JT_NON_JOINING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JT_NON_JOINING_name); + zend_string_release_ex(const_JT_NON_JOINING_name, true); zval const_JT_JOIN_CAUSING_value; ZVAL_LONG(&const_JT_JOIN_CAUSING_value, U_JT_JOIN_CAUSING); - zend_string *const_JT_JOIN_CAUSING_name = zend_string_init_interned("JT_JOIN_CAUSING", sizeof("JT_JOIN_CAUSING") - 1, 1); + zend_string *const_JT_JOIN_CAUSING_name = zend_string_init_interned("JT_JOIN_CAUSING", sizeof("JT_JOIN_CAUSING") - 1, true); zend_declare_typed_class_constant(class_entry, const_JT_JOIN_CAUSING_name, &const_JT_JOIN_CAUSING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JT_JOIN_CAUSING_name); + zend_string_release_ex(const_JT_JOIN_CAUSING_name, true); zval const_JT_DUAL_JOINING_value; ZVAL_LONG(&const_JT_DUAL_JOINING_value, U_JT_DUAL_JOINING); - zend_string *const_JT_DUAL_JOINING_name = zend_string_init_interned("JT_DUAL_JOINING", sizeof("JT_DUAL_JOINING") - 1, 1); + zend_string *const_JT_DUAL_JOINING_name = zend_string_init_interned("JT_DUAL_JOINING", sizeof("JT_DUAL_JOINING") - 1, true); zend_declare_typed_class_constant(class_entry, const_JT_DUAL_JOINING_name, &const_JT_DUAL_JOINING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JT_DUAL_JOINING_name); + zend_string_release_ex(const_JT_DUAL_JOINING_name, true); zval const_JT_LEFT_JOINING_value; ZVAL_LONG(&const_JT_LEFT_JOINING_value, U_JT_LEFT_JOINING); - zend_string *const_JT_LEFT_JOINING_name = zend_string_init_interned("JT_LEFT_JOINING", sizeof("JT_LEFT_JOINING") - 1, 1); + zend_string *const_JT_LEFT_JOINING_name = zend_string_init_interned("JT_LEFT_JOINING", sizeof("JT_LEFT_JOINING") - 1, true); zend_declare_typed_class_constant(class_entry, const_JT_LEFT_JOINING_name, &const_JT_LEFT_JOINING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JT_LEFT_JOINING_name); + zend_string_release_ex(const_JT_LEFT_JOINING_name, true); zval const_JT_RIGHT_JOINING_value; ZVAL_LONG(&const_JT_RIGHT_JOINING_value, U_JT_RIGHT_JOINING); - zend_string *const_JT_RIGHT_JOINING_name = zend_string_init_interned("JT_RIGHT_JOINING", sizeof("JT_RIGHT_JOINING") - 1, 1); + zend_string *const_JT_RIGHT_JOINING_name = zend_string_init_interned("JT_RIGHT_JOINING", sizeof("JT_RIGHT_JOINING") - 1, true); zend_declare_typed_class_constant(class_entry, const_JT_RIGHT_JOINING_name, &const_JT_RIGHT_JOINING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JT_RIGHT_JOINING_name); + zend_string_release_ex(const_JT_RIGHT_JOINING_name, true); zval const_JT_TRANSPARENT_value; ZVAL_LONG(&const_JT_TRANSPARENT_value, U_JT_TRANSPARENT); - zend_string *const_JT_TRANSPARENT_name = zend_string_init_interned("JT_TRANSPARENT", sizeof("JT_TRANSPARENT") - 1, 1); + zend_string *const_JT_TRANSPARENT_name = zend_string_init_interned("JT_TRANSPARENT", sizeof("JT_TRANSPARENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_JT_TRANSPARENT_name, &const_JT_TRANSPARENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JT_TRANSPARENT_name); + zend_string_release_ex(const_JT_TRANSPARENT_name, true); zval const_JT_COUNT_value; ZVAL_LONG(&const_JT_COUNT_value, U_JT_COUNT); - zend_string *const_JT_COUNT_name = zend_string_init_interned("JT_COUNT", sizeof("JT_COUNT") - 1, 1); + zend_string *const_JT_COUNT_name = zend_string_init_interned("JT_COUNT", sizeof("JT_COUNT") - 1, true); zend_declare_typed_class_constant(class_entry, const_JT_COUNT_name, &const_JT_COUNT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JT_COUNT_name); + zend_string_release_ex(const_JT_COUNT_name, true); zval const_JG_NO_JOINING_GROUP_value; ZVAL_LONG(&const_JG_NO_JOINING_GROUP_value, U_JG_NO_JOINING_GROUP); - zend_string *const_JG_NO_JOINING_GROUP_name = zend_string_init_interned("JG_NO_JOINING_GROUP", sizeof("JG_NO_JOINING_GROUP") - 1, 1); + zend_string *const_JG_NO_JOINING_GROUP_name = zend_string_init_interned("JG_NO_JOINING_GROUP", sizeof("JG_NO_JOINING_GROUP") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_NO_JOINING_GROUP_name, &const_JG_NO_JOINING_GROUP_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_NO_JOINING_GROUP_name); + zend_string_release_ex(const_JG_NO_JOINING_GROUP_name, true); zval const_JG_AIN_value; ZVAL_LONG(&const_JG_AIN_value, U_JG_AIN); - zend_string *const_JG_AIN_name = zend_string_init_interned("JG_AIN", sizeof("JG_AIN") - 1, 1); + zend_string *const_JG_AIN_name = zend_string_init_interned("JG_AIN", sizeof("JG_AIN") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_AIN_name, &const_JG_AIN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_AIN_name); + zend_string_release_ex(const_JG_AIN_name, true); zval const_JG_ALAPH_value; ZVAL_LONG(&const_JG_ALAPH_value, U_JG_ALAPH); - zend_string *const_JG_ALAPH_name = zend_string_init_interned("JG_ALAPH", sizeof("JG_ALAPH") - 1, 1); + zend_string *const_JG_ALAPH_name = zend_string_init_interned("JG_ALAPH", sizeof("JG_ALAPH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_ALAPH_name, &const_JG_ALAPH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_ALAPH_name); + zend_string_release_ex(const_JG_ALAPH_name, true); zval const_JG_ALEF_value; ZVAL_LONG(&const_JG_ALEF_value, U_JG_ALEF); - zend_string *const_JG_ALEF_name = zend_string_init_interned("JG_ALEF", sizeof("JG_ALEF") - 1, 1); + zend_string *const_JG_ALEF_name = zend_string_init_interned("JG_ALEF", sizeof("JG_ALEF") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_ALEF_name, &const_JG_ALEF_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_ALEF_name); + zend_string_release_ex(const_JG_ALEF_name, true); zval const_JG_BEH_value; ZVAL_LONG(&const_JG_BEH_value, U_JG_BEH); - zend_string *const_JG_BEH_name = zend_string_init_interned("JG_BEH", sizeof("JG_BEH") - 1, 1); + zend_string *const_JG_BEH_name = zend_string_init_interned("JG_BEH", sizeof("JG_BEH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_BEH_name, &const_JG_BEH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_BEH_name); + zend_string_release_ex(const_JG_BEH_name, true); zval const_JG_BETH_value; ZVAL_LONG(&const_JG_BETH_value, U_JG_BETH); - zend_string *const_JG_BETH_name = zend_string_init_interned("JG_BETH", sizeof("JG_BETH") - 1, 1); + zend_string *const_JG_BETH_name = zend_string_init_interned("JG_BETH", sizeof("JG_BETH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_BETH_name, &const_JG_BETH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_BETH_name); + zend_string_release_ex(const_JG_BETH_name, true); zval const_JG_DAL_value; ZVAL_LONG(&const_JG_DAL_value, U_JG_DAL); - zend_string *const_JG_DAL_name = zend_string_init_interned("JG_DAL", sizeof("JG_DAL") - 1, 1); + zend_string *const_JG_DAL_name = zend_string_init_interned("JG_DAL", sizeof("JG_DAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_DAL_name, &const_JG_DAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_DAL_name); + zend_string_release_ex(const_JG_DAL_name, true); zval const_JG_DALATH_RISH_value; ZVAL_LONG(&const_JG_DALATH_RISH_value, U_JG_DALATH_RISH); - zend_string *const_JG_DALATH_RISH_name = zend_string_init_interned("JG_DALATH_RISH", sizeof("JG_DALATH_RISH") - 1, 1); + zend_string *const_JG_DALATH_RISH_name = zend_string_init_interned("JG_DALATH_RISH", sizeof("JG_DALATH_RISH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_DALATH_RISH_name, &const_JG_DALATH_RISH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_DALATH_RISH_name); + zend_string_release_ex(const_JG_DALATH_RISH_name, true); zval const_JG_E_value; ZVAL_LONG(&const_JG_E_value, U_JG_E); - zend_string *const_JG_E_name = zend_string_init_interned("JG_E", sizeof("JG_E") - 1, 1); + zend_string *const_JG_E_name = zend_string_init_interned("JG_E", sizeof("JG_E") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_E_name, &const_JG_E_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_E_name); + zend_string_release_ex(const_JG_E_name, true); zval const_JG_FEH_value; ZVAL_LONG(&const_JG_FEH_value, U_JG_FEH); - zend_string *const_JG_FEH_name = zend_string_init_interned("JG_FEH", sizeof("JG_FEH") - 1, 1); + zend_string *const_JG_FEH_name = zend_string_init_interned("JG_FEH", sizeof("JG_FEH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_FEH_name, &const_JG_FEH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_FEH_name); + zend_string_release_ex(const_JG_FEH_name, true); zval const_JG_FINAL_SEMKATH_value; ZVAL_LONG(&const_JG_FINAL_SEMKATH_value, U_JG_FINAL_SEMKATH); - zend_string *const_JG_FINAL_SEMKATH_name = zend_string_init_interned("JG_FINAL_SEMKATH", sizeof("JG_FINAL_SEMKATH") - 1, 1); + zend_string *const_JG_FINAL_SEMKATH_name = zend_string_init_interned("JG_FINAL_SEMKATH", sizeof("JG_FINAL_SEMKATH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_FINAL_SEMKATH_name, &const_JG_FINAL_SEMKATH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_FINAL_SEMKATH_name); + zend_string_release_ex(const_JG_FINAL_SEMKATH_name, true); zval const_JG_GAF_value; ZVAL_LONG(&const_JG_GAF_value, U_JG_GAF); - zend_string *const_JG_GAF_name = zend_string_init_interned("JG_GAF", sizeof("JG_GAF") - 1, 1); + zend_string *const_JG_GAF_name = zend_string_init_interned("JG_GAF", sizeof("JG_GAF") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_GAF_name, &const_JG_GAF_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_GAF_name); + zend_string_release_ex(const_JG_GAF_name, true); zval const_JG_GAMAL_value; ZVAL_LONG(&const_JG_GAMAL_value, U_JG_GAMAL); - zend_string *const_JG_GAMAL_name = zend_string_init_interned("JG_GAMAL", sizeof("JG_GAMAL") - 1, 1); + zend_string *const_JG_GAMAL_name = zend_string_init_interned("JG_GAMAL", sizeof("JG_GAMAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_GAMAL_name, &const_JG_GAMAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_GAMAL_name); + zend_string_release_ex(const_JG_GAMAL_name, true); zval const_JG_HAH_value; ZVAL_LONG(&const_JG_HAH_value, U_JG_HAH); - zend_string *const_JG_HAH_name = zend_string_init_interned("JG_HAH", sizeof("JG_HAH") - 1, 1); + zend_string *const_JG_HAH_name = zend_string_init_interned("JG_HAH", sizeof("JG_HAH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_HAH_name, &const_JG_HAH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_HAH_name); + zend_string_release_ex(const_JG_HAH_name, true); zval const_JG_TEH_MARBUTA_GOAL_value; ZVAL_LONG(&const_JG_TEH_MARBUTA_GOAL_value, U_JG_TEH_MARBUTA_GOAL); - zend_string *const_JG_TEH_MARBUTA_GOAL_name = zend_string_init_interned("JG_TEH_MARBUTA_GOAL", sizeof("JG_TEH_MARBUTA_GOAL") - 1, 1); + zend_string *const_JG_TEH_MARBUTA_GOAL_name = zend_string_init_interned("JG_TEH_MARBUTA_GOAL", sizeof("JG_TEH_MARBUTA_GOAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_TEH_MARBUTA_GOAL_name, &const_JG_TEH_MARBUTA_GOAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_TEH_MARBUTA_GOAL_name); + zend_string_release_ex(const_JG_TEH_MARBUTA_GOAL_name, true); zval const_JG_HAMZA_ON_HEH_GOAL_value; ZVAL_LONG(&const_JG_HAMZA_ON_HEH_GOAL_value, U_JG_HAMZA_ON_HEH_GOAL); - zend_string *const_JG_HAMZA_ON_HEH_GOAL_name = zend_string_init_interned("JG_HAMZA_ON_HEH_GOAL", sizeof("JG_HAMZA_ON_HEH_GOAL") - 1, 1); + zend_string *const_JG_HAMZA_ON_HEH_GOAL_name = zend_string_init_interned("JG_HAMZA_ON_HEH_GOAL", sizeof("JG_HAMZA_ON_HEH_GOAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_HAMZA_ON_HEH_GOAL_name, &const_JG_HAMZA_ON_HEH_GOAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_HAMZA_ON_HEH_GOAL_name); + zend_string_release_ex(const_JG_HAMZA_ON_HEH_GOAL_name, true); zval const_JG_HE_value; ZVAL_LONG(&const_JG_HE_value, U_JG_HE); - zend_string *const_JG_HE_name = zend_string_init_interned("JG_HE", sizeof("JG_HE") - 1, 1); + zend_string *const_JG_HE_name = zend_string_init_interned("JG_HE", sizeof("JG_HE") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_HE_name, &const_JG_HE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_HE_name); + zend_string_release_ex(const_JG_HE_name, true); zval const_JG_HEH_value; ZVAL_LONG(&const_JG_HEH_value, U_JG_HEH); - zend_string *const_JG_HEH_name = zend_string_init_interned("JG_HEH", sizeof("JG_HEH") - 1, 1); + zend_string *const_JG_HEH_name = zend_string_init_interned("JG_HEH", sizeof("JG_HEH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_HEH_name, &const_JG_HEH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_HEH_name); + zend_string_release_ex(const_JG_HEH_name, true); zval const_JG_HEH_GOAL_value; ZVAL_LONG(&const_JG_HEH_GOAL_value, U_JG_HEH_GOAL); - zend_string *const_JG_HEH_GOAL_name = zend_string_init_interned("JG_HEH_GOAL", sizeof("JG_HEH_GOAL") - 1, 1); + zend_string *const_JG_HEH_GOAL_name = zend_string_init_interned("JG_HEH_GOAL", sizeof("JG_HEH_GOAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_HEH_GOAL_name, &const_JG_HEH_GOAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_HEH_GOAL_name); + zend_string_release_ex(const_JG_HEH_GOAL_name, true); zval const_JG_HETH_value; ZVAL_LONG(&const_JG_HETH_value, U_JG_HETH); - zend_string *const_JG_HETH_name = zend_string_init_interned("JG_HETH", sizeof("JG_HETH") - 1, 1); + zend_string *const_JG_HETH_name = zend_string_init_interned("JG_HETH", sizeof("JG_HETH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_HETH_name, &const_JG_HETH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_HETH_name); + zend_string_release_ex(const_JG_HETH_name, true); zval const_JG_KAF_value; ZVAL_LONG(&const_JG_KAF_value, U_JG_KAF); - zend_string *const_JG_KAF_name = zend_string_init_interned("JG_KAF", sizeof("JG_KAF") - 1, 1); + zend_string *const_JG_KAF_name = zend_string_init_interned("JG_KAF", sizeof("JG_KAF") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_KAF_name, &const_JG_KAF_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_KAF_name); + zend_string_release_ex(const_JG_KAF_name, true); zval const_JG_KAPH_value; ZVAL_LONG(&const_JG_KAPH_value, U_JG_KAPH); - zend_string *const_JG_KAPH_name = zend_string_init_interned("JG_KAPH", sizeof("JG_KAPH") - 1, 1); + zend_string *const_JG_KAPH_name = zend_string_init_interned("JG_KAPH", sizeof("JG_KAPH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_KAPH_name, &const_JG_KAPH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_KAPH_name); + zend_string_release_ex(const_JG_KAPH_name, true); zval const_JG_KNOTTED_HEH_value; ZVAL_LONG(&const_JG_KNOTTED_HEH_value, U_JG_KNOTTED_HEH); - zend_string *const_JG_KNOTTED_HEH_name = zend_string_init_interned("JG_KNOTTED_HEH", sizeof("JG_KNOTTED_HEH") - 1, 1); + zend_string *const_JG_KNOTTED_HEH_name = zend_string_init_interned("JG_KNOTTED_HEH", sizeof("JG_KNOTTED_HEH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_KNOTTED_HEH_name, &const_JG_KNOTTED_HEH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_KNOTTED_HEH_name); + zend_string_release_ex(const_JG_KNOTTED_HEH_name, true); zval const_JG_LAM_value; ZVAL_LONG(&const_JG_LAM_value, U_JG_LAM); - zend_string *const_JG_LAM_name = zend_string_init_interned("JG_LAM", sizeof("JG_LAM") - 1, 1); + zend_string *const_JG_LAM_name = zend_string_init_interned("JG_LAM", sizeof("JG_LAM") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_LAM_name, &const_JG_LAM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_LAM_name); + zend_string_release_ex(const_JG_LAM_name, true); zval const_JG_LAMADH_value; ZVAL_LONG(&const_JG_LAMADH_value, U_JG_LAMADH); - zend_string *const_JG_LAMADH_name = zend_string_init_interned("JG_LAMADH", sizeof("JG_LAMADH") - 1, 1); + zend_string *const_JG_LAMADH_name = zend_string_init_interned("JG_LAMADH", sizeof("JG_LAMADH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_LAMADH_name, &const_JG_LAMADH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_LAMADH_name); + zend_string_release_ex(const_JG_LAMADH_name, true); zval const_JG_MEEM_value; ZVAL_LONG(&const_JG_MEEM_value, U_JG_MEEM); - zend_string *const_JG_MEEM_name = zend_string_init_interned("JG_MEEM", sizeof("JG_MEEM") - 1, 1); + zend_string *const_JG_MEEM_name = zend_string_init_interned("JG_MEEM", sizeof("JG_MEEM") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MEEM_name, &const_JG_MEEM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MEEM_name); + zend_string_release_ex(const_JG_MEEM_name, true); zval const_JG_MIM_value; ZVAL_LONG(&const_JG_MIM_value, U_JG_MIM); - zend_string *const_JG_MIM_name = zend_string_init_interned("JG_MIM", sizeof("JG_MIM") - 1, 1); + zend_string *const_JG_MIM_name = zend_string_init_interned("JG_MIM", sizeof("JG_MIM") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MIM_name, &const_JG_MIM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MIM_name); + zend_string_release_ex(const_JG_MIM_name, true); zval const_JG_NOON_value; ZVAL_LONG(&const_JG_NOON_value, U_JG_NOON); - zend_string *const_JG_NOON_name = zend_string_init_interned("JG_NOON", sizeof("JG_NOON") - 1, 1); + zend_string *const_JG_NOON_name = zend_string_init_interned("JG_NOON", sizeof("JG_NOON") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_NOON_name, &const_JG_NOON_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_NOON_name); + zend_string_release_ex(const_JG_NOON_name, true); zval const_JG_NUN_value; ZVAL_LONG(&const_JG_NUN_value, U_JG_NUN); - zend_string *const_JG_NUN_name = zend_string_init_interned("JG_NUN", sizeof("JG_NUN") - 1, 1); + zend_string *const_JG_NUN_name = zend_string_init_interned("JG_NUN", sizeof("JG_NUN") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_NUN_name, &const_JG_NUN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_NUN_name); + zend_string_release_ex(const_JG_NUN_name, true); zval const_JG_PE_value; ZVAL_LONG(&const_JG_PE_value, U_JG_PE); - zend_string *const_JG_PE_name = zend_string_init_interned("JG_PE", sizeof("JG_PE") - 1, 1); + zend_string *const_JG_PE_name = zend_string_init_interned("JG_PE", sizeof("JG_PE") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_PE_name, &const_JG_PE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_PE_name); + zend_string_release_ex(const_JG_PE_name, true); zval const_JG_QAF_value; ZVAL_LONG(&const_JG_QAF_value, U_JG_QAF); - zend_string *const_JG_QAF_name = zend_string_init_interned("JG_QAF", sizeof("JG_QAF") - 1, 1); + zend_string *const_JG_QAF_name = zend_string_init_interned("JG_QAF", sizeof("JG_QAF") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_QAF_name, &const_JG_QAF_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_QAF_name); + zend_string_release_ex(const_JG_QAF_name, true); zval const_JG_QAPH_value; ZVAL_LONG(&const_JG_QAPH_value, U_JG_QAPH); - zend_string *const_JG_QAPH_name = zend_string_init_interned("JG_QAPH", sizeof("JG_QAPH") - 1, 1); + zend_string *const_JG_QAPH_name = zend_string_init_interned("JG_QAPH", sizeof("JG_QAPH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_QAPH_name, &const_JG_QAPH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_QAPH_name); + zend_string_release_ex(const_JG_QAPH_name, true); zval const_JG_REH_value; ZVAL_LONG(&const_JG_REH_value, U_JG_REH); - zend_string *const_JG_REH_name = zend_string_init_interned("JG_REH", sizeof("JG_REH") - 1, 1); + zend_string *const_JG_REH_name = zend_string_init_interned("JG_REH", sizeof("JG_REH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_REH_name, &const_JG_REH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_REH_name); + zend_string_release_ex(const_JG_REH_name, true); zval const_JG_REVERSED_PE_value; ZVAL_LONG(&const_JG_REVERSED_PE_value, U_JG_REVERSED_PE); - zend_string *const_JG_REVERSED_PE_name = zend_string_init_interned("JG_REVERSED_PE", sizeof("JG_REVERSED_PE") - 1, 1); + zend_string *const_JG_REVERSED_PE_name = zend_string_init_interned("JG_REVERSED_PE", sizeof("JG_REVERSED_PE") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_REVERSED_PE_name, &const_JG_REVERSED_PE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_REVERSED_PE_name); + zend_string_release_ex(const_JG_REVERSED_PE_name, true); zval const_JG_SAD_value; ZVAL_LONG(&const_JG_SAD_value, U_JG_SAD); - zend_string *const_JG_SAD_name = zend_string_init_interned("JG_SAD", sizeof("JG_SAD") - 1, 1); + zend_string *const_JG_SAD_name = zend_string_init_interned("JG_SAD", sizeof("JG_SAD") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_SAD_name, &const_JG_SAD_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_SAD_name); + zend_string_release_ex(const_JG_SAD_name, true); zval const_JG_SADHE_value; ZVAL_LONG(&const_JG_SADHE_value, U_JG_SADHE); - zend_string *const_JG_SADHE_name = zend_string_init_interned("JG_SADHE", sizeof("JG_SADHE") - 1, 1); + zend_string *const_JG_SADHE_name = zend_string_init_interned("JG_SADHE", sizeof("JG_SADHE") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_SADHE_name, &const_JG_SADHE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_SADHE_name); + zend_string_release_ex(const_JG_SADHE_name, true); zval const_JG_SEEN_value; ZVAL_LONG(&const_JG_SEEN_value, U_JG_SEEN); - zend_string *const_JG_SEEN_name = zend_string_init_interned("JG_SEEN", sizeof("JG_SEEN") - 1, 1); + zend_string *const_JG_SEEN_name = zend_string_init_interned("JG_SEEN", sizeof("JG_SEEN") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_SEEN_name, &const_JG_SEEN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_SEEN_name); + zend_string_release_ex(const_JG_SEEN_name, true); zval const_JG_SEMKATH_value; ZVAL_LONG(&const_JG_SEMKATH_value, U_JG_SEMKATH); - zend_string *const_JG_SEMKATH_name = zend_string_init_interned("JG_SEMKATH", sizeof("JG_SEMKATH") - 1, 1); + zend_string *const_JG_SEMKATH_name = zend_string_init_interned("JG_SEMKATH", sizeof("JG_SEMKATH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_SEMKATH_name, &const_JG_SEMKATH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_SEMKATH_name); + zend_string_release_ex(const_JG_SEMKATH_name, true); zval const_JG_SHIN_value; ZVAL_LONG(&const_JG_SHIN_value, U_JG_SHIN); - zend_string *const_JG_SHIN_name = zend_string_init_interned("JG_SHIN", sizeof("JG_SHIN") - 1, 1); + zend_string *const_JG_SHIN_name = zend_string_init_interned("JG_SHIN", sizeof("JG_SHIN") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_SHIN_name, &const_JG_SHIN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_SHIN_name); + zend_string_release_ex(const_JG_SHIN_name, true); zval const_JG_SWASH_KAF_value; ZVAL_LONG(&const_JG_SWASH_KAF_value, U_JG_SWASH_KAF); - zend_string *const_JG_SWASH_KAF_name = zend_string_init_interned("JG_SWASH_KAF", sizeof("JG_SWASH_KAF") - 1, 1); + zend_string *const_JG_SWASH_KAF_name = zend_string_init_interned("JG_SWASH_KAF", sizeof("JG_SWASH_KAF") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_SWASH_KAF_name, &const_JG_SWASH_KAF_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_SWASH_KAF_name); + zend_string_release_ex(const_JG_SWASH_KAF_name, true); zval const_JG_SYRIAC_WAW_value; ZVAL_LONG(&const_JG_SYRIAC_WAW_value, U_JG_SYRIAC_WAW); - zend_string *const_JG_SYRIAC_WAW_name = zend_string_init_interned("JG_SYRIAC_WAW", sizeof("JG_SYRIAC_WAW") - 1, 1); + zend_string *const_JG_SYRIAC_WAW_name = zend_string_init_interned("JG_SYRIAC_WAW", sizeof("JG_SYRIAC_WAW") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_SYRIAC_WAW_name, &const_JG_SYRIAC_WAW_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_SYRIAC_WAW_name); + zend_string_release_ex(const_JG_SYRIAC_WAW_name, true); zval const_JG_TAH_value; ZVAL_LONG(&const_JG_TAH_value, U_JG_TAH); - zend_string *const_JG_TAH_name = zend_string_init_interned("JG_TAH", sizeof("JG_TAH") - 1, 1); + zend_string *const_JG_TAH_name = zend_string_init_interned("JG_TAH", sizeof("JG_TAH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_TAH_name, &const_JG_TAH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_TAH_name); + zend_string_release_ex(const_JG_TAH_name, true); zval const_JG_TAW_value; ZVAL_LONG(&const_JG_TAW_value, U_JG_TAW); - zend_string *const_JG_TAW_name = zend_string_init_interned("JG_TAW", sizeof("JG_TAW") - 1, 1); + zend_string *const_JG_TAW_name = zend_string_init_interned("JG_TAW", sizeof("JG_TAW") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_TAW_name, &const_JG_TAW_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_TAW_name); + zend_string_release_ex(const_JG_TAW_name, true); zval const_JG_TEH_MARBUTA_value; ZVAL_LONG(&const_JG_TEH_MARBUTA_value, U_JG_TEH_MARBUTA); - zend_string *const_JG_TEH_MARBUTA_name = zend_string_init_interned("JG_TEH_MARBUTA", sizeof("JG_TEH_MARBUTA") - 1, 1); + zend_string *const_JG_TEH_MARBUTA_name = zend_string_init_interned("JG_TEH_MARBUTA", sizeof("JG_TEH_MARBUTA") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_TEH_MARBUTA_name, &const_JG_TEH_MARBUTA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_TEH_MARBUTA_name); + zend_string_release_ex(const_JG_TEH_MARBUTA_name, true); zval const_JG_TETH_value; ZVAL_LONG(&const_JG_TETH_value, U_JG_TETH); - zend_string *const_JG_TETH_name = zend_string_init_interned("JG_TETH", sizeof("JG_TETH") - 1, 1); + zend_string *const_JG_TETH_name = zend_string_init_interned("JG_TETH", sizeof("JG_TETH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_TETH_name, &const_JG_TETH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_TETH_name); + zend_string_release_ex(const_JG_TETH_name, true); zval const_JG_WAW_value; ZVAL_LONG(&const_JG_WAW_value, U_JG_WAW); - zend_string *const_JG_WAW_name = zend_string_init_interned("JG_WAW", sizeof("JG_WAW") - 1, 1); + zend_string *const_JG_WAW_name = zend_string_init_interned("JG_WAW", sizeof("JG_WAW") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_WAW_name, &const_JG_WAW_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_WAW_name); + zend_string_release_ex(const_JG_WAW_name, true); zval const_JG_YEH_value; ZVAL_LONG(&const_JG_YEH_value, U_JG_YEH); - zend_string *const_JG_YEH_name = zend_string_init_interned("JG_YEH", sizeof("JG_YEH") - 1, 1); + zend_string *const_JG_YEH_name = zend_string_init_interned("JG_YEH", sizeof("JG_YEH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_YEH_name, &const_JG_YEH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_YEH_name); + zend_string_release_ex(const_JG_YEH_name, true); zval const_JG_YEH_BARREE_value; ZVAL_LONG(&const_JG_YEH_BARREE_value, U_JG_YEH_BARREE); - zend_string *const_JG_YEH_BARREE_name = zend_string_init_interned("JG_YEH_BARREE", sizeof("JG_YEH_BARREE") - 1, 1); + zend_string *const_JG_YEH_BARREE_name = zend_string_init_interned("JG_YEH_BARREE", sizeof("JG_YEH_BARREE") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_YEH_BARREE_name, &const_JG_YEH_BARREE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_YEH_BARREE_name); + zend_string_release_ex(const_JG_YEH_BARREE_name, true); zval const_JG_YEH_WITH_TAIL_value; ZVAL_LONG(&const_JG_YEH_WITH_TAIL_value, U_JG_YEH_WITH_TAIL); - zend_string *const_JG_YEH_WITH_TAIL_name = zend_string_init_interned("JG_YEH_WITH_TAIL", sizeof("JG_YEH_WITH_TAIL") - 1, 1); + zend_string *const_JG_YEH_WITH_TAIL_name = zend_string_init_interned("JG_YEH_WITH_TAIL", sizeof("JG_YEH_WITH_TAIL") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_YEH_WITH_TAIL_name, &const_JG_YEH_WITH_TAIL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_YEH_WITH_TAIL_name); + zend_string_release_ex(const_JG_YEH_WITH_TAIL_name, true); zval const_JG_YUDH_value; ZVAL_LONG(&const_JG_YUDH_value, U_JG_YUDH); - zend_string *const_JG_YUDH_name = zend_string_init_interned("JG_YUDH", sizeof("JG_YUDH") - 1, 1); + zend_string *const_JG_YUDH_name = zend_string_init_interned("JG_YUDH", sizeof("JG_YUDH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_YUDH_name, &const_JG_YUDH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_YUDH_name); + zend_string_release_ex(const_JG_YUDH_name, true); zval const_JG_YUDH_HE_value; ZVAL_LONG(&const_JG_YUDH_HE_value, U_JG_YUDH_HE); - zend_string *const_JG_YUDH_HE_name = zend_string_init_interned("JG_YUDH_HE", sizeof("JG_YUDH_HE") - 1, 1); + zend_string *const_JG_YUDH_HE_name = zend_string_init_interned("JG_YUDH_HE", sizeof("JG_YUDH_HE") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_YUDH_HE_name, &const_JG_YUDH_HE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_YUDH_HE_name); + zend_string_release_ex(const_JG_YUDH_HE_name, true); zval const_JG_ZAIN_value; ZVAL_LONG(&const_JG_ZAIN_value, U_JG_ZAIN); - zend_string *const_JG_ZAIN_name = zend_string_init_interned("JG_ZAIN", sizeof("JG_ZAIN") - 1, 1); + zend_string *const_JG_ZAIN_name = zend_string_init_interned("JG_ZAIN", sizeof("JG_ZAIN") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_ZAIN_name, &const_JG_ZAIN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_ZAIN_name); + zend_string_release_ex(const_JG_ZAIN_name, true); zval const_JG_FE_value; ZVAL_LONG(&const_JG_FE_value, U_JG_FE); - zend_string *const_JG_FE_name = zend_string_init_interned("JG_FE", sizeof("JG_FE") - 1, 1); + zend_string *const_JG_FE_name = zend_string_init_interned("JG_FE", sizeof("JG_FE") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_FE_name, &const_JG_FE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_FE_name); + zend_string_release_ex(const_JG_FE_name, true); zval const_JG_KHAPH_value; ZVAL_LONG(&const_JG_KHAPH_value, U_JG_KHAPH); - zend_string *const_JG_KHAPH_name = zend_string_init_interned("JG_KHAPH", sizeof("JG_KHAPH") - 1, 1); + zend_string *const_JG_KHAPH_name = zend_string_init_interned("JG_KHAPH", sizeof("JG_KHAPH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_KHAPH_name, &const_JG_KHAPH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_KHAPH_name); + zend_string_release_ex(const_JG_KHAPH_name, true); zval const_JG_ZHAIN_value; ZVAL_LONG(&const_JG_ZHAIN_value, U_JG_ZHAIN); - zend_string *const_JG_ZHAIN_name = zend_string_init_interned("JG_ZHAIN", sizeof("JG_ZHAIN") - 1, 1); + zend_string *const_JG_ZHAIN_name = zend_string_init_interned("JG_ZHAIN", sizeof("JG_ZHAIN") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_ZHAIN_name, &const_JG_ZHAIN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_ZHAIN_name); + zend_string_release_ex(const_JG_ZHAIN_name, true); zval const_JG_BURUSHASKI_YEH_BARREE_value; ZVAL_LONG(&const_JG_BURUSHASKI_YEH_BARREE_value, U_JG_BURUSHASKI_YEH_BARREE); - zend_string *const_JG_BURUSHASKI_YEH_BARREE_name = zend_string_init_interned("JG_BURUSHASKI_YEH_BARREE", sizeof("JG_BURUSHASKI_YEH_BARREE") - 1, 1); + zend_string *const_JG_BURUSHASKI_YEH_BARREE_name = zend_string_init_interned("JG_BURUSHASKI_YEH_BARREE", sizeof("JG_BURUSHASKI_YEH_BARREE") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_BURUSHASKI_YEH_BARREE_name, &const_JG_BURUSHASKI_YEH_BARREE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_BURUSHASKI_YEH_BARREE_name); + zend_string_release_ex(const_JG_BURUSHASKI_YEH_BARREE_name, true); zval const_JG_FARSI_YEH_value; ZVAL_LONG(&const_JG_FARSI_YEH_value, U_JG_FARSI_YEH); - zend_string *const_JG_FARSI_YEH_name = zend_string_init_interned("JG_FARSI_YEH", sizeof("JG_FARSI_YEH") - 1, 1); + zend_string *const_JG_FARSI_YEH_name = zend_string_init_interned("JG_FARSI_YEH", sizeof("JG_FARSI_YEH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_FARSI_YEH_name, &const_JG_FARSI_YEH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_FARSI_YEH_name); + zend_string_release_ex(const_JG_FARSI_YEH_name, true); zval const_JG_NYA_value; ZVAL_LONG(&const_JG_NYA_value, U_JG_NYA); - zend_string *const_JG_NYA_name = zend_string_init_interned("JG_NYA", sizeof("JG_NYA") - 1, 1); + zend_string *const_JG_NYA_name = zend_string_init_interned("JG_NYA", sizeof("JG_NYA") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_NYA_name, &const_JG_NYA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_NYA_name); + zend_string_release_ex(const_JG_NYA_name, true); zval const_JG_ROHINGYA_YEH_value; ZVAL_LONG(&const_JG_ROHINGYA_YEH_value, U_JG_ROHINGYA_YEH); - zend_string *const_JG_ROHINGYA_YEH_name = zend_string_init_interned("JG_ROHINGYA_YEH", sizeof("JG_ROHINGYA_YEH") - 1, 1); + zend_string *const_JG_ROHINGYA_YEH_name = zend_string_init_interned("JG_ROHINGYA_YEH", sizeof("JG_ROHINGYA_YEH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_ROHINGYA_YEH_name, &const_JG_ROHINGYA_YEH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_ROHINGYA_YEH_name); + zend_string_release_ex(const_JG_ROHINGYA_YEH_name, true); zval const_JG_MANICHAEAN_ALEPH_value; ZVAL_LONG(&const_JG_MANICHAEAN_ALEPH_value, U_JG_MANICHAEAN_ALEPH); - zend_string *const_JG_MANICHAEAN_ALEPH_name = zend_string_init_interned("JG_MANICHAEAN_ALEPH", sizeof("JG_MANICHAEAN_ALEPH") - 1, 1); + zend_string *const_JG_MANICHAEAN_ALEPH_name = zend_string_init_interned("JG_MANICHAEAN_ALEPH", sizeof("JG_MANICHAEAN_ALEPH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_ALEPH_name, &const_JG_MANICHAEAN_ALEPH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_ALEPH_name); + zend_string_release_ex(const_JG_MANICHAEAN_ALEPH_name, true); zval const_JG_MANICHAEAN_AYIN_value; ZVAL_LONG(&const_JG_MANICHAEAN_AYIN_value, U_JG_MANICHAEAN_AYIN); - zend_string *const_JG_MANICHAEAN_AYIN_name = zend_string_init_interned("JG_MANICHAEAN_AYIN", sizeof("JG_MANICHAEAN_AYIN") - 1, 1); + zend_string *const_JG_MANICHAEAN_AYIN_name = zend_string_init_interned("JG_MANICHAEAN_AYIN", sizeof("JG_MANICHAEAN_AYIN") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_AYIN_name, &const_JG_MANICHAEAN_AYIN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_AYIN_name); + zend_string_release_ex(const_JG_MANICHAEAN_AYIN_name, true); zval const_JG_MANICHAEAN_BETH_value; ZVAL_LONG(&const_JG_MANICHAEAN_BETH_value, U_JG_MANICHAEAN_BETH); - zend_string *const_JG_MANICHAEAN_BETH_name = zend_string_init_interned("JG_MANICHAEAN_BETH", sizeof("JG_MANICHAEAN_BETH") - 1, 1); + zend_string *const_JG_MANICHAEAN_BETH_name = zend_string_init_interned("JG_MANICHAEAN_BETH", sizeof("JG_MANICHAEAN_BETH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_BETH_name, &const_JG_MANICHAEAN_BETH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_BETH_name); + zend_string_release_ex(const_JG_MANICHAEAN_BETH_name, true); zval const_JG_MANICHAEAN_DALETH_value; ZVAL_LONG(&const_JG_MANICHAEAN_DALETH_value, U_JG_MANICHAEAN_DALETH); - zend_string *const_JG_MANICHAEAN_DALETH_name = zend_string_init_interned("JG_MANICHAEAN_DALETH", sizeof("JG_MANICHAEAN_DALETH") - 1, 1); + zend_string *const_JG_MANICHAEAN_DALETH_name = zend_string_init_interned("JG_MANICHAEAN_DALETH", sizeof("JG_MANICHAEAN_DALETH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_DALETH_name, &const_JG_MANICHAEAN_DALETH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_DALETH_name); + zend_string_release_ex(const_JG_MANICHAEAN_DALETH_name, true); zval const_JG_MANICHAEAN_DHAMEDH_value; ZVAL_LONG(&const_JG_MANICHAEAN_DHAMEDH_value, U_JG_MANICHAEAN_DHAMEDH); - zend_string *const_JG_MANICHAEAN_DHAMEDH_name = zend_string_init_interned("JG_MANICHAEAN_DHAMEDH", sizeof("JG_MANICHAEAN_DHAMEDH") - 1, 1); + zend_string *const_JG_MANICHAEAN_DHAMEDH_name = zend_string_init_interned("JG_MANICHAEAN_DHAMEDH", sizeof("JG_MANICHAEAN_DHAMEDH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_DHAMEDH_name, &const_JG_MANICHAEAN_DHAMEDH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_DHAMEDH_name); + zend_string_release_ex(const_JG_MANICHAEAN_DHAMEDH_name, true); zval const_JG_MANICHAEAN_FIVE_value; ZVAL_LONG(&const_JG_MANICHAEAN_FIVE_value, U_JG_MANICHAEAN_FIVE); - zend_string *const_JG_MANICHAEAN_FIVE_name = zend_string_init_interned("JG_MANICHAEAN_FIVE", sizeof("JG_MANICHAEAN_FIVE") - 1, 1); + zend_string *const_JG_MANICHAEAN_FIVE_name = zend_string_init_interned("JG_MANICHAEAN_FIVE", sizeof("JG_MANICHAEAN_FIVE") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_FIVE_name, &const_JG_MANICHAEAN_FIVE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_FIVE_name); + zend_string_release_ex(const_JG_MANICHAEAN_FIVE_name, true); zval const_JG_MANICHAEAN_GIMEL_value; ZVAL_LONG(&const_JG_MANICHAEAN_GIMEL_value, U_JG_MANICHAEAN_GIMEL); - zend_string *const_JG_MANICHAEAN_GIMEL_name = zend_string_init_interned("JG_MANICHAEAN_GIMEL", sizeof("JG_MANICHAEAN_GIMEL") - 1, 1); + zend_string *const_JG_MANICHAEAN_GIMEL_name = zend_string_init_interned("JG_MANICHAEAN_GIMEL", sizeof("JG_MANICHAEAN_GIMEL") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_GIMEL_name, &const_JG_MANICHAEAN_GIMEL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_GIMEL_name); + zend_string_release_ex(const_JG_MANICHAEAN_GIMEL_name, true); zval const_JG_MANICHAEAN_HETH_value; ZVAL_LONG(&const_JG_MANICHAEAN_HETH_value, U_JG_MANICHAEAN_HETH); - zend_string *const_JG_MANICHAEAN_HETH_name = zend_string_init_interned("JG_MANICHAEAN_HETH", sizeof("JG_MANICHAEAN_HETH") - 1, 1); + zend_string *const_JG_MANICHAEAN_HETH_name = zend_string_init_interned("JG_MANICHAEAN_HETH", sizeof("JG_MANICHAEAN_HETH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_HETH_name, &const_JG_MANICHAEAN_HETH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_HETH_name); + zend_string_release_ex(const_JG_MANICHAEAN_HETH_name, true); zval const_JG_MANICHAEAN_HUNDRED_value; ZVAL_LONG(&const_JG_MANICHAEAN_HUNDRED_value, U_JG_MANICHAEAN_HUNDRED); - zend_string *const_JG_MANICHAEAN_HUNDRED_name = zend_string_init_interned("JG_MANICHAEAN_HUNDRED", sizeof("JG_MANICHAEAN_HUNDRED") - 1, 1); + zend_string *const_JG_MANICHAEAN_HUNDRED_name = zend_string_init_interned("JG_MANICHAEAN_HUNDRED", sizeof("JG_MANICHAEAN_HUNDRED") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_HUNDRED_name, &const_JG_MANICHAEAN_HUNDRED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_HUNDRED_name); + zend_string_release_ex(const_JG_MANICHAEAN_HUNDRED_name, true); zval const_JG_MANICHAEAN_KAPH_value; ZVAL_LONG(&const_JG_MANICHAEAN_KAPH_value, U_JG_MANICHAEAN_KAPH); - zend_string *const_JG_MANICHAEAN_KAPH_name = zend_string_init_interned("JG_MANICHAEAN_KAPH", sizeof("JG_MANICHAEAN_KAPH") - 1, 1); + zend_string *const_JG_MANICHAEAN_KAPH_name = zend_string_init_interned("JG_MANICHAEAN_KAPH", sizeof("JG_MANICHAEAN_KAPH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_KAPH_name, &const_JG_MANICHAEAN_KAPH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_KAPH_name); + zend_string_release_ex(const_JG_MANICHAEAN_KAPH_name, true); zval const_JG_MANICHAEAN_LAMEDH_value; ZVAL_LONG(&const_JG_MANICHAEAN_LAMEDH_value, U_JG_MANICHAEAN_LAMEDH); - zend_string *const_JG_MANICHAEAN_LAMEDH_name = zend_string_init_interned("JG_MANICHAEAN_LAMEDH", sizeof("JG_MANICHAEAN_LAMEDH") - 1, 1); + zend_string *const_JG_MANICHAEAN_LAMEDH_name = zend_string_init_interned("JG_MANICHAEAN_LAMEDH", sizeof("JG_MANICHAEAN_LAMEDH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_LAMEDH_name, &const_JG_MANICHAEAN_LAMEDH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_LAMEDH_name); + zend_string_release_ex(const_JG_MANICHAEAN_LAMEDH_name, true); zval const_JG_MANICHAEAN_MEM_value; ZVAL_LONG(&const_JG_MANICHAEAN_MEM_value, U_JG_MANICHAEAN_MEM); - zend_string *const_JG_MANICHAEAN_MEM_name = zend_string_init_interned("JG_MANICHAEAN_MEM", sizeof("JG_MANICHAEAN_MEM") - 1, 1); + zend_string *const_JG_MANICHAEAN_MEM_name = zend_string_init_interned("JG_MANICHAEAN_MEM", sizeof("JG_MANICHAEAN_MEM") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_MEM_name, &const_JG_MANICHAEAN_MEM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_MEM_name); + zend_string_release_ex(const_JG_MANICHAEAN_MEM_name, true); zval const_JG_MANICHAEAN_NUN_value; ZVAL_LONG(&const_JG_MANICHAEAN_NUN_value, U_JG_MANICHAEAN_NUN); - zend_string *const_JG_MANICHAEAN_NUN_name = zend_string_init_interned("JG_MANICHAEAN_NUN", sizeof("JG_MANICHAEAN_NUN") - 1, 1); + zend_string *const_JG_MANICHAEAN_NUN_name = zend_string_init_interned("JG_MANICHAEAN_NUN", sizeof("JG_MANICHAEAN_NUN") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_NUN_name, &const_JG_MANICHAEAN_NUN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_NUN_name); + zend_string_release_ex(const_JG_MANICHAEAN_NUN_name, true); zval const_JG_MANICHAEAN_ONE_value; ZVAL_LONG(&const_JG_MANICHAEAN_ONE_value, U_JG_MANICHAEAN_ONE); - zend_string *const_JG_MANICHAEAN_ONE_name = zend_string_init_interned("JG_MANICHAEAN_ONE", sizeof("JG_MANICHAEAN_ONE") - 1, 1); + zend_string *const_JG_MANICHAEAN_ONE_name = zend_string_init_interned("JG_MANICHAEAN_ONE", sizeof("JG_MANICHAEAN_ONE") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_ONE_name, &const_JG_MANICHAEAN_ONE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_ONE_name); + zend_string_release_ex(const_JG_MANICHAEAN_ONE_name, true); zval const_JG_MANICHAEAN_PE_value; ZVAL_LONG(&const_JG_MANICHAEAN_PE_value, U_JG_MANICHAEAN_PE); - zend_string *const_JG_MANICHAEAN_PE_name = zend_string_init_interned("JG_MANICHAEAN_PE", sizeof("JG_MANICHAEAN_PE") - 1, 1); + zend_string *const_JG_MANICHAEAN_PE_name = zend_string_init_interned("JG_MANICHAEAN_PE", sizeof("JG_MANICHAEAN_PE") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_PE_name, &const_JG_MANICHAEAN_PE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_PE_name); + zend_string_release_ex(const_JG_MANICHAEAN_PE_name, true); zval const_JG_MANICHAEAN_QOPH_value; ZVAL_LONG(&const_JG_MANICHAEAN_QOPH_value, U_JG_MANICHAEAN_QOPH); - zend_string *const_JG_MANICHAEAN_QOPH_name = zend_string_init_interned("JG_MANICHAEAN_QOPH", sizeof("JG_MANICHAEAN_QOPH") - 1, 1); + zend_string *const_JG_MANICHAEAN_QOPH_name = zend_string_init_interned("JG_MANICHAEAN_QOPH", sizeof("JG_MANICHAEAN_QOPH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_QOPH_name, &const_JG_MANICHAEAN_QOPH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_QOPH_name); + zend_string_release_ex(const_JG_MANICHAEAN_QOPH_name, true); zval const_JG_MANICHAEAN_RESH_value; ZVAL_LONG(&const_JG_MANICHAEAN_RESH_value, U_JG_MANICHAEAN_RESH); - zend_string *const_JG_MANICHAEAN_RESH_name = zend_string_init_interned("JG_MANICHAEAN_RESH", sizeof("JG_MANICHAEAN_RESH") - 1, 1); + zend_string *const_JG_MANICHAEAN_RESH_name = zend_string_init_interned("JG_MANICHAEAN_RESH", sizeof("JG_MANICHAEAN_RESH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_RESH_name, &const_JG_MANICHAEAN_RESH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_RESH_name); + zend_string_release_ex(const_JG_MANICHAEAN_RESH_name, true); zval const_JG_MANICHAEAN_SADHE_value; ZVAL_LONG(&const_JG_MANICHAEAN_SADHE_value, U_JG_MANICHAEAN_SADHE); - zend_string *const_JG_MANICHAEAN_SADHE_name = zend_string_init_interned("JG_MANICHAEAN_SADHE", sizeof("JG_MANICHAEAN_SADHE") - 1, 1); + zend_string *const_JG_MANICHAEAN_SADHE_name = zend_string_init_interned("JG_MANICHAEAN_SADHE", sizeof("JG_MANICHAEAN_SADHE") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_SADHE_name, &const_JG_MANICHAEAN_SADHE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_SADHE_name); + zend_string_release_ex(const_JG_MANICHAEAN_SADHE_name, true); zval const_JG_MANICHAEAN_SAMEKH_value; ZVAL_LONG(&const_JG_MANICHAEAN_SAMEKH_value, U_JG_MANICHAEAN_SAMEKH); - zend_string *const_JG_MANICHAEAN_SAMEKH_name = zend_string_init_interned("JG_MANICHAEAN_SAMEKH", sizeof("JG_MANICHAEAN_SAMEKH") - 1, 1); + zend_string *const_JG_MANICHAEAN_SAMEKH_name = zend_string_init_interned("JG_MANICHAEAN_SAMEKH", sizeof("JG_MANICHAEAN_SAMEKH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_SAMEKH_name, &const_JG_MANICHAEAN_SAMEKH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_SAMEKH_name); + zend_string_release_ex(const_JG_MANICHAEAN_SAMEKH_name, true); zval const_JG_MANICHAEAN_TAW_value; ZVAL_LONG(&const_JG_MANICHAEAN_TAW_value, U_JG_MANICHAEAN_TAW); - zend_string *const_JG_MANICHAEAN_TAW_name = zend_string_init_interned("JG_MANICHAEAN_TAW", sizeof("JG_MANICHAEAN_TAW") - 1, 1); + zend_string *const_JG_MANICHAEAN_TAW_name = zend_string_init_interned("JG_MANICHAEAN_TAW", sizeof("JG_MANICHAEAN_TAW") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_TAW_name, &const_JG_MANICHAEAN_TAW_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_TAW_name); + zend_string_release_ex(const_JG_MANICHAEAN_TAW_name, true); zval const_JG_MANICHAEAN_TEN_value; ZVAL_LONG(&const_JG_MANICHAEAN_TEN_value, U_JG_MANICHAEAN_TEN); - zend_string *const_JG_MANICHAEAN_TEN_name = zend_string_init_interned("JG_MANICHAEAN_TEN", sizeof("JG_MANICHAEAN_TEN") - 1, 1); + zend_string *const_JG_MANICHAEAN_TEN_name = zend_string_init_interned("JG_MANICHAEAN_TEN", sizeof("JG_MANICHAEAN_TEN") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_TEN_name, &const_JG_MANICHAEAN_TEN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_TEN_name); + zend_string_release_ex(const_JG_MANICHAEAN_TEN_name, true); zval const_JG_MANICHAEAN_TETH_value; ZVAL_LONG(&const_JG_MANICHAEAN_TETH_value, U_JG_MANICHAEAN_TETH); - zend_string *const_JG_MANICHAEAN_TETH_name = zend_string_init_interned("JG_MANICHAEAN_TETH", sizeof("JG_MANICHAEAN_TETH") - 1, 1); + zend_string *const_JG_MANICHAEAN_TETH_name = zend_string_init_interned("JG_MANICHAEAN_TETH", sizeof("JG_MANICHAEAN_TETH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_TETH_name, &const_JG_MANICHAEAN_TETH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_TETH_name); + zend_string_release_ex(const_JG_MANICHAEAN_TETH_name, true); zval const_JG_MANICHAEAN_THAMEDH_value; ZVAL_LONG(&const_JG_MANICHAEAN_THAMEDH_value, U_JG_MANICHAEAN_THAMEDH); - zend_string *const_JG_MANICHAEAN_THAMEDH_name = zend_string_init_interned("JG_MANICHAEAN_THAMEDH", sizeof("JG_MANICHAEAN_THAMEDH") - 1, 1); + zend_string *const_JG_MANICHAEAN_THAMEDH_name = zend_string_init_interned("JG_MANICHAEAN_THAMEDH", sizeof("JG_MANICHAEAN_THAMEDH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_THAMEDH_name, &const_JG_MANICHAEAN_THAMEDH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_THAMEDH_name); + zend_string_release_ex(const_JG_MANICHAEAN_THAMEDH_name, true); zval const_JG_MANICHAEAN_TWENTY_value; ZVAL_LONG(&const_JG_MANICHAEAN_TWENTY_value, U_JG_MANICHAEAN_TWENTY); - zend_string *const_JG_MANICHAEAN_TWENTY_name = zend_string_init_interned("JG_MANICHAEAN_TWENTY", sizeof("JG_MANICHAEAN_TWENTY") - 1, 1); + zend_string *const_JG_MANICHAEAN_TWENTY_name = zend_string_init_interned("JG_MANICHAEAN_TWENTY", sizeof("JG_MANICHAEAN_TWENTY") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_TWENTY_name, &const_JG_MANICHAEAN_TWENTY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_TWENTY_name); + zend_string_release_ex(const_JG_MANICHAEAN_TWENTY_name, true); zval const_JG_MANICHAEAN_WAW_value; ZVAL_LONG(&const_JG_MANICHAEAN_WAW_value, U_JG_MANICHAEAN_WAW); - zend_string *const_JG_MANICHAEAN_WAW_name = zend_string_init_interned("JG_MANICHAEAN_WAW", sizeof("JG_MANICHAEAN_WAW") - 1, 1); + zend_string *const_JG_MANICHAEAN_WAW_name = zend_string_init_interned("JG_MANICHAEAN_WAW", sizeof("JG_MANICHAEAN_WAW") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_WAW_name, &const_JG_MANICHAEAN_WAW_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_WAW_name); + zend_string_release_ex(const_JG_MANICHAEAN_WAW_name, true); zval const_JG_MANICHAEAN_YODH_value; ZVAL_LONG(&const_JG_MANICHAEAN_YODH_value, U_JG_MANICHAEAN_YODH); - zend_string *const_JG_MANICHAEAN_YODH_name = zend_string_init_interned("JG_MANICHAEAN_YODH", sizeof("JG_MANICHAEAN_YODH") - 1, 1); + zend_string *const_JG_MANICHAEAN_YODH_name = zend_string_init_interned("JG_MANICHAEAN_YODH", sizeof("JG_MANICHAEAN_YODH") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_YODH_name, &const_JG_MANICHAEAN_YODH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_YODH_name); + zend_string_release_ex(const_JG_MANICHAEAN_YODH_name, true); zval const_JG_MANICHAEAN_ZAYIN_value; ZVAL_LONG(&const_JG_MANICHAEAN_ZAYIN_value, U_JG_MANICHAEAN_ZAYIN); - zend_string *const_JG_MANICHAEAN_ZAYIN_name = zend_string_init_interned("JG_MANICHAEAN_ZAYIN", sizeof("JG_MANICHAEAN_ZAYIN") - 1, 1); + zend_string *const_JG_MANICHAEAN_ZAYIN_name = zend_string_init_interned("JG_MANICHAEAN_ZAYIN", sizeof("JG_MANICHAEAN_ZAYIN") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_MANICHAEAN_ZAYIN_name, &const_JG_MANICHAEAN_ZAYIN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_MANICHAEAN_ZAYIN_name); + zend_string_release_ex(const_JG_MANICHAEAN_ZAYIN_name, true); zval const_JG_STRAIGHT_WAW_value; ZVAL_LONG(&const_JG_STRAIGHT_WAW_value, U_JG_STRAIGHT_WAW); - zend_string *const_JG_STRAIGHT_WAW_name = zend_string_init_interned("JG_STRAIGHT_WAW", sizeof("JG_STRAIGHT_WAW") - 1, 1); + zend_string *const_JG_STRAIGHT_WAW_name = zend_string_init_interned("JG_STRAIGHT_WAW", sizeof("JG_STRAIGHT_WAW") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_STRAIGHT_WAW_name, &const_JG_STRAIGHT_WAW_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_STRAIGHT_WAW_name); + zend_string_release_ex(const_JG_STRAIGHT_WAW_name, true); zval const_JG_COUNT_value; ZVAL_LONG(&const_JG_COUNT_value, U_JG_COUNT); - zend_string *const_JG_COUNT_name = zend_string_init_interned("JG_COUNT", sizeof("JG_COUNT") - 1, 1); + zend_string *const_JG_COUNT_name = zend_string_init_interned("JG_COUNT", sizeof("JG_COUNT") - 1, true); zend_declare_typed_class_constant(class_entry, const_JG_COUNT_name, &const_JG_COUNT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_JG_COUNT_name); + zend_string_release_ex(const_JG_COUNT_name, true); zval const_GCB_OTHER_value; ZVAL_LONG(&const_GCB_OTHER_value, U_GCB_OTHER); - zend_string *const_GCB_OTHER_name = zend_string_init_interned("GCB_OTHER", sizeof("GCB_OTHER") - 1, 1); + zend_string *const_GCB_OTHER_name = zend_string_init_interned("GCB_OTHER", sizeof("GCB_OTHER") - 1, true); zend_declare_typed_class_constant(class_entry, const_GCB_OTHER_name, &const_GCB_OTHER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_GCB_OTHER_name); + zend_string_release_ex(const_GCB_OTHER_name, true); zval const_GCB_CONTROL_value; ZVAL_LONG(&const_GCB_CONTROL_value, U_GCB_CONTROL); - zend_string *const_GCB_CONTROL_name = zend_string_init_interned("GCB_CONTROL", sizeof("GCB_CONTROL") - 1, 1); + zend_string *const_GCB_CONTROL_name = zend_string_init_interned("GCB_CONTROL", sizeof("GCB_CONTROL") - 1, true); zend_declare_typed_class_constant(class_entry, const_GCB_CONTROL_name, &const_GCB_CONTROL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_GCB_CONTROL_name); + zend_string_release_ex(const_GCB_CONTROL_name, true); zval const_GCB_CR_value; ZVAL_LONG(&const_GCB_CR_value, U_GCB_CR); - zend_string *const_GCB_CR_name = zend_string_init_interned("GCB_CR", sizeof("GCB_CR") - 1, 1); + zend_string *const_GCB_CR_name = zend_string_init_interned("GCB_CR", sizeof("GCB_CR") - 1, true); zend_declare_typed_class_constant(class_entry, const_GCB_CR_name, &const_GCB_CR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_GCB_CR_name); + zend_string_release_ex(const_GCB_CR_name, true); zval const_GCB_EXTEND_value; ZVAL_LONG(&const_GCB_EXTEND_value, U_GCB_EXTEND); - zend_string *const_GCB_EXTEND_name = zend_string_init_interned("GCB_EXTEND", sizeof("GCB_EXTEND") - 1, 1); + zend_string *const_GCB_EXTEND_name = zend_string_init_interned("GCB_EXTEND", sizeof("GCB_EXTEND") - 1, true); zend_declare_typed_class_constant(class_entry, const_GCB_EXTEND_name, &const_GCB_EXTEND_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_GCB_EXTEND_name); + zend_string_release_ex(const_GCB_EXTEND_name, true); zval const_GCB_L_value; ZVAL_LONG(&const_GCB_L_value, U_GCB_L); - zend_string *const_GCB_L_name = zend_string_init_interned("GCB_L", sizeof("GCB_L") - 1, 1); + zend_string *const_GCB_L_name = zend_string_init_interned("GCB_L", sizeof("GCB_L") - 1, true); zend_declare_typed_class_constant(class_entry, const_GCB_L_name, &const_GCB_L_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_GCB_L_name); + zend_string_release_ex(const_GCB_L_name, true); zval const_GCB_LF_value; ZVAL_LONG(&const_GCB_LF_value, U_GCB_LF); - zend_string *const_GCB_LF_name = zend_string_init_interned("GCB_LF", sizeof("GCB_LF") - 1, 1); + zend_string *const_GCB_LF_name = zend_string_init_interned("GCB_LF", sizeof("GCB_LF") - 1, true); zend_declare_typed_class_constant(class_entry, const_GCB_LF_name, &const_GCB_LF_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_GCB_LF_name); + zend_string_release_ex(const_GCB_LF_name, true); zval const_GCB_LV_value; ZVAL_LONG(&const_GCB_LV_value, U_GCB_LV); - zend_string *const_GCB_LV_name = zend_string_init_interned("GCB_LV", sizeof("GCB_LV") - 1, 1); + zend_string *const_GCB_LV_name = zend_string_init_interned("GCB_LV", sizeof("GCB_LV") - 1, true); zend_declare_typed_class_constant(class_entry, const_GCB_LV_name, &const_GCB_LV_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_GCB_LV_name); + zend_string_release_ex(const_GCB_LV_name, true); zval const_GCB_LVT_value; ZVAL_LONG(&const_GCB_LVT_value, U_GCB_LVT); - zend_string *const_GCB_LVT_name = zend_string_init_interned("GCB_LVT", sizeof("GCB_LVT") - 1, 1); + zend_string *const_GCB_LVT_name = zend_string_init_interned("GCB_LVT", sizeof("GCB_LVT") - 1, true); zend_declare_typed_class_constant(class_entry, const_GCB_LVT_name, &const_GCB_LVT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_GCB_LVT_name); + zend_string_release_ex(const_GCB_LVT_name, true); zval const_GCB_T_value; ZVAL_LONG(&const_GCB_T_value, U_GCB_T); - zend_string *const_GCB_T_name = zend_string_init_interned("GCB_T", sizeof("GCB_T") - 1, 1); + zend_string *const_GCB_T_name = zend_string_init_interned("GCB_T", sizeof("GCB_T") - 1, true); zend_declare_typed_class_constant(class_entry, const_GCB_T_name, &const_GCB_T_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_GCB_T_name); + zend_string_release_ex(const_GCB_T_name, true); zval const_GCB_V_value; ZVAL_LONG(&const_GCB_V_value, U_GCB_V); - zend_string *const_GCB_V_name = zend_string_init_interned("GCB_V", sizeof("GCB_V") - 1, 1); + zend_string *const_GCB_V_name = zend_string_init_interned("GCB_V", sizeof("GCB_V") - 1, true); zend_declare_typed_class_constant(class_entry, const_GCB_V_name, &const_GCB_V_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_GCB_V_name); + zend_string_release_ex(const_GCB_V_name, true); zval const_GCB_SPACING_MARK_value; ZVAL_LONG(&const_GCB_SPACING_MARK_value, U_GCB_SPACING_MARK); - zend_string *const_GCB_SPACING_MARK_name = zend_string_init_interned("GCB_SPACING_MARK", sizeof("GCB_SPACING_MARK") - 1, 1); + zend_string *const_GCB_SPACING_MARK_name = zend_string_init_interned("GCB_SPACING_MARK", sizeof("GCB_SPACING_MARK") - 1, true); zend_declare_typed_class_constant(class_entry, const_GCB_SPACING_MARK_name, &const_GCB_SPACING_MARK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_GCB_SPACING_MARK_name); + zend_string_release_ex(const_GCB_SPACING_MARK_name, true); zval const_GCB_PREPEND_value; ZVAL_LONG(&const_GCB_PREPEND_value, U_GCB_PREPEND); - zend_string *const_GCB_PREPEND_name = zend_string_init_interned("GCB_PREPEND", sizeof("GCB_PREPEND") - 1, 1); + zend_string *const_GCB_PREPEND_name = zend_string_init_interned("GCB_PREPEND", sizeof("GCB_PREPEND") - 1, true); zend_declare_typed_class_constant(class_entry, const_GCB_PREPEND_name, &const_GCB_PREPEND_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_GCB_PREPEND_name); + zend_string_release_ex(const_GCB_PREPEND_name, true); zval const_GCB_REGIONAL_INDICATOR_value; ZVAL_LONG(&const_GCB_REGIONAL_INDICATOR_value, U_GCB_REGIONAL_INDICATOR); - zend_string *const_GCB_REGIONAL_INDICATOR_name = zend_string_init_interned("GCB_REGIONAL_INDICATOR", sizeof("GCB_REGIONAL_INDICATOR") - 1, 1); + zend_string *const_GCB_REGIONAL_INDICATOR_name = zend_string_init_interned("GCB_REGIONAL_INDICATOR", sizeof("GCB_REGIONAL_INDICATOR") - 1, true); zend_declare_typed_class_constant(class_entry, const_GCB_REGIONAL_INDICATOR_name, &const_GCB_REGIONAL_INDICATOR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_GCB_REGIONAL_INDICATOR_name); + zend_string_release_ex(const_GCB_REGIONAL_INDICATOR_name, true); zval const_GCB_COUNT_value; ZVAL_LONG(&const_GCB_COUNT_value, U_GCB_COUNT); - zend_string *const_GCB_COUNT_name = zend_string_init_interned("GCB_COUNT", sizeof("GCB_COUNT") - 1, 1); + zend_string *const_GCB_COUNT_name = zend_string_init_interned("GCB_COUNT", sizeof("GCB_COUNT") - 1, true); zend_declare_typed_class_constant(class_entry, const_GCB_COUNT_name, &const_GCB_COUNT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_GCB_COUNT_name); + zend_string_release_ex(const_GCB_COUNT_name, true); zval const_WB_OTHER_value; ZVAL_LONG(&const_WB_OTHER_value, U_WB_OTHER); - zend_string *const_WB_OTHER_name = zend_string_init_interned("WB_OTHER", sizeof("WB_OTHER") - 1, 1); + zend_string *const_WB_OTHER_name = zend_string_init_interned("WB_OTHER", sizeof("WB_OTHER") - 1, true); zend_declare_typed_class_constant(class_entry, const_WB_OTHER_name, &const_WB_OTHER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WB_OTHER_name); + zend_string_release_ex(const_WB_OTHER_name, true); zval const_WB_ALETTER_value; ZVAL_LONG(&const_WB_ALETTER_value, U_WB_ALETTER); - zend_string *const_WB_ALETTER_name = zend_string_init_interned("WB_ALETTER", sizeof("WB_ALETTER") - 1, 1); + zend_string *const_WB_ALETTER_name = zend_string_init_interned("WB_ALETTER", sizeof("WB_ALETTER") - 1, true); zend_declare_typed_class_constant(class_entry, const_WB_ALETTER_name, &const_WB_ALETTER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WB_ALETTER_name); + zend_string_release_ex(const_WB_ALETTER_name, true); zval const_WB_FORMAT_value; ZVAL_LONG(&const_WB_FORMAT_value, U_WB_FORMAT); - zend_string *const_WB_FORMAT_name = zend_string_init_interned("WB_FORMAT", sizeof("WB_FORMAT") - 1, 1); + zend_string *const_WB_FORMAT_name = zend_string_init_interned("WB_FORMAT", sizeof("WB_FORMAT") - 1, true); zend_declare_typed_class_constant(class_entry, const_WB_FORMAT_name, &const_WB_FORMAT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WB_FORMAT_name); + zend_string_release_ex(const_WB_FORMAT_name, true); zval const_WB_KATAKANA_value; ZVAL_LONG(&const_WB_KATAKANA_value, U_WB_KATAKANA); - zend_string *const_WB_KATAKANA_name = zend_string_init_interned("WB_KATAKANA", sizeof("WB_KATAKANA") - 1, 1); + zend_string *const_WB_KATAKANA_name = zend_string_init_interned("WB_KATAKANA", sizeof("WB_KATAKANA") - 1, true); zend_declare_typed_class_constant(class_entry, const_WB_KATAKANA_name, &const_WB_KATAKANA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WB_KATAKANA_name); + zend_string_release_ex(const_WB_KATAKANA_name, true); zval const_WB_MIDLETTER_value; ZVAL_LONG(&const_WB_MIDLETTER_value, U_WB_MIDLETTER); - zend_string *const_WB_MIDLETTER_name = zend_string_init_interned("WB_MIDLETTER", sizeof("WB_MIDLETTER") - 1, 1); + zend_string *const_WB_MIDLETTER_name = zend_string_init_interned("WB_MIDLETTER", sizeof("WB_MIDLETTER") - 1, true); zend_declare_typed_class_constant(class_entry, const_WB_MIDLETTER_name, &const_WB_MIDLETTER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WB_MIDLETTER_name); + zend_string_release_ex(const_WB_MIDLETTER_name, true); zval const_WB_MIDNUM_value; ZVAL_LONG(&const_WB_MIDNUM_value, U_WB_MIDNUM); - zend_string *const_WB_MIDNUM_name = zend_string_init_interned("WB_MIDNUM", sizeof("WB_MIDNUM") - 1, 1); + zend_string *const_WB_MIDNUM_name = zend_string_init_interned("WB_MIDNUM", sizeof("WB_MIDNUM") - 1, true); zend_declare_typed_class_constant(class_entry, const_WB_MIDNUM_name, &const_WB_MIDNUM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WB_MIDNUM_name); + zend_string_release_ex(const_WB_MIDNUM_name, true); zval const_WB_NUMERIC_value; ZVAL_LONG(&const_WB_NUMERIC_value, U_WB_NUMERIC); - zend_string *const_WB_NUMERIC_name = zend_string_init_interned("WB_NUMERIC", sizeof("WB_NUMERIC") - 1, 1); + zend_string *const_WB_NUMERIC_name = zend_string_init_interned("WB_NUMERIC", sizeof("WB_NUMERIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_WB_NUMERIC_name, &const_WB_NUMERIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WB_NUMERIC_name); + zend_string_release_ex(const_WB_NUMERIC_name, true); zval const_WB_EXTENDNUMLET_value; ZVAL_LONG(&const_WB_EXTENDNUMLET_value, U_WB_EXTENDNUMLET); - zend_string *const_WB_EXTENDNUMLET_name = zend_string_init_interned("WB_EXTENDNUMLET", sizeof("WB_EXTENDNUMLET") - 1, 1); + zend_string *const_WB_EXTENDNUMLET_name = zend_string_init_interned("WB_EXTENDNUMLET", sizeof("WB_EXTENDNUMLET") - 1, true); zend_declare_typed_class_constant(class_entry, const_WB_EXTENDNUMLET_name, &const_WB_EXTENDNUMLET_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WB_EXTENDNUMLET_name); + zend_string_release_ex(const_WB_EXTENDNUMLET_name, true); zval const_WB_CR_value; ZVAL_LONG(&const_WB_CR_value, U_WB_CR); - zend_string *const_WB_CR_name = zend_string_init_interned("WB_CR", sizeof("WB_CR") - 1, 1); + zend_string *const_WB_CR_name = zend_string_init_interned("WB_CR", sizeof("WB_CR") - 1, true); zend_declare_typed_class_constant(class_entry, const_WB_CR_name, &const_WB_CR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WB_CR_name); + zend_string_release_ex(const_WB_CR_name, true); zval const_WB_EXTEND_value; ZVAL_LONG(&const_WB_EXTEND_value, U_WB_EXTEND); - zend_string *const_WB_EXTEND_name = zend_string_init_interned("WB_EXTEND", sizeof("WB_EXTEND") - 1, 1); + zend_string *const_WB_EXTEND_name = zend_string_init_interned("WB_EXTEND", sizeof("WB_EXTEND") - 1, true); zend_declare_typed_class_constant(class_entry, const_WB_EXTEND_name, &const_WB_EXTEND_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WB_EXTEND_name); + zend_string_release_ex(const_WB_EXTEND_name, true); zval const_WB_LF_value; ZVAL_LONG(&const_WB_LF_value, U_WB_LF); - zend_string *const_WB_LF_name = zend_string_init_interned("WB_LF", sizeof("WB_LF") - 1, 1); + zend_string *const_WB_LF_name = zend_string_init_interned("WB_LF", sizeof("WB_LF") - 1, true); zend_declare_typed_class_constant(class_entry, const_WB_LF_name, &const_WB_LF_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WB_LF_name); + zend_string_release_ex(const_WB_LF_name, true); zval const_WB_MIDNUMLET_value; ZVAL_LONG(&const_WB_MIDNUMLET_value, U_WB_MIDNUMLET); - zend_string *const_WB_MIDNUMLET_name = zend_string_init_interned("WB_MIDNUMLET", sizeof("WB_MIDNUMLET") - 1, 1); + zend_string *const_WB_MIDNUMLET_name = zend_string_init_interned("WB_MIDNUMLET", sizeof("WB_MIDNUMLET") - 1, true); zend_declare_typed_class_constant(class_entry, const_WB_MIDNUMLET_name, &const_WB_MIDNUMLET_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WB_MIDNUMLET_name); + zend_string_release_ex(const_WB_MIDNUMLET_name, true); zval const_WB_NEWLINE_value; ZVAL_LONG(&const_WB_NEWLINE_value, U_WB_NEWLINE); - zend_string *const_WB_NEWLINE_name = zend_string_init_interned("WB_NEWLINE", sizeof("WB_NEWLINE") - 1, 1); + zend_string *const_WB_NEWLINE_name = zend_string_init_interned("WB_NEWLINE", sizeof("WB_NEWLINE") - 1, true); zend_declare_typed_class_constant(class_entry, const_WB_NEWLINE_name, &const_WB_NEWLINE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WB_NEWLINE_name); + zend_string_release_ex(const_WB_NEWLINE_name, true); zval const_WB_REGIONAL_INDICATOR_value; ZVAL_LONG(&const_WB_REGIONAL_INDICATOR_value, U_WB_REGIONAL_INDICATOR); - zend_string *const_WB_REGIONAL_INDICATOR_name = zend_string_init_interned("WB_REGIONAL_INDICATOR", sizeof("WB_REGIONAL_INDICATOR") - 1, 1); + zend_string *const_WB_REGIONAL_INDICATOR_name = zend_string_init_interned("WB_REGIONAL_INDICATOR", sizeof("WB_REGIONAL_INDICATOR") - 1, true); zend_declare_typed_class_constant(class_entry, const_WB_REGIONAL_INDICATOR_name, &const_WB_REGIONAL_INDICATOR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WB_REGIONAL_INDICATOR_name); + zend_string_release_ex(const_WB_REGIONAL_INDICATOR_name, true); zval const_WB_HEBREW_LETTER_value; ZVAL_LONG(&const_WB_HEBREW_LETTER_value, U_WB_HEBREW_LETTER); - zend_string *const_WB_HEBREW_LETTER_name = zend_string_init_interned("WB_HEBREW_LETTER", sizeof("WB_HEBREW_LETTER") - 1, 1); + zend_string *const_WB_HEBREW_LETTER_name = zend_string_init_interned("WB_HEBREW_LETTER", sizeof("WB_HEBREW_LETTER") - 1, true); zend_declare_typed_class_constant(class_entry, const_WB_HEBREW_LETTER_name, &const_WB_HEBREW_LETTER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WB_HEBREW_LETTER_name); + zend_string_release_ex(const_WB_HEBREW_LETTER_name, true); zval const_WB_SINGLE_QUOTE_value; ZVAL_LONG(&const_WB_SINGLE_QUOTE_value, U_WB_SINGLE_QUOTE); - zend_string *const_WB_SINGLE_QUOTE_name = zend_string_init_interned("WB_SINGLE_QUOTE", sizeof("WB_SINGLE_QUOTE") - 1, 1); + zend_string *const_WB_SINGLE_QUOTE_name = zend_string_init_interned("WB_SINGLE_QUOTE", sizeof("WB_SINGLE_QUOTE") - 1, true); zend_declare_typed_class_constant(class_entry, const_WB_SINGLE_QUOTE_name, &const_WB_SINGLE_QUOTE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WB_SINGLE_QUOTE_name); + zend_string_release_ex(const_WB_SINGLE_QUOTE_name, true); zval const_WB_DOUBLE_QUOTE_value; ZVAL_LONG(&const_WB_DOUBLE_QUOTE_value, U_WB_DOUBLE_QUOTE); - zend_string *const_WB_DOUBLE_QUOTE_name = zend_string_init_interned("WB_DOUBLE_QUOTE", sizeof("WB_DOUBLE_QUOTE") - 1, 1); + zend_string *const_WB_DOUBLE_QUOTE_name = zend_string_init_interned("WB_DOUBLE_QUOTE", sizeof("WB_DOUBLE_QUOTE") - 1, true); zend_declare_typed_class_constant(class_entry, const_WB_DOUBLE_QUOTE_name, &const_WB_DOUBLE_QUOTE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WB_DOUBLE_QUOTE_name); + zend_string_release_ex(const_WB_DOUBLE_QUOTE_name, true); zval const_WB_COUNT_value; ZVAL_LONG(&const_WB_COUNT_value, U_WB_COUNT); - zend_string *const_WB_COUNT_name = zend_string_init_interned("WB_COUNT", sizeof("WB_COUNT") - 1, 1); + zend_string *const_WB_COUNT_name = zend_string_init_interned("WB_COUNT", sizeof("WB_COUNT") - 1, true); zend_declare_typed_class_constant(class_entry, const_WB_COUNT_name, &const_WB_COUNT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WB_COUNT_name); + zend_string_release_ex(const_WB_COUNT_name, true); zval const_SB_OTHER_value; ZVAL_LONG(&const_SB_OTHER_value, U_SB_OTHER); - zend_string *const_SB_OTHER_name = zend_string_init_interned("SB_OTHER", sizeof("SB_OTHER") - 1, 1); + zend_string *const_SB_OTHER_name = zend_string_init_interned("SB_OTHER", sizeof("SB_OTHER") - 1, true); zend_declare_typed_class_constant(class_entry, const_SB_OTHER_name, &const_SB_OTHER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SB_OTHER_name); + zend_string_release_ex(const_SB_OTHER_name, true); zval const_SB_ATERM_value; ZVAL_LONG(&const_SB_ATERM_value, U_SB_ATERM); - zend_string *const_SB_ATERM_name = zend_string_init_interned("SB_ATERM", sizeof("SB_ATERM") - 1, 1); + zend_string *const_SB_ATERM_name = zend_string_init_interned("SB_ATERM", sizeof("SB_ATERM") - 1, true); zend_declare_typed_class_constant(class_entry, const_SB_ATERM_name, &const_SB_ATERM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SB_ATERM_name); + zend_string_release_ex(const_SB_ATERM_name, true); zval const_SB_CLOSE_value; ZVAL_LONG(&const_SB_CLOSE_value, U_SB_CLOSE); - zend_string *const_SB_CLOSE_name = zend_string_init_interned("SB_CLOSE", sizeof("SB_CLOSE") - 1, 1); + zend_string *const_SB_CLOSE_name = zend_string_init_interned("SB_CLOSE", sizeof("SB_CLOSE") - 1, true); zend_declare_typed_class_constant(class_entry, const_SB_CLOSE_name, &const_SB_CLOSE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SB_CLOSE_name); + zend_string_release_ex(const_SB_CLOSE_name, true); zval const_SB_FORMAT_value; ZVAL_LONG(&const_SB_FORMAT_value, U_SB_FORMAT); - zend_string *const_SB_FORMAT_name = zend_string_init_interned("SB_FORMAT", sizeof("SB_FORMAT") - 1, 1); + zend_string *const_SB_FORMAT_name = zend_string_init_interned("SB_FORMAT", sizeof("SB_FORMAT") - 1, true); zend_declare_typed_class_constant(class_entry, const_SB_FORMAT_name, &const_SB_FORMAT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SB_FORMAT_name); + zend_string_release_ex(const_SB_FORMAT_name, true); zval const_SB_LOWER_value; ZVAL_LONG(&const_SB_LOWER_value, U_SB_LOWER); - zend_string *const_SB_LOWER_name = zend_string_init_interned("SB_LOWER", sizeof("SB_LOWER") - 1, 1); + zend_string *const_SB_LOWER_name = zend_string_init_interned("SB_LOWER", sizeof("SB_LOWER") - 1, true); zend_declare_typed_class_constant(class_entry, const_SB_LOWER_name, &const_SB_LOWER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SB_LOWER_name); + zend_string_release_ex(const_SB_LOWER_name, true); zval const_SB_NUMERIC_value; ZVAL_LONG(&const_SB_NUMERIC_value, U_SB_NUMERIC); - zend_string *const_SB_NUMERIC_name = zend_string_init_interned("SB_NUMERIC", sizeof("SB_NUMERIC") - 1, 1); + zend_string *const_SB_NUMERIC_name = zend_string_init_interned("SB_NUMERIC", sizeof("SB_NUMERIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_SB_NUMERIC_name, &const_SB_NUMERIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SB_NUMERIC_name); + zend_string_release_ex(const_SB_NUMERIC_name, true); zval const_SB_OLETTER_value; ZVAL_LONG(&const_SB_OLETTER_value, U_SB_OLETTER); - zend_string *const_SB_OLETTER_name = zend_string_init_interned("SB_OLETTER", sizeof("SB_OLETTER") - 1, 1); + zend_string *const_SB_OLETTER_name = zend_string_init_interned("SB_OLETTER", sizeof("SB_OLETTER") - 1, true); zend_declare_typed_class_constant(class_entry, const_SB_OLETTER_name, &const_SB_OLETTER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SB_OLETTER_name); + zend_string_release_ex(const_SB_OLETTER_name, true); zval const_SB_SEP_value; ZVAL_LONG(&const_SB_SEP_value, U_SB_SEP); - zend_string *const_SB_SEP_name = zend_string_init_interned("SB_SEP", sizeof("SB_SEP") - 1, 1); + zend_string *const_SB_SEP_name = zend_string_init_interned("SB_SEP", sizeof("SB_SEP") - 1, true); zend_declare_typed_class_constant(class_entry, const_SB_SEP_name, &const_SB_SEP_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SB_SEP_name); + zend_string_release_ex(const_SB_SEP_name, true); zval const_SB_SP_value; ZVAL_LONG(&const_SB_SP_value, U_SB_SP); - zend_string *const_SB_SP_name = zend_string_init_interned("SB_SP", sizeof("SB_SP") - 1, 1); + zend_string *const_SB_SP_name = zend_string_init_interned("SB_SP", sizeof("SB_SP") - 1, true); zend_declare_typed_class_constant(class_entry, const_SB_SP_name, &const_SB_SP_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SB_SP_name); + zend_string_release_ex(const_SB_SP_name, true); zval const_SB_STERM_value; ZVAL_LONG(&const_SB_STERM_value, U_SB_STERM); - zend_string *const_SB_STERM_name = zend_string_init_interned("SB_STERM", sizeof("SB_STERM") - 1, 1); + zend_string *const_SB_STERM_name = zend_string_init_interned("SB_STERM", sizeof("SB_STERM") - 1, true); zend_declare_typed_class_constant(class_entry, const_SB_STERM_name, &const_SB_STERM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SB_STERM_name); + zend_string_release_ex(const_SB_STERM_name, true); zval const_SB_UPPER_value; ZVAL_LONG(&const_SB_UPPER_value, U_SB_UPPER); - zend_string *const_SB_UPPER_name = zend_string_init_interned("SB_UPPER", sizeof("SB_UPPER") - 1, 1); + zend_string *const_SB_UPPER_name = zend_string_init_interned("SB_UPPER", sizeof("SB_UPPER") - 1, true); zend_declare_typed_class_constant(class_entry, const_SB_UPPER_name, &const_SB_UPPER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SB_UPPER_name); + zend_string_release_ex(const_SB_UPPER_name, true); zval const_SB_CR_value; ZVAL_LONG(&const_SB_CR_value, U_SB_CR); - zend_string *const_SB_CR_name = zend_string_init_interned("SB_CR", sizeof("SB_CR") - 1, 1); + zend_string *const_SB_CR_name = zend_string_init_interned("SB_CR", sizeof("SB_CR") - 1, true); zend_declare_typed_class_constant(class_entry, const_SB_CR_name, &const_SB_CR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SB_CR_name); + zend_string_release_ex(const_SB_CR_name, true); zval const_SB_EXTEND_value; ZVAL_LONG(&const_SB_EXTEND_value, U_SB_EXTEND); - zend_string *const_SB_EXTEND_name = zend_string_init_interned("SB_EXTEND", sizeof("SB_EXTEND") - 1, 1); + zend_string *const_SB_EXTEND_name = zend_string_init_interned("SB_EXTEND", sizeof("SB_EXTEND") - 1, true); zend_declare_typed_class_constant(class_entry, const_SB_EXTEND_name, &const_SB_EXTEND_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SB_EXTEND_name); + zend_string_release_ex(const_SB_EXTEND_name, true); zval const_SB_LF_value; ZVAL_LONG(&const_SB_LF_value, U_SB_LF); - zend_string *const_SB_LF_name = zend_string_init_interned("SB_LF", sizeof("SB_LF") - 1, 1); + zend_string *const_SB_LF_name = zend_string_init_interned("SB_LF", sizeof("SB_LF") - 1, true); zend_declare_typed_class_constant(class_entry, const_SB_LF_name, &const_SB_LF_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SB_LF_name); + zend_string_release_ex(const_SB_LF_name, true); zval const_SB_SCONTINUE_value; ZVAL_LONG(&const_SB_SCONTINUE_value, U_SB_SCONTINUE); - zend_string *const_SB_SCONTINUE_name = zend_string_init_interned("SB_SCONTINUE", sizeof("SB_SCONTINUE") - 1, 1); + zend_string *const_SB_SCONTINUE_name = zend_string_init_interned("SB_SCONTINUE", sizeof("SB_SCONTINUE") - 1, true); zend_declare_typed_class_constant(class_entry, const_SB_SCONTINUE_name, &const_SB_SCONTINUE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SB_SCONTINUE_name); + zend_string_release_ex(const_SB_SCONTINUE_name, true); zval const_SB_COUNT_value; ZVAL_LONG(&const_SB_COUNT_value, U_SB_COUNT); - zend_string *const_SB_COUNT_name = zend_string_init_interned("SB_COUNT", sizeof("SB_COUNT") - 1, 1); + zend_string *const_SB_COUNT_name = zend_string_init_interned("SB_COUNT", sizeof("SB_COUNT") - 1, true); zend_declare_typed_class_constant(class_entry, const_SB_COUNT_name, &const_SB_COUNT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SB_COUNT_name); + zend_string_release_ex(const_SB_COUNT_name, true); zval const_LB_UNKNOWN_value; ZVAL_LONG(&const_LB_UNKNOWN_value, U_LB_UNKNOWN); - zend_string *const_LB_UNKNOWN_name = zend_string_init_interned("LB_UNKNOWN", sizeof("LB_UNKNOWN") - 1, 1); + zend_string *const_LB_UNKNOWN_name = zend_string_init_interned("LB_UNKNOWN", sizeof("LB_UNKNOWN") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_UNKNOWN_name, &const_LB_UNKNOWN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_UNKNOWN_name); + zend_string_release_ex(const_LB_UNKNOWN_name, true); zval const_LB_AMBIGUOUS_value; ZVAL_LONG(&const_LB_AMBIGUOUS_value, U_LB_AMBIGUOUS); - zend_string *const_LB_AMBIGUOUS_name = zend_string_init_interned("LB_AMBIGUOUS", sizeof("LB_AMBIGUOUS") - 1, 1); + zend_string *const_LB_AMBIGUOUS_name = zend_string_init_interned("LB_AMBIGUOUS", sizeof("LB_AMBIGUOUS") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_AMBIGUOUS_name, &const_LB_AMBIGUOUS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_AMBIGUOUS_name); + zend_string_release_ex(const_LB_AMBIGUOUS_name, true); zval const_LB_ALPHABETIC_value; ZVAL_LONG(&const_LB_ALPHABETIC_value, U_LB_ALPHABETIC); - zend_string *const_LB_ALPHABETIC_name = zend_string_init_interned("LB_ALPHABETIC", sizeof("LB_ALPHABETIC") - 1, 1); + zend_string *const_LB_ALPHABETIC_name = zend_string_init_interned("LB_ALPHABETIC", sizeof("LB_ALPHABETIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_ALPHABETIC_name, &const_LB_ALPHABETIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_ALPHABETIC_name); + zend_string_release_ex(const_LB_ALPHABETIC_name, true); zval const_LB_BREAK_BOTH_value; ZVAL_LONG(&const_LB_BREAK_BOTH_value, U_LB_BREAK_BOTH); - zend_string *const_LB_BREAK_BOTH_name = zend_string_init_interned("LB_BREAK_BOTH", sizeof("LB_BREAK_BOTH") - 1, 1); + zend_string *const_LB_BREAK_BOTH_name = zend_string_init_interned("LB_BREAK_BOTH", sizeof("LB_BREAK_BOTH") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_BREAK_BOTH_name, &const_LB_BREAK_BOTH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_BREAK_BOTH_name); + zend_string_release_ex(const_LB_BREAK_BOTH_name, true); zval const_LB_BREAK_AFTER_value; ZVAL_LONG(&const_LB_BREAK_AFTER_value, U_LB_BREAK_AFTER); - zend_string *const_LB_BREAK_AFTER_name = zend_string_init_interned("LB_BREAK_AFTER", sizeof("LB_BREAK_AFTER") - 1, 1); + zend_string *const_LB_BREAK_AFTER_name = zend_string_init_interned("LB_BREAK_AFTER", sizeof("LB_BREAK_AFTER") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_BREAK_AFTER_name, &const_LB_BREAK_AFTER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_BREAK_AFTER_name); + zend_string_release_ex(const_LB_BREAK_AFTER_name, true); zval const_LB_BREAK_BEFORE_value; ZVAL_LONG(&const_LB_BREAK_BEFORE_value, U_LB_BREAK_BEFORE); - zend_string *const_LB_BREAK_BEFORE_name = zend_string_init_interned("LB_BREAK_BEFORE", sizeof("LB_BREAK_BEFORE") - 1, 1); + zend_string *const_LB_BREAK_BEFORE_name = zend_string_init_interned("LB_BREAK_BEFORE", sizeof("LB_BREAK_BEFORE") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_BREAK_BEFORE_name, &const_LB_BREAK_BEFORE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_BREAK_BEFORE_name); + zend_string_release_ex(const_LB_BREAK_BEFORE_name, true); zval const_LB_MANDATORY_BREAK_value; ZVAL_LONG(&const_LB_MANDATORY_BREAK_value, U_LB_MANDATORY_BREAK); - zend_string *const_LB_MANDATORY_BREAK_name = zend_string_init_interned("LB_MANDATORY_BREAK", sizeof("LB_MANDATORY_BREAK") - 1, 1); + zend_string *const_LB_MANDATORY_BREAK_name = zend_string_init_interned("LB_MANDATORY_BREAK", sizeof("LB_MANDATORY_BREAK") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_MANDATORY_BREAK_name, &const_LB_MANDATORY_BREAK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_MANDATORY_BREAK_name); + zend_string_release_ex(const_LB_MANDATORY_BREAK_name, true); zval const_LB_CONTINGENT_BREAK_value; ZVAL_LONG(&const_LB_CONTINGENT_BREAK_value, U_LB_CONTINGENT_BREAK); - zend_string *const_LB_CONTINGENT_BREAK_name = zend_string_init_interned("LB_CONTINGENT_BREAK", sizeof("LB_CONTINGENT_BREAK") - 1, 1); + zend_string *const_LB_CONTINGENT_BREAK_name = zend_string_init_interned("LB_CONTINGENT_BREAK", sizeof("LB_CONTINGENT_BREAK") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_CONTINGENT_BREAK_name, &const_LB_CONTINGENT_BREAK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_CONTINGENT_BREAK_name); + zend_string_release_ex(const_LB_CONTINGENT_BREAK_name, true); zval const_LB_CLOSE_PUNCTUATION_value; ZVAL_LONG(&const_LB_CLOSE_PUNCTUATION_value, U_LB_CLOSE_PUNCTUATION); - zend_string *const_LB_CLOSE_PUNCTUATION_name = zend_string_init_interned("LB_CLOSE_PUNCTUATION", sizeof("LB_CLOSE_PUNCTUATION") - 1, 1); + zend_string *const_LB_CLOSE_PUNCTUATION_name = zend_string_init_interned("LB_CLOSE_PUNCTUATION", sizeof("LB_CLOSE_PUNCTUATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_CLOSE_PUNCTUATION_name, &const_LB_CLOSE_PUNCTUATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_CLOSE_PUNCTUATION_name); + zend_string_release_ex(const_LB_CLOSE_PUNCTUATION_name, true); zval const_LB_COMBINING_MARK_value; ZVAL_LONG(&const_LB_COMBINING_MARK_value, U_LB_COMBINING_MARK); - zend_string *const_LB_COMBINING_MARK_name = zend_string_init_interned("LB_COMBINING_MARK", sizeof("LB_COMBINING_MARK") - 1, 1); + zend_string *const_LB_COMBINING_MARK_name = zend_string_init_interned("LB_COMBINING_MARK", sizeof("LB_COMBINING_MARK") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_COMBINING_MARK_name, &const_LB_COMBINING_MARK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_COMBINING_MARK_name); + zend_string_release_ex(const_LB_COMBINING_MARK_name, true); zval const_LB_CARRIAGE_RETURN_value; ZVAL_LONG(&const_LB_CARRIAGE_RETURN_value, U_LB_CARRIAGE_RETURN); - zend_string *const_LB_CARRIAGE_RETURN_name = zend_string_init_interned("LB_CARRIAGE_RETURN", sizeof("LB_CARRIAGE_RETURN") - 1, 1); + zend_string *const_LB_CARRIAGE_RETURN_name = zend_string_init_interned("LB_CARRIAGE_RETURN", sizeof("LB_CARRIAGE_RETURN") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_CARRIAGE_RETURN_name, &const_LB_CARRIAGE_RETURN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_CARRIAGE_RETURN_name); + zend_string_release_ex(const_LB_CARRIAGE_RETURN_name, true); zval const_LB_EXCLAMATION_value; ZVAL_LONG(&const_LB_EXCLAMATION_value, U_LB_EXCLAMATION); - zend_string *const_LB_EXCLAMATION_name = zend_string_init_interned("LB_EXCLAMATION", sizeof("LB_EXCLAMATION") - 1, 1); + zend_string *const_LB_EXCLAMATION_name = zend_string_init_interned("LB_EXCLAMATION", sizeof("LB_EXCLAMATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_EXCLAMATION_name, &const_LB_EXCLAMATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_EXCLAMATION_name); + zend_string_release_ex(const_LB_EXCLAMATION_name, true); zval const_LB_GLUE_value; ZVAL_LONG(&const_LB_GLUE_value, U_LB_GLUE); - zend_string *const_LB_GLUE_name = zend_string_init_interned("LB_GLUE", sizeof("LB_GLUE") - 1, 1); + zend_string *const_LB_GLUE_name = zend_string_init_interned("LB_GLUE", sizeof("LB_GLUE") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_GLUE_name, &const_LB_GLUE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_GLUE_name); + zend_string_release_ex(const_LB_GLUE_name, true); zval const_LB_HYPHEN_value; ZVAL_LONG(&const_LB_HYPHEN_value, U_LB_HYPHEN); - zend_string *const_LB_HYPHEN_name = zend_string_init_interned("LB_HYPHEN", sizeof("LB_HYPHEN") - 1, 1); + zend_string *const_LB_HYPHEN_name = zend_string_init_interned("LB_HYPHEN", sizeof("LB_HYPHEN") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_HYPHEN_name, &const_LB_HYPHEN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_HYPHEN_name); + zend_string_release_ex(const_LB_HYPHEN_name, true); zval const_LB_IDEOGRAPHIC_value; ZVAL_LONG(&const_LB_IDEOGRAPHIC_value, U_LB_IDEOGRAPHIC); - zend_string *const_LB_IDEOGRAPHIC_name = zend_string_init_interned("LB_IDEOGRAPHIC", sizeof("LB_IDEOGRAPHIC") - 1, 1); + zend_string *const_LB_IDEOGRAPHIC_name = zend_string_init_interned("LB_IDEOGRAPHIC", sizeof("LB_IDEOGRAPHIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_IDEOGRAPHIC_name, &const_LB_IDEOGRAPHIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_IDEOGRAPHIC_name); + zend_string_release_ex(const_LB_IDEOGRAPHIC_name, true); zval const_LB_INSEPARABLE_value; ZVAL_LONG(&const_LB_INSEPARABLE_value, U_LB_INSEPARABLE); - zend_string *const_LB_INSEPARABLE_name = zend_string_init_interned("LB_INSEPARABLE", sizeof("LB_INSEPARABLE") - 1, 1); + zend_string *const_LB_INSEPARABLE_name = zend_string_init_interned("LB_INSEPARABLE", sizeof("LB_INSEPARABLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_INSEPARABLE_name, &const_LB_INSEPARABLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_INSEPARABLE_name); + zend_string_release_ex(const_LB_INSEPARABLE_name, true); zval const_LB_INSEPERABLE_value; ZVAL_LONG(&const_LB_INSEPERABLE_value, U_LB_INSEPERABLE); - zend_string *const_LB_INSEPERABLE_name = zend_string_init_interned("LB_INSEPERABLE", sizeof("LB_INSEPERABLE") - 1, 1); + zend_string *const_LB_INSEPERABLE_name = zend_string_init_interned("LB_INSEPERABLE", sizeof("LB_INSEPERABLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_INSEPERABLE_name, &const_LB_INSEPERABLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_INSEPERABLE_name); + zend_string_release_ex(const_LB_INSEPERABLE_name, true); zval const_LB_INFIX_NUMERIC_value; ZVAL_LONG(&const_LB_INFIX_NUMERIC_value, U_LB_INFIX_NUMERIC); - zend_string *const_LB_INFIX_NUMERIC_name = zend_string_init_interned("LB_INFIX_NUMERIC", sizeof("LB_INFIX_NUMERIC") - 1, 1); + zend_string *const_LB_INFIX_NUMERIC_name = zend_string_init_interned("LB_INFIX_NUMERIC", sizeof("LB_INFIX_NUMERIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_INFIX_NUMERIC_name, &const_LB_INFIX_NUMERIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_INFIX_NUMERIC_name); + zend_string_release_ex(const_LB_INFIX_NUMERIC_name, true); zval const_LB_LINE_FEED_value; ZVAL_LONG(&const_LB_LINE_FEED_value, U_LB_LINE_FEED); - zend_string *const_LB_LINE_FEED_name = zend_string_init_interned("LB_LINE_FEED", sizeof("LB_LINE_FEED") - 1, 1); + zend_string *const_LB_LINE_FEED_name = zend_string_init_interned("LB_LINE_FEED", sizeof("LB_LINE_FEED") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_LINE_FEED_name, &const_LB_LINE_FEED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_LINE_FEED_name); + zend_string_release_ex(const_LB_LINE_FEED_name, true); zval const_LB_NONSTARTER_value; ZVAL_LONG(&const_LB_NONSTARTER_value, U_LB_NONSTARTER); - zend_string *const_LB_NONSTARTER_name = zend_string_init_interned("LB_NONSTARTER", sizeof("LB_NONSTARTER") - 1, 1); + zend_string *const_LB_NONSTARTER_name = zend_string_init_interned("LB_NONSTARTER", sizeof("LB_NONSTARTER") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_NONSTARTER_name, &const_LB_NONSTARTER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_NONSTARTER_name); + zend_string_release_ex(const_LB_NONSTARTER_name, true); zval const_LB_NUMERIC_value; ZVAL_LONG(&const_LB_NUMERIC_value, U_LB_NUMERIC); - zend_string *const_LB_NUMERIC_name = zend_string_init_interned("LB_NUMERIC", sizeof("LB_NUMERIC") - 1, 1); + zend_string *const_LB_NUMERIC_name = zend_string_init_interned("LB_NUMERIC", sizeof("LB_NUMERIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_NUMERIC_name, &const_LB_NUMERIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_NUMERIC_name); + zend_string_release_ex(const_LB_NUMERIC_name, true); zval const_LB_OPEN_PUNCTUATION_value; ZVAL_LONG(&const_LB_OPEN_PUNCTUATION_value, U_LB_OPEN_PUNCTUATION); - zend_string *const_LB_OPEN_PUNCTUATION_name = zend_string_init_interned("LB_OPEN_PUNCTUATION", sizeof("LB_OPEN_PUNCTUATION") - 1, 1); + zend_string *const_LB_OPEN_PUNCTUATION_name = zend_string_init_interned("LB_OPEN_PUNCTUATION", sizeof("LB_OPEN_PUNCTUATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_OPEN_PUNCTUATION_name, &const_LB_OPEN_PUNCTUATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_OPEN_PUNCTUATION_name); + zend_string_release_ex(const_LB_OPEN_PUNCTUATION_name, true); zval const_LB_POSTFIX_NUMERIC_value; ZVAL_LONG(&const_LB_POSTFIX_NUMERIC_value, U_LB_POSTFIX_NUMERIC); - zend_string *const_LB_POSTFIX_NUMERIC_name = zend_string_init_interned("LB_POSTFIX_NUMERIC", sizeof("LB_POSTFIX_NUMERIC") - 1, 1); + zend_string *const_LB_POSTFIX_NUMERIC_name = zend_string_init_interned("LB_POSTFIX_NUMERIC", sizeof("LB_POSTFIX_NUMERIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_POSTFIX_NUMERIC_name, &const_LB_POSTFIX_NUMERIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_POSTFIX_NUMERIC_name); + zend_string_release_ex(const_LB_POSTFIX_NUMERIC_name, true); zval const_LB_PREFIX_NUMERIC_value; ZVAL_LONG(&const_LB_PREFIX_NUMERIC_value, U_LB_PREFIX_NUMERIC); - zend_string *const_LB_PREFIX_NUMERIC_name = zend_string_init_interned("LB_PREFIX_NUMERIC", sizeof("LB_PREFIX_NUMERIC") - 1, 1); + zend_string *const_LB_PREFIX_NUMERIC_name = zend_string_init_interned("LB_PREFIX_NUMERIC", sizeof("LB_PREFIX_NUMERIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_PREFIX_NUMERIC_name, &const_LB_PREFIX_NUMERIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_PREFIX_NUMERIC_name); + zend_string_release_ex(const_LB_PREFIX_NUMERIC_name, true); zval const_LB_QUOTATION_value; ZVAL_LONG(&const_LB_QUOTATION_value, U_LB_QUOTATION); - zend_string *const_LB_QUOTATION_name = zend_string_init_interned("LB_QUOTATION", sizeof("LB_QUOTATION") - 1, 1); + zend_string *const_LB_QUOTATION_name = zend_string_init_interned("LB_QUOTATION", sizeof("LB_QUOTATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_QUOTATION_name, &const_LB_QUOTATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_QUOTATION_name); + zend_string_release_ex(const_LB_QUOTATION_name, true); zval const_LB_COMPLEX_CONTEXT_value; ZVAL_LONG(&const_LB_COMPLEX_CONTEXT_value, U_LB_COMPLEX_CONTEXT); - zend_string *const_LB_COMPLEX_CONTEXT_name = zend_string_init_interned("LB_COMPLEX_CONTEXT", sizeof("LB_COMPLEX_CONTEXT") - 1, 1); + zend_string *const_LB_COMPLEX_CONTEXT_name = zend_string_init_interned("LB_COMPLEX_CONTEXT", sizeof("LB_COMPLEX_CONTEXT") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_COMPLEX_CONTEXT_name, &const_LB_COMPLEX_CONTEXT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_COMPLEX_CONTEXT_name); + zend_string_release_ex(const_LB_COMPLEX_CONTEXT_name, true); zval const_LB_SURROGATE_value; ZVAL_LONG(&const_LB_SURROGATE_value, U_LB_SURROGATE); - zend_string *const_LB_SURROGATE_name = zend_string_init_interned("LB_SURROGATE", sizeof("LB_SURROGATE") - 1, 1); + zend_string *const_LB_SURROGATE_name = zend_string_init_interned("LB_SURROGATE", sizeof("LB_SURROGATE") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_SURROGATE_name, &const_LB_SURROGATE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_SURROGATE_name); + zend_string_release_ex(const_LB_SURROGATE_name, true); zval const_LB_SPACE_value; ZVAL_LONG(&const_LB_SPACE_value, U_LB_SPACE); - zend_string *const_LB_SPACE_name = zend_string_init_interned("LB_SPACE", sizeof("LB_SPACE") - 1, 1); + zend_string *const_LB_SPACE_name = zend_string_init_interned("LB_SPACE", sizeof("LB_SPACE") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_SPACE_name, &const_LB_SPACE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_SPACE_name); + zend_string_release_ex(const_LB_SPACE_name, true); zval const_LB_BREAK_SYMBOLS_value; ZVAL_LONG(&const_LB_BREAK_SYMBOLS_value, U_LB_BREAK_SYMBOLS); - zend_string *const_LB_BREAK_SYMBOLS_name = zend_string_init_interned("LB_BREAK_SYMBOLS", sizeof("LB_BREAK_SYMBOLS") - 1, 1); + zend_string *const_LB_BREAK_SYMBOLS_name = zend_string_init_interned("LB_BREAK_SYMBOLS", sizeof("LB_BREAK_SYMBOLS") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_BREAK_SYMBOLS_name, &const_LB_BREAK_SYMBOLS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_BREAK_SYMBOLS_name); + zend_string_release_ex(const_LB_BREAK_SYMBOLS_name, true); zval const_LB_ZWSPACE_value; ZVAL_LONG(&const_LB_ZWSPACE_value, U_LB_ZWSPACE); - zend_string *const_LB_ZWSPACE_name = zend_string_init_interned("LB_ZWSPACE", sizeof("LB_ZWSPACE") - 1, 1); + zend_string *const_LB_ZWSPACE_name = zend_string_init_interned("LB_ZWSPACE", sizeof("LB_ZWSPACE") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_ZWSPACE_name, &const_LB_ZWSPACE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_ZWSPACE_name); + zend_string_release_ex(const_LB_ZWSPACE_name, true); zval const_LB_NEXT_LINE_value; ZVAL_LONG(&const_LB_NEXT_LINE_value, U_LB_NEXT_LINE); - zend_string *const_LB_NEXT_LINE_name = zend_string_init_interned("LB_NEXT_LINE", sizeof("LB_NEXT_LINE") - 1, 1); + zend_string *const_LB_NEXT_LINE_name = zend_string_init_interned("LB_NEXT_LINE", sizeof("LB_NEXT_LINE") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_NEXT_LINE_name, &const_LB_NEXT_LINE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_NEXT_LINE_name); + zend_string_release_ex(const_LB_NEXT_LINE_name, true); zval const_LB_WORD_JOINER_value; ZVAL_LONG(&const_LB_WORD_JOINER_value, U_LB_WORD_JOINER); - zend_string *const_LB_WORD_JOINER_name = zend_string_init_interned("LB_WORD_JOINER", sizeof("LB_WORD_JOINER") - 1, 1); + zend_string *const_LB_WORD_JOINER_name = zend_string_init_interned("LB_WORD_JOINER", sizeof("LB_WORD_JOINER") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_WORD_JOINER_name, &const_LB_WORD_JOINER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_WORD_JOINER_name); + zend_string_release_ex(const_LB_WORD_JOINER_name, true); zval const_LB_H2_value; ZVAL_LONG(&const_LB_H2_value, U_LB_H2); - zend_string *const_LB_H2_name = zend_string_init_interned("LB_H2", sizeof("LB_H2") - 1, 1); + zend_string *const_LB_H2_name = zend_string_init_interned("LB_H2", sizeof("LB_H2") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_H2_name, &const_LB_H2_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_H2_name); + zend_string_release_ex(const_LB_H2_name, true); zval const_LB_H3_value; ZVAL_LONG(&const_LB_H3_value, U_LB_H3); - zend_string *const_LB_H3_name = zend_string_init_interned("LB_H3", sizeof("LB_H3") - 1, 1); + zend_string *const_LB_H3_name = zend_string_init_interned("LB_H3", sizeof("LB_H3") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_H3_name, &const_LB_H3_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_H3_name); + zend_string_release_ex(const_LB_H3_name, true); zval const_LB_JL_value; ZVAL_LONG(&const_LB_JL_value, U_LB_JL); - zend_string *const_LB_JL_name = zend_string_init_interned("LB_JL", sizeof("LB_JL") - 1, 1); + zend_string *const_LB_JL_name = zend_string_init_interned("LB_JL", sizeof("LB_JL") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_JL_name, &const_LB_JL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_JL_name); + zend_string_release_ex(const_LB_JL_name, true); zval const_LB_JT_value; ZVAL_LONG(&const_LB_JT_value, U_LB_JT); - zend_string *const_LB_JT_name = zend_string_init_interned("LB_JT", sizeof("LB_JT") - 1, 1); + zend_string *const_LB_JT_name = zend_string_init_interned("LB_JT", sizeof("LB_JT") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_JT_name, &const_LB_JT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_JT_name); + zend_string_release_ex(const_LB_JT_name, true); zval const_LB_JV_value; ZVAL_LONG(&const_LB_JV_value, U_LB_JV); - zend_string *const_LB_JV_name = zend_string_init_interned("LB_JV", sizeof("LB_JV") - 1, 1); + zend_string *const_LB_JV_name = zend_string_init_interned("LB_JV", sizeof("LB_JV") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_JV_name, &const_LB_JV_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_JV_name); + zend_string_release_ex(const_LB_JV_name, true); zval const_LB_CLOSE_PARENTHESIS_value; ZVAL_LONG(&const_LB_CLOSE_PARENTHESIS_value, U_LB_CLOSE_PARENTHESIS); - zend_string *const_LB_CLOSE_PARENTHESIS_name = zend_string_init_interned("LB_CLOSE_PARENTHESIS", sizeof("LB_CLOSE_PARENTHESIS") - 1, 1); + zend_string *const_LB_CLOSE_PARENTHESIS_name = zend_string_init_interned("LB_CLOSE_PARENTHESIS", sizeof("LB_CLOSE_PARENTHESIS") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_CLOSE_PARENTHESIS_name, &const_LB_CLOSE_PARENTHESIS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_CLOSE_PARENTHESIS_name); + zend_string_release_ex(const_LB_CLOSE_PARENTHESIS_name, true); zval const_LB_CONDITIONAL_JAPANESE_STARTER_value; ZVAL_LONG(&const_LB_CONDITIONAL_JAPANESE_STARTER_value, U_LB_CONDITIONAL_JAPANESE_STARTER); - zend_string *const_LB_CONDITIONAL_JAPANESE_STARTER_name = zend_string_init_interned("LB_CONDITIONAL_JAPANESE_STARTER", sizeof("LB_CONDITIONAL_JAPANESE_STARTER") - 1, 1); + zend_string *const_LB_CONDITIONAL_JAPANESE_STARTER_name = zend_string_init_interned("LB_CONDITIONAL_JAPANESE_STARTER", sizeof("LB_CONDITIONAL_JAPANESE_STARTER") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_CONDITIONAL_JAPANESE_STARTER_name, &const_LB_CONDITIONAL_JAPANESE_STARTER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_CONDITIONAL_JAPANESE_STARTER_name); + zend_string_release_ex(const_LB_CONDITIONAL_JAPANESE_STARTER_name, true); zval const_LB_HEBREW_LETTER_value; ZVAL_LONG(&const_LB_HEBREW_LETTER_value, U_LB_HEBREW_LETTER); - zend_string *const_LB_HEBREW_LETTER_name = zend_string_init_interned("LB_HEBREW_LETTER", sizeof("LB_HEBREW_LETTER") - 1, 1); + zend_string *const_LB_HEBREW_LETTER_name = zend_string_init_interned("LB_HEBREW_LETTER", sizeof("LB_HEBREW_LETTER") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_HEBREW_LETTER_name, &const_LB_HEBREW_LETTER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_HEBREW_LETTER_name); + zend_string_release_ex(const_LB_HEBREW_LETTER_name, true); zval const_LB_REGIONAL_INDICATOR_value; ZVAL_LONG(&const_LB_REGIONAL_INDICATOR_value, U_LB_REGIONAL_INDICATOR); - zend_string *const_LB_REGIONAL_INDICATOR_name = zend_string_init_interned("LB_REGIONAL_INDICATOR", sizeof("LB_REGIONAL_INDICATOR") - 1, 1); + zend_string *const_LB_REGIONAL_INDICATOR_name = zend_string_init_interned("LB_REGIONAL_INDICATOR", sizeof("LB_REGIONAL_INDICATOR") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_REGIONAL_INDICATOR_name, &const_LB_REGIONAL_INDICATOR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_REGIONAL_INDICATOR_name); + zend_string_release_ex(const_LB_REGIONAL_INDICATOR_name, true); zval const_LB_COUNT_value; ZVAL_LONG(&const_LB_COUNT_value, U_LB_COUNT); - zend_string *const_LB_COUNT_name = zend_string_init_interned("LB_COUNT", sizeof("LB_COUNT") - 1, 1); + zend_string *const_LB_COUNT_name = zend_string_init_interned("LB_COUNT", sizeof("LB_COUNT") - 1, true); zend_declare_typed_class_constant(class_entry, const_LB_COUNT_name, &const_LB_COUNT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LB_COUNT_name); + zend_string_release_ex(const_LB_COUNT_name, true); zval const_NT_NONE_value; ZVAL_LONG(&const_NT_NONE_value, U_NT_NONE); - zend_string *const_NT_NONE_name = zend_string_init_interned("NT_NONE", sizeof("NT_NONE") - 1, 1); + zend_string *const_NT_NONE_name = zend_string_init_interned("NT_NONE", sizeof("NT_NONE") - 1, true); zend_declare_typed_class_constant(class_entry, const_NT_NONE_name, &const_NT_NONE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NT_NONE_name); + zend_string_release_ex(const_NT_NONE_name, true); zval const_NT_DECIMAL_value; ZVAL_LONG(&const_NT_DECIMAL_value, U_NT_DECIMAL); - zend_string *const_NT_DECIMAL_name = zend_string_init_interned("NT_DECIMAL", sizeof("NT_DECIMAL") - 1, 1); + zend_string *const_NT_DECIMAL_name = zend_string_init_interned("NT_DECIMAL", sizeof("NT_DECIMAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_NT_DECIMAL_name, &const_NT_DECIMAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NT_DECIMAL_name); + zend_string_release_ex(const_NT_DECIMAL_name, true); zval const_NT_DIGIT_value; ZVAL_LONG(&const_NT_DIGIT_value, U_NT_DIGIT); - zend_string *const_NT_DIGIT_name = zend_string_init_interned("NT_DIGIT", sizeof("NT_DIGIT") - 1, 1); + zend_string *const_NT_DIGIT_name = zend_string_init_interned("NT_DIGIT", sizeof("NT_DIGIT") - 1, true); zend_declare_typed_class_constant(class_entry, const_NT_DIGIT_name, &const_NT_DIGIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NT_DIGIT_name); + zend_string_release_ex(const_NT_DIGIT_name, true); zval const_NT_NUMERIC_value; ZVAL_LONG(&const_NT_NUMERIC_value, U_NT_NUMERIC); - zend_string *const_NT_NUMERIC_name = zend_string_init_interned("NT_NUMERIC", sizeof("NT_NUMERIC") - 1, 1); + zend_string *const_NT_NUMERIC_name = zend_string_init_interned("NT_NUMERIC", sizeof("NT_NUMERIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_NT_NUMERIC_name, &const_NT_NUMERIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NT_NUMERIC_name); + zend_string_release_ex(const_NT_NUMERIC_name, true); zval const_NT_COUNT_value; ZVAL_LONG(&const_NT_COUNT_value, U_NT_COUNT); - zend_string *const_NT_COUNT_name = zend_string_init_interned("NT_COUNT", sizeof("NT_COUNT") - 1, 1); + zend_string *const_NT_COUNT_name = zend_string_init_interned("NT_COUNT", sizeof("NT_COUNT") - 1, true); zend_declare_typed_class_constant(class_entry, const_NT_COUNT_name, &const_NT_COUNT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NT_COUNT_name); + zend_string_release_ex(const_NT_COUNT_name, true); zval const_HST_NOT_APPLICABLE_value; ZVAL_LONG(&const_HST_NOT_APPLICABLE_value, U_HST_NOT_APPLICABLE); - zend_string *const_HST_NOT_APPLICABLE_name = zend_string_init_interned("HST_NOT_APPLICABLE", sizeof("HST_NOT_APPLICABLE") - 1, 1); + zend_string *const_HST_NOT_APPLICABLE_name = zend_string_init_interned("HST_NOT_APPLICABLE", sizeof("HST_NOT_APPLICABLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_HST_NOT_APPLICABLE_name, &const_HST_NOT_APPLICABLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_HST_NOT_APPLICABLE_name); + zend_string_release_ex(const_HST_NOT_APPLICABLE_name, true); zval const_HST_LEADING_JAMO_value; ZVAL_LONG(&const_HST_LEADING_JAMO_value, U_HST_LEADING_JAMO); - zend_string *const_HST_LEADING_JAMO_name = zend_string_init_interned("HST_LEADING_JAMO", sizeof("HST_LEADING_JAMO") - 1, 1); + zend_string *const_HST_LEADING_JAMO_name = zend_string_init_interned("HST_LEADING_JAMO", sizeof("HST_LEADING_JAMO") - 1, true); zend_declare_typed_class_constant(class_entry, const_HST_LEADING_JAMO_name, &const_HST_LEADING_JAMO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_HST_LEADING_JAMO_name); + zend_string_release_ex(const_HST_LEADING_JAMO_name, true); zval const_HST_VOWEL_JAMO_value; ZVAL_LONG(&const_HST_VOWEL_JAMO_value, U_HST_VOWEL_JAMO); - zend_string *const_HST_VOWEL_JAMO_name = zend_string_init_interned("HST_VOWEL_JAMO", sizeof("HST_VOWEL_JAMO") - 1, 1); + zend_string *const_HST_VOWEL_JAMO_name = zend_string_init_interned("HST_VOWEL_JAMO", sizeof("HST_VOWEL_JAMO") - 1, true); zend_declare_typed_class_constant(class_entry, const_HST_VOWEL_JAMO_name, &const_HST_VOWEL_JAMO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_HST_VOWEL_JAMO_name); + zend_string_release_ex(const_HST_VOWEL_JAMO_name, true); zval const_HST_TRAILING_JAMO_value; ZVAL_LONG(&const_HST_TRAILING_JAMO_value, U_HST_TRAILING_JAMO); - zend_string *const_HST_TRAILING_JAMO_name = zend_string_init_interned("HST_TRAILING_JAMO", sizeof("HST_TRAILING_JAMO") - 1, 1); + zend_string *const_HST_TRAILING_JAMO_name = zend_string_init_interned("HST_TRAILING_JAMO", sizeof("HST_TRAILING_JAMO") - 1, true); zend_declare_typed_class_constant(class_entry, const_HST_TRAILING_JAMO_name, &const_HST_TRAILING_JAMO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_HST_TRAILING_JAMO_name); + zend_string_release_ex(const_HST_TRAILING_JAMO_name, true); zval const_HST_LV_SYLLABLE_value; ZVAL_LONG(&const_HST_LV_SYLLABLE_value, U_HST_LV_SYLLABLE); - zend_string *const_HST_LV_SYLLABLE_name = zend_string_init_interned("HST_LV_SYLLABLE", sizeof("HST_LV_SYLLABLE") - 1, 1); + zend_string *const_HST_LV_SYLLABLE_name = zend_string_init_interned("HST_LV_SYLLABLE", sizeof("HST_LV_SYLLABLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_HST_LV_SYLLABLE_name, &const_HST_LV_SYLLABLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_HST_LV_SYLLABLE_name); + zend_string_release_ex(const_HST_LV_SYLLABLE_name, true); zval const_HST_LVT_SYLLABLE_value; ZVAL_LONG(&const_HST_LVT_SYLLABLE_value, U_HST_LVT_SYLLABLE); - zend_string *const_HST_LVT_SYLLABLE_name = zend_string_init_interned("HST_LVT_SYLLABLE", sizeof("HST_LVT_SYLLABLE") - 1, 1); + zend_string *const_HST_LVT_SYLLABLE_name = zend_string_init_interned("HST_LVT_SYLLABLE", sizeof("HST_LVT_SYLLABLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_HST_LVT_SYLLABLE_name, &const_HST_LVT_SYLLABLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_HST_LVT_SYLLABLE_name); + zend_string_release_ex(const_HST_LVT_SYLLABLE_name, true); zval const_HST_COUNT_value; ZVAL_LONG(&const_HST_COUNT_value, U_HST_COUNT); - zend_string *const_HST_COUNT_name = zend_string_init_interned("HST_COUNT", sizeof("HST_COUNT") - 1, 1); + zend_string *const_HST_COUNT_name = zend_string_init_interned("HST_COUNT", sizeof("HST_COUNT") - 1, true); zend_declare_typed_class_constant(class_entry, const_HST_COUNT_name, &const_HST_COUNT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_HST_COUNT_name); + zend_string_release_ex(const_HST_COUNT_name, true); zval const_FOLD_CASE_DEFAULT_value; ZVAL_LONG(&const_FOLD_CASE_DEFAULT_value, U_FOLD_CASE_DEFAULT); - zend_string *const_FOLD_CASE_DEFAULT_name = zend_string_init_interned("FOLD_CASE_DEFAULT", sizeof("FOLD_CASE_DEFAULT") - 1, 1); + zend_string *const_FOLD_CASE_DEFAULT_name = zend_string_init_interned("FOLD_CASE_DEFAULT", sizeof("FOLD_CASE_DEFAULT") - 1, true); zend_declare_typed_class_constant(class_entry, const_FOLD_CASE_DEFAULT_name, &const_FOLD_CASE_DEFAULT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FOLD_CASE_DEFAULT_name); + zend_string_release_ex(const_FOLD_CASE_DEFAULT_name, true); zval const_FOLD_CASE_EXCLUDE_SPECIAL_I_value; ZVAL_LONG(&const_FOLD_CASE_EXCLUDE_SPECIAL_I_value, U_FOLD_CASE_EXCLUDE_SPECIAL_I); - zend_string *const_FOLD_CASE_EXCLUDE_SPECIAL_I_name = zend_string_init_interned("FOLD_CASE_EXCLUDE_SPECIAL_I", sizeof("FOLD_CASE_EXCLUDE_SPECIAL_I") - 1, 1); + zend_string *const_FOLD_CASE_EXCLUDE_SPECIAL_I_name = zend_string_init_interned("FOLD_CASE_EXCLUDE_SPECIAL_I", sizeof("FOLD_CASE_EXCLUDE_SPECIAL_I") - 1, true); zend_declare_typed_class_constant(class_entry, const_FOLD_CASE_EXCLUDE_SPECIAL_I_name, &const_FOLD_CASE_EXCLUDE_SPECIAL_I_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FOLD_CASE_EXCLUDE_SPECIAL_I_name); + zend_string_release_ex(const_FOLD_CASE_EXCLUDE_SPECIAL_I_name, true); return class_entry; } diff --git a/ext/json/json_encoder.c b/ext/json/json_encoder.c index c147b8eb23d73..186485c05c6f4 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,7 @@ 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; HashTable *myht, *prop_ht; zend_refcounted *recursion_rc; @@ -138,7 +124,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 +132,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 +147,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,17 +155,11 @@ 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; } - if (need_comma) { - smart_str_appendc(buf, ','); - } else { - need_comma = 1; - } - php_json_pretty_print_char(buf, options, '\n'); php_json_pretty_print_indent(buf, options, encoder); @@ -201,6 +179,14 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, PHP_JSON_HASH_UNPROTECT_RECURSION(obj); return FAILURE; } + + smart_str_appendc(buf, ','); + } + + bool empty = ZSTR_VAL(buf->s)[ZSTR_LEN(buf->s) - 1] != ','; + if (!empty) { + /* Drop the trailing comma. */ + ZSTR_LEN(buf->s)--; } PHP_JSON_HASH_UNPROTECT_RECURSION(obj); @@ -212,7 +198,7 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, } --encoder->depth; - if (need_comma) { + if (!empty) { php_json_pretty_print_char(buf, options, '\n'); php_json_pretty_print_indent(buf, options, encoder); } @@ -228,7 +214,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 +226,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, '{'); @@ -250,27 +236,23 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, uint32_t i = myht ? zend_hash_num_elements(myht) : 0; + bool empty = true; if (i > 0) { zend_string *key; zval *data; zend_ulong index; ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, data) { + bool need_dtor = false; 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) { - smart_str_appendc(buf, ','); - } else { - need_comma = 1; - } - 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. */ @@ -283,6 +265,7 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, if ((prop_info->flags & ZEND_ACC_VIRTUAL) && !prop_info->hooks[ZEND_PROPERTY_HOOK_GET]) { continue; } + need_dtor = true; data = zend_read_property_ex(prop_info->ce, Z_OBJ_P(val), prop_info->name, /* silent */ true, &tmp); if (EG(exception)) { PHP_JSON_HASH_UNPROTECT_RECURSION(recursion_rc); @@ -291,11 +274,6 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, } } - if (need_comma) { - smart_str_appendc(buf, ','); - } else { - need_comma = 1; - } php_json_pretty_print_char(buf, options, '\n'); php_json_pretty_print_indent(buf, options, encoder); @@ -308,12 +286,6 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, smart_str_appendl(buf, "\"\"", 2); } } else { - if (need_comma) { - smart_str_appendc(buf, ','); - } else { - need_comma = 1; - } - php_json_pretty_print_char(buf, options, '\n'); php_json_pretty_print_indent(buf, options, encoder); @@ -333,8 +305,18 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, zval_ptr_dtor(&tmp); return FAILURE; } - zval_ptr_dtor(&tmp); + if (UNEXPECTED(need_dtor)) { + zval_ptr_dtor(&tmp); + } + + smart_str_appendc(buf, ','); } ZEND_HASH_FOREACH_END(); + + empty = ZSTR_VAL(buf->s)[ZSTR_LEN(buf->s) - 1] != ','; + if (!empty) { + /* Drop the trailing comma. */ + ZSTR_LEN(buf->s)--; + } } PHP_JSON_HASH_UNPROTECT_RECURSION(recursion_rc); @@ -349,12 +331,12 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, --encoder->depth; /* Only keep closing bracket on same line for empty arrays/objects */ - if (need_comma) { + if (!empty) { php_json_pretty_print_char(buf, options, '\n'); 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 +351,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 +388,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 +607,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 ae0ae7fba9598..14174bd5dc26e 100644 --- a/ext/ldap/config.m4 +++ b/ext/ldap/config.m4 @@ -91,14 +91,17 @@ if test "$PHP_LDAP" != "no"; then elif test -f $LDAP_LIBDIR/libclntsh.$SHLIB_SUFFIX_NAME.12.1 || test -f $LDAP_LIBDIR/$MACHINE_INCLUDES/libclntsh.$SHLIB_SUFFIX_NAME.12.1; then PHP_ADD_LIBRARY_WITH_PATH([clntsh], [$LDAP_LIBDIR], [LDAP_SHARED_LIBADD]) AC_DEFINE([HAVE_ORALDAP], [1]) + AC_MSG_WARN([Build with Oracle Instant Client is deprecated as of PHP 8.5]) elif test -f $LDAP_LIBDIR/libclntsh.$SHLIB_SUFFIX_NAME.11.1 || test -f $LDAP_LIBDIR/$MACHINE_INCLUDES/libclntsh.$SHLIB_SUFFIX_NAME.11.1; then PHP_ADD_LIBRARY_WITH_PATH([clntsh], [$LDAP_LIBDIR], [LDAP_SHARED_LIBADD]) AC_DEFINE([HAVE_ORALDAP], [1]) + AC_MSG_WARN([Build with Oracle Instant Client is deprecated as of PHP 8.5]) elif test -f $LDAP_LIBDIR/libclntsh.$SHLIB_SUFFIX_NAME || test -f $LDAP_LIBDIR/$MACHINE_INCLUDES/libclntsh.$SHLIB_SUFFIX_NAME; then - PHP_ADD_LIBRARY_WITH_PATH([clntsh], [$LDAP_LIBDIR], [LDAP_SHARED_LIBADD]) - AC_DEFINE([HAVE_ORALDAP], [1]) + PHP_ADD_LIBRARY_WITH_PATH([clntsh], [$LDAP_LIBDIR], [LDAP_SHARED_LIBADD]) + AC_DEFINE([HAVE_ORALDAP], [1]) + AC_MSG_WARN([Build with Oracle Instant Client is deprecated as of PHP 8.5]) else AC_MSG_ERROR([Cannot find ldap libraries in $LDAP_LIBDIR.]) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index f5733c1781f9b..9e566a4ed1dcb 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); @@ -427,7 +425,7 @@ static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array, static int php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, const HashTable *control_ht) { zval* val; - zend_string *control_oid; + zend_string *control_oid, *control_oid_tmp; char** ldap_attrs = NULL; LDAPSortKey** sort_keys = NULL; zend_string *tmpstring = NULL, **tmpstrings1 = NULL, **tmpstrings2 = NULL; @@ -438,8 +436,8 @@ static int php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, const HashT return -1; } - control_oid = zval_get_string(val); - if (EG(exception)) { + control_oid = zval_try_get_tmp_string(val, &control_oid_tmp); + if (!control_oid) { return -1; } @@ -455,8 +453,8 @@ static int php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, const HashT if ((val = zend_hash_find(control_ht, ZSTR_KNOWN(ZEND_STR_VALUE))) != NULL) { if (Z_TYPE_P(val) != IS_ARRAY) { - tmpstring = zval_get_string(val); - if (EG(exception)) { + tmpstring = zval_try_get_string(val); + if (!tmpstring) { rc = -1; goto failure; } @@ -470,8 +468,8 @@ static int php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, const HashT pagesize = zval_get_long(tmp); } if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "cookie", sizeof("cookie") - 1)) != NULL) { - tmpstring = zval_get_string(tmp); - if (EG(exception)) { + tmpstring = zval_try_get_string(tmp); + if (!tmpstring) { rc = -1; goto failure; } @@ -479,20 +477,19 @@ static int php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, const HashT cookie.bv_len = ZSTR_LEN(tmpstring); } /* ldap_create_page_control_value() allocates memory for control_value.bv_val */ - control_value_alloc = 1; + control_value_alloc = true; rc = ldap_create_page_control_value(ld, pagesize, &cookie, &control_value); if (rc != LDAP_SUCCESS) { php_error_docref(NULL, E_WARNING, "Failed to create paged result control value: %s (%d)", ldap_err2string(rc), rc); } } 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); - if (EG(exception)) { + zend_string* assert = zval_try_get_string(tmp); + if (!assert) { rc = -1; goto failure; } @@ -501,7 +498,7 @@ static int php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, const HashT int success = LDAP_SUCCESS; ldap_set_option(ld, LDAP_OPT_RESULT_CODE, &success); /* ldap_create_assertion_control_value() allocates memory for control_value.bv_val */ - control_value_alloc = 1; + control_value_alloc = true; rc = ldap_create_assertion_control_value(ld, ZSTR_VAL(assert), &control_value); if (rc != LDAP_SUCCESS) { php_error_docref(NULL, E_WARNING, "Failed to create assert control value: %s (%d)", ldap_err2string(rc), rc); @@ -519,8 +516,8 @@ 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 { - tmpstring = zval_get_string(tmp); - if (EG(exception)) { + tmpstring = zval_try_get_string(tmp); + if (!tmpstring) { rc = -1; goto failure; } @@ -544,23 +541,22 @@ 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; i 2) { - zend_error(E_DEPRECATED, "Calling ldap_connect() with Oracle-specific arguments is deprecated, " - "use ldap_connect_wallet() instead"); + zend_error(E_DEPRECATED, "Calling ldap_connect() with Oracle-specific arguments is deprecated"); } else if (ZEND_NUM_ARGS() == 2) { zend_error(E_DEPRECATED, "Usage of ldap_connect with two arguments is deprecated"); } #ifdef HAVE_ORALDAP if (ZEND_NUM_ARGS() == 3 || ZEND_NUM_ARGS() == 4) { - WRONG_PARAM_COUNT; + zend_wrong_param_count(); + RETURN_THROWS(); } if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!lssl", &host, &hostlen, &port, &wallet, &walletlen, &walletpasswd, &walletpasswdlen, &authmode) != SUCCESS) { @@ -1226,9 +1221,6 @@ PHP_FUNCTION(ldap_bind_ext) HashTable *server_controls_ht = NULL; ldap_linkdata *ld; LDAPControl **lserverctrls = NULL; - ldap_resultdata *result; - LDAPMessage *ldap_res; - int rc; if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|p!p!h!", &link, ldap_link_ce, &ldap_bind_dn, &ldap_bind_dnlen, &ldap_bind_pw, &ldap_bind_pwlen, &server_controls_ht) != SUCCESS) { RETURN_THROWS(); @@ -1249,6 +1241,7 @@ PHP_FUNCTION(ldap_bind_ext) /* ldap_simple_bind() is deprecated, use ldap_sasl_bind() instead */ struct berval cred; int msgid; + int rc; cred.bv_val = ldap_bind_pw; cred.bv_len = ldap_bind_pw ? ldap_bind_pwlen : 0; @@ -1261,6 +1254,7 @@ PHP_FUNCTION(ldap_bind_ext) goto cleanup; } + 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, "Bind operation failed"); @@ -1270,7 +1264,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 +1485,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 +1501,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 +1540,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 +1562,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 +1575,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 +1597,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 +1626,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 +1643,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 +1659,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 +1715,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 +1742,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 +1759,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 +1785,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 +1860,6 @@ PHP_FUNCTION(ldap_first_entry) { zval *link, *result; ldap_linkdata *ld; - ldap_result_entry *resultentry; ldap_resultdata *ldap_result; LDAPMessage *entry; @@ -1884,7 +1877,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 +1890,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 +1906,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 +1920,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 +1954,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 +2084,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 +2104,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 +2142,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 +2162,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 +2257,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 +2269,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 +2291,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 +2386,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 +2459,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 +2475,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 +2550,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 +2560,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 +2578,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); } /* }}} */ @@ -2806,8 +2795,8 @@ PHP_FUNCTION(ldap_modify_batch) zend_ulong value_index = 0; zval *modification_value_zv = NULL; ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(modification_values), modification_value_zv) { - zend_string *modval = zval_get_string(modification_value_zv); - if (EG(exception)) { + zend_string *modval = zval_try_get_string(modification_value_zv); + if (!modval) { RETVAL_FALSE; ldap_mods[modification_index]->mod_bvalues[value_index] = NULL; num_mods = modification_index + 1; @@ -3148,7 +3137,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 +3331,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 +3342,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 +3365,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 +3393,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 +3401,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 +3514,6 @@ PHP_FUNCTION(ldap_first_reference) { zval *link, *result; ldap_linkdata *ld; - ldap_result_entry *resultentry; ldap_resultdata *ldap_result; LDAPMessage *entry; @@ -3544,7 +3531,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 +3544,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 +3560,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 +3575,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 +3596,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 +3609,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 +3675,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 +3693,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); } /* }}} */ @@ -3817,7 +3803,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; @@ -3938,7 +3924,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) { @@ -3950,9 +3936,8 @@ 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; + bool map[256] = {0}, havecharlist = false; if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|sl", &value, &valuelen, &ignores, &ignoreslen, &flags) != SUCCESS) { RETURN_THROWS(); @@ -3963,23 +3948,23 @@ PHP_FUNCTION(ldap_escape) } if (flags & PHP_LDAP_ESCAPE_FILTER) { - havecharlist = 1; - php_ldap_escape_map_set_chars(map, "\\*()\0", sizeof("\\*()\0") - 1, 1); + havecharlist = true; + 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); + havecharlist = true; + php_ldap_escape_map_set_chars(map, "\\,=+<>;\"#\r", sizeof("\\,=+<>;\"#\r") - 1, true); } if (!havecharlist) { - for (i = 0; i < 256; i++) { - map[i] = 1; + for (uint16_t i = 0; i < 256; i++) { + map[i] = true; } } 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); @@ -4234,7 +4219,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/ldap.stub.php b/ext/ldap/ldap.stub.php index f9f2aab85c40b..84befe3f43f8e 100644 --- a/ext/ldap/ldap.stub.php +++ b/ext/ldap/ldap.stub.php @@ -208,16 +208,19 @@ * @var int * @cvalue GSLC_SSL_NO_AUTH */ + #[\Deprecated(since: "8.5", message: "as it is broken since PHP 8.0")] const GSLC_SSL_NO_AUTH = UNKNOWN; /** * @var int * @cvalue GSLC_SSL_ONEWAY_AUTH */ + #[\Deprecated(since: "8.5", message: "as it is broken since PHP 8.0")] const GSLC_SSL_ONEWAY_AUTH = UNKNOWN; /** * @var int * @cvalue GSLC_SSL_TWOWAY_AUTH */ + #[\Deprecated(since: "8.5", message: "as it is broken since PHP 8.0")] const GSLC_SSL_TWOWAY_AUTH = UNKNOWN; #endif @@ -624,8 +627,10 @@ #endif #ifdef HAVE_ORALDAP + #[\Deprecated(since: "8.5", message: "as it is broken since PHP 8.0")] function ldap_connect(?string $uri = null, int $port = 389, string $wallet = UNKNOWN, #[\SensitiveParameter] string $password = UNKNOWN, int $auth_mode = GSLC_SSL_NO_AUTH): LDAP\Connection|false {} #ifdef LDAP_API_FEATURE_X_OPENLDAP + #[\Deprecated(since: "8.5", message: "as it is broken since PHP 8.0")] function ldap_connect_wallet(?string $uri = null, string $wallet, #[\SensitiveParameter] string $password, int $auth_mode = GSLC_SSL_NO_AUTH): LDAP\Connection|false {} #endif #else diff --git a/ext/ldap/ldap_arginfo.h b/ext/ldap/ldap_arginfo.h index 3341b736bb2f1..25aa03343ace0 100644 --- a/ext/ldap/ldap_arginfo.h +++ b/ext/ldap/ldap_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: edd31d6c19c01bee6ddb04c747640c97f0bacba6 */ + * Stub hash: 9e47a0d85336f0e149abbdf56468513c5d31780f */ #if defined(HAVE_ORALDAP) ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_ldap_connect, 0, 0, LDAP\\Connection, MAY_BE_FALSE) @@ -434,10 +434,10 @@ ZEND_FUNCTION(ldap_parse_exop); static const zend_function_entry ext_functions[] = { #if defined(HAVE_ORALDAP) - ZEND_FE(ldap_connect, arginfo_ldap_connect) + ZEND_RAW_FENTRY("ldap_connect", zif_ldap_connect, arginfo_ldap_connect, ZEND_ACC_DEPRECATED, NULL, NULL) #endif #if defined(HAVE_ORALDAP) && defined(LDAP_API_FEATURE_X_OPENLDAP) - ZEND_FE(ldap_connect_wallet, arginfo_ldap_connect_wallet) + ZEND_RAW_FENTRY("ldap_connect_wallet", zif_ldap_connect_wallet, arginfo_ldap_connect_wallet, ZEND_ACC_DEPRECATED, NULL, NULL) #endif #if !(defined(HAVE_ORALDAP)) ZEND_FE(ldap_connect, arginfo_ldap_connect) @@ -593,9 +593,9 @@ static void register_ldap_symbols(int module_number) REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_USERNAME", LDAP_OPT_X_SASL_USERNAME, CONST_PERSISTENT); #endif #if defined(HAVE_ORALDAP) - REGISTER_LONG_CONSTANT("GSLC_SSL_NO_AUTH", GSLC_SSL_NO_AUTH, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("GSLC_SSL_ONEWAY_AUTH", GSLC_SSL_ONEWAY_AUTH, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("GSLC_SSL_TWOWAY_AUTH", GSLC_SSL_TWOWAY_AUTH, CONST_PERSISTENT); + zend_constant *const_GSLC_SSL_NO_AUTH = REGISTER_LONG_CONSTANT("GSLC_SSL_NO_AUTH", GSLC_SSL_NO_AUTH, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_GSLC_SSL_ONEWAY_AUTH = REGISTER_LONG_CONSTANT("GSLC_SSL_ONEWAY_AUTH", GSLC_SSL_ONEWAY_AUTH, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_GSLC_SSL_TWOWAY_AUTH = REGISTER_LONG_CONSTANT("GSLC_SSL_TWOWAY_AUTH", GSLC_SSL_TWOWAY_AUTH, CONST_PERSISTENT | CONST_DEPRECATED); #endif #if (LDAP_API_VERSION > 2000) REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_REQUIRE_CERT", LDAP_OPT_X_TLS_REQUIRE_CERT, CONST_PERSISTENT); @@ -709,10 +709,24 @@ static void register_ldap_symbols(int module_number) #if defined(HAVE_ORALDAP) + zend_attribute *attribute_Deprecated_func_ldap_connect_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "ldap_connect", sizeof("ldap_connect") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_func_ldap_connect_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_func_ldap_connect_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_ldap_connect_0_arg1_str = zend_string_init("as it is broken since PHP 8.0", strlen("as it is broken since PHP 8.0"), 1); + ZVAL_STR(&attribute_Deprecated_func_ldap_connect_0->args[1].value, attribute_Deprecated_func_ldap_connect_0_arg1_str); + attribute_Deprecated_func_ldap_connect_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "ldap_connect", sizeof("ldap_connect") - 1), 3, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); #endif #if defined(HAVE_ORALDAP) && defined(LDAP_API_FEATURE_X_OPENLDAP) + zend_attribute *attribute_Deprecated_func_ldap_connect_wallet_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "ldap_connect_wallet", sizeof("ldap_connect_wallet") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_func_ldap_connect_wallet_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_func_ldap_connect_wallet_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_ldap_connect_wallet_0_arg1_str = zend_string_init("as it is broken since PHP 8.0", strlen("as it is broken since PHP 8.0"), 1); + ZVAL_STR(&attribute_Deprecated_func_ldap_connect_wallet_0->args[1].value, attribute_Deprecated_func_ldap_connect_wallet_0_arg1_str); + attribute_Deprecated_func_ldap_connect_wallet_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "ldap_connect_wallet", sizeof("ldap_connect_wallet") - 1), 2, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); #endif @@ -729,6 +743,29 @@ static void register_ldap_symbols(int module_number) zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "ldap_exop_passwd", sizeof("ldap_exop_passwd") - 1), 3, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); #endif +#if defined(HAVE_ORALDAP) + + zend_attribute *attribute_Deprecated_const_GSLC_SSL_NO_AUTH_0 = zend_add_global_constant_attribute(const_GSLC_SSL_NO_AUTH, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_GSLC_SSL_NO_AUTH_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_const_GSLC_SSL_NO_AUTH_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_const_GSLC_SSL_NO_AUTH_0_arg1_str = zend_string_init("as it is broken since PHP 8.0", strlen("as it is broken since PHP 8.0"), 1); + ZVAL_STR(&attribute_Deprecated_const_GSLC_SSL_NO_AUTH_0->args[1].value, attribute_Deprecated_const_GSLC_SSL_NO_AUTH_0_arg1_str); + attribute_Deprecated_const_GSLC_SSL_NO_AUTH_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_GSLC_SSL_ONEWAY_AUTH_0 = zend_add_global_constant_attribute(const_GSLC_SSL_ONEWAY_AUTH, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_GSLC_SSL_ONEWAY_AUTH_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_const_GSLC_SSL_ONEWAY_AUTH_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_const_GSLC_SSL_ONEWAY_AUTH_0_arg1_str = zend_string_init("as it is broken since PHP 8.0", strlen("as it is broken since PHP 8.0"), 1); + ZVAL_STR(&attribute_Deprecated_const_GSLC_SSL_ONEWAY_AUTH_0->args[1].value, attribute_Deprecated_const_GSLC_SSL_ONEWAY_AUTH_0_arg1_str); + attribute_Deprecated_const_GSLC_SSL_ONEWAY_AUTH_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_GSLC_SSL_TWOWAY_AUTH_0 = zend_add_global_constant_attribute(const_GSLC_SSL_TWOWAY_AUTH, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_GSLC_SSL_TWOWAY_AUTH_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_const_GSLC_SSL_TWOWAY_AUTH_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_const_GSLC_SSL_TWOWAY_AUTH_0_arg1_str = zend_string_init("as it is broken since PHP 8.0", strlen("as it is broken since PHP 8.0"), 1); + ZVAL_STR(&attribute_Deprecated_const_GSLC_SSL_TWOWAY_AUTH_0->args[1].value, attribute_Deprecated_const_GSLC_SSL_TWOWAY_AUTH_0_arg1_str); + attribute_Deprecated_const_GSLC_SSL_TWOWAY_AUTH_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); +#endif } static zend_class_entry *register_class_LDAP_Connection(void) diff --git a/ext/ldap/tests/ldap_set_option_leak_attrvalue_context.phpt b/ext/ldap/tests/ldap_set_option_leak_attrvalue_context.phpt new file mode 100644 index 0000000000000..5829ad24faf57 --- /dev/null +++ b/ext/ldap/tests/ldap_set_option_leak_attrvalue_context.phpt @@ -0,0 +1,34 @@ +--TEST-- +ldap_set_option() - Leaks attrvalue and context +--EXTENSIONS-- +ldap +--FILE-- + "2.16.840.1.113730.3.4.9", "value" => ["attrvalue" => $attrvalue, "context" => $context, "before" => 0, "after" => 0]], +]; + +ldap_set_option($link, LDAP_OPT_CLIENT_CONTROLS, $controls); +ldap_get_option($link, LDAP_OPT_CLIENT_CONTROLS, $controls_out); + +var_dump($controls_out); +?> +--EXPECTF-- +array(1) { + ["2.16.840.1.113730.3.4.9"]=> + array(3) { + ["oid"]=> + string(23) "2.16.840.1.113730.3.4.9" + ["iscritical"]=> + bool(false) + ["value"]=> + string(28) "0%0%0� attrvaluecontext" + } +} 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 3b3c574f1d9a9..bf8fc547d88d0 100644 --- a/ext/lexbor/lexbor/core/str.c +++ b/ext/lexbor/lexbor/core/str.c @@ -80,6 +80,7 @@ lexbor_str_destroy(lexbor_str_t *str, lexbor_mraw_t *mraw, bool destroy_obj) } if (str->data != NULL) { + lexbor_str_clean(str); str->data = lexbor_mraw_free(mraw, str->data); } @@ -133,9 +134,9 @@ lexbor_str_append(lexbor_str_t *str, lexbor_mraw_t *mraw, { lxb_char_t *data_begin; - if (length == 0) { - return str->data; - } + 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 ed3732a5ccab2..0eef7a6deba46 100644 --- a/ext/lexbor/lexbor/url/url.c +++ b/ext/lexbor/lexbor/url/url.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023-2024 Alexander Borisov + * Copyright (C) 2023-2025 Alexander Borisov * * Author: Alexander Borisov */ @@ -36,6 +36,7 @@ typedef enum { LXB_URL_MAP_PATH = 0x10, LXB_URL_MAP_USERINFO = 0x20, LXB_URL_MAP_COMPONENT = 0x40, + LXB_URL_MAP_X_WWW_FORM = 0x80, LXB_URL_MAP_ALL = 0xff } lxb_url_map_type_t; @@ -54,6 +55,13 @@ typedef struct { } lxb_url_idna_ctx_t; +typedef struct { + lexbor_str_t **out_buf; + size_t out_length; + size_t out_size; +} +lxb_url_search_params_ctx_t; + static const uint8_t lxb_url_map[256] = { @@ -89,22 +97,22 @@ static const uint8_t lxb_url_map[256] = LXB_URL_MAP_ALL, /* 0x1d */ LXB_URL_MAP_ALL, /* 0x1e */ LXB_URL_MAP_ALL, /* 0x1f */ - LXB_URL_MAP_USERINFO|LXB_URL_MAP_FRAGMENT|LXB_URL_MAP_QUERY|LXB_URL_MAP_SPECIAL_QUERY|LXB_URL_MAP_PATH|LXB_URL_MAP_COMPONENT, /* 0x20 ( ) */ - LXB_URL_MAP_UNDEF, /* 0x21 (!) */ - LXB_URL_MAP_USERINFO|LXB_URL_MAP_FRAGMENT|LXB_URL_MAP_QUERY|LXB_URL_MAP_SPECIAL_QUERY|LXB_URL_MAP_PATH|LXB_URL_MAP_COMPONENT, /* 0x22 (") */ - LXB_URL_MAP_USERINFO|LXB_URL_MAP_QUERY|LXB_URL_MAP_SPECIAL_QUERY|LXB_URL_MAP_PATH|LXB_URL_MAP_COMPONENT, /* 0x23 (#) */ - LXB_URL_MAP_COMPONENT, /* 0x24 ($) */ - LXB_URL_MAP_UNDEF, /* 0x25 (%) */ - LXB_URL_MAP_COMPONENT, /* 0x26 (&) */ - LXB_URL_MAP_SPECIAL_QUERY, /* 0x27 (') */ - LXB_URL_MAP_UNDEF, /* 0x28 (() */ - LXB_URL_MAP_UNDEF, /* 0x29 ()) */ + LXB_URL_MAP_USERINFO|LXB_URL_MAP_FRAGMENT|LXB_URL_MAP_QUERY|LXB_URL_MAP_SPECIAL_QUERY|LXB_URL_MAP_PATH|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x20 ( ) */ + LXB_URL_MAP_X_WWW_FORM, /* 0x21 (!) */ + LXB_URL_MAP_USERINFO|LXB_URL_MAP_FRAGMENT|LXB_URL_MAP_QUERY|LXB_URL_MAP_SPECIAL_QUERY|LXB_URL_MAP_PATH|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x22 (") */ + LXB_URL_MAP_USERINFO|LXB_URL_MAP_QUERY|LXB_URL_MAP_SPECIAL_QUERY|LXB_URL_MAP_PATH|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x23 (#) */ + LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x24 ($) */ + LXB_URL_MAP_X_WWW_FORM, /* 0x25 (%) */ + LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x26 (&) */ + LXB_URL_MAP_SPECIAL_QUERY|LXB_URL_MAP_X_WWW_FORM, /* 0x27 (') */ + LXB_URL_MAP_X_WWW_FORM, /* 0x28 (() */ + LXB_URL_MAP_X_WWW_FORM, /* 0x29 ()) */ LXB_URL_MAP_UNDEF, /* 0x2a (*) */ - LXB_URL_MAP_COMPONENT, /* 0x2b (+) */ - LXB_URL_MAP_COMPONENT, /* 0x2c (,) */ + LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x2b (+) */ + LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x2c (,) */ LXB_URL_MAP_UNDEF, /* 0x2d (-) */ LXB_URL_MAP_UNDEF, /* 0x2e (.) */ - LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT, /* 0x2f (/) */ + LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x2f (/) */ LXB_URL_MAP_UNDEF, /* 0x30 (0) */ LXB_URL_MAP_UNDEF, /* 0x31 (1) */ LXB_URL_MAP_UNDEF, /* 0x32 (2) */ @@ -115,13 +123,13 @@ static const uint8_t lxb_url_map[256] = LXB_URL_MAP_UNDEF, /* 0x37 (7) */ LXB_URL_MAP_UNDEF, /* 0x38 (8) */ LXB_URL_MAP_UNDEF, /* 0x39 (9) */ - LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT, /* 0x3a (:) */ - LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT, /* 0x3b (;) */ - LXB_URL_MAP_USERINFO|LXB_URL_MAP_FRAGMENT|LXB_URL_MAP_QUERY|LXB_URL_MAP_SPECIAL_QUERY|LXB_URL_MAP_PATH|LXB_URL_MAP_COMPONENT, /* 0x3c (<) */ - LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT, /* 0x3d (=) */ - LXB_URL_MAP_USERINFO|LXB_URL_MAP_FRAGMENT|LXB_URL_MAP_QUERY|LXB_URL_MAP_SPECIAL_QUERY|LXB_URL_MAP_PATH|LXB_URL_MAP_COMPONENT, /* 0x3e (>) */ - LXB_URL_MAP_PATH|LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT, /* 0x3f (?) */ - LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT, /* 0x40 (@) */ + LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x3a (:) */ + LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x3b (;) */ + LXB_URL_MAP_USERINFO|LXB_URL_MAP_FRAGMENT|LXB_URL_MAP_QUERY|LXB_URL_MAP_SPECIAL_QUERY|LXB_URL_MAP_PATH|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x3c (<) */ + LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x3d (=) */ + LXB_URL_MAP_USERINFO|LXB_URL_MAP_FRAGMENT|LXB_URL_MAP_QUERY|LXB_URL_MAP_SPECIAL_QUERY|LXB_URL_MAP_PATH|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x3e (>) */ + LXB_URL_MAP_PATH|LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x3f (?) */ + LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x40 (@) */ LXB_URL_MAP_UNDEF, /* 0x41 (A) */ LXB_URL_MAP_UNDEF, /* 0x42 (B) */ LXB_URL_MAP_UNDEF, /* 0x43 (C) */ @@ -148,12 +156,12 @@ static const uint8_t lxb_url_map[256] = LXB_URL_MAP_UNDEF, /* 0x58 (X) */ LXB_URL_MAP_UNDEF, /* 0x59 (Y) */ LXB_URL_MAP_UNDEF, /* 0x5a (Z) */ - LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT, /* 0x5b ([) */ - LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT, /* 0x5c (\) */ - LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT, /* 0x5d (]) */ - LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT, /* 0x5e (^) */ + LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x5b ([) */ + LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x5c (\) */ + LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x5d (]) */ + LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x5e (^) */ LXB_URL_MAP_UNDEF, /* 0x5f (_) */ - LXB_URL_MAP_PATH|LXB_URL_MAP_FRAGMENT|LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT, /* 0x60 (`) */ + LXB_URL_MAP_PATH|LXB_URL_MAP_FRAGMENT|LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x60 (`) */ LXB_URL_MAP_UNDEF, /* 0x61 (a) */ LXB_URL_MAP_UNDEF, /* 0x62 (b) */ LXB_URL_MAP_UNDEF, /* 0x63 (c) */ @@ -180,10 +188,10 @@ static const uint8_t lxb_url_map[256] = LXB_URL_MAP_UNDEF, /* 0x78 (x) */ LXB_URL_MAP_UNDEF, /* 0x79 (y) */ LXB_URL_MAP_UNDEF, /* 0x7a (z) */ - LXB_URL_MAP_PATH|LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT, /* 0x7b ({) */ - LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT, /* 0x7c (|) */ - LXB_URL_MAP_PATH|LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT, /* 0x7d (}) */ - LXB_URL_MAP_UNDEF, /* 0x7e (~) */ + LXB_URL_MAP_PATH|LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x7b ({) */ + LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x7c (|) */ + LXB_URL_MAP_PATH|LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x7d (}) */ + LXB_URL_MAP_X_WWW_FORM, /* 0x7e (~) */ LXB_URL_MAP_ALL, /* 0x7f */ LXB_URL_MAP_ALL, /* 0x80 */ LXB_URL_MAP_ALL, /* 0x81 */ @@ -471,7 +479,7 @@ lxb_url_scheme_length = sizeof(lxb_url_scheme_res) / sizeof(lxb_url_scheme_data_ #define lxb_url_parse_return(data, buf, status) \ do { \ if ((buf) != (data)) { \ - lexbor_free((lxb_char_t *) (buf)); \ + parser->buffer = (lxb_char_t *) (buf); \ } \ return (status); \ } \ @@ -604,6 +612,10 @@ lxb_url_percent_decode(const lxb_char_t *data, const lxb_char_t *end, lexbor_str_t *str, lexbor_mraw_t *mraw, lxb_url_host_opt_t *opt); +static lxb_status_t +lxb_url_percent_decode_plus(const lxb_char_t *data, const lxb_char_t *end, + lexbor_str_t *str, lexbor_mraw_t *mraw); + static const lxb_char_t * lxb_url_path_part_by_index(const lxb_url_t *url, size_t index, size_t *out_length); @@ -613,6 +625,10 @@ lxb_url_host_set_h(lxb_url_t *url, lxb_url_parser_t *parser, const lxb_char_t *host, size_t length, lxb_url_state_t override_state); +static lxb_status_t +lxb_url_search_params_parse(lxb_url_search_params_t *search_params, + const lxb_char_t *query, size_t length); + lxb_url_parser_t * lxb_url_parser_create(void) @@ -645,6 +661,7 @@ lxb_url_parser_init(lxb_url_parser_t *parser, lexbor_mraw_t *mraw) parser->mraw = mraw; parser->log = NULL; parser->idna = NULL; + parser->buffer = NULL; return LXB_STATUS_OK; @@ -667,6 +684,10 @@ lxb_url_parser_clean(lxb_url_parser_t *parser) if (parser->log != NULL) { lexbor_plog_clean(parser->log); } + + if (parser->buffer != NULL) { + parser->buffer = lexbor_free(parser->buffer); + } } lxb_url_parser_t * @@ -679,6 +700,10 @@ lxb_url_parser_destroy(lxb_url_parser_t *parser, bool destroy_self) parser->log = lexbor_plog_destroy(parser->log, true); parser->idna = lxb_unicode_idna_destroy(parser->idna, true); + if (parser->buffer != NULL) { + parser->buffer = lexbor_free(parser->buffer); + } + if (destroy_self) { return lexbor_free(parser); } @@ -1004,27 +1029,34 @@ lxb_url_path_append_wo_slash(lxb_url_t *url, static lxb_status_t lxb_url_path_append(lxb_url_t *url, const lxb_char_t *data, size_t length) { - size_t len; - lxb_char_t *p; + lxb_char_t *p, *begin; lexbor_str_t *str; str = &url->path.str; if (str->data == NULL) { p = lexbor_str_init(str, url->mraw, length + 1); - if (p == NULL) { - return LXB_STATUS_ERROR_MEMORY_ALLOCATION; - } + } + else { + /* + 2 == begin '/' and end '\0' */ + p = lexbor_str_check_size(str, url->mraw, length + 2); } - len = str->length; - str->length += 1; + if (p == NULL) { + return LXB_STATUS_ERROR_MEMORY_ALLOCATION; + } - p = lexbor_str_append(&url->path.str, url->mraw, data, length); + begin = &str->data[str->length]; + begin[0] = '/'; - str->data[len] = '/'; + if (length > 0) { + memcpy(&begin[1], data, sizeof(lxb_char_t) * length); + } - return (p != NULL) ? LXB_STATUS_OK : LXB_STATUS_ERROR_MEMORY_ALLOCATION; + str->length += length + 1; + str->data[str->length] = '\0'; + + return LXB_STATUS_OK; } static lxb_status_t @@ -1081,9 +1113,9 @@ lxb_url_host_copy(const lxb_url_host_t *src, lxb_url_host_t *dst, } } - if (src->type <= LXB_URL_HOST_TYPE_OPAQUE) { - dst->type = src->type; + dst->type = src->type; + if (src->type <= LXB_URL_HOST_TYPE_OPAQUE) { if (src->type == LXB_URL_HOST_TYPE__UNDEF) { return LXB_STATUS_OK; } @@ -1785,7 +1817,6 @@ lxb_url_parse_basic_h(lxb_url_parser_t *parser, lxb_url_t *url, if (override_state != LXB_URL_STATE__UNDEF && url->scheme.type == LXB_URL_SCHEMEL_TYPE_FILE) { - p -= 1; state = LXB_URL_STATE_FILE_HOST_STATE; goto again; } @@ -1906,7 +1937,7 @@ lxb_url_parse_basic_h(lxb_url_parser_t *parser, lxb_url_t *url, { if (begin == p) { if (override_state != LXB_URL_STATE__UNDEF) { - lxb_url_parse_return(orig_data, buf, LXB_STATUS_OK); + lxb_url_parse_return(orig_data, buf, LXB_STATUS_ERROR); } state = LXB_URL_STATE_PATH_START_STATE; @@ -3056,7 +3087,7 @@ lxb_url_remove_tab_newline(lxb_url_parser_t *parser, return NULL; } - buf = lexbor_malloc(*length); + buf = lexbor_malloc(*length + 1); if (buf == NULL) { return NULL; } @@ -3083,6 +3114,8 @@ lxb_url_remove_tab_newline(lxb_url_parser_t *parser, *length = p_buf - buf; + buf[*length] = '\0'; + return buf; } @@ -4012,6 +4045,50 @@ lxb_url_percent_decode(const lxb_char_t *data, const lxb_char_t *end, return LXB_STATUS_OK; } +static lxb_status_t +lxb_url_percent_decode_plus(const lxb_char_t *data, const lxb_char_t *end, + lexbor_str_t *str, lexbor_mraw_t *mraw) +{ + lxb_char_t c, *dp; + lxb_status_t status; + const lxb_char_t *p; + + status = lxb_url_str_init(str, mraw, (end - data) + 1); + if (status != LXB_STATUS_OK) { + return status; + } + + p = data; + dp = str->data; + + while (p < end) { + c = *p++; + + if (c != '%') { + if (c == '+') { + c = ' '; + } + + *dp++ = c; + continue; + } + + if (p + 2 <= end && lexbor_str_res_map_hex[p[0]] != 0xff + && lexbor_str_res_map_hex[p[1]] != 0xff) + { + c = lexbor_str_res_map_hex[p[0]] << 4 | lexbor_str_res_map_hex[p[1]]; + p += 2; + } + + *dp++ = c; + } + + *dp = '\0'; + str->length = dp - str->data; + + return LXB_STATUS_OK; +} + void lxb_url_erase(lxb_url_t *url) { @@ -4123,6 +4200,7 @@ lxb_url_api_href_set(lxb_url_t *url, lxb_url_parser_t *parser, parser->log = NULL; parser->idna = NULL; + parser->buffer = NULL; } origin_mraw = parser->mraw; @@ -4167,6 +4245,7 @@ lxb_url_api_protocol_set(lxb_url_t *url, lxb_url_parser_t *parser, parser->log = NULL; parser->idna = NULL; + parser->buffer = NULL; } status = lxb_url_parse_basic_h(parser, url, NULL, protocol, length, @@ -4246,7 +4325,8 @@ lxb_url_host_set_h(lxb_url_t *url, lxb_url_parser_t *parser, lxb_url_parser_t self_parser; const lxb_char_t tmp[1] = ""; - if (url->host.type == LXB_URL_HOST_TYPE_OPAQUE) { + /* If this’s URL has an opaque path, then return. */ + if (url->path.opaque) { return LXB_STATUS_OK; } @@ -4260,6 +4340,7 @@ lxb_url_host_set_h(lxb_url_t *url, lxb_url_parser_t *parser, parser->log = NULL; parser->idna = NULL; + parser->buffer = NULL; } old = url->host; @@ -4314,6 +4395,7 @@ lxb_url_api_port_set(lxb_url_t *url, lxb_url_parser_t *parser, parser->log = NULL; parser->idna = NULL; + parser->buffer = NULL; } status = lxb_url_parse_basic_h(parser, url, NULL, port, length, @@ -4348,6 +4430,7 @@ lxb_url_api_pathname_set(lxb_url_t *url, lxb_url_parser_t *parser, parser->log = NULL; parser->idna = NULL; + parser->buffer = NULL; } url->path.length = 0; @@ -4390,6 +4473,7 @@ lxb_url_api_search_set(lxb_url_t *url, lxb_url_parser_t *parser, parser->log = NULL; parser->idna = NULL; + parser->buffer = NULL; } status = lxb_url_parse_basic_h(parser, url, NULL, search, length, @@ -4429,6 +4513,7 @@ lxb_url_api_hash_set(lxb_url_t *url, lxb_url_parser_t *parser, parser->log = NULL; parser->idna = NULL; + parser->buffer = NULL; } status = lxb_url_parse_basic_h(parser, url, NULL, hash, length, @@ -4804,7 +4889,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; @@ -4862,3 +4947,747 @@ lxb_url_clone(lexbor_mraw_t *mraw, lxb_url_t *url) return NULL; } + +lxb_url_search_params_t * +lxb_url_search_params_init(lexbor_mraw_t *mraw, + const lxb_char_t *query, size_t length) +{ + lxb_status_t status; + lxb_url_search_params_t *sp; + + sp = lexbor_mraw_calloc(mraw, sizeof(lxb_url_search_params_t)); + if (sp == NULL) { + return NULL; + } + + sp->mraw = mraw; + sp->length = 0; + + status = lxb_url_search_params_parse(sp, query, length); + if (status != LXB_STATUS_OK) { + return lxb_url_search_params_destroy(sp); + } + + return sp; +} + +lxb_inline lxb_url_search_entry_t * +lxb_url_search_params_entry(lxb_url_search_params_t *search_params, + lxb_url_search_entry_t *last, lexbor_mraw_t *mraw, + const lxb_char_t *query, const lxb_char_t *p, + lxb_status_t *status) +{ + lxb_url_search_entry_t *entry; + + entry = lexbor_mraw_calloc(mraw, + sizeof(lxb_url_search_entry_t)); + if (entry == NULL) { + *status = LXB_STATUS_ERROR_MEMORY_ALLOCATION; + return NULL; + } + + last->next = entry; + entry->prev = last; + entry->next = NULL; + + search_params->length += 1; + + *status = lxb_url_percent_decode_plus(query, p, &entry->name, mraw); + + return entry; +} + +static lxb_status_t +lxb_url_search_params_parse(lxb_url_search_params_t *search_params, + const lxb_char_t *query, size_t length) +{ + lxb_char_t c; + lxb_status_t status; + const lxb_char_t *p, *end; + lexbor_mraw_t *mraw; + lxb_url_search_entry_t first, *last, *entry; + + if (query == NULL || length == 0) { + return LXB_STATUS_OK; + } + + if (*query == '?') { + query += 1; + length -= 1; + } + + p = query; + end = p + length; + mraw = search_params->mraw; + last = &first; + last->next = NULL; + last->prev = NULL; + + while (p < end) { + c = *p++; + + if (c == '=') { + entry = lxb_url_search_params_entry(search_params, last, mraw, + query, p - 1, &status); + if (status != LXB_STATUS_OK) { + return status; + } + + last = entry; + query = p; + + while (p < end) { + c = *p; + + if (c == '&') { + break; + } + + p += 1; + } + + status = lxb_url_percent_decode_plus(query, p, + &entry->value, mraw); + if (status != LXB_STATUS_OK) { + return status; + } + + p += 1; + query = p; + } + else if (c == '&') { + entry = lxb_url_search_params_entry(search_params, last, mraw, + query, p - 1, &status); + if (status != LXB_STATUS_OK) { + return status; + } + + last = entry; + + lexbor_str_init(&entry->value, mraw, 0); + if (entry->value.data == NULL) { + return LXB_STATUS_ERROR_MEMORY_ALLOCATION; + } + + query = p; + } + } + + if (query < p) { + entry = lxb_url_search_params_entry(search_params, last, mraw, + query, p, &status); + if (status != LXB_STATUS_OK) { + return status; + } + + lexbor_str_init(&entry->value, mraw, 0); + if (entry->value.data == NULL) { + return LXB_STATUS_ERROR_MEMORY_ALLOCATION; + } + } + + search_params->first = first.next; + + if (first.next != NULL) { + search_params->last = last; + search_params->first->prev = NULL; + } + else { + search_params->last = NULL; + } + + return LXB_STATUS_OK; +} + +lxb_url_search_params_t * +lxb_url_search_params_destroy(lxb_url_search_params_t *search_params) +{ + lxb_url_search_entry_t *entry, *next; + lexbor_mraw_t *mraw; + + if (search_params == NULL) { + return NULL; + } + + entry = search_params->first; + mraw = search_params->mraw; + + while (entry != NULL) { + next = entry->next; + + lexbor_str_destroy(&entry->name, mraw, false); + lexbor_str_destroy(&entry->value, mraw, false); + lexbor_mraw_free(mraw, entry); + + entry = next; + } + + return lexbor_mraw_free(mraw, search_params); +} + +static void +lxb_url_search_params_entry_destroy(lxb_url_search_params_t *search_params, + lxb_url_search_entry_t *entry) +{ + lexbor_mraw_t *mraw = search_params->mraw; + + lexbor_str_destroy(&entry->name, mraw, false); + lexbor_str_destroy(&entry->value, mraw, false); + lexbor_mraw_free(mraw, entry); +} + +static lxb_status_t +lxb_url_search_params_to_str(lexbor_str_t *str, lexbor_mraw_t *mraw, + const lxb_char_t *data, size_t length) +{ + if (data == NULL || length == 0) { + lexbor_str_init(str, mraw, 0); + } + else { + lexbor_str_init_append(str, mraw, data, length); + } + + return str->data != NULL ? LXB_STATUS_OK + : LXB_STATUS_ERROR_MEMORY_ALLOCATION; +} + +lxb_url_search_entry_t * +lxb_url_search_params_append(lxb_url_search_params_t *search_params, + const lxb_char_t *name, size_t name_length, + const lxb_char_t *value, size_t value_length) +{ + lxb_status_t status; + lxb_url_search_entry_t *entry; + + entry = lexbor_mraw_calloc(search_params->mraw, + sizeof(lxb_url_search_entry_t)); + if (entry == NULL) { + return NULL; + } + + status = lxb_url_search_params_to_str(&entry->name, search_params->mraw, + name, name_length); + if (status != LXB_STATUS_OK) { + goto failed; + } + + status = lxb_url_search_params_to_str(&entry->value, search_params->mraw, + value, value_length); + if (status != LXB_STATUS_OK) { + goto failed; + } + + if (search_params->first == NULL) { + search_params->first = entry; + } + + if (search_params->last != NULL) { + search_params->last->next = entry; + } + + entry->prev = search_params->last; + entry->next = NULL; + search_params->last = entry; + + search_params->length += 1; + + return entry; + +failed: + + if (entry->name.data != NULL) { + lexbor_mraw_free(search_params->mraw, entry->name.data); + } + + if (entry->value.data != NULL) { + lexbor_mraw_free(search_params->mraw, entry->value.data); + } + + lexbor_mraw_free(search_params->mraw, entry); + + return NULL; +} + +static lexbor_action_t +lxb_url_search_params_delete_cb(lxb_url_search_params_t *sp, + lxb_url_search_entry_t *entry, void *ctx) +{ + if (sp->first == entry) { + sp->first = entry->next; + } + + if (sp->last == entry) { + sp->last = entry->prev; + } + + if (entry->next != NULL) { + entry->next->prev = entry->prev; + } + + if (entry->prev != NULL) { + entry->prev->next = entry->next; + } + + lxb_url_search_params_entry_destroy(sp, entry); + + sp->length -= 1; + + return LEXBOR_ACTION_OK; +} + +void +lxb_url_search_params_delete(lxb_url_search_params_t *search_params, + const lxb_char_t *name, size_t name_length, + const lxb_char_t *value, size_t value_length) +{ + lxb_url_search_params_match(search_params, name, name_length, + value, value_length, + lxb_url_search_params_delete_cb, NULL); +} + +lxb_url_search_entry_t * +lxb_url_search_params_get_entry(lxb_url_search_params_t *search_params, + const lxb_char_t *name, size_t length) +{ + lexbor_str_t *str; + lxb_url_search_entry_t *entry; + + entry = search_params->first; + + while (entry != NULL) { + str = &entry->name; + + if (str->length == length + && memcmp(str->data, name, length) == 0) + { + return entry; + } + + entry = entry->next; + } + + return NULL; +} + +lexbor_str_t * +lxb_url_search_params_get(lxb_url_search_params_t *search_params, + const lxb_char_t *name, size_t length) +{ + lxb_url_search_entry_t *entry; + + entry = lxb_url_search_params_get_entry(search_params, name, length); + if (entry == NULL) { + return NULL; + } + + return &entry->value; +} + +static lexbor_action_t +lxb_url_search_params_get_all_cb(lxb_url_search_params_t *sp, + lxb_url_search_entry_t *entry, void *context) +{ + lxb_url_search_params_ctx_t *ctx = context; + + if (ctx->out_length >= ctx->out_size) { + return LEXBOR_ACTION_STOP; + } + + ctx->out_buf[ctx->out_length] = &entry->value; + ctx->out_length += 1; + + return LEXBOR_ACTION_OK; +} + +size_t +lxb_url_search_params_get_all(lxb_url_search_params_t *search_params, + const lxb_char_t *name, size_t length, + lexbor_str_t **out_buf, size_t out_size) +{ + lxb_url_search_params_ctx_t ctx; + + ctx.out_buf = out_buf; + ctx.out_length = 0; + ctx.out_size = out_size; + + lxb_url_search_params_match(search_params, name, length, NULL, 0, + lxb_url_search_params_get_all_cb, &ctx); + return ctx.out_length; +} + +static lexbor_action_t +lxb_url_search_params_get_count_cb(lxb_url_search_params_t *sp, + lxb_url_search_entry_t *entry, void *context) +{ + size_t *count = context; + + *count += 1; + + return LEXBOR_ACTION_OK; +} + +size_t +lxb_url_search_params_get_count(lxb_url_search_params_t *search_params, + const lxb_char_t *name, size_t length) +{ + size_t count = 0; + + lxb_url_search_params_match(search_params, name, length, NULL, 0, + lxb_url_search_params_get_count_cb, &count); + return count; +} + +lxb_url_search_entry_t * +lxb_url_search_params_match_entry(lxb_url_search_params_t *search_params, + const lxb_char_t *name, size_t name_length, + const lxb_char_t *value, size_t value_length, + lxb_url_search_entry_t *entry) +{ + lexbor_str_t *str; + + if (entry == NULL) { + entry = search_params->first; + } + + while (entry != NULL) { + str = &entry->name; + + if (str->length == name_length + && memcmp(str->data, name, name_length) == 0) + { + if (value != NULL) { + str = &entry->value; + + if (str->length == value_length + && memcmp(str->data, value, value_length) == 0) + { + return entry; + } + } + else { + return entry; + } + } + + entry = entry->next; + } + + return NULL; +} + +void +lxb_url_search_params_match(lxb_url_search_params_t *search_params, + const lxb_char_t *name, size_t name_length, + const lxb_char_t *value, size_t value_length, + lxb_url_search_params_match_f cb, void *ctx) +{ + lexbor_str_t *str; + lexbor_action_t action; + lxb_url_search_entry_t *entry, *next; + + entry = search_params->first; + + while (entry != NULL) { + str = &entry->name; + next = entry->next; + + if (str->length == name_length + && memcmp(str->data, name, name_length) == 0) + { + if (value != NULL) { + str = &entry->value; + + if (str->length == value_length + && memcmp(str->data, value, value_length) == 0) + { + action = cb(search_params, entry, ctx); + if (action == LEXBOR_ACTION_STOP) { + return; + } + } + } + else { + action = cb(search_params, entry, ctx); + if (action == LEXBOR_ACTION_STOP) { + return; + } + } + } + + entry = next; + } +} + +static lexbor_action_t +lxb_url_search_params_has_cb(lxb_url_search_params_t *sp, + lxb_url_search_entry_t *entry, void *ctx) +{ + bool *is = ctx; + + *is = true; + + return LEXBOR_ACTION_STOP; +} + +bool +lxb_url_search_params_has(lxb_url_search_params_t *search_params, + const lxb_char_t *name, size_t name_length, + const lxb_char_t *value, size_t value_length) +{ + bool is = false; + + lxb_url_search_params_match(search_params, name, name_length, + value, value_length, + lxb_url_search_params_has_cb, &is); + return is; +} + +lxb_url_search_entry_t * +lxb_url_search_params_set(lxb_url_search_params_t *search_params, + const lxb_char_t *name, size_t name_length, + const lxb_char_t *value, size_t value_length) +{ + bool changed; + lxb_status_t status; + lexbor_str_t *str, str_name, str_value; + lexbor_mraw_t *mraw; + lxb_url_search_entry_t *entry, *next, *root; + + mraw = search_params->mraw; + entry = search_params->first; + changed = false; + root = NULL; + + while (entry != NULL) { + str = &entry->name; + next = entry->next; + + if (str->length == name_length + && memcmp(str->data, name, name_length) == 0) + { + if (changed) { + lxb_url_search_params_delete_cb(search_params, entry, NULL); + entry = next; + continue; + } + + str_name = entry->name; + str_value = entry->value; + + status = lxb_url_search_params_to_str(&entry->name, mraw, + name, name_length); + if (status != LXB_STATUS_OK) { + goto failed; + } + + status = lxb_url_search_params_to_str(&entry->value, mraw, + value, value_length); + if (status != LXB_STATUS_OK) { + lexbor_str_destroy(&entry->name, mraw, false); + goto failed; + } + + lexbor_str_destroy(&str_name, mraw, false); + lexbor_str_destroy(&str_value, mraw, false); + + changed = true; + root = entry; + } + + entry = next; + } + + if (!changed) { + return lxb_url_search_params_append(search_params, name, name_length, + value, value_length); + } + + return root; + +failed: + + entry->name = str_name; + entry->value = str_value; + + return NULL; +} + +lxb_inline int +lxb_url_search_params_compare(lxb_url_search_entry_t *first, + lxb_url_search_entry_t *second) +{ + return strcmp((const char *) first->name.data, + (const char *) second->name.data); +} + +void +lxb_url_search_params_sort(lxb_url_search_params_t *search_params) +{ + lxb_url_search_entry_t *root, *new_root, *node, *current; + + root = search_params->first; + + if (root == NULL) { + return; + } + + node = root; + root = root->next; + + node->next = NULL; + new_root = node; + + while (root != NULL) { + node = root; + root = root->next; + + if (lxb_url_search_params_compare(node, new_root) < 0) { + node->next = new_root; + new_root->prev = node; + new_root = node; + } + else { + current = new_root; + + while (current->next != NULL + && lxb_url_search_params_compare(node, current->next) >= 0) + { + current = current->next; + } + + node->next = current->next; + + if (current->next != NULL) { + current->next->prev = node; + } + + current->next = node; + node->prev = current; + } + } + + new_root->prev = NULL; + + search_params->first = new_root; + search_params->last = node->next != NULL ? node->next : node; +} + +static size_t +lxb_url_search_params_length(const lexbor_str_t *str) +{ + size_t length; + const lxb_char_t *p, *end; + + p = str->data; + end = p + str->length; + length = str->length; + + while (p < end) { + if (lxb_url_map[*p++] & LXB_URL_MAP_X_WWW_FORM) { + length += 2; + } + } + + return length; +} + +static lxb_char_t * +lxb_url_search_params_to_buf(const lexbor_str_t *str, lxb_char_t *buf) +{ + lxb_char_t c; + const lxb_char_t *p, *end; + + p = str->data; + end = p + str->length; + + while (p < end) { + c = *p; + + if (c == ' ') { + *buf++ = '+'; + } + else if (lxb_url_map[c] & LXB_URL_MAP_X_WWW_FORM) { + *buf++ = '%'; + *buf++ = lexbor_str_res_char_to_two_hex_value[c][0]; + *buf++ = lexbor_str_res_char_to_two_hex_value[c][1]; + } + else { + *buf++ = c; + } + + p += 1; + } + + return buf; +} + +lxb_status_t +lxb_url_search_params_serialize(lxb_url_search_params_t *search_params, + lexbor_callback_f cb, void *ctx) +{ + size_t length; + lxb_status_t status; + lxb_char_t *p, *begin; + lxb_url_search_entry_t *entry; + lxb_char_t buf[1024]; + + entry = search_params->first; + + if (entry == NULL) { + buf[0] = '\0'; + return cb(buf, 0, ctx); + } + + /* Calc length. */ + + length = 0; + + while (entry != NULL) { + length += lxb_url_search_params_length(&entry->name); + length += lxb_url_search_params_length(&entry->value); + length += 2; /* = and & */ + + entry = entry->next; + } + + if (length < sizeof(buf)) { + p = buf; + } + else { + p = lexbor_malloc(length); + if (p == NULL) { + return LXB_STATUS_ERROR_MEMORY_ALLOCATION; + } + } + + /* To buffer. */ + + begin = p; + entry = search_params->first; + + p = lxb_url_search_params_to_buf(&entry->name, p); + *p++ = '='; + p = lxb_url_search_params_to_buf(&entry->value, p); + + entry = entry->next; + + while (entry != NULL) { + *p++ = '&'; + + p = lxb_url_search_params_to_buf(&entry->name, p); + *p++ = '='; + p = lxb_url_search_params_to_buf(&entry->value, p); + + entry = entry->next; + } + + *p = '\0'; + + status = cb(begin, p - begin, ctx); + + if (buf != begin) { + lexbor_free(begin); + } + + return status; +} diff --git a/ext/lexbor/lexbor/url/url.h b/ext/lexbor/lexbor/url/url.h index 58952a0f910b6..4ed3f32aa6467 100644 --- a/ext/lexbor/lexbor/url/url.h +++ b/ext/lexbor/lexbor/url/url.h @@ -168,9 +168,35 @@ typedef struct { lexbor_plog_t *log; lxb_unicode_idna_t *idna; + + lxb_char_t *buffer; } lxb_url_parser_t; +/* URLSearchParams */ + +typedef struct lxb_url_search_entry lxb_url_search_entry_t; + +struct lxb_url_search_entry { + lexbor_str_t name; + lexbor_str_t value; + + lxb_url_search_entry_t *next; + lxb_url_search_entry_t *prev; +}; + +typedef struct { + lxb_url_search_entry_t *first; + lxb_url_search_entry_t *last; + lexbor_mraw_t *mraw; + size_t length; +} +lxb_url_search_params_t; + +typedef lexbor_action_t +(*lxb_url_search_params_match_f)(lxb_url_search_params_t *sp, + lxb_url_search_entry_t *entry, void *ctx); + /* * Create lxb_url_parser_t object. @@ -463,7 +489,279 @@ 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); + +/* URLSearchParams */ + +/* + * Initialization of lxb_url_search_params_t object. + * + * Corresponds to the URLSearchParams interface constructor. + * https://url.spec.whatwg.org/#interface-urlsearchparams + * + * @param[in] lexbor_mraw_t *. Not NULL. Can be taken from lxb_url_t. + * @param[in] const lxb_char_t *. Can be NULL. Query. + * @param[in] size_t. Can be 0. Length of query. + * + * @return lxb_url_search_params_t * if successful, otherwise NULL value. + */ +LXB_API lxb_url_search_params_t * +lxb_url_search_params_init(lexbor_mraw_t *mraw, + const lxb_char_t *params, size_t length); + +/* + * Destroy lxb_url_search_params_t object. + * + * Corresponds to the URLSearchParams interface constructor. + * https://url.spec.whatwg.org/#interface-urlsearchparams + * + * @param[in] lxb_url_search_params_t *. Not NULL. + * + * @return NULL value. + */ +LXB_API lxb_url_search_params_t * +lxb_url_search_params_destroy(lxb_url_search_params_t *search_params); + +/* + * Append a specified key/value pair as a new search parameter. + * + * Adds a new key-value pair to the end of the search parameters list. + * If a parameter with this name already exists, creates a duplicate. + * Equivalent to URLSearchParams.prototype.append(). + * https://url.spec.whatwg.org/#dom-urlsearchparams-append + * + * @param[in] lxb_url_search_params_t *. Must not be NULL. + * @param[in] name Parameter. Can be NULL. + * @param[in] name_length Length of parameter name. Can be 0. + * @param[in] value Parameter. Must not be NULL. Can be NULL. + * @param[in] Length of parameter value. Can be 0. + * + * @return lxb_url_search_entry_t * if successful, otherwise NULL value. + */ +LXB_API lxb_url_search_entry_t * +lxb_url_search_params_append(lxb_url_search_params_t *search_params, + const lxb_char_t *name, size_t name_length, + const lxb_char_t *value, size_t value_length); + +/* + * Delete search parameters that match a name and value. + * + * Removes all search parameters that match the specified name and value. + * If only name is specified (value == NULL), removes all parameters with + * that name. + * Equivalent to URLSearchParams.prototype.delete(). + * https://url.spec.whatwg.org/#dom-urlsearchparams-delete + * + * @param[in] lxb_url_search_params_t *. Must not be NULL. + * @param[in] name Parameter. Must not be NULL. + * @param[in] name_length Length of parameter name. + * @param[in] value Parameter. Can be NULL. + * @param[in] Length of parameter value. Can be 0. + * + * @return void. + */ +LXB_API void +lxb_url_search_params_delete(lxb_url_search_params_t *search_params, + const lxb_char_t *name, size_t name_length, + const lxb_char_t *value, size_t value_length); + +/* + * Get the first entry object associated with the given search parameter name. + * + * Returns the first search parameter entry with the specified name. + * Useful for obtaining both name and value of the parameter. + * + * @param[in] lxb_url_search_params_t *. Must not be NULL. + * @param[in] Name of the parameter to find. Must not be NULL. + * @param[in] Length of parameter name. Can be 0. + * + * @return Pointer to found parameter entry or NULL if parameter not found. + */ +LXB_API lxb_url_search_entry_t * +lxb_url_search_params_get_entry(lxb_url_search_params_t *search_params, + const lxb_char_t *name, size_t length); + +/* + * Get the first value associated with the given search parameter name. + * + * Returns the first value associated with the specified search parameter name. + * Equivalent to URLSearchParams.prototype.get(). + * https://url.spec.whatwg.org/#dom-urlsearchparams-get + * + * @param[in] lxb_url_search_params_t *. Must not be NULL. + * @param[in] Name of the parameter to find. Must not be NULL. + * @param[in] Length of parameter name. Can be 0. + * + * @return Pointer to string with parameter value or NULL if parameter not found. + */ +LXB_API lexbor_str_t * +lxb_url_search_params_get(lxb_url_search_params_t *search_params, + const lxb_char_t *name, size_t length); + +/* + * Get all values associated with the given search parameter name. + * + * Returns all values associated with the specified search parameter name. + * Fills the provided buffer with pointers to strings. + * Equivalent to URLSearchParams.prototype.getAll(). + * https://url.spec.whatwg.org/#dom-urlsearchparams-getall + * + * @param[in] lxb_url_search_params_t *. Must not be NULL. + * @param[in] Name of the parameter to find. Must not be NULL. + * @param[in] Length of parameter name. Can be 0. + * @param[out] Buffer for writing pointers to found strings. Must not be NULL. + * @param[in] Size of output buffer. + * + * @return Number of found values or 0 if parameter not found. + */ +LXB_API size_t +lxb_url_search_params_get_all(lxb_url_search_params_t *search_params, + const lxb_char_t *name, size_t length, + lexbor_str_t **out_buf, size_t out_size); + +/* + * Get the count of values associated with the given search parameter name. + * + * Returns the number of values associated with the specified search parameter + * name. Useful for determining buffer size before calling + * lxb_url_search_params_get_all. + * + * @param[in] lxb_url_search_params_t *. Must not be NULL. + * @param[in] Name of the parameter to find. Must not be NULL. + * @param[in] Length of parameter name. Can be 0. + * + * @return Number of found values or 0 if parameter not found. + */ +LXB_API size_t +lxb_url_search_params_get_count(lxb_url_search_params_t *search_params, + const lxb_char_t *name, size_t length); + +/* + * Find an entry that matches with the specified name and, optionally, value, + * starting from a given entry. + * + * Searches for a parameter entry that matches the specified name and, + * optionally, value, starting the search from the specified position. + * Useful for iterating through duplicate parameters. + * + * @param[in] lxb_url_search_params_t *. Must not be NULL. + * @param[in] Name of the parameter to find. Must not be NULL. + * @param[in] Length of parameter name. Can be 0. + * @param[in] Value of the parameter to find. Can be NULL. + * @param[in] Length of parameter value. Can be 0. + * @param[in] Entry to start search from. May be NULL to search from beginning. + * + * @return Pointer to found entry or NULL if no match found. + */ +LXB_API lxb_url_search_entry_t * +lxb_url_search_params_match_entry(lxb_url_search_params_t *search_params, + const lxb_char_t *name, size_t name_length, + const lxb_char_t *value, size_t value_length, + lxb_url_search_entry_t *entry); + +/* + * Check if a search parameter exists. + * + * Checks if a search parameter with the specified name and, optionally, value + * exists. + * If value is specified, checks for existence of specific name-value pair. + * Equivalent to URLSearchParams.prototype.has(). + * https://url.spec.whatwg.org/#dom-urlsearchparams-has + * + * @param[in] lxb_url_search_params_t *. Must not be NULL. + * @param[in] Name of the parameter to find. Must not be NULL. + * @param[in] Length of parameter name. Can be 0. + * @param[in] Value to check for. May be NULL to check only name. + * @param[in] Length of parameter value. Can be 0. + * + * @return true if parameter exists, false otherwise. + */ +LXB_API bool +lxb_url_search_params_has(lxb_url_search_params_t *search_params, + const lxb_char_t *name, size_t name_length, + const lxb_char_t *value, size_t value_length); + +/* + * Set the value associated with a given search parameter. + * + * Sets the value for a search parameter with the specified name. + * If parameters with this name already exist, removes them all and creates + * a new one. + * If parameter doesn't exist, creates it. + * Equivalent to URLSearchParams.prototype.set(). + * https://url.spec.whatwg.org/#dom-urlsearchparams-set + * + * @param[in] lxb_url_search_params_t *. Must not be NULL. + * @param[in] Parameter name to set. Must not be NULL. + * @param[in] Length of parameter name. Can be 0. + * @param[in] Parameter value to set. Can be NULL. + * @param[in] Length of parameter value. Can be 0. + * + * @return Pointer to created or updated parameter entry or NULL on error. + */ +LXB_API lxb_url_search_entry_t * +lxb_url_search_params_set(lxb_url_search_params_t *search_params, + const lxb_char_t *name, size_t name_length, + const lxb_char_t *value, size_t value_length); + +/* + * Iterate through all search parameters that match a name and, optionally, + * value. + * + * Iterates through all search parameters that match the specified name and, + * optionally, value, calling the callback function for each found parameter. + * + * @param[in] lxb_url_search_params_t *. Must not be NULL. + * @param[in] Name of the parameter to find. Must not be NULL. + * @param[in] Length of parameter name. Can be 0. + * @param[in] Value to search for. May be NULL to search by name only. + * @param[in] Length of parameter value. Can be 0. + * @param[in] Callback function to process found parameters. Must not be NULL. + * @param[in] User context passed to callback function. Can be NULL. + * + * @return void. + */ +LXB_API void +lxb_url_search_params_match(lxb_url_search_params_t *search_params, + const lxb_char_t *name, size_t name_length, + const lxb_char_t *value, size_t value_length, + lxb_url_search_params_match_f cb, void *ctx); + +/* + * Sort all key/value pairs by their keys. + * + * Sorts all key-value pairs in alphabetical order by keys (parameter names). + * Equivalent to URLSearchParams.prototype.sort(). + * https://url.spec.whatwg.org/#dom-urlsearchparams-sort + * + * @param[in] lxb_url_search_params_t *. Must not be NULL. + * + * @return void. + */ +LXB_API void +lxb_url_search_params_sort(lxb_url_search_params_t *search_params); + +/* + * Serialize search parameters into a URL query string format. + * + * Converts all search parameters into a properly encoded query string format + * according to the application/x-www-form-urlencoded specification. + * The serialized output is passed to the provided callback function. + * Equivalent to URLSearchParams.prototype.toString(). + * https://url.spec.whatwg.org/#concept-urlencoded-serializer + * + * The callback will be called only once. It will be passed a fully prepared + * string. + * + * @param[in] lxb_url_search_params_t *. Must not be NULL. + * @param[in] Callback function to receive serialized data chunks. Not NULL. + * @param[in] User context passed to callback function. May be NULL. + * + * @return LXB_STATUS_OK on success, error status on failure. + */ +LXB_API lxb_status_t +lxb_url_search_params_serialize(lxb_url_search_params_t *search_params, + lexbor_callback_f cb, void *ctx); /* * Inline functions. diff --git a/ext/lexbor/php_lexbor.c b/ext/lexbor/php_lexbor.c index 9421af0884223..7f847bfb0afeb 100644 --- a/ext/lexbor/php_lexbor.c +++ b/ext/lexbor/php_lexbor.c @@ -72,7 +72,7 @@ zend_module_entry lexbor_module_entry = { NULL, /* per-request startup function */ NULL, /* per-request shutdown function */ PHP_MINFO(lexbor), /* information function */ - NULL, + PHP_VERSION, STANDARD_MODULE_PROPERTIES }; 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/libxml/image_svg.h b/ext/libxml/image_svg.h new file mode 100644 index 0000000000000..d023334af36b6 --- /dev/null +++ b/ext/libxml/image_svg.h @@ -0,0 +1,25 @@ +/* + +----------------------------------------------------------------------+ + | 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 | + +----------------------------------------------------------------------+ + */ + +#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..0105106d9531b 100644 --- a/ext/libxml/libxml.c +++ b/ext/libxml/libxml.c @@ -40,9 +40,11 @@ #ifdef LIBXML_SCHEMAS_ENABLED #include #include +#include #endif #include "php_libxml.h" +#include "image_svg.h" #define PHP_LIBXML_LOADED_VERSION ((char *)xmlParserVersion) @@ -84,8 +86,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 +343,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); + } } } } @@ -499,6 +526,7 @@ static int php_libxml_streams_IO_close(void *context) return php_stream_close((php_stream*)context); } +/* TODO: This needs to be replaced by context-specific APIs in the future! */ static xmlParserInputBufferPtr php_libxml_input_buffer_create_filename(const char *URI, xmlCharEncoding enc) { @@ -533,13 +561,10 @@ php_libxml_input_buffer_create_filename(const char *URI, xmlCharEncoding enc) } /* Allocate the Input buffer front-end. */ - ret = xmlAllocParserInputBuffer(enc); - if (ret != NULL) { - ret->context = context; - ret->readcallback = php_libxml_streams_IO_read; - ret->closecallback = php_libxml_streams_IO_close; - } else + ret = xmlParserInputBufferCreateIO(php_libxml_streams_IO_read, php_libxml_streams_IO_close, context, enc); + if (ret == NULL) { php_libxml_streams_IO_close(context); + } return ret; } @@ -588,11 +613,10 @@ php_libxml_output_buffer_create_filename(const char *URI, } /* Allocate the Output buffer front-end. */ - ret = xmlAllocOutputBuffer(encoder); - if (ret != NULL) { - ret->context = context; - ret->writecallback = php_libxml_streams_IO_write; - ret->closecallback = php_libxml_streams_IO_close; + ret = xmlOutputBufferCreateIO(php_libxml_streams_IO_write, php_libxml_streams_IO_close, context, encoder); + if (ret == NULL) { + php_libxml_streams_IO_close(context); + goto err; } return ret; @@ -779,6 +803,7 @@ static xmlParserInputPtr php_libxml_external_entity_loader(const char *URL, zend_string_release(callable_name); zval_ptr_dtor(&callable); } else { +#if LIBXML_VERSION < 21400 /* TODO: allow storing the encoding in the stream context? */ xmlCharEncoding enc = XML_CHAR_ENCODING_NONE; xmlParserInputBufferPtr pib = xmlAllocParserInputBuffer(enc); @@ -788,15 +813,24 @@ static xmlParserInputPtr php_libxml_external_entity_loader(const char *URL, } else { /* make stream not being closed when the zval is freed */ GC_ADDREF(stream->res); + + ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations") pib->context = stream; pib->readcallback = php_libxml_streams_IO_read; pib->closecallback = php_libxml_streams_IO_close; + ZEND_DIAGNOSTIC_IGNORED_END ret = xmlNewIOInputStream(context, pib, enc); if (ret == NULL) { xmlFreeParserInputBuffer(pib); } } +#else + /* make stream not being closed when the zval is freed */ + GC_ADDREF(stream->res); + ret = xmlNewInputFromIO(NULL, php_libxml_streams_IO_read, php_libxml_streams_IO_close, stream, 0); + /* Note: if ret == NULL, the close operation will be executed, so don't DELREF stream->res upon failure! */ +#endif } } else if (Z_TYPE(retval) != IS_NULL) { /* retval not string nor resource nor null; convert to string */ @@ -902,7 +936,16 @@ PHP_LIBXML_API void php_libxml_initialize(void) if (!php_libxml_initialized) { /* we should be the only one's to ever init!! */ ZEND_IGNORE_LEAKS_BEGIN(); + xmlInitParser(); +#ifdef ZTS +# ifdef LIBXML_SCHEMAS_ENABLED + xmlSchemaInitTypes(); +# endif +# ifdef LIBXML_RELAXNG_ENABLED + xmlRelaxNGInitTypes(); +# endif +#endif ZEND_IGNORE_LEAKS_END(); php_libxml_default_entity_loader = xmlGetExternalEntityLoader(); @@ -969,6 +1012,8 @@ static PHP_MINIT_FUNCTION(libxml) xmlOutputBufferCreateFilenameDefault(php_libxml_output_buffer_create_filename); } + php_libxml_register_image_svg_handler(); + return SUCCESS; } @@ -1010,7 +1055,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 40963d9f98d95..9e3e07c83e503 100644 --- a/ext/libxml/libxml_arginfo.h +++ b/ext/libxml/libxml_arginfo.h @@ -90,10 +90,8 @@ 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_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); } @@ -106,9 +104,9 @@ static zend_class_entry *register_class_LibXMLError(void) zval property_level_default_value; ZVAL_UNDEF(&property_level_default_value); - zend_string *property_level_name = zend_string_init("level", sizeof("level") - 1, 1); + zend_string *property_level_name = zend_string_init("level", sizeof("level") - 1, true); zend_declare_typed_property(class_entry, property_level_name, &property_level_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_level_name); + zend_string_release_ex(property_level_name, true); zval property_code_default_value; ZVAL_UNDEF(&property_code_default_value); @@ -116,9 +114,9 @@ static zend_class_entry *register_class_LibXMLError(void) zval property_column_default_value; ZVAL_UNDEF(&property_column_default_value); - zend_string *property_column_name = zend_string_init("column", sizeof("column") - 1, 1); + zend_string *property_column_name = zend_string_init("column", sizeof("column") - 1, true); zend_declare_typed_property(class_entry, property_column_name, &property_column_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_column_name); + zend_string_release_ex(property_column_name, true); zval property_message_default_value; ZVAL_UNDEF(&property_message_default_value); 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 9c1759f05db63..118986411a8bb 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -116,7 +116,8 @@ static const enum mbfl_no_encoding php_mb_default_identify_list_cn[] = { mbfl_no_encoding_ascii, mbfl_no_encoding_utf8, mbfl_no_encoding_euc_cn, - mbfl_no_encoding_cp936 + mbfl_no_encoding_cp936, + mbfl_no_encoding_gb18030_2022 }; static const enum mbfl_no_encoding php_mb_default_identify_list_tw_hk[] = { @@ -313,7 +314,7 @@ static zend_result php_mb_parse_encoding_list(const char *value, size_t value_le list = (const mbfl_encoding **)pecalloc(size, sizeof(mbfl_encoding*), persistent); entry = list; n = 0; - included_auto = 0; + included_auto = false; p1 = tmpstr; while (1) { const char *comma = memchr(p1, ',', endp - p1); @@ -333,7 +334,7 @@ static zend_result php_mb_parse_encoding_list(const char *value, size_t value_le const enum mbfl_no_encoding *src = MBSTRG(default_detect_order_list); const size_t identify_list_size = MBSTRG(default_detect_order_list_size); size_t i; - included_auto = 1; + included_auto = true; for (i = 0; i < identify_list_size; i++) { *entry++ = mbfl_no2encoding(*src++); n++; @@ -379,7 +380,7 @@ static zend_result php_mb_parse_encoding_array(HashTable *target_hash, const mbf size_t size = zend_hash_num_elements(target_hash) + MBSTRG(default_detect_order_list_size); const mbfl_encoding **list = ecalloc(size, sizeof(mbfl_encoding*)); const mbfl_encoding **entry = list; - bool included_auto = 0; + bool included_auto = false; size_t n = 0; zval *hash_entry; ZEND_HASH_FOREACH_VAL(target_hash, hash_entry) { @@ -396,7 +397,7 @@ static zend_result php_mb_parse_encoding_array(HashTable *target_hash, const mbf const size_t identify_list_size = MBSTRG(default_detect_order_list_size); size_t j; - included_auto = 1; + included_auto = true; for (j = 0; j < identify_list_size; j++) { *entry++ = mbfl_no2encoding(*src++); n++; @@ -718,6 +719,11 @@ static PHP_INI_MH(OnUpdate_mbstring_detect_order) } MBSTRG(detect_order_list) = list; MBSTRG(detect_order_list_size) = size; + + if (stage == PHP_INI_STAGE_RUNTIME) { + php_mb_populate_current_detect_order_list(); + } + return SUCCESS; } /* }}} */ @@ -729,7 +735,7 @@ static zend_result _php_mb_ini_mbstring_http_input_set(const char *new_value, si list = (const mbfl_encoding**)pecalloc(1, sizeof(mbfl_encoding*), 1); *list = &mbfl_encoding_pass; size = 1; - } else if (FAILURE == php_mb_parse_encoding_list(new_value, new_value_length, &list, &size, /* persistent */ 1, /* arg_num */ 0) || size == 0) { + } else if (FAILURE == php_mb_parse_encoding_list(new_value, new_value_length, &list, &size, /* persistent */ true, /* arg_num */ 0) || size == 0) { return FAILURE; } if (MBSTRG(http_input_list)) { @@ -1160,8 +1166,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; } @@ -2788,7 +2794,7 @@ MBSTRING_API HashTable *php_mb_convert_encoding_recursive(HashTable *input, cons case IS_FALSE: case IS_LONG: case IS_DOUBLE: - ZVAL_COPY(&entry_tmp, entry); + ZVAL_COPY_VALUE(&entry_tmp, entry); break; case IS_ARRAY: chash = php_mb_convert_encoding_recursive( @@ -4506,7 +4512,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(); } @@ -5578,19 +5584,16 @@ static bool mb_check_str_encoding(zend_string *str, const mbfl_encoding *encodin static bool php_mb_check_encoding_recursive(HashTable *vars, const mbfl_encoding *encoding) { - zend_long idx; zend_string *key; zval *entry; bool valid = true; - (void)(idx); /* Suppress spurious compiler warning that `idx` is not used */ - if (GC_IS_RECURSIVE(vars)) { php_error_docref(NULL, E_WARNING, "Cannot not handle circular references"); return false; } GC_TRY_PROTECT_RECURSION(vars); - ZEND_HASH_FOREACH_KEY_VAL(vars, idx, key, entry) { + ZEND_HASH_FOREACH_STR_KEY_VAL(vars, key, entry) { ZVAL_DEREF(entry); if (key) { if (!mb_check_str_encoding(key, encoding)) { @@ -5984,6 +5987,11 @@ static void php_mb_populate_current_detect_order_list(void) entry[i] = mbfl_no2encoding(src[i]); } } + + if (MBSTRG(current_detect_order_list) != NULL) { + efree(ZEND_VOIDP(MBSTRG(current_detect_order_list))); + } + MBSTRG(current_detect_order_list) = entry; MBSTRG(current_detect_order_list_size) = nentries; } @@ -6667,13 +6675,15 @@ static zend_string* mb_mime_header_decode(zend_string *input, const mbfl_encodin p = temp; /* Decoding of MIME encoded word was successful; * Try to collapse a run of whitespace */ - if (p < e && (*p == '\n' || *p == '\r')) { + if (p < e && (*p == '\n' || *p == '\r' || *p == '\t' || *p == ' ')) { do { p++; } while (p < e && (*p == '\n' || *p == '\r' || *p == '\t' || *p == ' ')); /* We will only actually output a space if this is not immediately followed * by another valid encoded word */ space_pending = true; + } else { + space_pending = false; } continue; } diff --git a/ext/mbstring/php_onig_compat.h b/ext/mbstring/php_onig_compat.h index c97ba0c5cb674..5a1fa8eeaaf1b 100644 --- a/ext/mbstring/php_onig_compat.h +++ b/ext/mbstring/php_onig_compat.h @@ -5,4 +5,10 @@ #define regex_t php_mb_regex_t #define re_registers php_mb_re_registers +/* Required for some distros that conditionally override PV_. + * As we're in C99 this header is always available. */ +#ifndef HAVE_STDARG_H +# define HAVE_STDARG_H +#endif + #endif /* _PHP_ONIG_COMPAT_H */ 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/gh20674.phpt b/ext/mbstring/tests/gh20674.phpt new file mode 100644 index 0000000000000..2fb8206037dee --- /dev/null +++ b/ext/mbstring/tests/gh20674.phpt @@ -0,0 +1,40 @@ +--TEST-- +GH-20674 (mb_decode_mimeheader does not handle separator) +--EXTENSIONS-- +mbstring +--FILE-- + +--EXPECTF-- +string(11) "The PHP 8.5" +string(11) "The PHP 8.5" +string(11) "The PHP 8.5" +string(11) "The PHP 8.5" +string(3) "(a)" +string(5) "(a b)" +string(5) "(a b)" +string(4) "(ab)" +string(4) "(ab)" +string(4) "(ab)" 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-- +--EXPECT-- +array(4) { + [0]=> + string(5) "UTF-8" + [1]=> + string(11) "ISO-8859-15" + [2]=> + string(10) "ISO-8859-1" + [3]=> + string(5) "ASCII" +} +array(3) { + [0]=> + string(5) "UTF-8" + [1]=> + string(10) "ISO-8859-1" + [2]=> + string(5) "ASCII" +} +array(1) { + [0]=> + string(5) "UTF-8" +} +array(1) { + [0]=> + string(5) "UTF-8" +} +array(1) { + [0]=> + string(5) "UTF-8" +} + diff --git a/ext/mbstring/tests/mb_encode_mimeheader_indent.phpt b/ext/mbstring/tests/mb_encode_mimeheader_indent.phpt index afaab29c87427..288401e0aee88 100644 --- a/ext/mbstring/tests/mb_encode_mimeheader_indent.phpt +++ b/ext/mbstring/tests/mb_encode_mimeheader_indent.phpt @@ -2,6 +2,8 @@ Test mb_encode_mimeheader() function : basic functionality, indent --EXTENSIONS-- mbstring +--INI-- +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-- +--EXPECT-- +array(5) { + [0]=> + string(5) "ASCII" + [1]=> + string(5) "UTF-8" + [2]=> + string(6) "EUC-CN" + [3]=> + string(5) "CP936" + [4]=> + string(12) "GB18030-2022" +} diff --git a/ext/mbstring/unicode_data.h b/ext/mbstring/unicode_data.h index b205e67b21f12..31de0e5c20a29 100644 --- a/ext/mbstring/unicode_data.h +++ b/ext/mbstring/unicode_data.h @@ -13,11 +13,11 @@ static const unsigned short _ucprop_size = 37; static const unsigned short _ucprop_offsets[] = { - 0x0000, 0x02ca, 0x0446, 0x0450, 0x04de, 0x04f6, 0x0586, 0x0594, - 0x0596, 0x0598, 0x059a, 0x05a0, 0x05a0, 0x0ab6, 0x0fe2, 0x0ff6, - 0x108c, 0x14ac, 0x152e, 0x1558, 0x1596, 0x170c, 0x1d18, 0x1db0, - 0x1dcc, 0x1dde, 0x1e0e, 0x1e20, 0x1e3a, 0x1e44, 0x1e4a, 0x1e58, - 0x2290, 0x230c, 0x233a, 0x24c6, 0x2604, 0x298c, 0x0000, 0x0000 + 0x0000, 0x02da, 0x045c, 0x0466, 0x04f6, 0x0510, 0x05a0, 0x05ae, + 0x05b0, 0x05b2, 0x05b4, 0x05ba, 0x05ba, 0x0ad8, 0x1008, 0x101c, + 0x10ba, 0x14ec, 0x1572, 0x159c, 0x15da, 0x175c, 0x1d7a, 0x1e12, + 0x1e2e, 0x1e40, 0x1e70, 0x1e82, 0x1e9c, 0x1ea6, 0x1eac, 0x1eba, + 0x2310, 0x238c, 0x23ba, 0x2548, 0x2684, 0x2a24, 0x0000, 0x0000 }; static const unsigned int _ucprop_ranges[] = { @@ -92,85 +92,87 @@ static const unsigned int _ucprop_ranges[] = { 0x00001a60, 0x00001a60, 0x00001a62, 0x00001a62, 0x00001a65, 0x00001a6c, 0x00001a73, 0x00001a7c, 0x00001a7f, 0x00001a7f, 0x00001ab0, 0x00001abd, - 0x00001abf, 0x00001ace, 0x00001b00, 0x00001b03, - 0x00001b34, 0x00001b34, 0x00001b36, 0x00001b3a, - 0x00001b3c, 0x00001b3c, 0x00001b42, 0x00001b42, - 0x00001b6b, 0x00001b73, 0x00001b80, 0x00001b81, - 0x00001ba2, 0x00001ba5, 0x00001ba8, 0x00001ba9, - 0x00001bab, 0x00001bad, 0x00001be6, 0x00001be6, - 0x00001be8, 0x00001be9, 0x00001bed, 0x00001bed, - 0x00001bef, 0x00001bf1, 0x00001c2c, 0x00001c33, - 0x00001c36, 0x00001c37, 0x00001cd0, 0x00001cd2, - 0x00001cd4, 0x00001ce0, 0x00001ce2, 0x00001ce8, - 0x00001ced, 0x00001ced, 0x00001cf4, 0x00001cf4, - 0x00001cf8, 0x00001cf9, 0x00001dc0, 0x00001dff, - 0x000020d0, 0x000020dc, 0x000020e1, 0x000020e1, - 0x000020e5, 0x000020f0, 0x00002cef, 0x00002cf1, - 0x00002d7f, 0x00002d7f, 0x00002de0, 0x00002dff, - 0x0000302a, 0x0000302d, 0x00003099, 0x0000309a, - 0x0000a66f, 0x0000a66f, 0x0000a674, 0x0000a67d, - 0x0000a69e, 0x0000a69f, 0x0000a6f0, 0x0000a6f1, - 0x0000a802, 0x0000a802, 0x0000a806, 0x0000a806, - 0x0000a80b, 0x0000a80b, 0x0000a825, 0x0000a826, - 0x0000a82c, 0x0000a82c, 0x0000a8c4, 0x0000a8c5, - 0x0000a8e0, 0x0000a8f1, 0x0000a8ff, 0x0000a8ff, - 0x0000a926, 0x0000a92d, 0x0000a947, 0x0000a951, - 0x0000a980, 0x0000a982, 0x0000a9b3, 0x0000a9b3, - 0x0000a9b6, 0x0000a9b9, 0x0000a9bc, 0x0000a9bd, - 0x0000a9e5, 0x0000a9e5, 0x0000aa29, 0x0000aa2e, - 0x0000aa31, 0x0000aa32, 0x0000aa35, 0x0000aa36, - 0x0000aa43, 0x0000aa43, 0x0000aa4c, 0x0000aa4c, - 0x0000aa7c, 0x0000aa7c, 0x0000aab0, 0x0000aab0, - 0x0000aab2, 0x0000aab4, 0x0000aab7, 0x0000aab8, - 0x0000aabe, 0x0000aabf, 0x0000aac1, 0x0000aac1, - 0x0000aaec, 0x0000aaed, 0x0000aaf6, 0x0000aaf6, - 0x0000abe5, 0x0000abe5, 0x0000abe8, 0x0000abe8, - 0x0000abed, 0x0000abed, 0x0000fb1e, 0x0000fb1e, - 0x0000fe00, 0x0000fe0f, 0x0000fe20, 0x0000fe2f, - 0x000101fd, 0x000101fd, 0x000102e0, 0x000102e0, - 0x00010376, 0x0001037a, 0x00010a01, 0x00010a03, - 0x00010a05, 0x00010a06, 0x00010a0c, 0x00010a0f, - 0x00010a38, 0x00010a3a, 0x00010a3f, 0x00010a3f, - 0x00010ae5, 0x00010ae6, 0x00010d24, 0x00010d27, - 0x00010d69, 0x00010d6d, 0x00010eab, 0x00010eac, - 0x00010efc, 0x00010eff, 0x00010f46, 0x00010f50, - 0x00010f82, 0x00010f85, 0x00011001, 0x00011001, - 0x00011038, 0x00011046, 0x00011070, 0x00011070, - 0x00011073, 0x00011074, 0x0001107f, 0x00011081, - 0x000110b3, 0x000110b6, 0x000110b9, 0x000110ba, - 0x000110c2, 0x000110c2, 0x00011100, 0x00011102, - 0x00011127, 0x0001112b, 0x0001112d, 0x00011134, - 0x00011173, 0x00011173, 0x00011180, 0x00011181, - 0x000111b6, 0x000111be, 0x000111c9, 0x000111cc, - 0x000111cf, 0x000111cf, 0x0001122f, 0x00011231, - 0x00011234, 0x00011234, 0x00011236, 0x00011237, - 0x0001123e, 0x0001123e, 0x00011241, 0x00011241, - 0x000112df, 0x000112df, 0x000112e3, 0x000112ea, - 0x00011300, 0x00011301, 0x0001133b, 0x0001133c, - 0x00011340, 0x00011340, 0x00011366, 0x0001136c, - 0x00011370, 0x00011374, 0x000113bb, 0x000113c0, - 0x000113ce, 0x000113ce, 0x000113d0, 0x000113d0, - 0x000113d2, 0x000113d2, 0x000113e1, 0x000113e2, - 0x00011438, 0x0001143f, 0x00011442, 0x00011444, - 0x00011446, 0x00011446, 0x0001145e, 0x0001145e, - 0x000114b3, 0x000114b8, 0x000114ba, 0x000114ba, - 0x000114bf, 0x000114c0, 0x000114c2, 0x000114c3, - 0x000115b2, 0x000115b5, 0x000115bc, 0x000115bd, - 0x000115bf, 0x000115c0, 0x000115dc, 0x000115dd, - 0x00011633, 0x0001163a, 0x0001163d, 0x0001163d, - 0x0001163f, 0x00011640, 0x000116ab, 0x000116ab, - 0x000116ad, 0x000116ad, 0x000116b0, 0x000116b5, - 0x000116b7, 0x000116b7, 0x0001171d, 0x0001171d, - 0x0001171f, 0x0001171f, 0x00011722, 0x00011725, - 0x00011727, 0x0001172b, 0x0001182f, 0x00011837, - 0x00011839, 0x0001183a, 0x0001193b, 0x0001193c, - 0x0001193e, 0x0001193e, 0x00011943, 0x00011943, - 0x000119d4, 0x000119d7, 0x000119da, 0x000119db, - 0x000119e0, 0x000119e0, 0x00011a01, 0x00011a0a, - 0x00011a33, 0x00011a38, 0x00011a3b, 0x00011a3e, - 0x00011a47, 0x00011a47, 0x00011a51, 0x00011a56, - 0x00011a59, 0x00011a5b, 0x00011a8a, 0x00011a96, - 0x00011a98, 0x00011a99, 0x00011c30, 0x00011c36, + 0x00001abf, 0x00001add, 0x00001ae0, 0x00001aeb, + 0x00001b00, 0x00001b03, 0x00001b34, 0x00001b34, + 0x00001b36, 0x00001b3a, 0x00001b3c, 0x00001b3c, + 0x00001b42, 0x00001b42, 0x00001b6b, 0x00001b73, + 0x00001b80, 0x00001b81, 0x00001ba2, 0x00001ba5, + 0x00001ba8, 0x00001ba9, 0x00001bab, 0x00001bad, + 0x00001be6, 0x00001be6, 0x00001be8, 0x00001be9, + 0x00001bed, 0x00001bed, 0x00001bef, 0x00001bf1, + 0x00001c2c, 0x00001c33, 0x00001c36, 0x00001c37, + 0x00001cd0, 0x00001cd2, 0x00001cd4, 0x00001ce0, + 0x00001ce2, 0x00001ce8, 0x00001ced, 0x00001ced, + 0x00001cf4, 0x00001cf4, 0x00001cf8, 0x00001cf9, + 0x00001dc0, 0x00001dff, 0x000020d0, 0x000020dc, + 0x000020e1, 0x000020e1, 0x000020e5, 0x000020f0, + 0x00002cef, 0x00002cf1, 0x00002d7f, 0x00002d7f, + 0x00002de0, 0x00002dff, 0x0000302a, 0x0000302d, + 0x00003099, 0x0000309a, 0x0000a66f, 0x0000a66f, + 0x0000a674, 0x0000a67d, 0x0000a69e, 0x0000a69f, + 0x0000a6f0, 0x0000a6f1, 0x0000a802, 0x0000a802, + 0x0000a806, 0x0000a806, 0x0000a80b, 0x0000a80b, + 0x0000a825, 0x0000a826, 0x0000a82c, 0x0000a82c, + 0x0000a8c4, 0x0000a8c5, 0x0000a8e0, 0x0000a8f1, + 0x0000a8ff, 0x0000a8ff, 0x0000a926, 0x0000a92d, + 0x0000a947, 0x0000a951, 0x0000a980, 0x0000a982, + 0x0000a9b3, 0x0000a9b3, 0x0000a9b6, 0x0000a9b9, + 0x0000a9bc, 0x0000a9bd, 0x0000a9e5, 0x0000a9e5, + 0x0000aa29, 0x0000aa2e, 0x0000aa31, 0x0000aa32, + 0x0000aa35, 0x0000aa36, 0x0000aa43, 0x0000aa43, + 0x0000aa4c, 0x0000aa4c, 0x0000aa7c, 0x0000aa7c, + 0x0000aab0, 0x0000aab0, 0x0000aab2, 0x0000aab4, + 0x0000aab7, 0x0000aab8, 0x0000aabe, 0x0000aabf, + 0x0000aac1, 0x0000aac1, 0x0000aaec, 0x0000aaed, + 0x0000aaf6, 0x0000aaf6, 0x0000abe5, 0x0000abe5, + 0x0000abe8, 0x0000abe8, 0x0000abed, 0x0000abed, + 0x0000fb1e, 0x0000fb1e, 0x0000fe00, 0x0000fe0f, + 0x0000fe20, 0x0000fe2f, 0x000101fd, 0x000101fd, + 0x000102e0, 0x000102e0, 0x00010376, 0x0001037a, + 0x00010a01, 0x00010a03, 0x00010a05, 0x00010a06, + 0x00010a0c, 0x00010a0f, 0x00010a38, 0x00010a3a, + 0x00010a3f, 0x00010a3f, 0x00010ae5, 0x00010ae6, + 0x00010d24, 0x00010d27, 0x00010d69, 0x00010d6d, + 0x00010eab, 0x00010eac, 0x00010efa, 0x00010eff, + 0x00010f46, 0x00010f50, 0x00010f82, 0x00010f85, + 0x00011001, 0x00011001, 0x00011038, 0x00011046, + 0x00011070, 0x00011070, 0x00011073, 0x00011074, + 0x0001107f, 0x00011081, 0x000110b3, 0x000110b6, + 0x000110b9, 0x000110ba, 0x000110c2, 0x000110c2, + 0x00011100, 0x00011102, 0x00011127, 0x0001112b, + 0x0001112d, 0x00011134, 0x00011173, 0x00011173, + 0x00011180, 0x00011181, 0x000111b6, 0x000111be, + 0x000111c9, 0x000111cc, 0x000111cf, 0x000111cf, + 0x0001122f, 0x00011231, 0x00011234, 0x00011234, + 0x00011236, 0x00011237, 0x0001123e, 0x0001123e, + 0x00011241, 0x00011241, 0x000112df, 0x000112df, + 0x000112e3, 0x000112ea, 0x00011300, 0x00011301, + 0x0001133b, 0x0001133c, 0x00011340, 0x00011340, + 0x00011366, 0x0001136c, 0x00011370, 0x00011374, + 0x000113bb, 0x000113c0, 0x000113ce, 0x000113ce, + 0x000113d0, 0x000113d0, 0x000113d2, 0x000113d2, + 0x000113e1, 0x000113e2, 0x00011438, 0x0001143f, + 0x00011442, 0x00011444, 0x00011446, 0x00011446, + 0x0001145e, 0x0001145e, 0x000114b3, 0x000114b8, + 0x000114ba, 0x000114ba, 0x000114bf, 0x000114c0, + 0x000114c2, 0x000114c3, 0x000115b2, 0x000115b5, + 0x000115bc, 0x000115bd, 0x000115bf, 0x000115c0, + 0x000115dc, 0x000115dd, 0x00011633, 0x0001163a, + 0x0001163d, 0x0001163d, 0x0001163f, 0x00011640, + 0x000116ab, 0x000116ab, 0x000116ad, 0x000116ad, + 0x000116b0, 0x000116b5, 0x000116b7, 0x000116b7, + 0x0001171d, 0x0001171d, 0x0001171f, 0x0001171f, + 0x00011722, 0x00011725, 0x00011727, 0x0001172b, + 0x0001182f, 0x00011837, 0x00011839, 0x0001183a, + 0x0001193b, 0x0001193c, 0x0001193e, 0x0001193e, + 0x00011943, 0x00011943, 0x000119d4, 0x000119d7, + 0x000119da, 0x000119db, 0x000119e0, 0x000119e0, + 0x00011a01, 0x00011a0a, 0x00011a33, 0x00011a38, + 0x00011a3b, 0x00011a3e, 0x00011a47, 0x00011a47, + 0x00011a51, 0x00011a56, 0x00011a59, 0x00011a5b, + 0x00011a8a, 0x00011a96, 0x00011a98, 0x00011a99, + 0x00011b60, 0x00011b60, 0x00011b62, 0x00011b64, + 0x00011b66, 0x00011b66, 0x00011c30, 0x00011c36, 0x00011c38, 0x00011c3d, 0x00011c3f, 0x00011c3f, 0x00011c92, 0x00011ca7, 0x00011caa, 0x00011cb0, 0x00011cb2, 0x00011cb3, 0x00011cb5, 0x00011cb6, @@ -198,6 +200,8 @@ static const unsigned int _ucprop_ranges[] = { 0x0001e08f, 0x0001e08f, 0x0001e130, 0x0001e136, 0x0001e2ae, 0x0001e2ae, 0x0001e2ec, 0x0001e2ef, 0x0001e4ec, 0x0001e4ef, 0x0001e5ee, 0x0001e5ef, + 0x0001e6e3, 0x0001e6e3, 0x0001e6e6, 0x0001e6e6, + 0x0001e6ee, 0x0001e6ef, 0x0001e6f5, 0x0001e6f5, 0x0001e8d0, 0x0001e8d6, 0x0001e944, 0x0001e94a, 0x000e0100, 0x000e01ef, 0x00000903, 0x00000903, 0x0000093b, 0x0000093b, 0x0000093e, 0x00000940, @@ -285,47 +289,49 @@ static const unsigned int _ucprop_ranges[] = { 0x00011942, 0x00011942, 0x000119d1, 0x000119d3, 0x000119dc, 0x000119df, 0x000119e4, 0x000119e4, 0x00011a39, 0x00011a39, 0x00011a57, 0x00011a58, - 0x00011a97, 0x00011a97, 0x00011c2f, 0x00011c2f, - 0x00011c3e, 0x00011c3e, 0x00011ca9, 0x00011ca9, - 0x00011cb1, 0x00011cb1, 0x00011cb4, 0x00011cb4, - 0x00011d8a, 0x00011d8e, 0x00011d93, 0x00011d94, - 0x00011d96, 0x00011d96, 0x00011ef5, 0x00011ef6, - 0x00011f03, 0x00011f03, 0x00011f34, 0x00011f35, - 0x00011f3e, 0x00011f3f, 0x00011f41, 0x00011f41, - 0x0001612a, 0x0001612c, 0x00016f51, 0x00016f87, - 0x00016ff0, 0x00016ff1, 0x0001d165, 0x0001d166, - 0x0001d16d, 0x0001d172, 0x00000488, 0x00000489, - 0x00001abe, 0x00001abe, 0x000020dd, 0x000020e0, - 0x000020e2, 0x000020e4, 0x0000a670, 0x0000a672, - 0x00000030, 0x00000039, 0x00000660, 0x00000669, - 0x000006f0, 0x000006f9, 0x000007c0, 0x000007c9, - 0x00000966, 0x0000096f, 0x000009e6, 0x000009ef, - 0x00000a66, 0x00000a6f, 0x00000ae6, 0x00000aef, - 0x00000b66, 0x00000b6f, 0x00000be6, 0x00000bef, - 0x00000c66, 0x00000c6f, 0x00000ce6, 0x00000cef, - 0x00000d66, 0x00000d6f, 0x00000de6, 0x00000def, - 0x00000e50, 0x00000e59, 0x00000ed0, 0x00000ed9, - 0x00000f20, 0x00000f29, 0x00001040, 0x00001049, - 0x00001090, 0x00001099, 0x000017e0, 0x000017e9, - 0x00001810, 0x00001819, 0x00001946, 0x0000194f, - 0x000019d0, 0x000019d9, 0x00001a80, 0x00001a89, - 0x00001a90, 0x00001a99, 0x00001b50, 0x00001b59, - 0x00001bb0, 0x00001bb9, 0x00001c40, 0x00001c49, - 0x00001c50, 0x00001c59, 0x0000a620, 0x0000a629, - 0x0000a8d0, 0x0000a8d9, 0x0000a900, 0x0000a909, - 0x0000a9d0, 0x0000a9d9, 0x0000a9f0, 0x0000a9f9, - 0x0000aa50, 0x0000aa59, 0x0000abf0, 0x0000abf9, - 0x0000ff10, 0x0000ff19, 0x000104a0, 0x000104a9, - 0x00010d30, 0x00010d39, 0x00010d40, 0x00010d49, - 0x00011066, 0x0001106f, 0x000110f0, 0x000110f9, - 0x00011136, 0x0001113f, 0x000111d0, 0x000111d9, - 0x000112f0, 0x000112f9, 0x00011450, 0x00011459, - 0x000114d0, 0x000114d9, 0x00011650, 0x00011659, - 0x000116c0, 0x000116c9, 0x000116d0, 0x000116e3, - 0x00011730, 0x00011739, 0x000118e0, 0x000118e9, - 0x00011950, 0x00011959, 0x00011bf0, 0x00011bf9, - 0x00011c50, 0x00011c59, 0x00011d50, 0x00011d59, - 0x00011da0, 0x00011da9, 0x00011f50, 0x00011f59, + 0x00011a97, 0x00011a97, 0x00011b61, 0x00011b61, + 0x00011b65, 0x00011b65, 0x00011b67, 0x00011b67, + 0x00011c2f, 0x00011c2f, 0x00011c3e, 0x00011c3e, + 0x00011ca9, 0x00011ca9, 0x00011cb1, 0x00011cb1, + 0x00011cb4, 0x00011cb4, 0x00011d8a, 0x00011d8e, + 0x00011d93, 0x00011d94, 0x00011d96, 0x00011d96, + 0x00011ef5, 0x00011ef6, 0x00011f03, 0x00011f03, + 0x00011f34, 0x00011f35, 0x00011f3e, 0x00011f3f, + 0x00011f41, 0x00011f41, 0x0001612a, 0x0001612c, + 0x00016f51, 0x00016f87, 0x00016ff0, 0x00016ff1, + 0x0001d165, 0x0001d166, 0x0001d16d, 0x0001d172, + 0x00000488, 0x00000489, 0x00001abe, 0x00001abe, + 0x000020dd, 0x000020e0, 0x000020e2, 0x000020e4, + 0x0000a670, 0x0000a672, 0x00000030, 0x00000039, + 0x00000660, 0x00000669, 0x000006f0, 0x000006f9, + 0x000007c0, 0x000007c9, 0x00000966, 0x0000096f, + 0x000009e6, 0x000009ef, 0x00000a66, 0x00000a6f, + 0x00000ae6, 0x00000aef, 0x00000b66, 0x00000b6f, + 0x00000be6, 0x00000bef, 0x00000c66, 0x00000c6f, + 0x00000ce6, 0x00000cef, 0x00000d66, 0x00000d6f, + 0x00000de6, 0x00000def, 0x00000e50, 0x00000e59, + 0x00000ed0, 0x00000ed9, 0x00000f20, 0x00000f29, + 0x00001040, 0x00001049, 0x00001090, 0x00001099, + 0x000017e0, 0x000017e9, 0x00001810, 0x00001819, + 0x00001946, 0x0000194f, 0x000019d0, 0x000019d9, + 0x00001a80, 0x00001a89, 0x00001a90, 0x00001a99, + 0x00001b50, 0x00001b59, 0x00001bb0, 0x00001bb9, + 0x00001c40, 0x00001c49, 0x00001c50, 0x00001c59, + 0x0000a620, 0x0000a629, 0x0000a8d0, 0x0000a8d9, + 0x0000a900, 0x0000a909, 0x0000a9d0, 0x0000a9d9, + 0x0000a9f0, 0x0000a9f9, 0x0000aa50, 0x0000aa59, + 0x0000abf0, 0x0000abf9, 0x0000ff10, 0x0000ff19, + 0x000104a0, 0x000104a9, 0x00010d30, 0x00010d39, + 0x00010d40, 0x00010d49, 0x00011066, 0x0001106f, + 0x000110f0, 0x000110f9, 0x00011136, 0x0001113f, + 0x000111d0, 0x000111d9, 0x000112f0, 0x000112f9, + 0x00011450, 0x00011459, 0x000114d0, 0x000114d9, + 0x00011650, 0x00011659, 0x000116c0, 0x000116c9, + 0x000116d0, 0x000116e3, 0x00011730, 0x00011739, + 0x000118e0, 0x000118e9, 0x00011950, 0x00011959, + 0x00011bf0, 0x00011bf9, 0x00011c50, 0x00011c59, + 0x00011d50, 0x00011d59, 0x00011da0, 0x00011da9, + 0x00011de0, 0x00011de9, 0x00011f50, 0x00011f59, 0x00016130, 0x00016139, 0x00016a60, 0x00016a69, 0x00016ac0, 0x00016ac9, 0x00016b50, 0x00016b59, 0x00016d70, 0x00016d79, 0x0001ccf0, 0x0001ccf9, @@ -338,351 +344,353 @@ static const unsigned int _ucprop_ranges[] = { 0x00003038, 0x0000303a, 0x0000a6e6, 0x0000a6ef, 0x00010140, 0x00010174, 0x00010341, 0x00010341, 0x0001034a, 0x0001034a, 0x000103d1, 0x000103d5, - 0x00012400, 0x0001246e, 0x000000b2, 0x000000b3, - 0x000000b9, 0x000000b9, 0x000000bc, 0x000000be, - 0x000009f4, 0x000009f9, 0x00000b72, 0x00000b77, - 0x00000bf0, 0x00000bf2, 0x00000c78, 0x00000c7e, - 0x00000d58, 0x00000d5e, 0x00000d70, 0x00000d78, - 0x00000f2a, 0x00000f33, 0x00001369, 0x0000137c, - 0x000017f0, 0x000017f9, 0x000019da, 0x000019da, - 0x00002070, 0x00002070, 0x00002074, 0x00002079, - 0x00002080, 0x00002089, 0x00002150, 0x0000215f, - 0x00002189, 0x00002189, 0x00002460, 0x0000249b, - 0x000024ea, 0x000024ff, 0x00002776, 0x00002793, - 0x00002cfd, 0x00002cfd, 0x00003192, 0x00003195, - 0x00003220, 0x00003229, 0x00003248, 0x0000324f, - 0x00003251, 0x0000325f, 0x00003280, 0x00003289, - 0x000032b1, 0x000032bf, 0x0000a830, 0x0000a835, - 0x00010107, 0x00010133, 0x00010175, 0x00010178, - 0x0001018a, 0x0001018b, 0x000102e1, 0x000102fb, - 0x00010320, 0x00010323, 0x00010858, 0x0001085f, - 0x00010879, 0x0001087f, 0x000108a7, 0x000108af, - 0x000108fb, 0x000108ff, 0x00010916, 0x0001091b, - 0x000109bc, 0x000109bd, 0x000109c0, 0x000109cf, - 0x000109d2, 0x000109ff, 0x00010a40, 0x00010a48, - 0x00010a7d, 0x00010a7e, 0x00010a9d, 0x00010a9f, - 0x00010aeb, 0x00010aef, 0x00010b58, 0x00010b5f, - 0x00010b78, 0x00010b7f, 0x00010ba9, 0x00010baf, - 0x00010cfa, 0x00010cff, 0x00010e60, 0x00010e7e, - 0x00010f1d, 0x00010f26, 0x00010f51, 0x00010f54, - 0x00010fc5, 0x00010fcb, 0x00011052, 0x00011065, - 0x000111e1, 0x000111f4, 0x0001173a, 0x0001173b, - 0x000118ea, 0x000118f2, 0x00011c5a, 0x00011c6c, - 0x00011fc0, 0x00011fd4, 0x00016b5b, 0x00016b61, - 0x00016e80, 0x00016e96, 0x0001d2c0, 0x0001d2d3, - 0x0001d2e0, 0x0001d2f3, 0x0001d360, 0x0001d378, - 0x0001e8c7, 0x0001e8cf, 0x0001ec71, 0x0001ecab, - 0x0001ecad, 0x0001ecaf, 0x0001ecb1, 0x0001ecb4, - 0x0001ed01, 0x0001ed2d, 0x0001ed2f, 0x0001ed3d, - 0x0001f100, 0x0001f10c, 0x00000020, 0x00000020, - 0x000000a0, 0x000000a0, 0x00001680, 0x00001680, - 0x00002000, 0x0000200a, 0x0000202f, 0x0000202f, - 0x0000205f, 0x0000205f, 0x00003000, 0x00003000, - 0x00002028, 0x00002028, 0x00002029, 0x00002029, - 0x0000d800, 0x0000dfff, 0x0000e000, 0x0000f8ff, - 0x000f0000, 0x000ffffd, 0x00100000, 0x0010fffd, - 0x00000041, 0x0000005a, 0x000000c0, 0x000000d6, - 0x000000d8, 0x000000de, 0x00000100, 0x00000100, - 0x00000102, 0x00000102, 0x00000104, 0x00000104, - 0x00000106, 0x00000106, 0x00000108, 0x00000108, - 0x0000010a, 0x0000010a, 0x0000010c, 0x0000010c, - 0x0000010e, 0x0000010e, 0x00000110, 0x00000110, - 0x00000112, 0x00000112, 0x00000114, 0x00000114, - 0x00000116, 0x00000116, 0x00000118, 0x00000118, - 0x0000011a, 0x0000011a, 0x0000011c, 0x0000011c, - 0x0000011e, 0x0000011e, 0x00000120, 0x00000120, - 0x00000122, 0x00000122, 0x00000124, 0x00000124, - 0x00000126, 0x00000126, 0x00000128, 0x00000128, - 0x0000012a, 0x0000012a, 0x0000012c, 0x0000012c, - 0x0000012e, 0x0000012e, 0x00000130, 0x00000130, - 0x00000132, 0x00000132, 0x00000134, 0x00000134, - 0x00000136, 0x00000136, 0x00000139, 0x00000139, - 0x0000013b, 0x0000013b, 0x0000013d, 0x0000013d, - 0x0000013f, 0x0000013f, 0x00000141, 0x00000141, - 0x00000143, 0x00000143, 0x00000145, 0x00000145, - 0x00000147, 0x00000147, 0x0000014a, 0x0000014a, - 0x0000014c, 0x0000014c, 0x0000014e, 0x0000014e, - 0x00000150, 0x00000150, 0x00000152, 0x00000152, - 0x00000154, 0x00000154, 0x00000156, 0x00000156, - 0x00000158, 0x00000158, 0x0000015a, 0x0000015a, - 0x0000015c, 0x0000015c, 0x0000015e, 0x0000015e, - 0x00000160, 0x00000160, 0x00000162, 0x00000162, - 0x00000164, 0x00000164, 0x00000166, 0x00000166, - 0x00000168, 0x00000168, 0x0000016a, 0x0000016a, - 0x0000016c, 0x0000016c, 0x0000016e, 0x0000016e, - 0x00000170, 0x00000170, 0x00000172, 0x00000172, - 0x00000174, 0x00000174, 0x00000176, 0x00000176, - 0x00000178, 0x00000179, 0x0000017b, 0x0000017b, - 0x0000017d, 0x0000017d, 0x00000181, 0x00000182, - 0x00000184, 0x00000184, 0x00000186, 0x00000187, - 0x00000189, 0x0000018b, 0x0000018e, 0x00000191, - 0x00000193, 0x00000194, 0x00000196, 0x00000198, - 0x0000019c, 0x0000019d, 0x0000019f, 0x000001a0, - 0x000001a2, 0x000001a2, 0x000001a4, 0x000001a4, - 0x000001a6, 0x000001a7, 0x000001a9, 0x000001a9, - 0x000001ac, 0x000001ac, 0x000001ae, 0x000001af, - 0x000001b1, 0x000001b3, 0x000001b5, 0x000001b5, - 0x000001b7, 0x000001b8, 0x000001bc, 0x000001bc, - 0x000001c4, 0x000001c4, 0x000001c7, 0x000001c7, - 0x000001ca, 0x000001ca, 0x000001cd, 0x000001cd, - 0x000001cf, 0x000001cf, 0x000001d1, 0x000001d1, - 0x000001d3, 0x000001d3, 0x000001d5, 0x000001d5, - 0x000001d7, 0x000001d7, 0x000001d9, 0x000001d9, - 0x000001db, 0x000001db, 0x000001de, 0x000001de, - 0x000001e0, 0x000001e0, 0x000001e2, 0x000001e2, - 0x000001e4, 0x000001e4, 0x000001e6, 0x000001e6, - 0x000001e8, 0x000001e8, 0x000001ea, 0x000001ea, - 0x000001ec, 0x000001ec, 0x000001ee, 0x000001ee, - 0x000001f1, 0x000001f1, 0x000001f4, 0x000001f4, - 0x000001f6, 0x000001f8, 0x000001fa, 0x000001fa, - 0x000001fc, 0x000001fc, 0x000001fe, 0x000001fe, - 0x00000200, 0x00000200, 0x00000202, 0x00000202, - 0x00000204, 0x00000204, 0x00000206, 0x00000206, - 0x00000208, 0x00000208, 0x0000020a, 0x0000020a, - 0x0000020c, 0x0000020c, 0x0000020e, 0x0000020e, - 0x00000210, 0x00000210, 0x00000212, 0x00000212, - 0x00000214, 0x00000214, 0x00000216, 0x00000216, - 0x00000218, 0x00000218, 0x0000021a, 0x0000021a, - 0x0000021c, 0x0000021c, 0x0000021e, 0x0000021e, - 0x00000220, 0x00000220, 0x00000222, 0x00000222, - 0x00000224, 0x00000224, 0x00000226, 0x00000226, - 0x00000228, 0x00000228, 0x0000022a, 0x0000022a, - 0x0000022c, 0x0000022c, 0x0000022e, 0x0000022e, - 0x00000230, 0x00000230, 0x00000232, 0x00000232, - 0x0000023a, 0x0000023b, 0x0000023d, 0x0000023e, - 0x00000241, 0x00000241, 0x00000243, 0x00000246, - 0x00000248, 0x00000248, 0x0000024a, 0x0000024a, - 0x0000024c, 0x0000024c, 0x0000024e, 0x0000024e, - 0x00000370, 0x00000370, 0x00000372, 0x00000372, - 0x00000376, 0x00000376, 0x0000037f, 0x0000037f, - 0x00000386, 0x00000386, 0x00000388, 0x0000038a, - 0x0000038c, 0x0000038c, 0x0000038e, 0x0000038f, - 0x00000391, 0x000003a1, 0x000003a3, 0x000003ab, - 0x000003cf, 0x000003cf, 0x000003d2, 0x000003d4, - 0x000003d8, 0x000003d8, 0x000003da, 0x000003da, - 0x000003dc, 0x000003dc, 0x000003de, 0x000003de, - 0x000003e0, 0x000003e0, 0x000003e2, 0x000003e2, - 0x000003e4, 0x000003e4, 0x000003e6, 0x000003e6, - 0x000003e8, 0x000003e8, 0x000003ea, 0x000003ea, - 0x000003ec, 0x000003ec, 0x000003ee, 0x000003ee, - 0x000003f4, 0x000003f4, 0x000003f7, 0x000003f7, - 0x000003f9, 0x000003fa, 0x000003fd, 0x0000042f, - 0x00000460, 0x00000460, 0x00000462, 0x00000462, - 0x00000464, 0x00000464, 0x00000466, 0x00000466, - 0x00000468, 0x00000468, 0x0000046a, 0x0000046a, - 0x0000046c, 0x0000046c, 0x0000046e, 0x0000046e, - 0x00000470, 0x00000470, 0x00000472, 0x00000472, - 0x00000474, 0x00000474, 0x00000476, 0x00000476, - 0x00000478, 0x00000478, 0x0000047a, 0x0000047a, - 0x0000047c, 0x0000047c, 0x0000047e, 0x0000047e, - 0x00000480, 0x00000480, 0x0000048a, 0x0000048a, - 0x0000048c, 0x0000048c, 0x0000048e, 0x0000048e, - 0x00000490, 0x00000490, 0x00000492, 0x00000492, - 0x00000494, 0x00000494, 0x00000496, 0x00000496, - 0x00000498, 0x00000498, 0x0000049a, 0x0000049a, - 0x0000049c, 0x0000049c, 0x0000049e, 0x0000049e, - 0x000004a0, 0x000004a0, 0x000004a2, 0x000004a2, - 0x000004a4, 0x000004a4, 0x000004a6, 0x000004a6, - 0x000004a8, 0x000004a8, 0x000004aa, 0x000004aa, - 0x000004ac, 0x000004ac, 0x000004ae, 0x000004ae, - 0x000004b0, 0x000004b0, 0x000004b2, 0x000004b2, - 0x000004b4, 0x000004b4, 0x000004b6, 0x000004b6, - 0x000004b8, 0x000004b8, 0x000004ba, 0x000004ba, - 0x000004bc, 0x000004bc, 0x000004be, 0x000004be, - 0x000004c0, 0x000004c1, 0x000004c3, 0x000004c3, - 0x000004c5, 0x000004c5, 0x000004c7, 0x000004c7, - 0x000004c9, 0x000004c9, 0x000004cb, 0x000004cb, - 0x000004cd, 0x000004cd, 0x000004d0, 0x000004d0, - 0x000004d2, 0x000004d2, 0x000004d4, 0x000004d4, - 0x000004d6, 0x000004d6, 0x000004d8, 0x000004d8, - 0x000004da, 0x000004da, 0x000004dc, 0x000004dc, - 0x000004de, 0x000004de, 0x000004e0, 0x000004e0, - 0x000004e2, 0x000004e2, 0x000004e4, 0x000004e4, - 0x000004e6, 0x000004e6, 0x000004e8, 0x000004e8, - 0x000004ea, 0x000004ea, 0x000004ec, 0x000004ec, - 0x000004ee, 0x000004ee, 0x000004f0, 0x000004f0, - 0x000004f2, 0x000004f2, 0x000004f4, 0x000004f4, - 0x000004f6, 0x000004f6, 0x000004f8, 0x000004f8, - 0x000004fa, 0x000004fa, 0x000004fc, 0x000004fc, - 0x000004fe, 0x000004fe, 0x00000500, 0x00000500, - 0x00000502, 0x00000502, 0x00000504, 0x00000504, - 0x00000506, 0x00000506, 0x00000508, 0x00000508, - 0x0000050a, 0x0000050a, 0x0000050c, 0x0000050c, - 0x0000050e, 0x0000050e, 0x00000510, 0x00000510, - 0x00000512, 0x00000512, 0x00000514, 0x00000514, - 0x00000516, 0x00000516, 0x00000518, 0x00000518, - 0x0000051a, 0x0000051a, 0x0000051c, 0x0000051c, - 0x0000051e, 0x0000051e, 0x00000520, 0x00000520, - 0x00000522, 0x00000522, 0x00000524, 0x00000524, - 0x00000526, 0x00000526, 0x00000528, 0x00000528, - 0x0000052a, 0x0000052a, 0x0000052c, 0x0000052c, - 0x0000052e, 0x0000052e, 0x00000531, 0x00000556, - 0x000010a0, 0x000010c5, 0x000010c7, 0x000010c7, - 0x000010cd, 0x000010cd, 0x000013a0, 0x000013f5, - 0x00001c89, 0x00001c89, 0x00001c90, 0x00001cba, - 0x00001cbd, 0x00001cbf, 0x00001e00, 0x00001e00, - 0x00001e02, 0x00001e02, 0x00001e04, 0x00001e04, - 0x00001e06, 0x00001e06, 0x00001e08, 0x00001e08, - 0x00001e0a, 0x00001e0a, 0x00001e0c, 0x00001e0c, - 0x00001e0e, 0x00001e0e, 0x00001e10, 0x00001e10, - 0x00001e12, 0x00001e12, 0x00001e14, 0x00001e14, - 0x00001e16, 0x00001e16, 0x00001e18, 0x00001e18, - 0x00001e1a, 0x00001e1a, 0x00001e1c, 0x00001e1c, - 0x00001e1e, 0x00001e1e, 0x00001e20, 0x00001e20, - 0x00001e22, 0x00001e22, 0x00001e24, 0x00001e24, - 0x00001e26, 0x00001e26, 0x00001e28, 0x00001e28, - 0x00001e2a, 0x00001e2a, 0x00001e2c, 0x00001e2c, - 0x00001e2e, 0x00001e2e, 0x00001e30, 0x00001e30, - 0x00001e32, 0x00001e32, 0x00001e34, 0x00001e34, - 0x00001e36, 0x00001e36, 0x00001e38, 0x00001e38, - 0x00001e3a, 0x00001e3a, 0x00001e3c, 0x00001e3c, - 0x00001e3e, 0x00001e3e, 0x00001e40, 0x00001e40, - 0x00001e42, 0x00001e42, 0x00001e44, 0x00001e44, - 0x00001e46, 0x00001e46, 0x00001e48, 0x00001e48, - 0x00001e4a, 0x00001e4a, 0x00001e4c, 0x00001e4c, - 0x00001e4e, 0x00001e4e, 0x00001e50, 0x00001e50, - 0x00001e52, 0x00001e52, 0x00001e54, 0x00001e54, - 0x00001e56, 0x00001e56, 0x00001e58, 0x00001e58, - 0x00001e5a, 0x00001e5a, 0x00001e5c, 0x00001e5c, - 0x00001e5e, 0x00001e5e, 0x00001e60, 0x00001e60, - 0x00001e62, 0x00001e62, 0x00001e64, 0x00001e64, - 0x00001e66, 0x00001e66, 0x00001e68, 0x00001e68, - 0x00001e6a, 0x00001e6a, 0x00001e6c, 0x00001e6c, - 0x00001e6e, 0x00001e6e, 0x00001e70, 0x00001e70, - 0x00001e72, 0x00001e72, 0x00001e74, 0x00001e74, - 0x00001e76, 0x00001e76, 0x00001e78, 0x00001e78, - 0x00001e7a, 0x00001e7a, 0x00001e7c, 0x00001e7c, - 0x00001e7e, 0x00001e7e, 0x00001e80, 0x00001e80, - 0x00001e82, 0x00001e82, 0x00001e84, 0x00001e84, - 0x00001e86, 0x00001e86, 0x00001e88, 0x00001e88, - 0x00001e8a, 0x00001e8a, 0x00001e8c, 0x00001e8c, - 0x00001e8e, 0x00001e8e, 0x00001e90, 0x00001e90, - 0x00001e92, 0x00001e92, 0x00001e94, 0x00001e94, - 0x00001e9e, 0x00001e9e, 0x00001ea0, 0x00001ea0, - 0x00001ea2, 0x00001ea2, 0x00001ea4, 0x00001ea4, - 0x00001ea6, 0x00001ea6, 0x00001ea8, 0x00001ea8, - 0x00001eaa, 0x00001eaa, 0x00001eac, 0x00001eac, - 0x00001eae, 0x00001eae, 0x00001eb0, 0x00001eb0, - 0x00001eb2, 0x00001eb2, 0x00001eb4, 0x00001eb4, - 0x00001eb6, 0x00001eb6, 0x00001eb8, 0x00001eb8, - 0x00001eba, 0x00001eba, 0x00001ebc, 0x00001ebc, - 0x00001ebe, 0x00001ebe, 0x00001ec0, 0x00001ec0, - 0x00001ec2, 0x00001ec2, 0x00001ec4, 0x00001ec4, - 0x00001ec6, 0x00001ec6, 0x00001ec8, 0x00001ec8, - 0x00001eca, 0x00001eca, 0x00001ecc, 0x00001ecc, - 0x00001ece, 0x00001ece, 0x00001ed0, 0x00001ed0, - 0x00001ed2, 0x00001ed2, 0x00001ed4, 0x00001ed4, - 0x00001ed6, 0x00001ed6, 0x00001ed8, 0x00001ed8, - 0x00001eda, 0x00001eda, 0x00001edc, 0x00001edc, - 0x00001ede, 0x00001ede, 0x00001ee0, 0x00001ee0, - 0x00001ee2, 0x00001ee2, 0x00001ee4, 0x00001ee4, - 0x00001ee6, 0x00001ee6, 0x00001ee8, 0x00001ee8, - 0x00001eea, 0x00001eea, 0x00001eec, 0x00001eec, - 0x00001eee, 0x00001eee, 0x00001ef0, 0x00001ef0, - 0x00001ef2, 0x00001ef2, 0x00001ef4, 0x00001ef4, - 0x00001ef6, 0x00001ef6, 0x00001ef8, 0x00001ef8, - 0x00001efa, 0x00001efa, 0x00001efc, 0x00001efc, - 0x00001efe, 0x00001efe, 0x00001f08, 0x00001f0f, - 0x00001f18, 0x00001f1d, 0x00001f28, 0x00001f2f, - 0x00001f38, 0x00001f3f, 0x00001f48, 0x00001f4d, - 0x00001f59, 0x00001f59, 0x00001f5b, 0x00001f5b, - 0x00001f5d, 0x00001f5d, 0x00001f5f, 0x00001f5f, - 0x00001f68, 0x00001f6f, 0x00001fb8, 0x00001fbb, - 0x00001fc8, 0x00001fcb, 0x00001fd8, 0x00001fdb, - 0x00001fe8, 0x00001fec, 0x00001ff8, 0x00001ffb, - 0x00002102, 0x00002102, 0x00002107, 0x00002107, - 0x0000210b, 0x0000210d, 0x00002110, 0x00002112, - 0x00002115, 0x00002115, 0x00002119, 0x0000211d, - 0x00002124, 0x00002124, 0x00002126, 0x00002126, - 0x00002128, 0x00002128, 0x0000212a, 0x0000212d, - 0x00002130, 0x00002133, 0x0000213e, 0x0000213f, - 0x00002145, 0x00002145, 0x00002183, 0x00002183, - 0x00002c00, 0x00002c2f, 0x00002c60, 0x00002c60, - 0x00002c62, 0x00002c64, 0x00002c67, 0x00002c67, - 0x00002c69, 0x00002c69, 0x00002c6b, 0x00002c6b, - 0x00002c6d, 0x00002c70, 0x00002c72, 0x00002c72, - 0x00002c75, 0x00002c75, 0x00002c7e, 0x00002c80, - 0x00002c82, 0x00002c82, 0x00002c84, 0x00002c84, - 0x00002c86, 0x00002c86, 0x00002c88, 0x00002c88, - 0x00002c8a, 0x00002c8a, 0x00002c8c, 0x00002c8c, - 0x00002c8e, 0x00002c8e, 0x00002c90, 0x00002c90, - 0x00002c92, 0x00002c92, 0x00002c94, 0x00002c94, - 0x00002c96, 0x00002c96, 0x00002c98, 0x00002c98, - 0x00002c9a, 0x00002c9a, 0x00002c9c, 0x00002c9c, - 0x00002c9e, 0x00002c9e, 0x00002ca0, 0x00002ca0, - 0x00002ca2, 0x00002ca2, 0x00002ca4, 0x00002ca4, - 0x00002ca6, 0x00002ca6, 0x00002ca8, 0x00002ca8, - 0x00002caa, 0x00002caa, 0x00002cac, 0x00002cac, - 0x00002cae, 0x00002cae, 0x00002cb0, 0x00002cb0, - 0x00002cb2, 0x00002cb2, 0x00002cb4, 0x00002cb4, - 0x00002cb6, 0x00002cb6, 0x00002cb8, 0x00002cb8, - 0x00002cba, 0x00002cba, 0x00002cbc, 0x00002cbc, - 0x00002cbe, 0x00002cbe, 0x00002cc0, 0x00002cc0, - 0x00002cc2, 0x00002cc2, 0x00002cc4, 0x00002cc4, - 0x00002cc6, 0x00002cc6, 0x00002cc8, 0x00002cc8, - 0x00002cca, 0x00002cca, 0x00002ccc, 0x00002ccc, - 0x00002cce, 0x00002cce, 0x00002cd0, 0x00002cd0, - 0x00002cd2, 0x00002cd2, 0x00002cd4, 0x00002cd4, - 0x00002cd6, 0x00002cd6, 0x00002cd8, 0x00002cd8, - 0x00002cda, 0x00002cda, 0x00002cdc, 0x00002cdc, - 0x00002cde, 0x00002cde, 0x00002ce0, 0x00002ce0, - 0x00002ce2, 0x00002ce2, 0x00002ceb, 0x00002ceb, - 0x00002ced, 0x00002ced, 0x00002cf2, 0x00002cf2, - 0x0000a640, 0x0000a640, 0x0000a642, 0x0000a642, - 0x0000a644, 0x0000a644, 0x0000a646, 0x0000a646, - 0x0000a648, 0x0000a648, 0x0000a64a, 0x0000a64a, - 0x0000a64c, 0x0000a64c, 0x0000a64e, 0x0000a64e, - 0x0000a650, 0x0000a650, 0x0000a652, 0x0000a652, - 0x0000a654, 0x0000a654, 0x0000a656, 0x0000a656, - 0x0000a658, 0x0000a658, 0x0000a65a, 0x0000a65a, - 0x0000a65c, 0x0000a65c, 0x0000a65e, 0x0000a65e, - 0x0000a660, 0x0000a660, 0x0000a662, 0x0000a662, - 0x0000a664, 0x0000a664, 0x0000a666, 0x0000a666, - 0x0000a668, 0x0000a668, 0x0000a66a, 0x0000a66a, - 0x0000a66c, 0x0000a66c, 0x0000a680, 0x0000a680, - 0x0000a682, 0x0000a682, 0x0000a684, 0x0000a684, - 0x0000a686, 0x0000a686, 0x0000a688, 0x0000a688, - 0x0000a68a, 0x0000a68a, 0x0000a68c, 0x0000a68c, - 0x0000a68e, 0x0000a68e, 0x0000a690, 0x0000a690, - 0x0000a692, 0x0000a692, 0x0000a694, 0x0000a694, - 0x0000a696, 0x0000a696, 0x0000a698, 0x0000a698, - 0x0000a69a, 0x0000a69a, 0x0000a722, 0x0000a722, - 0x0000a724, 0x0000a724, 0x0000a726, 0x0000a726, - 0x0000a728, 0x0000a728, 0x0000a72a, 0x0000a72a, - 0x0000a72c, 0x0000a72c, 0x0000a72e, 0x0000a72e, - 0x0000a732, 0x0000a732, 0x0000a734, 0x0000a734, - 0x0000a736, 0x0000a736, 0x0000a738, 0x0000a738, - 0x0000a73a, 0x0000a73a, 0x0000a73c, 0x0000a73c, - 0x0000a73e, 0x0000a73e, 0x0000a740, 0x0000a740, - 0x0000a742, 0x0000a742, 0x0000a744, 0x0000a744, - 0x0000a746, 0x0000a746, 0x0000a748, 0x0000a748, - 0x0000a74a, 0x0000a74a, 0x0000a74c, 0x0000a74c, - 0x0000a74e, 0x0000a74e, 0x0000a750, 0x0000a750, - 0x0000a752, 0x0000a752, 0x0000a754, 0x0000a754, - 0x0000a756, 0x0000a756, 0x0000a758, 0x0000a758, - 0x0000a75a, 0x0000a75a, 0x0000a75c, 0x0000a75c, - 0x0000a75e, 0x0000a75e, 0x0000a760, 0x0000a760, - 0x0000a762, 0x0000a762, 0x0000a764, 0x0000a764, - 0x0000a766, 0x0000a766, 0x0000a768, 0x0000a768, - 0x0000a76a, 0x0000a76a, 0x0000a76c, 0x0000a76c, - 0x0000a76e, 0x0000a76e, 0x0000a779, 0x0000a779, - 0x0000a77b, 0x0000a77b, 0x0000a77d, 0x0000a77e, - 0x0000a780, 0x0000a780, 0x0000a782, 0x0000a782, - 0x0000a784, 0x0000a784, 0x0000a786, 0x0000a786, - 0x0000a78b, 0x0000a78b, 0x0000a78d, 0x0000a78d, - 0x0000a790, 0x0000a790, 0x0000a792, 0x0000a792, - 0x0000a796, 0x0000a796, 0x0000a798, 0x0000a798, - 0x0000a79a, 0x0000a79a, 0x0000a79c, 0x0000a79c, - 0x0000a79e, 0x0000a79e, 0x0000a7a0, 0x0000a7a0, - 0x0000a7a2, 0x0000a7a2, 0x0000a7a4, 0x0000a7a4, - 0x0000a7a6, 0x0000a7a6, 0x0000a7a8, 0x0000a7a8, - 0x0000a7aa, 0x0000a7ae, 0x0000a7b0, 0x0000a7b4, - 0x0000a7b6, 0x0000a7b6, 0x0000a7b8, 0x0000a7b8, - 0x0000a7ba, 0x0000a7ba, 0x0000a7bc, 0x0000a7bc, - 0x0000a7be, 0x0000a7be, 0x0000a7c0, 0x0000a7c0, - 0x0000a7c2, 0x0000a7c2, 0x0000a7c4, 0x0000a7c7, - 0x0000a7c9, 0x0000a7c9, 0x0000a7cb, 0x0000a7cc, - 0x0000a7d0, 0x0000a7d0, 0x0000a7d6, 0x0000a7d6, + 0x00012400, 0x0001246e, 0x00016ff4, 0x00016ff6, + 0x000000b2, 0x000000b3, 0x000000b9, 0x000000b9, + 0x000000bc, 0x000000be, 0x000009f4, 0x000009f9, + 0x00000b72, 0x00000b77, 0x00000bf0, 0x00000bf2, + 0x00000c78, 0x00000c7e, 0x00000d58, 0x00000d5e, + 0x00000d70, 0x00000d78, 0x00000f2a, 0x00000f33, + 0x00001369, 0x0000137c, 0x000017f0, 0x000017f9, + 0x000019da, 0x000019da, 0x00002070, 0x00002070, + 0x00002074, 0x00002079, 0x00002080, 0x00002089, + 0x00002150, 0x0000215f, 0x00002189, 0x00002189, + 0x00002460, 0x0000249b, 0x000024ea, 0x000024ff, + 0x00002776, 0x00002793, 0x00002cfd, 0x00002cfd, + 0x00003192, 0x00003195, 0x00003220, 0x00003229, + 0x00003248, 0x0000324f, 0x00003251, 0x0000325f, + 0x00003280, 0x00003289, 0x000032b1, 0x000032bf, + 0x0000a830, 0x0000a835, 0x00010107, 0x00010133, + 0x00010175, 0x00010178, 0x0001018a, 0x0001018b, + 0x000102e1, 0x000102fb, 0x00010320, 0x00010323, + 0x00010858, 0x0001085f, 0x00010879, 0x0001087f, + 0x000108a7, 0x000108af, 0x000108fb, 0x000108ff, + 0x00010916, 0x0001091b, 0x000109bc, 0x000109bd, + 0x000109c0, 0x000109cf, 0x000109d2, 0x000109ff, + 0x00010a40, 0x00010a48, 0x00010a7d, 0x00010a7e, + 0x00010a9d, 0x00010a9f, 0x00010aeb, 0x00010aef, + 0x00010b58, 0x00010b5f, 0x00010b78, 0x00010b7f, + 0x00010ba9, 0x00010baf, 0x00010cfa, 0x00010cff, + 0x00010e60, 0x00010e7e, 0x00010f1d, 0x00010f26, + 0x00010f51, 0x00010f54, 0x00010fc5, 0x00010fcb, + 0x00011052, 0x00011065, 0x000111e1, 0x000111f4, + 0x0001173a, 0x0001173b, 0x000118ea, 0x000118f2, + 0x00011c5a, 0x00011c6c, 0x00011fc0, 0x00011fd4, + 0x00016b5b, 0x00016b61, 0x00016e80, 0x00016e96, + 0x0001d2c0, 0x0001d2d3, 0x0001d2e0, 0x0001d2f3, + 0x0001d360, 0x0001d378, 0x0001e8c7, 0x0001e8cf, + 0x0001ec71, 0x0001ecab, 0x0001ecad, 0x0001ecaf, + 0x0001ecb1, 0x0001ecb4, 0x0001ed01, 0x0001ed2d, + 0x0001ed2f, 0x0001ed3d, 0x0001f100, 0x0001f10c, + 0x00000020, 0x00000020, 0x000000a0, 0x000000a0, + 0x00001680, 0x00001680, 0x00002000, 0x0000200a, + 0x0000202f, 0x0000202f, 0x0000205f, 0x0000205f, + 0x00003000, 0x00003000, 0x00002028, 0x00002028, + 0x00002029, 0x00002029, 0x0000d800, 0x0000dfff, + 0x0000e000, 0x0000f8ff, 0x000f0000, 0x000ffffd, + 0x00100000, 0x0010fffd, 0x00000041, 0x0000005a, + 0x000000c0, 0x000000d6, 0x000000d8, 0x000000de, + 0x00000100, 0x00000100, 0x00000102, 0x00000102, + 0x00000104, 0x00000104, 0x00000106, 0x00000106, + 0x00000108, 0x00000108, 0x0000010a, 0x0000010a, + 0x0000010c, 0x0000010c, 0x0000010e, 0x0000010e, + 0x00000110, 0x00000110, 0x00000112, 0x00000112, + 0x00000114, 0x00000114, 0x00000116, 0x00000116, + 0x00000118, 0x00000118, 0x0000011a, 0x0000011a, + 0x0000011c, 0x0000011c, 0x0000011e, 0x0000011e, + 0x00000120, 0x00000120, 0x00000122, 0x00000122, + 0x00000124, 0x00000124, 0x00000126, 0x00000126, + 0x00000128, 0x00000128, 0x0000012a, 0x0000012a, + 0x0000012c, 0x0000012c, 0x0000012e, 0x0000012e, + 0x00000130, 0x00000130, 0x00000132, 0x00000132, + 0x00000134, 0x00000134, 0x00000136, 0x00000136, + 0x00000139, 0x00000139, 0x0000013b, 0x0000013b, + 0x0000013d, 0x0000013d, 0x0000013f, 0x0000013f, + 0x00000141, 0x00000141, 0x00000143, 0x00000143, + 0x00000145, 0x00000145, 0x00000147, 0x00000147, + 0x0000014a, 0x0000014a, 0x0000014c, 0x0000014c, + 0x0000014e, 0x0000014e, 0x00000150, 0x00000150, + 0x00000152, 0x00000152, 0x00000154, 0x00000154, + 0x00000156, 0x00000156, 0x00000158, 0x00000158, + 0x0000015a, 0x0000015a, 0x0000015c, 0x0000015c, + 0x0000015e, 0x0000015e, 0x00000160, 0x00000160, + 0x00000162, 0x00000162, 0x00000164, 0x00000164, + 0x00000166, 0x00000166, 0x00000168, 0x00000168, + 0x0000016a, 0x0000016a, 0x0000016c, 0x0000016c, + 0x0000016e, 0x0000016e, 0x00000170, 0x00000170, + 0x00000172, 0x00000172, 0x00000174, 0x00000174, + 0x00000176, 0x00000176, 0x00000178, 0x00000179, + 0x0000017b, 0x0000017b, 0x0000017d, 0x0000017d, + 0x00000181, 0x00000182, 0x00000184, 0x00000184, + 0x00000186, 0x00000187, 0x00000189, 0x0000018b, + 0x0000018e, 0x00000191, 0x00000193, 0x00000194, + 0x00000196, 0x00000198, 0x0000019c, 0x0000019d, + 0x0000019f, 0x000001a0, 0x000001a2, 0x000001a2, + 0x000001a4, 0x000001a4, 0x000001a6, 0x000001a7, + 0x000001a9, 0x000001a9, 0x000001ac, 0x000001ac, + 0x000001ae, 0x000001af, 0x000001b1, 0x000001b3, + 0x000001b5, 0x000001b5, 0x000001b7, 0x000001b8, + 0x000001bc, 0x000001bc, 0x000001c4, 0x000001c4, + 0x000001c7, 0x000001c7, 0x000001ca, 0x000001ca, + 0x000001cd, 0x000001cd, 0x000001cf, 0x000001cf, + 0x000001d1, 0x000001d1, 0x000001d3, 0x000001d3, + 0x000001d5, 0x000001d5, 0x000001d7, 0x000001d7, + 0x000001d9, 0x000001d9, 0x000001db, 0x000001db, + 0x000001de, 0x000001de, 0x000001e0, 0x000001e0, + 0x000001e2, 0x000001e2, 0x000001e4, 0x000001e4, + 0x000001e6, 0x000001e6, 0x000001e8, 0x000001e8, + 0x000001ea, 0x000001ea, 0x000001ec, 0x000001ec, + 0x000001ee, 0x000001ee, 0x000001f1, 0x000001f1, + 0x000001f4, 0x000001f4, 0x000001f6, 0x000001f8, + 0x000001fa, 0x000001fa, 0x000001fc, 0x000001fc, + 0x000001fe, 0x000001fe, 0x00000200, 0x00000200, + 0x00000202, 0x00000202, 0x00000204, 0x00000204, + 0x00000206, 0x00000206, 0x00000208, 0x00000208, + 0x0000020a, 0x0000020a, 0x0000020c, 0x0000020c, + 0x0000020e, 0x0000020e, 0x00000210, 0x00000210, + 0x00000212, 0x00000212, 0x00000214, 0x00000214, + 0x00000216, 0x00000216, 0x00000218, 0x00000218, + 0x0000021a, 0x0000021a, 0x0000021c, 0x0000021c, + 0x0000021e, 0x0000021e, 0x00000220, 0x00000220, + 0x00000222, 0x00000222, 0x00000224, 0x00000224, + 0x00000226, 0x00000226, 0x00000228, 0x00000228, + 0x0000022a, 0x0000022a, 0x0000022c, 0x0000022c, + 0x0000022e, 0x0000022e, 0x00000230, 0x00000230, + 0x00000232, 0x00000232, 0x0000023a, 0x0000023b, + 0x0000023d, 0x0000023e, 0x00000241, 0x00000241, + 0x00000243, 0x00000246, 0x00000248, 0x00000248, + 0x0000024a, 0x0000024a, 0x0000024c, 0x0000024c, + 0x0000024e, 0x0000024e, 0x00000370, 0x00000370, + 0x00000372, 0x00000372, 0x00000376, 0x00000376, + 0x0000037f, 0x0000037f, 0x00000386, 0x00000386, + 0x00000388, 0x0000038a, 0x0000038c, 0x0000038c, + 0x0000038e, 0x0000038f, 0x00000391, 0x000003a1, + 0x000003a3, 0x000003ab, 0x000003cf, 0x000003cf, + 0x000003d2, 0x000003d4, 0x000003d8, 0x000003d8, + 0x000003da, 0x000003da, 0x000003dc, 0x000003dc, + 0x000003de, 0x000003de, 0x000003e0, 0x000003e0, + 0x000003e2, 0x000003e2, 0x000003e4, 0x000003e4, + 0x000003e6, 0x000003e6, 0x000003e8, 0x000003e8, + 0x000003ea, 0x000003ea, 0x000003ec, 0x000003ec, + 0x000003ee, 0x000003ee, 0x000003f4, 0x000003f4, + 0x000003f7, 0x000003f7, 0x000003f9, 0x000003fa, + 0x000003fd, 0x0000042f, 0x00000460, 0x00000460, + 0x00000462, 0x00000462, 0x00000464, 0x00000464, + 0x00000466, 0x00000466, 0x00000468, 0x00000468, + 0x0000046a, 0x0000046a, 0x0000046c, 0x0000046c, + 0x0000046e, 0x0000046e, 0x00000470, 0x00000470, + 0x00000472, 0x00000472, 0x00000474, 0x00000474, + 0x00000476, 0x00000476, 0x00000478, 0x00000478, + 0x0000047a, 0x0000047a, 0x0000047c, 0x0000047c, + 0x0000047e, 0x0000047e, 0x00000480, 0x00000480, + 0x0000048a, 0x0000048a, 0x0000048c, 0x0000048c, + 0x0000048e, 0x0000048e, 0x00000490, 0x00000490, + 0x00000492, 0x00000492, 0x00000494, 0x00000494, + 0x00000496, 0x00000496, 0x00000498, 0x00000498, + 0x0000049a, 0x0000049a, 0x0000049c, 0x0000049c, + 0x0000049e, 0x0000049e, 0x000004a0, 0x000004a0, + 0x000004a2, 0x000004a2, 0x000004a4, 0x000004a4, + 0x000004a6, 0x000004a6, 0x000004a8, 0x000004a8, + 0x000004aa, 0x000004aa, 0x000004ac, 0x000004ac, + 0x000004ae, 0x000004ae, 0x000004b0, 0x000004b0, + 0x000004b2, 0x000004b2, 0x000004b4, 0x000004b4, + 0x000004b6, 0x000004b6, 0x000004b8, 0x000004b8, + 0x000004ba, 0x000004ba, 0x000004bc, 0x000004bc, + 0x000004be, 0x000004be, 0x000004c0, 0x000004c1, + 0x000004c3, 0x000004c3, 0x000004c5, 0x000004c5, + 0x000004c7, 0x000004c7, 0x000004c9, 0x000004c9, + 0x000004cb, 0x000004cb, 0x000004cd, 0x000004cd, + 0x000004d0, 0x000004d0, 0x000004d2, 0x000004d2, + 0x000004d4, 0x000004d4, 0x000004d6, 0x000004d6, + 0x000004d8, 0x000004d8, 0x000004da, 0x000004da, + 0x000004dc, 0x000004dc, 0x000004de, 0x000004de, + 0x000004e0, 0x000004e0, 0x000004e2, 0x000004e2, + 0x000004e4, 0x000004e4, 0x000004e6, 0x000004e6, + 0x000004e8, 0x000004e8, 0x000004ea, 0x000004ea, + 0x000004ec, 0x000004ec, 0x000004ee, 0x000004ee, + 0x000004f0, 0x000004f0, 0x000004f2, 0x000004f2, + 0x000004f4, 0x000004f4, 0x000004f6, 0x000004f6, + 0x000004f8, 0x000004f8, 0x000004fa, 0x000004fa, + 0x000004fc, 0x000004fc, 0x000004fe, 0x000004fe, + 0x00000500, 0x00000500, 0x00000502, 0x00000502, + 0x00000504, 0x00000504, 0x00000506, 0x00000506, + 0x00000508, 0x00000508, 0x0000050a, 0x0000050a, + 0x0000050c, 0x0000050c, 0x0000050e, 0x0000050e, + 0x00000510, 0x00000510, 0x00000512, 0x00000512, + 0x00000514, 0x00000514, 0x00000516, 0x00000516, + 0x00000518, 0x00000518, 0x0000051a, 0x0000051a, + 0x0000051c, 0x0000051c, 0x0000051e, 0x0000051e, + 0x00000520, 0x00000520, 0x00000522, 0x00000522, + 0x00000524, 0x00000524, 0x00000526, 0x00000526, + 0x00000528, 0x00000528, 0x0000052a, 0x0000052a, + 0x0000052c, 0x0000052c, 0x0000052e, 0x0000052e, + 0x00000531, 0x00000556, 0x000010a0, 0x000010c5, + 0x000010c7, 0x000010c7, 0x000010cd, 0x000010cd, + 0x000013a0, 0x000013f5, 0x00001c89, 0x00001c89, + 0x00001c90, 0x00001cba, 0x00001cbd, 0x00001cbf, + 0x00001e00, 0x00001e00, 0x00001e02, 0x00001e02, + 0x00001e04, 0x00001e04, 0x00001e06, 0x00001e06, + 0x00001e08, 0x00001e08, 0x00001e0a, 0x00001e0a, + 0x00001e0c, 0x00001e0c, 0x00001e0e, 0x00001e0e, + 0x00001e10, 0x00001e10, 0x00001e12, 0x00001e12, + 0x00001e14, 0x00001e14, 0x00001e16, 0x00001e16, + 0x00001e18, 0x00001e18, 0x00001e1a, 0x00001e1a, + 0x00001e1c, 0x00001e1c, 0x00001e1e, 0x00001e1e, + 0x00001e20, 0x00001e20, 0x00001e22, 0x00001e22, + 0x00001e24, 0x00001e24, 0x00001e26, 0x00001e26, + 0x00001e28, 0x00001e28, 0x00001e2a, 0x00001e2a, + 0x00001e2c, 0x00001e2c, 0x00001e2e, 0x00001e2e, + 0x00001e30, 0x00001e30, 0x00001e32, 0x00001e32, + 0x00001e34, 0x00001e34, 0x00001e36, 0x00001e36, + 0x00001e38, 0x00001e38, 0x00001e3a, 0x00001e3a, + 0x00001e3c, 0x00001e3c, 0x00001e3e, 0x00001e3e, + 0x00001e40, 0x00001e40, 0x00001e42, 0x00001e42, + 0x00001e44, 0x00001e44, 0x00001e46, 0x00001e46, + 0x00001e48, 0x00001e48, 0x00001e4a, 0x00001e4a, + 0x00001e4c, 0x00001e4c, 0x00001e4e, 0x00001e4e, + 0x00001e50, 0x00001e50, 0x00001e52, 0x00001e52, + 0x00001e54, 0x00001e54, 0x00001e56, 0x00001e56, + 0x00001e58, 0x00001e58, 0x00001e5a, 0x00001e5a, + 0x00001e5c, 0x00001e5c, 0x00001e5e, 0x00001e5e, + 0x00001e60, 0x00001e60, 0x00001e62, 0x00001e62, + 0x00001e64, 0x00001e64, 0x00001e66, 0x00001e66, + 0x00001e68, 0x00001e68, 0x00001e6a, 0x00001e6a, + 0x00001e6c, 0x00001e6c, 0x00001e6e, 0x00001e6e, + 0x00001e70, 0x00001e70, 0x00001e72, 0x00001e72, + 0x00001e74, 0x00001e74, 0x00001e76, 0x00001e76, + 0x00001e78, 0x00001e78, 0x00001e7a, 0x00001e7a, + 0x00001e7c, 0x00001e7c, 0x00001e7e, 0x00001e7e, + 0x00001e80, 0x00001e80, 0x00001e82, 0x00001e82, + 0x00001e84, 0x00001e84, 0x00001e86, 0x00001e86, + 0x00001e88, 0x00001e88, 0x00001e8a, 0x00001e8a, + 0x00001e8c, 0x00001e8c, 0x00001e8e, 0x00001e8e, + 0x00001e90, 0x00001e90, 0x00001e92, 0x00001e92, + 0x00001e94, 0x00001e94, 0x00001e9e, 0x00001e9e, + 0x00001ea0, 0x00001ea0, 0x00001ea2, 0x00001ea2, + 0x00001ea4, 0x00001ea4, 0x00001ea6, 0x00001ea6, + 0x00001ea8, 0x00001ea8, 0x00001eaa, 0x00001eaa, + 0x00001eac, 0x00001eac, 0x00001eae, 0x00001eae, + 0x00001eb0, 0x00001eb0, 0x00001eb2, 0x00001eb2, + 0x00001eb4, 0x00001eb4, 0x00001eb6, 0x00001eb6, + 0x00001eb8, 0x00001eb8, 0x00001eba, 0x00001eba, + 0x00001ebc, 0x00001ebc, 0x00001ebe, 0x00001ebe, + 0x00001ec0, 0x00001ec0, 0x00001ec2, 0x00001ec2, + 0x00001ec4, 0x00001ec4, 0x00001ec6, 0x00001ec6, + 0x00001ec8, 0x00001ec8, 0x00001eca, 0x00001eca, + 0x00001ecc, 0x00001ecc, 0x00001ece, 0x00001ece, + 0x00001ed0, 0x00001ed0, 0x00001ed2, 0x00001ed2, + 0x00001ed4, 0x00001ed4, 0x00001ed6, 0x00001ed6, + 0x00001ed8, 0x00001ed8, 0x00001eda, 0x00001eda, + 0x00001edc, 0x00001edc, 0x00001ede, 0x00001ede, + 0x00001ee0, 0x00001ee0, 0x00001ee2, 0x00001ee2, + 0x00001ee4, 0x00001ee4, 0x00001ee6, 0x00001ee6, + 0x00001ee8, 0x00001ee8, 0x00001eea, 0x00001eea, + 0x00001eec, 0x00001eec, 0x00001eee, 0x00001eee, + 0x00001ef0, 0x00001ef0, 0x00001ef2, 0x00001ef2, + 0x00001ef4, 0x00001ef4, 0x00001ef6, 0x00001ef6, + 0x00001ef8, 0x00001ef8, 0x00001efa, 0x00001efa, + 0x00001efc, 0x00001efc, 0x00001efe, 0x00001efe, + 0x00001f08, 0x00001f0f, 0x00001f18, 0x00001f1d, + 0x00001f28, 0x00001f2f, 0x00001f38, 0x00001f3f, + 0x00001f48, 0x00001f4d, 0x00001f59, 0x00001f59, + 0x00001f5b, 0x00001f5b, 0x00001f5d, 0x00001f5d, + 0x00001f5f, 0x00001f5f, 0x00001f68, 0x00001f6f, + 0x00001fb8, 0x00001fbb, 0x00001fc8, 0x00001fcb, + 0x00001fd8, 0x00001fdb, 0x00001fe8, 0x00001fec, + 0x00001ff8, 0x00001ffb, 0x00002102, 0x00002102, + 0x00002107, 0x00002107, 0x0000210b, 0x0000210d, + 0x00002110, 0x00002112, 0x00002115, 0x00002115, + 0x00002119, 0x0000211d, 0x00002124, 0x00002124, + 0x00002126, 0x00002126, 0x00002128, 0x00002128, + 0x0000212a, 0x0000212d, 0x00002130, 0x00002133, + 0x0000213e, 0x0000213f, 0x00002145, 0x00002145, + 0x00002183, 0x00002183, 0x00002c00, 0x00002c2f, + 0x00002c60, 0x00002c60, 0x00002c62, 0x00002c64, + 0x00002c67, 0x00002c67, 0x00002c69, 0x00002c69, + 0x00002c6b, 0x00002c6b, 0x00002c6d, 0x00002c70, + 0x00002c72, 0x00002c72, 0x00002c75, 0x00002c75, + 0x00002c7e, 0x00002c80, 0x00002c82, 0x00002c82, + 0x00002c84, 0x00002c84, 0x00002c86, 0x00002c86, + 0x00002c88, 0x00002c88, 0x00002c8a, 0x00002c8a, + 0x00002c8c, 0x00002c8c, 0x00002c8e, 0x00002c8e, + 0x00002c90, 0x00002c90, 0x00002c92, 0x00002c92, + 0x00002c94, 0x00002c94, 0x00002c96, 0x00002c96, + 0x00002c98, 0x00002c98, 0x00002c9a, 0x00002c9a, + 0x00002c9c, 0x00002c9c, 0x00002c9e, 0x00002c9e, + 0x00002ca0, 0x00002ca0, 0x00002ca2, 0x00002ca2, + 0x00002ca4, 0x00002ca4, 0x00002ca6, 0x00002ca6, + 0x00002ca8, 0x00002ca8, 0x00002caa, 0x00002caa, + 0x00002cac, 0x00002cac, 0x00002cae, 0x00002cae, + 0x00002cb0, 0x00002cb0, 0x00002cb2, 0x00002cb2, + 0x00002cb4, 0x00002cb4, 0x00002cb6, 0x00002cb6, + 0x00002cb8, 0x00002cb8, 0x00002cba, 0x00002cba, + 0x00002cbc, 0x00002cbc, 0x00002cbe, 0x00002cbe, + 0x00002cc0, 0x00002cc0, 0x00002cc2, 0x00002cc2, + 0x00002cc4, 0x00002cc4, 0x00002cc6, 0x00002cc6, + 0x00002cc8, 0x00002cc8, 0x00002cca, 0x00002cca, + 0x00002ccc, 0x00002ccc, 0x00002cce, 0x00002cce, + 0x00002cd0, 0x00002cd0, 0x00002cd2, 0x00002cd2, + 0x00002cd4, 0x00002cd4, 0x00002cd6, 0x00002cd6, + 0x00002cd8, 0x00002cd8, 0x00002cda, 0x00002cda, + 0x00002cdc, 0x00002cdc, 0x00002cde, 0x00002cde, + 0x00002ce0, 0x00002ce0, 0x00002ce2, 0x00002ce2, + 0x00002ceb, 0x00002ceb, 0x00002ced, 0x00002ced, + 0x00002cf2, 0x00002cf2, 0x0000a640, 0x0000a640, + 0x0000a642, 0x0000a642, 0x0000a644, 0x0000a644, + 0x0000a646, 0x0000a646, 0x0000a648, 0x0000a648, + 0x0000a64a, 0x0000a64a, 0x0000a64c, 0x0000a64c, + 0x0000a64e, 0x0000a64e, 0x0000a650, 0x0000a650, + 0x0000a652, 0x0000a652, 0x0000a654, 0x0000a654, + 0x0000a656, 0x0000a656, 0x0000a658, 0x0000a658, + 0x0000a65a, 0x0000a65a, 0x0000a65c, 0x0000a65c, + 0x0000a65e, 0x0000a65e, 0x0000a660, 0x0000a660, + 0x0000a662, 0x0000a662, 0x0000a664, 0x0000a664, + 0x0000a666, 0x0000a666, 0x0000a668, 0x0000a668, + 0x0000a66a, 0x0000a66a, 0x0000a66c, 0x0000a66c, + 0x0000a680, 0x0000a680, 0x0000a682, 0x0000a682, + 0x0000a684, 0x0000a684, 0x0000a686, 0x0000a686, + 0x0000a688, 0x0000a688, 0x0000a68a, 0x0000a68a, + 0x0000a68c, 0x0000a68c, 0x0000a68e, 0x0000a68e, + 0x0000a690, 0x0000a690, 0x0000a692, 0x0000a692, + 0x0000a694, 0x0000a694, 0x0000a696, 0x0000a696, + 0x0000a698, 0x0000a698, 0x0000a69a, 0x0000a69a, + 0x0000a722, 0x0000a722, 0x0000a724, 0x0000a724, + 0x0000a726, 0x0000a726, 0x0000a728, 0x0000a728, + 0x0000a72a, 0x0000a72a, 0x0000a72c, 0x0000a72c, + 0x0000a72e, 0x0000a72e, 0x0000a732, 0x0000a732, + 0x0000a734, 0x0000a734, 0x0000a736, 0x0000a736, + 0x0000a738, 0x0000a738, 0x0000a73a, 0x0000a73a, + 0x0000a73c, 0x0000a73c, 0x0000a73e, 0x0000a73e, + 0x0000a740, 0x0000a740, 0x0000a742, 0x0000a742, + 0x0000a744, 0x0000a744, 0x0000a746, 0x0000a746, + 0x0000a748, 0x0000a748, 0x0000a74a, 0x0000a74a, + 0x0000a74c, 0x0000a74c, 0x0000a74e, 0x0000a74e, + 0x0000a750, 0x0000a750, 0x0000a752, 0x0000a752, + 0x0000a754, 0x0000a754, 0x0000a756, 0x0000a756, + 0x0000a758, 0x0000a758, 0x0000a75a, 0x0000a75a, + 0x0000a75c, 0x0000a75c, 0x0000a75e, 0x0000a75e, + 0x0000a760, 0x0000a760, 0x0000a762, 0x0000a762, + 0x0000a764, 0x0000a764, 0x0000a766, 0x0000a766, + 0x0000a768, 0x0000a768, 0x0000a76a, 0x0000a76a, + 0x0000a76c, 0x0000a76c, 0x0000a76e, 0x0000a76e, + 0x0000a779, 0x0000a779, 0x0000a77b, 0x0000a77b, + 0x0000a77d, 0x0000a77e, 0x0000a780, 0x0000a780, + 0x0000a782, 0x0000a782, 0x0000a784, 0x0000a784, + 0x0000a786, 0x0000a786, 0x0000a78b, 0x0000a78b, + 0x0000a78d, 0x0000a78d, 0x0000a790, 0x0000a790, + 0x0000a792, 0x0000a792, 0x0000a796, 0x0000a796, + 0x0000a798, 0x0000a798, 0x0000a79a, 0x0000a79a, + 0x0000a79c, 0x0000a79c, 0x0000a79e, 0x0000a79e, + 0x0000a7a0, 0x0000a7a0, 0x0000a7a2, 0x0000a7a2, + 0x0000a7a4, 0x0000a7a4, 0x0000a7a6, 0x0000a7a6, + 0x0000a7a8, 0x0000a7a8, 0x0000a7aa, 0x0000a7ae, + 0x0000a7b0, 0x0000a7b4, 0x0000a7b6, 0x0000a7b6, + 0x0000a7b8, 0x0000a7b8, 0x0000a7ba, 0x0000a7ba, + 0x0000a7bc, 0x0000a7bc, 0x0000a7be, 0x0000a7be, + 0x0000a7c0, 0x0000a7c0, 0x0000a7c2, 0x0000a7c2, + 0x0000a7c4, 0x0000a7c7, 0x0000a7c9, 0x0000a7c9, + 0x0000a7cb, 0x0000a7cc, 0x0000a7ce, 0x0000a7ce, + 0x0000a7d0, 0x0000a7d0, 0x0000a7d2, 0x0000a7d2, + 0x0000a7d4, 0x0000a7d4, 0x0000a7d6, 0x0000a7d6, 0x0000a7d8, 0x0000a7d8, 0x0000a7da, 0x0000a7da, 0x0000a7dc, 0x0000a7dc, 0x0000a7f5, 0x0000a7f5, 0x0000ff21, 0x0000ff3a, 0x00010400, 0x00010427, @@ -690,326 +698,327 @@ static const unsigned int _ucprop_ranges[] = { 0x0001057c, 0x0001058a, 0x0001058c, 0x00010592, 0x00010594, 0x00010595, 0x00010c80, 0x00010cb2, 0x00010d50, 0x00010d65, 0x000118a0, 0x000118bf, - 0x00016e40, 0x00016e5f, 0x0001d400, 0x0001d419, - 0x0001d434, 0x0001d44d, 0x0001d468, 0x0001d481, - 0x0001d49c, 0x0001d49c, 0x0001d49e, 0x0001d49f, - 0x0001d4a2, 0x0001d4a2, 0x0001d4a5, 0x0001d4a6, - 0x0001d4a9, 0x0001d4ac, 0x0001d4ae, 0x0001d4b5, - 0x0001d4d0, 0x0001d4e9, 0x0001d504, 0x0001d505, - 0x0001d507, 0x0001d50a, 0x0001d50d, 0x0001d514, - 0x0001d516, 0x0001d51c, 0x0001d538, 0x0001d539, - 0x0001d53b, 0x0001d53e, 0x0001d540, 0x0001d544, - 0x0001d546, 0x0001d546, 0x0001d54a, 0x0001d550, - 0x0001d56c, 0x0001d585, 0x0001d5a0, 0x0001d5b9, - 0x0001d5d4, 0x0001d5ed, 0x0001d608, 0x0001d621, - 0x0001d63c, 0x0001d655, 0x0001d670, 0x0001d689, - 0x0001d6a8, 0x0001d6c0, 0x0001d6e2, 0x0001d6fa, - 0x0001d71c, 0x0001d734, 0x0001d756, 0x0001d76e, - 0x0001d790, 0x0001d7a8, 0x0001d7ca, 0x0001d7ca, - 0x0001e900, 0x0001e921, 0x00000061, 0x0000007a, - 0x000000b5, 0x000000b5, 0x000000df, 0x000000f6, - 0x000000f8, 0x000000ff, 0x00000101, 0x00000101, - 0x00000103, 0x00000103, 0x00000105, 0x00000105, - 0x00000107, 0x00000107, 0x00000109, 0x00000109, - 0x0000010b, 0x0000010b, 0x0000010d, 0x0000010d, - 0x0000010f, 0x0000010f, 0x00000111, 0x00000111, - 0x00000113, 0x00000113, 0x00000115, 0x00000115, - 0x00000117, 0x00000117, 0x00000119, 0x00000119, - 0x0000011b, 0x0000011b, 0x0000011d, 0x0000011d, - 0x0000011f, 0x0000011f, 0x00000121, 0x00000121, - 0x00000123, 0x00000123, 0x00000125, 0x00000125, - 0x00000127, 0x00000127, 0x00000129, 0x00000129, - 0x0000012b, 0x0000012b, 0x0000012d, 0x0000012d, - 0x0000012f, 0x0000012f, 0x00000131, 0x00000131, - 0x00000133, 0x00000133, 0x00000135, 0x00000135, - 0x00000137, 0x00000138, 0x0000013a, 0x0000013a, - 0x0000013c, 0x0000013c, 0x0000013e, 0x0000013e, - 0x00000140, 0x00000140, 0x00000142, 0x00000142, - 0x00000144, 0x00000144, 0x00000146, 0x00000146, - 0x00000148, 0x00000149, 0x0000014b, 0x0000014b, - 0x0000014d, 0x0000014d, 0x0000014f, 0x0000014f, - 0x00000151, 0x00000151, 0x00000153, 0x00000153, - 0x00000155, 0x00000155, 0x00000157, 0x00000157, - 0x00000159, 0x00000159, 0x0000015b, 0x0000015b, - 0x0000015d, 0x0000015d, 0x0000015f, 0x0000015f, - 0x00000161, 0x00000161, 0x00000163, 0x00000163, - 0x00000165, 0x00000165, 0x00000167, 0x00000167, - 0x00000169, 0x00000169, 0x0000016b, 0x0000016b, - 0x0000016d, 0x0000016d, 0x0000016f, 0x0000016f, - 0x00000171, 0x00000171, 0x00000173, 0x00000173, - 0x00000175, 0x00000175, 0x00000177, 0x00000177, - 0x0000017a, 0x0000017a, 0x0000017c, 0x0000017c, - 0x0000017e, 0x00000180, 0x00000183, 0x00000183, - 0x00000185, 0x00000185, 0x00000188, 0x00000188, - 0x0000018c, 0x0000018d, 0x00000192, 0x00000192, - 0x00000195, 0x00000195, 0x00000199, 0x0000019b, - 0x0000019e, 0x0000019e, 0x000001a1, 0x000001a1, - 0x000001a3, 0x000001a3, 0x000001a5, 0x000001a5, - 0x000001a8, 0x000001a8, 0x000001aa, 0x000001ab, - 0x000001ad, 0x000001ad, 0x000001b0, 0x000001b0, - 0x000001b4, 0x000001b4, 0x000001b6, 0x000001b6, - 0x000001b9, 0x000001ba, 0x000001bd, 0x000001bf, - 0x000001c6, 0x000001c6, 0x000001c9, 0x000001c9, - 0x000001cc, 0x000001cc, 0x000001ce, 0x000001ce, - 0x000001d0, 0x000001d0, 0x000001d2, 0x000001d2, - 0x000001d4, 0x000001d4, 0x000001d6, 0x000001d6, - 0x000001d8, 0x000001d8, 0x000001da, 0x000001da, - 0x000001dc, 0x000001dd, 0x000001df, 0x000001df, - 0x000001e1, 0x000001e1, 0x000001e3, 0x000001e3, - 0x000001e5, 0x000001e5, 0x000001e7, 0x000001e7, - 0x000001e9, 0x000001e9, 0x000001eb, 0x000001eb, - 0x000001ed, 0x000001ed, 0x000001ef, 0x000001f0, - 0x000001f3, 0x000001f3, 0x000001f5, 0x000001f5, - 0x000001f9, 0x000001f9, 0x000001fb, 0x000001fb, - 0x000001fd, 0x000001fd, 0x000001ff, 0x000001ff, - 0x00000201, 0x00000201, 0x00000203, 0x00000203, - 0x00000205, 0x00000205, 0x00000207, 0x00000207, - 0x00000209, 0x00000209, 0x0000020b, 0x0000020b, - 0x0000020d, 0x0000020d, 0x0000020f, 0x0000020f, - 0x00000211, 0x00000211, 0x00000213, 0x00000213, - 0x00000215, 0x00000215, 0x00000217, 0x00000217, - 0x00000219, 0x00000219, 0x0000021b, 0x0000021b, - 0x0000021d, 0x0000021d, 0x0000021f, 0x0000021f, - 0x00000221, 0x00000221, 0x00000223, 0x00000223, - 0x00000225, 0x00000225, 0x00000227, 0x00000227, - 0x00000229, 0x00000229, 0x0000022b, 0x0000022b, - 0x0000022d, 0x0000022d, 0x0000022f, 0x0000022f, - 0x00000231, 0x00000231, 0x00000233, 0x00000239, - 0x0000023c, 0x0000023c, 0x0000023f, 0x00000240, - 0x00000242, 0x00000242, 0x00000247, 0x00000247, - 0x00000249, 0x00000249, 0x0000024b, 0x0000024b, - 0x0000024d, 0x0000024d, 0x0000024f, 0x00000293, - 0x00000295, 0x000002af, 0x00000371, 0x00000371, - 0x00000373, 0x00000373, 0x00000377, 0x00000377, - 0x0000037b, 0x0000037d, 0x00000390, 0x00000390, - 0x000003ac, 0x000003ce, 0x000003d0, 0x000003d1, - 0x000003d5, 0x000003d7, 0x000003d9, 0x000003d9, - 0x000003db, 0x000003db, 0x000003dd, 0x000003dd, - 0x000003df, 0x000003df, 0x000003e1, 0x000003e1, - 0x000003e3, 0x000003e3, 0x000003e5, 0x000003e5, - 0x000003e7, 0x000003e7, 0x000003e9, 0x000003e9, - 0x000003eb, 0x000003eb, 0x000003ed, 0x000003ed, - 0x000003ef, 0x000003f3, 0x000003f5, 0x000003f5, - 0x000003f8, 0x000003f8, 0x000003fb, 0x000003fc, - 0x00000430, 0x0000045f, 0x00000461, 0x00000461, - 0x00000463, 0x00000463, 0x00000465, 0x00000465, - 0x00000467, 0x00000467, 0x00000469, 0x00000469, - 0x0000046b, 0x0000046b, 0x0000046d, 0x0000046d, - 0x0000046f, 0x0000046f, 0x00000471, 0x00000471, - 0x00000473, 0x00000473, 0x00000475, 0x00000475, - 0x00000477, 0x00000477, 0x00000479, 0x00000479, - 0x0000047b, 0x0000047b, 0x0000047d, 0x0000047d, - 0x0000047f, 0x0000047f, 0x00000481, 0x00000481, - 0x0000048b, 0x0000048b, 0x0000048d, 0x0000048d, - 0x0000048f, 0x0000048f, 0x00000491, 0x00000491, - 0x00000493, 0x00000493, 0x00000495, 0x00000495, - 0x00000497, 0x00000497, 0x00000499, 0x00000499, - 0x0000049b, 0x0000049b, 0x0000049d, 0x0000049d, - 0x0000049f, 0x0000049f, 0x000004a1, 0x000004a1, - 0x000004a3, 0x000004a3, 0x000004a5, 0x000004a5, - 0x000004a7, 0x000004a7, 0x000004a9, 0x000004a9, - 0x000004ab, 0x000004ab, 0x000004ad, 0x000004ad, - 0x000004af, 0x000004af, 0x000004b1, 0x000004b1, - 0x000004b3, 0x000004b3, 0x000004b5, 0x000004b5, - 0x000004b7, 0x000004b7, 0x000004b9, 0x000004b9, - 0x000004bb, 0x000004bb, 0x000004bd, 0x000004bd, - 0x000004bf, 0x000004bf, 0x000004c2, 0x000004c2, - 0x000004c4, 0x000004c4, 0x000004c6, 0x000004c6, - 0x000004c8, 0x000004c8, 0x000004ca, 0x000004ca, - 0x000004cc, 0x000004cc, 0x000004ce, 0x000004cf, - 0x000004d1, 0x000004d1, 0x000004d3, 0x000004d3, - 0x000004d5, 0x000004d5, 0x000004d7, 0x000004d7, - 0x000004d9, 0x000004d9, 0x000004db, 0x000004db, - 0x000004dd, 0x000004dd, 0x000004df, 0x000004df, - 0x000004e1, 0x000004e1, 0x000004e3, 0x000004e3, - 0x000004e5, 0x000004e5, 0x000004e7, 0x000004e7, - 0x000004e9, 0x000004e9, 0x000004eb, 0x000004eb, - 0x000004ed, 0x000004ed, 0x000004ef, 0x000004ef, - 0x000004f1, 0x000004f1, 0x000004f3, 0x000004f3, - 0x000004f5, 0x000004f5, 0x000004f7, 0x000004f7, - 0x000004f9, 0x000004f9, 0x000004fb, 0x000004fb, - 0x000004fd, 0x000004fd, 0x000004ff, 0x000004ff, - 0x00000501, 0x00000501, 0x00000503, 0x00000503, - 0x00000505, 0x00000505, 0x00000507, 0x00000507, - 0x00000509, 0x00000509, 0x0000050b, 0x0000050b, - 0x0000050d, 0x0000050d, 0x0000050f, 0x0000050f, - 0x00000511, 0x00000511, 0x00000513, 0x00000513, - 0x00000515, 0x00000515, 0x00000517, 0x00000517, - 0x00000519, 0x00000519, 0x0000051b, 0x0000051b, - 0x0000051d, 0x0000051d, 0x0000051f, 0x0000051f, - 0x00000521, 0x00000521, 0x00000523, 0x00000523, - 0x00000525, 0x00000525, 0x00000527, 0x00000527, - 0x00000529, 0x00000529, 0x0000052b, 0x0000052b, - 0x0000052d, 0x0000052d, 0x0000052f, 0x0000052f, - 0x00000560, 0x00000588, 0x000010d0, 0x000010fa, - 0x000010fd, 0x000010ff, 0x000013f8, 0x000013fd, - 0x00001c80, 0x00001c88, 0x00001c8a, 0x00001c8a, - 0x00001d00, 0x00001d2b, 0x00001d6b, 0x00001d77, - 0x00001d79, 0x00001d9a, 0x00001e01, 0x00001e01, - 0x00001e03, 0x00001e03, 0x00001e05, 0x00001e05, - 0x00001e07, 0x00001e07, 0x00001e09, 0x00001e09, - 0x00001e0b, 0x00001e0b, 0x00001e0d, 0x00001e0d, - 0x00001e0f, 0x00001e0f, 0x00001e11, 0x00001e11, - 0x00001e13, 0x00001e13, 0x00001e15, 0x00001e15, - 0x00001e17, 0x00001e17, 0x00001e19, 0x00001e19, - 0x00001e1b, 0x00001e1b, 0x00001e1d, 0x00001e1d, - 0x00001e1f, 0x00001e1f, 0x00001e21, 0x00001e21, - 0x00001e23, 0x00001e23, 0x00001e25, 0x00001e25, - 0x00001e27, 0x00001e27, 0x00001e29, 0x00001e29, - 0x00001e2b, 0x00001e2b, 0x00001e2d, 0x00001e2d, - 0x00001e2f, 0x00001e2f, 0x00001e31, 0x00001e31, - 0x00001e33, 0x00001e33, 0x00001e35, 0x00001e35, - 0x00001e37, 0x00001e37, 0x00001e39, 0x00001e39, - 0x00001e3b, 0x00001e3b, 0x00001e3d, 0x00001e3d, - 0x00001e3f, 0x00001e3f, 0x00001e41, 0x00001e41, - 0x00001e43, 0x00001e43, 0x00001e45, 0x00001e45, - 0x00001e47, 0x00001e47, 0x00001e49, 0x00001e49, - 0x00001e4b, 0x00001e4b, 0x00001e4d, 0x00001e4d, - 0x00001e4f, 0x00001e4f, 0x00001e51, 0x00001e51, - 0x00001e53, 0x00001e53, 0x00001e55, 0x00001e55, - 0x00001e57, 0x00001e57, 0x00001e59, 0x00001e59, - 0x00001e5b, 0x00001e5b, 0x00001e5d, 0x00001e5d, - 0x00001e5f, 0x00001e5f, 0x00001e61, 0x00001e61, - 0x00001e63, 0x00001e63, 0x00001e65, 0x00001e65, - 0x00001e67, 0x00001e67, 0x00001e69, 0x00001e69, - 0x00001e6b, 0x00001e6b, 0x00001e6d, 0x00001e6d, - 0x00001e6f, 0x00001e6f, 0x00001e71, 0x00001e71, - 0x00001e73, 0x00001e73, 0x00001e75, 0x00001e75, - 0x00001e77, 0x00001e77, 0x00001e79, 0x00001e79, - 0x00001e7b, 0x00001e7b, 0x00001e7d, 0x00001e7d, - 0x00001e7f, 0x00001e7f, 0x00001e81, 0x00001e81, - 0x00001e83, 0x00001e83, 0x00001e85, 0x00001e85, - 0x00001e87, 0x00001e87, 0x00001e89, 0x00001e89, - 0x00001e8b, 0x00001e8b, 0x00001e8d, 0x00001e8d, - 0x00001e8f, 0x00001e8f, 0x00001e91, 0x00001e91, - 0x00001e93, 0x00001e93, 0x00001e95, 0x00001e9d, - 0x00001e9f, 0x00001e9f, 0x00001ea1, 0x00001ea1, - 0x00001ea3, 0x00001ea3, 0x00001ea5, 0x00001ea5, - 0x00001ea7, 0x00001ea7, 0x00001ea9, 0x00001ea9, - 0x00001eab, 0x00001eab, 0x00001ead, 0x00001ead, - 0x00001eaf, 0x00001eaf, 0x00001eb1, 0x00001eb1, - 0x00001eb3, 0x00001eb3, 0x00001eb5, 0x00001eb5, - 0x00001eb7, 0x00001eb7, 0x00001eb9, 0x00001eb9, - 0x00001ebb, 0x00001ebb, 0x00001ebd, 0x00001ebd, - 0x00001ebf, 0x00001ebf, 0x00001ec1, 0x00001ec1, - 0x00001ec3, 0x00001ec3, 0x00001ec5, 0x00001ec5, - 0x00001ec7, 0x00001ec7, 0x00001ec9, 0x00001ec9, - 0x00001ecb, 0x00001ecb, 0x00001ecd, 0x00001ecd, - 0x00001ecf, 0x00001ecf, 0x00001ed1, 0x00001ed1, - 0x00001ed3, 0x00001ed3, 0x00001ed5, 0x00001ed5, - 0x00001ed7, 0x00001ed7, 0x00001ed9, 0x00001ed9, - 0x00001edb, 0x00001edb, 0x00001edd, 0x00001edd, - 0x00001edf, 0x00001edf, 0x00001ee1, 0x00001ee1, - 0x00001ee3, 0x00001ee3, 0x00001ee5, 0x00001ee5, - 0x00001ee7, 0x00001ee7, 0x00001ee9, 0x00001ee9, - 0x00001eeb, 0x00001eeb, 0x00001eed, 0x00001eed, - 0x00001eef, 0x00001eef, 0x00001ef1, 0x00001ef1, - 0x00001ef3, 0x00001ef3, 0x00001ef5, 0x00001ef5, - 0x00001ef7, 0x00001ef7, 0x00001ef9, 0x00001ef9, - 0x00001efb, 0x00001efb, 0x00001efd, 0x00001efd, - 0x00001eff, 0x00001f07, 0x00001f10, 0x00001f15, - 0x00001f20, 0x00001f27, 0x00001f30, 0x00001f37, - 0x00001f40, 0x00001f45, 0x00001f50, 0x00001f57, - 0x00001f60, 0x00001f67, 0x00001f70, 0x00001f7d, - 0x00001f80, 0x00001f87, 0x00001f90, 0x00001f97, - 0x00001fa0, 0x00001fa7, 0x00001fb0, 0x00001fb4, - 0x00001fb6, 0x00001fb7, 0x00001fbe, 0x00001fbe, - 0x00001fc2, 0x00001fc4, 0x00001fc6, 0x00001fc7, - 0x00001fd0, 0x00001fd3, 0x00001fd6, 0x00001fd7, - 0x00001fe0, 0x00001fe7, 0x00001ff2, 0x00001ff4, - 0x00001ff6, 0x00001ff7, 0x0000210a, 0x0000210a, - 0x0000210e, 0x0000210f, 0x00002113, 0x00002113, - 0x0000212f, 0x0000212f, 0x00002134, 0x00002134, - 0x00002139, 0x00002139, 0x0000213c, 0x0000213d, - 0x00002146, 0x00002149, 0x0000214e, 0x0000214e, - 0x00002184, 0x00002184, 0x00002c30, 0x00002c5f, - 0x00002c61, 0x00002c61, 0x00002c65, 0x00002c66, - 0x00002c68, 0x00002c68, 0x00002c6a, 0x00002c6a, - 0x00002c6c, 0x00002c6c, 0x00002c71, 0x00002c71, - 0x00002c73, 0x00002c74, 0x00002c76, 0x00002c7b, - 0x00002c81, 0x00002c81, 0x00002c83, 0x00002c83, - 0x00002c85, 0x00002c85, 0x00002c87, 0x00002c87, - 0x00002c89, 0x00002c89, 0x00002c8b, 0x00002c8b, - 0x00002c8d, 0x00002c8d, 0x00002c8f, 0x00002c8f, - 0x00002c91, 0x00002c91, 0x00002c93, 0x00002c93, - 0x00002c95, 0x00002c95, 0x00002c97, 0x00002c97, - 0x00002c99, 0x00002c99, 0x00002c9b, 0x00002c9b, - 0x00002c9d, 0x00002c9d, 0x00002c9f, 0x00002c9f, - 0x00002ca1, 0x00002ca1, 0x00002ca3, 0x00002ca3, - 0x00002ca5, 0x00002ca5, 0x00002ca7, 0x00002ca7, - 0x00002ca9, 0x00002ca9, 0x00002cab, 0x00002cab, - 0x00002cad, 0x00002cad, 0x00002caf, 0x00002caf, - 0x00002cb1, 0x00002cb1, 0x00002cb3, 0x00002cb3, - 0x00002cb5, 0x00002cb5, 0x00002cb7, 0x00002cb7, - 0x00002cb9, 0x00002cb9, 0x00002cbb, 0x00002cbb, - 0x00002cbd, 0x00002cbd, 0x00002cbf, 0x00002cbf, - 0x00002cc1, 0x00002cc1, 0x00002cc3, 0x00002cc3, - 0x00002cc5, 0x00002cc5, 0x00002cc7, 0x00002cc7, - 0x00002cc9, 0x00002cc9, 0x00002ccb, 0x00002ccb, - 0x00002ccd, 0x00002ccd, 0x00002ccf, 0x00002ccf, - 0x00002cd1, 0x00002cd1, 0x00002cd3, 0x00002cd3, - 0x00002cd5, 0x00002cd5, 0x00002cd7, 0x00002cd7, - 0x00002cd9, 0x00002cd9, 0x00002cdb, 0x00002cdb, - 0x00002cdd, 0x00002cdd, 0x00002cdf, 0x00002cdf, - 0x00002ce1, 0x00002ce1, 0x00002ce3, 0x00002ce4, - 0x00002cec, 0x00002cec, 0x00002cee, 0x00002cee, - 0x00002cf3, 0x00002cf3, 0x00002d00, 0x00002d25, - 0x00002d27, 0x00002d27, 0x00002d2d, 0x00002d2d, - 0x0000a641, 0x0000a641, 0x0000a643, 0x0000a643, - 0x0000a645, 0x0000a645, 0x0000a647, 0x0000a647, - 0x0000a649, 0x0000a649, 0x0000a64b, 0x0000a64b, - 0x0000a64d, 0x0000a64d, 0x0000a64f, 0x0000a64f, - 0x0000a651, 0x0000a651, 0x0000a653, 0x0000a653, - 0x0000a655, 0x0000a655, 0x0000a657, 0x0000a657, - 0x0000a659, 0x0000a659, 0x0000a65b, 0x0000a65b, - 0x0000a65d, 0x0000a65d, 0x0000a65f, 0x0000a65f, - 0x0000a661, 0x0000a661, 0x0000a663, 0x0000a663, - 0x0000a665, 0x0000a665, 0x0000a667, 0x0000a667, - 0x0000a669, 0x0000a669, 0x0000a66b, 0x0000a66b, - 0x0000a66d, 0x0000a66d, 0x0000a681, 0x0000a681, - 0x0000a683, 0x0000a683, 0x0000a685, 0x0000a685, - 0x0000a687, 0x0000a687, 0x0000a689, 0x0000a689, - 0x0000a68b, 0x0000a68b, 0x0000a68d, 0x0000a68d, - 0x0000a68f, 0x0000a68f, 0x0000a691, 0x0000a691, - 0x0000a693, 0x0000a693, 0x0000a695, 0x0000a695, - 0x0000a697, 0x0000a697, 0x0000a699, 0x0000a699, - 0x0000a69b, 0x0000a69b, 0x0000a723, 0x0000a723, - 0x0000a725, 0x0000a725, 0x0000a727, 0x0000a727, - 0x0000a729, 0x0000a729, 0x0000a72b, 0x0000a72b, - 0x0000a72d, 0x0000a72d, 0x0000a72f, 0x0000a731, - 0x0000a733, 0x0000a733, 0x0000a735, 0x0000a735, - 0x0000a737, 0x0000a737, 0x0000a739, 0x0000a739, - 0x0000a73b, 0x0000a73b, 0x0000a73d, 0x0000a73d, - 0x0000a73f, 0x0000a73f, 0x0000a741, 0x0000a741, - 0x0000a743, 0x0000a743, 0x0000a745, 0x0000a745, - 0x0000a747, 0x0000a747, 0x0000a749, 0x0000a749, - 0x0000a74b, 0x0000a74b, 0x0000a74d, 0x0000a74d, - 0x0000a74f, 0x0000a74f, 0x0000a751, 0x0000a751, - 0x0000a753, 0x0000a753, 0x0000a755, 0x0000a755, - 0x0000a757, 0x0000a757, 0x0000a759, 0x0000a759, - 0x0000a75b, 0x0000a75b, 0x0000a75d, 0x0000a75d, - 0x0000a75f, 0x0000a75f, 0x0000a761, 0x0000a761, - 0x0000a763, 0x0000a763, 0x0000a765, 0x0000a765, - 0x0000a767, 0x0000a767, 0x0000a769, 0x0000a769, - 0x0000a76b, 0x0000a76b, 0x0000a76d, 0x0000a76d, - 0x0000a76f, 0x0000a76f, 0x0000a771, 0x0000a778, - 0x0000a77a, 0x0000a77a, 0x0000a77c, 0x0000a77c, - 0x0000a77f, 0x0000a77f, 0x0000a781, 0x0000a781, - 0x0000a783, 0x0000a783, 0x0000a785, 0x0000a785, - 0x0000a787, 0x0000a787, 0x0000a78c, 0x0000a78c, - 0x0000a78e, 0x0000a78e, 0x0000a791, 0x0000a791, - 0x0000a793, 0x0000a795, 0x0000a797, 0x0000a797, - 0x0000a799, 0x0000a799, 0x0000a79b, 0x0000a79b, - 0x0000a79d, 0x0000a79d, 0x0000a79f, 0x0000a79f, - 0x0000a7a1, 0x0000a7a1, 0x0000a7a3, 0x0000a7a3, - 0x0000a7a5, 0x0000a7a5, 0x0000a7a7, 0x0000a7a7, - 0x0000a7a9, 0x0000a7a9, 0x0000a7af, 0x0000a7af, - 0x0000a7b5, 0x0000a7b5, 0x0000a7b7, 0x0000a7b7, - 0x0000a7b9, 0x0000a7b9, 0x0000a7bb, 0x0000a7bb, - 0x0000a7bd, 0x0000a7bd, 0x0000a7bf, 0x0000a7bf, - 0x0000a7c1, 0x0000a7c1, 0x0000a7c3, 0x0000a7c3, - 0x0000a7c8, 0x0000a7c8, 0x0000a7ca, 0x0000a7ca, - 0x0000a7cd, 0x0000a7cd, 0x0000a7d1, 0x0000a7d1, + 0x00016e40, 0x00016e5f, 0x00016ea0, 0x00016eb8, + 0x0001d400, 0x0001d419, 0x0001d434, 0x0001d44d, + 0x0001d468, 0x0001d481, 0x0001d49c, 0x0001d49c, + 0x0001d49e, 0x0001d49f, 0x0001d4a2, 0x0001d4a2, + 0x0001d4a5, 0x0001d4a6, 0x0001d4a9, 0x0001d4ac, + 0x0001d4ae, 0x0001d4b5, 0x0001d4d0, 0x0001d4e9, + 0x0001d504, 0x0001d505, 0x0001d507, 0x0001d50a, + 0x0001d50d, 0x0001d514, 0x0001d516, 0x0001d51c, + 0x0001d538, 0x0001d539, 0x0001d53b, 0x0001d53e, + 0x0001d540, 0x0001d544, 0x0001d546, 0x0001d546, + 0x0001d54a, 0x0001d550, 0x0001d56c, 0x0001d585, + 0x0001d5a0, 0x0001d5b9, 0x0001d5d4, 0x0001d5ed, + 0x0001d608, 0x0001d621, 0x0001d63c, 0x0001d655, + 0x0001d670, 0x0001d689, 0x0001d6a8, 0x0001d6c0, + 0x0001d6e2, 0x0001d6fa, 0x0001d71c, 0x0001d734, + 0x0001d756, 0x0001d76e, 0x0001d790, 0x0001d7a8, + 0x0001d7ca, 0x0001d7ca, 0x0001e900, 0x0001e921, + 0x00000061, 0x0000007a, 0x000000b5, 0x000000b5, + 0x000000df, 0x000000f6, 0x000000f8, 0x000000ff, + 0x00000101, 0x00000101, 0x00000103, 0x00000103, + 0x00000105, 0x00000105, 0x00000107, 0x00000107, + 0x00000109, 0x00000109, 0x0000010b, 0x0000010b, + 0x0000010d, 0x0000010d, 0x0000010f, 0x0000010f, + 0x00000111, 0x00000111, 0x00000113, 0x00000113, + 0x00000115, 0x00000115, 0x00000117, 0x00000117, + 0x00000119, 0x00000119, 0x0000011b, 0x0000011b, + 0x0000011d, 0x0000011d, 0x0000011f, 0x0000011f, + 0x00000121, 0x00000121, 0x00000123, 0x00000123, + 0x00000125, 0x00000125, 0x00000127, 0x00000127, + 0x00000129, 0x00000129, 0x0000012b, 0x0000012b, + 0x0000012d, 0x0000012d, 0x0000012f, 0x0000012f, + 0x00000131, 0x00000131, 0x00000133, 0x00000133, + 0x00000135, 0x00000135, 0x00000137, 0x00000138, + 0x0000013a, 0x0000013a, 0x0000013c, 0x0000013c, + 0x0000013e, 0x0000013e, 0x00000140, 0x00000140, + 0x00000142, 0x00000142, 0x00000144, 0x00000144, + 0x00000146, 0x00000146, 0x00000148, 0x00000149, + 0x0000014b, 0x0000014b, 0x0000014d, 0x0000014d, + 0x0000014f, 0x0000014f, 0x00000151, 0x00000151, + 0x00000153, 0x00000153, 0x00000155, 0x00000155, + 0x00000157, 0x00000157, 0x00000159, 0x00000159, + 0x0000015b, 0x0000015b, 0x0000015d, 0x0000015d, + 0x0000015f, 0x0000015f, 0x00000161, 0x00000161, + 0x00000163, 0x00000163, 0x00000165, 0x00000165, + 0x00000167, 0x00000167, 0x00000169, 0x00000169, + 0x0000016b, 0x0000016b, 0x0000016d, 0x0000016d, + 0x0000016f, 0x0000016f, 0x00000171, 0x00000171, + 0x00000173, 0x00000173, 0x00000175, 0x00000175, + 0x00000177, 0x00000177, 0x0000017a, 0x0000017a, + 0x0000017c, 0x0000017c, 0x0000017e, 0x00000180, + 0x00000183, 0x00000183, 0x00000185, 0x00000185, + 0x00000188, 0x00000188, 0x0000018c, 0x0000018d, + 0x00000192, 0x00000192, 0x00000195, 0x00000195, + 0x00000199, 0x0000019b, 0x0000019e, 0x0000019e, + 0x000001a1, 0x000001a1, 0x000001a3, 0x000001a3, + 0x000001a5, 0x000001a5, 0x000001a8, 0x000001a8, + 0x000001aa, 0x000001ab, 0x000001ad, 0x000001ad, + 0x000001b0, 0x000001b0, 0x000001b4, 0x000001b4, + 0x000001b6, 0x000001b6, 0x000001b9, 0x000001ba, + 0x000001bd, 0x000001bf, 0x000001c6, 0x000001c6, + 0x000001c9, 0x000001c9, 0x000001cc, 0x000001cc, + 0x000001ce, 0x000001ce, 0x000001d0, 0x000001d0, + 0x000001d2, 0x000001d2, 0x000001d4, 0x000001d4, + 0x000001d6, 0x000001d6, 0x000001d8, 0x000001d8, + 0x000001da, 0x000001da, 0x000001dc, 0x000001dd, + 0x000001df, 0x000001df, 0x000001e1, 0x000001e1, + 0x000001e3, 0x000001e3, 0x000001e5, 0x000001e5, + 0x000001e7, 0x000001e7, 0x000001e9, 0x000001e9, + 0x000001eb, 0x000001eb, 0x000001ed, 0x000001ed, + 0x000001ef, 0x000001f0, 0x000001f3, 0x000001f3, + 0x000001f5, 0x000001f5, 0x000001f9, 0x000001f9, + 0x000001fb, 0x000001fb, 0x000001fd, 0x000001fd, + 0x000001ff, 0x000001ff, 0x00000201, 0x00000201, + 0x00000203, 0x00000203, 0x00000205, 0x00000205, + 0x00000207, 0x00000207, 0x00000209, 0x00000209, + 0x0000020b, 0x0000020b, 0x0000020d, 0x0000020d, + 0x0000020f, 0x0000020f, 0x00000211, 0x00000211, + 0x00000213, 0x00000213, 0x00000215, 0x00000215, + 0x00000217, 0x00000217, 0x00000219, 0x00000219, + 0x0000021b, 0x0000021b, 0x0000021d, 0x0000021d, + 0x0000021f, 0x0000021f, 0x00000221, 0x00000221, + 0x00000223, 0x00000223, 0x00000225, 0x00000225, + 0x00000227, 0x00000227, 0x00000229, 0x00000229, + 0x0000022b, 0x0000022b, 0x0000022d, 0x0000022d, + 0x0000022f, 0x0000022f, 0x00000231, 0x00000231, + 0x00000233, 0x00000239, 0x0000023c, 0x0000023c, + 0x0000023f, 0x00000240, 0x00000242, 0x00000242, + 0x00000247, 0x00000247, 0x00000249, 0x00000249, + 0x0000024b, 0x0000024b, 0x0000024d, 0x0000024d, + 0x0000024f, 0x00000293, 0x00000296, 0x000002af, + 0x00000371, 0x00000371, 0x00000373, 0x00000373, + 0x00000377, 0x00000377, 0x0000037b, 0x0000037d, + 0x00000390, 0x00000390, 0x000003ac, 0x000003ce, + 0x000003d0, 0x000003d1, 0x000003d5, 0x000003d7, + 0x000003d9, 0x000003d9, 0x000003db, 0x000003db, + 0x000003dd, 0x000003dd, 0x000003df, 0x000003df, + 0x000003e1, 0x000003e1, 0x000003e3, 0x000003e3, + 0x000003e5, 0x000003e5, 0x000003e7, 0x000003e7, + 0x000003e9, 0x000003e9, 0x000003eb, 0x000003eb, + 0x000003ed, 0x000003ed, 0x000003ef, 0x000003f3, + 0x000003f5, 0x000003f5, 0x000003f8, 0x000003f8, + 0x000003fb, 0x000003fc, 0x00000430, 0x0000045f, + 0x00000461, 0x00000461, 0x00000463, 0x00000463, + 0x00000465, 0x00000465, 0x00000467, 0x00000467, + 0x00000469, 0x00000469, 0x0000046b, 0x0000046b, + 0x0000046d, 0x0000046d, 0x0000046f, 0x0000046f, + 0x00000471, 0x00000471, 0x00000473, 0x00000473, + 0x00000475, 0x00000475, 0x00000477, 0x00000477, + 0x00000479, 0x00000479, 0x0000047b, 0x0000047b, + 0x0000047d, 0x0000047d, 0x0000047f, 0x0000047f, + 0x00000481, 0x00000481, 0x0000048b, 0x0000048b, + 0x0000048d, 0x0000048d, 0x0000048f, 0x0000048f, + 0x00000491, 0x00000491, 0x00000493, 0x00000493, + 0x00000495, 0x00000495, 0x00000497, 0x00000497, + 0x00000499, 0x00000499, 0x0000049b, 0x0000049b, + 0x0000049d, 0x0000049d, 0x0000049f, 0x0000049f, + 0x000004a1, 0x000004a1, 0x000004a3, 0x000004a3, + 0x000004a5, 0x000004a5, 0x000004a7, 0x000004a7, + 0x000004a9, 0x000004a9, 0x000004ab, 0x000004ab, + 0x000004ad, 0x000004ad, 0x000004af, 0x000004af, + 0x000004b1, 0x000004b1, 0x000004b3, 0x000004b3, + 0x000004b5, 0x000004b5, 0x000004b7, 0x000004b7, + 0x000004b9, 0x000004b9, 0x000004bb, 0x000004bb, + 0x000004bd, 0x000004bd, 0x000004bf, 0x000004bf, + 0x000004c2, 0x000004c2, 0x000004c4, 0x000004c4, + 0x000004c6, 0x000004c6, 0x000004c8, 0x000004c8, + 0x000004ca, 0x000004ca, 0x000004cc, 0x000004cc, + 0x000004ce, 0x000004cf, 0x000004d1, 0x000004d1, + 0x000004d3, 0x000004d3, 0x000004d5, 0x000004d5, + 0x000004d7, 0x000004d7, 0x000004d9, 0x000004d9, + 0x000004db, 0x000004db, 0x000004dd, 0x000004dd, + 0x000004df, 0x000004df, 0x000004e1, 0x000004e1, + 0x000004e3, 0x000004e3, 0x000004e5, 0x000004e5, + 0x000004e7, 0x000004e7, 0x000004e9, 0x000004e9, + 0x000004eb, 0x000004eb, 0x000004ed, 0x000004ed, + 0x000004ef, 0x000004ef, 0x000004f1, 0x000004f1, + 0x000004f3, 0x000004f3, 0x000004f5, 0x000004f5, + 0x000004f7, 0x000004f7, 0x000004f9, 0x000004f9, + 0x000004fb, 0x000004fb, 0x000004fd, 0x000004fd, + 0x000004ff, 0x000004ff, 0x00000501, 0x00000501, + 0x00000503, 0x00000503, 0x00000505, 0x00000505, + 0x00000507, 0x00000507, 0x00000509, 0x00000509, + 0x0000050b, 0x0000050b, 0x0000050d, 0x0000050d, + 0x0000050f, 0x0000050f, 0x00000511, 0x00000511, + 0x00000513, 0x00000513, 0x00000515, 0x00000515, + 0x00000517, 0x00000517, 0x00000519, 0x00000519, + 0x0000051b, 0x0000051b, 0x0000051d, 0x0000051d, + 0x0000051f, 0x0000051f, 0x00000521, 0x00000521, + 0x00000523, 0x00000523, 0x00000525, 0x00000525, + 0x00000527, 0x00000527, 0x00000529, 0x00000529, + 0x0000052b, 0x0000052b, 0x0000052d, 0x0000052d, + 0x0000052f, 0x0000052f, 0x00000560, 0x00000588, + 0x000010d0, 0x000010fa, 0x000010fd, 0x000010ff, + 0x000013f8, 0x000013fd, 0x00001c80, 0x00001c88, + 0x00001c8a, 0x00001c8a, 0x00001d00, 0x00001d2b, + 0x00001d6b, 0x00001d77, 0x00001d79, 0x00001d9a, + 0x00001e01, 0x00001e01, 0x00001e03, 0x00001e03, + 0x00001e05, 0x00001e05, 0x00001e07, 0x00001e07, + 0x00001e09, 0x00001e09, 0x00001e0b, 0x00001e0b, + 0x00001e0d, 0x00001e0d, 0x00001e0f, 0x00001e0f, + 0x00001e11, 0x00001e11, 0x00001e13, 0x00001e13, + 0x00001e15, 0x00001e15, 0x00001e17, 0x00001e17, + 0x00001e19, 0x00001e19, 0x00001e1b, 0x00001e1b, + 0x00001e1d, 0x00001e1d, 0x00001e1f, 0x00001e1f, + 0x00001e21, 0x00001e21, 0x00001e23, 0x00001e23, + 0x00001e25, 0x00001e25, 0x00001e27, 0x00001e27, + 0x00001e29, 0x00001e29, 0x00001e2b, 0x00001e2b, + 0x00001e2d, 0x00001e2d, 0x00001e2f, 0x00001e2f, + 0x00001e31, 0x00001e31, 0x00001e33, 0x00001e33, + 0x00001e35, 0x00001e35, 0x00001e37, 0x00001e37, + 0x00001e39, 0x00001e39, 0x00001e3b, 0x00001e3b, + 0x00001e3d, 0x00001e3d, 0x00001e3f, 0x00001e3f, + 0x00001e41, 0x00001e41, 0x00001e43, 0x00001e43, + 0x00001e45, 0x00001e45, 0x00001e47, 0x00001e47, + 0x00001e49, 0x00001e49, 0x00001e4b, 0x00001e4b, + 0x00001e4d, 0x00001e4d, 0x00001e4f, 0x00001e4f, + 0x00001e51, 0x00001e51, 0x00001e53, 0x00001e53, + 0x00001e55, 0x00001e55, 0x00001e57, 0x00001e57, + 0x00001e59, 0x00001e59, 0x00001e5b, 0x00001e5b, + 0x00001e5d, 0x00001e5d, 0x00001e5f, 0x00001e5f, + 0x00001e61, 0x00001e61, 0x00001e63, 0x00001e63, + 0x00001e65, 0x00001e65, 0x00001e67, 0x00001e67, + 0x00001e69, 0x00001e69, 0x00001e6b, 0x00001e6b, + 0x00001e6d, 0x00001e6d, 0x00001e6f, 0x00001e6f, + 0x00001e71, 0x00001e71, 0x00001e73, 0x00001e73, + 0x00001e75, 0x00001e75, 0x00001e77, 0x00001e77, + 0x00001e79, 0x00001e79, 0x00001e7b, 0x00001e7b, + 0x00001e7d, 0x00001e7d, 0x00001e7f, 0x00001e7f, + 0x00001e81, 0x00001e81, 0x00001e83, 0x00001e83, + 0x00001e85, 0x00001e85, 0x00001e87, 0x00001e87, + 0x00001e89, 0x00001e89, 0x00001e8b, 0x00001e8b, + 0x00001e8d, 0x00001e8d, 0x00001e8f, 0x00001e8f, + 0x00001e91, 0x00001e91, 0x00001e93, 0x00001e93, + 0x00001e95, 0x00001e9d, 0x00001e9f, 0x00001e9f, + 0x00001ea1, 0x00001ea1, 0x00001ea3, 0x00001ea3, + 0x00001ea5, 0x00001ea5, 0x00001ea7, 0x00001ea7, + 0x00001ea9, 0x00001ea9, 0x00001eab, 0x00001eab, + 0x00001ead, 0x00001ead, 0x00001eaf, 0x00001eaf, + 0x00001eb1, 0x00001eb1, 0x00001eb3, 0x00001eb3, + 0x00001eb5, 0x00001eb5, 0x00001eb7, 0x00001eb7, + 0x00001eb9, 0x00001eb9, 0x00001ebb, 0x00001ebb, + 0x00001ebd, 0x00001ebd, 0x00001ebf, 0x00001ebf, + 0x00001ec1, 0x00001ec1, 0x00001ec3, 0x00001ec3, + 0x00001ec5, 0x00001ec5, 0x00001ec7, 0x00001ec7, + 0x00001ec9, 0x00001ec9, 0x00001ecb, 0x00001ecb, + 0x00001ecd, 0x00001ecd, 0x00001ecf, 0x00001ecf, + 0x00001ed1, 0x00001ed1, 0x00001ed3, 0x00001ed3, + 0x00001ed5, 0x00001ed5, 0x00001ed7, 0x00001ed7, + 0x00001ed9, 0x00001ed9, 0x00001edb, 0x00001edb, + 0x00001edd, 0x00001edd, 0x00001edf, 0x00001edf, + 0x00001ee1, 0x00001ee1, 0x00001ee3, 0x00001ee3, + 0x00001ee5, 0x00001ee5, 0x00001ee7, 0x00001ee7, + 0x00001ee9, 0x00001ee9, 0x00001eeb, 0x00001eeb, + 0x00001eed, 0x00001eed, 0x00001eef, 0x00001eef, + 0x00001ef1, 0x00001ef1, 0x00001ef3, 0x00001ef3, + 0x00001ef5, 0x00001ef5, 0x00001ef7, 0x00001ef7, + 0x00001ef9, 0x00001ef9, 0x00001efb, 0x00001efb, + 0x00001efd, 0x00001efd, 0x00001eff, 0x00001f07, + 0x00001f10, 0x00001f15, 0x00001f20, 0x00001f27, + 0x00001f30, 0x00001f37, 0x00001f40, 0x00001f45, + 0x00001f50, 0x00001f57, 0x00001f60, 0x00001f67, + 0x00001f70, 0x00001f7d, 0x00001f80, 0x00001f87, + 0x00001f90, 0x00001f97, 0x00001fa0, 0x00001fa7, + 0x00001fb0, 0x00001fb4, 0x00001fb6, 0x00001fb7, + 0x00001fbe, 0x00001fbe, 0x00001fc2, 0x00001fc4, + 0x00001fc6, 0x00001fc7, 0x00001fd0, 0x00001fd3, + 0x00001fd6, 0x00001fd7, 0x00001fe0, 0x00001fe7, + 0x00001ff2, 0x00001ff4, 0x00001ff6, 0x00001ff7, + 0x0000210a, 0x0000210a, 0x0000210e, 0x0000210f, + 0x00002113, 0x00002113, 0x0000212f, 0x0000212f, + 0x00002134, 0x00002134, 0x00002139, 0x00002139, + 0x0000213c, 0x0000213d, 0x00002146, 0x00002149, + 0x0000214e, 0x0000214e, 0x00002184, 0x00002184, + 0x00002c30, 0x00002c5f, 0x00002c61, 0x00002c61, + 0x00002c65, 0x00002c66, 0x00002c68, 0x00002c68, + 0x00002c6a, 0x00002c6a, 0x00002c6c, 0x00002c6c, + 0x00002c71, 0x00002c71, 0x00002c73, 0x00002c74, + 0x00002c76, 0x00002c7b, 0x00002c81, 0x00002c81, + 0x00002c83, 0x00002c83, 0x00002c85, 0x00002c85, + 0x00002c87, 0x00002c87, 0x00002c89, 0x00002c89, + 0x00002c8b, 0x00002c8b, 0x00002c8d, 0x00002c8d, + 0x00002c8f, 0x00002c8f, 0x00002c91, 0x00002c91, + 0x00002c93, 0x00002c93, 0x00002c95, 0x00002c95, + 0x00002c97, 0x00002c97, 0x00002c99, 0x00002c99, + 0x00002c9b, 0x00002c9b, 0x00002c9d, 0x00002c9d, + 0x00002c9f, 0x00002c9f, 0x00002ca1, 0x00002ca1, + 0x00002ca3, 0x00002ca3, 0x00002ca5, 0x00002ca5, + 0x00002ca7, 0x00002ca7, 0x00002ca9, 0x00002ca9, + 0x00002cab, 0x00002cab, 0x00002cad, 0x00002cad, + 0x00002caf, 0x00002caf, 0x00002cb1, 0x00002cb1, + 0x00002cb3, 0x00002cb3, 0x00002cb5, 0x00002cb5, + 0x00002cb7, 0x00002cb7, 0x00002cb9, 0x00002cb9, + 0x00002cbb, 0x00002cbb, 0x00002cbd, 0x00002cbd, + 0x00002cbf, 0x00002cbf, 0x00002cc1, 0x00002cc1, + 0x00002cc3, 0x00002cc3, 0x00002cc5, 0x00002cc5, + 0x00002cc7, 0x00002cc7, 0x00002cc9, 0x00002cc9, + 0x00002ccb, 0x00002ccb, 0x00002ccd, 0x00002ccd, + 0x00002ccf, 0x00002ccf, 0x00002cd1, 0x00002cd1, + 0x00002cd3, 0x00002cd3, 0x00002cd5, 0x00002cd5, + 0x00002cd7, 0x00002cd7, 0x00002cd9, 0x00002cd9, + 0x00002cdb, 0x00002cdb, 0x00002cdd, 0x00002cdd, + 0x00002cdf, 0x00002cdf, 0x00002ce1, 0x00002ce1, + 0x00002ce3, 0x00002ce4, 0x00002cec, 0x00002cec, + 0x00002cee, 0x00002cee, 0x00002cf3, 0x00002cf3, + 0x00002d00, 0x00002d25, 0x00002d27, 0x00002d27, + 0x00002d2d, 0x00002d2d, 0x0000a641, 0x0000a641, + 0x0000a643, 0x0000a643, 0x0000a645, 0x0000a645, + 0x0000a647, 0x0000a647, 0x0000a649, 0x0000a649, + 0x0000a64b, 0x0000a64b, 0x0000a64d, 0x0000a64d, + 0x0000a64f, 0x0000a64f, 0x0000a651, 0x0000a651, + 0x0000a653, 0x0000a653, 0x0000a655, 0x0000a655, + 0x0000a657, 0x0000a657, 0x0000a659, 0x0000a659, + 0x0000a65b, 0x0000a65b, 0x0000a65d, 0x0000a65d, + 0x0000a65f, 0x0000a65f, 0x0000a661, 0x0000a661, + 0x0000a663, 0x0000a663, 0x0000a665, 0x0000a665, + 0x0000a667, 0x0000a667, 0x0000a669, 0x0000a669, + 0x0000a66b, 0x0000a66b, 0x0000a66d, 0x0000a66d, + 0x0000a681, 0x0000a681, 0x0000a683, 0x0000a683, + 0x0000a685, 0x0000a685, 0x0000a687, 0x0000a687, + 0x0000a689, 0x0000a689, 0x0000a68b, 0x0000a68b, + 0x0000a68d, 0x0000a68d, 0x0000a68f, 0x0000a68f, + 0x0000a691, 0x0000a691, 0x0000a693, 0x0000a693, + 0x0000a695, 0x0000a695, 0x0000a697, 0x0000a697, + 0x0000a699, 0x0000a699, 0x0000a69b, 0x0000a69b, + 0x0000a723, 0x0000a723, 0x0000a725, 0x0000a725, + 0x0000a727, 0x0000a727, 0x0000a729, 0x0000a729, + 0x0000a72b, 0x0000a72b, 0x0000a72d, 0x0000a72d, + 0x0000a72f, 0x0000a731, 0x0000a733, 0x0000a733, + 0x0000a735, 0x0000a735, 0x0000a737, 0x0000a737, + 0x0000a739, 0x0000a739, 0x0000a73b, 0x0000a73b, + 0x0000a73d, 0x0000a73d, 0x0000a73f, 0x0000a73f, + 0x0000a741, 0x0000a741, 0x0000a743, 0x0000a743, + 0x0000a745, 0x0000a745, 0x0000a747, 0x0000a747, + 0x0000a749, 0x0000a749, 0x0000a74b, 0x0000a74b, + 0x0000a74d, 0x0000a74d, 0x0000a74f, 0x0000a74f, + 0x0000a751, 0x0000a751, 0x0000a753, 0x0000a753, + 0x0000a755, 0x0000a755, 0x0000a757, 0x0000a757, + 0x0000a759, 0x0000a759, 0x0000a75b, 0x0000a75b, + 0x0000a75d, 0x0000a75d, 0x0000a75f, 0x0000a75f, + 0x0000a761, 0x0000a761, 0x0000a763, 0x0000a763, + 0x0000a765, 0x0000a765, 0x0000a767, 0x0000a767, + 0x0000a769, 0x0000a769, 0x0000a76b, 0x0000a76b, + 0x0000a76d, 0x0000a76d, 0x0000a76f, 0x0000a76f, + 0x0000a771, 0x0000a778, 0x0000a77a, 0x0000a77a, + 0x0000a77c, 0x0000a77c, 0x0000a77f, 0x0000a77f, + 0x0000a781, 0x0000a781, 0x0000a783, 0x0000a783, + 0x0000a785, 0x0000a785, 0x0000a787, 0x0000a787, + 0x0000a78c, 0x0000a78c, 0x0000a78e, 0x0000a78e, + 0x0000a791, 0x0000a791, 0x0000a793, 0x0000a795, + 0x0000a797, 0x0000a797, 0x0000a799, 0x0000a799, + 0x0000a79b, 0x0000a79b, 0x0000a79d, 0x0000a79d, + 0x0000a79f, 0x0000a79f, 0x0000a7a1, 0x0000a7a1, + 0x0000a7a3, 0x0000a7a3, 0x0000a7a5, 0x0000a7a5, + 0x0000a7a7, 0x0000a7a7, 0x0000a7a9, 0x0000a7a9, + 0x0000a7af, 0x0000a7af, 0x0000a7b5, 0x0000a7b5, + 0x0000a7b7, 0x0000a7b7, 0x0000a7b9, 0x0000a7b9, + 0x0000a7bb, 0x0000a7bb, 0x0000a7bd, 0x0000a7bd, + 0x0000a7bf, 0x0000a7bf, 0x0000a7c1, 0x0000a7c1, + 0x0000a7c3, 0x0000a7c3, 0x0000a7c8, 0x0000a7c8, + 0x0000a7ca, 0x0000a7ca, 0x0000a7cd, 0x0000a7cd, + 0x0000a7cf, 0x0000a7cf, 0x0000a7d1, 0x0000a7d1, 0x0000a7d3, 0x0000a7d3, 0x0000a7d5, 0x0000a7d5, 0x0000a7d7, 0x0000a7d7, 0x0000a7d9, 0x0000a7d9, 0x0000a7db, 0x0000a7db, 0x0000a7f6, 0x0000a7f6, @@ -1021,228 +1030,231 @@ static const unsigned int _ucprop_ranges[] = { 0x000105a3, 0x000105b1, 0x000105b3, 0x000105b9, 0x000105bb, 0x000105bc, 0x00010cc0, 0x00010cf2, 0x00010d70, 0x00010d85, 0x000118c0, 0x000118df, - 0x00016e60, 0x00016e7f, 0x0001d41a, 0x0001d433, - 0x0001d44e, 0x0001d454, 0x0001d456, 0x0001d467, - 0x0001d482, 0x0001d49b, 0x0001d4b6, 0x0001d4b9, - 0x0001d4bb, 0x0001d4bb, 0x0001d4bd, 0x0001d4c3, - 0x0001d4c5, 0x0001d4cf, 0x0001d4ea, 0x0001d503, - 0x0001d51e, 0x0001d537, 0x0001d552, 0x0001d56b, - 0x0001d586, 0x0001d59f, 0x0001d5ba, 0x0001d5d3, - 0x0001d5ee, 0x0001d607, 0x0001d622, 0x0001d63b, - 0x0001d656, 0x0001d66f, 0x0001d68a, 0x0001d6a5, - 0x0001d6c2, 0x0001d6da, 0x0001d6dc, 0x0001d6e1, - 0x0001d6fc, 0x0001d714, 0x0001d716, 0x0001d71b, - 0x0001d736, 0x0001d74e, 0x0001d750, 0x0001d755, - 0x0001d770, 0x0001d788, 0x0001d78a, 0x0001d78f, - 0x0001d7aa, 0x0001d7c2, 0x0001d7c4, 0x0001d7c9, - 0x0001d7cb, 0x0001d7cb, 0x0001df00, 0x0001df09, - 0x0001df0b, 0x0001df1e, 0x0001df25, 0x0001df2a, - 0x0001e922, 0x0001e943, 0x000001c5, 0x000001c5, - 0x000001c8, 0x000001c8, 0x000001cb, 0x000001cb, - 0x000001f2, 0x000001f2, 0x00001f88, 0x00001f8f, - 0x00001f98, 0x00001f9f, 0x00001fa8, 0x00001faf, - 0x00001fbc, 0x00001fbc, 0x00001fcc, 0x00001fcc, - 0x00001ffc, 0x00001ffc, 0x000002b0, 0x000002c1, - 0x000002c6, 0x000002d1, 0x000002e0, 0x000002e4, - 0x000002ec, 0x000002ec, 0x000002ee, 0x000002ee, - 0x00000374, 0x00000374, 0x0000037a, 0x0000037a, - 0x00000559, 0x00000559, 0x00000640, 0x00000640, - 0x000006e5, 0x000006e6, 0x000007f4, 0x000007f5, - 0x000007fa, 0x000007fa, 0x0000081a, 0x0000081a, - 0x00000824, 0x00000824, 0x00000828, 0x00000828, - 0x000008c9, 0x000008c9, 0x00000971, 0x00000971, - 0x00000e46, 0x00000e46, 0x00000ec6, 0x00000ec6, - 0x000010fc, 0x000010fc, 0x000017d7, 0x000017d7, - 0x00001843, 0x00001843, 0x00001aa7, 0x00001aa7, - 0x00001c78, 0x00001c7d, 0x00001d2c, 0x00001d6a, - 0x00001d78, 0x00001d78, 0x00001d9b, 0x00001dbf, - 0x00002071, 0x00002071, 0x0000207f, 0x0000207f, - 0x00002090, 0x0000209c, 0x00002c7c, 0x00002c7d, - 0x00002d6f, 0x00002d6f, 0x00002e2f, 0x00002e2f, - 0x00003005, 0x00003005, 0x00003031, 0x00003035, - 0x0000303b, 0x0000303b, 0x0000309d, 0x0000309e, - 0x000030fc, 0x000030fe, 0x0000a015, 0x0000a015, - 0x0000a4f8, 0x0000a4fd, 0x0000a60c, 0x0000a60c, - 0x0000a67f, 0x0000a67f, 0x0000a69c, 0x0000a69d, - 0x0000a717, 0x0000a71f, 0x0000a770, 0x0000a770, - 0x0000a788, 0x0000a788, 0x0000a7f2, 0x0000a7f4, - 0x0000a7f8, 0x0000a7f9, 0x0000a9cf, 0x0000a9cf, - 0x0000a9e6, 0x0000a9e6, 0x0000aa70, 0x0000aa70, - 0x0000aadd, 0x0000aadd, 0x0000aaf3, 0x0000aaf4, - 0x0000ab5c, 0x0000ab5f, 0x0000ab69, 0x0000ab69, - 0x0000ff70, 0x0000ff70, 0x0000ff9e, 0x0000ff9f, - 0x00010780, 0x00010785, 0x00010787, 0x000107b0, - 0x000107b2, 0x000107ba, 0x00010d4e, 0x00010d4e, - 0x00010d6f, 0x00010d6f, 0x00016b40, 0x00016b43, - 0x00016d40, 0x00016d42, 0x00016d6b, 0x00016d6c, - 0x00016f93, 0x00016f9f, 0x00016fe0, 0x00016fe1, - 0x00016fe3, 0x00016fe3, 0x0001aff0, 0x0001aff3, + 0x00016e60, 0x00016e7f, 0x00016ebb, 0x00016ed3, + 0x0001d41a, 0x0001d433, 0x0001d44e, 0x0001d454, + 0x0001d456, 0x0001d467, 0x0001d482, 0x0001d49b, + 0x0001d4b6, 0x0001d4b9, 0x0001d4bb, 0x0001d4bb, + 0x0001d4bd, 0x0001d4c3, 0x0001d4c5, 0x0001d4cf, + 0x0001d4ea, 0x0001d503, 0x0001d51e, 0x0001d537, + 0x0001d552, 0x0001d56b, 0x0001d586, 0x0001d59f, + 0x0001d5ba, 0x0001d5d3, 0x0001d5ee, 0x0001d607, + 0x0001d622, 0x0001d63b, 0x0001d656, 0x0001d66f, + 0x0001d68a, 0x0001d6a5, 0x0001d6c2, 0x0001d6da, + 0x0001d6dc, 0x0001d6e1, 0x0001d6fc, 0x0001d714, + 0x0001d716, 0x0001d71b, 0x0001d736, 0x0001d74e, + 0x0001d750, 0x0001d755, 0x0001d770, 0x0001d788, + 0x0001d78a, 0x0001d78f, 0x0001d7aa, 0x0001d7c2, + 0x0001d7c4, 0x0001d7c9, 0x0001d7cb, 0x0001d7cb, + 0x0001df00, 0x0001df09, 0x0001df0b, 0x0001df1e, + 0x0001df25, 0x0001df2a, 0x0001e922, 0x0001e943, + 0x000001c5, 0x000001c5, 0x000001c8, 0x000001c8, + 0x000001cb, 0x000001cb, 0x000001f2, 0x000001f2, + 0x00001f88, 0x00001f8f, 0x00001f98, 0x00001f9f, + 0x00001fa8, 0x00001faf, 0x00001fbc, 0x00001fbc, + 0x00001fcc, 0x00001fcc, 0x00001ffc, 0x00001ffc, + 0x000002b0, 0x000002c1, 0x000002c6, 0x000002d1, + 0x000002e0, 0x000002e4, 0x000002ec, 0x000002ec, + 0x000002ee, 0x000002ee, 0x00000374, 0x00000374, + 0x0000037a, 0x0000037a, 0x00000559, 0x00000559, + 0x00000640, 0x00000640, 0x000006e5, 0x000006e6, + 0x000007f4, 0x000007f5, 0x000007fa, 0x000007fa, + 0x0000081a, 0x0000081a, 0x00000824, 0x00000824, + 0x00000828, 0x00000828, 0x000008c9, 0x000008c9, + 0x00000971, 0x00000971, 0x00000e46, 0x00000e46, + 0x00000ec6, 0x00000ec6, 0x000010fc, 0x000010fc, + 0x000017d7, 0x000017d7, 0x00001843, 0x00001843, + 0x00001aa7, 0x00001aa7, 0x00001c78, 0x00001c7d, + 0x00001d2c, 0x00001d6a, 0x00001d78, 0x00001d78, + 0x00001d9b, 0x00001dbf, 0x00002071, 0x00002071, + 0x0000207f, 0x0000207f, 0x00002090, 0x0000209c, + 0x00002c7c, 0x00002c7d, 0x00002d6f, 0x00002d6f, + 0x00002e2f, 0x00002e2f, 0x00003005, 0x00003005, + 0x00003031, 0x00003035, 0x0000303b, 0x0000303b, + 0x0000309d, 0x0000309e, 0x000030fc, 0x000030fe, + 0x0000a015, 0x0000a015, 0x0000a4f8, 0x0000a4fd, + 0x0000a60c, 0x0000a60c, 0x0000a67f, 0x0000a67f, + 0x0000a69c, 0x0000a69d, 0x0000a717, 0x0000a71f, + 0x0000a770, 0x0000a770, 0x0000a788, 0x0000a788, + 0x0000a7f1, 0x0000a7f4, 0x0000a7f8, 0x0000a7f9, + 0x0000a9cf, 0x0000a9cf, 0x0000a9e6, 0x0000a9e6, + 0x0000aa70, 0x0000aa70, 0x0000aadd, 0x0000aadd, + 0x0000aaf3, 0x0000aaf4, 0x0000ab5c, 0x0000ab5f, + 0x0000ab69, 0x0000ab69, 0x0000ff70, 0x0000ff70, + 0x0000ff9e, 0x0000ff9f, 0x00010780, 0x00010785, + 0x00010787, 0x000107b0, 0x000107b2, 0x000107ba, + 0x00010d4e, 0x00010d4e, 0x00010d6f, 0x00010d6f, + 0x00010ec5, 0x00010ec5, 0x00011dd9, 0x00011dd9, + 0x00016b40, 0x00016b43, 0x00016d40, 0x00016d42, + 0x00016d6b, 0x00016d6c, 0x00016f93, 0x00016f9f, + 0x00016fe0, 0x00016fe1, 0x00016fe3, 0x00016fe3, + 0x00016ff2, 0x00016ff3, 0x0001aff0, 0x0001aff3, 0x0001aff5, 0x0001affb, 0x0001affd, 0x0001affe, 0x0001e030, 0x0001e06d, 0x0001e137, 0x0001e13d, - 0x0001e4eb, 0x0001e4eb, 0x0001e94b, 0x0001e94b, - 0x000000aa, 0x000000aa, 0x000000ba, 0x000000ba, - 0x000001bb, 0x000001bb, 0x000001c0, 0x000001c3, - 0x00000294, 0x00000294, 0x000005d0, 0x000005ea, - 0x000005ef, 0x000005f2, 0x00000620, 0x0000063f, - 0x00000641, 0x0000064a, 0x0000066e, 0x0000066f, - 0x00000671, 0x000006d3, 0x000006d5, 0x000006d5, - 0x000006ee, 0x000006ef, 0x000006fa, 0x000006fc, - 0x000006ff, 0x000006ff, 0x00000710, 0x00000710, - 0x00000712, 0x0000072f, 0x0000074d, 0x000007a5, - 0x000007b1, 0x000007b1, 0x000007ca, 0x000007ea, - 0x00000800, 0x00000815, 0x00000840, 0x00000858, - 0x00000860, 0x0000086a, 0x00000870, 0x00000887, - 0x00000889, 0x0000088e, 0x000008a0, 0x000008c8, - 0x00000904, 0x00000939, 0x0000093d, 0x0000093d, - 0x00000950, 0x00000950, 0x00000958, 0x00000961, - 0x00000972, 0x00000980, 0x00000985, 0x0000098c, - 0x0000098f, 0x00000990, 0x00000993, 0x000009a8, - 0x000009aa, 0x000009b0, 0x000009b2, 0x000009b2, - 0x000009b6, 0x000009b9, 0x000009bd, 0x000009bd, - 0x000009ce, 0x000009ce, 0x000009dc, 0x000009dd, - 0x000009df, 0x000009e1, 0x000009f0, 0x000009f1, - 0x000009fc, 0x000009fc, 0x00000a05, 0x00000a0a, - 0x00000a0f, 0x00000a10, 0x00000a13, 0x00000a28, - 0x00000a2a, 0x00000a30, 0x00000a32, 0x00000a33, - 0x00000a35, 0x00000a36, 0x00000a38, 0x00000a39, - 0x00000a59, 0x00000a5c, 0x00000a5e, 0x00000a5e, - 0x00000a72, 0x00000a74, 0x00000a85, 0x00000a8d, - 0x00000a8f, 0x00000a91, 0x00000a93, 0x00000aa8, - 0x00000aaa, 0x00000ab0, 0x00000ab2, 0x00000ab3, - 0x00000ab5, 0x00000ab9, 0x00000abd, 0x00000abd, - 0x00000ad0, 0x00000ad0, 0x00000ae0, 0x00000ae1, - 0x00000af9, 0x00000af9, 0x00000b05, 0x00000b0c, - 0x00000b0f, 0x00000b10, 0x00000b13, 0x00000b28, - 0x00000b2a, 0x00000b30, 0x00000b32, 0x00000b33, - 0x00000b35, 0x00000b39, 0x00000b3d, 0x00000b3d, - 0x00000b5c, 0x00000b5d, 0x00000b5f, 0x00000b61, - 0x00000b71, 0x00000b71, 0x00000b83, 0x00000b83, - 0x00000b85, 0x00000b8a, 0x00000b8e, 0x00000b90, - 0x00000b92, 0x00000b95, 0x00000b99, 0x00000b9a, - 0x00000b9c, 0x00000b9c, 0x00000b9e, 0x00000b9f, - 0x00000ba3, 0x00000ba4, 0x00000ba8, 0x00000baa, - 0x00000bae, 0x00000bb9, 0x00000bd0, 0x00000bd0, - 0x00000c05, 0x00000c0c, 0x00000c0e, 0x00000c10, - 0x00000c12, 0x00000c28, 0x00000c2a, 0x00000c39, - 0x00000c3d, 0x00000c3d, 0x00000c58, 0x00000c5a, - 0x00000c5d, 0x00000c5d, 0x00000c60, 0x00000c61, - 0x00000c80, 0x00000c80, 0x00000c85, 0x00000c8c, - 0x00000c8e, 0x00000c90, 0x00000c92, 0x00000ca8, - 0x00000caa, 0x00000cb3, 0x00000cb5, 0x00000cb9, - 0x00000cbd, 0x00000cbd, 0x00000cdd, 0x00000cde, - 0x00000ce0, 0x00000ce1, 0x00000cf1, 0x00000cf2, - 0x00000d04, 0x00000d0c, 0x00000d0e, 0x00000d10, - 0x00000d12, 0x00000d3a, 0x00000d3d, 0x00000d3d, - 0x00000d4e, 0x00000d4e, 0x00000d54, 0x00000d56, - 0x00000d5f, 0x00000d61, 0x00000d7a, 0x00000d7f, - 0x00000d85, 0x00000d96, 0x00000d9a, 0x00000db1, - 0x00000db3, 0x00000dbb, 0x00000dbd, 0x00000dbd, - 0x00000dc0, 0x00000dc6, 0x00000e01, 0x00000e30, - 0x00000e32, 0x00000e33, 0x00000e40, 0x00000e45, - 0x00000e81, 0x00000e82, 0x00000e84, 0x00000e84, - 0x00000e86, 0x00000e8a, 0x00000e8c, 0x00000ea3, - 0x00000ea5, 0x00000ea5, 0x00000ea7, 0x00000eb0, - 0x00000eb2, 0x00000eb3, 0x00000ebd, 0x00000ebd, - 0x00000ec0, 0x00000ec4, 0x00000edc, 0x00000edf, - 0x00000f00, 0x00000f00, 0x00000f40, 0x00000f47, - 0x00000f49, 0x00000f6c, 0x00000f88, 0x00000f8c, - 0x00001000, 0x0000102a, 0x0000103f, 0x0000103f, - 0x00001050, 0x00001055, 0x0000105a, 0x0000105d, - 0x00001061, 0x00001061, 0x00001065, 0x00001066, - 0x0000106e, 0x00001070, 0x00001075, 0x00001081, - 0x0000108e, 0x0000108e, 0x00001100, 0x00001248, - 0x0000124a, 0x0000124d, 0x00001250, 0x00001256, - 0x00001258, 0x00001258, 0x0000125a, 0x0000125d, - 0x00001260, 0x00001288, 0x0000128a, 0x0000128d, - 0x00001290, 0x000012b0, 0x000012b2, 0x000012b5, - 0x000012b8, 0x000012be, 0x000012c0, 0x000012c0, - 0x000012c2, 0x000012c5, 0x000012c8, 0x000012d6, - 0x000012d8, 0x00001310, 0x00001312, 0x00001315, - 0x00001318, 0x0000135a, 0x00001380, 0x0000138f, - 0x00001401, 0x0000166c, 0x0000166f, 0x0000167f, - 0x00001681, 0x0000169a, 0x000016a0, 0x000016ea, - 0x000016f1, 0x000016f8, 0x00001700, 0x00001711, - 0x0000171f, 0x00001731, 0x00001740, 0x00001751, - 0x00001760, 0x0000176c, 0x0000176e, 0x00001770, - 0x00001780, 0x000017b3, 0x000017dc, 0x000017dc, - 0x00001820, 0x00001842, 0x00001844, 0x00001878, - 0x00001880, 0x00001884, 0x00001887, 0x000018a8, - 0x000018aa, 0x000018aa, 0x000018b0, 0x000018f5, - 0x00001900, 0x0000191e, 0x00001950, 0x0000196d, - 0x00001970, 0x00001974, 0x00001980, 0x000019ab, - 0x000019b0, 0x000019c9, 0x00001a00, 0x00001a16, - 0x00001a20, 0x00001a54, 0x00001b05, 0x00001b33, - 0x00001b45, 0x00001b4c, 0x00001b83, 0x00001ba0, - 0x00001bae, 0x00001baf, 0x00001bba, 0x00001be5, - 0x00001c00, 0x00001c23, 0x00001c4d, 0x00001c4f, - 0x00001c5a, 0x00001c77, 0x00001ce9, 0x00001cec, - 0x00001cee, 0x00001cf3, 0x00001cf5, 0x00001cf6, - 0x00001cfa, 0x00001cfa, 0x00002135, 0x00002138, - 0x00002d30, 0x00002d67, 0x00002d80, 0x00002d96, - 0x00002da0, 0x00002da6, 0x00002da8, 0x00002dae, - 0x00002db0, 0x00002db6, 0x00002db8, 0x00002dbe, - 0x00002dc0, 0x00002dc6, 0x00002dc8, 0x00002dce, - 0x00002dd0, 0x00002dd6, 0x00002dd8, 0x00002dde, - 0x00003006, 0x00003006, 0x0000303c, 0x0000303c, - 0x00003041, 0x00003096, 0x0000309f, 0x0000309f, - 0x000030a1, 0x000030fa, 0x000030ff, 0x000030ff, - 0x00003105, 0x0000312f, 0x00003131, 0x0000318e, - 0x000031a0, 0x000031bf, 0x000031f0, 0x000031ff, - 0x00003400, 0x00004dbf, 0x00004e00, 0x0000a014, - 0x0000a016, 0x0000a48c, 0x0000a4d0, 0x0000a4f7, - 0x0000a500, 0x0000a60b, 0x0000a610, 0x0000a61f, - 0x0000a62a, 0x0000a62b, 0x0000a66e, 0x0000a66e, - 0x0000a6a0, 0x0000a6e5, 0x0000a78f, 0x0000a78f, - 0x0000a7f7, 0x0000a7f7, 0x0000a7fb, 0x0000a801, - 0x0000a803, 0x0000a805, 0x0000a807, 0x0000a80a, - 0x0000a80c, 0x0000a822, 0x0000a840, 0x0000a873, - 0x0000a882, 0x0000a8b3, 0x0000a8f2, 0x0000a8f7, - 0x0000a8fb, 0x0000a8fb, 0x0000a8fd, 0x0000a8fe, - 0x0000a90a, 0x0000a925, 0x0000a930, 0x0000a946, - 0x0000a960, 0x0000a97c, 0x0000a984, 0x0000a9b2, - 0x0000a9e0, 0x0000a9e4, 0x0000a9e7, 0x0000a9ef, - 0x0000a9fa, 0x0000a9fe, 0x0000aa00, 0x0000aa28, - 0x0000aa40, 0x0000aa42, 0x0000aa44, 0x0000aa4b, - 0x0000aa60, 0x0000aa6f, 0x0000aa71, 0x0000aa76, - 0x0000aa7a, 0x0000aa7a, 0x0000aa7e, 0x0000aaaf, - 0x0000aab1, 0x0000aab1, 0x0000aab5, 0x0000aab6, - 0x0000aab9, 0x0000aabd, 0x0000aac0, 0x0000aac0, - 0x0000aac2, 0x0000aac2, 0x0000aadb, 0x0000aadc, - 0x0000aae0, 0x0000aaea, 0x0000aaf2, 0x0000aaf2, - 0x0000ab01, 0x0000ab06, 0x0000ab09, 0x0000ab0e, - 0x0000ab11, 0x0000ab16, 0x0000ab20, 0x0000ab26, - 0x0000ab28, 0x0000ab2e, 0x0000abc0, 0x0000abe2, - 0x0000ac00, 0x0000d7a3, 0x0000d7b0, 0x0000d7c6, - 0x0000d7cb, 0x0000d7fb, 0x0000f900, 0x0000fa6d, - 0x0000fa70, 0x0000fad9, 0x0000fb1d, 0x0000fb1d, - 0x0000fb1f, 0x0000fb28, 0x0000fb2a, 0x0000fb36, - 0x0000fb38, 0x0000fb3c, 0x0000fb3e, 0x0000fb3e, - 0x0000fb40, 0x0000fb41, 0x0000fb43, 0x0000fb44, - 0x0000fb46, 0x0000fbb1, 0x0000fbd3, 0x0000fd3d, - 0x0000fd50, 0x0000fd8f, 0x0000fd92, 0x0000fdc7, - 0x0000fdf0, 0x0000fdfb, 0x0000fe70, 0x0000fe74, - 0x0000fe76, 0x0000fefc, 0x0000ff66, 0x0000ff6f, - 0x0000ff71, 0x0000ff9d, 0x0000ffa0, 0x0000ffbe, - 0x0000ffc2, 0x0000ffc7, 0x0000ffca, 0x0000ffcf, - 0x0000ffd2, 0x0000ffd7, 0x0000ffda, 0x0000ffdc, - 0x00010000, 0x0001000b, 0x0001000d, 0x00010026, - 0x00010028, 0x0001003a, 0x0001003c, 0x0001003d, - 0x0001003f, 0x0001004d, 0x00010050, 0x0001005d, - 0x00010080, 0x000100fa, 0x00010280, 0x0001029c, - 0x000102a0, 0x000102d0, 0x00010300, 0x0001031f, - 0x0001032d, 0x00010340, 0x00010342, 0x00010349, - 0x00010350, 0x00010375, 0x00010380, 0x0001039d, - 0x000103a0, 0x000103c3, 0x000103c8, 0x000103cf, - 0x00010450, 0x0001049d, 0x00010500, 0x00010527, - 0x00010530, 0x00010563, 0x000105c0, 0x000105f3, - 0x00010600, 0x00010736, 0x00010740, 0x00010755, - 0x00010760, 0x00010767, 0x00010800, 0x00010805, - 0x00010808, 0x00010808, 0x0001080a, 0x00010835, - 0x00010837, 0x00010838, 0x0001083c, 0x0001083c, - 0x0001083f, 0x00010855, 0x00010860, 0x00010876, - 0x00010880, 0x0001089e, 0x000108e0, 0x000108f2, - 0x000108f4, 0x000108f5, 0x00010900, 0x00010915, - 0x00010920, 0x00010939, 0x00010980, 0x000109b7, + 0x0001e4eb, 0x0001e4eb, 0x0001e6ff, 0x0001e6ff, + 0x0001e94b, 0x0001e94b, 0x000000aa, 0x000000aa, + 0x000000ba, 0x000000ba, 0x000001bb, 0x000001bb, + 0x000001c0, 0x000001c3, 0x00000294, 0x00000295, + 0x000005d0, 0x000005ea, 0x000005ef, 0x000005f2, + 0x00000620, 0x0000063f, 0x00000641, 0x0000064a, + 0x0000066e, 0x0000066f, 0x00000671, 0x000006d3, + 0x000006d5, 0x000006d5, 0x000006ee, 0x000006ef, + 0x000006fa, 0x000006fc, 0x000006ff, 0x000006ff, + 0x00000710, 0x00000710, 0x00000712, 0x0000072f, + 0x0000074d, 0x000007a5, 0x000007b1, 0x000007b1, + 0x000007ca, 0x000007ea, 0x00000800, 0x00000815, + 0x00000840, 0x00000858, 0x00000860, 0x0000086a, + 0x00000870, 0x00000887, 0x00000889, 0x0000088f, + 0x000008a0, 0x000008c8, 0x00000904, 0x00000939, + 0x0000093d, 0x0000093d, 0x00000950, 0x00000950, + 0x00000958, 0x00000961, 0x00000972, 0x00000980, + 0x00000985, 0x0000098c, 0x0000098f, 0x00000990, + 0x00000993, 0x000009a8, 0x000009aa, 0x000009b0, + 0x000009b2, 0x000009b2, 0x000009b6, 0x000009b9, + 0x000009bd, 0x000009bd, 0x000009ce, 0x000009ce, + 0x000009dc, 0x000009dd, 0x000009df, 0x000009e1, + 0x000009f0, 0x000009f1, 0x000009fc, 0x000009fc, + 0x00000a05, 0x00000a0a, 0x00000a0f, 0x00000a10, + 0x00000a13, 0x00000a28, 0x00000a2a, 0x00000a30, + 0x00000a32, 0x00000a33, 0x00000a35, 0x00000a36, + 0x00000a38, 0x00000a39, 0x00000a59, 0x00000a5c, + 0x00000a5e, 0x00000a5e, 0x00000a72, 0x00000a74, + 0x00000a85, 0x00000a8d, 0x00000a8f, 0x00000a91, + 0x00000a93, 0x00000aa8, 0x00000aaa, 0x00000ab0, + 0x00000ab2, 0x00000ab3, 0x00000ab5, 0x00000ab9, + 0x00000abd, 0x00000abd, 0x00000ad0, 0x00000ad0, + 0x00000ae0, 0x00000ae1, 0x00000af9, 0x00000af9, + 0x00000b05, 0x00000b0c, 0x00000b0f, 0x00000b10, + 0x00000b13, 0x00000b28, 0x00000b2a, 0x00000b30, + 0x00000b32, 0x00000b33, 0x00000b35, 0x00000b39, + 0x00000b3d, 0x00000b3d, 0x00000b5c, 0x00000b5d, + 0x00000b5f, 0x00000b61, 0x00000b71, 0x00000b71, + 0x00000b83, 0x00000b83, 0x00000b85, 0x00000b8a, + 0x00000b8e, 0x00000b90, 0x00000b92, 0x00000b95, + 0x00000b99, 0x00000b9a, 0x00000b9c, 0x00000b9c, + 0x00000b9e, 0x00000b9f, 0x00000ba3, 0x00000ba4, + 0x00000ba8, 0x00000baa, 0x00000bae, 0x00000bb9, + 0x00000bd0, 0x00000bd0, 0x00000c05, 0x00000c0c, + 0x00000c0e, 0x00000c10, 0x00000c12, 0x00000c28, + 0x00000c2a, 0x00000c39, 0x00000c3d, 0x00000c3d, + 0x00000c58, 0x00000c5a, 0x00000c5c, 0x00000c5d, + 0x00000c60, 0x00000c61, 0x00000c80, 0x00000c80, + 0x00000c85, 0x00000c8c, 0x00000c8e, 0x00000c90, + 0x00000c92, 0x00000ca8, 0x00000caa, 0x00000cb3, + 0x00000cb5, 0x00000cb9, 0x00000cbd, 0x00000cbd, + 0x00000cdc, 0x00000cde, 0x00000ce0, 0x00000ce1, + 0x00000cf1, 0x00000cf2, 0x00000d04, 0x00000d0c, + 0x00000d0e, 0x00000d10, 0x00000d12, 0x00000d3a, + 0x00000d3d, 0x00000d3d, 0x00000d4e, 0x00000d4e, + 0x00000d54, 0x00000d56, 0x00000d5f, 0x00000d61, + 0x00000d7a, 0x00000d7f, 0x00000d85, 0x00000d96, + 0x00000d9a, 0x00000db1, 0x00000db3, 0x00000dbb, + 0x00000dbd, 0x00000dbd, 0x00000dc0, 0x00000dc6, + 0x00000e01, 0x00000e30, 0x00000e32, 0x00000e33, + 0x00000e40, 0x00000e45, 0x00000e81, 0x00000e82, + 0x00000e84, 0x00000e84, 0x00000e86, 0x00000e8a, + 0x00000e8c, 0x00000ea3, 0x00000ea5, 0x00000ea5, + 0x00000ea7, 0x00000eb0, 0x00000eb2, 0x00000eb3, + 0x00000ebd, 0x00000ebd, 0x00000ec0, 0x00000ec4, + 0x00000edc, 0x00000edf, 0x00000f00, 0x00000f00, + 0x00000f40, 0x00000f47, 0x00000f49, 0x00000f6c, + 0x00000f88, 0x00000f8c, 0x00001000, 0x0000102a, + 0x0000103f, 0x0000103f, 0x00001050, 0x00001055, + 0x0000105a, 0x0000105d, 0x00001061, 0x00001061, + 0x00001065, 0x00001066, 0x0000106e, 0x00001070, + 0x00001075, 0x00001081, 0x0000108e, 0x0000108e, + 0x00001100, 0x00001248, 0x0000124a, 0x0000124d, + 0x00001250, 0x00001256, 0x00001258, 0x00001258, + 0x0000125a, 0x0000125d, 0x00001260, 0x00001288, + 0x0000128a, 0x0000128d, 0x00001290, 0x000012b0, + 0x000012b2, 0x000012b5, 0x000012b8, 0x000012be, + 0x000012c0, 0x000012c0, 0x000012c2, 0x000012c5, + 0x000012c8, 0x000012d6, 0x000012d8, 0x00001310, + 0x00001312, 0x00001315, 0x00001318, 0x0000135a, + 0x00001380, 0x0000138f, 0x00001401, 0x0000166c, + 0x0000166f, 0x0000167f, 0x00001681, 0x0000169a, + 0x000016a0, 0x000016ea, 0x000016f1, 0x000016f8, + 0x00001700, 0x00001711, 0x0000171f, 0x00001731, + 0x00001740, 0x00001751, 0x00001760, 0x0000176c, + 0x0000176e, 0x00001770, 0x00001780, 0x000017b3, + 0x000017dc, 0x000017dc, 0x00001820, 0x00001842, + 0x00001844, 0x00001878, 0x00001880, 0x00001884, + 0x00001887, 0x000018a8, 0x000018aa, 0x000018aa, + 0x000018b0, 0x000018f5, 0x00001900, 0x0000191e, + 0x00001950, 0x0000196d, 0x00001970, 0x00001974, + 0x00001980, 0x000019ab, 0x000019b0, 0x000019c9, + 0x00001a00, 0x00001a16, 0x00001a20, 0x00001a54, + 0x00001b05, 0x00001b33, 0x00001b45, 0x00001b4c, + 0x00001b83, 0x00001ba0, 0x00001bae, 0x00001baf, + 0x00001bba, 0x00001be5, 0x00001c00, 0x00001c23, + 0x00001c4d, 0x00001c4f, 0x00001c5a, 0x00001c77, + 0x00001ce9, 0x00001cec, 0x00001cee, 0x00001cf3, + 0x00001cf5, 0x00001cf6, 0x00001cfa, 0x00001cfa, + 0x00002135, 0x00002138, 0x00002d30, 0x00002d67, + 0x00002d80, 0x00002d96, 0x00002da0, 0x00002da6, + 0x00002da8, 0x00002dae, 0x00002db0, 0x00002db6, + 0x00002db8, 0x00002dbe, 0x00002dc0, 0x00002dc6, + 0x00002dc8, 0x00002dce, 0x00002dd0, 0x00002dd6, + 0x00002dd8, 0x00002dde, 0x00003006, 0x00003006, + 0x0000303c, 0x0000303c, 0x00003041, 0x00003096, + 0x0000309f, 0x0000309f, 0x000030a1, 0x000030fa, + 0x000030ff, 0x000030ff, 0x00003105, 0x0000312f, + 0x00003131, 0x0000318e, 0x000031a0, 0x000031bf, + 0x000031f0, 0x000031ff, 0x00003400, 0x00004dbf, + 0x00004e00, 0x0000a014, 0x0000a016, 0x0000a48c, + 0x0000a4d0, 0x0000a4f7, 0x0000a500, 0x0000a60b, + 0x0000a610, 0x0000a61f, 0x0000a62a, 0x0000a62b, + 0x0000a66e, 0x0000a66e, 0x0000a6a0, 0x0000a6e5, + 0x0000a78f, 0x0000a78f, 0x0000a7f7, 0x0000a7f7, + 0x0000a7fb, 0x0000a801, 0x0000a803, 0x0000a805, + 0x0000a807, 0x0000a80a, 0x0000a80c, 0x0000a822, + 0x0000a840, 0x0000a873, 0x0000a882, 0x0000a8b3, + 0x0000a8f2, 0x0000a8f7, 0x0000a8fb, 0x0000a8fb, + 0x0000a8fd, 0x0000a8fe, 0x0000a90a, 0x0000a925, + 0x0000a930, 0x0000a946, 0x0000a960, 0x0000a97c, + 0x0000a984, 0x0000a9b2, 0x0000a9e0, 0x0000a9e4, + 0x0000a9e7, 0x0000a9ef, 0x0000a9fa, 0x0000a9fe, + 0x0000aa00, 0x0000aa28, 0x0000aa40, 0x0000aa42, + 0x0000aa44, 0x0000aa4b, 0x0000aa60, 0x0000aa6f, + 0x0000aa71, 0x0000aa76, 0x0000aa7a, 0x0000aa7a, + 0x0000aa7e, 0x0000aaaf, 0x0000aab1, 0x0000aab1, + 0x0000aab5, 0x0000aab6, 0x0000aab9, 0x0000aabd, + 0x0000aac0, 0x0000aac0, 0x0000aac2, 0x0000aac2, + 0x0000aadb, 0x0000aadc, 0x0000aae0, 0x0000aaea, + 0x0000aaf2, 0x0000aaf2, 0x0000ab01, 0x0000ab06, + 0x0000ab09, 0x0000ab0e, 0x0000ab11, 0x0000ab16, + 0x0000ab20, 0x0000ab26, 0x0000ab28, 0x0000ab2e, + 0x0000abc0, 0x0000abe2, 0x0000ac00, 0x0000d7a3, + 0x0000d7b0, 0x0000d7c6, 0x0000d7cb, 0x0000d7fb, + 0x0000f900, 0x0000fa6d, 0x0000fa70, 0x0000fad9, + 0x0000fb1d, 0x0000fb1d, 0x0000fb1f, 0x0000fb28, + 0x0000fb2a, 0x0000fb36, 0x0000fb38, 0x0000fb3c, + 0x0000fb3e, 0x0000fb3e, 0x0000fb40, 0x0000fb41, + 0x0000fb43, 0x0000fb44, 0x0000fb46, 0x0000fbb1, + 0x0000fbd3, 0x0000fd3d, 0x0000fd50, 0x0000fd8f, + 0x0000fd92, 0x0000fdc7, 0x0000fdf0, 0x0000fdfb, + 0x0000fe70, 0x0000fe74, 0x0000fe76, 0x0000fefc, + 0x0000ff66, 0x0000ff6f, 0x0000ff71, 0x0000ff9d, + 0x0000ffa0, 0x0000ffbe, 0x0000ffc2, 0x0000ffc7, + 0x0000ffca, 0x0000ffcf, 0x0000ffd2, 0x0000ffd7, + 0x0000ffda, 0x0000ffdc, 0x00010000, 0x0001000b, + 0x0001000d, 0x00010026, 0x00010028, 0x0001003a, + 0x0001003c, 0x0001003d, 0x0001003f, 0x0001004d, + 0x00010050, 0x0001005d, 0x00010080, 0x000100fa, + 0x00010280, 0x0001029c, 0x000102a0, 0x000102d0, + 0x00010300, 0x0001031f, 0x0001032d, 0x00010340, + 0x00010342, 0x00010349, 0x00010350, 0x00010375, + 0x00010380, 0x0001039d, 0x000103a0, 0x000103c3, + 0x000103c8, 0x000103cf, 0x00010450, 0x0001049d, + 0x00010500, 0x00010527, 0x00010530, 0x00010563, + 0x000105c0, 0x000105f3, 0x00010600, 0x00010736, + 0x00010740, 0x00010755, 0x00010760, 0x00010767, + 0x00010800, 0x00010805, 0x00010808, 0x00010808, + 0x0001080a, 0x00010835, 0x00010837, 0x00010838, + 0x0001083c, 0x0001083c, 0x0001083f, 0x00010855, + 0x00010860, 0x00010876, 0x00010880, 0x0001089e, + 0x000108e0, 0x000108f2, 0x000108f4, 0x000108f5, + 0x00010900, 0x00010915, 0x00010920, 0x00010939, + 0x00010940, 0x00010959, 0x00010980, 0x000109b7, 0x000109be, 0x000109bf, 0x00010a00, 0x00010a00, 0x00010a10, 0x00010a13, 0x00010a15, 0x00010a17, 0x00010a19, 0x00010a35, 0x00010a60, 0x00010a7c, @@ -1253,97 +1265,101 @@ static const unsigned int _ucprop_ranges[] = { 0x00010d00, 0x00010d23, 0x00010d4a, 0x00010d4d, 0x00010d4f, 0x00010d4f, 0x00010e80, 0x00010ea9, 0x00010eb0, 0x00010eb1, 0x00010ec2, 0x00010ec4, - 0x00010f00, 0x00010f1c, 0x00010f27, 0x00010f27, - 0x00010f30, 0x00010f45, 0x00010f70, 0x00010f81, - 0x00010fb0, 0x00010fc4, 0x00010fe0, 0x00010ff6, - 0x00011003, 0x00011037, 0x00011071, 0x00011072, - 0x00011075, 0x00011075, 0x00011083, 0x000110af, - 0x000110d0, 0x000110e8, 0x00011103, 0x00011126, - 0x00011144, 0x00011144, 0x00011147, 0x00011147, - 0x00011150, 0x00011172, 0x00011176, 0x00011176, - 0x00011183, 0x000111b2, 0x000111c1, 0x000111c4, - 0x000111da, 0x000111da, 0x000111dc, 0x000111dc, - 0x00011200, 0x00011211, 0x00011213, 0x0001122b, - 0x0001123f, 0x00011240, 0x00011280, 0x00011286, - 0x00011288, 0x00011288, 0x0001128a, 0x0001128d, - 0x0001128f, 0x0001129d, 0x0001129f, 0x000112a8, - 0x000112b0, 0x000112de, 0x00011305, 0x0001130c, - 0x0001130f, 0x00011310, 0x00011313, 0x00011328, - 0x0001132a, 0x00011330, 0x00011332, 0x00011333, - 0x00011335, 0x00011339, 0x0001133d, 0x0001133d, - 0x00011350, 0x00011350, 0x0001135d, 0x00011361, - 0x00011380, 0x00011389, 0x0001138b, 0x0001138b, - 0x0001138e, 0x0001138e, 0x00011390, 0x000113b5, - 0x000113b7, 0x000113b7, 0x000113d1, 0x000113d1, - 0x000113d3, 0x000113d3, 0x00011400, 0x00011434, - 0x00011447, 0x0001144a, 0x0001145f, 0x00011461, - 0x00011480, 0x000114af, 0x000114c4, 0x000114c5, - 0x000114c7, 0x000114c7, 0x00011580, 0x000115ae, - 0x000115d8, 0x000115db, 0x00011600, 0x0001162f, - 0x00011644, 0x00011644, 0x00011680, 0x000116aa, - 0x000116b8, 0x000116b8, 0x00011700, 0x0001171a, - 0x00011740, 0x00011746, 0x00011800, 0x0001182b, - 0x000118ff, 0x00011906, 0x00011909, 0x00011909, - 0x0001190c, 0x00011913, 0x00011915, 0x00011916, - 0x00011918, 0x0001192f, 0x0001193f, 0x0001193f, - 0x00011941, 0x00011941, 0x000119a0, 0x000119a7, - 0x000119aa, 0x000119d0, 0x000119e1, 0x000119e1, - 0x000119e3, 0x000119e3, 0x00011a00, 0x00011a00, - 0x00011a0b, 0x00011a32, 0x00011a3a, 0x00011a3a, - 0x00011a50, 0x00011a50, 0x00011a5c, 0x00011a89, - 0x00011a9d, 0x00011a9d, 0x00011ab0, 0x00011af8, - 0x00011bc0, 0x00011be0, 0x00011c00, 0x00011c08, - 0x00011c0a, 0x00011c2e, 0x00011c40, 0x00011c40, - 0x00011c72, 0x00011c8f, 0x00011d00, 0x00011d06, - 0x00011d08, 0x00011d09, 0x00011d0b, 0x00011d30, - 0x00011d46, 0x00011d46, 0x00011d60, 0x00011d65, - 0x00011d67, 0x00011d68, 0x00011d6a, 0x00011d89, - 0x00011d98, 0x00011d98, 0x00011ee0, 0x00011ef2, - 0x00011f02, 0x00011f02, 0x00011f04, 0x00011f10, - 0x00011f12, 0x00011f33, 0x00011fb0, 0x00011fb0, - 0x00012000, 0x00012399, 0x00012480, 0x00012543, - 0x00012f90, 0x00012ff0, 0x00013000, 0x0001342f, - 0x00013441, 0x00013446, 0x00013460, 0x000143fa, - 0x00014400, 0x00014646, 0x00016100, 0x0001611d, - 0x00016800, 0x00016a38, 0x00016a40, 0x00016a5e, - 0x00016a70, 0x00016abe, 0x00016ad0, 0x00016aed, - 0x00016b00, 0x00016b2f, 0x00016b63, 0x00016b77, - 0x00016b7d, 0x00016b8f, 0x00016d43, 0x00016d6a, - 0x00016f00, 0x00016f4a, 0x00016f50, 0x00016f50, - 0x00017000, 0x000187f7, 0x00018800, 0x00018cd5, - 0x00018cff, 0x00018d08, 0x0001b000, 0x0001b122, - 0x0001b132, 0x0001b132, 0x0001b150, 0x0001b152, - 0x0001b155, 0x0001b155, 0x0001b164, 0x0001b167, - 0x0001b170, 0x0001b2fb, 0x0001bc00, 0x0001bc6a, - 0x0001bc70, 0x0001bc7c, 0x0001bc80, 0x0001bc88, - 0x0001bc90, 0x0001bc99, 0x0001df0a, 0x0001df0a, - 0x0001e100, 0x0001e12c, 0x0001e14e, 0x0001e14e, - 0x0001e290, 0x0001e2ad, 0x0001e2c0, 0x0001e2eb, - 0x0001e4d0, 0x0001e4ea, 0x0001e5d0, 0x0001e5ed, - 0x0001e5f0, 0x0001e5f0, 0x0001e7e0, 0x0001e7e6, - 0x0001e7e8, 0x0001e7eb, 0x0001e7ed, 0x0001e7ee, - 0x0001e7f0, 0x0001e7fe, 0x0001e800, 0x0001e8c4, - 0x0001ee00, 0x0001ee03, 0x0001ee05, 0x0001ee1f, - 0x0001ee21, 0x0001ee22, 0x0001ee24, 0x0001ee24, - 0x0001ee27, 0x0001ee27, 0x0001ee29, 0x0001ee32, - 0x0001ee34, 0x0001ee37, 0x0001ee39, 0x0001ee39, - 0x0001ee3b, 0x0001ee3b, 0x0001ee42, 0x0001ee42, - 0x0001ee47, 0x0001ee47, 0x0001ee49, 0x0001ee49, - 0x0001ee4b, 0x0001ee4b, 0x0001ee4d, 0x0001ee4f, - 0x0001ee51, 0x0001ee52, 0x0001ee54, 0x0001ee54, - 0x0001ee57, 0x0001ee57, 0x0001ee59, 0x0001ee59, - 0x0001ee5b, 0x0001ee5b, 0x0001ee5d, 0x0001ee5d, - 0x0001ee5f, 0x0001ee5f, 0x0001ee61, 0x0001ee62, - 0x0001ee64, 0x0001ee64, 0x0001ee67, 0x0001ee6a, - 0x0001ee6c, 0x0001ee72, 0x0001ee74, 0x0001ee77, - 0x0001ee79, 0x0001ee7c, 0x0001ee7e, 0x0001ee7e, - 0x0001ee80, 0x0001ee89, 0x0001ee8b, 0x0001ee9b, - 0x0001eea1, 0x0001eea3, 0x0001eea5, 0x0001eea9, - 0x0001eeab, 0x0001eebb, 0x00020000, 0x0002a6df, - 0x0002a700, 0x0002b739, 0x0002b740, 0x0002b81d, - 0x0002b820, 0x0002cea1, 0x0002ceb0, 0x0002ebe0, + 0x00010ec6, 0x00010ec7, 0x00010f00, 0x00010f1c, + 0x00010f27, 0x00010f27, 0x00010f30, 0x00010f45, + 0x00010f70, 0x00010f81, 0x00010fb0, 0x00010fc4, + 0x00010fe0, 0x00010ff6, 0x00011003, 0x00011037, + 0x00011071, 0x00011072, 0x00011075, 0x00011075, + 0x00011083, 0x000110af, 0x000110d0, 0x000110e8, + 0x00011103, 0x00011126, 0x00011144, 0x00011144, + 0x00011147, 0x00011147, 0x00011150, 0x00011172, + 0x00011176, 0x00011176, 0x00011183, 0x000111b2, + 0x000111c1, 0x000111c4, 0x000111da, 0x000111da, + 0x000111dc, 0x000111dc, 0x00011200, 0x00011211, + 0x00011213, 0x0001122b, 0x0001123f, 0x00011240, + 0x00011280, 0x00011286, 0x00011288, 0x00011288, + 0x0001128a, 0x0001128d, 0x0001128f, 0x0001129d, + 0x0001129f, 0x000112a8, 0x000112b0, 0x000112de, + 0x00011305, 0x0001130c, 0x0001130f, 0x00011310, + 0x00011313, 0x00011328, 0x0001132a, 0x00011330, + 0x00011332, 0x00011333, 0x00011335, 0x00011339, + 0x0001133d, 0x0001133d, 0x00011350, 0x00011350, + 0x0001135d, 0x00011361, 0x00011380, 0x00011389, + 0x0001138b, 0x0001138b, 0x0001138e, 0x0001138e, + 0x00011390, 0x000113b5, 0x000113b7, 0x000113b7, + 0x000113d1, 0x000113d1, 0x000113d3, 0x000113d3, + 0x00011400, 0x00011434, 0x00011447, 0x0001144a, + 0x0001145f, 0x00011461, 0x00011480, 0x000114af, + 0x000114c4, 0x000114c5, 0x000114c7, 0x000114c7, + 0x00011580, 0x000115ae, 0x000115d8, 0x000115db, + 0x00011600, 0x0001162f, 0x00011644, 0x00011644, + 0x00011680, 0x000116aa, 0x000116b8, 0x000116b8, + 0x00011700, 0x0001171a, 0x00011740, 0x00011746, + 0x00011800, 0x0001182b, 0x000118ff, 0x00011906, + 0x00011909, 0x00011909, 0x0001190c, 0x00011913, + 0x00011915, 0x00011916, 0x00011918, 0x0001192f, + 0x0001193f, 0x0001193f, 0x00011941, 0x00011941, + 0x000119a0, 0x000119a7, 0x000119aa, 0x000119d0, + 0x000119e1, 0x000119e1, 0x000119e3, 0x000119e3, + 0x00011a00, 0x00011a00, 0x00011a0b, 0x00011a32, + 0x00011a3a, 0x00011a3a, 0x00011a50, 0x00011a50, + 0x00011a5c, 0x00011a89, 0x00011a9d, 0x00011a9d, + 0x00011ab0, 0x00011af8, 0x00011bc0, 0x00011be0, + 0x00011c00, 0x00011c08, 0x00011c0a, 0x00011c2e, + 0x00011c40, 0x00011c40, 0x00011c72, 0x00011c8f, + 0x00011d00, 0x00011d06, 0x00011d08, 0x00011d09, + 0x00011d0b, 0x00011d30, 0x00011d46, 0x00011d46, + 0x00011d60, 0x00011d65, 0x00011d67, 0x00011d68, + 0x00011d6a, 0x00011d89, 0x00011d98, 0x00011d98, + 0x00011db0, 0x00011dd8, 0x00011dda, 0x00011ddb, + 0x00011ee0, 0x00011ef2, 0x00011f02, 0x00011f02, + 0x00011f04, 0x00011f10, 0x00011f12, 0x00011f33, + 0x00011fb0, 0x00011fb0, 0x00012000, 0x00012399, + 0x00012480, 0x00012543, 0x00012f90, 0x00012ff0, + 0x00013000, 0x0001342f, 0x00013441, 0x00013446, + 0x00013460, 0x000143fa, 0x00014400, 0x00014646, + 0x00016100, 0x0001611d, 0x00016800, 0x00016a38, + 0x00016a40, 0x00016a5e, 0x00016a70, 0x00016abe, + 0x00016ad0, 0x00016aed, 0x00016b00, 0x00016b2f, + 0x00016b63, 0x00016b77, 0x00016b7d, 0x00016b8f, + 0x00016d43, 0x00016d6a, 0x00016f00, 0x00016f4a, + 0x00016f50, 0x00016f50, 0x00017000, 0x00018cd5, + 0x00018cff, 0x00018d1e, 0x00018d80, 0x00018df2, + 0x0001b000, 0x0001b122, 0x0001b132, 0x0001b132, + 0x0001b150, 0x0001b152, 0x0001b155, 0x0001b155, + 0x0001b164, 0x0001b167, 0x0001b170, 0x0001b2fb, + 0x0001bc00, 0x0001bc6a, 0x0001bc70, 0x0001bc7c, + 0x0001bc80, 0x0001bc88, 0x0001bc90, 0x0001bc99, + 0x0001df0a, 0x0001df0a, 0x0001e100, 0x0001e12c, + 0x0001e14e, 0x0001e14e, 0x0001e290, 0x0001e2ad, + 0x0001e2c0, 0x0001e2eb, 0x0001e4d0, 0x0001e4ea, + 0x0001e5d0, 0x0001e5ed, 0x0001e5f0, 0x0001e5f0, + 0x0001e6c0, 0x0001e6de, 0x0001e6e0, 0x0001e6e2, + 0x0001e6e4, 0x0001e6e5, 0x0001e6e7, 0x0001e6ed, + 0x0001e6f0, 0x0001e6f4, 0x0001e6fe, 0x0001e6fe, + 0x0001e7e0, 0x0001e7e6, 0x0001e7e8, 0x0001e7eb, + 0x0001e7ed, 0x0001e7ee, 0x0001e7f0, 0x0001e7fe, + 0x0001e800, 0x0001e8c4, 0x0001ee00, 0x0001ee03, + 0x0001ee05, 0x0001ee1f, 0x0001ee21, 0x0001ee22, + 0x0001ee24, 0x0001ee24, 0x0001ee27, 0x0001ee27, + 0x0001ee29, 0x0001ee32, 0x0001ee34, 0x0001ee37, + 0x0001ee39, 0x0001ee39, 0x0001ee3b, 0x0001ee3b, + 0x0001ee42, 0x0001ee42, 0x0001ee47, 0x0001ee47, + 0x0001ee49, 0x0001ee49, 0x0001ee4b, 0x0001ee4b, + 0x0001ee4d, 0x0001ee4f, 0x0001ee51, 0x0001ee52, + 0x0001ee54, 0x0001ee54, 0x0001ee57, 0x0001ee57, + 0x0001ee59, 0x0001ee59, 0x0001ee5b, 0x0001ee5b, + 0x0001ee5d, 0x0001ee5d, 0x0001ee5f, 0x0001ee5f, + 0x0001ee61, 0x0001ee62, 0x0001ee64, 0x0001ee64, + 0x0001ee67, 0x0001ee6a, 0x0001ee6c, 0x0001ee72, + 0x0001ee74, 0x0001ee77, 0x0001ee79, 0x0001ee7c, + 0x0001ee7e, 0x0001ee7e, 0x0001ee80, 0x0001ee89, + 0x0001ee8b, 0x0001ee9b, 0x0001eea1, 0x0001eea3, + 0x0001eea5, 0x0001eea9, 0x0001eeab, 0x0001eebb, + 0x00020000, 0x0002a6df, 0x0002a700, 0x0002b81d, + 0x0002b820, 0x0002cead, 0x0002ceb0, 0x0002ebe0, 0x0002ebf0, 0x0002ee5d, 0x0002f800, 0x0002fa1d, - 0x00030000, 0x0003134a, 0x00031350, 0x000323af, + 0x00030000, 0x0003134a, 0x00031350, 0x00033479, 0x0000002b, 0x0000002b, 0x0000003c, 0x0000003e, 0x0000007c, 0x0000007c, 0x0000007e, 0x0000007e, 0x000000ac, 0x000000ac, 0x000000b1, 0x000000b1, @@ -1371,18 +1387,19 @@ static const unsigned int _ucprop_ranges[] = { 0x0000ff1c, 0x0000ff1e, 0x0000ff5c, 0x0000ff5c, 0x0000ff5e, 0x0000ff5e, 0x0000ffe2, 0x0000ffe2, 0x0000ffe9, 0x0000ffec, 0x00010d8e, 0x00010d8f, - 0x0001d6c1, 0x0001d6c1, 0x0001d6db, 0x0001d6db, - 0x0001d6fb, 0x0001d6fb, 0x0001d715, 0x0001d715, - 0x0001d735, 0x0001d735, 0x0001d74f, 0x0001d74f, - 0x0001d76f, 0x0001d76f, 0x0001d789, 0x0001d789, - 0x0001d7a9, 0x0001d7a9, 0x0001d7c3, 0x0001d7c3, - 0x0001eef0, 0x0001eef1, 0x00000024, 0x00000024, + 0x0001cef0, 0x0001cef0, 0x0001d6c1, 0x0001d6c1, + 0x0001d6db, 0x0001d6db, 0x0001d6fb, 0x0001d6fb, + 0x0001d715, 0x0001d715, 0x0001d735, 0x0001d735, + 0x0001d74f, 0x0001d74f, 0x0001d76f, 0x0001d76f, + 0x0001d789, 0x0001d789, 0x0001d7a9, 0x0001d7a9, + 0x0001d7c3, 0x0001d7c3, 0x0001eef0, 0x0001eef1, + 0x0001f8d0, 0x0001f8d8, 0x00000024, 0x00000024, 0x000000a2, 0x000000a5, 0x0000058f, 0x0000058f, 0x0000060b, 0x0000060b, 0x000007fe, 0x000007ff, 0x000009f2, 0x000009f3, 0x000009fb, 0x000009fb, 0x00000af1, 0x00000af1, 0x00000bf9, 0x00000bf9, 0x00000e3f, 0x00000e3f, 0x000017db, 0x000017db, - 0x000020a0, 0x000020c0, 0x0000a838, 0x0000a838, + 0x000020a0, 0x000020c1, 0x0000a838, 0x0000a838, 0x0000fdfc, 0x0000fdfc, 0x0000fe69, 0x0000fe69, 0x0000ff04, 0x0000ff04, 0x0000ffe0, 0x0000ffe1, 0x0000ffe5, 0x0000ffe6, 0x00011fdd, 0x00011fe0, @@ -1442,60 +1459,63 @@ static const unsigned int _ucprop_ranges[] = { 0x00002670, 0x00002767, 0x00002794, 0x000027bf, 0x00002800, 0x000028ff, 0x00002b00, 0x00002b2f, 0x00002b45, 0x00002b46, 0x00002b4d, 0x00002b73, - 0x00002b76, 0x00002b95, 0x00002b97, 0x00002bff, - 0x00002ce5, 0x00002cea, 0x00002e50, 0x00002e51, - 0x00002e80, 0x00002e99, 0x00002e9b, 0x00002ef3, - 0x00002f00, 0x00002fd5, 0x00002ff0, 0x00002fff, - 0x00003004, 0x00003004, 0x00003012, 0x00003013, - 0x00003020, 0x00003020, 0x00003036, 0x00003037, - 0x0000303e, 0x0000303f, 0x00003190, 0x00003191, - 0x00003196, 0x0000319f, 0x000031c0, 0x000031e5, - 0x000031ef, 0x000031ef, 0x00003200, 0x0000321e, - 0x0000322a, 0x00003247, 0x00003250, 0x00003250, - 0x00003260, 0x0000327f, 0x0000328a, 0x000032b0, - 0x000032c0, 0x000033ff, 0x00004dc0, 0x00004dff, - 0x0000a490, 0x0000a4c6, 0x0000a828, 0x0000a82b, - 0x0000a836, 0x0000a837, 0x0000a839, 0x0000a839, - 0x0000aa77, 0x0000aa79, 0x0000fd40, 0x0000fd4f, - 0x0000fdcf, 0x0000fdcf, 0x0000fdfd, 0x0000fdff, - 0x0000ffe4, 0x0000ffe4, 0x0000ffe8, 0x0000ffe8, - 0x0000ffed, 0x0000ffee, 0x0000fffc, 0x0000fffd, - 0x00010137, 0x0001013f, 0x00010179, 0x00010189, - 0x0001018c, 0x0001018e, 0x00010190, 0x0001019c, - 0x000101a0, 0x000101a0, 0x000101d0, 0x000101fc, - 0x00010877, 0x00010878, 0x00010ac8, 0x00010ac8, + 0x00002b76, 0x00002bff, 0x00002ce5, 0x00002cea, + 0x00002e50, 0x00002e51, 0x00002e80, 0x00002e99, + 0x00002e9b, 0x00002ef3, 0x00002f00, 0x00002fd5, + 0x00002ff0, 0x00002fff, 0x00003004, 0x00003004, + 0x00003012, 0x00003013, 0x00003020, 0x00003020, + 0x00003036, 0x00003037, 0x0000303e, 0x0000303f, + 0x00003190, 0x00003191, 0x00003196, 0x0000319f, + 0x000031c0, 0x000031e5, 0x000031ef, 0x000031ef, + 0x00003200, 0x0000321e, 0x0000322a, 0x00003247, + 0x00003250, 0x00003250, 0x00003260, 0x0000327f, + 0x0000328a, 0x000032b0, 0x000032c0, 0x000033ff, + 0x00004dc0, 0x00004dff, 0x0000a490, 0x0000a4c6, + 0x0000a828, 0x0000a82b, 0x0000a836, 0x0000a837, + 0x0000a839, 0x0000a839, 0x0000aa77, 0x0000aa79, + 0x0000fbc3, 0x0000fbd2, 0x0000fd40, 0x0000fd4f, + 0x0000fd90, 0x0000fd91, 0x0000fdc8, 0x0000fdcf, + 0x0000fdfd, 0x0000fdff, 0x0000ffe4, 0x0000ffe4, + 0x0000ffe8, 0x0000ffe8, 0x0000ffed, 0x0000ffee, + 0x0000fffc, 0x0000fffd, 0x00010137, 0x0001013f, + 0x00010179, 0x00010189, 0x0001018c, 0x0001018e, + 0x00010190, 0x0001019c, 0x000101a0, 0x000101a0, + 0x000101d0, 0x000101fc, 0x00010877, 0x00010878, + 0x00010ac8, 0x00010ac8, 0x00010ed1, 0x00010ed8, 0x0001173f, 0x0001173f, 0x00011fd5, 0x00011fdc, 0x00011fe1, 0x00011ff1, 0x00016b3c, 0x00016b3f, 0x00016b45, 0x00016b45, 0x0001bc9c, 0x0001bc9c, - 0x0001cc00, 0x0001ccef, 0x0001cd00, 0x0001ceb3, - 0x0001cf50, 0x0001cfc3, 0x0001d000, 0x0001d0f5, - 0x0001d100, 0x0001d126, 0x0001d129, 0x0001d164, - 0x0001d16a, 0x0001d16c, 0x0001d183, 0x0001d184, - 0x0001d18c, 0x0001d1a9, 0x0001d1ae, 0x0001d1ea, - 0x0001d200, 0x0001d241, 0x0001d245, 0x0001d245, - 0x0001d300, 0x0001d356, 0x0001d800, 0x0001d9ff, - 0x0001da37, 0x0001da3a, 0x0001da6d, 0x0001da74, - 0x0001da76, 0x0001da83, 0x0001da85, 0x0001da86, - 0x0001e14f, 0x0001e14f, 0x0001ecac, 0x0001ecac, - 0x0001ed2e, 0x0001ed2e, 0x0001f000, 0x0001f02b, - 0x0001f030, 0x0001f093, 0x0001f0a0, 0x0001f0ae, - 0x0001f0b1, 0x0001f0bf, 0x0001f0c1, 0x0001f0cf, - 0x0001f0d1, 0x0001f0f5, 0x0001f10d, 0x0001f1ad, - 0x0001f1e6, 0x0001f202, 0x0001f210, 0x0001f23b, - 0x0001f240, 0x0001f248, 0x0001f250, 0x0001f251, - 0x0001f260, 0x0001f265, 0x0001f300, 0x0001f3fa, - 0x0001f400, 0x0001f6d7, 0x0001f6dc, 0x0001f6ec, - 0x0001f6f0, 0x0001f6fc, 0x0001f700, 0x0001f776, - 0x0001f77b, 0x0001f7d9, 0x0001f7e0, 0x0001f7eb, + 0x0001cc00, 0x0001ccef, 0x0001ccfa, 0x0001ccfc, + 0x0001cd00, 0x0001ceb3, 0x0001ceba, 0x0001ced0, + 0x0001cee0, 0x0001ceef, 0x0001cf50, 0x0001cfc3, + 0x0001d000, 0x0001d0f5, 0x0001d100, 0x0001d126, + 0x0001d129, 0x0001d164, 0x0001d16a, 0x0001d16c, + 0x0001d183, 0x0001d184, 0x0001d18c, 0x0001d1a9, + 0x0001d1ae, 0x0001d1ea, 0x0001d200, 0x0001d241, + 0x0001d245, 0x0001d245, 0x0001d300, 0x0001d356, + 0x0001d800, 0x0001d9ff, 0x0001da37, 0x0001da3a, + 0x0001da6d, 0x0001da74, 0x0001da76, 0x0001da83, + 0x0001da85, 0x0001da86, 0x0001e14f, 0x0001e14f, + 0x0001ecac, 0x0001ecac, 0x0001ed2e, 0x0001ed2e, + 0x0001f000, 0x0001f02b, 0x0001f030, 0x0001f093, + 0x0001f0a0, 0x0001f0ae, 0x0001f0b1, 0x0001f0bf, + 0x0001f0c1, 0x0001f0cf, 0x0001f0d1, 0x0001f0f5, + 0x0001f10d, 0x0001f1ad, 0x0001f1e6, 0x0001f202, + 0x0001f210, 0x0001f23b, 0x0001f240, 0x0001f248, + 0x0001f250, 0x0001f251, 0x0001f260, 0x0001f265, + 0x0001f300, 0x0001f3fa, 0x0001f400, 0x0001f6d8, + 0x0001f6dc, 0x0001f6ec, 0x0001f6f0, 0x0001f6fc, + 0x0001f700, 0x0001f7d9, 0x0001f7e0, 0x0001f7eb, 0x0001f7f0, 0x0001f7f0, 0x0001f800, 0x0001f80b, 0x0001f810, 0x0001f847, 0x0001f850, 0x0001f859, 0x0001f860, 0x0001f887, 0x0001f890, 0x0001f8ad, 0x0001f8b0, 0x0001f8bb, 0x0001f8c0, 0x0001f8c1, - 0x0001f900, 0x0001fa53, 0x0001fa60, 0x0001fa6d, - 0x0001fa70, 0x0001fa7c, 0x0001fa80, 0x0001fa89, - 0x0001fa8f, 0x0001fac6, 0x0001face, 0x0001fadc, - 0x0001fadf, 0x0001fae9, 0x0001faf0, 0x0001faf8, - 0x0001fb00, 0x0001fb92, 0x0001fb94, 0x0001fbef, + 0x0001f900, 0x0001fa57, 0x0001fa60, 0x0001fa6d, + 0x0001fa70, 0x0001fa7c, 0x0001fa80, 0x0001fa8a, + 0x0001fa8e, 0x0001fac6, 0x0001fac8, 0x0001fac8, + 0x0001facd, 0x0001fadc, 0x0001fadf, 0x0001faea, + 0x0001faef, 0x0001faf8, 0x0001fb00, 0x0001fb92, + 0x0001fb94, 0x0001fbef, 0x0001fbfa, 0x0001fbfa, 0x00000041, 0x0000005a, 0x00000061, 0x0000007a, 0x000000aa, 0x000000aa, 0x000000b5, 0x000000b5, 0x000000ba, 0x000000ba, 0x000000c0, 0x000000d6, @@ -1554,14 +1574,14 @@ static const unsigned int _ucprop_ranges[] = { 0x00000c05, 0x00000c0c, 0x00000c0e, 0x00000c10, 0x00000c12, 0x00000c28, 0x00000c2a, 0x00000c39, 0x00000c3d, 0x00000c3d, 0x00000c41, 0x00000c44, - 0x00000c58, 0x00000c5a, 0x00000c5d, 0x00000c5d, + 0x00000c58, 0x00000c5a, 0x00000c5c, 0x00000c5d, 0x00000c60, 0x00000c61, 0x00000c66, 0x00000c6f, 0x00000c77, 0x00000c77, 0x00000c7f, 0x00000c80, 0x00000c82, 0x00000c8c, 0x00000c8e, 0x00000c90, 0x00000c92, 0x00000ca8, 0x00000caa, 0x00000cb3, 0x00000cb5, 0x00000cb9, 0x00000cbd, 0x00000cc4, 0x00000cc6, 0x00000cc8, 0x00000cca, 0x00000ccb, - 0x00000cd5, 0x00000cd6, 0x00000cdd, 0x00000cde, + 0x00000cd5, 0x00000cd6, 0x00000cdc, 0x00000cde, 0x00000ce0, 0x00000ce1, 0x00000ce6, 0x00000cef, 0x00000cf1, 0x00000cf3, 0x00000d02, 0x00000d0c, 0x00000d0e, 0x00000d10, 0x00000d12, 0x00000d3a, @@ -1683,123 +1703,123 @@ static const unsigned int _ucprop_ranges[] = { 0x0000a4d0, 0x0000a60c, 0x0000a610, 0x0000a62b, 0x0000a640, 0x0000a66e, 0x0000a680, 0x0000a69d, 0x0000a6a0, 0x0000a6ef, 0x0000a6f2, 0x0000a6f7, - 0x0000a722, 0x0000a787, 0x0000a789, 0x0000a7cd, - 0x0000a7d0, 0x0000a7d1, 0x0000a7d3, 0x0000a7d3, - 0x0000a7d5, 0x0000a7dc, 0x0000a7f2, 0x0000a801, - 0x0000a803, 0x0000a805, 0x0000a807, 0x0000a80a, - 0x0000a80c, 0x0000a824, 0x0000a827, 0x0000a827, - 0x0000a830, 0x0000a837, 0x0000a840, 0x0000a873, - 0x0000a880, 0x0000a8c3, 0x0000a8ce, 0x0000a8d9, - 0x0000a8f2, 0x0000a8fe, 0x0000a900, 0x0000a925, - 0x0000a92e, 0x0000a946, 0x0000a952, 0x0000a953, - 0x0000a95f, 0x0000a97c, 0x0000a983, 0x0000a9b2, - 0x0000a9b4, 0x0000a9b5, 0x0000a9ba, 0x0000a9bb, - 0x0000a9be, 0x0000a9cd, 0x0000a9cf, 0x0000a9d9, - 0x0000a9de, 0x0000a9e4, 0x0000a9e6, 0x0000a9fe, - 0x0000aa00, 0x0000aa28, 0x0000aa2f, 0x0000aa30, - 0x0000aa33, 0x0000aa34, 0x0000aa40, 0x0000aa42, - 0x0000aa44, 0x0000aa4b, 0x0000aa4d, 0x0000aa4d, - 0x0000aa50, 0x0000aa59, 0x0000aa5c, 0x0000aa7b, - 0x0000aa7d, 0x0000aaaf, 0x0000aab1, 0x0000aab1, - 0x0000aab5, 0x0000aab6, 0x0000aab9, 0x0000aabd, - 0x0000aac0, 0x0000aac0, 0x0000aac2, 0x0000aac2, - 0x0000aadb, 0x0000aaeb, 0x0000aaee, 0x0000aaf5, - 0x0000ab01, 0x0000ab06, 0x0000ab09, 0x0000ab0e, - 0x0000ab11, 0x0000ab16, 0x0000ab20, 0x0000ab26, - 0x0000ab28, 0x0000ab2e, 0x0000ab30, 0x0000ab69, - 0x0000ab70, 0x0000abe4, 0x0000abe6, 0x0000abe7, - 0x0000abe9, 0x0000abec, 0x0000abf0, 0x0000abf9, - 0x0000ac00, 0x0000d7a3, 0x0000d7b0, 0x0000d7c6, - 0x0000d7cb, 0x0000d7fb, 0x0000d800, 0x0000fa6d, - 0x0000fa70, 0x0000fad9, 0x0000fb00, 0x0000fb06, - 0x0000fb13, 0x0000fb17, 0x0000ff21, 0x0000ff3a, - 0x0000ff41, 0x0000ff5a, 0x0000ff66, 0x0000ffbe, - 0x0000ffc2, 0x0000ffc7, 0x0000ffca, 0x0000ffcf, - 0x0000ffd2, 0x0000ffd7, 0x0000ffda, 0x0000ffdc, - 0x00010000, 0x0001000b, 0x0001000d, 0x00010026, - 0x00010028, 0x0001003a, 0x0001003c, 0x0001003d, - 0x0001003f, 0x0001004d, 0x00010050, 0x0001005d, - 0x00010080, 0x000100fa, 0x00010100, 0x00010100, - 0x00010102, 0x00010102, 0x00010107, 0x00010133, - 0x00010137, 0x0001013f, 0x0001018d, 0x0001018e, - 0x000101d0, 0x000101fc, 0x00010280, 0x0001029c, - 0x000102a0, 0x000102d0, 0x00010300, 0x00010323, - 0x0001032d, 0x0001034a, 0x00010350, 0x00010375, - 0x00010380, 0x0001039d, 0x0001039f, 0x000103c3, - 0x000103c8, 0x000103d5, 0x00010400, 0x0001049d, - 0x000104a0, 0x000104a9, 0x000104b0, 0x000104d3, - 0x000104d8, 0x000104fb, 0x00010500, 0x00010527, - 0x00010530, 0x00010563, 0x0001056f, 0x0001057a, - 0x0001057c, 0x0001058a, 0x0001058c, 0x00010592, - 0x00010594, 0x00010595, 0x00010597, 0x000105a1, - 0x000105a3, 0x000105b1, 0x000105b3, 0x000105b9, - 0x000105bb, 0x000105bc, 0x000105c0, 0x000105f3, - 0x00010600, 0x00010736, 0x00010740, 0x00010755, - 0x00010760, 0x00010767, 0x00010780, 0x00010785, - 0x00010787, 0x000107b0, 0x000107b2, 0x000107ba, - 0x00011000, 0x00011000, 0x00011002, 0x00011037, - 0x00011047, 0x0001104d, 0x00011066, 0x0001106f, - 0x00011071, 0x00011072, 0x00011075, 0x00011075, - 0x00011082, 0x000110b2, 0x000110b7, 0x000110b8, - 0x000110bb, 0x000110c1, 0x000110cd, 0x000110cd, - 0x000110d0, 0x000110e8, 0x000110f0, 0x000110f9, - 0x00011103, 0x00011126, 0x0001112c, 0x0001112c, - 0x00011136, 0x00011147, 0x00011150, 0x00011172, - 0x00011174, 0x00011176, 0x00011182, 0x000111b5, - 0x000111bf, 0x000111c8, 0x000111cd, 0x000111ce, - 0x000111d0, 0x000111df, 0x000111e1, 0x000111f4, - 0x00011200, 0x00011211, 0x00011213, 0x0001122e, - 0x00011232, 0x00011233, 0x00011235, 0x00011235, - 0x00011238, 0x0001123d, 0x0001123f, 0x00011240, - 0x00011280, 0x00011286, 0x00011288, 0x00011288, - 0x0001128a, 0x0001128d, 0x0001128f, 0x0001129d, - 0x0001129f, 0x000112a9, 0x000112b0, 0x000112de, - 0x000112e0, 0x000112e2, 0x000112f0, 0x000112f9, - 0x00011302, 0x00011303, 0x00011305, 0x0001130c, - 0x0001130f, 0x00011310, 0x00011313, 0x00011328, - 0x0001132a, 0x00011330, 0x00011332, 0x00011333, - 0x00011335, 0x00011339, 0x0001133d, 0x0001133f, - 0x00011341, 0x00011344, 0x00011347, 0x00011348, - 0x0001134b, 0x0001134d, 0x00011350, 0x00011350, - 0x00011357, 0x00011357, 0x0001135d, 0x00011363, - 0x00011380, 0x00011389, 0x0001138b, 0x0001138b, - 0x0001138e, 0x0001138e, 0x00011390, 0x000113b5, - 0x000113b7, 0x000113ba, 0x000113c2, 0x000113c2, - 0x000113c5, 0x000113c5, 0x000113c7, 0x000113ca, - 0x000113cc, 0x000113cd, 0x000113cf, 0x000113cf, - 0x000113d1, 0x000113d1, 0x000113d3, 0x000113d5, - 0x000113d7, 0x000113d8, 0x00011400, 0x00011437, - 0x00011440, 0x00011441, 0x00011445, 0x00011445, - 0x00011447, 0x0001145b, 0x0001145d, 0x0001145d, - 0x0001145f, 0x00011461, 0x00011480, 0x000114b2, - 0x000114b9, 0x000114b9, 0x000114bb, 0x000114be, - 0x000114c1, 0x000114c1, 0x000114c4, 0x000114c7, - 0x000114d0, 0x000114d9, 0x00011580, 0x000115b1, - 0x000115b8, 0x000115bb, 0x000115be, 0x000115be, - 0x000115c1, 0x000115db, 0x00011600, 0x00011632, - 0x0001163b, 0x0001163c, 0x0001163e, 0x0001163e, - 0x00011641, 0x00011644, 0x00011650, 0x00011659, - 0x00011680, 0x000116aa, 0x000116ac, 0x000116ac, - 0x000116ae, 0x000116af, 0x000116b6, 0x000116b6, - 0x000116b8, 0x000116b9, 0x000116c0, 0x000116c9, - 0x000116d0, 0x000116e3, 0x00011700, 0x0001171a, - 0x0001171e, 0x0001171e, 0x00011720, 0x00011721, - 0x00011726, 0x00011726, 0x00011730, 0x00011746, - 0x00011800, 0x0001182e, 0x00011838, 0x00011838, - 0x0001183b, 0x0001183b, 0x000118a0, 0x000118f2, - 0x000118ff, 0x00011906, 0x00011909, 0x00011909, - 0x0001190c, 0x00011913, 0x00011915, 0x00011916, - 0x00011918, 0x00011935, 0x00011937, 0x00011938, - 0x0001193d, 0x0001193d, 0x0001193f, 0x00011942, - 0x00011944, 0x00011946, 0x00011950, 0x00011959, - 0x000119a0, 0x000119a7, 0x000119aa, 0x000119d3, - 0x000119dc, 0x000119df, 0x000119e1, 0x000119e4, - 0x00011a00, 0x00011a00, 0x00011a07, 0x00011a08, - 0x00011a0b, 0x00011a32, 0x00011a39, 0x00011a3a, - 0x00011a3f, 0x00011a46, 0x00011a50, 0x00011a50, - 0x00011a57, 0x00011a58, 0x00011a5c, 0x00011a89, - 0x00011a97, 0x00011a97, 0x00011a9a, 0x00011aa2, - 0x00011ab0, 0x00011af8, 0x00011b00, 0x00011b09, + 0x0000a722, 0x0000a787, 0x0000a789, 0x0000a7dc, + 0x0000a7f1, 0x0000a801, 0x0000a803, 0x0000a805, + 0x0000a807, 0x0000a80a, 0x0000a80c, 0x0000a824, + 0x0000a827, 0x0000a827, 0x0000a830, 0x0000a837, + 0x0000a840, 0x0000a873, 0x0000a880, 0x0000a8c3, + 0x0000a8ce, 0x0000a8d9, 0x0000a8f2, 0x0000a8fe, + 0x0000a900, 0x0000a925, 0x0000a92e, 0x0000a946, + 0x0000a952, 0x0000a953, 0x0000a95f, 0x0000a97c, + 0x0000a983, 0x0000a9b2, 0x0000a9b4, 0x0000a9b5, + 0x0000a9ba, 0x0000a9bb, 0x0000a9be, 0x0000a9cd, + 0x0000a9cf, 0x0000a9d9, 0x0000a9de, 0x0000a9e4, + 0x0000a9e6, 0x0000a9fe, 0x0000aa00, 0x0000aa28, + 0x0000aa2f, 0x0000aa30, 0x0000aa33, 0x0000aa34, + 0x0000aa40, 0x0000aa42, 0x0000aa44, 0x0000aa4b, + 0x0000aa4d, 0x0000aa4d, 0x0000aa50, 0x0000aa59, + 0x0000aa5c, 0x0000aa7b, 0x0000aa7d, 0x0000aaaf, + 0x0000aab1, 0x0000aab1, 0x0000aab5, 0x0000aab6, + 0x0000aab9, 0x0000aabd, 0x0000aac0, 0x0000aac0, + 0x0000aac2, 0x0000aac2, 0x0000aadb, 0x0000aaeb, + 0x0000aaee, 0x0000aaf5, 0x0000ab01, 0x0000ab06, + 0x0000ab09, 0x0000ab0e, 0x0000ab11, 0x0000ab16, + 0x0000ab20, 0x0000ab26, 0x0000ab28, 0x0000ab2e, + 0x0000ab30, 0x0000ab69, 0x0000ab70, 0x0000abe4, + 0x0000abe6, 0x0000abe7, 0x0000abe9, 0x0000abec, + 0x0000abf0, 0x0000abf9, 0x0000ac00, 0x0000d7a3, + 0x0000d7b0, 0x0000d7c6, 0x0000d7cb, 0x0000d7fb, + 0x0000d800, 0x0000fa6d, 0x0000fa70, 0x0000fad9, + 0x0000fb00, 0x0000fb06, 0x0000fb13, 0x0000fb17, + 0x0000ff21, 0x0000ff3a, 0x0000ff41, 0x0000ff5a, + 0x0000ff66, 0x0000ffbe, 0x0000ffc2, 0x0000ffc7, + 0x0000ffca, 0x0000ffcf, 0x0000ffd2, 0x0000ffd7, + 0x0000ffda, 0x0000ffdc, 0x00010000, 0x0001000b, + 0x0001000d, 0x00010026, 0x00010028, 0x0001003a, + 0x0001003c, 0x0001003d, 0x0001003f, 0x0001004d, + 0x00010050, 0x0001005d, 0x00010080, 0x000100fa, + 0x00010100, 0x00010100, 0x00010102, 0x00010102, + 0x00010107, 0x00010133, 0x00010137, 0x0001013f, + 0x0001018d, 0x0001018e, 0x000101d0, 0x000101fc, + 0x00010280, 0x0001029c, 0x000102a0, 0x000102d0, + 0x00010300, 0x00010323, 0x0001032d, 0x0001034a, + 0x00010350, 0x00010375, 0x00010380, 0x0001039d, + 0x0001039f, 0x000103c3, 0x000103c8, 0x000103d5, + 0x00010400, 0x0001049d, 0x000104a0, 0x000104a9, + 0x000104b0, 0x000104d3, 0x000104d8, 0x000104fb, + 0x00010500, 0x00010527, 0x00010530, 0x00010563, + 0x0001056f, 0x0001057a, 0x0001057c, 0x0001058a, + 0x0001058c, 0x00010592, 0x00010594, 0x00010595, + 0x00010597, 0x000105a1, 0x000105a3, 0x000105b1, + 0x000105b3, 0x000105b9, 0x000105bb, 0x000105bc, + 0x000105c0, 0x000105f3, 0x00010600, 0x00010736, + 0x00010740, 0x00010755, 0x00010760, 0x00010767, + 0x00010780, 0x00010785, 0x00010787, 0x000107b0, + 0x000107b2, 0x000107ba, 0x00011000, 0x00011000, + 0x00011002, 0x00011037, 0x00011047, 0x0001104d, + 0x00011066, 0x0001106f, 0x00011071, 0x00011072, + 0x00011075, 0x00011075, 0x00011082, 0x000110b2, + 0x000110b7, 0x000110b8, 0x000110bb, 0x000110c1, + 0x000110cd, 0x000110cd, 0x000110d0, 0x000110e8, + 0x000110f0, 0x000110f9, 0x00011103, 0x00011126, + 0x0001112c, 0x0001112c, 0x00011136, 0x00011147, + 0x00011150, 0x00011172, 0x00011174, 0x00011176, + 0x00011182, 0x000111b5, 0x000111bf, 0x000111c8, + 0x000111cd, 0x000111ce, 0x000111d0, 0x000111df, + 0x000111e1, 0x000111f4, 0x00011200, 0x00011211, + 0x00011213, 0x0001122e, 0x00011232, 0x00011233, + 0x00011235, 0x00011235, 0x00011238, 0x0001123d, + 0x0001123f, 0x00011240, 0x00011280, 0x00011286, + 0x00011288, 0x00011288, 0x0001128a, 0x0001128d, + 0x0001128f, 0x0001129d, 0x0001129f, 0x000112a9, + 0x000112b0, 0x000112de, 0x000112e0, 0x000112e2, + 0x000112f0, 0x000112f9, 0x00011302, 0x00011303, + 0x00011305, 0x0001130c, 0x0001130f, 0x00011310, + 0x00011313, 0x00011328, 0x0001132a, 0x00011330, + 0x00011332, 0x00011333, 0x00011335, 0x00011339, + 0x0001133d, 0x0001133f, 0x00011341, 0x00011344, + 0x00011347, 0x00011348, 0x0001134b, 0x0001134d, + 0x00011350, 0x00011350, 0x00011357, 0x00011357, + 0x0001135d, 0x00011363, 0x00011380, 0x00011389, + 0x0001138b, 0x0001138b, 0x0001138e, 0x0001138e, + 0x00011390, 0x000113b5, 0x000113b7, 0x000113ba, + 0x000113c2, 0x000113c2, 0x000113c5, 0x000113c5, + 0x000113c7, 0x000113ca, 0x000113cc, 0x000113cd, + 0x000113cf, 0x000113cf, 0x000113d1, 0x000113d1, + 0x000113d3, 0x000113d5, 0x000113d7, 0x000113d8, + 0x00011400, 0x00011437, 0x00011440, 0x00011441, + 0x00011445, 0x00011445, 0x00011447, 0x0001145b, + 0x0001145d, 0x0001145d, 0x0001145f, 0x00011461, + 0x00011480, 0x000114b2, 0x000114b9, 0x000114b9, + 0x000114bb, 0x000114be, 0x000114c1, 0x000114c1, + 0x000114c4, 0x000114c7, 0x000114d0, 0x000114d9, + 0x00011580, 0x000115b1, 0x000115b8, 0x000115bb, + 0x000115be, 0x000115be, 0x000115c1, 0x000115db, + 0x00011600, 0x00011632, 0x0001163b, 0x0001163c, + 0x0001163e, 0x0001163e, 0x00011641, 0x00011644, + 0x00011650, 0x00011659, 0x00011680, 0x000116aa, + 0x000116ac, 0x000116ac, 0x000116ae, 0x000116af, + 0x000116b6, 0x000116b6, 0x000116b8, 0x000116b9, + 0x000116c0, 0x000116c9, 0x000116d0, 0x000116e3, + 0x00011700, 0x0001171a, 0x0001171e, 0x0001171e, + 0x00011720, 0x00011721, 0x00011726, 0x00011726, + 0x00011730, 0x00011746, 0x00011800, 0x0001182e, + 0x00011838, 0x00011838, 0x0001183b, 0x0001183b, + 0x000118a0, 0x000118f2, 0x000118ff, 0x00011906, + 0x00011909, 0x00011909, 0x0001190c, 0x00011913, + 0x00011915, 0x00011916, 0x00011918, 0x00011935, + 0x00011937, 0x00011938, 0x0001193d, 0x0001193d, + 0x0001193f, 0x00011942, 0x00011944, 0x00011946, + 0x00011950, 0x00011959, 0x000119a0, 0x000119a7, + 0x000119aa, 0x000119d3, 0x000119dc, 0x000119df, + 0x000119e1, 0x000119e4, 0x00011a00, 0x00011a00, + 0x00011a07, 0x00011a08, 0x00011a0b, 0x00011a32, + 0x00011a39, 0x00011a3a, 0x00011a3f, 0x00011a46, + 0x00011a50, 0x00011a50, 0x00011a57, 0x00011a58, + 0x00011a5c, 0x00011a89, 0x00011a97, 0x00011a97, + 0x00011a9a, 0x00011aa2, 0x00011ab0, 0x00011af8, + 0x00011b00, 0x00011b09, 0x00011b61, 0x00011b61, + 0x00011b65, 0x00011b65, 0x00011b67, 0x00011b67, 0x00011bc0, 0x00011be1, 0x00011bf0, 0x00011bf9, 0x00011c00, 0x00011c08, 0x00011c0a, 0x00011c2f, 0x00011c3e, 0x00011c45, 0x00011c50, 0x00011c6c, @@ -1811,6 +1831,7 @@ static const unsigned int _ucprop_ranges[] = { 0x00011d67, 0x00011d68, 0x00011d6a, 0x00011d8e, 0x00011d93, 0x00011d94, 0x00011d96, 0x00011d96, 0x00011d98, 0x00011d98, 0x00011da0, 0x00011da9, + 0x00011db0, 0x00011ddb, 0x00011de0, 0x00011de9, 0x00011ee0, 0x00011ef2, 0x00011ef5, 0x00011ef8, 0x00011f02, 0x00011f10, 0x00011f12, 0x00011f35, 0x00011f3e, 0x00011f3f, 0x00011f41, 0x00011f41, @@ -1829,11 +1850,12 @@ static const unsigned int _ucprop_ranges[] = { 0x00016b50, 0x00016b59, 0x00016b5b, 0x00016b61, 0x00016b63, 0x00016b77, 0x00016b7d, 0x00016b8f, 0x00016d40, 0x00016d79, 0x00016e40, 0x00016e9a, + 0x00016ea0, 0x00016eb8, 0x00016ebb, 0x00016ed3, 0x00016f00, 0x00016f4a, 0x00016f50, 0x00016f87, 0x00016f93, 0x00016f9f, 0x00016fe0, 0x00016fe1, - 0x00016fe3, 0x00016fe3, 0x00016ff0, 0x00016ff1, - 0x00017000, 0x000187f7, 0x00018800, 0x00018cd5, - 0x00018cff, 0x00018d08, 0x0001aff0, 0x0001aff3, + 0x00016fe3, 0x00016fe3, 0x00016ff0, 0x00016ff6, + 0x00017000, 0x00018cd5, 0x00018cff, 0x00018d1e, + 0x00018d80, 0x00018df2, 0x0001aff0, 0x0001aff3, 0x0001aff5, 0x0001affb, 0x0001affd, 0x0001affe, 0x0001b000, 0x0001b122, 0x0001b132, 0x0001b132, 0x0001b150, 0x0001b152, 0x0001b155, 0x0001b155, @@ -1872,186 +1894,189 @@ static const unsigned int _ucprop_ranges[] = { 0x0001e2f0, 0x0001e2f9, 0x0001e4d0, 0x0001e4eb, 0x0001e4f0, 0x0001e4f9, 0x0001e5d0, 0x0001e5ed, 0x0001e5f0, 0x0001e5fa, 0x0001e5ff, 0x0001e5ff, + 0x0001e6c0, 0x0001e6de, 0x0001e6e0, 0x0001e6e2, + 0x0001e6e4, 0x0001e6e5, 0x0001e6e7, 0x0001e6ed, + 0x0001e6f0, 0x0001e6f4, 0x0001e6fe, 0x0001e6ff, 0x0001e7e0, 0x0001e7e6, 0x0001e7e8, 0x0001e7eb, 0x0001e7ed, 0x0001e7ee, 0x0001e7f0, 0x0001e7fe, 0x0001f110, 0x0001f12e, 0x0001f130, 0x0001f169, 0x0001f170, 0x0001f1ac, 0x0001f1e6, 0x0001f202, 0x0001f210, 0x0001f23b, 0x0001f240, 0x0001f248, 0x0001f250, 0x0001f251, 0x00020000, 0x0002a6df, - 0x0002a700, 0x0002b739, 0x0002b740, 0x0002b81d, - 0x0002b820, 0x0002cea1, 0x0002ceb0, 0x0002ebe0, - 0x0002ebf0, 0x0002ee5d, 0x0002f800, 0x0002fa1d, - 0x00030000, 0x0003134a, 0x00031350, 0x000323af, - 0x000f0000, 0x000ffffd, 0x00100000, 0x0010fffd, - 0x000005be, 0x000005be, 0x000005c0, 0x000005c0, - 0x000005c3, 0x000005c3, 0x000005c6, 0x000005c6, - 0x000005d0, 0x000005ea, 0x000005ef, 0x000005f4, - 0x000007c0, 0x000007ea, 0x000007f4, 0x000007f5, - 0x000007fa, 0x000007fa, 0x000007fe, 0x00000815, - 0x0000081a, 0x0000081a, 0x00000824, 0x00000824, - 0x00000828, 0x00000828, 0x00000830, 0x0000083e, - 0x00000840, 0x00000858, 0x0000085e, 0x0000085e, - 0x0000200f, 0x0000200f, 0x0000fb1d, 0x0000fb1d, - 0x0000fb1f, 0x0000fb28, 0x0000fb2a, 0x0000fb36, - 0x0000fb38, 0x0000fb3c, 0x0000fb3e, 0x0000fb3e, - 0x0000fb40, 0x0000fb41, 0x0000fb43, 0x0000fb44, - 0x0000fb46, 0x0000fb4f, 0x00010800, 0x00010805, - 0x00010808, 0x00010808, 0x0001080a, 0x00010835, - 0x00010837, 0x00010838, 0x0001083c, 0x0001083c, - 0x0001083f, 0x00010855, 0x00010857, 0x0001089e, - 0x000108a7, 0x000108af, 0x000108e0, 0x000108f2, - 0x000108f4, 0x000108f5, 0x000108fb, 0x0001091b, - 0x00010920, 0x00010939, 0x0001093f, 0x0001093f, - 0x00010980, 0x000109b7, 0x000109bc, 0x000109cf, - 0x000109d2, 0x00010a00, 0x00010a10, 0x00010a13, - 0x00010a15, 0x00010a17, 0x00010a19, 0x00010a35, - 0x00010a40, 0x00010a48, 0x00010a50, 0x00010a58, - 0x00010a60, 0x00010a9f, 0x00010ac0, 0x00010ae4, - 0x00010aeb, 0x00010af6, 0x00010b00, 0x00010b35, - 0x00010b40, 0x00010b55, 0x00010b58, 0x00010b72, - 0x00010b78, 0x00010b91, 0x00010b99, 0x00010b9c, - 0x00010ba9, 0x00010baf, 0x00010c00, 0x00010c48, - 0x00010c80, 0x00010cb2, 0x00010cc0, 0x00010cf2, - 0x00010cfa, 0x00010cff, 0x00010d4a, 0x00010d65, - 0x00010d6f, 0x00010d85, 0x00010d8e, 0x00010d8f, - 0x00010e80, 0x00010ea9, 0x00010ead, 0x00010ead, - 0x00010eb0, 0x00010eb1, 0x00010f00, 0x00010f27, - 0x00010f70, 0x00010f81, 0x00010f86, 0x00010f89, - 0x00010fb0, 0x00010fcb, 0x00010fe0, 0x00010ff6, - 0x0001e800, 0x0001e8c4, 0x0001e8c7, 0x0001e8cf, - 0x0001e900, 0x0001e943, 0x0001e94b, 0x0001e94b, - 0x0001e950, 0x0001e959, 0x0001e95e, 0x0001e95f, - 0x00000030, 0x00000039, 0x000000b2, 0x000000b3, - 0x000000b9, 0x000000b9, 0x000006f0, 0x000006f9, - 0x00002070, 0x00002070, 0x00002074, 0x00002079, - 0x00002080, 0x00002089, 0x00002488, 0x0000249b, - 0x0000ff10, 0x0000ff19, 0x000102e1, 0x000102fb, - 0x0001ccf0, 0x0001ccf9, 0x0001d7ce, 0x0001d7ff, - 0x0001f100, 0x0001f10a, 0x0001fbf0, 0x0001fbf9, - 0x0000002b, 0x0000002b, 0x0000002d, 0x0000002d, - 0x0000207a, 0x0000207b, 0x0000208a, 0x0000208b, - 0x00002212, 0x00002212, 0x0000fb29, 0x0000fb29, - 0x0000fe62, 0x0000fe63, 0x0000ff0b, 0x0000ff0b, - 0x0000ff0d, 0x0000ff0d, 0x00000023, 0x00000025, - 0x000000a2, 0x000000a5, 0x000000b0, 0x000000b1, - 0x0000058f, 0x0000058f, 0x00000609, 0x0000060a, - 0x0000066a, 0x0000066a, 0x000009f2, 0x000009f3, - 0x000009fb, 0x000009fb, 0x00000af1, 0x00000af1, - 0x00000bf9, 0x00000bf9, 0x00000e3f, 0x00000e3f, - 0x000017db, 0x000017db, 0x00002030, 0x00002034, - 0x000020a0, 0x000020c0, 0x0000212e, 0x0000212e, - 0x00002213, 0x00002213, 0x0000a838, 0x0000a839, - 0x0000fe5f, 0x0000fe5f, 0x0000fe69, 0x0000fe6a, - 0x0000ff03, 0x0000ff05, 0x0000ffe0, 0x0000ffe1, - 0x0000ffe5, 0x0000ffe6, 0x00011fdd, 0x00011fe0, - 0x0001e2ff, 0x0001e2ff, 0x00000600, 0x00000605, - 0x00000660, 0x00000669, 0x0000066b, 0x0000066c, - 0x000006dd, 0x000006dd, 0x00000890, 0x00000891, - 0x000008e2, 0x000008e2, 0x00010d30, 0x00010d39, - 0x00010d40, 0x00010d49, 0x00010e60, 0x00010e7e, - 0x0000002c, 0x0000002c, 0x0000002e, 0x0000002f, - 0x0000003a, 0x0000003a, 0x000000a0, 0x000000a0, - 0x0000060c, 0x0000060c, 0x0000202f, 0x0000202f, - 0x00002044, 0x00002044, 0x0000fe50, 0x0000fe50, - 0x0000fe52, 0x0000fe52, 0x0000fe55, 0x0000fe55, - 0x0000ff0c, 0x0000ff0c, 0x0000ff0e, 0x0000ff0f, - 0x0000ff1a, 0x0000ff1a, 0x0000000a, 0x0000000a, - 0x0000000d, 0x0000000d, 0x0000001c, 0x0000001e, - 0x00000085, 0x00000085, 0x00002029, 0x00002029, - 0x00000009, 0x00000009, 0x0000000b, 0x0000000b, - 0x0000001f, 0x0000001f, 0x0000000c, 0x0000000c, - 0x00000020, 0x00000020, 0x00001680, 0x00001680, - 0x00002000, 0x0000200a, 0x00002028, 0x00002028, - 0x0000205f, 0x0000205f, 0x00003000, 0x00003000, - 0x00000000, 0x00000008, 0x0000000e, 0x0000001b, - 0x00000021, 0x00000022, 0x00000026, 0x0000002a, - 0x0000003b, 0x00000040, 0x0000005b, 0x00000060, - 0x0000007b, 0x00000084, 0x00000086, 0x0000009f, - 0x000000a1, 0x000000a1, 0x000000a6, 0x000000a9, - 0x000000ab, 0x000000af, 0x000000b4, 0x000000b4, - 0x000000b6, 0x000000b8, 0x000000bb, 0x000000bf, - 0x000000d7, 0x000000d7, 0x000000f7, 0x000000f7, - 0x000002b9, 0x000002ba, 0x000002c2, 0x000002cf, - 0x000002d2, 0x000002df, 0x000002e5, 0x000002ed, - 0x000002ef, 0x0000036f, 0x00000374, 0x00000375, - 0x0000037e, 0x0000037e, 0x00000384, 0x00000385, - 0x00000387, 0x00000387, 0x000003f6, 0x000003f6, - 0x00000483, 0x00000489, 0x0000058a, 0x0000058a, - 0x0000058d, 0x0000058e, 0x00000591, 0x000005bd, - 0x000005bf, 0x000005bf, 0x000005c1, 0x000005c2, - 0x000005c4, 0x000005c5, 0x000005c7, 0x000005c7, - 0x00000606, 0x00000607, 0x0000060e, 0x0000061a, - 0x0000064b, 0x0000065f, 0x00000670, 0x00000670, - 0x000006d6, 0x000006dc, 0x000006de, 0x000006e4, - 0x000006e7, 0x000006ed, 0x00000711, 0x00000711, - 0x00000730, 0x0000074a, 0x000007a6, 0x000007b0, - 0x000007eb, 0x000007f3, 0x000007f6, 0x000007f9, - 0x000007fd, 0x000007fd, 0x00000816, 0x00000819, - 0x0000081b, 0x00000823, 0x00000825, 0x00000827, - 0x00000829, 0x0000082d, 0x00000859, 0x0000085b, - 0x00000897, 0x0000089f, 0x000008ca, 0x000008e1, - 0x000008e3, 0x00000902, 0x0000093a, 0x0000093a, - 0x0000093c, 0x0000093c, 0x00000941, 0x00000948, - 0x0000094d, 0x0000094d, 0x00000951, 0x00000957, - 0x00000962, 0x00000963, 0x00000981, 0x00000981, - 0x000009bc, 0x000009bc, 0x000009c1, 0x000009c4, - 0x000009cd, 0x000009cd, 0x000009e2, 0x000009e3, - 0x000009fe, 0x000009fe, 0x00000a01, 0x00000a02, - 0x00000a3c, 0x00000a3c, 0x00000a41, 0x00000a42, - 0x00000a47, 0x00000a48, 0x00000a4b, 0x00000a4d, - 0x00000a51, 0x00000a51, 0x00000a70, 0x00000a71, - 0x00000a75, 0x00000a75, 0x00000a81, 0x00000a82, - 0x00000abc, 0x00000abc, 0x00000ac1, 0x00000ac5, - 0x00000ac7, 0x00000ac8, 0x00000acd, 0x00000acd, - 0x00000ae2, 0x00000ae3, 0x00000afa, 0x00000aff, - 0x00000b01, 0x00000b01, 0x00000b3c, 0x00000b3c, - 0x00000b3f, 0x00000b3f, 0x00000b41, 0x00000b44, - 0x00000b4d, 0x00000b4d, 0x00000b55, 0x00000b56, - 0x00000b62, 0x00000b63, 0x00000b82, 0x00000b82, - 0x00000bc0, 0x00000bc0, 0x00000bcd, 0x00000bcd, - 0x00000bf3, 0x00000bf8, 0x00000bfa, 0x00000bfa, - 0x00000c00, 0x00000c00, 0x00000c04, 0x00000c04, - 0x00000c3c, 0x00000c3c, 0x00000c3e, 0x00000c40, - 0x00000c46, 0x00000c48, 0x00000c4a, 0x00000c4d, - 0x00000c55, 0x00000c56, 0x00000c62, 0x00000c63, - 0x00000c78, 0x00000c7e, 0x00000c81, 0x00000c81, - 0x00000cbc, 0x00000cbc, 0x00000ccc, 0x00000ccd, - 0x00000ce2, 0x00000ce3, 0x00000d00, 0x00000d01, - 0x00000d3b, 0x00000d3c, 0x00000d41, 0x00000d44, - 0x00000d4d, 0x00000d4d, 0x00000d62, 0x00000d63, - 0x00000d81, 0x00000d81, 0x00000dca, 0x00000dca, - 0x00000dd2, 0x00000dd4, 0x00000dd6, 0x00000dd6, - 0x00000e31, 0x00000e31, 0x00000e34, 0x00000e3a, - 0x00000e47, 0x00000e4e, 0x00000eb1, 0x00000eb1, - 0x00000eb4, 0x00000ebc, 0x00000ec8, 0x00000ece, - 0x00000f18, 0x00000f19, 0x00000f35, 0x00000f35, - 0x00000f37, 0x00000f37, 0x00000f39, 0x00000f3d, - 0x00000f71, 0x00000f7e, 0x00000f80, 0x00000f84, - 0x00000f86, 0x00000f87, 0x00000f8d, 0x00000f97, - 0x00000f99, 0x00000fbc, 0x00000fc6, 0x00000fc6, - 0x0000102d, 0x00001030, 0x00001032, 0x00001037, - 0x00001039, 0x0000103a, 0x0000103d, 0x0000103e, - 0x00001058, 0x00001059, 0x0000105e, 0x00001060, - 0x00001071, 0x00001074, 0x00001082, 0x00001082, - 0x00001085, 0x00001086, 0x0000108d, 0x0000108d, - 0x0000109d, 0x0000109d, 0x0000135d, 0x0000135f, - 0x00001390, 0x00001399, 0x00001400, 0x00001400, - 0x0000169b, 0x0000169c, 0x00001712, 0x00001714, - 0x00001732, 0x00001733, 0x00001752, 0x00001753, - 0x00001772, 0x00001773, 0x000017b4, 0x000017b5, - 0x000017b7, 0x000017bd, 0x000017c6, 0x000017c6, - 0x000017c9, 0x000017d3, 0x000017dd, 0x000017dd, - 0x000017f0, 0x000017f9, 0x00001800, 0x0000180f, - 0x00001885, 0x00001886, 0x000018a9, 0x000018a9, - 0x00001920, 0x00001922, 0x00001927, 0x00001928, - 0x00001932, 0x00001932, 0x00001939, 0x0000193b, - 0x00001940, 0x00001940, 0x00001944, 0x00001945, - 0x000019de, 0x000019ff, 0x00001a17, 0x00001a18, - 0x00001a1b, 0x00001a1b, 0x00001a56, 0x00001a56, - 0x00001a58, 0x00001a5e, 0x00001a60, 0x00001a60, - 0x00001a62, 0x00001a62, 0x00001a65, 0x00001a6c, - 0x00001a73, 0x00001a7c, 0x00001a7f, 0x00001a7f, - 0x00001ab0, 0x00001ace, 0x00001b00, 0x00001b03, + 0x0002a700, 0x0002b81d, 0x0002b820, 0x0002cead, + 0x0002ceb0, 0x0002ebe0, 0x0002ebf0, 0x0002ee5d, + 0x0002f800, 0x0002fa1d, 0x00030000, 0x0003134a, + 0x00031350, 0x00033479, 0x000f0000, 0x000ffffd, + 0x00100000, 0x0010fffd, 0x000005be, 0x000005be, + 0x000005c0, 0x000005c0, 0x000005c3, 0x000005c3, + 0x000005c6, 0x000005c6, 0x000005d0, 0x000005ea, + 0x000005ef, 0x000005f4, 0x000007c0, 0x000007ea, + 0x000007f4, 0x000007f5, 0x000007fa, 0x000007fa, + 0x000007fe, 0x00000815, 0x0000081a, 0x0000081a, + 0x00000824, 0x00000824, 0x00000828, 0x00000828, + 0x00000830, 0x0000083e, 0x00000840, 0x00000858, + 0x0000085e, 0x0000085e, 0x0000200f, 0x0000200f, + 0x0000fb1d, 0x0000fb1d, 0x0000fb1f, 0x0000fb28, + 0x0000fb2a, 0x0000fb36, 0x0000fb38, 0x0000fb3c, + 0x0000fb3e, 0x0000fb3e, 0x0000fb40, 0x0000fb41, + 0x0000fb43, 0x0000fb44, 0x0000fb46, 0x0000fb4f, + 0x00010800, 0x00010805, 0x00010808, 0x00010808, + 0x0001080a, 0x00010835, 0x00010837, 0x00010838, + 0x0001083c, 0x0001083c, 0x0001083f, 0x00010855, + 0x00010857, 0x0001089e, 0x000108a7, 0x000108af, + 0x000108e0, 0x000108f2, 0x000108f4, 0x000108f5, + 0x000108fb, 0x0001091b, 0x00010920, 0x00010939, + 0x0001093f, 0x00010959, 0x00010980, 0x000109b7, + 0x000109bc, 0x000109cf, 0x000109d2, 0x00010a00, + 0x00010a10, 0x00010a13, 0x00010a15, 0x00010a17, + 0x00010a19, 0x00010a35, 0x00010a40, 0x00010a48, + 0x00010a50, 0x00010a58, 0x00010a60, 0x00010a9f, + 0x00010ac0, 0x00010ae4, 0x00010aeb, 0x00010af6, + 0x00010b00, 0x00010b35, 0x00010b40, 0x00010b55, + 0x00010b58, 0x00010b72, 0x00010b78, 0x00010b91, + 0x00010b99, 0x00010b9c, 0x00010ba9, 0x00010baf, + 0x00010c00, 0x00010c48, 0x00010c80, 0x00010cb2, + 0x00010cc0, 0x00010cf2, 0x00010cfa, 0x00010cff, + 0x00010d4a, 0x00010d65, 0x00010d6f, 0x00010d85, + 0x00010d8e, 0x00010d8f, 0x00010e80, 0x00010ea9, + 0x00010ead, 0x00010ead, 0x00010eb0, 0x00010eb1, + 0x00010f00, 0x00010f27, 0x00010f70, 0x00010f81, + 0x00010f86, 0x00010f89, 0x00010fb0, 0x00010fcb, + 0x00010fe0, 0x00010ff6, 0x0001e800, 0x0001e8c4, + 0x0001e8c7, 0x0001e8cf, 0x0001e900, 0x0001e943, + 0x0001e94b, 0x0001e94b, 0x0001e950, 0x0001e959, + 0x0001e95e, 0x0001e95f, 0x00000030, 0x00000039, + 0x000000b2, 0x000000b3, 0x000000b9, 0x000000b9, + 0x000006f0, 0x000006f9, 0x00002070, 0x00002070, + 0x00002074, 0x00002079, 0x00002080, 0x00002089, + 0x00002488, 0x0000249b, 0x0000ff10, 0x0000ff19, + 0x000102e1, 0x000102fb, 0x0001ccf0, 0x0001ccf9, + 0x0001d7ce, 0x0001d7ff, 0x0001f100, 0x0001f10a, + 0x0001fbf0, 0x0001fbf9, 0x0000002b, 0x0000002b, + 0x0000002d, 0x0000002d, 0x0000207a, 0x0000207b, + 0x0000208a, 0x0000208b, 0x00002212, 0x00002212, + 0x0000fb29, 0x0000fb29, 0x0000fe62, 0x0000fe63, + 0x0000ff0b, 0x0000ff0b, 0x0000ff0d, 0x0000ff0d, + 0x00000023, 0x00000025, 0x000000a2, 0x000000a5, + 0x000000b0, 0x000000b1, 0x0000058f, 0x0000058f, + 0x00000609, 0x0000060a, 0x0000066a, 0x0000066a, + 0x000009f2, 0x000009f3, 0x000009fb, 0x000009fb, + 0x00000af1, 0x00000af1, 0x00000bf9, 0x00000bf9, + 0x00000e3f, 0x00000e3f, 0x000017db, 0x000017db, + 0x00002030, 0x00002034, 0x000020a0, 0x000020c1, + 0x0000212e, 0x0000212e, 0x00002213, 0x00002213, + 0x0000a838, 0x0000a839, 0x0000fe5f, 0x0000fe5f, + 0x0000fe69, 0x0000fe6a, 0x0000ff03, 0x0000ff05, + 0x0000ffe0, 0x0000ffe1, 0x0000ffe5, 0x0000ffe6, + 0x00011fdd, 0x00011fe0, 0x0001e2ff, 0x0001e2ff, + 0x00000600, 0x00000605, 0x00000660, 0x00000669, + 0x0000066b, 0x0000066c, 0x000006dd, 0x000006dd, + 0x00000890, 0x00000891, 0x000008e2, 0x000008e2, + 0x00010d30, 0x00010d39, 0x00010d40, 0x00010d49, + 0x00010e60, 0x00010e7e, 0x0000002c, 0x0000002c, + 0x0000002e, 0x0000002f, 0x0000003a, 0x0000003a, + 0x000000a0, 0x000000a0, 0x0000060c, 0x0000060c, + 0x0000202f, 0x0000202f, 0x00002044, 0x00002044, + 0x0000fe50, 0x0000fe50, 0x0000fe52, 0x0000fe52, + 0x0000fe55, 0x0000fe55, 0x0000ff0c, 0x0000ff0c, + 0x0000ff0e, 0x0000ff0f, 0x0000ff1a, 0x0000ff1a, + 0x0000000a, 0x0000000a, 0x0000000d, 0x0000000d, + 0x0000001c, 0x0000001e, 0x00000085, 0x00000085, + 0x00002029, 0x00002029, 0x00000009, 0x00000009, + 0x0000000b, 0x0000000b, 0x0000001f, 0x0000001f, + 0x0000000c, 0x0000000c, 0x00000020, 0x00000020, + 0x00001680, 0x00001680, 0x00002000, 0x0000200a, + 0x00002028, 0x00002028, 0x0000205f, 0x0000205f, + 0x00003000, 0x00003000, 0x00000000, 0x00000008, + 0x0000000e, 0x0000001b, 0x00000021, 0x00000022, + 0x00000026, 0x0000002a, 0x0000003b, 0x00000040, + 0x0000005b, 0x00000060, 0x0000007b, 0x00000084, + 0x00000086, 0x0000009f, 0x000000a1, 0x000000a1, + 0x000000a6, 0x000000a9, 0x000000ab, 0x000000af, + 0x000000b4, 0x000000b4, 0x000000b6, 0x000000b8, + 0x000000bb, 0x000000bf, 0x000000d7, 0x000000d7, + 0x000000f7, 0x000000f7, 0x000002b9, 0x000002ba, + 0x000002c2, 0x000002cf, 0x000002d2, 0x000002df, + 0x000002e5, 0x000002ed, 0x000002ef, 0x0000036f, + 0x00000374, 0x00000375, 0x0000037e, 0x0000037e, + 0x00000384, 0x00000385, 0x00000387, 0x00000387, + 0x000003f6, 0x000003f6, 0x00000483, 0x00000489, + 0x0000058a, 0x0000058a, 0x0000058d, 0x0000058e, + 0x00000591, 0x000005bd, 0x000005bf, 0x000005bf, + 0x000005c1, 0x000005c2, 0x000005c4, 0x000005c5, + 0x000005c7, 0x000005c7, 0x00000606, 0x00000607, + 0x0000060e, 0x0000061a, 0x0000064b, 0x0000065f, + 0x00000670, 0x00000670, 0x000006d6, 0x000006dc, + 0x000006de, 0x000006e4, 0x000006e7, 0x000006ed, + 0x00000711, 0x00000711, 0x00000730, 0x0000074a, + 0x000007a6, 0x000007b0, 0x000007eb, 0x000007f3, + 0x000007f6, 0x000007f9, 0x000007fd, 0x000007fd, + 0x00000816, 0x00000819, 0x0000081b, 0x00000823, + 0x00000825, 0x00000827, 0x00000829, 0x0000082d, + 0x00000859, 0x0000085b, 0x00000897, 0x0000089f, + 0x000008ca, 0x000008e1, 0x000008e3, 0x00000902, + 0x0000093a, 0x0000093a, 0x0000093c, 0x0000093c, + 0x00000941, 0x00000948, 0x0000094d, 0x0000094d, + 0x00000951, 0x00000957, 0x00000962, 0x00000963, + 0x00000981, 0x00000981, 0x000009bc, 0x000009bc, + 0x000009c1, 0x000009c4, 0x000009cd, 0x000009cd, + 0x000009e2, 0x000009e3, 0x000009fe, 0x000009fe, + 0x00000a01, 0x00000a02, 0x00000a3c, 0x00000a3c, + 0x00000a41, 0x00000a42, 0x00000a47, 0x00000a48, + 0x00000a4b, 0x00000a4d, 0x00000a51, 0x00000a51, + 0x00000a70, 0x00000a71, 0x00000a75, 0x00000a75, + 0x00000a81, 0x00000a82, 0x00000abc, 0x00000abc, + 0x00000ac1, 0x00000ac5, 0x00000ac7, 0x00000ac8, + 0x00000acd, 0x00000acd, 0x00000ae2, 0x00000ae3, + 0x00000afa, 0x00000aff, 0x00000b01, 0x00000b01, + 0x00000b3c, 0x00000b3c, 0x00000b3f, 0x00000b3f, + 0x00000b41, 0x00000b44, 0x00000b4d, 0x00000b4d, + 0x00000b55, 0x00000b56, 0x00000b62, 0x00000b63, + 0x00000b82, 0x00000b82, 0x00000bc0, 0x00000bc0, + 0x00000bcd, 0x00000bcd, 0x00000bf3, 0x00000bf8, + 0x00000bfa, 0x00000bfa, 0x00000c00, 0x00000c00, + 0x00000c04, 0x00000c04, 0x00000c3c, 0x00000c3c, + 0x00000c3e, 0x00000c40, 0x00000c46, 0x00000c48, + 0x00000c4a, 0x00000c4d, 0x00000c55, 0x00000c56, + 0x00000c62, 0x00000c63, 0x00000c78, 0x00000c7e, + 0x00000c81, 0x00000c81, 0x00000cbc, 0x00000cbc, + 0x00000ccc, 0x00000ccd, 0x00000ce2, 0x00000ce3, + 0x00000d00, 0x00000d01, 0x00000d3b, 0x00000d3c, + 0x00000d41, 0x00000d44, 0x00000d4d, 0x00000d4d, + 0x00000d62, 0x00000d63, 0x00000d81, 0x00000d81, + 0x00000dca, 0x00000dca, 0x00000dd2, 0x00000dd4, + 0x00000dd6, 0x00000dd6, 0x00000e31, 0x00000e31, + 0x00000e34, 0x00000e3a, 0x00000e47, 0x00000e4e, + 0x00000eb1, 0x00000eb1, 0x00000eb4, 0x00000ebc, + 0x00000ec8, 0x00000ece, 0x00000f18, 0x00000f19, + 0x00000f35, 0x00000f35, 0x00000f37, 0x00000f37, + 0x00000f39, 0x00000f3d, 0x00000f71, 0x00000f7e, + 0x00000f80, 0x00000f84, 0x00000f86, 0x00000f87, + 0x00000f8d, 0x00000f97, 0x00000f99, 0x00000fbc, + 0x00000fc6, 0x00000fc6, 0x0000102d, 0x00001030, + 0x00001032, 0x00001037, 0x00001039, 0x0000103a, + 0x0000103d, 0x0000103e, 0x00001058, 0x00001059, + 0x0000105e, 0x00001060, 0x00001071, 0x00001074, + 0x00001082, 0x00001082, 0x00001085, 0x00001086, + 0x0000108d, 0x0000108d, 0x0000109d, 0x0000109d, + 0x0000135d, 0x0000135f, 0x00001390, 0x00001399, + 0x00001400, 0x00001400, 0x0000169b, 0x0000169c, + 0x00001712, 0x00001714, 0x00001732, 0x00001733, + 0x00001752, 0x00001753, 0x00001772, 0x00001773, + 0x000017b4, 0x000017b5, 0x000017b7, 0x000017bd, + 0x000017c6, 0x000017c6, 0x000017c9, 0x000017d3, + 0x000017dd, 0x000017dd, 0x000017f0, 0x000017f9, + 0x00001800, 0x0000180f, 0x00001885, 0x00001886, + 0x000018a9, 0x000018a9, 0x00001920, 0x00001922, + 0x00001927, 0x00001928, 0x00001932, 0x00001932, + 0x00001939, 0x0000193b, 0x00001940, 0x00001940, + 0x00001944, 0x00001945, 0x000019de, 0x000019ff, + 0x00001a17, 0x00001a18, 0x00001a1b, 0x00001a1b, + 0x00001a56, 0x00001a56, 0x00001a58, 0x00001a5e, + 0x00001a60, 0x00001a60, 0x00001a62, 0x00001a62, + 0x00001a65, 0x00001a6c, 0x00001a73, 0x00001a7c, + 0x00001a7f, 0x00001a7f, 0x00001ab0, 0x00001add, + 0x00001ae0, 0x00001aeb, 0x00001b00, 0x00001b03, 0x00001b34, 0x00001b34, 0x00001b36, 0x00001b3a, 0x00001b3c, 0x00001b3c, 0x00001b42, 0x00001b42, 0x00001b6b, 0x00001b73, 0x00001b80, 0x00001b81, @@ -2082,62 +2107,63 @@ static const unsigned int _ucprop_ranges[] = { 0x0000237b, 0x00002394, 0x00002396, 0x00002429, 0x00002440, 0x0000244a, 0x00002460, 0x00002487, 0x000024ea, 0x000026ab, 0x000026ad, 0x000027ff, - 0x00002900, 0x00002b73, 0x00002b76, 0x00002b95, - 0x00002b97, 0x00002bff, 0x00002ce5, 0x00002cea, - 0x00002cef, 0x00002cf1, 0x00002cf9, 0x00002cff, - 0x00002d7f, 0x00002d7f, 0x00002de0, 0x00002e5d, - 0x00002e80, 0x00002e99, 0x00002e9b, 0x00002ef3, - 0x00002f00, 0x00002fd5, 0x00002ff0, 0x00002fff, - 0x00003001, 0x00003004, 0x00003008, 0x00003020, - 0x0000302a, 0x0000302d, 0x00003030, 0x00003030, - 0x00003036, 0x00003037, 0x0000303d, 0x0000303f, - 0x00003099, 0x0000309c, 0x000030a0, 0x000030a0, - 0x000030fb, 0x000030fb, 0x000031c0, 0x000031e5, - 0x000031ef, 0x000031ef, 0x0000321d, 0x0000321e, - 0x00003250, 0x0000325f, 0x0000327c, 0x0000327e, - 0x000032b1, 0x000032bf, 0x000032cc, 0x000032cf, - 0x00003377, 0x0000337a, 0x000033de, 0x000033df, - 0x000033ff, 0x000033ff, 0x00004dc0, 0x00004dff, - 0x0000a490, 0x0000a4c6, 0x0000a60d, 0x0000a60f, - 0x0000a66f, 0x0000a67f, 0x0000a69e, 0x0000a69f, - 0x0000a6f0, 0x0000a6f1, 0x0000a700, 0x0000a721, - 0x0000a788, 0x0000a788, 0x0000a802, 0x0000a802, - 0x0000a806, 0x0000a806, 0x0000a80b, 0x0000a80b, - 0x0000a825, 0x0000a826, 0x0000a828, 0x0000a82c, - 0x0000a874, 0x0000a877, 0x0000a8c4, 0x0000a8c5, - 0x0000a8e0, 0x0000a8f1, 0x0000a8ff, 0x0000a8ff, - 0x0000a926, 0x0000a92d, 0x0000a947, 0x0000a951, - 0x0000a980, 0x0000a982, 0x0000a9b3, 0x0000a9b3, - 0x0000a9b6, 0x0000a9b9, 0x0000a9bc, 0x0000a9bd, - 0x0000a9e5, 0x0000a9e5, 0x0000aa29, 0x0000aa2e, - 0x0000aa31, 0x0000aa32, 0x0000aa35, 0x0000aa36, - 0x0000aa43, 0x0000aa43, 0x0000aa4c, 0x0000aa4c, - 0x0000aa7c, 0x0000aa7c, 0x0000aab0, 0x0000aab0, - 0x0000aab2, 0x0000aab4, 0x0000aab7, 0x0000aab8, - 0x0000aabe, 0x0000aabf, 0x0000aac1, 0x0000aac1, - 0x0000aaec, 0x0000aaed, 0x0000aaf6, 0x0000aaf6, - 0x0000ab6a, 0x0000ab6b, 0x0000abe5, 0x0000abe5, - 0x0000abe8, 0x0000abe8, 0x0000abed, 0x0000abed, - 0x0000fb1e, 0x0000fb1e, 0x0000fd3e, 0x0000fd4f, - 0x0000fdcf, 0x0000fdcf, 0x0000fdfd, 0x0000fe19, - 0x0000fe20, 0x0000fe4f, 0x0000fe51, 0x0000fe51, - 0x0000fe54, 0x0000fe54, 0x0000fe56, 0x0000fe5e, - 0x0000fe60, 0x0000fe61, 0x0000fe64, 0x0000fe66, - 0x0000fe68, 0x0000fe68, 0x0000fe6b, 0x0000fe6b, - 0x0000feff, 0x0000feff, 0x0000ff01, 0x0000ff02, - 0x0000ff06, 0x0000ff0a, 0x0000ff1b, 0x0000ff20, - 0x0000ff3b, 0x0000ff40, 0x0000ff5b, 0x0000ff65, - 0x0000ffe2, 0x0000ffe4, 0x0000ffe8, 0x0000ffee, - 0x0000fff9, 0x0000fffd, 0x00010101, 0x00010101, - 0x00010140, 0x0001018c, 0x00010190, 0x0001019c, - 0x000101a0, 0x000101a0, 0x000101fd, 0x000101fd, - 0x000102e0, 0x000102e0, 0x00010376, 0x0001037a, - 0x0001091f, 0x0001091f, 0x00010a01, 0x00010a03, - 0x00010a05, 0x00010a06, 0x00010a0c, 0x00010a0f, - 0x00010a38, 0x00010a3a, 0x00010a3f, 0x00010a3f, - 0x00010ae5, 0x00010ae6, 0x00010b39, 0x00010b3f, - 0x00010d24, 0x00010d27, 0x00010d69, 0x00010d6e, - 0x00010eab, 0x00010eac, 0x00010efc, 0x00010eff, + 0x00002900, 0x00002b73, 0x00002b76, 0x00002bff, + 0x00002ce5, 0x00002cea, 0x00002cef, 0x00002cf1, + 0x00002cf9, 0x00002cff, 0x00002d7f, 0x00002d7f, + 0x00002de0, 0x00002e5d, 0x00002e80, 0x00002e99, + 0x00002e9b, 0x00002ef3, 0x00002f00, 0x00002fd5, + 0x00002ff0, 0x00002fff, 0x00003001, 0x00003004, + 0x00003008, 0x00003020, 0x0000302a, 0x0000302d, + 0x00003030, 0x00003030, 0x00003036, 0x00003037, + 0x0000303d, 0x0000303f, 0x00003099, 0x0000309c, + 0x000030a0, 0x000030a0, 0x000030fb, 0x000030fb, + 0x000031c0, 0x000031e5, 0x000031ef, 0x000031ef, + 0x0000321d, 0x0000321e, 0x00003250, 0x0000325f, + 0x0000327c, 0x0000327e, 0x000032b1, 0x000032bf, + 0x000032cc, 0x000032cf, 0x00003377, 0x0000337a, + 0x000033de, 0x000033df, 0x000033ff, 0x000033ff, + 0x00004dc0, 0x00004dff, 0x0000a490, 0x0000a4c6, + 0x0000a60d, 0x0000a60f, 0x0000a66f, 0x0000a67f, + 0x0000a69e, 0x0000a69f, 0x0000a6f0, 0x0000a6f1, + 0x0000a700, 0x0000a721, 0x0000a788, 0x0000a788, + 0x0000a802, 0x0000a802, 0x0000a806, 0x0000a806, + 0x0000a80b, 0x0000a80b, 0x0000a825, 0x0000a826, + 0x0000a828, 0x0000a82c, 0x0000a874, 0x0000a877, + 0x0000a8c4, 0x0000a8c5, 0x0000a8e0, 0x0000a8f1, + 0x0000a8ff, 0x0000a8ff, 0x0000a926, 0x0000a92d, + 0x0000a947, 0x0000a951, 0x0000a980, 0x0000a982, + 0x0000a9b3, 0x0000a9b3, 0x0000a9b6, 0x0000a9b9, + 0x0000a9bc, 0x0000a9bd, 0x0000a9e5, 0x0000a9e5, + 0x0000aa29, 0x0000aa2e, 0x0000aa31, 0x0000aa32, + 0x0000aa35, 0x0000aa36, 0x0000aa43, 0x0000aa43, + 0x0000aa4c, 0x0000aa4c, 0x0000aa7c, 0x0000aa7c, + 0x0000aab0, 0x0000aab0, 0x0000aab2, 0x0000aab4, + 0x0000aab7, 0x0000aab8, 0x0000aabe, 0x0000aabf, + 0x0000aac1, 0x0000aac1, 0x0000aaec, 0x0000aaed, + 0x0000aaf6, 0x0000aaf6, 0x0000ab6a, 0x0000ab6b, + 0x0000abe5, 0x0000abe5, 0x0000abe8, 0x0000abe8, + 0x0000abed, 0x0000abed, 0x0000fb1e, 0x0000fb1e, + 0x0000fbc3, 0x0000fbd2, 0x0000fd3e, 0x0000fd4f, + 0x0000fd90, 0x0000fd91, 0x0000fdc8, 0x0000fdcf, + 0x0000fdfd, 0x0000fe19, 0x0000fe20, 0x0000fe4f, + 0x0000fe51, 0x0000fe51, 0x0000fe54, 0x0000fe54, + 0x0000fe56, 0x0000fe5e, 0x0000fe60, 0x0000fe61, + 0x0000fe64, 0x0000fe66, 0x0000fe68, 0x0000fe68, + 0x0000fe6b, 0x0000fe6b, 0x0000feff, 0x0000feff, + 0x0000ff01, 0x0000ff02, 0x0000ff06, 0x0000ff0a, + 0x0000ff1b, 0x0000ff20, 0x0000ff3b, 0x0000ff40, + 0x0000ff5b, 0x0000ff65, 0x0000ffe2, 0x0000ffe4, + 0x0000ffe8, 0x0000ffee, 0x0000fff9, 0x0000fffd, + 0x00010101, 0x00010101, 0x00010140, 0x0001018c, + 0x00010190, 0x0001019c, 0x000101a0, 0x000101a0, + 0x000101fd, 0x000101fd, 0x000102e0, 0x000102e0, + 0x00010376, 0x0001037a, 0x0001091f, 0x0001091f, + 0x00010a01, 0x00010a03, 0x00010a05, 0x00010a06, + 0x00010a0c, 0x00010a0f, 0x00010a38, 0x00010a3a, + 0x00010a3f, 0x00010a3f, 0x00010ae5, 0x00010ae6, + 0x00010b39, 0x00010b3f, 0x00010d24, 0x00010d27, + 0x00010d69, 0x00010d6e, 0x00010eab, 0x00010eac, + 0x00010ed0, 0x00010ed8, 0x00010efa, 0x00010eff, 0x00010f46, 0x00010f50, 0x00010f82, 0x00010f85, 0x00011001, 0x00011001, 0x00011038, 0x00011046, 0x00011052, 0x00011065, 0x00011070, 0x00011070, @@ -2176,25 +2202,28 @@ static const unsigned int _ucprop_ranges[] = { 0x00011a33, 0x00011a38, 0x00011a3b, 0x00011a3e, 0x00011a47, 0x00011a47, 0x00011a51, 0x00011a56, 0x00011a59, 0x00011a5b, 0x00011a8a, 0x00011a96, - 0x00011a98, 0x00011a99, 0x00011c30, 0x00011c36, - 0x00011c38, 0x00011c3d, 0x00011c92, 0x00011ca7, - 0x00011caa, 0x00011cb0, 0x00011cb2, 0x00011cb3, - 0x00011cb5, 0x00011cb6, 0x00011d31, 0x00011d36, - 0x00011d3a, 0x00011d3a, 0x00011d3c, 0x00011d3d, - 0x00011d3f, 0x00011d45, 0x00011d47, 0x00011d47, - 0x00011d90, 0x00011d91, 0x00011d95, 0x00011d95, - 0x00011d97, 0x00011d97, 0x00011ef3, 0x00011ef4, - 0x00011f00, 0x00011f01, 0x00011f36, 0x00011f3a, - 0x00011f40, 0x00011f40, 0x00011f42, 0x00011f42, - 0x00011f5a, 0x00011f5a, 0x00011fd5, 0x00011fdc, - 0x00011fe1, 0x00011ff1, 0x00013440, 0x00013440, - 0x00013447, 0x00013455, 0x0001611e, 0x00016129, - 0x0001612d, 0x0001612f, 0x00016af0, 0x00016af4, - 0x00016b30, 0x00016b36, 0x00016f4f, 0x00016f4f, - 0x00016f8f, 0x00016f92, 0x00016fe2, 0x00016fe2, - 0x00016fe4, 0x00016fe4, 0x0001bc9d, 0x0001bc9e, - 0x0001bca0, 0x0001bca3, 0x0001cc00, 0x0001ccd5, - 0x0001cd00, 0x0001ceb3, 0x0001cf00, 0x0001cf2d, + 0x00011a98, 0x00011a99, 0x00011b60, 0x00011b60, + 0x00011b62, 0x00011b64, 0x00011b66, 0x00011b66, + 0x00011c30, 0x00011c36, 0x00011c38, 0x00011c3d, + 0x00011c92, 0x00011ca7, 0x00011caa, 0x00011cb0, + 0x00011cb2, 0x00011cb3, 0x00011cb5, 0x00011cb6, + 0x00011d31, 0x00011d36, 0x00011d3a, 0x00011d3a, + 0x00011d3c, 0x00011d3d, 0x00011d3f, 0x00011d45, + 0x00011d47, 0x00011d47, 0x00011d90, 0x00011d91, + 0x00011d95, 0x00011d95, 0x00011d97, 0x00011d97, + 0x00011ef3, 0x00011ef4, 0x00011f00, 0x00011f01, + 0x00011f36, 0x00011f3a, 0x00011f40, 0x00011f40, + 0x00011f42, 0x00011f42, 0x00011f5a, 0x00011f5a, + 0x00011fd5, 0x00011fdc, 0x00011fe1, 0x00011ff1, + 0x00013440, 0x00013440, 0x00013447, 0x00013455, + 0x0001611e, 0x00016129, 0x0001612d, 0x0001612f, + 0x00016af0, 0x00016af4, 0x00016b30, 0x00016b36, + 0x00016f4f, 0x00016f4f, 0x00016f8f, 0x00016f92, + 0x00016fe2, 0x00016fe2, 0x00016fe4, 0x00016fe4, + 0x0001bc9d, 0x0001bc9e, 0x0001bca0, 0x0001bca3, + 0x0001cc00, 0x0001ccd5, 0x0001ccfa, 0x0001ccfc, + 0x0001cd00, 0x0001ceb3, 0x0001ceba, 0x0001ced0, + 0x0001cee0, 0x0001cef0, 0x0001cf00, 0x0001cf2d, 0x0001cf30, 0x0001cf46, 0x0001d167, 0x0001d169, 0x0001d173, 0x0001d182, 0x0001d185, 0x0001d18b, 0x0001d1aa, 0x0001d1ad, 0x0001d1e9, 0x0001d1ea, @@ -2212,26 +2241,29 @@ static const unsigned int _ucprop_ranges[] = { 0x0001e026, 0x0001e02a, 0x0001e08f, 0x0001e08f, 0x0001e130, 0x0001e136, 0x0001e2ae, 0x0001e2ae, 0x0001e2ec, 0x0001e2ef, 0x0001e4ec, 0x0001e4ef, - 0x0001e5ee, 0x0001e5ef, 0x0001e8d0, 0x0001e8d6, + 0x0001e5ee, 0x0001e5ef, 0x0001e6e3, 0x0001e6e3, + 0x0001e6e6, 0x0001e6e6, 0x0001e6ee, 0x0001e6ef, + 0x0001e6f5, 0x0001e6f5, 0x0001e8d0, 0x0001e8d6, 0x0001e944, 0x0001e94a, 0x0001eef0, 0x0001eef1, 0x0001f000, 0x0001f02b, 0x0001f030, 0x0001f093, 0x0001f0a0, 0x0001f0ae, 0x0001f0b1, 0x0001f0bf, 0x0001f0c1, 0x0001f0cf, 0x0001f0d1, 0x0001f0f5, 0x0001f10b, 0x0001f10f, 0x0001f12f, 0x0001f12f, 0x0001f16a, 0x0001f16f, 0x0001f1ad, 0x0001f1ad, - 0x0001f260, 0x0001f265, 0x0001f300, 0x0001f6d7, + 0x0001f260, 0x0001f265, 0x0001f300, 0x0001f6d8, 0x0001f6dc, 0x0001f6ec, 0x0001f6f0, 0x0001f6fc, - 0x0001f700, 0x0001f776, 0x0001f77b, 0x0001f7d9, - 0x0001f7e0, 0x0001f7eb, 0x0001f7f0, 0x0001f7f0, - 0x0001f800, 0x0001f80b, 0x0001f810, 0x0001f847, - 0x0001f850, 0x0001f859, 0x0001f860, 0x0001f887, - 0x0001f890, 0x0001f8ad, 0x0001f8b0, 0x0001f8bb, - 0x0001f8c0, 0x0001f8c1, 0x0001f900, 0x0001fa53, + 0x0001f700, 0x0001f7d9, 0x0001f7e0, 0x0001f7eb, + 0x0001f7f0, 0x0001f7f0, 0x0001f800, 0x0001f80b, + 0x0001f810, 0x0001f847, 0x0001f850, 0x0001f859, + 0x0001f860, 0x0001f887, 0x0001f890, 0x0001f8ad, + 0x0001f8b0, 0x0001f8bb, 0x0001f8c0, 0x0001f8c1, + 0x0001f8d0, 0x0001f8d8, 0x0001f900, 0x0001fa57, 0x0001fa60, 0x0001fa6d, 0x0001fa70, 0x0001fa7c, - 0x0001fa80, 0x0001fa89, 0x0001fa8f, 0x0001fac6, - 0x0001face, 0x0001fadc, 0x0001fadf, 0x0001fae9, - 0x0001faf0, 0x0001faf8, 0x0001fb00, 0x0001fb92, - 0x0001fb94, 0x0001fbef, 0x000e0001, 0x000e0001, + 0x0001fa80, 0x0001fa8a, 0x0001fa8e, 0x0001fac6, + 0x0001fac8, 0x0001fac8, 0x0001facd, 0x0001fadc, + 0x0001fadf, 0x0001faea, 0x0001faef, 0x0001faf8, + 0x0001fb00, 0x0001fb92, 0x0001fb94, 0x0001fbef, + 0x0001fbfa, 0x0001fbfa, 0x000e0001, 0x000e0001, 0x000e0020, 0x000e007f, 0x000e0100, 0x000e01ef, 0x00000608, 0x00000608, 0x0000060b, 0x0000060b, 0x0000060d, 0x0000060d, 0x0000061b, 0x0000064a, @@ -2240,12 +2272,12 @@ static const unsigned int _ucprop_ranges[] = { 0x000006fa, 0x0000070d, 0x0000070f, 0x00000710, 0x00000712, 0x0000072f, 0x0000074d, 0x000007a5, 0x000007b1, 0x000007b1, 0x00000860, 0x0000086a, - 0x00000870, 0x0000088e, 0x000008a0, 0x000008c9, + 0x00000870, 0x0000088f, 0x000008a0, 0x000008c9, 0x0000fb50, 0x0000fbc2, 0x0000fbd3, 0x0000fd3d, 0x0000fd50, 0x0000fd8f, 0x0000fd92, 0x0000fdc7, 0x0000fdf0, 0x0000fdfc, 0x0000fe70, 0x0000fe74, 0x0000fe76, 0x0000fefc, 0x00010d00, 0x00010d23, - 0x00010ec2, 0x00010ec4, 0x00010f30, 0x00010f45, + 0x00010ec2, 0x00010ec7, 0x00010f30, 0x00010f45, 0x00010f51, 0x00010f59, 0x0001ec71, 0x0001ecb4, 0x0001ed01, 0x0001ed3d, 0x0001ee00, 0x0001ee03, 0x0001ee05, 0x0001ee1f, 0x0001ee21, 0x0001ee22, @@ -2349,78 +2381,77 @@ static const unsigned int _ucprop_ranges[] = { 0x00010a50, 0x00010a58, 0x00010a7f, 0x00010a7f, 0x00010af0, 0x00010af6, 0x00010b39, 0x00010b3f, 0x00010b99, 0x00010b9c, 0x00010d6e, 0x00010d6e, - 0x00010ead, 0x00010ead, 0x00010f55, 0x00010f59, - 0x00010f86, 0x00010f89, 0x00011047, 0x0001104d, - 0x000110bb, 0x000110bc, 0x000110be, 0x000110c1, - 0x00011140, 0x00011143, 0x00011174, 0x00011175, - 0x000111c5, 0x000111c8, 0x000111cd, 0x000111cd, - 0x000111db, 0x000111db, 0x000111dd, 0x000111df, - 0x00011238, 0x0001123d, 0x000112a9, 0x000112a9, - 0x000113d4, 0x000113d5, 0x000113d7, 0x000113d8, - 0x0001144b, 0x0001144f, 0x0001145a, 0x0001145b, - 0x0001145d, 0x0001145d, 0x000114c6, 0x000114c6, - 0x000115c1, 0x000115d7, 0x00011641, 0x00011643, - 0x00011660, 0x0001166c, 0x000116b9, 0x000116b9, - 0x0001173c, 0x0001173e, 0x0001183b, 0x0001183b, - 0x00011944, 0x00011946, 0x000119e2, 0x000119e2, - 0x00011a3f, 0x00011a46, 0x00011a9a, 0x00011a9c, - 0x00011a9e, 0x00011aa2, 0x00011b00, 0x00011b09, - 0x00011be1, 0x00011be1, 0x00011c41, 0x00011c45, - 0x00011c70, 0x00011c71, 0x00011ef7, 0x00011ef8, - 0x00011f43, 0x00011f4f, 0x00011fff, 0x00011fff, - 0x00012470, 0x00012474, 0x00012ff1, 0x00012ff2, - 0x00016a6e, 0x00016a6f, 0x00016af5, 0x00016af5, - 0x00016b37, 0x00016b3b, 0x00016b44, 0x00016b44, - 0x00016d6d, 0x00016d6f, 0x00016e97, 0x00016e9a, - 0x00016fe2, 0x00016fe2, 0x0001bc9f, 0x0001bc9f, - 0x0001da87, 0x0001da8b, 0x0001e5ff, 0x0001e5ff, - 0x0001e95e, 0x0001e95f, 0x00000041, 0x0000005a, - 0x00000061, 0x0000007a, 0x000000aa, 0x000000aa, - 0x000000b5, 0x000000b5, 0x000000ba, 0x000000ba, - 0x000000c0, 0x000000d6, 0x000000d8, 0x000000f6, - 0x000000f8, 0x000001ba, 0x000001bc, 0x000001bf, - 0x000001c4, 0x00000293, 0x00000295, 0x000002b8, - 0x000002c0, 0x000002c1, 0x000002e0, 0x000002e4, - 0x00000345, 0x00000345, 0x00000370, 0x00000373, - 0x00000376, 0x00000377, 0x0000037a, 0x0000037d, - 0x0000037f, 0x0000037f, 0x00000386, 0x00000386, - 0x00000388, 0x0000038a, 0x0000038c, 0x0000038c, - 0x0000038e, 0x000003a1, 0x000003a3, 0x000003f5, - 0x000003f7, 0x00000481, 0x0000048a, 0x0000052f, - 0x00000531, 0x00000556, 0x00000560, 0x00000588, - 0x000010a0, 0x000010c5, 0x000010c7, 0x000010c7, - 0x000010cd, 0x000010cd, 0x000010d0, 0x000010fa, - 0x000010fc, 0x000010ff, 0x000013a0, 0x000013f5, - 0x000013f8, 0x000013fd, 0x00001c80, 0x00001c8a, - 0x00001c90, 0x00001cba, 0x00001cbd, 0x00001cbf, - 0x00001d00, 0x00001dbf, 0x00001e00, 0x00001f15, - 0x00001f18, 0x00001f1d, 0x00001f20, 0x00001f45, - 0x00001f48, 0x00001f4d, 0x00001f50, 0x00001f57, - 0x00001f59, 0x00001f59, 0x00001f5b, 0x00001f5b, - 0x00001f5d, 0x00001f5d, 0x00001f5f, 0x00001f7d, - 0x00001f80, 0x00001fb4, 0x00001fb6, 0x00001fbc, - 0x00001fbe, 0x00001fbe, 0x00001fc2, 0x00001fc4, - 0x00001fc6, 0x00001fcc, 0x00001fd0, 0x00001fd3, - 0x00001fd6, 0x00001fdb, 0x00001fe0, 0x00001fec, - 0x00001ff2, 0x00001ff4, 0x00001ff6, 0x00001ffc, - 0x00002071, 0x00002071, 0x0000207f, 0x0000207f, - 0x00002090, 0x0000209c, 0x00002102, 0x00002102, - 0x00002107, 0x00002107, 0x0000210a, 0x00002113, - 0x00002115, 0x00002115, 0x00002119, 0x0000211d, - 0x00002124, 0x00002124, 0x00002126, 0x00002126, - 0x00002128, 0x00002128, 0x0000212a, 0x0000212d, - 0x0000212f, 0x00002134, 0x00002139, 0x00002139, - 0x0000213c, 0x0000213f, 0x00002145, 0x00002149, - 0x0000214e, 0x0000214e, 0x00002160, 0x0000217f, - 0x00002183, 0x00002184, 0x000024b6, 0x000024e9, - 0x00002c00, 0x00002ce4, 0x00002ceb, 0x00002cee, - 0x00002cf2, 0x00002cf3, 0x00002d00, 0x00002d25, - 0x00002d27, 0x00002d27, 0x00002d2d, 0x00002d2d, - 0x0000a640, 0x0000a66d, 0x0000a680, 0x0000a69d, - 0x0000a722, 0x0000a787, 0x0000a78b, 0x0000a78e, - 0x0000a790, 0x0000a7cd, 0x0000a7d0, 0x0000a7d1, - 0x0000a7d3, 0x0000a7d3, 0x0000a7d5, 0x0000a7dc, - 0x0000a7f2, 0x0000a7f6, 0x0000a7f8, 0x0000a7fa, + 0x00010ead, 0x00010ead, 0x00010ed0, 0x00010ed0, + 0x00010f55, 0x00010f59, 0x00010f86, 0x00010f89, + 0x00011047, 0x0001104d, 0x000110bb, 0x000110bc, + 0x000110be, 0x000110c1, 0x00011140, 0x00011143, + 0x00011174, 0x00011175, 0x000111c5, 0x000111c8, + 0x000111cd, 0x000111cd, 0x000111db, 0x000111db, + 0x000111dd, 0x000111df, 0x00011238, 0x0001123d, + 0x000112a9, 0x000112a9, 0x000113d4, 0x000113d5, + 0x000113d7, 0x000113d8, 0x0001144b, 0x0001144f, + 0x0001145a, 0x0001145b, 0x0001145d, 0x0001145d, + 0x000114c6, 0x000114c6, 0x000115c1, 0x000115d7, + 0x00011641, 0x00011643, 0x00011660, 0x0001166c, + 0x000116b9, 0x000116b9, 0x0001173c, 0x0001173e, + 0x0001183b, 0x0001183b, 0x00011944, 0x00011946, + 0x000119e2, 0x000119e2, 0x00011a3f, 0x00011a46, + 0x00011a9a, 0x00011a9c, 0x00011a9e, 0x00011aa2, + 0x00011b00, 0x00011b09, 0x00011be1, 0x00011be1, + 0x00011c41, 0x00011c45, 0x00011c70, 0x00011c71, + 0x00011ef7, 0x00011ef8, 0x00011f43, 0x00011f4f, + 0x00011fff, 0x00011fff, 0x00012470, 0x00012474, + 0x00012ff1, 0x00012ff2, 0x00016a6e, 0x00016a6f, + 0x00016af5, 0x00016af5, 0x00016b37, 0x00016b3b, + 0x00016b44, 0x00016b44, 0x00016d6d, 0x00016d6f, + 0x00016e97, 0x00016e9a, 0x00016fe2, 0x00016fe2, + 0x0001bc9f, 0x0001bc9f, 0x0001da87, 0x0001da8b, + 0x0001e5ff, 0x0001e5ff, 0x0001e95e, 0x0001e95f, + 0x00000041, 0x0000005a, 0x00000061, 0x0000007a, + 0x000000aa, 0x000000aa, 0x000000b5, 0x000000b5, + 0x000000ba, 0x000000ba, 0x000000c0, 0x000000d6, + 0x000000d8, 0x000000f6, 0x000000f8, 0x000001ba, + 0x000001bc, 0x000001bf, 0x000001c4, 0x00000293, + 0x00000296, 0x000002b8, 0x000002c0, 0x000002c1, + 0x000002e0, 0x000002e4, 0x00000345, 0x00000345, + 0x00000370, 0x00000373, 0x00000376, 0x00000377, + 0x0000037a, 0x0000037d, 0x0000037f, 0x0000037f, + 0x00000386, 0x00000386, 0x00000388, 0x0000038a, + 0x0000038c, 0x0000038c, 0x0000038e, 0x000003a1, + 0x000003a3, 0x000003f5, 0x000003f7, 0x00000481, + 0x0000048a, 0x0000052f, 0x00000531, 0x00000556, + 0x00000560, 0x00000588, 0x000010a0, 0x000010c5, + 0x000010c7, 0x000010c7, 0x000010cd, 0x000010cd, + 0x000010d0, 0x000010fa, 0x000010fc, 0x000010ff, + 0x000013a0, 0x000013f5, 0x000013f8, 0x000013fd, + 0x00001c80, 0x00001c8a, 0x00001c90, 0x00001cba, + 0x00001cbd, 0x00001cbf, 0x00001d00, 0x00001dbf, + 0x00001e00, 0x00001f15, 0x00001f18, 0x00001f1d, + 0x00001f20, 0x00001f45, 0x00001f48, 0x00001f4d, + 0x00001f50, 0x00001f57, 0x00001f59, 0x00001f59, + 0x00001f5b, 0x00001f5b, 0x00001f5d, 0x00001f5d, + 0x00001f5f, 0x00001f7d, 0x00001f80, 0x00001fb4, + 0x00001fb6, 0x00001fbc, 0x00001fbe, 0x00001fbe, + 0x00001fc2, 0x00001fc4, 0x00001fc6, 0x00001fcc, + 0x00001fd0, 0x00001fd3, 0x00001fd6, 0x00001fdb, + 0x00001fe0, 0x00001fec, 0x00001ff2, 0x00001ff4, + 0x00001ff6, 0x00001ffc, 0x00002071, 0x00002071, + 0x0000207f, 0x0000207f, 0x00002090, 0x0000209c, + 0x00002102, 0x00002102, 0x00002107, 0x00002107, + 0x0000210a, 0x00002113, 0x00002115, 0x00002115, + 0x00002119, 0x0000211d, 0x00002124, 0x00002124, + 0x00002126, 0x00002126, 0x00002128, 0x00002128, + 0x0000212a, 0x0000212d, 0x0000212f, 0x00002134, + 0x00002139, 0x00002139, 0x0000213c, 0x0000213f, + 0x00002145, 0x00002149, 0x0000214e, 0x0000214e, + 0x00002160, 0x0000217f, 0x00002183, 0x00002184, + 0x000024b6, 0x000024e9, 0x00002c00, 0x00002ce4, + 0x00002ceb, 0x00002cee, 0x00002cf2, 0x00002cf3, + 0x00002d00, 0x00002d25, 0x00002d27, 0x00002d27, + 0x00002d2d, 0x00002d2d, 0x0000a640, 0x0000a66d, + 0x0000a680, 0x0000a69d, 0x0000a722, 0x0000a787, + 0x0000a78b, 0x0000a78e, 0x0000a790, 0x0000a7dc, + 0x0000a7f1, 0x0000a7f6, 0x0000a7f8, 0x0000a7fa, 0x0000ab30, 0x0000ab5a, 0x0000ab5c, 0x0000ab69, 0x0000ab70, 0x0000abbf, 0x0000fb00, 0x0000fb06, 0x0000fb13, 0x0000fb17, 0x0000ff21, 0x0000ff3a, @@ -2435,6 +2466,7 @@ static const unsigned int _ucprop_ranges[] = { 0x00010c80, 0x00010cb2, 0x00010cc0, 0x00010cf2, 0x00010d50, 0x00010d65, 0x00010d70, 0x00010d85, 0x000118a0, 0x000118df, 0x00016e40, 0x00016e7f, + 0x00016ea0, 0x00016eb8, 0x00016ebb, 0x00016ed3, 0x0001d400, 0x0001d454, 0x0001d456, 0x0001d49c, 0x0001d49e, 0x0001d49f, 0x0001d4a2, 0x0001d4a2, 0x0001d4a5, 0x0001d4a6, 0x0001d4a9, 0x0001d4ac, @@ -2536,77 +2568,78 @@ static const unsigned int _ucprop_ranges[] = { 0x00001a58, 0x00001a5e, 0x00001a60, 0x00001a60, 0x00001a62, 0x00001a62, 0x00001a65, 0x00001a6c, 0x00001a73, 0x00001a7c, 0x00001a7f, 0x00001a7f, - 0x00001aa7, 0x00001aa7, 0x00001ab0, 0x00001ace, - 0x00001b00, 0x00001b03, 0x00001b34, 0x00001b34, - 0x00001b36, 0x00001b3a, 0x00001b3c, 0x00001b3c, - 0x00001b42, 0x00001b42, 0x00001b6b, 0x00001b73, - 0x00001b80, 0x00001b81, 0x00001ba2, 0x00001ba5, - 0x00001ba8, 0x00001ba9, 0x00001bab, 0x00001bad, - 0x00001be6, 0x00001be6, 0x00001be8, 0x00001be9, - 0x00001bed, 0x00001bed, 0x00001bef, 0x00001bf1, - 0x00001c2c, 0x00001c33, 0x00001c36, 0x00001c37, - 0x00001c78, 0x00001c7d, 0x00001cd0, 0x00001cd2, - 0x00001cd4, 0x00001ce0, 0x00001ce2, 0x00001ce8, - 0x00001ced, 0x00001ced, 0x00001cf4, 0x00001cf4, - 0x00001cf8, 0x00001cf9, 0x00001d2c, 0x00001d6a, - 0x00001d78, 0x00001d78, 0x00001d9b, 0x00001dff, - 0x00001fbd, 0x00001fbd, 0x00001fbf, 0x00001fc1, - 0x00001fcd, 0x00001fcf, 0x00001fdd, 0x00001fdf, - 0x00001fed, 0x00001fef, 0x00001ffd, 0x00001ffe, - 0x0000200b, 0x0000200f, 0x00002018, 0x00002019, - 0x00002024, 0x00002024, 0x00002027, 0x00002027, - 0x0000202a, 0x0000202e, 0x00002060, 0x00002064, - 0x00002066, 0x0000206f, 0x00002071, 0x00002071, - 0x0000207f, 0x0000207f, 0x00002090, 0x0000209c, - 0x000020d0, 0x000020f0, 0x00002c7c, 0x00002c7d, - 0x00002cef, 0x00002cf1, 0x00002d6f, 0x00002d6f, - 0x00002d7f, 0x00002d7f, 0x00002de0, 0x00002dff, - 0x00002e2f, 0x00002e2f, 0x00003005, 0x00003005, - 0x0000302a, 0x0000302d, 0x00003031, 0x00003035, - 0x0000303b, 0x0000303b, 0x00003099, 0x0000309e, - 0x000030fc, 0x000030fe, 0x0000a015, 0x0000a015, - 0x0000a4f8, 0x0000a4fd, 0x0000a60c, 0x0000a60c, - 0x0000a66f, 0x0000a672, 0x0000a674, 0x0000a67d, - 0x0000a67f, 0x0000a67f, 0x0000a69c, 0x0000a69f, - 0x0000a6f0, 0x0000a6f1, 0x0000a700, 0x0000a721, - 0x0000a770, 0x0000a770, 0x0000a788, 0x0000a78a, - 0x0000a7f2, 0x0000a7f4, 0x0000a7f8, 0x0000a7f9, - 0x0000a802, 0x0000a802, 0x0000a806, 0x0000a806, - 0x0000a80b, 0x0000a80b, 0x0000a825, 0x0000a826, - 0x0000a82c, 0x0000a82c, 0x0000a8c4, 0x0000a8c5, - 0x0000a8e0, 0x0000a8f1, 0x0000a8ff, 0x0000a8ff, - 0x0000a926, 0x0000a92d, 0x0000a947, 0x0000a951, - 0x0000a980, 0x0000a982, 0x0000a9b3, 0x0000a9b3, - 0x0000a9b6, 0x0000a9b9, 0x0000a9bc, 0x0000a9bd, - 0x0000a9cf, 0x0000a9cf, 0x0000a9e5, 0x0000a9e6, - 0x0000aa29, 0x0000aa2e, 0x0000aa31, 0x0000aa32, - 0x0000aa35, 0x0000aa36, 0x0000aa43, 0x0000aa43, - 0x0000aa4c, 0x0000aa4c, 0x0000aa70, 0x0000aa70, - 0x0000aa7c, 0x0000aa7c, 0x0000aab0, 0x0000aab0, - 0x0000aab2, 0x0000aab4, 0x0000aab7, 0x0000aab8, - 0x0000aabe, 0x0000aabf, 0x0000aac1, 0x0000aac1, - 0x0000aadd, 0x0000aadd, 0x0000aaec, 0x0000aaed, - 0x0000aaf3, 0x0000aaf4, 0x0000aaf6, 0x0000aaf6, - 0x0000ab5b, 0x0000ab5f, 0x0000ab69, 0x0000ab6b, - 0x0000abe5, 0x0000abe5, 0x0000abe8, 0x0000abe8, - 0x0000abed, 0x0000abed, 0x0000fb1e, 0x0000fb1e, - 0x0000fbb2, 0x0000fbc2, 0x0000fe00, 0x0000fe0f, - 0x0000fe13, 0x0000fe13, 0x0000fe20, 0x0000fe2f, - 0x0000fe52, 0x0000fe52, 0x0000fe55, 0x0000fe55, - 0x0000feff, 0x0000feff, 0x0000ff07, 0x0000ff07, - 0x0000ff0e, 0x0000ff0e, 0x0000ff1a, 0x0000ff1a, - 0x0000ff3e, 0x0000ff3e, 0x0000ff40, 0x0000ff40, - 0x0000ff70, 0x0000ff70, 0x0000ff9e, 0x0000ff9f, - 0x0000ffe3, 0x0000ffe3, 0x0000fff9, 0x0000fffb, - 0x000101fd, 0x000101fd, 0x000102e0, 0x000102e0, - 0x00010376, 0x0001037a, 0x00010780, 0x00010785, - 0x00010787, 0x000107b0, 0x000107b2, 0x000107ba, - 0x00010a01, 0x00010a03, 0x00010a05, 0x00010a06, - 0x00010a0c, 0x00010a0f, 0x00010a38, 0x00010a3a, - 0x00010a3f, 0x00010a3f, 0x00010ae5, 0x00010ae6, - 0x00010d24, 0x00010d27, 0x00010d4e, 0x00010d4e, - 0x00010d69, 0x00010d6d, 0x00010d6f, 0x00010d6f, - 0x00010eab, 0x00010eac, 0x00010efc, 0x00010eff, + 0x00001aa7, 0x00001aa7, 0x00001ab0, 0x00001add, + 0x00001ae0, 0x00001aeb, 0x00001b00, 0x00001b03, + 0x00001b34, 0x00001b34, 0x00001b36, 0x00001b3a, + 0x00001b3c, 0x00001b3c, 0x00001b42, 0x00001b42, + 0x00001b6b, 0x00001b73, 0x00001b80, 0x00001b81, + 0x00001ba2, 0x00001ba5, 0x00001ba8, 0x00001ba9, + 0x00001bab, 0x00001bad, 0x00001be6, 0x00001be6, + 0x00001be8, 0x00001be9, 0x00001bed, 0x00001bed, + 0x00001bef, 0x00001bf1, 0x00001c2c, 0x00001c33, + 0x00001c36, 0x00001c37, 0x00001c78, 0x00001c7d, + 0x00001cd0, 0x00001cd2, 0x00001cd4, 0x00001ce0, + 0x00001ce2, 0x00001ce8, 0x00001ced, 0x00001ced, + 0x00001cf4, 0x00001cf4, 0x00001cf8, 0x00001cf9, + 0x00001d2c, 0x00001d6a, 0x00001d78, 0x00001d78, + 0x00001d9b, 0x00001dff, 0x00001fbd, 0x00001fbd, + 0x00001fbf, 0x00001fc1, 0x00001fcd, 0x00001fcf, + 0x00001fdd, 0x00001fdf, 0x00001fed, 0x00001fef, + 0x00001ffd, 0x00001ffe, 0x0000200b, 0x0000200f, + 0x00002018, 0x00002019, 0x00002024, 0x00002024, + 0x00002027, 0x00002027, 0x0000202a, 0x0000202e, + 0x00002060, 0x00002064, 0x00002066, 0x0000206f, + 0x00002071, 0x00002071, 0x0000207f, 0x0000207f, + 0x00002090, 0x0000209c, 0x000020d0, 0x000020f0, + 0x00002c7c, 0x00002c7d, 0x00002cef, 0x00002cf1, + 0x00002d6f, 0x00002d6f, 0x00002d7f, 0x00002d7f, + 0x00002de0, 0x00002dff, 0x00002e2f, 0x00002e2f, + 0x00003005, 0x00003005, 0x0000302a, 0x0000302d, + 0x00003031, 0x00003035, 0x0000303b, 0x0000303b, + 0x00003099, 0x0000309e, 0x000030fc, 0x000030fe, + 0x0000a015, 0x0000a015, 0x0000a4f8, 0x0000a4fd, + 0x0000a60c, 0x0000a60c, 0x0000a66f, 0x0000a672, + 0x0000a674, 0x0000a67d, 0x0000a67f, 0x0000a67f, + 0x0000a69c, 0x0000a69f, 0x0000a6f0, 0x0000a6f1, + 0x0000a700, 0x0000a721, 0x0000a770, 0x0000a770, + 0x0000a788, 0x0000a78a, 0x0000a7f1, 0x0000a7f4, + 0x0000a7f8, 0x0000a7f9, 0x0000a802, 0x0000a802, + 0x0000a806, 0x0000a806, 0x0000a80b, 0x0000a80b, + 0x0000a825, 0x0000a826, 0x0000a82c, 0x0000a82c, + 0x0000a8c4, 0x0000a8c5, 0x0000a8e0, 0x0000a8f1, + 0x0000a8ff, 0x0000a8ff, 0x0000a926, 0x0000a92d, + 0x0000a947, 0x0000a951, 0x0000a980, 0x0000a982, + 0x0000a9b3, 0x0000a9b3, 0x0000a9b6, 0x0000a9b9, + 0x0000a9bc, 0x0000a9bd, 0x0000a9cf, 0x0000a9cf, + 0x0000a9e5, 0x0000a9e6, 0x0000aa29, 0x0000aa2e, + 0x0000aa31, 0x0000aa32, 0x0000aa35, 0x0000aa36, + 0x0000aa43, 0x0000aa43, 0x0000aa4c, 0x0000aa4c, + 0x0000aa70, 0x0000aa70, 0x0000aa7c, 0x0000aa7c, + 0x0000aab0, 0x0000aab0, 0x0000aab2, 0x0000aab4, + 0x0000aab7, 0x0000aab8, 0x0000aabe, 0x0000aabf, + 0x0000aac1, 0x0000aac1, 0x0000aadd, 0x0000aadd, + 0x0000aaec, 0x0000aaed, 0x0000aaf3, 0x0000aaf4, + 0x0000aaf6, 0x0000aaf6, 0x0000ab5b, 0x0000ab5f, + 0x0000ab69, 0x0000ab6b, 0x0000abe5, 0x0000abe5, + 0x0000abe8, 0x0000abe8, 0x0000abed, 0x0000abed, + 0x0000fb1e, 0x0000fb1e, 0x0000fbb2, 0x0000fbc2, + 0x0000fe00, 0x0000fe0f, 0x0000fe13, 0x0000fe13, + 0x0000fe20, 0x0000fe2f, 0x0000fe52, 0x0000fe52, + 0x0000fe55, 0x0000fe55, 0x0000feff, 0x0000feff, + 0x0000ff07, 0x0000ff07, 0x0000ff0e, 0x0000ff0e, + 0x0000ff1a, 0x0000ff1a, 0x0000ff3e, 0x0000ff3e, + 0x0000ff40, 0x0000ff40, 0x0000ff70, 0x0000ff70, + 0x0000ff9e, 0x0000ff9f, 0x0000ffe3, 0x0000ffe3, + 0x0000fff9, 0x0000fffb, 0x000101fd, 0x000101fd, + 0x000102e0, 0x000102e0, 0x00010376, 0x0001037a, + 0x00010780, 0x00010785, 0x00010787, 0x000107b0, + 0x000107b2, 0x000107ba, 0x00010a01, 0x00010a03, + 0x00010a05, 0x00010a06, 0x00010a0c, 0x00010a0f, + 0x00010a38, 0x00010a3a, 0x00010a3f, 0x00010a3f, + 0x00010ae5, 0x00010ae6, 0x00010d24, 0x00010d27, + 0x00010d4e, 0x00010d4e, 0x00010d69, 0x00010d6d, + 0x00010d6f, 0x00010d6f, 0x00010eab, 0x00010eac, + 0x00010ec5, 0x00010ec5, 0x00010efa, 0x00010eff, 0x00010f46, 0x00010f50, 0x00010f82, 0x00010f85, 0x00011001, 0x00011001, 0x00011038, 0x00011046, 0x00011070, 0x00011070, 0x00011073, 0x00011074, @@ -2645,14 +2678,16 @@ static const unsigned int _ucprop_ranges[] = { 0x00011a3b, 0x00011a3e, 0x00011a47, 0x00011a47, 0x00011a51, 0x00011a56, 0x00011a59, 0x00011a5b, 0x00011a8a, 0x00011a96, 0x00011a98, 0x00011a99, - 0x00011c30, 0x00011c36, 0x00011c38, 0x00011c3d, - 0x00011c3f, 0x00011c3f, 0x00011c92, 0x00011ca7, - 0x00011caa, 0x00011cb0, 0x00011cb2, 0x00011cb3, - 0x00011cb5, 0x00011cb6, 0x00011d31, 0x00011d36, - 0x00011d3a, 0x00011d3a, 0x00011d3c, 0x00011d3d, - 0x00011d3f, 0x00011d45, 0x00011d47, 0x00011d47, - 0x00011d90, 0x00011d91, 0x00011d95, 0x00011d95, - 0x00011d97, 0x00011d97, 0x00011ef3, 0x00011ef4, + 0x00011b60, 0x00011b60, 0x00011b62, 0x00011b64, + 0x00011b66, 0x00011b66, 0x00011c30, 0x00011c36, + 0x00011c38, 0x00011c3d, 0x00011c3f, 0x00011c3f, + 0x00011c92, 0x00011ca7, 0x00011caa, 0x00011cb0, + 0x00011cb2, 0x00011cb3, 0x00011cb5, 0x00011cb6, + 0x00011d31, 0x00011d36, 0x00011d3a, 0x00011d3a, + 0x00011d3c, 0x00011d3d, 0x00011d3f, 0x00011d45, + 0x00011d47, 0x00011d47, 0x00011d90, 0x00011d91, + 0x00011d95, 0x00011d95, 0x00011d97, 0x00011d97, + 0x00011dd9, 0x00011dd9, 0x00011ef3, 0x00011ef4, 0x00011f00, 0x00011f01, 0x00011f36, 0x00011f3a, 0x00011f40, 0x00011f40, 0x00011f42, 0x00011f42, 0x00011f5a, 0x00011f5a, 0x00013430, 0x00013440, @@ -2662,1620 +2697,1657 @@ static const unsigned int _ucprop_ranges[] = { 0x00016d40, 0x00016d42, 0x00016d6b, 0x00016d6c, 0x00016f4f, 0x00016f4f, 0x00016f8f, 0x00016f9f, 0x00016fe0, 0x00016fe1, 0x00016fe3, 0x00016fe4, - 0x0001aff0, 0x0001aff3, 0x0001aff5, 0x0001affb, - 0x0001affd, 0x0001affe, 0x0001bc9d, 0x0001bc9e, - 0x0001bca0, 0x0001bca3, 0x0001cf00, 0x0001cf2d, - 0x0001cf30, 0x0001cf46, 0x0001d167, 0x0001d169, - 0x0001d173, 0x0001d182, 0x0001d185, 0x0001d18b, - 0x0001d1aa, 0x0001d1ad, 0x0001d242, 0x0001d244, - 0x0001da00, 0x0001da36, 0x0001da3b, 0x0001da6c, - 0x0001da75, 0x0001da75, 0x0001da84, 0x0001da84, - 0x0001da9b, 0x0001da9f, 0x0001daa1, 0x0001daaf, - 0x0001e000, 0x0001e006, 0x0001e008, 0x0001e018, - 0x0001e01b, 0x0001e021, 0x0001e023, 0x0001e024, - 0x0001e026, 0x0001e02a, 0x0001e030, 0x0001e06d, - 0x0001e08f, 0x0001e08f, 0x0001e130, 0x0001e13d, - 0x0001e2ae, 0x0001e2ae, 0x0001e2ec, 0x0001e2ef, - 0x0001e4eb, 0x0001e4ef, 0x0001e5ee, 0x0001e5ef, + 0x00016ff2, 0x00016ff3, 0x0001aff0, 0x0001aff3, + 0x0001aff5, 0x0001affb, 0x0001affd, 0x0001affe, + 0x0001bc9d, 0x0001bc9e, 0x0001bca0, 0x0001bca3, + 0x0001cf00, 0x0001cf2d, 0x0001cf30, 0x0001cf46, + 0x0001d167, 0x0001d169, 0x0001d173, 0x0001d182, + 0x0001d185, 0x0001d18b, 0x0001d1aa, 0x0001d1ad, + 0x0001d242, 0x0001d244, 0x0001da00, 0x0001da36, + 0x0001da3b, 0x0001da6c, 0x0001da75, 0x0001da75, + 0x0001da84, 0x0001da84, 0x0001da9b, 0x0001da9f, + 0x0001daa1, 0x0001daaf, 0x0001e000, 0x0001e006, + 0x0001e008, 0x0001e018, 0x0001e01b, 0x0001e021, + 0x0001e023, 0x0001e024, 0x0001e026, 0x0001e02a, + 0x0001e030, 0x0001e06d, 0x0001e08f, 0x0001e08f, + 0x0001e130, 0x0001e13d, 0x0001e2ae, 0x0001e2ae, + 0x0001e2ec, 0x0001e2ef, 0x0001e4eb, 0x0001e4ef, + 0x0001e5ee, 0x0001e5ef, 0x0001e6e3, 0x0001e6e3, + 0x0001e6e6, 0x0001e6e6, 0x0001e6ee, 0x0001e6ef, + 0x0001e6f5, 0x0001e6f5, 0x0001e6ff, 0x0001e6ff, 0x0001e8d0, 0x0001e8d6, 0x0001e944, 0x0001e94b, 0x0001f3fb, 0x0001f3ff, 0x000e0001, 0x000e0001, 0x000e0020, 0x000e007f, 0x000e0100, 0x000e01ef }; -static const unsigned _uccase_upper_g_size = 306; +static const unsigned _uccase_upper_g_size = 296; static const short _uccase_upper_g[] = { - 3332, 32, 1410, 122, 4805, 2, 25559, 556, - 94, 76, 416, 837, 187, 1295, 46, 592, - 84, 1561, 3990, 79, 536, 1310, 7720, 1, - 448, 643, 1767, 268, 535, 1298, 352, 1137, - 118, 11, 442, 70, -619, 33, 1186, 4346, - 1179, 2, 863, 924, 5932, 572, 252, 824, - 623, 170, 73, 1, -113, 189, -663, 176, - 4628, 183, 1162, 66, 550, 1406, 1580, 2160, - 45, 1073, 1123, 1120, 474, 27, -337, 6, - -852, 252, 3326, 22, 731, 44, 793, 873, - 1305, 2397, 545, 554, 1732, 1107, 897, 58, - 537, 1335, 99, 181, 16501, 19, 493, 2, - 520, 2024, 129, 565, 556, 331, 192, 44, - 516, 1, 2432, 197, -910, 82, 4898, 14, - -963, 1, 886, 1750, 1691, 1920, 616, 645, - 2555, 155, 77, 36, 10886, 22, 506, 520, - 1804, 16, 870, 9, -1321, 2097, 1547, 2548, - 702, 1259, 8016, 561, 21, 2099, 606, 1, - 325, 5, 3624, 16, 1341, 2, 2997, 63, - 202, 2577, 966, 893, 297, 558, 12, 1017, - 2683, 1, 4145, 708, 5119, 16, -989, 1, - 768, 12, 1026, 180, 703, 81, 4373, 968, - 564, 621, 676, 1, 2583, 69, 1315, 27, - -1048, 2, 1531, 187, 7, 350, 4635, 17, - 2013, 515, 1109, 3288, 1011, 1, 530, 564, - 1074, 18, 1471, 100, 825, 181, 1150, 212, - 1011, 12, 1614, 985, 1082, 84, 102, 14, - 166, 224, 822, 19, -1079, 1630, 4882, 161, - 309, 1620, 390, 601, -1467, 1177, 1155, 692, - 940, 4, -406, 1, 1028, 566, -1118, 348, - 2880, 9, 122, 1782, 55, 3, 579, 1034, - 1252, 37, 1531, 1410, -504, 1, 1199, 569, - -1169, 405, 1541, 29, 387, 1989, 33, 816, - 4142, 872, 1347, 517, 2656, 1393, -610, 1, - 1191, 31, 1294, 164, 16301, 10, 857, 602, - 32, 985, 2445, 1208, 323, 2159, 3138, 31, - 3063, 1, 1033, 35, 1048, 40, 1655, 50, - 1144, 577, 81, 170, 13582, 1154, 2882, 424, - 5094, 288 + 5173, 1327, 662, 96, -164, 48, -492, 1, + 365, 482, 321, 681, 4198, 272, 313, 2175, + 861, 42, 151, 387, 2049, 2, 126, 2543, + 1017, 18, 1026, 869, 1317, 1, 1026, 547, + -1089, 1, -235, 197, 1443, 970, 380, 589, + 322, 1290, 4261, 224, 375, 2601, 2433, 75, + 84, -78, 2350, 1, 233, 201, 1411, 36, + 490, 484, -981, 2, 2336, 3, 286, 65, + 3591, 553, -522, 685, 209, 535, 2717, 416, + 640, 610, 70, 1447, 887, 162, 76, 659, + 862, 1, 546, 1898, 5192, 11, 2941, 630, + 5, 4, 6427, 2, 1465, 79, 2714, 247, + 2133, 1592, 3167, 4, -1186, 1824, 9109, 126, + 201, 4990, 116, 9, 271, 1173, 2684, 2, + 3193, 5555, 187, 1, 598, 3070, 1789, 8, + 207, 18, 2105, 1, 378, 1393, -718, 2572, + -1149, 37, 528, 6943, 14669, 141, 1099, 1486, + 1219, 530, 5, 2073, 1868, 1, 852, 395, + 1236, 1, 1358, 969, 1801, 36, 117, 13, + 279, 4, 529, 31, 2582, 3135, -1156, 333, + 32767, 1410, 16838, 61, 239, -994, 1536, 2, + 520, 2958, 2821, 4, 560, 2608, -419, 3, + 594, 270, 3218, 506, 720, 2, 1026, 131, + 256, 718, 2657, 1591, 1672, 449, -1520, -927, + 540, 2, 1041, -1035, 1749, 7, 1121, 842, + 2419, 1, 776, 1239, -469, 33, 2144, 299, + 1400, 802, -77, 88, -85, 72, 533, 609, + 1851, 1666, 305, 8, -1564, -977, 4680, 27, + 107, 753, 1831, 6, 348, 1745, 2786, 2, + 535, 1897, 8874, 13, 2239, 157, 1703, 286, + 820, 9, 1240, 1631, 216, 768, 2977, 292, + -1162, 5, 1210, 946, 6605, 741, 49, 384, + 794, 2, 524, 241, 656, 12, 122, 1978, + 2495, 4, 8929, 575, 7400, 513, 1071, 32, + -479, 15, 651, 1024, 666, 854, 1797, 4, + 183, -412, 852, 6, 127, 1574, 2028, 1, + 69, 1571, 1799, 1, 485, 2664, 3076, 1 }; -static const unsigned _uccase_upper_table_size = 1552; +static const unsigned _uccase_upper_table_size = 1580; static const unsigned _uccase_upper_table[] = { - 0x0000012b, 0x0000012a, 0x00000271, 0x00002c6e, - 0x0000a687, 0x0000a686, 0x000013fb, 0x000013f3, - 0x0000050d, 0x0000050c, 0x00002cee, 0x00002ced, - 0x00001fa7, 0x02000045, 0x00001e8b, 0x00001e8a, - 0x00001f94, 0x02000024, 0x00002c44, 0x00002c14, - 0x0000a691, 0x0000a690, 0x00001f62, 0x00001f6a, - 0x000105b4, 0x0001058d, 0x00001e47, 0x00001e46, - 0x0000abab, 0x000013db, 0x0000024f, 0x0000024e, - 0x00001c81, 0x00000414, 0x0000a741, 0x0000a740, - 0x0000ab82, 0x000013b2, 0x00000078, 0x00000058, - 0x000010ed, 0x00001cad, 0x00010ce4, 0x00010ca4, - 0x00000493, 0x00000492, 0x00000430, 0x00000410, - 0x0000a72d, 0x0000a72c, 0x00000205, 0x00000204, - 0x0000abb2, 0x000013e2, 0x000001dd, 0x0000018e, - 0x000010f5, 0x00001cb5, 0x000104fa, 0x000104d2, - 0x0000049b, 0x0000049a, 0x000024da, 0x000024c0, - 0x00001e0b, 0x00001e0a, 0x00001fab, 0x0200010c, - 0x00001e9a, 0x02000097, 0x00002178, 0x00002168, - 0x0000a695, 0x0000a694, 0x00016e63, 0x00016e43, - 0x00002cb9, 0x00002cb8, 0x00000185, 0x00000184, - 0x00001e0d, 0x00001e0c, 0x00000142, 0x00000141, - 0x00010d70, 0x00010d50, 0x0000aba2, 0x000013d2, - 0x00001ec7, 0x00001ec6, 0x00001ecf, 0x00001ece, - 0x000000eb, 0x000000cb, 0x0000019b, 0x0000a7dc, - 0x00010d81, 0x00010d61, 0x00001ffc, 0x02000121, - 0x0000056d, 0x0000053d, 0x00010cd1, 0x00010c91, - 0x0001e92d, 0x0001e90b, 0x00000161, 0x00000160, - 0x0001043c, 0x00010414, 0x00000269, 0x00000196, - 0x0000a7db, 0x0000a7da, 0x0000a745, 0x0000a744, - 0x00002c5f, 0x00002c2f, 0x0000ab83, 0x000013b3, - 0x00000252, 0x00002c70, 0x00000242, 0x00000241, - 0x00000573, 0x00000543, 0x0000a7d9, 0x0000a7d8, - 0x00001f86, 0x02000012, 0x00001f02, 0x00001f0a, - 0x0000014d, 0x0000014c, 0x000104f2, 0x000104ca, - 0x0000a65b, 0x0000a65a, 0x000004bf, 0x000004be, - 0x00001f23, 0x00001f2b, 0x0000aba1, 0x000013d1, - 0x000001c9, 0x000001c7, 0x0000ab77, 0x000013a7, - 0x000104e4, 0x000104bc, 0x00000473, 0x00000472, - 0x00000390, 0x03000080, 0x00002cb7, 0x00002cb6, - 0x00000209, 0x00000208, 0x00001ef1, 0x00001ef0, - 0x0000217f, 0x0000216f, 0x00010cda, 0x00010c9a, - 0x00001fe2, 0x030000be, 0x00001ef5, 0x00001ef4, - 0x0000057a, 0x0000054a, 0x00010443, 0x0001041b, - 0x000001a3, 0x000001a2, 0x0000a781, 0x0000a780, - 0x000004e3, 0x000004e2, 0x0000a757, 0x0000a756, - 0x00010ced, 0x00010cad, 0x00002ccb, 0x00002cca, - 0x00001f32, 0x00001f3a, 0x0001059b, 0x00010574, - 0x000004cf, 0x000004c0, 0x0000a74f, 0x0000a74e, - 0x00001f11, 0x00001f19, 0x00000061, 0x00000041, - 0x0000a64f, 0x0000a64e, 0x00000477, 0x00000476, - 0x00010d7a, 0x00010d5a, 0x00002c68, 0x00002c67, - 0x000004f7, 0x000004f6, 0x00002d05, 0x000010a5, - 0x00000127, 0x00000126, 0x0001043a, 0x00010412, - 0x000010f2, 0x00001cb2, 0x000003ed, 0x000003ec, - 0x000104dd, 0x000104b5, 0x00001e71, 0x00001e70, - 0x000000e1, 0x000000c1, 0x000003f5, 0x00000395, - 0x000010d1, 0x00001c91, 0x0000013e, 0x0000013d, - 0x0000a7a7, 0x0000a7a6, 0x0000ff52, 0x0000ff32, - 0x000024e4, 0x000024ca, 0x0000051d, 0x0000051c, - 0x00000283, 0x000001a9, 0x000010d9, 0x00001c99, - 0x0000ff59, 0x0000ff39, 0x000003b0, 0x03000084, - 0x00001efb, 0x00001efa, 0x000118c2, 0x000118a2, - 0x0000ab72, 0x000013a2, 0x00001f35, 0x00001f3d, - 0x0000028b, 0x000001b2, 0x0000a69b, 0x0000a69a, - 0x000003cc, 0x0000038c, 0x00016e68, 0x00016e48, - 0x000003f0, 0x0000039a, 0x0000016b, 0x0000016a, - 0x00000272, 0x0000019d, 0x0000a661, 0x0000a660, - 0x000001cc, 0x000001ca, 0x00000451, 0x00000401, - 0x00001e07, 0x00001e06, 0x00001f37, 0x00001f3f, - 0x0001044a, 0x00010422, 0x0001e930, 0x0001e90e, - 0x000004fb, 0x000004fa, 0x000004d3, 0x000004d2, - 0x00002c9f, 0x00002c9e, 0x00000111, 0x00000110, - 0x00002c30, 0x00002c00, 0x00001fa6, 0x02000042, - 0x000000f0, 0x000000d0, 0x000104e2, 0x000104ba, - 0x00002d24, 0x000010c4, 0x00001ee7, 0x00001ee6, - 0x0000020b, 0x0000020a, 0x00002c89, 0x00002c88, - 0x000003c6, 0x000003a6, 0x0000a747, 0x0000a746, - 0x0000a76b, 0x0000a76a, 0x000004f5, 0x000004f4, - 0x0000ff5a, 0x0000ff3a, 0x0000ab75, 0x000013a5, - 0x000003af, 0x0000038a, 0x00001efd, 0x00001efc, - 0x00000101, 0x00000100, 0x0000a693, 0x0000a692, - 0x00001f9a, 0x020000f1, 0x000010dd, 0x00001c9d, - 0x00001f52, 0x0300009d, 0x000000df, 0x02000051, - 0x00000503, 0x00000502, 0x00010d7b, 0x00010d5b, - 0x0000fb01, 0x02000057, 0x000003c2, 0x000003a3, - 0x0000016d, 0x0000016c, 0x00000263, 0x00000194, - 0x0001044b, 0x00010423, 0x00000465, 0x00000464, - 0x000003ad, 0x00000388, 0x00001fb4, 0x02000127, - 0x0000abb1, 0x000013e1, 0x00001e25, 0x00001e24, - 0x00000148, 0x00000147, 0x0001e93c, 0x0001e91a, - 0x000000ee, 0x000000ce, 0x0000023f, 0x00002c7e, - 0x0000abba, 0x000013ea, 0x00001f00, 0x00001f08, - 0x00010d79, 0x00010d59, 0x000003cd, 0x0000038e, - 0x0000a651, 0x0000a650, 0x0000ab84, 0x000013b4, - 0x00002c58, 0x00002c28, 0x0000057b, 0x0000054b, - 0x000010fa, 0x00001cba, 0x00010ce8, 0x00010ca8, - 0x000004a1, 0x000004a0, 0x00002c95, 0x00002c94, - 0x00000567, 0x00000537, 0x0000a657, 0x0000a656, - 0x000000ed, 0x000000cd, 0x00001f8f, 0x020000e8, - 0x000000e4, 0x000000c4, 0x00001f9e, 0x020000fd, - 0x00001c86, 0x0000042a, 0x000118c8, 0x000118a8, - 0x0000a68f, 0x0000a68e, 0x0000011b, 0x0000011a, - 0x0000a77a, 0x0000a779, 0x0000015b, 0x0000015a, - 0x000001f2, 0x000001f1, 0x00010ce5, 0x00010ca5, - 0x00001e6b, 0x00001e6a, 0x00001f51, 0x00001f59, - 0x00001f12, 0x00001f1a, 0x0000a66b, 0x0000a66a, - 0x000104e9, 0x000104c1, 0x000024d4, 0x000024ba, - 0x00000073, 0x00000053, 0x00001f95, 0x02000027, - 0x00002c76, 0x00002c75, 0x0000a65d, 0x0000a65c, - 0x0000026b, 0x00002c62, 0x00000455, 0x00000405, - 0x00001ff6, 0x020000d0, 0x00001f70, 0x00001fba, - 0x0001042a, 0x00010402, 0x000013f8, 0x000013f0, - 0x000001e1, 0x000001e0, 0x00016e72, 0x00016e52, - 0x00002d0a, 0x000010aa, 0x00001e01, 0x00001e00, - 0x00000062, 0x00000042, 0x0000ab93, 0x000013c3, - 0x00001fc7, 0x0300013a, 0x000004d1, 0x000004d0, - 0x00000575, 0x00000545, 0x0000abbf, 0x000013ef, - 0x000118de, 0x000118be, 0x000010d5, 0x00001c95, - 0x00002d11, 0x000010b1, 0x0000047f, 0x0000047e, - 0x0000217b, 0x0000216b, 0x000105b7, 0x00010590, - 0x000118d0, 0x000118b0, 0x00001ead, 0x00001eac, - 0x00001f87, 0x02000015, 0x00002cbf, 0x00002cbe, - 0x0001043d, 0x00010415, 0x000000fd, 0x000000dd, - 0x000004d7, 0x000004d6, 0x00001e65, 0x00001e64, - 0x000118d8, 0x000118b8, 0x00002d02, 0x000010a2, - 0x0000a66d, 0x0000a66c, 0x0000a763, 0x0000a762, - 0x000004cc, 0x000004cb, 0x00001eed, 0x00001eec, - 0x00000153, 0x00000152, 0x00001e7b, 0x00001e7a, - 0x000104fb, 0x000104d3, 0x00002c5c, 0x00002c2c, - 0x000004e7, 0x000004e6, 0x0000ab78, 0x000013a8, - 0x00002d03, 0x000010a3, 0x00001e41, 0x00001e40, - 0x0001e92c, 0x0001e90a, 0x0000a72f, 0x0000a72e, - 0x000004b9, 0x000004b8, 0x000001fb, 0x000001fa, - 0x00016e61, 0x00016e41, 0x000001d2, 0x000001d1, - 0x0000ab7d, 0x000013ad, 0x000003b1, 0x00000391, - 0x0001e93d, 0x0001e91b, 0x000104e7, 0x000104bf, - 0x00001ec9, 0x00001ec8, 0x0000006e, 0x0000004e, - 0x00001fa9, 0x02000106, 0x000118df, 0x000118bf, - 0x000104f0, 0x000104c8, 0x00001c88, 0x0000a64a, - 0x000105b9, 0x00010592, 0x00001e19, 0x00001e18, - 0x00001ea9, 0x00001ea8, 0x000001bd, 0x000001bc, - 0x0001e92e, 0x0001e90c, 0x0001e93f, 0x0001e91d, - 0x0000046d, 0x0000046c, 0x000003ce, 0x0000038f, - 0x00001ee9, 0x00001ee8, 0x00000183, 0x00000182, - 0x0000ab95, 0x000013c5, 0x0000ff43, 0x0000ff23, - 0x0000a647, 0x0000a646, 0x0000a767, 0x0000a766, - 0x000104e3, 0x000104bb, 0x00002d09, 0x000010a9, - 0x00001e83, 0x00001e82, 0x00001f85, 0x0200000f, - 0x00002c91, 0x00002c90, 0x000004c6, 0x000004c5, - 0x000013fd, 0x000013f5, 0x000118cd, 0x000118ad, - 0x000003e5, 0x000003e4, 0x0000ab8f, 0x000013bf, - 0x000003db, 0x000003da, 0x0000049d, 0x0000049c, - 0x00001fa2, 0x02000036, 0x0000abbb, 0x000013eb, - 0x00001e9b, 0x00001e60, 0x000010eb, 0x00001cab, - 0x00010431, 0x00010409, 0x0000a655, 0x0000a654, - 0x000001eb, 0x000001ea, 0x0000ff4c, 0x0000ff2c, - 0x00001e51, 0x00001e50, 0x000024de, 0x000024c4, - 0x000118cb, 0x000118ab, 0x00010440, 0x00010418, - 0x000003b5, 0x00000395, 0x0000051f, 0x0000051e, - 0x000024db, 0x000024c1, 0x000000e7, 0x000000c7, - 0x000003f1, 0x000003a1, 0x0001e925, 0x0001e903, - 0x00002c40, 0x00002c10, 0x0001044c, 0x00010424, - 0x0000fb02, 0x0200005a, 0x00001fb0, 0x00001fb8, - 0x0000fb13, 0x0200006e, 0x00001ea3, 0x00001ea2, - 0x00002d0f, 0x000010af, 0x00010d7c, 0x00010d5c, - 0x00000505, 0x00000504, 0x00001e5b, 0x00001e5a, - 0x000118c3, 0x000118a3, 0x0000026f, 0x0000019c, - 0x0000ab9f, 0x000013cf, 0x0000011f, 0x0000011e, - 0x000004d5, 0x000004d4, 0x00000140, 0x0000013f, - 0x00001f42, 0x00001f4a, 0x00001e4b, 0x00001e4a, - 0x00000173, 0x00000172, 0x00010d74, 0x00010d54, - 0x00000444, 0x00000424, 0x0000a7a5, 0x0000a7a4, - 0x00001e21, 0x00001e20, 0x00001e3d, 0x00001e3c, - 0x0001e93a, 0x0001e918, 0x00010cec, 0x00010cac, - 0x00000495, 0x00000494, 0x0000a755, 0x0000a754, - 0x00002c36, 0x00002c06, 0x00001fad, 0x02000112, - 0x00000521, 0x00000520, 0x00001f73, 0x00001fc9, - 0x000010f7, 0x00001cb7, 0x000003bd, 0x0000039d, - 0x00002d04, 0x000010a4, 0x00002d08, 0x000010a8, - 0x000000e3, 0x000000c3, 0x00001e09, 0x00001e08, - 0x000000f1, 0x000000d1, 0x0000214e, 0x00002132, - 0x00000525, 0x00000524, 0x00010435, 0x0001040d, - 0x000003ba, 0x0000039a, 0x00000440, 0x00000420, - 0x00001e7f, 0x00001e7e, 0x0000217c, 0x0000216c, - 0x00002c38, 0x00002c08, 0x00010599, 0x00010572, - 0x0000044b, 0x0000042b, 0x000004c8, 0x000004c7, - 0x00001e93, 0x00001e92, 0x000003ae, 0x00000389, - 0x000004a7, 0x000004a6, 0x0000a685, 0x0000a684, - 0x00001e1b, 0x00001e1a, 0x000118db, 0x000118bb, - 0x00001e4d, 0x00001e4c, 0x00001f43, 0x00001f4b, - 0x000001e7, 0x000001e6, 0x00002d0e, 0x000010ae, - 0x00000450, 0x00000400, 0x000004dd, 0x000004dc, - 0x00001f90, 0x02000018, 0x000010f1, 0x00001cb1, - 0x00010ce6, 0x00010ca6, 0x0000a735, 0x0000a734, - 0x0000052d, 0x0000052c, 0x00016e70, 0x00016e50, - 0x00000203, 0x00000202, 0x00002d13, 0x000010b3, - 0x00010439, 0x00010411, 0x0000a64d, 0x0000a64c, - 0x000000fb, 0x000000db, 0x00001e1f, 0x00001e1e, - 0x000004ed, 0x000004ec, 0x0000abb6, 0x000013e6, - 0x000001cb, 0x000001ca, 0x000024e6, 0x000024cc, - 0x00002d01, 0x000010a1, 0x00001eb1, 0x00001eb0, - 0x00000569, 0x00000539, 0x00002cbb, 0x00002cba, - 0x0000fb03, 0x0300005d, 0x00000233, 0x00000232, - 0x0000043a, 0x0000041a, 0x00010445, 0x0001041d, - 0x0000057c, 0x0000054c, 0x00001ee5, 0x00001ee4, - 0x0000ab8b, 0x000013bb, 0x00001ebd, 0x00001ebc, - 0x000001a5, 0x000001a4, 0x000001ef, 0x000001ee, - 0x000001f5, 0x000001f4, 0x00001e8f, 0x00001e8e, - 0x0000ab98, 0x000013c8, 0x00002d00, 0x000010a0, - 0x00000149, 0x0200007d, 0x00010d83, 0x00010d63, - 0x00016e6e, 0x00016e4e, 0x00016e77, 0x00016e57, - 0x000003e3, 0x000003e2, 0x00000070, 0x00000050, - 0x00000155, 0x00000154, 0x0000a79f, 0x0000a79e, - 0x0000217e, 0x0000216e, 0x0000ff47, 0x0000ff27, - 0x000004df, 0x000004de, 0x00001f84, 0x0200000c, - 0x00001e5d, 0x00001e5c, 0x00001e37, 0x00001e36, - 0x000000e8, 0x000000c8, 0x00002173, 0x00002163, - 0x0000a7d7, 0x0000a7d6, 0x00010429, 0x00010401, - 0x00002cc3, 0x00002cc2, 0x00000207, 0x00000206, - 0x0001e922, 0x0001e900, 0x00002170, 0x00002160, - 0x0000a7a9, 0x0000a7a8, 0x00010cdd, 0x00010c9d, - 0x00002d07, 0x000010a7, 0x00002d10, 0x000010b0, - 0x00001e79, 0x00001e78, 0x00000377, 0x00000376, - 0x00010447, 0x0001041f, 0x00016e67, 0x00016e47, - 0x0000a791, 0x0000a790, 0x00001f04, 0x00001f0c, - 0x00001e2d, 0x00001e2c, 0x000001ad, 0x000001ac, - 0x000104f9, 0x000104d1, 0x0000045b, 0x0000040b, - 0x00000109, 0x00000108, 0x00001f92, 0x0200001e, - 0x00002c81, 0x00002c80, 0x0001e92b, 0x0001e909, - 0x00010cdf, 0x00010c9f, 0x0001044f, 0x00010427, - 0x0000a75d, 0x0000a75c, 0x00010cce, 0x00010c8e, - 0x00001e33, 0x00001e32, 0x0000abad, 0x000013dd, - 0x000001e9, 0x000001e8, 0x0000017c, 0x0000017b, - 0x00010cee, 0x00010cae, 0x0000047d, 0x0000047c, - 0x00002c3d, 0x00002c0d, 0x0000019e, 0x00000220, - 0x00001fd3, 0x030000b3, 0x000003c5, 0x000003a5, - 0x00010ce2, 0x00010ca2, 0x000010d8, 0x00001c98, - 0x0001059e, 0x00010577, 0x0000056a, 0x0000053a, - 0x0000ff56, 0x0000ff36, 0x0000a7bf, 0x0000a7be, - 0x00001fd1, 0x00001fd9, 0x00000229, 0x00000228, - 0x00001f01, 0x00001f09, 0x00001c80, 0x00000412, - 0x0000fb05, 0x02000065, 0x00002c53, 0x00002c23, - 0x00001f8c, 0x020000df, 0x0000ff58, 0x0000ff38, - 0x0000037c, 0x000003fe, 0x00001fe5, 0x00001fec, - 0x00001fe1, 0x00001fe9, 0x00002cad, 0x00002cac, - 0x000010fe, 0x00001cbe, 0x00010448, 0x00010420, - 0x000003ef, 0x000003ee, 0x000001ed, 0x000001ec, - 0x000024e0, 0x000024c6, 0x00001e63, 0x00001e62, - 0x00001f71, 0x00001fbb, 0x0000a79b, 0x0000a79a, - 0x0000a649, 0x0000a648, 0x000003b2, 0x00000392, - 0x00010ccd, 0x00010c8d, 0x000010dc, 0x00001c9c, - 0x00001f54, 0x030000a1, 0x00001fa8, 0x02000103, - 0x0000043c, 0x0000041c, 0x00001edb, 0x00001eda, - 0x00010ce9, 0x00010ca9, 0x000104d9, 0x000104b1, - 0x00002d15, 0x000010b5, 0x00000075, 0x00000055, - 0x00002ce3, 0x00002ce2, 0x000001e3, 0x000001e2, - 0x00016e7e, 0x00016e5e, 0x00000583, 0x00000553, - 0x00000576, 0x00000546, 0x00001f15, 0x00001f1d, - 0x000010d0, 0x00001c90, 0x00001f8e, 0x020000e5, - 0x00002d1c, 0x000010bc, 0x00010cd9, 0x00010c99, - 0x000104db, 0x000104b3, 0x000118da, 0x000118ba, - 0x000000e5, 0x000000c5, 0x000105bc, 0x00010595, - 0x000024e5, 0x000024cb, 0x00010cd2, 0x00010c92, - 0x00001e7d, 0x00001e7c, 0x000118ce, 0x000118ae, - 0x00002cdb, 0x00002cda, 0x00001f63, 0x00001f6b, - 0x00010cd8, 0x00010c98, 0x00000457, 0x00000407, - 0x000000fe, 0x000000de, 0x000003f2, 0x000003f9, - 0x00001e61, 0x00001e60, 0x0000ab97, 0x000013c7, - 0x0000006c, 0x0000004c, 0x0000a725, 0x0000a724, - 0x00010ce7, 0x00010ca7, 0x00002c8f, 0x00002c8e, - 0x0000ab9a, 0x000013ca, 0x00001ef7, 0x00001ef6, - 0x00001ee1, 0x00001ee0, 0x00001faa, 0x02000109, - 0x00010449, 0x00010421, 0x00000437, 0x00000417, - 0x00001fc4, 0x0200012d, 0x00002d12, 0x000010b2, - 0x00001e53, 0x00001e52, 0x0000024b, 0x0000024a, - 0x00002c59, 0x00002c29, 0x00016e74, 0x00016e54, - 0x0000a739, 0x0000a738, 0x00000447, 0x00000427, - 0x00000105, 0x00000104, 0x0000ab73, 0x000013a3, - 0x00010cde, 0x00010c9e, 0x00000433, 0x00000413, - 0x0001044d, 0x00010425, 0x00001ec5, 0x00001ec4, - 0x00001f9d, 0x020000fa, 0x0000aba3, 0x000013d3, - 0x00001fb7, 0x03000136, 0x000004a5, 0x000004a4, - 0x0000a749, 0x0000a748, 0x0000ab8c, 0x000013bc, - 0x00001f7c, 0x00001ffa, 0x00002cd5, 0x00002cd4, - 0x00001f89, 0x020000d6, 0x0001e92a, 0x0001e908, - 0x000003b4, 0x00000394, 0x00000463, 0x00000462, - 0x00010cf1, 0x00010cb1, 0x00002c9b, 0x00002c9a, - 0x00000195, 0x000001f6, 0x00000439, 0x00000419, - 0x0001e939, 0x0001e917, 0x0000a783, 0x0000a782, - 0x00000570, 0x00000540, 0x000003e9, 0x000003e8, - 0x0000010d, 0x0000010c, 0x00001e6d, 0x00001e6c, - 0x00002174, 0x00002164, 0x0000a737, 0x0000a736, - 0x00002c4a, 0x00002c1a, 0x0000ff50, 0x0000ff30, - 0x00002c55, 0x00002c25, 0x00010432, 0x0001040a, - 0x0000aba5, 0x000013d5, 0x0000a7c3, 0x0000a7c2, - 0x000004bb, 0x000004ba, 0x0000021d, 0x0000021c, - 0x00010cc7, 0x00010c87, 0x000000f9, 0x000000d9, - 0x000010ef, 0x00001caf, 0x00000121, 0x00000120, - 0x0000048d, 0x0000048c, 0x000105a0, 0x00010579, - 0x00001f7a, 0x00001fea, 0x00000067, 0x00000047, - 0x0001e929, 0x0001e907, 0x00001f96, 0x0200002a, - 0x000105a6, 0x0001057f, 0x000105bb, 0x00010594, - 0x00000436, 0x00000416, 0x00016e7b, 0x00016e5b, - 0x00001eab, 0x00001eaa, 0x0000abac, 0x000013dc, - 0x0000a7bd, 0x0000a7bc, 0x00002c6a, 0x00002c69, - 0x0000043e, 0x0000041e, 0x00000445, 0x00000425, - 0x000003c4, 0x000003a4, 0x00001f13, 0x00001f1b, - 0x000010e4, 0x00001ca4, 0x00010cd0, 0x00010c90, - 0x000004c4, 0x000004c3, 0x00010cc3, 0x00010c83, - 0x00001fbe, 0x00000399, 0x00000446, 0x00000426, - 0x00001e85, 0x00001e84, 0x000024e2, 0x000024c8, - 0x0000ff44, 0x0000ff24, 0x0000a683, 0x0000a682, - 0x00000571, 0x00000541, 0x00001f7b, 0x00001feb, - 0x0000013c, 0x0000013b, 0x0000017f, 0x00000053, - 0x000003c3, 0x000003a3, 0x0000ff4e, 0x0000ff2e, - 0x00010cd6, 0x00010c96, 0x0000ab94, 0x000013c4, - 0x00001e35, 0x00001e34, 0x0000ab79, 0x000013a9, - 0x00002c47, 0x00002c17, 0x000001da, 0x000001d9, - 0x00010cd5, 0x00010c95, 0x00001fa3, 0x02000039, - 0x0000ff42, 0x0000ff22, 0x00000177, 0x00000176, - 0x00000151, 0x00000150, 0x00010d82, 0x00010d62, - 0x000003b7, 0x00000397, 0x0000a76d, 0x0000a76c, - 0x0000ab86, 0x000013b6, 0x00002cdd, 0x00002cdc, - 0x00000529, 0x00000528, 0x000010e9, 0x00001ca9, - 0x0000a641, 0x0000a640, 0x00000469, 0x00000468, - 0x00000572, 0x00000542, 0x00000264, 0x0000a7cb, - 0x0000fb15, 0x02000074, 0x00000275, 0x0000019f, - 0x00010d75, 0x00010d55, 0x0000ff4b, 0x0000ff2b, - 0x00001e91, 0x00001e90, 0x0000a645, 0x0000a644, - 0x000004ca, 0x000004c9, 0x00001e8d, 0x00001e8c, - 0x00002c3e, 0x00002c0e, 0x00000443, 0x00000423, - 0x0000a681, 0x0000a680, 0x00000448, 0x00000428, - 0x00001d79, 0x0000a77d, 0x00001f05, 0x00001f0d, - 0x0000013a, 0x00000139, 0x00000253, 0x00000181, - 0x0000057e, 0x0000054e, 0x0000a76f, 0x0000a76e, - 0x0000ab96, 0x000013c6, 0x00001e57, 0x00001e56, - 0x0000ab81, 0x000013b1, 0x00010cc6, 0x00010c86, - 0x00001c8a, 0x00001c89, 0x00002c66, 0x0000023e, - 0x00000266, 0x0000a7aa, 0x00000066, 0x00000046, - 0x00001f64, 0x00001f6c, 0x00010446, 0x0001041e, - 0x000010f9, 0x00001cb9, 0x000010ea, 0x00001caa, - 0x00000438, 0x00000418, 0x00001f26, 0x00001f2e, - 0x0000abb8, 0x000013e8, 0x00001fc3, 0x0200004b, - 0x0000028a, 0x000001b1, 0x0000217d, 0x0000216d, - 0x00000471, 0x00000470, 0x0000a659, 0x0000a658, - 0x00002c99, 0x00002c98, 0x00001ff3, 0x0200004e, - 0x0000027d, 0x00002c64, 0x0001e932, 0x0001e910, - 0x0000ff53, 0x0000ff33, 0x00000479, 0x00000478, - 0x00000561, 0x00000531, 0x00000268, 0x00000197, - 0x00002cbd, 0x00002cbc, 0x0000ab85, 0x000013b5, - 0x0000ff48, 0x0000ff28, 0x00002cc9, 0x00002cc8, - 0x0000056f, 0x0000053f, 0x000118c5, 0x000118a5, - 0x000000b5, 0x0000039c, 0x00000163, 0x00000162, - 0x00010433, 0x0001040b, 0x0001e92f, 0x0001e90d, - 0x000024e3, 0x000024c9, 0x00010ce1, 0x00010ca1, - 0x00000063, 0x00000043, 0x00001f57, 0x00001f5f, - 0x00002c41, 0x00002c11, 0x00001e23, 0x00001e22, - 0x000104da, 0x000104b2, 0x000010d4, 0x00001c94, - 0x00000180, 0x00000243, 0x00001f76, 0x00001fda, - 0x0000014f, 0x0000014e, 0x0000028c, 0x00000245, - 0x00010cd4, 0x00010c94, 0x00010d78, 0x00010d58, - 0x000105a4, 0x0001057d, 0x00002ccf, 0x00002cce, - 0x000118c7, 0x000118a7, 0x0001e933, 0x0001e911, - 0x00001ecb, 0x00001eca, 0x0000045d, 0x0000040d, - 0x00016e69, 0x00016e49, 0x00001fc2, 0x0200012a, - 0x000118c1, 0x000118a1, 0x0000ab7c, 0x000013ac, - 0x00001faf, 0x02000118, 0x00002d22, 0x000010c2, - 0x0000ab9c, 0x000013cc, 0x00016e79, 0x00016e59, - 0x000118c0, 0x000118a0, 0x0000abb3, 0x000013e3, - 0x00002c5b, 0x00002c2b, 0x000003bc, 0x0000039c, - 0x0000045a, 0x0000040a, 0x0000a733, 0x0000a732, - 0x000118dc, 0x000118bc, 0x0000ab89, 0x000013b9, - 0x0000abbd, 0x000013ed, 0x00000259, 0x0000018f, - 0x00016e60, 0x00016e40, 0x0000a753, 0x0000a752, - 0x0000020d, 0x0000020c, 0x00000065, 0x00000045, - 0x0000abaa, 0x000013da, 0x000001e5, 0x000001e4, - 0x0001e934, 0x0001e912, 0x0000a793, 0x0000a792, - 0x00001fc6, 0x020000ac, 0x00001e4f, 0x00001e4e, - 0x00001f36, 0x00001f3e, 0x000001b9, 0x000001b8, - 0x00002c57, 0x00002c27, 0x000000f5, 0x000000d5, - 0x000004ad, 0x000004ac, 0x0000a643, 0x0000a642, - 0x0000057d, 0x0000054d, 0x00000076, 0x00000056, - 0x0001e924, 0x0001e902, 0x0001059a, 0x00010573, - 0x0000ff4f, 0x0000ff2f, 0x00010cdc, 0x00010c9c, - 0x00002d0c, 0x000010ac, 0x00010cd7, 0x00010c97, - 0x00002cc5, 0x00002cc4, 0x0000037b, 0x000003fd, - 0x000105b5, 0x0001058e, 0x000003c8, 0x000003a8, - 0x00001ee3, 0x00001ee2, 0x000024d3, 0x000024b9, - 0x00002ca5, 0x00002ca4, 0x0000abb9, 0x000013e9, - 0x00000282, 0x0000a7c5, 0x00002176, 0x00002166, - 0x0000a785, 0x0000a784, 0x00001f10, 0x00001f18, - 0x00001e75, 0x00001e74, 0x00010cdb, 0x00010c9b, - 0x00000261, 0x0000a7ac, 0x0000a663, 0x0000a662, - 0x00010cc1, 0x00010c81, 0x000105a7, 0x00010580, - 0x0000006d, 0x0000004d, 0x00001f56, 0x030000a5, - 0x000104e8, 0x000104c0, 0x0001e935, 0x0001e913, - 0x0000043d, 0x0000041d, 0x0000021f, 0x0000021e, - 0x00002c35, 0x00002c05, 0x0000019a, 0x0000023d, - 0x0001042c, 0x00010404, 0x00002ce1, 0x00002ce0, - 0x00010cea, 0x00010caa, 0x0000a78c, 0x0000a78b, - 0x000105af, 0x00010588, 0x00002c49, 0x00002c19, - 0x00001e29, 0x00001e28, 0x000010f8, 0x00001cb8, - 0x000000ea, 0x000000ca, 0x00002c4d, 0x00002c1d, - 0x000104f3, 0x000104cb, 0x00000454, 0x00000404, - 0x000118d9, 0x000118b9, 0x000001ce, 0x000001cd, - 0x0000037d, 0x000003ff, 0x000000f6, 0x000000d6, - 0x00002175, 0x00002165, 0x00001e59, 0x00001e58, - 0x000118ca, 0x000118aa, 0x00002cc7, 0x00002cc6, - 0x00001fa5, 0x0200003f, 0x000024e1, 0x000024c7, - 0x000003cb, 0x000003ab, 0x00001fbc, 0x0200011b, - 0x000010d6, 0x00001c96, 0x00002c85, 0x00002c84, - 0x00001f53, 0x00001f5b, 0x0000024d, 0x0000024c, - 0x00000171, 0x00000170, 0x0000a759, 0x0000a758, - 0x00002c6c, 0x00002c6b, 0x0000ab9e, 0x000013ce, - 0x00001fb2, 0x02000124, 0x00001e67, 0x00001e66, - 0x0000a77c, 0x0000a77b, 0x0000a7cd, 0x0000a7cc, - 0x000004e1, 0x000004e0, 0x00002c3f, 0x00002c0f, - 0x00002d17, 0x000010b7, 0x00001e5f, 0x00001e5e, - 0x00001f99, 0x020000ee, 0x0000044f, 0x0000042f, - 0x00016e78, 0x00016e58, 0x00000585, 0x00000555, - 0x0000044d, 0x0000042d, 0x00001eff, 0x00001efe, - 0x00000133, 0x00000132, 0x0000025c, 0x0000a7ab, - 0x0000a699, 0x0000a698, 0x0000056b, 0x0000053b, - 0x00000458, 0x00000408, 0x0000a7ca, 0x0000a7c9, - 0x000010ff, 0x00001cbf, 0x00000199, 0x00000198, - 0x000104ee, 0x000104c6, 0x00001ed1, 0x00001ed0, - 0x0000044a, 0x0000042a, 0x00010d7d, 0x00010d5d, - 0x00002cd1, 0x00002cd0, 0x00001d8e, 0x0000a7c6, - 0x0000029d, 0x0000a7b2, 0x00000225, 0x00000224, - 0x0000047b, 0x0000047a, 0x000104e5, 0x000104bd, - 0x000003b6, 0x00000396, 0x00001f55, 0x00001f5d, - 0x000104ed, 0x000104c5, 0x000003e7, 0x000003e6, - 0x0000a761, 0x0000a760, 0x000004ab, 0x000004aa, - 0x00002c65, 0x0000023a, 0x000010d7, 0x00001c97, - 0x00001e6f, 0x00001e6e, 0x00000213, 0x00000212, - 0x0000a73b, 0x0000a73a, 0x0000a7c8, 0x0000a7c7, - 0x000004eb, 0x000004ea, 0x00002d1f, 0x000010bf, - 0x00000072, 0x00000052, 0x00001f33, 0x00001f3b, - 0x000003d5, 0x000003a6, 0x00016e76, 0x00016e56, - 0x0000a77f, 0x0000a77e, 0x000024e7, 0x000024cd, - 0x00002c43, 0x00002c13, 0x000010e1, 0x00001ca1, - 0x00010436, 0x0001040e, 0x0000048b, 0x0000048a, - 0x000104df, 0x000104b7, 0x0000a74b, 0x0000a74a, - 0x00000453, 0x00000403, 0x00000137, 0x00000136, - 0x000001b6, 0x000001b5, 0x000104e6, 0x000104be, - 0x0000052f, 0x0000052e, 0x00002c54, 0x00002c24, - 0x000024d5, 0x000024bb, 0x00002cd7, 0x00002cd6, - 0x00001f8b, 0x020000dc, 0x00000249, 0x00000248, - 0x00002c51, 0x00002c21, 0x0000a7b7, 0x0000a7b6, - 0x00002c97, 0x00002c96, 0x0000ab9d, 0x000013cd, - 0x000118d1, 0x000118b1, 0x0000ab53, 0x0000a7b3, - 0x000010f4, 0x00001cb4, 0x0000a74d, 0x0000a74c, - 0x00010cef, 0x00010caf, 0x000104f1, 0x000104c9, - 0x0000abae, 0x000013de, 0x0001042d, 0x00010405, - 0x00001f65, 0x00001f6d, 0x00001ecd, 0x00001ecc, - 0x0000044e, 0x0000042e, 0x00001fd2, 0x030000af, - 0x000003c1, 0x000003a1, 0x00001e43, 0x00001e42, - 0x0000aba7, 0x000013d7, 0x00002184, 0x00002183, - 0x000004bd, 0x000004bc, 0x0000a73d, 0x0000a73c, - 0x000004ef, 0x000004ee, 0x00001e17, 0x00001e16, - 0x00000131, 0x00000049, 0x0001042f, 0x00010407, - 0x0000ff54, 0x0000ff34, 0x000001f3, 0x000001f1, - 0x00001f06, 0x00001f0e, 0x000105b3, 0x0001058c, - 0x00001f20, 0x00001f28, 0x000010de, 0x00001c9e, - 0x00010444, 0x0001041c, 0x00000565, 0x00000535, - 0x00000497, 0x00000496, 0x00000523, 0x00000522, - 0x00002cdf, 0x00002cde, 0x00001e98, 0x02000091, - 0x0000a7bb, 0x0000a7ba, 0x00002c45, 0x00002c15, - 0x0000a79d, 0x0000a79c, 0x00000579, 0x00000549, - 0x00002c83, 0x00002c82, 0x0000fb16, 0x02000077, - 0x00001ef9, 0x00001ef8, 0x00000217, 0x00000216, - 0x00002d18, 0x000010b8, 0x0000017e, 0x0000017d, - 0x00000441, 0x00000421, 0x0000057f, 0x0000054f, - 0x00001e87, 0x00001e86, 0x00000103, 0x00000102, - 0x00002c4e, 0x00002c1e, 0x0000a68b, 0x0000a68a, - 0x0000abbc, 0x000013ec, 0x000003ac, 0x00000386, - 0x00002c8b, 0x00002c8a, 0x00000159, 0x00000158, - 0x0000015d, 0x0000015c, 0x0001e938, 0x0001e916, - 0x00000584, 0x00000554, 0x000004b3, 0x000004b2, - 0x0000007a, 0x0000005a, 0x0000ab7f, 0x000013af, - 0x00010ce0, 0x00010ca0, 0x00000491, 0x00000490, - 0x00001ed7, 0x00001ed6, 0x0001059d, 0x00010576, - 0x00002cab, 0x00002caa, 0x00001e99, 0x02000094, - 0x00001f77, 0x00001fdb, 0x00010d84, 0x00010d64, - 0x000003b9, 0x00000399, 0x0000a799, 0x0000a798, - 0x00001fe7, 0x030000cc, 0x0000ab99, 0x000013c9, - 0x000001c5, 0x000001c4, 0x000104f4, 0x000104cc, - 0x0000217a, 0x0000216a, 0x0000046f, 0x0000046e, - 0x00000146, 0x00000145, 0x00002cb3, 0x00002cb2, - 0x0000fb17, 0x0200007a, 0x0000ab8d, 0x000013bd, - 0x0001e931, 0x0001e90f, 0x00002c3c, 0x00002c0c, - 0x000104ef, 0x000104c7, 0x0000020f, 0x0000020e, - 0x00002d06, 0x000010a6, 0x0001043b, 0x00010413, - 0x000010db, 0x00001c9b, 0x00000475, 0x00000474, - 0x000004b1, 0x000004b0, 0x000105a3, 0x0001057c, - 0x00010598, 0x00010571, 0x0000ab8e, 0x000013be, - 0x00001f41, 0x00001f49, 0x000104d8, 0x000104b0, - 0x000010d2, 0x00001c92, 0x00001eb9, 0x00001eb8, - 0x00001eb3, 0x00001eb2, 0x00016e6d, 0x00016e4d, - 0x000010f3, 0x00001cb3, 0x00001fa1, 0x02000033, - 0x00002cc1, 0x00002cc0, 0x0000006a, 0x0000004a, - 0x0000051b, 0x0000051a, 0x000001dc, 0x000001db, - 0x00001f78, 0x00001ff8, 0x00010437, 0x0001040f, - 0x00010cc8, 0x00010c88, 0x000000e2, 0x000000c2, - 0x0000a7d1, 0x0000a7d0, 0x00000434, 0x00000414, - 0x00001e27, 0x00001e26, 0x00016e66, 0x00016e46, - 0x000010e2, 0x00001ca2, 0x000003c9, 0x000003a9, - 0x00010cca, 0x00010c8a, 0x000004fd, 0x000004fc, - 0x0000056c, 0x0000053c, 0x000118c6, 0x000118a6, - 0x00000250, 0x00002c6f, 0x00002c48, 0x00002c18, - 0x0000ff55, 0x0000ff35, 0x00001f9f, 0x02000100, - 0x00016e6f, 0x00016e4f, 0x0000a729, 0x0000a728, - 0x00001e31, 0x00001e30, 0x0001e942, 0x0001e920, - 0x00000287, 0x0000a7b1, 0x000104eb, 0x000104c3, - 0x00001c83, 0x00000421, 0x000104dc, 0x000104b4, - 0x00000527, 0x00000526, 0x00000165, 0x00000164, - 0x0000011d, 0x0000011c, 0x00016e6c, 0x00016e4c, - 0x000001fd, 0x000001fc, 0x000105aa, 0x00010583, - 0x00016e75, 0x00016e55, 0x0000014b, 0x0000014a, - 0x00000578, 0x00000548, 0x00010d77, 0x00010d57, - 0x00000566, 0x00000536, 0x000003e1, 0x000003e0, - 0x00002c9d, 0x00002c9c, 0x000004f1, 0x000004f0, - 0x0000ab76, 0x000013a6, 0x00010d73, 0x00010d53, - 0x00010cf0, 0x00010cb0, 0x000105ac, 0x00010585, - 0x000105a5, 0x0001057e, 0x000004af, 0x000004ae, - 0x00001e13, 0x00001e12, 0x000010d3, 0x00001c93, - 0x00010cc4, 0x00010c84, 0x000013fa, 0x000013f2, - 0x0000050b, 0x0000050a, 0x000003bf, 0x0000039f, - 0x00002ca1, 0x00002ca0, 0x000010ee, 0x00001cae, - 0x00002c42, 0x00002c12, 0x000024e9, 0x000024cf, - 0x00016e6a, 0x00016e4a, 0x00001fd6, 0x020000b7, - 0x0000aba4, 0x000013d4, 0x00002c87, 0x00002c86, - 0x00001f7d, 0x00001ffb, 0x00000563, 0x00000533, - 0x000001f0, 0x02000088, 0x00001f44, 0x00001f4c, - 0x00001fa4, 0x0200003c, 0x00001f22, 0x00001f2a, - 0x0001e93e, 0x0001e91c, 0x00000211, 0x00000210, - 0x0000a653, 0x0000a652, 0x00000519, 0x00000518, - 0x000104f5, 0x000104cd, 0x0000006b, 0x0000004b, - 0x0000ab80, 0x000013b0, 0x00001ef3, 0x00001ef2, - 0x000010e8, 0x00001ca8, 0x000105a9, 0x00010582, - 0x0001059f, 0x00010578, 0x00002d1e, 0x000010be, - 0x0000010f, 0x0000010e, 0x00000265, 0x0000a78d, - 0x000000fc, 0x000000dc, 0x000000ff, 0x00000178, - 0x0001e937, 0x0001e915, 0x000105a1, 0x0001057a, - 0x000004ce, 0x000004cd, 0x000001ff, 0x000001fe, - 0x0001e926, 0x0001e904, 0x0000ab87, 0x000013b7, - 0x00001fd7, 0x030000ba, 0x00010ccb, 0x00010c8b, - 0x0000ab90, 0x000013c0, 0x00001f21, 0x00001f29, - 0x00001e96, 0x0200008b, 0x00001f8a, 0x020000d9, - 0x0000ff41, 0x0000ff21, 0x0000a697, 0x0000a696, - 0x0000a7b5, 0x0000a7b4, 0x00001f83, 0x02000009, - 0x00001e2f, 0x00001e2e, 0x00001f34, 0x00001f3c, - 0x00010d72, 0x00010d52, 0x0000050f, 0x0000050e, - 0x0000a787, 0x0000a786, 0x000105b8, 0x00010591, - 0x000118dd, 0x000118bd, 0x0000ab92, 0x000013c2, - 0x00001f14, 0x00001f1c, 0x0000a665, 0x0000a664, - 0x00001ebb, 0x00001eba, 0x00002c93, 0x00002c92, - 0x00001eef, 0x00001eee, 0x00001f45, 0x00001f4d, - 0x0001e923, 0x0001e901, 0x0000a64b, 0x0000a64a, - 0x000105ab, 0x00010584, 0x0000022b, 0x0000022a, - 0x000104e0, 0x000104b8, 0x00002d1d, 0x000010bd, - 0x00000077, 0x00000057, 0x0000abb4, 0x000013e4, - 0x00001c84, 0x00000422, 0x00000586, 0x00000556, - 0x00016e7d, 0x00016e5d, 0x00001f24, 0x00001f2c, - 0x00001e11, 0x00001e10, 0x0000ab7e, 0x000013ae, - 0x00001f91, 0x0200001b, 0x00001fe6, 0x020000c9, - 0x00002c56, 0x00002c26, 0x000003f8, 0x000003f7, - 0x0000017a, 0x00000179, 0x0000ab74, 0x000013a4, - 0x00001fb1, 0x00001fb9, 0x0000015f, 0x0000015e, - 0x00002177, 0x00002167, 0x0000a794, 0x0000a7c4, - 0x000004f9, 0x000004f8, 0x00002cb1, 0x00002cb0, - 0x00000068, 0x00000048, 0x00000280, 0x000001a6, - 0x00000509, 0x00000508, 0x000000f4, 0x000000d4, - 0x00000517, 0x00000516, 0x00000188, 0x00000187, - 0x000118d4, 0x000118b4, 0x0000a7a3, 0x0000a7a2, - 0x00000113, 0x00000112, 0x0000a75f, 0x0000a75e, - 0x00000513, 0x00000512, 0x00000071, 0x00000051, - 0x00000175, 0x00000174, 0x00001e69, 0x00001e68, - 0x000003d6, 0x000003a0, 0x000000e6, 0x000000c6, - 0x000010e0, 0x00001ca0, 0x00002c73, 0x00002c72, - 0x00002d19, 0x000010b9, 0x00010428, 0x00010400, - 0x0000ab9b, 0x000013cb, 0x00000192, 0x00000191, - 0x0000a7a1, 0x0000a7a0, 0x00000587, 0x0200006b, - 0x0000ff4d, 0x0000ff2d, 0x00001eb7, 0x00001eb6, - 0x0000ab71, 0x000013a1, 0x000105ad, 0x00010586, - 0x0000048f, 0x0000048e, 0x00000582, 0x00000552, - 0x000024d6, 0x000024bc, 0x0000026c, 0x0000a7ad, - 0x00002cf3, 0x00002cf2, 0x00001e95, 0x00001e94, - 0x00002d20, 0x000010c0, 0x0001e941, 0x0001e91f, - 0x000010da, 0x00001c9a, 0x000118d2, 0x000118b2, - 0x00001ea5, 0x00001ea4, 0x000001a1, 0x000001a0, - 0x00000201, 0x00000200, 0x00002c32, 0x00002c02, - 0x00000461, 0x00000460, 0x0000fb00, 0x02000054, - 0x00001e55, 0x00001e54, 0x00001f74, 0x00001fca, - 0x00000260, 0x00000193, 0x00000345, 0x00000399, - 0x000013f9, 0x000013f1, 0x00002cec, 0x00002ceb, - 0x0000fb06, 0x02000068, 0x0000aba0, 0x000013d0, - 0x000104ea, 0x000104c2, 0x00002c8d, 0x00002c8c, - 0x00001eb5, 0x00001eb4, 0x0000a689, 0x0000a688, - 0x000001c8, 0x000001c7, 0x00002d1a, 0x000010ba, - 0x00010430, 0x00010408, 0x00000227, 0x00000226, - 0x000003d7, 0x000003cf, 0x00016e7a, 0x00016e5a, - 0x00010cc5, 0x00010c85, 0x00001f80, 0x02000000, - 0x000003fb, 0x000003fa, 0x000010f0, 0x00001cb0, - 0x00010438, 0x00010410, 0x00001fcc, 0x0200011e, - 0x00001c87, 0x00000462, 0x0000018c, 0x0000018b, - 0x00001f9c, 0x020000f7, 0x0001e927, 0x0001e905, - 0x0001044e, 0x00010426, 0x0000043b, 0x0000041b, - 0x00000580, 0x00000550, 0x000105b0, 0x00010589, - 0x000024d7, 0x000024bd, 0x00002cd9, 0x00002cd8, - 0x00001f8d, 0x020000e2, 0x00010442, 0x0001041a, - 0x00000107, 0x00000106, 0x0000a7c1, 0x0000a7c0, - 0x0000abbe, 0x000013ee, 0x00002ca9, 0x00002ca8, - 0x0000012f, 0x0000012e, 0x0000ab91, 0x000013c1, - 0x00002c39, 0x00002c09, 0x0000ff51, 0x0000ff31, - 0x00001ed5, 0x00001ed4, 0x00002c61, 0x00002c60, - 0x00010cd3, 0x00010c93, 0x000003c0, 0x000003a0, - 0x00001f67, 0x00001f6f, 0x0001043f, 0x00010417, - 0x00001ff2, 0x02000130, 0x000000ec, 0x000000cc, - 0x00001ff7, 0x0300013e, 0x00001e45, 0x00001e44, - 0x0000aba9, 0x000013d9, 0x000003df, 0x000003de, - 0x00016e7c, 0x00016e5c, 0x0000ff46, 0x0000ff26, - 0x00001e05, 0x00001e04, 0x00001e2b, 0x00001e2a, - 0x0000ab7b, 0x000013ab, 0x00000254, 0x00000186, - 0x00016e62, 0x00016e42, 0x000004db, 0x000004da, - 0x0000052b, 0x0000052a, 0x00000215, 0x00000214, - 0x000001c6, 0x000001c4, 0x00001f88, 0x020000d3, - 0x000024dc, 0x000024c2, 0x000003bb, 0x0000039b, - 0x00000499, 0x00000498, 0x000024df, 0x000024c5, - 0x00001e0f, 0x00001e0e, 0x00001f25, 0x00001f2d, - 0x00002c50, 0x00002c20, 0x00002c4f, 0x00002c1f, - 0x0000046b, 0x0000046a, 0x000001d6, 0x000001d5, - 0x00001ec1, 0x00001ec0, 0x000118d5, 0x000118b5, - 0x0000010b, 0x0000010a, 0x0000016f, 0x0000016e, - 0x00010d7e, 0x00010d5e, 0x0000045c, 0x0000040c, - 0x000013fc, 0x000013f4, 0x00001c85, 0x00000422, - 0x00001e89, 0x00001e88, 0x00001f97, 0x0200002d, - 0x0001042b, 0x00010403, 0x000000f8, 0x000000d8, - 0x00000564, 0x00000534, 0x000118c4, 0x000118a4, - 0x00002ccd, 0x00002ccc, 0x000105b6, 0x0001058f, - 0x00000251, 0x00002c6d, 0x00002d21, 0x000010c1, - 0x000004d9, 0x000004d8, 0x00001f82, 0x02000006, - 0x00001e3f, 0x00001e3e, 0x00000135, 0x00000134, - 0x00002c34, 0x00002c04, 0x0000a769, 0x0000a768, - 0x000000fa, 0x000000da, 0x0000ab88, 0x000013b8, - 0x0000021b, 0x0000021a, 0x00002d2d, 0x000010cd, - 0x00001f81, 0x02000003, 0x000010df, 0x00001c9f, - 0x00000240, 0x00002c7f, 0x00002c5e, 0x00002c2e, - 0x00000431, 0x00000411, 0x000000ef, 0x000000cf, - 0x00002d0b, 0x000010ab, 0x00000288, 0x000001ae, - 0x00000256, 0x00000189, 0x00016e64, 0x00016e44, - 0x000001d8, 0x000001d7, 0x00002cb5, 0x00002cb4, - 0x0000012d, 0x0000012c, 0x00000257, 0x0000018a, - 0x00001e97, 0x0200008e, 0x0001e943, 0x0001e921, - 0x000104e1, 0x000104b9, 0x000105ae, 0x00010587, - 0x00016e65, 0x00016e45, 0x00002ca7, 0x00002ca6, - 0x0000abaf, 0x000013df, 0x000004a3, 0x000004a2, - 0x000000f2, 0x000000d2, 0x00001fa0, 0x02000030, - 0x00001d7d, 0x00002c63, 0x00000574, 0x00000544, - 0x00000169, 0x00000168, 0x00016e6b, 0x00016e4b, - 0x000010ec, 0x00001cac, 0x00010cc9, 0x00010c89, - 0x0000026a, 0x0000a7ae, 0x00001e77, 0x00001e76, - 0x000001df, 0x000001de, 0x00000117, 0x00000116, - 0x000024d8, 0x000024be, 0x00000577, 0x00000547, - 0x0000049f, 0x0000049e, 0x000001b0, 0x000001af, - 0x00000115, 0x00000114, 0x00001f9b, 0x020000f4, - 0x00002c52, 0x00002c22, 0x000003b8, 0x00000398, - 0x00002c5a, 0x00002c2a, 0x00010ccf, 0x00010c8f, - 0x000000e9, 0x000000c9, 0x00001e39, 0x00001e38, - 0x0000ab70, 0x000013a0, 0x00001ed3, 0x00001ed2, - 0x00002d25, 0x000010c5, 0x00001e3b, 0x00001e3a, - 0x00002ca3, 0x00002ca2, 0x00002d27, 0x000010c7, - 0x000000f3, 0x000000d3, 0x00000373, 0x00000372, - 0x0000ff57, 0x0000ff37, 0x00000449, 0x00000429, - 0x00010597, 0x00010570, 0x0000a68d, 0x0000a68c, - 0x0000abb7, 0x000013e7, 0x00001f60, 0x00001f68, - 0x00000289, 0x00000244, 0x000004a9, 0x000004a8, - 0x000003c7, 0x000003a7, 0x00001e1d, 0x00001e1c, - 0x00001ea1, 0x00001ea0, 0x00000167, 0x00000166, - 0x0000025b, 0x00000190, 0x000004e9, 0x000004e8, - 0x0000a751, 0x0000a750, 0x00010cf2, 0x00010cb2, - 0x0000006f, 0x0000004f, 0x0000aba8, 0x000013d8, - 0x000104ec, 0x000104c4, 0x00000125, 0x00000124, - 0x0000a797, 0x0000a796, 0x0000043f, 0x0000041f, - 0x00000511, 0x00000510, 0x00002d0d, 0x000010ad, - 0x0001043e, 0x00010416, 0x0000aba6, 0x000013d6, - 0x000003be, 0x0000039e, 0x000004f3, 0x000004f2, - 0x00001e73, 0x00001e72, 0x00002cd3, 0x00002cd2, - 0x00001fd0, 0x00001fd8, 0x00001edf, 0x00001ede, - 0x000118d3, 0x000118b3, 0x000024d2, 0x000024b8, - 0x0000ff45, 0x0000ff25, 0x00002d14, 0x000010b4, - 0x00000064, 0x00000044, 0x000010e7, 0x00001ca7, - 0x00001fb3, 0x02000048, 0x00000467, 0x00000466, - 0x0000ab8a, 0x000013ba, 0x00001ff4, 0x02000133, - 0x000118cc, 0x000118ac, 0x00001e81, 0x00001e80, - 0x000001d0, 0x000001cf, 0x000001d4, 0x000001d3, - 0x00016e71, 0x00016e51, 0x00000432, 0x00000412, - 0x000003ca, 0x000003aa, 0x00010ceb, 0x00010cab, - 0x00001f40, 0x00001f48, 0x0000023c, 0x0000023b, - 0x0000a669, 0x0000a668, 0x00002c3a, 0x00002c0a, - 0x000105b1, 0x0001058a, 0x00000562, 0x00000532, - 0x00001f30, 0x00001f38, 0x00010434, 0x0001040c, - 0x000003d1, 0x00000398, 0x0000a743, 0x0000a742, - 0x0000a7f6, 0x0000a7f5, 0x0000a72b, 0x0000a72a, - 0x000000e0, 0x000000c0, 0x00001f07, 0x00001f0f, - 0x0001059c, 0x00010575, 0x00010cc2, 0x00010c82, - 0x0000a65f, 0x0000a65e, 0x00000581, 0x00000551, - 0x00001eeb, 0x00001eea, 0x00000069, 0x00000049, - 0x0001e928, 0x0001e906, 0x00001c82, 0x0000041e, - 0x00010d71, 0x00010d51, 0x0000a765, 0x0000a764, - 0x000024d1, 0x000024b7, 0x000118d7, 0x000118b7, - 0x00010d7f, 0x00010d5f, 0x000003f3, 0x0000037f, - 0x00000119, 0x00000118, 0x00002171, 0x00002161, - 0x00001fe0, 0x00001fe8, 0x00001f98, 0x020000eb, - 0x00002caf, 0x00002cae, 0x000001a8, 0x000001a7, - 0x000024e8, 0x000024ce, 0x0001e940, 0x0001e91e, - 0x0000022d, 0x0000022c, 0x00001fac, 0x0200010f, - 0x00001fae, 0x02000115, 0x00001f66, 0x00001f6e, - 0x00002c4c, 0x00002c1c, 0x0000a667, 0x0000a666, - 0x0000a75b, 0x0000a75a, 0x0000056e, 0x0000053e, - 0x00000231, 0x00000230, 0x000001f9, 0x000001f8, - 0x00000442, 0x00000422, 0x00000247, 0x00000246, - 0x00002c37, 0x00002c07, 0x000004e5, 0x000004e4, - 0x00002c33, 0x00002c03, 0x00000129, 0x00000128, - 0x00000079, 0x00000059, 0x00001f79, 0x00001ff9, - 0x00001edd, 0x00001edc, 0x00002172, 0x00002162, - 0x00010ce3, 0x00010ca3, 0x0000abb0, 0x000013e0, - 0x00002c31, 0x00002c01, 0x000010fd, 0x00001cbd, - 0x00001fe3, 0x030000c2, 0x00000481, 0x00000480, - 0x0000ff4a, 0x0000ff2a, 0x00010d76, 0x00010d56, - 0x00002c5d, 0x00002c2d, 0x000010e6, 0x00001ca6, - 0x00001f93, 0x02000021, 0x000004b5, 0x000004b4, - 0x00002179, 0x00002169, 0x00001fe4, 0x020000c6, - 0x00001fb6, 0x020000a9, 0x00016e7f, 0x00016e5f, - 0x00000144, 0x00000143, 0x00000223, 0x00000222, - 0x00000501, 0x00000500, 0x0000045f, 0x0000040f, - 0x000104f7, 0x000104cf, 0x00001ed9, 0x00001ed8, - 0x000118d6, 0x000118b6, 0x000118c9, 0x000118a9, - 0x00002d23, 0x000010c3, 0x0000044c, 0x0000042c, - 0x00000123, 0x00000122, 0x0000022f, 0x0000022e, - 0x0000029e, 0x0000a7b0, 0x00001f27, 0x00001f2f, - 0x00002c4b, 0x00002c1b, 0x00002c46, 0x00002c16, - 0x0000ff49, 0x0000ff29, 0x000104de, 0x000104b6, - 0x00002d1b, 0x000010bb, 0x0001042e, 0x00010406, - 0x00001f31, 0x00001f39, 0x000003dd, 0x000003dc, - 0x000004b7, 0x000004b6, 0x0000fb04, 0x03000061, - 0x0000045e, 0x0000040e, 0x00001e15, 0x00001e14, - 0x000010e3, 0x00001ca3, 0x00001e03, 0x00001e02, - 0x000001bf, 0x000001f7, 0x00000435, 0x00000415, - 0x0000ab7a, 0x000013aa, 0x00000456, 0x00000406, - 0x00010d85, 0x00010d65, 0x00001f03, 0x00001f0b, - 0x000104f8, 0x000104d0, 0x00000507, 0x00000506, - 0x000105a8, 0x00010581, 0x000024dd, 0x000024c3, - 0x00001ea7, 0x00001ea6, 0x00001f75, 0x00001fcb, - 0x00010441, 0x00010419, 0x00000371, 0x00000370, - 0x00001f50, 0x0200009a, 0x000004c2, 0x000004c1, - 0x000003eb, 0x000003ea, 0x000118cf, 0x000118af, - 0x00000292, 0x000001b7, 0x000003d0, 0x00000392, - 0x00000219, 0x00000218, 0x00000452, 0x00000402, - 0x00002c3b, 0x00002c0b, 0x00000157, 0x00000156, - 0x00000074, 0x00000054, 0x00001f61, 0x00001f69, - 0x0000fb14, 0x02000071, 0x00016e73, 0x00016e53, - 0x000001b4, 0x000001b3, 0x000004ff, 0x000004fe, - 0x00001e49, 0x00001e48, 0x0001e936, 0x0001e914, - 0x000003d9, 0x000003d8, 0x000104f6, 0x000104ce, - 0x0000a73f, 0x0000a73e, 0x000024d0, 0x000024b6, - 0x00001ebf, 0x00001ebe, 0x000010e5, 0x00001ca5, - 0x00010cc0, 0x00010c80, 0x00000459, 0x00000409, - 0x00010ccc, 0x00010c8c, 0x0000a727, 0x0000a726, - 0x00000568, 0x00000538, 0x0000abb5, 0x000013e5, - 0x00002d16, 0x000010b6, 0x00010d80, 0x00010d60, - 0x000003b3, 0x00000393, 0x00000515, 0x00000514, - 0x000024d9, 0x000024bf, 0x00001eaf, 0x00001eae, - 0x00001f72, 0x00001fc8, 0x000010f6, 0x00001cb6, - 0x0001e93b, 0x0001e919, 0x0000a723, 0x0000a722, - 0x0000a7b9, 0x0000a7b8, 0x00001ec3, 0x00001ec2 + 0x0000007a, 0x0000005a, 0x000105a0, 0x00010579, + 0x00002d0e, 0x000010ae, 0x000003d5, 0x000003a6, + 0x0000a7b9, 0x0000a7b8, 0x00000373, 0x00000372, + 0x00001f92, 0x0200001e, 0x0000056f, 0x0000053f, + 0x00001e67, 0x00001e66, 0x00002d09, 0x000010a9, + 0x0000ab75, 0x000013a5, 0x0000217b, 0x0000216b, + 0x00010d7b, 0x00010d5b, 0x000003e9, 0x000003e8, + 0x000004e7, 0x000004e6, 0x00002c81, 0x00002c80, + 0x00001ee1, 0x00001ee0, 0x000000ec, 0x000000cc, + 0x00000436, 0x00000416, 0x00002c97, 0x00002c96, + 0x00002cec, 0x00002ceb, 0x0000045d, 0x0000040d, + 0x0001042e, 0x00010406, 0x00001eb9, 0x00001eb8, + 0x0000214e, 0x00002132, 0x00002cc5, 0x00002cc4, + 0x00016e6a, 0x00016e4a, 0x00001e43, 0x00001e42, + 0x00001f7c, 0x00001ffa, 0x0000015f, 0x0000015e, + 0x00010435, 0x0001040d, 0x0001e931, 0x0001e90f, + 0x00010cd6, 0x00010c96, 0x000105a3, 0x0001057c, + 0x000001f9, 0x000001f8, 0x00002d04, 0x000010a4, + 0x00000259, 0x0000018f, 0x00002c43, 0x00002c13, + 0x00001f87, 0x02000015, 0x00001f45, 0x00001f4d, + 0x0000a794, 0x0000a7c4, 0x00000377, 0x00000376, + 0x00001f36, 0x00001f3e, 0x0001042d, 0x00010405, + 0x000105a9, 0x00010582, 0x00002cb9, 0x00002cb8, + 0x000118c7, 0x000118a7, 0x00001f31, 0x00001f39, + 0x0000ab8c, 0x000013bc, 0x00002d22, 0x000010c2, + 0x00002c42, 0x00002c12, 0x00002cc9, 0x00002cc8, + 0x00001ea9, 0x00001ea8, 0x00002d2d, 0x000010cd, + 0x00001f62, 0x00001f6a, 0x000105b4, 0x0001058d, + 0x00001eed, 0x00001eec, 0x0001e922, 0x0001e900, + 0x000003c0, 0x000003a0, 0x00001fc3, 0x0200004b, + 0x000105bb, 0x00010594, 0x0000a723, 0x0000a722, + 0x00001fab, 0x0200010c, 0x00000578, 0x00000548, + 0x00001f75, 0x00001fcb, 0x0001e938, 0x0001e916, + 0x00001fb3, 0x02000048, 0x00001e97, 0x0200008e, + 0x000010ea, 0x00001caa, 0x000010ff, 0x00001cbf, + 0x0000019e, 0x00000220, 0x000004ad, 0x000004ac, + 0x00000211, 0x00000210, 0x00002c47, 0x00002c17, + 0x00001e0f, 0x00001e0e, 0x00010ccd, 0x00010c8d, + 0x0000abbe, 0x000013ee, 0x000000e6, 0x000000c6, + 0x00000253, 0x00000181, 0x0000a733, 0x0000a732, + 0x00016e6f, 0x00016e4f, 0x000118d7, 0x000118b7, + 0x00000167, 0x00000166, 0x000010d9, 0x00001c99, + 0x0000a781, 0x0000a780, 0x00000254, 0x00000186, + 0x00000477, 0x00000476, 0x0000a683, 0x0000a682, + 0x000013f9, 0x000013f1, 0x00000171, 0x00000170, + 0x0000019b, 0x0000a7dc, 0x00001fa9, 0x02000106, + 0x00001f54, 0x030000a1, 0x000003eb, 0x000003ea, + 0x000004eb, 0x000004ea, 0x00002c5e, 0x00002c2e, + 0x00002c3f, 0x00002c0f, 0x000010d2, 0x00001c92, + 0x00001f63, 0x00001f6b, 0x00010d7a, 0x00010d5a, + 0x00016ed1, 0x00016eb6, 0x00016e6e, 0x00016e4e, + 0x00000515, 0x00000514, 0x00001e59, 0x00001e58, + 0x0000a669, 0x0000a668, 0x00002cee, 0x00002ced, + 0x00000169, 0x00000168, 0x0000a7c3, 0x0000a7c2, + 0x00016ebf, 0x00016ea4, 0x000004d5, 0x000004d4, + 0x00010444, 0x0001041c, 0x00001f33, 0x00001f3b, + 0x0000ab76, 0x000013a6, 0x0000a7d1, 0x0000a7d0, + 0x00010d7c, 0x00010d5c, 0x000000ea, 0x000000ca, + 0x00001f14, 0x00001f1c, 0x0000aba9, 0x000013d9, + 0x0000029e, 0x0000a7b0, 0x00001f65, 0x00001f6d, + 0x00002c30, 0x00002c00, 0x0000043a, 0x0000041a, + 0x000105a4, 0x0001057d, 0x00000513, 0x00000512, + 0x0000010d, 0x0000010c, 0x00002cbb, 0x00002cba, + 0x000118df, 0x000118bf, 0x00010cc8, 0x00010c88, + 0x000010e4, 0x00001ca4, 0x00010448, 0x00010420, + 0x000004b3, 0x000004b2, 0x0000057c, 0x0000054c, + 0x0000006c, 0x0000004c, 0x000010d4, 0x00001c94, + 0x00000289, 0x00000244, 0x00001fe2, 0x030000be, + 0x00002178, 0x00002168, 0x0000fb00, 0x02000054, + 0x000003b8, 0x00000398, 0x00001e87, 0x00001e86, + 0x000010e1, 0x00001ca1, 0x0000a729, 0x0000a728, + 0x00001f83, 0x02000009, 0x0000a7a3, 0x0000a7a2, + 0x00016ecc, 0x00016eb1, 0x0000049d, 0x0000049c, + 0x00000113, 0x00000112, 0x00001f7b, 0x00001feb, + 0x00002d21, 0x000010c1, 0x0000a79d, 0x0000a79c, + 0x00002c48, 0x00002c18, 0x0000045c, 0x0000040c, + 0x000105b3, 0x0001058c, 0x00002d0d, 0x000010ad, + 0x00001e13, 0x00001e12, 0x0000051b, 0x0000051a, + 0x0000ab9d, 0x000013cd, 0x0000ab92, 0x000013c2, + 0x0000057a, 0x0000054a, 0x00000101, 0x00000100, + 0x00001e01, 0x00001e00, 0x000010e2, 0x00001ca2, + 0x00001ecd, 0x00001ecc, 0x00001f89, 0x020000d6, + 0x00000564, 0x00000534, 0x00010d77, 0x00010d57, + 0x00016ebc, 0x00016ea1, 0x00010d72, 0x00010d52, + 0x00001e75, 0x00001e74, 0x00001f8a, 0x020000d9, + 0x00001e77, 0x00001e76, 0x000003d6, 0x000003a0, + 0x0001e932, 0x0001e910, 0x00001fe6, 0x020000c9, + 0x0000006b, 0x0000004b, 0x0001e940, 0x0001e91e, + 0x00001fb4, 0x02000127, 0x0000ab73, 0x000013a3, + 0x00001f71, 0x00001fbb, 0x0000a75d, 0x0000a75c, + 0x000104f0, 0x000104c8, 0x00016ebb, 0x00016ea0, + 0x000001f5, 0x000001f4, 0x00001f84, 0x0200000c, + 0x000003c9, 0x000003a9, 0x000001d8, 0x000001d7, + 0x00010cec, 0x00010cac, 0x0000217d, 0x0000216d, + 0x00016e7b, 0x00016e5b, 0x00000456, 0x00000406, + 0x00001f8c, 0x020000df, 0x000003db, 0x000003da, + 0x00010ce4, 0x00010ca4, 0x00002d10, 0x000010b0, + 0x00002c91, 0x00002c90, 0x000003ce, 0x0000038f, + 0x00002c66, 0x0000023e, 0x000001f2, 0x000001f1, + 0x00001e6f, 0x00001e6e, 0x00001f41, 0x00001f49, + 0x0000a75f, 0x0000a75e, 0x00000250, 0x00002c6f, + 0x00000443, 0x00000423, 0x000003cd, 0x0000038e, + 0x0001e92f, 0x0001e90d, 0x00000439, 0x00000419, + 0x000000df, 0x02000051, 0x000010d3, 0x00001c93, + 0x0000a7cf, 0x0000a7ce, 0x00000282, 0x0000a7c5, + 0x000004b5, 0x000004b4, 0x00000260, 0x00000193, + 0x00001eb1, 0x00001eb0, 0x0000ab77, 0x000013a7, + 0x00001ef7, 0x00001ef6, 0x0000a743, 0x0000a742, + 0x000003ca, 0x000003aa, 0x0000ab83, 0x000013b3, + 0x0000052b, 0x0000052a, 0x00001fcc, 0x0200011e, + 0x00001f25, 0x00001f2d, 0x0000a72b, 0x0000a72a, + 0x00001d79, 0x0000a77d, 0x00002c58, 0x00002c28, + 0x00016ec6, 0x00016eab, 0x0001e93d, 0x0001e91b, + 0x000003c1, 0x000003a1, 0x00001e3f, 0x00001e3e, + 0x00001e98, 0x02000091, 0x0000a659, 0x0000a658, + 0x00002ca1, 0x00002ca0, 0x000003b6, 0x00000396, + 0x0001042f, 0x00010407, 0x00000511, 0x00000510, + 0x00002d13, 0x000010b3, 0x00000566, 0x00000536, + 0x000118cc, 0x000118ac, 0x00016ec5, 0x00016eaa, + 0x0000ff57, 0x0000ff37, 0x000004c4, 0x000004c3, + 0x0001e93c, 0x0001e91a, 0x00000137, 0x00000136, + 0x0000020b, 0x0000020a, 0x00001f81, 0x02000003, + 0x0000a791, 0x0000a790, 0x00000266, 0x0000a7aa, + 0x00010d73, 0x00010d53, 0x0001059a, 0x00010573, + 0x00000062, 0x00000042, 0x0000017e, 0x0000017d, + 0x00001efb, 0x00001efa, 0x000010dd, 0x00001c9d, + 0x00016e63, 0x00016e43, 0x000003bf, 0x0000039f, + 0x0000006f, 0x0000004f, 0x00001f93, 0x02000021, + 0x0000056a, 0x0000053a, 0x00001e73, 0x00001e72, + 0x0000021d, 0x0000021c, 0x00002172, 0x00002162, + 0x00000371, 0x00000370, 0x00000272, 0x0000019d, + 0x000000eb, 0x000000cb, 0x000003e3, 0x000003e2, + 0x00000068, 0x00000048, 0x000010fa, 0x00001cba, + 0x00001faa, 0x02000109, 0x0000aba4, 0x000013d4, + 0x0001043f, 0x00010417, 0x000004d9, 0x000004d8, + 0x00001fe1, 0x00001fe9, 0x00001edb, 0x00001eda, + 0x000010d5, 0x00001c95, 0x000010dc, 0x00001c9c, + 0x00000251, 0x00002c6d, 0x0000ff4d, 0x0000ff2d, + 0x0000026b, 0x00002c62, 0x00000268, 0x00000197, + 0x00001e53, 0x00001e52, 0x0000a655, 0x0000a654, + 0x0000a759, 0x0000a758, 0x0000023c, 0x0000023b, + 0x00000587, 0x0200006b, 0x0000ab8f, 0x000013bf, + 0x0001042c, 0x00010404, 0x00002c8f, 0x00002c8e, + 0x00000257, 0x0000018a, 0x00002c44, 0x00002c14, + 0x000001a1, 0x000001a0, 0x000003bb, 0x0000039b, + 0x000004ce, 0x000004cd, 0x00000517, 0x00000516, + 0x00002c41, 0x00002c11, 0x00002cc1, 0x00002cc0, + 0x00002c37, 0x00002c07, 0x0000a747, 0x0000a746, + 0x0000ff45, 0x0000ff25, 0x00000431, 0x00000411, + 0x0000052f, 0x0000052e, 0x00016e79, 0x00016e59, + 0x00002cb5, 0x00002cb4, 0x00001f20, 0x00001f28, + 0x00010cc2, 0x00010c82, 0x0000a7bb, 0x0000a7ba, + 0x0001044c, 0x00010424, 0x000004a5, 0x000004a4, + 0x00000064, 0x00000044, 0x00001fd7, 0x030000ba, + 0x00001f9f, 0x02000100, 0x00001f21, 0x00001f29, + 0x0000ab79, 0x000013a9, 0x00001e8b, 0x00001e8a, + 0x000104e1, 0x000104b9, 0x000000e2, 0x000000c2, + 0x0000011f, 0x0000011e, 0x0000ab8d, 0x000013bd, + 0x00002c5c, 0x00002c2c, 0x00000580, 0x00000550, + 0x0001043e, 0x00010416, 0x0000050b, 0x0000050a, + 0x0001e936, 0x0001e914, 0x00002c8b, 0x00002c8a, + 0x000001e3, 0x000001e2, 0x00001f8d, 0x020000e2, + 0x000001e9, 0x000001e8, 0x00016ec9, 0x00016eae, + 0x0001043c, 0x00010414, 0x00000579, 0x00000549, + 0x000000fa, 0x000000da, 0x00002d01, 0x000010a1, + 0x00000229, 0x00000228, 0x00001f79, 0x00001ff9, + 0x0000014d, 0x0000014c, 0x00010439, 0x00010411, + 0x00000073, 0x00000053, 0x00010ccf, 0x00010c8f, + 0x00002c3d, 0x00002c0d, 0x000010df, 0x00001c9f, + 0x000118d3, 0x000118b3, 0x0000a7a5, 0x0000a7a4, + 0x0000037b, 0x000003fd, 0x0001043b, 0x00010413, + 0x000000f9, 0x000000d9, 0x0000a65b, 0x0000a65a, + 0x0000016f, 0x0000016e, 0x0000a76b, 0x0000a76a, + 0x00010cde, 0x00010c9e, 0x00016ec1, 0x00016ea6, + 0x00010ce9, 0x00010ca9, 0x000004ef, 0x000004ee, + 0x0001e943, 0x0001e921, 0x00001edf, 0x00001ede, + 0x0000019a, 0x0000023d, 0x00001f66, 0x00001f6e, + 0x00002c40, 0x00002c10, 0x0000a7ca, 0x0000a7c9, + 0x00000453, 0x00000403, 0x000104e5, 0x000104bd, + 0x00001e57, 0x00001e56, 0x00001f53, 0x00001f5b, + 0x000118cf, 0x000118af, 0x00010ce8, 0x00010ca8, + 0x0000043e, 0x0000041e, 0x00002176, 0x00002166, + 0x000004d7, 0x000004d6, 0x000001f0, 0x02000088, + 0x00000442, 0x00000422, 0x00010cf2, 0x00010cb2, + 0x00002ce1, 0x00002ce0, 0x0000022f, 0x0000022e, + 0x000004bf, 0x000004be, 0x00001f73, 0x00001fc9, + 0x00002c4b, 0x00002c1b, 0x000001b9, 0x000001b8, + 0x0000a64f, 0x0000a64e, 0x0000a75b, 0x0000a75a, + 0x00001f9c, 0x020000f7, 0x00000433, 0x00000413, + 0x000000e5, 0x000000c5, 0x00010436, 0x0001040e, + 0x0000ab90, 0x000013c0, 0x0001e924, 0x0001e902, + 0x00010cc6, 0x00010c86, 0x000024d4, 0x000024ba, + 0x00010446, 0x0001041e, 0x000004a7, 0x000004a6, + 0x00000583, 0x00000553, 0x00001ea1, 0x00001ea0, + 0x000000f4, 0x000000d4, 0x00010cf1, 0x00010cb1, + 0x00002c76, 0x00002c75, 0x000010eb, 0x00001cab, + 0x0000ab81, 0x000013b1, 0x0000051d, 0x0000051c, + 0x0001e942, 0x0001e920, 0x0000fb17, 0x0200007a, + 0x0000a725, 0x0000a724, 0x00001faf, 0x02000118, + 0x0000fb05, 0x02000065, 0x00010ce5, 0x00010ca5, + 0x00000499, 0x00000498, 0x00001f80, 0x02000000, + 0x00000256, 0x00000189, 0x00001fad, 0x02000112, + 0x00000261, 0x0000a7ac, 0x00001f9e, 0x020000fd, + 0x0001059b, 0x00010574, 0x000118cd, 0x000118ad, + 0x00000501, 0x00000500, 0x00002d03, 0x000010a3, + 0x00002d18, 0x000010b8, 0x00000576, 0x00000546, + 0x00001c83, 0x00000421, 0x000000ff, 0x00000178, + 0x000004fb, 0x000004fa, 0x00000434, 0x00000414, + 0x00002ccf, 0x00002cce, 0x0000aba7, 0x000013d7, + 0x0000a68b, 0x0000a68a, 0x0000217a, 0x0000216a, + 0x00002c51, 0x00002c21, 0x00001f77, 0x00001fdb, + 0x00016e73, 0x00016e53, 0x00001ecf, 0x00001ece, + 0x000003d9, 0x000003d8, 0x0000abbf, 0x000013ef, + 0x0000050f, 0x0000050e, 0x0000ab74, 0x000013a4, + 0x000010e0, 0x00001ca0, 0x000004e5, 0x000004e4, + 0x0000015b, 0x0000015a, 0x00001ecb, 0x00001eca, + 0x0000ab71, 0x000013a1, 0x00001f12, 0x00001f1a, + 0x000003ae, 0x00000389, 0x00001ebb, 0x00001eba, + 0x00000461, 0x00000460, 0x0000013a, 0x00000139, + 0x00001e5b, 0x00001e5a, 0x00001fbc, 0x0200011b, + 0x0000a761, 0x0000a760, 0x00001fa4, 0x0200003c, + 0x0000046f, 0x0000046e, 0x00002c5b, 0x00002c2b, + 0x000001fb, 0x000001fa, 0x00000275, 0x0000019f, + 0x00001e85, 0x00001e84, 0x00016e7f, 0x00016e5f, + 0x0000a7d5, 0x0000a7d4, 0x000010fd, 0x00001cbd, + 0x000024e5, 0x000024cb, 0x00001f30, 0x00001f38, + 0x00016e7d, 0x00016e5d, 0x00001e45, 0x00001e44, + 0x0000ff56, 0x0000ff36, 0x0000abb1, 0x000013e1, + 0x00002c54, 0x00002c24, 0x00001f04, 0x00001f0c, + 0x000001e1, 0x000001e0, 0x00002d14, 0x000010b4, + 0x00002cb1, 0x00002cb0, 0x0000abbb, 0x000013eb, + 0x00010cca, 0x00010c8a, 0x00000148, 0x00000147, + 0x0000fb06, 0x02000068, 0x00016ebd, 0x00016ea2, + 0x00002cab, 0x00002caa, 0x00001e83, 0x00001e82, + 0x000001d2, 0x000001d1, 0x0000217c, 0x0000216c, + 0x0000a7b7, 0x0000a7b6, 0x0000057e, 0x0000054e, + 0x000013fc, 0x000013f4, 0x0000043d, 0x0000041d, + 0x00001e23, 0x00001e22, 0x0000043b, 0x0000041b, + 0x000105af, 0x00010588, 0x00001fa1, 0x02000033, + 0x0000056c, 0x0000053c, 0x000104e9, 0x000104c1, + 0x00000155, 0x00000154, 0x0000022d, 0x0000022c, + 0x00000451, 0x00000401, 0x000104f1, 0x000104c9, + 0x00001fd6, 0x020000b7, 0x00010449, 0x00010421, + 0x0000048b, 0x0000048a, 0x00002c9d, 0x00002c9c, + 0x00000519, 0x00000518, 0x00001e0d, 0x00001e0c, + 0x00000265, 0x0000a78d, 0x0000045e, 0x0000040e, + 0x000104eb, 0x000104c3, 0x0001e937, 0x0001e915, + 0x000004fd, 0x000004fc, 0x0001e93a, 0x0001e918, + 0x000118c5, 0x000118a5, 0x00002c38, 0x00002c08, + 0x0000a68d, 0x0000a68c, 0x0000fb03, 0x0300005d, + 0x0000037d, 0x000003ff, 0x00000473, 0x00000472, + 0x00000573, 0x00000543, 0x00001e63, 0x00001e62, + 0x00000582, 0x00000552, 0x00000078, 0x00000058, + 0x000010e9, 0x00001ca9, 0x0000ab86, 0x000013b6, + 0x000118c0, 0x000118a0, 0x00000061, 0x00000041, + 0x000003d1, 0x00000398, 0x00001f50, 0x0200009a, + 0x0000ab7b, 0x000013ab, 0x00000572, 0x00000542, + 0x000001fd, 0x000001fc, 0x0000ab88, 0x000013b8, + 0x0000a641, 0x0000a640, 0x000003ac, 0x00000386, + 0x00001f24, 0x00001f2c, 0x00000173, 0x00000172, + 0x0000a769, 0x0000a768, 0x00001f10, 0x00001f18, + 0x000104ef, 0x000104c7, 0x00002c55, 0x00002c25, + 0x000004d1, 0x000004d0, 0x0000017f, 0x00000053, + 0x000004cf, 0x000004c0, 0x0000044c, 0x0000042c, + 0x0000a7d9, 0x0000a7d8, 0x000003ef, 0x000003ee, + 0x00000217, 0x00000216, 0x00002c56, 0x00002c26, + 0x00002c4d, 0x00002c1d, 0x000001c6, 0x000001c4, + 0x00001f43, 0x00001f4b, 0x00002c6c, 0x00002c6b, + 0x00002c61, 0x00002c60, 0x000003c6, 0x000003a6, + 0x000003c2, 0x000003a3, 0x00001e1d, 0x00001e1c, + 0x00000142, 0x00000141, 0x00000280, 0x000001a6, + 0x0000013e, 0x0000013d, 0x0001e926, 0x0001e904, + 0x000003b9, 0x00000399, 0x000000e0, 0x000000c0, + 0x00001f57, 0x00001f5f, 0x00010d79, 0x00010d59, + 0x000001bd, 0x000001bc, 0x00001c81, 0x00000414, + 0x0000044a, 0x0000042a, 0x00002d16, 0x000010b6, + 0x00010597, 0x00010570, 0x00000521, 0x00000520, + 0x00001e25, 0x00001e24, 0x00001f23, 0x00001f2b, + 0x000024e6, 0x000024cc, 0x00001eb7, 0x00001eb6, + 0x00010ccb, 0x00010c8b, 0x00010430, 0x00010408, + 0x000118cb, 0x000118ab, 0x00002cbf, 0x00002cbe, + 0x00001e9b, 0x00001e60, 0x00000199, 0x00000198, + 0x0000a7a1, 0x0000a7a0, 0x00000227, 0x00000226, + 0x0000ab78, 0x000013a8, 0x00002c3e, 0x00002c0e, + 0x000001cc, 0x000001ca, 0x00001e37, 0x00001e36, + 0x000010e5, 0x00001ca5, 0x00000203, 0x00000202, + 0x0000ff48, 0x0000ff28, 0x0000044f, 0x0000042f, + 0x0000ff55, 0x0000ff35, 0x00001e03, 0x00001e02, + 0x00002c89, 0x00002c88, 0x00001e81, 0x00001e80, + 0x000000f6, 0x000000d6, 0x00010d70, 0x00010d50, + 0x00001f86, 0x02000012, 0x00000479, 0x00000478, + 0x00000577, 0x00000547, 0x00000079, 0x00000059, + 0x00000175, 0x00000174, 0x00001ff4, 0x02000133, + 0x000024e7, 0x000024cd, 0x0000028b, 0x000001b2, + 0x000003b5, 0x00000395, 0x000004ed, 0x000004ec, + 0x00010440, 0x00010418, 0x00002173, 0x00002163, + 0x00001c88, 0x0000a64a, 0x000001df, 0x000001de, + 0x000001cb, 0x000001ca, 0x00016ed0, 0x00016eb5, + 0x00000469, 0x00000468, 0x000000ef, 0x000000cf, + 0x00001f88, 0x020000d3, 0x0000018c, 0x0000018b, + 0x00000077, 0x00000057, 0x00010cf0, 0x00010cb0, + 0x000003ba, 0x0000039a, 0x0000025b, 0x00000190, + 0x000004dd, 0x000004dc, 0x00002cd3, 0x00002cd2, + 0x00001ef3, 0x00001ef2, 0x000010d7, 0x00001c97, + 0x000000b5, 0x0000039c, 0x00001fb2, 0x02000124, + 0x00001fc6, 0x020000ac, 0x0001e933, 0x0001e911, + 0x00001f76, 0x00001fda, 0x00001e49, 0x00001e48, + 0x00001fb7, 0x03000136, 0x0000a751, 0x0000a750, + 0x00000105, 0x00000104, 0x000004ca, 0x000004c9, + 0x000010e3, 0x00001ca3, 0x000000e7, 0x000000c7, + 0x00002c85, 0x00002c84, 0x00001ebd, 0x00001ebc, + 0x00001ff2, 0x02000130, 0x000105aa, 0x00010583, + 0x0001042b, 0x00010403, 0x0001043d, 0x00010415, + 0x000003b2, 0x00000392, 0x00001eb5, 0x00001eb4, + 0x00002d1e, 0x000010be, 0x000001d6, 0x000001d5, + 0x00000183, 0x00000182, 0x0000ff47, 0x0000ff27, + 0x0000037c, 0x000003fe, 0x0001e92d, 0x0001e90b, + 0x0000a681, 0x0000a680, 0x0000012f, 0x0000012e, + 0x0000a739, 0x0000a738, 0x00001fae, 0x02000115, + 0x00001ec7, 0x00001ec6, 0x00000213, 0x00000212, + 0x000004af, 0x000004ae, 0x00002cd7, 0x00002cd6, + 0x000105bc, 0x00010595, 0x00001f9b, 0x020000f4, + 0x000000fd, 0x000000dd, 0x00016ecd, 0x00016eb2, + 0x00001fc2, 0x0200012a, 0x000001ef, 0x000001ee, + 0x0000051f, 0x0000051e, 0x00001e15, 0x00001e14, + 0x00000450, 0x00000400, 0x000010f3, 0x00001cb3, + 0x00000107, 0x00000106, 0x000118c3, 0x000118a3, + 0x00000507, 0x00000506, 0x000003c7, 0x000003a7, + 0x00002ccd, 0x00002ccc, 0x00000201, 0x00000200, + 0x0000a697, 0x0000a696, 0x00000240, 0x00002c7f, + 0x0000ff51, 0x0000ff31, 0x0000047b, 0x0000047a, + 0x0000057b, 0x0000054b, 0x000003d7, 0x000003cf, + 0x00001e05, 0x00001e04, 0x00000066, 0x00000046, + 0x00001ff3, 0x0200004e, 0x000105b6, 0x0001058f, + 0x000003b7, 0x00000397, 0x0000006d, 0x0000004d, + 0x00010598, 0x00010571, 0x00016e72, 0x00016e52, + 0x0000ab7d, 0x000013ad, 0x000003f5, 0x00000395, + 0x00002c6a, 0x00002c69, 0x000024e3, 0x000024c9, + 0x00000467, 0x00000466, 0x00000565, 0x00000535, + 0x00001e7d, 0x00001e7c, 0x00000131, 0x00000049, + 0x0000a76d, 0x0000a76c, 0x00010ce3, 0x00010ca3, + 0x0000045b, 0x0000040b, 0x000003ed, 0x000003ec, + 0x000004e1, 0x000004e0, 0x0001e93b, 0x0001e919, + 0x00001f27, 0x00001f2f, 0x00010cea, 0x00010caa, + 0x00010438, 0x00010410, 0x000001a5, 0x000001a4, + 0x0000044d, 0x0000042d, 0x000104ea, 0x000104c2, + 0x00016ec2, 0x00016ea7, 0x00001e5f, 0x00001e5e, + 0x00001f55, 0x00001f5d, 0x00000209, 0x00000208, + 0x00001f52, 0x0300009d, 0x000104d8, 0x000104b0, + 0x0000022b, 0x0000022a, 0x00002c33, 0x00002c03, + 0x00002c87, 0x00002c86, 0x0000020f, 0x0000020e, + 0x00016ec4, 0x00016ea9, 0x0000a643, 0x0000a642, + 0x000001c8, 0x000001c7, 0x00001d8e, 0x0000a7c6, + 0x00001fb6, 0x020000a9, 0x000000f8, 0x000000d8, + 0x00001e47, 0x00001e46, 0x000003ad, 0x00000388, + 0x0000a767, 0x0000a766, 0x0000abbc, 0x000013ec, + 0x00002c52, 0x00002c22, 0x0000052d, 0x0000052c, + 0x00001e2f, 0x00001e2e, 0x00002cbd, 0x00002cbc, + 0x0000abb9, 0x000013e9, 0x00010cce, 0x00010c8e, + 0x000104f3, 0x000104cb, 0x0000ab7f, 0x000013af, + 0x000004a9, 0x000004a8, 0x000001a8, 0x000001a7, + 0x00001ea3, 0x00001ea2, 0x000024e8, 0x000024ce, + 0x0000a7a9, 0x0000a7a8, 0x000001ed, 0x000001ec, + 0x00001e7f, 0x00001e7e, 0x00000441, 0x00000421, + 0x00001f37, 0x00001f3f, 0x00001e17, 0x00001e16, + 0x00016e6d, 0x00016e4d, 0x000105a5, 0x0001057e, + 0x0000ff5a, 0x0000ff3a, 0x000104dd, 0x000104b5, + 0x0000abb8, 0x000013e8, 0x00000497, 0x00000496, + 0x000001c9, 0x000001c7, 0x00001e8d, 0x00001e8c, + 0x00001f07, 0x00001f0f, 0x0000a737, 0x0000a736, + 0x00000180, 0x00000243, 0x00001e96, 0x0200008b, + 0x000024dc, 0x000024c2, 0x0001e93f, 0x0001e91d, + 0x00001e09, 0x00001e08, 0x00001c82, 0x0000041e, + 0x0000ab93, 0x000013c3, 0x0000ff49, 0x0000ff29, + 0x000013f8, 0x000013f0, 0x0000017c, 0x0000017b, + 0x000105a6, 0x0001057f, 0x0000a661, 0x0000a660, + 0x00001e71, 0x00001e70, 0x000003b0, 0x03000084, + 0x000024d3, 0x000024b9, 0x00016e70, 0x00016e50, + 0x00000570, 0x00000540, 0x000000e1, 0x000000c1, + 0x00001e6b, 0x00001e6a, 0x000118ca, 0x000118aa, + 0x0000abb5, 0x000013e5, 0x00001f95, 0x02000027, + 0x00010d76, 0x00010d56, 0x00002c3c, 0x00002c0c, + 0x0000013c, 0x0000013b, 0x000001b4, 0x000001b3, + 0x00001ec5, 0x00001ec4, 0x00010cef, 0x00010caf, + 0x000000fe, 0x000000de, 0x00000233, 0x00000232, + 0x0000ab70, 0x000013a0, 0x00002cc3, 0x00002cc2, + 0x00002c34, 0x00002c04, 0x00001e55, 0x00001e54, + 0x0000a663, 0x0000a662, 0x000024d9, 0x000024bf, + 0x00010ce0, 0x00010ca0, 0x00010cd7, 0x00010c97, + 0x000104f5, 0x000104cd, 0x000004f5, 0x000004f4, + 0x00001fc7, 0x0300013a, 0x00010cdb, 0x00010c9b, + 0x00010cda, 0x00010c9a, 0x0000a7d3, 0x0000a7d2, + 0x000003c5, 0x000003a5, 0x000004bb, 0x000004ba, + 0x00001f9d, 0x020000fa, 0x0000ab53, 0x0000a7b3, + 0x00001e79, 0x00001e78, 0x000003f8, 0x000003f7, + 0x0000a74b, 0x0000a74a, 0x00016ecf, 0x00016eb4, + 0x0000021b, 0x0000021a, 0x00001f26, 0x00001f2e, + 0x00001ebf, 0x00001ebe, 0x00001f98, 0x020000eb, + 0x000118c1, 0x000118a1, 0x00010cc4, 0x00010c84, + 0x000024d8, 0x000024be, 0x00016ece, 0x00016eb3, + 0x000024e1, 0x000024c7, 0x000001b6, 0x000001b5, + 0x000010f9, 0x00001cb9, 0x0000ab8e, 0x000013be, + 0x0000ab7c, 0x000013ac, 0x0001044d, 0x00010425, + 0x00016e62, 0x00016e42, 0x000104e0, 0x000104b8, + 0x00002d20, 0x000010c0, 0x0000fb16, 0x02000077, + 0x00001f97, 0x0200002d, 0x0000a72d, 0x0000a72c, + 0x00000454, 0x00000404, 0x00000437, 0x00000417, + 0x00001f44, 0x00001f4c, 0x000000fc, 0x000000dc, + 0x00002c95, 0x00002c94, 0x000003f1, 0x000003a1, + 0x00001f8b, 0x020000dc, 0x00000444, 0x00000424, + 0x00000292, 0x000001b7, 0x000024e4, 0x000024ca, + 0x00002d12, 0x000010b2, 0x0000a783, 0x0000a782, + 0x00000586, 0x00000556, 0x0000006a, 0x0000004a, + 0x0000ab95, 0x000013c5, 0x0000abb6, 0x000013e6, + 0x00002c4c, 0x00002c1c, 0x000104f7, 0x000104cf, + 0x000000f5, 0x000000d5, 0x000001f3, 0x000001f1, + 0x00001e89, 0x00001e88, 0x00001f05, 0x00001f0d, + 0x00000264, 0x0000a7cb, 0x0000011b, 0x0000011a, + 0x00000475, 0x00000474, 0x00000569, 0x00000539, + 0x00001e6d, 0x00001e6c, 0x000010f1, 0x00001cb1, + 0x0000abb7, 0x000013e7, 0x00001eff, 0x00001efe, + 0x00001f32, 0x00001f3a, 0x0000aba8, 0x000013d8, + 0x00000065, 0x00000045, 0x00000215, 0x00000214, + 0x00001ee3, 0x00001ee2, 0x000001c5, 0x000001c4, + 0x00001f61, 0x00001f69, 0x0000026f, 0x0000019c, + 0x0001e92c, 0x0001e90a, 0x00000584, 0x00000554, + 0x00010442, 0x0001041a, 0x00002d1f, 0x000010bf, + 0x00000448, 0x00000428, 0x000024d1, 0x000024b7, + 0x000104e8, 0x000104c0, 0x0000044b, 0x0000042b, + 0x0000a65f, 0x0000a65e, 0x00010d7f, 0x00010d5f, + 0x00002cd1, 0x00002cd0, 0x00001ec9, 0x00001ec8, + 0x00010cdc, 0x00010c9c, 0x0000a7d7, 0x0000a7d6, + 0x00010d7d, 0x00010d5d, 0x000024df, 0x000024c5, + 0x00001f90, 0x02000018, 0x00000149, 0x0200007d, + 0x00001e41, 0x00001e40, 0x0000a651, 0x0000a650, + 0x0000a74f, 0x0000a74e, 0x0000ff43, 0x0000ff23, + 0x000104dc, 0x000104b4, 0x00010d75, 0x00010d55, + 0x000118c8, 0x000118a8, 0x0000012b, 0x0000012a, + 0x000000e4, 0x000000c4, 0x000010d0, 0x00001c90, + 0x00000287, 0x0000a7b1, 0x000104df, 0x000104b7, + 0x000004b1, 0x000004b0, 0x00010429, 0x00010401, + 0x00001f40, 0x00001f48, 0x00000144, 0x00000143, + 0x00000161, 0x00000160, 0x0000ff4c, 0x0000ff2c, + 0x00001c87, 0x00000462, 0x00002177, 0x00002167, + 0x00000525, 0x00000524, 0x00002d1b, 0x000010bb, + 0x000118da, 0x000118ba, 0x0000aba5, 0x000013d5, + 0x00001f99, 0x020000ee, 0x00002c50, 0x00002c20, + 0x00010432, 0x0001040a, 0x0001e93e, 0x0001e91c, + 0x00001fbe, 0x00000399, 0x00001e91, 0x00001e90, + 0x000010da, 0x00001c9a, 0x0000a799, 0x0000a798, + 0x000010ed, 0x00001cad, 0x00001e9a, 0x02000097, + 0x00010d71, 0x00010d51, 0x000105a1, 0x0001057a, + 0x000003be, 0x0000039e, 0x00001fe4, 0x020000c6, + 0x000104f4, 0x000104cc, 0x0000fb15, 0x02000074, + 0x00000445, 0x00000425, 0x000003df, 0x000003de, + 0x00016e66, 0x00016e46, 0x00000581, 0x00000551, + 0x000001ff, 0x000001fe, 0x00002d0c, 0x000010ac, + 0x000010f5, 0x00001cb5, 0x0000ab8b, 0x000013bb, + 0x0001e927, 0x0001e905, 0x0000057f, 0x0000054f, + 0x000013fb, 0x000013f3, 0x00000177, 0x00000176, + 0x00000459, 0x00000409, 0x00001ff6, 0x020000d0, + 0x0000ff4a, 0x0000ff2a, 0x00016ec3, 0x00016ea8, + 0x00000069, 0x00000049, 0x0000abb0, 0x000013e0, + 0x00001ee7, 0x00001ee6, 0x0001059c, 0x00010575, + 0x00001f51, 0x00001f59, 0x0000ab80, 0x000013b0, + 0x0000ab94, 0x000013c4, 0x00016e65, 0x00016e45, + 0x00000567, 0x00000537, 0x00001e5d, 0x00001e5c, + 0x0000aba2, 0x000013d2, 0x000024dd, 0x000024c3, + 0x0000014f, 0x0000014e, 0x0000045f, 0x0000040f, + 0x00016e76, 0x00016e56, 0x000004db, 0x000004da, + 0x00002cdb, 0x00002cda, 0x000118dc, 0x000118bc, + 0x000010db, 0x00001c9b, 0x00002d08, 0x000010a8, + 0x000003c3, 0x000003a3, 0x000118d6, 0x000118b6, + 0x00001fe5, 0x00001fec, 0x000000e3, 0x000000c3, + 0x00001e4d, 0x00001e4c, 0x0000a653, 0x0000a652, + 0x0000a753, 0x0000a752, 0x00016e68, 0x00016e48, + 0x00000263, 0x00000194, 0x00010cc3, 0x00010c83, + 0x00001fd0, 0x00001fd8, 0x000001d4, 0x000001d3, + 0x00001f22, 0x00001f2a, 0x00010ccc, 0x00010c8c, + 0x000010f8, 0x00001cb8, 0x0001044e, 0x00010426, + 0x000004b9, 0x000004b8, 0x00016ec7, 0x00016eac, + 0x00002c3b, 0x00002c0b, 0x000010e8, 0x00001ca8, + 0x0000fb01, 0x02000057, 0x0000a73d, 0x0000a73c, + 0x0000ff4b, 0x0000ff2b, 0x0000028a, 0x000001b1, + 0x00000529, 0x00000528, 0x0001e939, 0x0001e917, + 0x00002cad, 0x00002cac, 0x00002184, 0x00002183, + 0x00001fa5, 0x0200003f, 0x0000ab96, 0x000013c6, + 0x000105b8, 0x00010591, 0x0001043a, 0x00010412, + 0x00002c93, 0x00002c92, 0x0001059e, 0x00010577, + 0x00002d23, 0x000010c3, 0x0000a685, 0x0000a684, + 0x00001f9a, 0x020000f1, 0x0001059f, 0x00010578, + 0x000104e3, 0x000104bb, 0x00001e3b, 0x00001e3a, + 0x00001e1f, 0x00001e1e, 0x000001e7, 0x000001e6, + 0x0000ab9f, 0x000013cf, 0x0000ff58, 0x0000ff38, + 0x00000447, 0x00000427, 0x00000269, 0x00000196, + 0x00010d7e, 0x00010d5e, 0x00000140, 0x0000013f, + 0x00001e8f, 0x00001e8e, 0x0000056e, 0x0000053e, + 0x000105ae, 0x00010587, 0x0000abab, 0x000013db, + 0x00000471, 0x00000470, 0x00000575, 0x00000545, + 0x00001e3d, 0x00001e3c, 0x000001b0, 0x000001af, + 0x00001ec1, 0x00001ec0, 0x00010d74, 0x00010d54, + 0x00000432, 0x00000412, 0x00010441, 0x00010419, + 0x000004f1, 0x000004f0, 0x0000ab7e, 0x000013ae, + 0x00001eeb, 0x00001eea, 0x00002d11, 0x000010b1, + 0x00000219, 0x00000218, 0x00010cdf, 0x00010c9f, + 0x00002c59, 0x00002c29, 0x0000024f, 0x0000024e, + 0x000000e9, 0x000000c9, 0x000001e5, 0x000001e4, + 0x00001f15, 0x00001f1d, 0x00000345, 0x00000399, + 0x00001fe7, 0x030000cc, 0x0000fb04, 0x03000061, + 0x00001f02, 0x00001f0a, 0x000004df, 0x000004de, + 0x00000231, 0x00000230, 0x00001ed5, 0x00001ed4, + 0x00010ce6, 0x00010ca6, 0x0000a77f, 0x0000a77e, + 0x00010ceb, 0x00010cab, 0x00002c68, 0x00002c67, + 0x000104e2, 0x000104ba, 0x000000ed, 0x000000cd, + 0x00001e51, 0x00001e50, 0x000010f7, 0x00001cb7, + 0x0000abae, 0x000013de, 0x00016e60, 0x00016e40, + 0x0000016b, 0x0000016a, 0x00002170, 0x00002160, + 0x00002d02, 0x000010a2, 0x000105b0, 0x00010589, + 0x000104f2, 0x000104ca, 0x000004cc, 0x000004cb, + 0x00010d84, 0x00010d64, 0x00016eca, 0x00016eaf, + 0x000000f1, 0x000000d1, 0x00010433, 0x0001040b, + 0x0000024b, 0x0000024a, 0x00001e35, 0x00001e34, + 0x00002c99, 0x00002c98, 0x0000a65d, 0x0000a65c, + 0x0000ff59, 0x0000ff39, 0x000104e4, 0x000104bc, + 0x00001f7d, 0x00001ffb, 0x00016e75, 0x00016e55, + 0x0000010b, 0x0000010a, 0x00001c8a, 0x00001c89, + 0x00010cc0, 0x00010c80, 0x0000fb02, 0x0200005a, + 0x000104f6, 0x000104ce, 0x000004a1, 0x000004a0, + 0x00000121, 0x00000120, 0x00001f8f, 0x020000e8, + 0x00002d27, 0x000010c7, 0x0000fb14, 0x02000071, + 0x00002d00, 0x000010a0, 0x000000f2, 0x000000d2, + 0x000118c4, 0x000118a4, 0x000118d1, 0x000118b1, + 0x00001e19, 0x00001e18, 0x00010599, 0x00010572, + 0x000010e7, 0x00001ca7, 0x000004c8, 0x000004c7, + 0x00016e64, 0x00016e44, 0x00000503, 0x00000502, + 0x0000029d, 0x0000a7b2, 0x000010ec, 0x00001cac, + 0x0000ab91, 0x000013c1, 0x0000a693, 0x0000a692, + 0x0000a793, 0x0000a792, 0x00002c5f, 0x00002c2f, + 0x00010ce7, 0x00010ca7, 0x00000481, 0x00000480, + 0x0000ab7a, 0x000013aa, 0x00001e07, 0x00001e06, + 0x00002d24, 0x000010c4, 0x0000a72f, 0x0000a72e, + 0x00010cee, 0x00010cae, 0x00010443, 0x0001041b, + 0x00001eef, 0x00001eee, 0x000003f2, 0x000003f9, + 0x0000026c, 0x0000a7ad, 0x00001e7b, 0x00001e7a, + 0x00001fb1, 0x00001fb9, 0x000105b1, 0x0001058a, + 0x000010f4, 0x00001cb4, 0x00002ca7, 0x00002ca6, + 0x00000561, 0x00000531, 0x000010ef, 0x00001caf, + 0x0000ff53, 0x0000ff33, 0x00001ee9, 0x00001ee8, + 0x00016e7e, 0x00016e5e, 0x00010d83, 0x00010d63, + 0x000003e7, 0x000003e6, 0x000004f3, 0x000004f2, + 0x00002cdd, 0x00002cdc, 0x0000a647, 0x0000a646, + 0x00001fd3, 0x030000b3, 0x00002c5a, 0x00002c2a, + 0x0000217e, 0x0000216e, 0x000024e2, 0x000024c8, + 0x000024e9, 0x000024cf, 0x000003f3, 0x0000037f, + 0x00000252, 0x00002c70, 0x0000043c, 0x0000041c, + 0x000118c2, 0x000118a2, 0x00016e6c, 0x00016e4c, + 0x00000449, 0x00000429, 0x0000abac, 0x000013dc, + 0x0000a649, 0x0000a648, 0x000010d6, 0x00001c96, + 0x00001f85, 0x0200000f, 0x00001e39, 0x00001e38, + 0x00000192, 0x00000191, 0x0000ff46, 0x0000ff26, + 0x000004bd, 0x000004bc, 0x00010447, 0x0001041f, + 0x00002c36, 0x00002c06, 0x00001e65, 0x00001e64, + 0x0000a64d, 0x0000a64c, 0x0000a741, 0x0000a740, + 0x00002c3a, 0x00002c0a, 0x000104da, 0x000104b2, + 0x000105ad, 0x00010586, 0x00001e2b, 0x00001e2a, + 0x00002cb7, 0x00002cb6, 0x0000020d, 0x0000020c, + 0x000104fa, 0x000104d2, 0x00000458, 0x00000408, + 0x00000225, 0x00000224, 0x0001059d, 0x00010576, + 0x0000012d, 0x0000012c, 0x00001fac, 0x0200010f, + 0x0000a68f, 0x0000a68e, 0x00001fe0, 0x00001fe8, + 0x000024d2, 0x000024b8, 0x000118de, 0x000118be, + 0x00010cdd, 0x00010c9d, 0x000118d2, 0x000118b2, + 0x00002d19, 0x000010b9, 0x00001f11, 0x00001f19, + 0x00002d1d, 0x000010bd, 0x00001f74, 0x00001fca, + 0x00000223, 0x00000222, 0x00010cd1, 0x00010c91, + 0x000004b7, 0x000004b6, 0x00000109, 0x00000108, + 0x00000205, 0x00000204, 0x0000a699, 0x0000a698, + 0x0000a797, 0x0000a796, 0x00001c84, 0x00000422, + 0x00010cd3, 0x00010c93, 0x0000057d, 0x0000054d, + 0x000001ad, 0x000001ac, 0x00001e1b, 0x00001e1a, + 0x00002ca9, 0x00002ca8, 0x0000a77a, 0x0000a779, + 0x00010cd9, 0x00010c99, 0x000105b5, 0x0001058e, + 0x000004f9, 0x000004f8, 0x000003cb, 0x000003ab, + 0x000003e1, 0x000003e0, 0x00002c5d, 0x00002c2d, + 0x0000a689, 0x0000a688, 0x00010d80, 0x00010d60, + 0x000118d8, 0x000118b8, 0x00000463, 0x00000462, + 0x0000056d, 0x0000053d, 0x00001f64, 0x00001f6c, + 0x00002cf3, 0x00002cf2, 0x00001ef9, 0x00001ef8, + 0x00000146, 0x00000145, 0x00016e74, 0x00016e54, + 0x0000aba6, 0x000013d6, 0x00000063, 0x00000043, + 0x000003cc, 0x0000038c, 0x00001ed9, 0x00001ed8, + 0x00016ec0, 0x00016ea5, 0x0000a645, 0x0000a644, + 0x00000195, 0x000001f6, 0x0000ff42, 0x0000ff22, + 0x000118dd, 0x000118bd, 0x00002c39, 0x00002c09, + 0x00002d15, 0x000010b5, 0x00016e61, 0x00016e41, + 0x0000fb13, 0x0200006e, 0x00001fd1, 0x00001fd9, + 0x000024d6, 0x000024bc, 0x0000026a, 0x0000a7ae, + 0x00000165, 0x00000164, 0x0000ab9c, 0x000013cc, + 0x00000247, 0x00000246, 0x00001ff7, 0x0300013e, + 0x0000abba, 0x000013ea, 0x0001044a, 0x00010422, + 0x0000048f, 0x0000048e, 0x000024d0, 0x000024b6, + 0x00010431, 0x00010409, 0x000001bf, 0x000001f7, + 0x0000ff50, 0x0000ff30, 0x00010d81, 0x00010d61, + 0x000003bd, 0x0000039d, 0x000118d0, 0x000118b0, + 0x00002174, 0x00002164, 0x00001e31, 0x00001e30, + 0x0000017a, 0x00000179, 0x00001eab, 0x00001eaa, + 0x0001e928, 0x0001e906, 0x000118db, 0x000118bb, + 0x000003b3, 0x00000393, 0x000003d0, 0x00000392, + 0x00000127, 0x00000126, 0x00001ea5, 0x00001ea4, + 0x000104ee, 0x000104c6, 0x00002d0b, 0x000010ab, + 0x0000a73f, 0x0000a73e, 0x0000ff44, 0x0000ff24, + 0x0000abb2, 0x000013e2, 0x00000523, 0x00000522, + 0x00001e21, 0x00001e20, 0x0000a735, 0x0000a734, + 0x0000a727, 0x0000a726, 0x00000457, 0x00000407, + 0x0000a7a7, 0x0000a7a6, 0x00002171, 0x00002161, + 0x0000049b, 0x0000049a, 0x00000115, 0x00000114, + 0x00001e95, 0x00001e94, 0x0000a69b, 0x0000a69a, + 0x0000a79b, 0x0000a79a, 0x00000283, 0x000001a9, + 0x000003c4, 0x000003a4, 0x0000ab9a, 0x000013ca, + 0x00002c8d, 0x00002c8c, 0x00000242, 0x00000241, + 0x00010cc5, 0x00010c85, 0x0000025c, 0x0000a7ab, + 0x00016ebe, 0x00016ea3, 0x00002c4f, 0x00002c1f, + 0x000004f7, 0x000004f6, 0x000001da, 0x000001d9, + 0x00002c83, 0x00002c82, 0x00000119, 0x00000118, + 0x0000a687, 0x0000a686, 0x0000a785, 0x0000a784, + 0x0001042a, 0x00010402, 0x0000047d, 0x0000047c, + 0x00000571, 0x00000541, 0x00000075, 0x00000055, + 0x00000185, 0x00000184, 0x00001ef1, 0x00001ef0, + 0x0000ff54, 0x0000ff34, 0x000013fa, 0x000013f2, + 0x000010e6, 0x00001ca6, 0x00000067, 0x00000047, + 0x0001e941, 0x0001e91f, 0x000000ee, 0x000000ce, + 0x0000a66d, 0x0000a66c, 0x00000438, 0x00000418, + 0x000000e8, 0x000000c8, 0x00001f06, 0x00001f0e, + 0x000104e6, 0x000104be, 0x00001f03, 0x00001f0b, + 0x00002d17, 0x000010b7, 0x00001f67, 0x00001f6f, + 0x0000a763, 0x0000a762, 0x00010cd4, 0x00010c94, + 0x00001f60, 0x00001f68, 0x00002ce3, 0x00002ce2, + 0x0000a7bf, 0x0000a7be, 0x00000562, 0x00000532, + 0x00001ed7, 0x00001ed6, 0x00001fa0, 0x02000030, + 0x00002d06, 0x000010a6, 0x00002175, 0x00002165, + 0x00010ce1, 0x00010ca1, 0x000104fb, 0x000104d3, + 0x000118d4, 0x000118b4, 0x00001e4b, 0x00001e4a, + 0x00001f8e, 0x020000e5, 0x0000a74d, 0x0000a74c, + 0x00002cc7, 0x00002cc6, 0x00000435, 0x00000415, + 0x00010ced, 0x00010cad, 0x00001e33, 0x00001e32, + 0x00000133, 0x00000132, 0x000000fb, 0x000000db, + 0x00001ef5, 0x00001ef4, 0x000010f6, 0x00001cb6, + 0x00000452, 0x00000402, 0x00010cc7, 0x00010c87, + 0x00000574, 0x00000544, 0x00001ea7, 0x00001ea6, + 0x000003af, 0x0000038a, 0x00001fa6, 0x02000042, + 0x0000a7f6, 0x0000a7f5, 0x000104f9, 0x000104d1, + 0x00001f7a, 0x00001fea, 0x00000527, 0x00000526, + 0x00001e29, 0x00001e28, 0x0000abad, 0x000013dd, + 0x00000271, 0x00002c6e, 0x00001fa7, 0x02000045, + 0x00002c9f, 0x00002c9e, 0x00002c9b, 0x00002c9a, + 0x0000049f, 0x0000049e, 0x00000135, 0x00000134, + 0x00001e99, 0x02000094, 0x00001fa2, 0x02000036, + 0x00002c31, 0x00002c01, 0x00002cdf, 0x00002cde, + 0x000024d5, 0x000024bb, 0x00010445, 0x0001041d, + 0x0001e92e, 0x0001e90c, 0x00002d05, 0x000010a5, + 0x00001f72, 0x00001fc8, 0x00002d0a, 0x000010aa, + 0x000004c2, 0x000004c1, 0x00001f78, 0x00001ff8, + 0x00001f34, 0x00001f3c, 0x00000117, 0x00000116, + 0x000118d9, 0x000118b9, 0x00002ca5, 0x00002ca4, + 0x000000f0, 0x000000d0, 0x000105b7, 0x00010590, + 0x00000076, 0x00000056, 0x000118c9, 0x000118a9, + 0x00001f35, 0x00001f3d, 0x0001e929, 0x0001e907, + 0x00000153, 0x00000152, 0x00001efd, 0x00001efc, + 0x00000288, 0x000001ae, 0x00001f96, 0x0200002a, + 0x000010fe, 0x00001cbe, 0x000004e9, 0x000004e8, + 0x0000a7c8, 0x0000a7c7, 0x00001ee5, 0x00001ee4, + 0x0001e930, 0x0001e90e, 0x0000006e, 0x0000004e, + 0x00002c57, 0x00002c27, 0x00002c53, 0x00002c23, + 0x00016e69, 0x00016e49, 0x000003b4, 0x00000394, + 0x00001e61, 0x00001e60, 0x0000011d, 0x0000011c, + 0x0000a765, 0x0000a764, 0x00001f01, 0x00001f09, + 0x00000455, 0x00000405, 0x00016ecb, 0x00016eb0, + 0x000001dd, 0x0000018e, 0x00000159, 0x00000158, + 0x0000ab82, 0x000013b2, 0x000010d1, 0x00001c91, + 0x0000a7db, 0x0000a7da, 0x0000024d, 0x0000024c, + 0x00000585, 0x00000555, 0x000105ac, 0x00010585, + 0x00001f00, 0x00001f08, 0x00001e4f, 0x00001e4e, + 0x00000390, 0x03000080, 0x00000249, 0x00000248, + 0x000001dc, 0x000001db, 0x00000465, 0x00000464, + 0x00016e67, 0x00016e47, 0x000003c8, 0x000003a8, + 0x00000125, 0x00000124, 0x00001ec3, 0x00001ec2, + 0x00010cd0, 0x00010c90, 0x0000a7c1, 0x0000a7c0, + 0x00002c4a, 0x00002c1a, 0x0000a64b, 0x0000a64a, + 0x0000045a, 0x0000040a, 0x0001e935, 0x0001e913, + 0x0000abbd, 0x000013ed, 0x00001f70, 0x00001fba, + 0x00010d78, 0x00010d58, 0x0000ff41, 0x0000ff21, + 0x000104e7, 0x000104bf, 0x00000074, 0x00000054, + 0x0000aba0, 0x000013d0, 0x00000129, 0x00000128, + 0x0000abb3, 0x000013e3, 0x00002ca3, 0x00002ca2, + 0x000105a7, 0x00010580, 0x0000ff52, 0x0000ff32, + 0x000004a3, 0x000004a2, 0x00000111, 0x00000110, + 0x0000a77c, 0x0000a77b, 0x00002d07, 0x000010a7, + 0x000024d7, 0x000024bd, 0x00002c32, 0x00002c02, + 0x00000491, 0x00000490, 0x000105b9, 0x00010592, + 0x0000050d, 0x0000050c, 0x00001e11, 0x00001e10, + 0x00001c86, 0x0000042a, 0x0000ab9b, 0x000013cb, + 0x000004c6, 0x000004c5, 0x00010cc9, 0x00010c89, + 0x00000505, 0x00000504, 0x0000027d, 0x00002c64, + 0x00016e71, 0x00016e51, 0x00001ead, 0x00001eac, + 0x0000a695, 0x0000a694, 0x00016e77, 0x00016e57, + 0x00016ed3, 0x00016eb8, 0x0000ab8a, 0x000013ba, + 0x00001d7d, 0x00002c63, 0x000013fd, 0x000013f5, + 0x00001c85, 0x00000422, 0x0000ab85, 0x000013b5, + 0x00001f82, 0x02000006, 0x00002c35, 0x00002c05, + 0x00002d1a, 0x000010ba, 0x00000163, 0x00000162, + 0x00010437, 0x0001040f, 0x00002c73, 0x00002c72, + 0x0000a78c, 0x0000a78b, 0x00001f91, 0x0200001b, + 0x000003e5, 0x000003e4, 0x0000ff4f, 0x0000ff2f, + 0x0000046b, 0x0000046a, 0x00000103, 0x00000102, + 0x0000028c, 0x00000245, 0x0000a66b, 0x0000a66a, + 0x000024db, 0x000024c1, 0x00016e7a, 0x00016e5a, + 0x0000044e, 0x0000042e, 0x0000217f, 0x0000216f, + 0x000004ff, 0x000004fe, 0x00000151, 0x00000150, + 0x00001ed1, 0x00001ed0, 0x00010ce2, 0x00010ca2, + 0x0000021f, 0x0000021e, 0x000003b1, 0x00000391, + 0x0000048d, 0x0000048c, 0x000104db, 0x000104b3, + 0x0000010f, 0x0000010e, 0x00001f56, 0x030000a5, + 0x00002179, 0x00002169, 0x0000a755, 0x0000a754, + 0x00016e7c, 0x00016e5c, 0x0001044f, 0x00010427, + 0x000010ee, 0x00001cae, 0x000001a3, 0x000001a2, + 0x00002c45, 0x00002c15, 0x000004d3, 0x000004d2, + 0x0000ab9e, 0x000013ce, 0x0000a7b5, 0x0000a7b4, + 0x00016ed2, 0x00016eb7, 0x000004ab, 0x000004aa, + 0x00001fb0, 0x00001fb8, 0x000104ed, 0x000104c5, + 0x000118d5, 0x000118b5, 0x00001f13, 0x00001f1b, + 0x0000a745, 0x0000a744, 0x000118ce, 0x000118ae, + 0x0000ab89, 0x000013b9, 0x0000014b, 0x0000014a, + 0x00001e2d, 0x00001e2c, 0x00001fd2, 0x030000af, + 0x0000ab97, 0x000013c7, 0x00010cd2, 0x00010c92, + 0x0000ab87, 0x000013b7, 0x00001f94, 0x02000024, + 0x0000abaf, 0x000013df, 0x00000070, 0x00000050, + 0x00001ffc, 0x02000121, 0x00002d25, 0x000010c5, + 0x0000a7bd, 0x0000a7bc, 0x00010428, 0x00010400, + 0x00000495, 0x00000494, 0x000104d9, 0x000104b1, + 0x00000157, 0x00000156, 0x0000a73b, 0x0000a73a, + 0x0000a665, 0x0000a664, 0x0000aba1, 0x000013d1, + 0x0000ab72, 0x000013a2, 0x00010d82, 0x00010d62, + 0x000024de, 0x000024c4, 0x000001eb, 0x000001ea, + 0x00002caf, 0x00002cae, 0x00000207, 0x00000206, + 0x000010d8, 0x00001c98, 0x0000a79f, 0x0000a79e, + 0x00002cd9, 0x00002cd8, 0x00001c80, 0x00000412, + 0x0000ab84, 0x000013b4, 0x00000440, 0x00000420, + 0x00001e27, 0x00001e26, 0x000105ab, 0x00010584, + 0x00001fa8, 0x02000103, 0x000104f8, 0x000104d0, + 0x000003fb, 0x000003fa, 0x0001e92a, 0x0001e908, + 0x00001fc4, 0x0200012d, 0x00000568, 0x00000538, + 0x0001e934, 0x0001e912, 0x00000563, 0x00000533, + 0x0000a787, 0x0000a786, 0x0001e92b, 0x0001e909, + 0x0000046d, 0x0000046c, 0x0000056b, 0x0000053b, + 0x00001e69, 0x00001e68, 0x0000a657, 0x0000a656, + 0x0000a76f, 0x0000a76e, 0x00000446, 0x00000426, + 0x00002c46, 0x00002c16, 0x0001044b, 0x00010423, + 0x000004e3, 0x000004e2, 0x0000015d, 0x0000015c, + 0x00001edd, 0x00001edc, 0x000010de, 0x00001c9e, + 0x000000f3, 0x000000d3, 0x0000abb4, 0x000013e4, + 0x0001e923, 0x0001e901, 0x0000047f, 0x0000047e, + 0x00002cd5, 0x00002cd4, 0x00000188, 0x00000187, + 0x00001fe3, 0x030000c2, 0x0000a757, 0x0000a756, + 0x0000016d, 0x0000016c, 0x000104de, 0x000104b6, + 0x00010cd5, 0x00010c95, 0x00002c4e, 0x00002c1e, + 0x00002ccb, 0x00002cca, 0x00002c65, 0x0000023a, + 0x00010cd8, 0x00010c98, 0x0000a7cd, 0x0000a7cc, + 0x000001ce, 0x000001cd, 0x00001ed3, 0x00001ed2, + 0x00010d85, 0x00010d65, 0x00001f42, 0x00001f4a, + 0x0000043f, 0x0000041f, 0x000003bc, 0x0000039c, + 0x0000a749, 0x0000a748, 0x0000ff4e, 0x0000ff2e, + 0x000024e0, 0x000024c6, 0x000003f0, 0x0000039a, + 0x00000430, 0x00000410, 0x00002cb3, 0x00002cb2, + 0x00001eb3, 0x00001eb2, 0x00001fa3, 0x02000039, + 0x00010cc1, 0x00010c81, 0x00016ec8, 0x00016ead, + 0x000010f2, 0x00001cb2, 0x00000123, 0x00000122, + 0x00001eaf, 0x00001eae, 0x0000abaa, 0x000013da, + 0x0000023f, 0x00002c7e, 0x00010434, 0x0001040c, + 0x00016e78, 0x00016e58, 0x000024da, 0x000024c0, + 0x000118c6, 0x000118a6, 0x000001d0, 0x000001cf, + 0x0000a667, 0x0000a666, 0x0000aba3, 0x000013d3, + 0x00002c49, 0x00002c19, 0x00002d1c, 0x000010bc, + 0x0001e925, 0x0001e903, 0x00000493, 0x00000492, + 0x00000072, 0x00000052, 0x00001e93, 0x00001e92, + 0x0000a691, 0x0000a690, 0x000104ec, 0x000104c4, + 0x00002d0f, 0x000010af, 0x000010f0, 0x00001cb0, + 0x0000ab98, 0x000013c8, 0x00000509, 0x00000508, + 0x00001e0b, 0x00001e0a, 0x000003dd, 0x000003dc, + 0x0000ab99, 0x000013c9, 0x00016e6b, 0x00016e4b, + 0x000105a8, 0x00010581, 0x00000071, 0x00000051 }; -static const unsigned _uccase_lower_g_size = 274; +static const unsigned _uccase_lower_g_size = 339; static const short _uccase_lower_g[] = { - 19, -339, 8836, 631, 9135, 8, 27, -1063, - 10, 3627, 876, 27, 47, 16534, 60, 888, - 17, 64, 2, 5, 9, 1237, 18, 2342, - 111, 17, 359, 110, 69, 2640, 78, 354, - 228, 4917, 61, 260, 3, 2614, 9, 353, - 37, 68, 1061, 3015, 21, 4002, 962, 1724, - 446, 776, 17, 8978, 421, 336, 506, 8550, - 148, -474, 3259, 933, 1171, 413, 126, -1086, - 2, 3008, 295, 110, 16, -1061, 67, 598, - 126, 3575, 79, 98, 103, 693, 32, 749, - 3, 2501, 260, 1003, 15, 4463, 282, 349, - 16, 40, 6, 935, 546, 726, 2, 353, - 94, 928, 780, 7113, 39, 3599, 6035, 315, - 186, 4306, 16, 9259, 100, 82, 1069, 537, - 72, -686, 12102, 8064, 216, 95, 1761, 32767, - 8, 3436, 116, 1035, 14, 5405, 40, 1012, - 22, 135, 22, 1252, 589, 812, 8, 1721, - 10, 761, 84, 103, 36, 655, 600, 3517, - 11, 475, 1, 205, 17, 4384, 20, 5705, - 198, 741, 154, 8691, 28, 247, 739, 144, - 343, 703, 16, 32767, 809, 773, 806, 15951, - 270, 443, 360, 4365, 2648, 154, 109, -191, - 12, 11910, 43, 849, 2, 1876, 65, 460, - 19, 585, 1, 684, 391, 463, 203, 782, - 102, 2630, 679, 1610, 35, 5529, 84, 3992, - 1, 157, 8, 389, 1295, 1272, 153, 406, - 133, 1074, 59, 9484, 2, 264, 7316, 276, - 252, 520, 29, -220, 113, 15121, 525, 2091, - 283, 6976, 1, 13412, 647, 51, 285, 2206, - 3, 678, 17, 948, 114, 1233, 1, 38, - 19, 1583, 52, 803, 770, 1329, 380, 8813, - 66, 133, 256, 6495, 18, 7784, 53, 2867, - 4, 680, 34, 258, 1488, 1040, 19, 3566, - 844, 12080, 391, 7012, 1, 2670, 3227, 146, - 362, 1934 + 2657, 182, 11, 3707, 9309, 2, 2598, 245, + 521, 3500, 2366, 1, 57, 3082, -1357, 3638, + 4489, 2573, 646, -865, 3844, 3, -399, 132, + 41, -467, 9225, 16, 3073, 838, 2220, 606, + 1687, -71, 191, 148, 2573, 2042, 263, 2955, + 3, 2055, 2442, 3116, 935, 166, 3306, 2547, + 1115, 470, 516, 1064, 512, 9286, 1262, 38, + 270, 565, 756, 8014, 5285, 3296, 38, 1298, + 12, 574, 2572, 7250, 2, 2616, 28, 64, + 3676, 43, 1, 2574, 3532, 242, 3367, 2181, + 70, 800, 5195, 32767, 1076, 3784, 2565, 199, + -864, 3795, 4, -386, 143, 2051, 3282, 9328, + 2833, 9266, 675, 2245, 522, 3845, -20, 532, + 2570, 2970, 736, 2638, 2634, 175, -1268, 3373, + 12978, 943, 836, 3641, 5729, 1049, 66, 263, + 1147, 332, 2119, 2822, 66, 1353, 1604, 1498, + 9, 2461, 654, 872, 3475, 937, 65, 3233, + 7822, 2, 2605, 1, 167, 3841, 329, 65, + 2574, 2549, 2069, 1, 2707, 786, 174, 2947, + -1341, 72, -1248, 2177, 96, -831, 9341, 18, + -343, 2243, 3854, 2179, 689, 626, 4269, 884, + 196, 39, 270, -2, 2566, 2737, 2955, 649, + 2561, -459, 22, 2878, 332, 3772, 1768, 555, + 172, 3687, 2104, 169, 524, 1170, 421, 6443, + 3073, 501, 365, 518, 727, 54, 2315, 10847, + 610, 3584, 148, 8, 2695, 396, 1, 2595, + 6, 2053, 3572, 2722, 1, 4043, 2216, 547, + 132, 449, 763, 3570, 2415, 15812, 1, 32767, + 3606, 8, -791, 3613, 477, 3521, 3689, 1308, + 4020, 3417, 7, 4748, 783, 3078, 209, 3363, + 3088, 2180, 2509, 2566, 3079, 2560, 2072, 781, + 12740, 331, 3252, 900, 2030, 459, 2990, 3076, + 151, 25, 9, 406, 2836, 3084, 55, 1, + 3613, 159, 64, 2275, 10626, 36, 1647, 428, + 36, 3714, 302, 64, 2792, 11, 1731, 3733, + 2822, 1, 3969, 3596, 2248, 145, 140, 752, + 3332, -1244, 10190, 2, 32767, 92, 2, -585, + -229, 390, 9696, 1000, 2134, 9344, 3363, 178, + 737, 811, 3182, 2176, 2581, 2977, 164, 2570, + 3887, 3616, 1557, 3597, 227, 2329, 295, 3478, + 1683, 1105, 515, 4023, 2958, 28, 379, 257, + 257, 753, 2540, 35, 2, 3585, 1, 719, + 2310, 1005, 10 }; -static const unsigned _uccase_lower_table_size = 1460; +static const unsigned _uccase_lower_table_size = 1488; static const unsigned _uccase_lower_table[] = { - 0x00002cac, 0x00002cad, 0x00001e78, 0x00001e79, - 0x0000042d, 0x0000044d, 0x0000023d, 0x0000019a, - 0x00002169, 0x00002179, 0x00001fb9, 0x00001fb1, - 0x000013e9, 0x0000abb9, 0x000001a9, 0x00000283, - 0x000001c4, 0x000001c6, 0x000000c5, 0x000000e5, - 0x00000230, 0x00000231, 0x00000372, 0x00000373, - 0x00000232, 0x00000233, 0x00000053, 0x00000073, - 0x0000018a, 0x00000257, 0x00001ec0, 0x00001ec1, - 0x0000046c, 0x0000046d, 0x00010ca1, 0x00010ce1, - 0x00000536, 0x00000566, 0x00001e32, 0x00001e33, - 0x00010d59, 0x00010d79, 0x00001ec4, 0x00001ec5, - 0x00000200, 0x00000201, 0x000013bd, 0x0000ab8d, - 0x00001f48, 0x00001f40, 0x00000423, 0x00000443, - 0x00002c07, 0x00002c37, 0x000104bc, 0x000104e4, - 0x000013af, 0x0000ab7f, 0x00010caa, 0x00010cea, - 0x000004a8, 0x000004a9, 0x000024bf, 0x000024d9, - 0x000000d0, 0x000000f0, 0x00001e42, 0x00001e43, - 0x00010577, 0x0001059e, 0x00001e1a, 0x00001e1b, - 0x0000a750, 0x0000a751, 0x000000dd, 0x000000fd, - 0x00002c0c, 0x00002c3c, 0x0001e91b, 0x0001e93d, - 0x00002126, 0x000003c9, 0x00016e41, 0x00016e61, - 0x000010b4, 0x00002d14, 0x000001b3, 0x000001b4, - 0x00000050, 0x00000070, 0x00000122, 0x00000123, - 0x00000427, 0x00000447, 0x000013f5, 0x000013fd, - 0x00001e60, 0x00001e61, 0x00010c92, 0x00010cd2, - 0x00001f0a, 0x00001f02, 0x0000a662, 0x0000a663, - 0x0000040d, 0x0000045d, 0x000013d4, 0x0000aba4, - 0x000013ec, 0x0000abbc, 0x0000012e, 0x0000012f, - 0x00001ec8, 0x00001ec9, 0x00000498, 0x00000499, - 0x00001e22, 0x00001e23, 0x00010574, 0x0001059b, - 0x0000ff25, 0x0000ff45, 0x00000535, 0x00000565, - 0x000001e4, 0x000001e5, 0x000104b0, 0x000104d8, - 0x00000386, 0x000003ac, 0x000013ed, 0x0000abbd, - 0x00002c72, 0x00002c73, 0x000118a8, 0x000118c8, - 0x000003e0, 0x000003e1, 0x00010412, 0x0001043a, - 0x0000048a, 0x0000048b, 0x000013ee, 0x0000abbe, - 0x000000c0, 0x000000e0, 0x0001058f, 0x000105b6, - 0x0000016a, 0x0000016b, 0x0000a646, 0x0000a647, - 0x00000206, 0x00000207, 0x00000399, 0x000003b9, - 0x00002c17, 0x00002c47, 0x0000a79a, 0x0000a79b, - 0x000013b1, 0x0000ab81, 0x00002c9a, 0x00002c9b, - 0x00000428, 0x00000448, 0x000010bd, 0x00002d1d, - 0x0000053d, 0x0000056d, 0x00002166, 0x00002176, - 0x00000170, 0x00000171, 0x00010c9c, 0x00010cdc, - 0x000001a0, 0x000001a1, 0x0001057d, 0x000105a4, - 0x00002c29, 0x00002c59, 0x00010c8b, 0x00010ccb, - 0x00000051, 0x00000071, 0x00001f88, 0x00001f80, - 0x000013e6, 0x0000abb6, 0x000024b8, 0x000024d2, - 0x000004b8, 0x000004b9, 0x00016e56, 0x00016e76, - 0x00010586, 0x000105ad, 0x000013d7, 0x0000aba7, - 0x000013cf, 0x0000ab9f, 0x0000011e, 0x0000011f, - 0x00000043, 0x00000063, 0x000001c8, 0x000001c9, - 0x000010a9, 0x00002d09, 0x000001d3, 0x000001d4, - 0x000004cb, 0x000004cc, 0x00002c60, 0x00002c61, - 0x0000a724, 0x0000a725, 0x00002cda, 0x00002cdb, - 0x000024ca, 0x000024e4, 0x00000470, 0x00000471, - 0x000000db, 0x000000fb, 0x0000051a, 0x0000051b, - 0x00000516, 0x00000517, 0x0001057a, 0x000105a1, - 0x00000224, 0x00000225, 0x000001e8, 0x000001e9, - 0x000010ba, 0x00002d1a, 0x0000a78d, 0x00000265, - 0x000013c4, 0x0000ab94, 0x0001e905, 0x0001e927, - 0x000013c3, 0x0000ab93, 0x000003e4, 0x000003e5, - 0x000003ec, 0x000003ed, 0x00010415, 0x0001043d, - 0x0000046a, 0x0000046b, 0x00010422, 0x0001044a, - 0x00001ffb, 0x00001f7d, 0x0001e906, 0x0001e928, - 0x00001ee0, 0x00001ee1, 0x00000208, 0x00000209, - 0x0000a686, 0x0000a687, 0x00001e00, 0x00001e01, - 0x000013ac, 0x0000ab7c, 0x000013b8, 0x0000ab88, - 0x0000ff38, 0x0000ff58, 0x0000039d, 0x000003bd, - 0x00000422, 0x00000442, 0x000004e0, 0x000004e1, - 0x00001cba, 0x000010fa, 0x00001cb3, 0x000010f3, - 0x00001e6c, 0x00001e6d, 0x0000a684, 0x0000a685, - 0x00010c8d, 0x00010ccd, 0x0000a72e, 0x0000a72f, - 0x0000022c, 0x0000022d, 0x00001f9a, 0x00001f92, - 0x00000395, 0x000003b5, 0x00000114, 0x00000115, - 0x00001f8d, 0x00001f85, 0x00001c9a, 0x000010da, - 0x00000198, 0x00000199, 0x000013ce, 0x0000ab9e, - 0x00010c8f, 0x00010ccf, 0x00010588, 0x000105af, - 0x00010401, 0x00010429, 0x000004e8, 0x000004e9, - 0x00000396, 0x000003b6, 0x00001e5c, 0x00001e5d, - 0x0000a728, 0x0000a729, 0x00000193, 0x00000260, - 0x00001cac, 0x000010ec, 0x000024c9, 0x000024e3, - 0x00002c69, 0x00002c6a, 0x00010c9f, 0x00010cdf, - 0x0000a7c0, 0x0000a7c1, 0x0000a722, 0x0000a723, - 0x00000534, 0x00000564, 0x0000a754, 0x0000a755, - 0x000104b6, 0x000104de, 0x000118b0, 0x000118d0, - 0x00000214, 0x00000215, 0x00001f1c, 0x00001f14, - 0x00001e50, 0x00001e51, 0x00010c90, 0x00010cd0, - 0x000001b5, 0x000001b6, 0x00000510, 0x00000511, - 0x0000a64c, 0x0000a64d, 0x0000004e, 0x0000006e, - 0x000118ab, 0x000118cb, 0x000118b3, 0x000118d3, - 0x000104b9, 0x000104e1, 0x000001a2, 0x000001a3, - 0x00001e3e, 0x00001e3f, 0x00001f99, 0x00001f91, - 0x00000220, 0x0000019e, 0x00001fcb, 0x00001f75, - 0x00002cde, 0x00002cdf, 0x000013e1, 0x0000abb1, - 0x000013cc, 0x0000ab9c, 0x000001d7, 0x000001d8, - 0x00000389, 0x000003ae, 0x000010af, 0x00002d0f, - 0x0000a66c, 0x0000a66d, 0x000004f2, 0x000004f3, - 0x00001ca5, 0x000010e5, 0x000004f4, 0x000004f5, - 0x0000a68a, 0x0000a68b, 0x00001eaa, 0x00001eab, - 0x0000021a, 0x0000021b, 0x0000a7be, 0x0000a7bf, - 0x0000038f, 0x000003ce, 0x0000a79e, 0x0000a79f, - 0x0000ff31, 0x0000ff51, 0x000010b5, 0x00002d15, - 0x00016e55, 0x00016e75, 0x000010a8, 0x00002d08, - 0x00010c9d, 0x00010cdd, 0x000104cc, 0x000104f4, - 0x00000112, 0x00000113, 0x0000a654, 0x0000a655, - 0x0000a7ba, 0x0000a7bb, 0x0000a7b3, 0x0000ab53, - 0x000013e3, 0x0000abb3, 0x00000412, 0x00000432, - 0x00001efa, 0x00001efb, 0x0000a7ad, 0x0000026c, - 0x0001e920, 0x0001e942, 0x00016e58, 0x00016e78, - 0x00001cbd, 0x000010fd, 0x00000490, 0x00000491, - 0x00010ca7, 0x00010ce7, 0x00001e2c, 0x00001e2d, - 0x00001e56, 0x00001e57, 0x0000a75e, 0x0000a75f, - 0x00001f1d, 0x00001f15, 0x00010576, 0x0001059d, - 0x00002c20, 0x00002c50, 0x000013a2, 0x0000ab72, - 0x00002cbc, 0x00002cbd, 0x000024c1, 0x000024db, - 0x0000042b, 0x0000044b, 0x00002c21, 0x00002c51, - 0x0000216e, 0x0000217e, 0x00002c8a, 0x00002c8b, - 0x00001ff9, 0x00001f79, 0x00000544, 0x00000574, - 0x0000a688, 0x0000a689, 0x000001d1, 0x000001d2, - 0x0000020a, 0x0000020b, 0x00001cb5, 0x000010f5, - 0x00002c24, 0x00002c54, 0x0000a7d8, 0x0000a7d9, - 0x0000053f, 0x0000056f, 0x0000041d, 0x0000043d, - 0x00016e47, 0x00016e67, 0x000118b9, 0x000118d9, - 0x000010b8, 0x00002d18, 0x000013b3, 0x0000ab83, - 0x000024cd, 0x000024e7, 0x00002c84, 0x00002c85, - 0x000001f8, 0x000001f9, 0x000104ce, 0x000104f6, - 0x00001f3e, 0x00001f36, 0x0000024a, 0x0000024b, - 0x00001fe8, 0x00001fe0, 0x00001fc8, 0x00001f72, - 0x0000a782, 0x0000a783, 0x000013bf, 0x0000ab8f, - 0x000024c0, 0x000024da, 0x0000047c, 0x0000047d, - 0x00002c92, 0x00002c93, 0x00010c99, 0x00010cd9, - 0x00001e66, 0x00001e67, 0x00002c2d, 0x00002c5d, - 0x00010402, 0x0001042a, 0x000001f6, 0x00000195, - 0x000010c2, 0x00002d22, 0x00010ca6, 0x00010ce6, - 0x0001e913, 0x0001e935, 0x00002cae, 0x00002caf, - 0x000118aa, 0x000118ca, 0x00001cbe, 0x000010fe, - 0x0000004a, 0x0000006a, 0x0001040d, 0x00010435, - 0x000004ae, 0x000004af, 0x000000d4, 0x000000f4, - 0x00000522, 0x00000523, 0x0000a65a, 0x0000a65b, - 0x00001e0c, 0x00001e0d, 0x00000228, 0x00000229, - 0x00010c8c, 0x00010ccc, 0x00001feb, 0x00001f7b, - 0x0000a79c, 0x0000a79d, 0x0001e903, 0x0001e925, - 0x00002ca0, 0x00002ca1, 0x0000054b, 0x0000057b, - 0x000024bd, 0x000024d7, 0x000004d0, 0x000004d1, - 0x0000216c, 0x0000217c, 0x00000164, 0x00000165, - 0x00000468, 0x00000469, 0x0000a682, 0x0000a683, - 0x0000a7c5, 0x00000282, 0x0000a72c, 0x0000a72d, - 0x000013a1, 0x0000ab71, 0x000004bc, 0x000004bd, - 0x00000393, 0x000003b3, 0x00002165, 0x00002175, - 0x00002cd2, 0x00002cd3, 0x00016e49, 0x00016e69, - 0x00002c23, 0x00002c53, 0x000118b4, 0x000118d4, - 0x00010d52, 0x00010d72, 0x00000174, 0x00000175, - 0x00016e4a, 0x00016e6a, 0x000001a6, 0x00000280, - 0x00000388, 0x000003ad, 0x000010a5, 0x00002d05, - 0x000000cf, 0x000000ef, 0x00001ece, 0x00001ecf, - 0x00001faa, 0x00001fa2, 0x00000162, 0x00000163, - 0x00002c67, 0x00002c68, 0x00000409, 0x00000459, - 0x0000041c, 0x0000043c, 0x000001c7, 0x000001c9, - 0x00000520, 0x00000521, 0x00001e72, 0x00001e73, - 0x00000549, 0x00000579, 0x00001ed6, 0x00001ed7, - 0x00002ce2, 0x00002ce3, 0x00000244, 0x00000289, - 0x0000a78b, 0x0000a78c, 0x00000506, 0x00000507, - 0x000003a1, 0x000003c1, 0x000118bf, 0x000118df, - 0x000004fc, 0x000004fd, 0x0000ff35, 0x0000ff55, - 0x0001040b, 0x00010433, 0x000118a9, 0x000118c9, - 0x00000552, 0x00000582, 0x00001e54, 0x00001e55, - 0x00002c15, 0x00002c45, 0x00001ed2, 0x00001ed3, - 0x00001e80, 0x00001e81, 0x0000a650, 0x0000a651, - 0x00001f9c, 0x00001f94, 0x00001cbf, 0x000010ff, - 0x000013a6, 0x0000ab76, 0x00001faf, 0x00001fa7, - 0x0000ff39, 0x0000ff59, 0x00001e58, 0x00001e59, - 0x00000494, 0x00000495, 0x00000136, 0x00000137, - 0x00001ca3, 0x000010e3, 0x000104c1, 0x000104e9, - 0x00001e62, 0x00001e63, 0x00001c9f, 0x000010df, - 0x0000a7b1, 0x00000287, 0x0000a75c, 0x0000a75d, - 0x00001fca, 0x00001f74, 0x0000a65c, 0x0000a65d, - 0x00002c75, 0x00002c76, 0x0000039e, 0x000003be, - 0x00001c9c, 0x000010dc, 0x0000a7c4, 0x0000a794, - 0x00002c64, 0x0000027d, 0x00002c2b, 0x00002c5b, - 0x00000130, 0x02000142, 0x00001e12, 0x00001e13, - 0x000001fc, 0x000001fd, 0x00010d54, 0x00010d74, - 0x0000a76e, 0x0000a76f, 0x00000414, 0x00000434, - 0x00001fe9, 0x00001fe1, 0x00002ce0, 0x00002ce1, - 0x00010414, 0x0001043c, 0x000118b2, 0x000118d2, - 0x000004d8, 0x000004d9, 0x000004a2, 0x000004a3, - 0x000000c2, 0x000000e2, 0x0001041e, 0x00010446, - 0x00001e30, 0x00001e31, 0x00010d5f, 0x00010d7f, - 0x0000022a, 0x0000022b, 0x00010572, 0x00010599, - 0x0000020c, 0x0000020d, 0x0000a7ae, 0x0000026a, - 0x0001057c, 0x000105a3, 0x00002c9e, 0x00002c9f, - 0x00001e1e, 0x00001e1f, 0x00001f2b, 0x00001f23, - 0x0000018f, 0x00000259, 0x0000216a, 0x0000217a, - 0x00001eac, 0x00001ead, 0x000104d3, 0x000104fb, - 0x0000a694, 0x0000a695, 0x00000190, 0x0000025b, - 0x00001f0c, 0x00001f04, 0x00000212, 0x00000213, - 0x00001f8c, 0x00001f84, 0x0000a7d6, 0x0000a7d7, - 0x00001cb9, 0x000010f9, 0x000024bc, 0x000024d6, - 0x00001c97, 0x000010d7, 0x000010c0, 0x00002d20, - 0x00001f2f, 0x00001f27, 0x00001f5d, 0x00001f55, - 0x00010425, 0x0001044d, 0x00010c81, 0x00010cc1, - 0x000104cf, 0x000104f7, 0x00010587, 0x000105ae, - 0x0001040c, 0x00010434, 0x0000a760, 0x0000a761, - 0x000013c2, 0x0000ab92, 0x00001eae, 0x00001eaf, - 0x000004ba, 0x000004bb, 0x0001e914, 0x0001e936, - 0x0000ff26, 0x0000ff46, 0x00000411, 0x00000431, - 0x000003ff, 0x0000037d, 0x0000051e, 0x0000051f, - 0x0000016c, 0x0000016d, 0x000118a2, 0x000118c2, - 0x000010ab, 0x00002d0b, 0x00010c85, 0x00010cc5, - 0x00001f39, 0x00001f31, 0x0000a779, 0x0000a77a, - 0x0001e915, 0x0001e937, 0x00002cc6, 0x00002cc7, - 0x00001cb1, 0x000010f1, 0x000003e6, 0x000003e7, - 0x0000004c, 0x0000006c, 0x00010417, 0x0001043f, - 0x000004de, 0x000004df, 0x000104bf, 0x000104e7, - 0x00001e70, 0x00001e71, 0x0000a64e, 0x0000a64f, - 0x0000a642, 0x0000a643, 0x000013f4, 0x000013fc, - 0x000010ae, 0x00002d0e, 0x00001e04, 0x00001e05, - 0x0000a796, 0x0000a797, 0x00002ca6, 0x00002ca7, - 0x00002cb6, 0x00002cb7, 0x00000533, 0x00000563, - 0x00000512, 0x00000513, 0x00002c6f, 0x00000250, - 0x00002168, 0x00002178, 0x0000a7aa, 0x00000266, - 0x00000462, 0x00000463, 0x000001f4, 0x000001f5, - 0x00002167, 0x00002177, 0x00001f4a, 0x00001f42, - 0x0000a758, 0x0000a759, 0x00002ca4, 0x00002ca5, - 0x0001e916, 0x0001e938, 0x00002c2f, 0x00002c5f, - 0x000024ba, 0x000024d4, 0x00001cae, 0x000010ee, - 0x0000004f, 0x0000006f, 0x00001ca9, 0x000010e9, - 0x0000a656, 0x0000a657, 0x00000391, 0x000003b1, - 0x00000120, 0x00000121, 0x00000508, 0x00000509, - 0x000001ca, 0x000001cc, 0x00010418, 0x00010440, - 0x0000a748, 0x0000a749, 0x00001efc, 0x00001efd, - 0x00001eb8, 0x00001eb9, 0x00010ca4, 0x00010ce4, - 0x00000179, 0x0000017a, 0x00000056, 0x00000076, - 0x00000472, 0x00000473, 0x00010416, 0x0001043e, - 0x00010c9b, 0x00010cdb, 0x0001058e, 0x000105b5, - 0x00010d63, 0x00010d83, 0x00001ed4, 0x00001ed5, - 0x00001ef8, 0x00001ef9, 0x00001e7c, 0x00001e7d, - 0x00001f69, 0x00001f61, 0x0001e921, 0x0001e943, - 0x000003a8, 0x000003c8, 0x00001fbb, 0x00001f71, - 0x00001fda, 0x00001f76, 0x00000041, 0x00000061, - 0x0001040f, 0x00010437, 0x0000048e, 0x0000048f, - 0x00000059, 0x00000079, 0x00000528, 0x00000529, - 0x00010d64, 0x00010d84, 0x00001e3c, 0x00001e3d, - 0x00000419, 0x00000439, 0x00001f3b, 0x00001f33, - 0x000013f0, 0x000013f8, 0x0000a7f5, 0x0000a7f6, - 0x000013dc, 0x0000abac, 0x00002cba, 0x00002cbb, - 0x00000464, 0x00000465, 0x00000166, 0x00000167, - 0x00001ca6, 0x000010e6, 0x00010578, 0x0001059f, - 0x00001fd9, 0x00001fd1, 0x0000054c, 0x0000057c, - 0x00001e68, 0x00001e69, 0x0000a690, 0x0000a691, - 0x0000a7b8, 0x0000a7b9, 0x0000a73a, 0x0000a73b, - 0x00001fbc, 0x00001fb3, 0x00001c93, 0x000010d3, - 0x000004c0, 0x000004cf, 0x00001ca2, 0x000010e2, - 0x00001c96, 0x000010d6, 0x000010c4, 0x00002d24, - 0x000000da, 0x000000fa, 0x000004e6, 0x000004e7, - 0x00000397, 0x000003b7, 0x00000531, 0x00000561, - 0x00001e94, 0x00001e95, 0x000013c8, 0x0000ab98, - 0x0000018b, 0x0000018c, 0x0001e90d, 0x0001e92f, - 0x00002c70, 0x00000252, 0x000010a0, 0x00002d00, - 0x000010ad, 0x00002d0d, 0x00001ea8, 0x00001ea9, - 0x000001f1, 0x000001f3, 0x000010a2, 0x00002d02, - 0x000000c8, 0x000000e8, 0x0000053a, 0x0000056a, - 0x00001e36, 0x00001e37, 0x0000013d, 0x0000013e, - 0x0000021c, 0x0000021d, 0x0001058d, 0x000105b4, - 0x00002c12, 0x00002c42, 0x000013ab, 0x0000ab7b, - 0x00000370, 0x00000371, 0x00010592, 0x000105b9, - 0x00000545, 0x00000575, 0x0000a77b, 0x0000a77c, - 0x0000ff2b, 0x0000ff4b, 0x00001fac, 0x00001fa4, - 0x00001f19, 0x00001f11, 0x000104b7, 0x000104df, - 0x00001e46, 0x00001e47, 0x00010584, 0x000105ab, - 0x00000514, 0x00000515, 0x0000a73c, 0x0000a73d, - 0x00001fcc, 0x00001fc3, 0x00002c0e, 0x00002c3e, - 0x0001e91e, 0x0001e940, 0x00002cc8, 0x00002cc9, - 0x0000ff34, 0x0000ff54, 0x0000ff2a, 0x0000ff4a, - 0x000118ba, 0x000118da, 0x0000047a, 0x0000047b, - 0x00010423, 0x0001044b, 0x00000132, 0x00000133, - 0x000104cd, 0x000104f5, 0x000001fe, 0x000001ff, - 0x00000504, 0x00000505, 0x0000a756, 0x0000a757, - 0x00010ca0, 0x00010ce0, 0x0000a786, 0x0000a787, - 0x00001f5b, 0x00001f53, 0x000013ea, 0x0000abba, - 0x00002cf2, 0x00002cf3, 0x0000047e, 0x0000047f, - 0x00000408, 0x00000458, 0x00016e46, 0x00016e66, - 0x00000176, 0x00000177, 0x0000041a, 0x0000043a, - 0x00002c1b, 0x00002c4b, 0x000001e6, 0x000001e7, - 0x00001e0e, 0x00001e0f, 0x000024c3, 0x000024dd, - 0x0000a764, 0x0000a765, 0x000004c7, 0x000004c8, - 0x00001cb8, 0x000010f8, 0x000013d5, 0x0000aba5, - 0x0000038a, 0x000003af, 0x00000417, 0x00000437, - 0x00001ebe, 0x00001ebf, 0x00000548, 0x00000578, - 0x00010ca9, 0x00010ce9, 0x00001ee6, 0x00001ee7, - 0x0000a644, 0x0000a645, 0x000003a0, 0x000003c0, - 0x0001057f, 0x000105a6, 0x00002cc2, 0x00002cc3, - 0x000013b0, 0x0000ab80, 0x000013be, 0x0000ab8e, - 0x00002cbe, 0x00002cbf, 0x00000426, 0x00000446, - 0x0000054d, 0x0000057d, 0x000013a3, 0x0000ab73, - 0x0001041d, 0x00010445, 0x000000c9, 0x000000e9, - 0x00010c89, 0x00010cc9, 0x00000401, 0x00000451, - 0x00010571, 0x00010598, 0x00001f49, 0x00001f41, - 0x0000a732, 0x0000a733, 0x00001fa8, 0x00001fa0, - 0x00001e7a, 0x00001e7b, 0x0000012a, 0x0000012b, - 0x000024be, 0x000024d8, 0x00001e18, 0x00001e19, - 0x000004f8, 0x000004f9, 0x0000010a, 0x0000010b, - 0x000004b2, 0x000004b3, 0x00002163, 0x00002173, - 0x000010a1, 0x00002d01, 0x000104c3, 0x000104eb, - 0x000001ec, 0x000001ed, 0x0000020e, 0x0000020f, - 0x0000a746, 0x0000a747, 0x00000403, 0x00000453, - 0x00000241, 0x00000242, 0x00001e16, 0x00001e17, - 0x000003ea, 0x000003eb, 0x00000055, 0x00000075, - 0x00000476, 0x00000477, 0x000013ef, 0x0000abbf, - 0x000010c7, 0x00002d27, 0x00000154, 0x00000155, - 0x00000145, 0x00000146, 0x000001a7, 0x000001a8, - 0x00000126, 0x00000127, 0x000004be, 0x000004bf, - 0x0000a7a0, 0x0000a7a1, 0x000010a6, 0x00002d06, - 0x000024bb, 0x000024d5, 0x00001eca, 0x00001ecb, - 0x000010b7, 0x00002d17, 0x00001c99, 0x000010d9, - 0x000118af, 0x000118cf, 0x0000049e, 0x0000049f, - 0x000000d6, 0x000000f6, 0x00010585, 0x000105ac, - 0x00010d61, 0x00010d81, 0x00001e84, 0x00001e85, - 0x00001ef0, 0x00001ef1, 0x0000ff21, 0x0000ff41, - 0x00001ca7, 0x000010e7, 0x0000a7a4, 0x0000a7a5, - 0x000013bc, 0x0000ab8c, 0x0000ff32, 0x0000ff52, - 0x00002c1a, 0x00002c4a, 0x000013d9, 0x0000aba9, - 0x000004d2, 0x000004d3, 0x00002c6d, 0x00000251, - 0x00010403, 0x0001042b, 0x00000550, 0x00000580, - 0x0000a664, 0x0000a665, 0x00001f08, 0x00001f00, - 0x0000a740, 0x0000a741, 0x00000466, 0x00000467, - 0x00001f98, 0x00001f90, 0x00002c04, 0x00002c34, - 0x00002cca, 0x00002ccb, 0x000013dd, 0x0000abad, - 0x0000042e, 0x0000044e, 0x00000424, 0x00000444, - 0x0000039a, 0x000003ba, 0x000104c8, 0x000104f0, - 0x00000152, 0x00000153, 0x00010406, 0x0001042e, - 0x00001e90, 0x00001e91, 0x0000a692, 0x0000a693, - 0x00001f4b, 0x00001f43, 0x0000a74c, 0x0000a74d, - 0x00002c02, 0x00002c32, 0x00002c62, 0x0000026b, - 0x000003fa, 0x000003fb, 0x00000245, 0x0000028c, - 0x00001c91, 0x000010d1, 0x00000474, 0x00000475, - 0x00010cb0, 0x00010cf0, 0x00010413, 0x0001043b, - 0x000001f7, 0x000001bf, 0x00010420, 0x00010448, - 0x00001eda, 0x00001edb, 0x000104ca, 0x000104f2, - 0x000013cb, 0x0000ab9b, 0x0000a790, 0x0000a791, - 0x00016e5c, 0x00016e7c, 0x00002c98, 0x00002c99, - 0x00010c94, 0x00010cd4, 0x000003a7, 0x000003c7, - 0x0000004b, 0x0000006b, 0x000118a1, 0x000118c1, - 0x00001f6b, 0x00001f63, 0x00010cb2, 0x00010cf2, - 0x00001e44, 0x00001e45, 0x000104c0, 0x000104e8, - 0x00001eee, 0x00001eef, 0x0000023a, 0x00002c65, - 0x000104c6, 0x000104ee, 0x00002c26, 0x00002c56, - 0x0000040e, 0x0000045e, 0x0000038e, 0x000003cd, - 0x00001ca0, 0x000010e0, 0x0000ff2f, 0x0000ff4f, - 0x00001e14, 0x00001e15, 0x000004e2, 0x000004e3, - 0x0000040a, 0x0000045a, 0x0000011c, 0x0000011d, - 0x0000053e, 0x0000056e, 0x00001e5e, 0x00001e5f, - 0x00001f3a, 0x00001f32, 0x00016e50, 0x00016e70, - 0x0000a7ac, 0x00000261, 0x000104c4, 0x000104ec, - 0x0000a65e, 0x0000a65f, 0x0000216d, 0x0000217d, - 0x000024cc, 0x000024e6, 0x00016e54, 0x00016e74, - 0x000000c6, 0x000000e6, 0x00000518, 0x00000519, - 0x00001fad, 0x00001fa5, 0x00000524, 0x00000525, - 0x0000053c, 0x0000056c, 0x00001ea2, 0x00001ea3, - 0x00002c88, 0x00002c89, 0x00001f4c, 0x00001f44, - 0x0000a76a, 0x0000a76b, 0x00002c7e, 0x0000023f, - 0x000000d9, 0x000000f9, 0x00001ca8, 0x000010e8, - 0x00016e44, 0x00016e64, 0x000004a6, 0x000004a7, - 0x000118a3, 0x000118c3, 0x00010cad, 0x00010ced, - 0x0000052c, 0x0000052d, 0x0000015e, 0x0000015f, - 0x0000a7bc, 0x0000a7bd, 0x00002c09, 0x00002c39, - 0x000004dc, 0x000004dd, 0x0000a7a6, 0x0000a7a7, - 0x000013b4, 0x0000ab84, 0x000001db, 0x000001dc, - 0x00016e4f, 0x00016e6f, 0x00000406, 0x00000456, - 0x00000147, 0x00000148, 0x00000058, 0x00000078, - 0x00002c19, 0x00002c49, 0x00000102, 0x00000103, - 0x0001040a, 0x00010432, 0x000001ac, 0x000001ad, - 0x000001a4, 0x000001a5, 0x0000017b, 0x0000017c, - 0x0000a73e, 0x0000a73f, 0x000013bb, 0x0000ab8b, - 0x00002c2c, 0x00002c5c, 0x000013c0, 0x0000ab90, - 0x00001c95, 0x000010d5, 0x00001c90, 0x000010d0, - 0x00016e40, 0x00016e60, 0x000010b2, 0x00002d12, - 0x000118b5, 0x000118d5, 0x0000a68c, 0x0000a68d, - 0x000004fe, 0x000004ff, 0x00001e8e, 0x00001e8f, - 0x0000053b, 0x0000056b, 0x00001f38, 0x00001f30, - 0x00001f3f, 0x00001f37, 0x00001eb4, 0x00001eb5, - 0x000003a4, 0x000003c4, 0x0001e90e, 0x0001e930, - 0x0000ff23, 0x0000ff43, 0x000024c4, 0x000024de, - 0x000004b4, 0x000004b5, 0x000000d2, 0x000000f2, - 0x000010c5, 0x00002d25, 0x00000460, 0x00000461, - 0x0000015a, 0x0000015b, 0x00001ea6, 0x00001ea7, - 0x00000118, 0x00000119, 0x00010591, 0x000105b8, - 0x0000023b, 0x0000023c, 0x0000a77e, 0x0000a77f, - 0x0001e912, 0x0001e934, 0x000024cf, 0x000024e9, - 0x000003e8, 0x000003e9, 0x00000044, 0x00000064, - 0x000004ac, 0x000004ad, 0x000024b7, 0x000024d1, - 0x000000cc, 0x000000ec, 0x0000a7ab, 0x0000025c, - 0x0000019f, 0x00000275, 0x000010c3, 0x00002d23, - 0x0000a7b4, 0x0000a7b5, 0x00001ffa, 0x00001f7c, - 0x000013a5, 0x0000ab75, 0x0000041e, 0x0000043e, - 0x000013ba, 0x0000ab8a, 0x00016e51, 0x00016e71, - 0x00016e43, 0x00016e63, 0x00001f8b, 0x00001f83, - 0x00002183, 0x00002184, 0x000104bd, 0x000104e5, - 0x00000191, 0x00000192, 0x00000539, 0x00000569, - 0x00001e64, 0x00001e65, 0x00016e52, 0x00016e72, - 0x00000143, 0x00000144, 0x0000a738, 0x0000a739, - 0x00001fb8, 0x00001fb0, 0x00001f2c, 0x00001f24, - 0x000013de, 0x0000abae, 0x00010c84, 0x00010cc4, - 0x00001f9f, 0x00001f97, 0x00001f0f, 0x00001f07, - 0x00010c91, 0x00010cd1, 0x00001e28, 0x00001e29, - 0x0000013b, 0x0000013c, 0x0000a64a, 0x0000a64b, - 0x000001bc, 0x000001bd, 0x000013d2, 0x0000aba2, - 0x0000a762, 0x0000a763, 0x000013b2, 0x0000ab82, - 0x00002c0a, 0x00002c3a, 0x00001f1b, 0x00001f13, - 0x000001af, 0x000001b0, 0x00001ca1, 0x000010e1, - 0x0001e918, 0x0001e93a, 0x0000216f, 0x0000217f, - 0x000000c4, 0x000000e4, 0x00000538, 0x00000568, - 0x00000172, 0x00000173, 0x00010d57, 0x00010d77, - 0x00000218, 0x00000219, 0x000118ae, 0x000118ce, - 0x00010581, 0x000105a8, 0x00001f2e, 0x00001f26, - 0x000001b7, 0x00000292, 0x00000187, 0x00000188, - 0x0000040b, 0x0000045b, 0x000010be, 0x00002d1e, - 0x00002162, 0x00002172, 0x000118ad, 0x000118cd, - 0x0001e907, 0x0001e929, 0x000104b1, 0x000104d9, - 0x00001e26, 0x00001e27, 0x00010575, 0x0001059c, - 0x00016e5e, 0x00016e7e, 0x00001ef4, 0x00001ef5, - 0x00001caa, 0x000010ea, 0x00002c08, 0x00002c38, - 0x00016e5a, 0x00016e7a, 0x000003cf, 0x000003d7, - 0x00016e53, 0x00016e73, 0x000013c9, 0x0000ab99, - 0x00001e8a, 0x00001e8b, 0x0000a7cc, 0x0000a7cd, - 0x00000042, 0x00000062, 0x00002c03, 0x00002c33, - 0x000104c5, 0x000104ed, 0x00001e6e, 0x00001e6f, - 0x00001f1a, 0x00001f12, 0x00001f18, 0x00001f10, - 0x00010d62, 0x00010d82, 0x00001fae, 0x00001fa6, - 0x00001cb4, 0x000010f4, 0x000013e4, 0x0000abb4, - 0x0000ff33, 0x0000ff53, 0x00000537, 0x00000567, - 0x0000017d, 0x0000017e, 0x00010426, 0x0001044e, - 0x000024c5, 0x000024df, 0x00000168, 0x00000169, - 0x00001e9e, 0x000000df, 0x000001e0, 0x000001e1, - 0x0001e908, 0x0001e92a, 0x00002c27, 0x00002c57, - 0x0001e911, 0x0001e933, 0x00000108, 0x00000109, - 0x000001d5, 0x000001d6, 0x00002c00, 0x00002c30, - 0x000013c7, 0x0000ab97, 0x00000196, 0x00000269, - 0x000004a0, 0x000004a1, 0x000000ce, 0x000000ee, - 0x00010cb1, 0x00010cf1, 0x00000178, 0x000000ff, - 0x00010d53, 0x00010d73, 0x00000222, 0x00000223, - 0x0000010c, 0x0000010d, 0x00010404, 0x0001042c, - 0x0000a792, 0x0000a793, 0x00000376, 0x00000377, - 0x00002c1f, 0x00002c4f, 0x00000420, 0x00000440, - 0x000118b8, 0x000118d8, 0x00010d56, 0x00010d76, - 0x000004a4, 0x000004a5, 0x00001ffc, 0x00001ff3, - 0x000104c7, 0x000104ef, 0x0000a69a, 0x0000a69b, - 0x00010c87, 0x00010cc7, 0x00001ebc, 0x00001ebd, - 0x0000012c, 0x0000012d, 0x000013b7, 0x0000ab87, - 0x0000a7dc, 0x0000019b, 0x000013ca, 0x0000ab9a, - 0x00010c83, 0x00010cc3, 0x0000212b, 0x000000e5, - 0x0000216b, 0x0000217b, 0x00000405, 0x00000455, - 0x00002c25, 0x00002c55, 0x000001d9, 0x000001da, - 0x00000160, 0x00000161, 0x00001f28, 0x00001f20, - 0x00000186, 0x00000254, 0x00000543, 0x00000573, - 0x0000024e, 0x0000024f, 0x00001f89, 0x00001f81, - 0x00001c9d, 0x000010dd, 0x000010ac, 0x00002d0c, - 0x00002c63, 0x00001d7d, 0x00000052, 0x00000072, - 0x000118b7, 0x000118d7, 0x0000ff2c, 0x0000ff4c, - 0x00010c97, 0x00010cd7, 0x000013db, 0x0000abab, - 0x00000156, 0x00000157, 0x000013d3, 0x0000aba3, - 0x0000a660, 0x0000a661, 0x000013f2, 0x000013fa, - 0x000003f9, 0x000003f2, 0x00001f6c, 0x00001f64, - 0x00002c96, 0x00002c97, 0x00001ec2, 0x00001ec3, - 0x000003fe, 0x0000037c, 0x00001f09, 0x00001f01, - 0x0001041b, 0x00010443, 0x000000cb, 0x000000eb, - 0x000104b5, 0x000104dd, 0x00002c1d, 0x00002c4d, - 0x00001e3a, 0x00001e3b, 0x00002ced, 0x00002cee, - 0x0000a666, 0x0000a667, 0x0000a7d0, 0x0000a7d1, - 0x00001f8e, 0x00001f86, 0x000013d0, 0x0000aba0, - 0x00016e4e, 0x00016e6e, 0x00002cb2, 0x00002cb3, - 0x0000ff2d, 0x0000ff4d, 0x000010a7, 0x00002d07, - 0x00002160, 0x00002170, 0x00002164, 0x00002174, - 0x0000011a, 0x0000011b, 0x000104d1, 0x000104f9, - 0x0000a696, 0x0000a697, 0x0000041b, 0x0000043b, - 0x00001f3d, 0x00001f35, 0x00000226, 0x00000227, - 0x00001e06, 0x00001e07, 0x00002c2a, 0x00002c5a, - 0x000013a4, 0x0000ab74, 0x00002cd4, 0x00002cd5, - 0x00001c92, 0x000010d2, 0x00000429, 0x00000449, - 0x000000dc, 0x000000fc, 0x00010410, 0x00010438, - 0x000010bf, 0x00002d1f, 0x000104ba, 0x000104e2, - 0x000001ee, 0x000001ef, 0x00001cb7, 0x000010f7, - 0x00001eba, 0x00001ebb, 0x00010590, 0x000105b7, - 0x00001e10, 0x00001e11, 0x000003ee, 0x000003ef, - 0x000118b6, 0x000118d6, 0x000003de, 0x000003df, - 0x00000045, 0x00000065, 0x000013ad, 0x0000ab7d, - 0x000010b3, 0x00002d13, 0x00000532, 0x00000562, - 0x00001ec6, 0x00001ec7, 0x00000158, 0x00000159, - 0x00000216, 0x00000217, 0x00000202, 0x00000203, - 0x00010c82, 0x00010cc2, 0x00001e0a, 0x00001e0b, - 0x0001e919, 0x0001e93b, 0x000104c2, 0x000104ea, - 0x00002c0b, 0x00002c3b, 0x00000400, 0x00000450, - 0x00000046, 0x00000066, 0x000004aa, 0x000004ab, - 0x00000197, 0x00000268, 0x00000554, 0x00000584, - 0x00001e2e, 0x00001e2f, 0x00001e2a, 0x00001e2b, - 0x00000425, 0x00000445, 0x00001efe, 0x00001eff, - 0x00000421, 0x00000441, 0x00002c06, 0x00002c36, - 0x000013d6, 0x0000aba6, 0x000013a0, 0x0000ab70, - 0x00016e4b, 0x00016e6b, 0x000004b6, 0x000004b7, - 0x00010580, 0x000105a7, 0x0000010e, 0x0000010f, - 0x000013e5, 0x0000abb5, 0x00002c13, 0x00002c43, - 0x000010b9, 0x00002d19, 0x0000a68e, 0x0000a68f, - 0x00001f5f, 0x00001f57, 0x000000c1, 0x000000e1, - 0x000004e4, 0x000004e5, 0x0000037f, 0x000003f3, - 0x00002c14, 0x00002c44, 0x000000c3, 0x000000e3, - 0x00002cd6, 0x00002cd7, 0x0000046e, 0x0000046f, - 0x00002c8c, 0x00002c8d, 0x00001ca4, 0x000010e4, - 0x00000500, 0x00000501, 0x0000a780, 0x0000a781, - 0x00010c98, 0x00010cd8, 0x00000181, 0x00000253, - 0x00010c86, 0x00010cc6, 0x00001e52, 0x00001e53, - 0x0000a766, 0x0000a767, 0x0001041a, 0x00010442, - 0x0000ff29, 0x0000ff49, 0x00000141, 0x00000142, - 0x000003da, 0x000003db, 0x0000004d, 0x0000006d, - 0x000010aa, 0x00002d0a, 0x000001cf, 0x000001d0, - 0x0000052e, 0x0000052f, 0x00001e34, 0x00001e35, - 0x0000a640, 0x0000a641, 0x0000a72a, 0x0000a72b, - 0x00000204, 0x00000205, 0x00002c10, 0x00002c40, - 0x00010400, 0x00010428, 0x000013d1, 0x0000aba1, - 0x00002c9c, 0x00002c9d, 0x0000ff27, 0x0000ff47, - 0x00000402, 0x00000452, 0x00016e5d, 0x00016e7d, - 0x000118a7, 0x000118c7, 0x00000407, 0x00000457, - 0x00000556, 0x00000586, 0x00001e4a, 0x00001e4b, - 0x0000a648, 0x0000a649, 0x00001e24, 0x00001e25, - 0x000013eb, 0x0000abbb, 0x000001c5, 0x000001c6, - 0x00001f8a, 0x00001f82, 0x0001e91f, 0x0001e941, - 0x00002cb4, 0x00002cb5, 0x000003fd, 0x0000037b, - 0x000013c1, 0x0000ab91, 0x00001cb0, 0x000010f0, - 0x00010570, 0x00010597, 0x00001cb6, 0x000010f6, - 0x000000d3, 0x000000f3, 0x0000a66a, 0x0000a66b, - 0x00000184, 0x00000185, 0x000013b9, 0x0000ab89, - 0x00000541, 0x00000571, 0x00002c05, 0x00002c35, - 0x00001f4d, 0x00001f45, 0x0000a7c9, 0x0000a7ca, - 0x000003d8, 0x000003d9, 0x000024c6, 0x000024e0, - 0x0000042c, 0x0000044c, 0x00000542, 0x00000572, - 0x0000051c, 0x0000051d, 0x00000546, 0x00000576, - 0x0001041c, 0x00010444, 0x000004fa, 0x000004fb, - 0x000001ea, 0x000001eb, 0x000104b8, 0x000104e0, - 0x00001e86, 0x00001e87, 0x0001e909, 0x0001e92b, - 0x0001e90f, 0x0001e931, 0x000024c2, 0x000024dc, - 0x00016e59, 0x00016e79, 0x00010d60, 0x00010d80, - 0x00010411, 0x00010439, 0x000004c9, 0x000004ca, - 0x000104bb, 0x000104e3, 0x00000526, 0x00000527, - 0x00010d65, 0x00010d85, 0x00001ef2, 0x00001ef3, - 0x0000a7cb, 0x00000264, 0x0000a7c6, 0x00001d8e, - 0x00002c2e, 0x00002c5e, 0x000013a8, 0x0000ab78, - 0x00002ca2, 0x00002ca3, 0x00002cb0, 0x00002cb1, - 0x0001058a, 0x000105b1, 0x000010cd, 0x00002d2d, - 0x000104d2, 0x000104fa, 0x00001cab, 0x000010eb, - 0x0000039f, 0x000003bf, 0x00001e74, 0x00001e75, - 0x00001ef6, 0x00001ef7, 0x00010424, 0x0001044c, - 0x00001f0e, 0x00001f06, 0x0000a734, 0x0000a735, - 0x0000039c, 0x000003bc, 0x000003a6, 0x000003c6, - 0x000013da, 0x0000abaa, 0x00002c18, 0x00002c48, - 0x00001c94, 0x000010d4, 0x000024c7, 0x000024e1, - 0x00016e48, 0x00016e68, 0x0000a75a, 0x0000a75b, - 0x000004ea, 0x000004eb, 0x00000134, 0x00000135, - 0x00000182, 0x00000183, 0x000001de, 0x000001df, - 0x00001f3c, 0x00001f34, 0x00000547, 0x00000577, - 0x00002c94, 0x00002c95, 0x000013f1, 0x000013f9, - 0x00000243, 0x00000180, 0x00001c9e, 0x000010de, - 0x00016e5b, 0x00016e7b, 0x000118be, 0x000118de, - 0x00002c6b, 0x00002c6c, 0x00010c93, 0x00010cd3, - 0x0000016e, 0x0000016f, 0x0000a7b0, 0x0000029e, - 0x00001f9b, 0x00001f93, 0x0000a7b6, 0x0000a7b7, - 0x000003aa, 0x000003ca, 0x000003a3, 0x000003c3, - 0x0001e910, 0x0001e932, 0x00002caa, 0x00002cab, - 0x0000ff37, 0x0000ff57, 0x000001b2, 0x0000028b, - 0x00000048, 0x00000068, 0x00010407, 0x0001042f, - 0x000004d6, 0x000004d7, 0x000001b8, 0x000001b9, - 0x0000019c, 0x0000026f, 0x00001e02, 0x00001e03, - 0x00000139, 0x0000013a, 0x00001eec, 0x00001eed, - 0x00010589, 0x000105b0, 0x00001f9e, 0x00001f96, - 0x0001e901, 0x0001e923, 0x000013e0, 0x0000abb0, - 0x0000ff3a, 0x0000ff5a, 0x00002c11, 0x00002c41, - 0x00000054, 0x00000074, 0x00010419, 0x00010441, - 0x00000124, 0x00000125, 0x00002ceb, 0x00002cec, - 0x00010c8a, 0x00010cca, 0x0000018e, 0x000001dd, - 0x00010ca8, 0x00010ce8, 0x0000042f, 0x0000044f, - 0x0000ff2e, 0x0000ff4e, 0x000118ac, 0x000118cc, - 0x0000a74e, 0x0000a74f, 0x0000038c, 0x000003cc, - 0x00002cce, 0x00002ccf, 0x00016e57, 0x00016e77, - 0x00000540, 0x00000570, 0x0000052a, 0x0000052b, - 0x00001eb2, 0x00001eb3, 0x0000014c, 0x0000014d, - 0x00001e08, 0x00001e09, 0x0000039b, 0x000003bb, - 0x00000553, 0x00000583, 0x00001fab, 0x00001fa3, - 0x000104be, 0x000104e6, 0x00001ff8, 0x00001f78, - 0x000003ab, 0x000003cb, 0x000004c1, 0x000004c2, - 0x00010408, 0x00010430, 0x000004b0, 0x000004b1, - 0x00002cc4, 0x00002cc5, 0x00010ca3, 0x00010ce3, - 0x000013c5, 0x0000ab95, 0x00001e6a, 0x00001e6b, - 0x00010d51, 0x00010d71, 0x00001edc, 0x00001edd, - 0x0001e90a, 0x0001e92c, 0x00002c22, 0x00002c52, - 0x0000a798, 0x0000a799, 0x00002cb8, 0x00002cb9, - 0x00000410, 0x00000430, 0x00000398, 0x000003b8, - 0x0000050c, 0x0000050d, 0x0000005a, 0x0000007a, + 0x00000050, 0x00000070, 0x000004a8, 0x000004a9, + 0x000000c8, 0x000000e8, 0x000001c4, 0x000001c6, + 0x00002c03, 0x00002c33, 0x00000537, 0x00000567, + 0x00001e0e, 0x00001e0f, 0x00010420, 0x00010448, + 0x0000ff3a, 0x0000ff5a, 0x00016e5c, 0x00016e7c, + 0x00001f38, 0x00001f30, 0x00010d5e, 0x00010d7e, + 0x00001e5c, 0x00001e5d, 0x00010416, 0x0001043e, + 0x000010c1, 0x00002d21, 0x0000a666, 0x0000a667, + 0x0001e920, 0x0001e942, 0x00000492, 0x00000493, + 0x00001f8a, 0x00001f82, 0x000004da, 0x000004db, + 0x000000ca, 0x000000ea, 0x0000042d, 0x0000044d, + 0x00001e4c, 0x00001e4d, 0x00002cd0, 0x00002cd1, + 0x0000a72e, 0x0000a72f, 0x000118ba, 0x000118da, + 0x00000549, 0x00000579, 0x000004e0, 0x000004e1, + 0x00010c88, 0x00010cc8, 0x0000039f, 0x000003bf, + 0x00001caa, 0x000010ea, 0x00002c96, 0x00002c97, + 0x000013f0, 0x000013f8, 0x00000397, 0x000003b7, + 0x00001e0a, 0x00001e0b, 0x000001fe, 0x000001ff, + 0x00001e48, 0x00001e49, 0x000104cb, 0x000104f3, + 0x00001e86, 0x00001e87, 0x00010caf, 0x00010cef, + 0x00001f09, 0x00001f01, 0x00016eae, 0x00016ec9, + 0x0000019d, 0x00000272, 0x00002c2e, 0x00002c5e, + 0x0000a7bc, 0x0000a7bd, 0x000001d5, 0x000001d6, + 0x000000cf, 0x000000ef, 0x0000a644, 0x0000a645, + 0x0000a7b4, 0x0000a7b5, 0x000104c1, 0x000104e9, + 0x00001f3f, 0x00001f37, 0x000013a9, 0x0000ab79, + 0x0000a77d, 0x00001d79, 0x00001fc9, 0x00001f73, + 0x0000054b, 0x0000057b, 0x0000a65e, 0x0000a65f, + 0x000013cd, 0x0000ab9d, 0x00000370, 0x00000371, + 0x0000053c, 0x0000056c, 0x00010c85, 0x00010cc5, + 0x0000a726, 0x0000a727, 0x000001e0, 0x000001e1, + 0x00010414, 0x0001043c, 0x00000179, 0x0000017a, + 0x00002c16, 0x00002c46, 0x0000017d, 0x0000017e, + 0x000104bb, 0x000104e3, 0x00000222, 0x00000223, + 0x00016e55, 0x00016e75, 0x0000014c, 0x0000014d, + 0x00001fa9, 0x00001fa1, 0x000000cc, 0x000000ec, + 0x000013cc, 0x0000ab9c, 0x00001cad, 0x000010ed, + 0x0000049a, 0x0000049b, 0x0001057d, 0x000105a4, + 0x000118a0, 0x000118c0, 0x000000da, 0x000000fa, + 0x00000241, 0x00000242, 0x0000018b, 0x0000018c, + 0x000013a6, 0x0000ab76, 0x000003dc, 0x000003dd, + 0x00001cac, 0x000010ec, 0x000000c2, 0x000000e2, + 0x00002c10, 0x00002c40, 0x000004fe, 0x000004ff, + 0x00010592, 0x000105b9, 0x00000508, 0x00000509, + 0x00001e68, 0x00001e69, 0x00016e52, 0x00016e72, + 0x00016ea8, 0x00016ec3, 0x000004ec, 0x000004ed, + 0x00016eab, 0x00016ec6, 0x000001e2, 0x000001e3, + 0x00000543, 0x00000573, 0x00001fec, 0x00001fe5, + 0x00010584, 0x000105ab, 0x00016e59, 0x00016e79, + 0x00000534, 0x00000564, 0x000013e5, 0x0000abb5, + 0x00010d59, 0x00010d79, 0x00001ef2, 0x00001ef3, + 0x00016e5f, 0x00016e7f, 0x00001ebe, 0x00001ebf, + 0x000024ca, 0x000024e4, 0x0000ff2a, 0x0000ff4a, + 0x00010419, 0x00010441, 0x00000478, 0x00000479, + 0x0000a652, 0x0000a653, 0x00001ef6, 0x00001ef7, + 0x00010411, 0x00010439, 0x00001ffa, 0x00001f7c, + 0x000004d6, 0x000004d7, 0x00001fb8, 0x00001fb0, + 0x00000405, 0x00000455, 0x00000545, 0x00000575, + 0x000004d2, 0x000004d3, 0x0000216a, 0x0000217a, + 0x000003fe, 0x0000037c, 0x00001e3a, 0x00001e3b, + 0x00016eb8, 0x00016ed3, 0x00002c09, 0x00002c39, + 0x000118b5, 0x000118d5, 0x00001f1d, 0x00001f15, + 0x00010ca9, 0x00010ce9, 0x00001f8d, 0x00001f85, + 0x00000399, 0x000003b9, 0x00001e92, 0x00001e93, + 0x000004d8, 0x000004d9, 0x0000a766, 0x0000a767, + 0x00002cba, 0x00002cbb, 0x00000041, 0x00000061, + 0x00010d5a, 0x00010d7a, 0x0000a64e, 0x0000a64f, + 0x00000106, 0x00000107, 0x00001ec8, 0x00001ec9, + 0x00001cb8, 0x000010f8, 0x00016eb3, 0x00016ece, + 0x00000500, 0x00000501, 0x00001faa, 0x00001fa2, + 0x00016e49, 0x00016e69, 0x0000a7c6, 0x00001d8e, + 0x000001b5, 0x000001b6, 0x00001f08, 0x00001f00, + 0x000001f4, 0x000001f5, 0x00016eb1, 0x00016ecc, + 0x00002c6d, 0x00000251, 0x000104c7, 0x000104ef, + 0x00010c86, 0x00010cc6, 0x000010a9, 0x00002d09, + 0x00002cf2, 0x00002cf3, 0x00001ca3, 0x000010e3, + 0x0000a750, 0x0000a751, 0x0000a79c, 0x0000a79d, + 0x00001f3b, 0x00001f33, 0x00001c93, 0x000010d3, + 0x000001f2, 0x000001f3, 0x00002c94, 0x00002c95, + 0x00000126, 0x00000127, 0x00010574, 0x0001059b, + 0x00001edc, 0x00001edd, 0x00001f8f, 0x00001f87, + 0x00000174, 0x00000175, 0x00001e2a, 0x00001e2b, + 0x00002ca0, 0x00002ca1, 0x0000a748, 0x0000a749, + 0x00000498, 0x00000499, 0x00010572, 0x00010599, + 0x000001cd, 0x000001ce, 0x00001ec2, 0x00001ec3, + 0x0000015c, 0x0000015d, 0x00000496, 0x00000497, + 0x00000198, 0x00000199, 0x00001e8e, 0x00001e8f, + 0x000000de, 0x000000fe, 0x000104b7, 0x000104df, + 0x00016ea7, 0x00016ec2, 0x000010a1, 0x00002d01, + 0x000003a6, 0x000003c6, 0x000000d5, 0x000000f5, + 0x00000422, 0x00000442, 0x00001e6e, 0x00001e6f, + 0x00000058, 0x00000078, 0x00000423, 0x00000443, + 0x00002c1c, 0x00002c4c, 0x00002c9e, 0x00002c9f, + 0x00000120, 0x00000121, 0x00000531, 0x00000561, + 0x00001eb8, 0x00001eb9, 0x000104b2, 0x000104da, + 0x0000a7ce, 0x0000a7cf, 0x0000052c, 0x0000052d, + 0x00001fdb, 0x00001f77, 0x000013c1, 0x0000ab91, + 0x0000a7c0, 0x0000a7c1, 0x0000042e, 0x0000044e, + 0x000010b7, 0x00002d17, 0x0000037f, 0x000003f3, + 0x00001ed4, 0x00001ed5, 0x00000494, 0x00000495, + 0x00001f4a, 0x00001f42, 0x0000a786, 0x0000a787, + 0x0000a7d2, 0x0000a7d3, 0x00010401, 0x00010429, + 0x00010c9f, 0x00010cdf, 0x0000051a, 0x0000051b, + 0x00001e62, 0x00001e63, 0x00000429, 0x00000449, + 0x00001ea6, 0x00001ea7, 0x00002c80, 0x00002c81, + 0x00001eee, 0x00001eef, 0x000004b6, 0x000004b7, + 0x00001fab, 0x00001fa3, 0x00002cc0, 0x00002cc1, + 0x00016eb6, 0x00016ed1, 0x000118a5, 0x000118c5, + 0x00001e40, 0x00001e41, 0x0000023a, 0x00002c65, + 0x000013d7, 0x0000aba7, 0x000003a8, 0x000003c8, + 0x00001e80, 0x00001e81, 0x00000122, 0x00000123, + 0x0000a642, 0x0000a643, 0x0000024a, 0x0000024b, + 0x00001e06, 0x00001e07, 0x00002160, 0x00002170, + 0x0000a7c7, 0x0000a7c8, 0x000003ec, 0x000003ed, + 0x00001f5d, 0x00001f55, 0x000013ad, 0x0000ab7d, + 0x0000a7c9, 0x0000a7ca, 0x00002c6b, 0x00002c6c, + 0x00010422, 0x0001044a, 0x00016e4b, 0x00016e6b, + 0x0000a798, 0x0000a799, 0x0000010e, 0x0000010f, + 0x0000010c, 0x0000010d, 0x00000196, 0x00000269, + 0x0000a78b, 0x0000a78c, 0x00001f2c, 0x00001f24, + 0x00010d57, 0x00010d77, 0x00010ca4, 0x00010ce4, + 0x000013d0, 0x0000aba0, 0x00002ced, 0x00002cee, + 0x00001c9c, 0x000010dc, 0x0000a74c, 0x0000a74d, + 0x0000a78d, 0x00000265, 0x000001a2, 0x000001a3, + 0x00001c89, 0x00001c8a, 0x0000216c, 0x0000217c, + 0x000010c0, 0x00002d20, 0x00002c63, 0x00001d7d, + 0x00000470, 0x00000471, 0x00000424, 0x00000444, + 0x0000a698, 0x0000a699, 0x000001ea, 0x000001eb, + 0x0000023e, 0x00002c66, 0x0001057f, 0x000105a6, + 0x000024c4, 0x000024de, 0x00000145, 0x00000146, + 0x00001efe, 0x00001eff, 0x00000232, 0x00000233, + 0x0000a680, 0x0000a681, 0x000001b1, 0x0000028a, + 0x00010400, 0x00010428, 0x00000193, 0x00000260, + 0x000024cf, 0x000024e9, 0x0000016c, 0x0000016d, + 0x00000245, 0x0000028c, 0x00000547, 0x00000577, + 0x000010b3, 0x00002d13, 0x00000134, 0x00000135, + 0x00010590, 0x000105b7, 0x00000194, 0x00000263, + 0x00002c2c, 0x00002c5c, 0x00000048, 0x00000068, + 0x00010423, 0x0001044b, 0x0000212a, 0x0000006b, + 0x00001ee0, 0x00001ee1, 0x00001f5b, 0x00001f53, + 0x00000539, 0x00000569, 0x00001fda, 0x00001f76, + 0x00010c92, 0x00010cd2, 0x0000a762, 0x0000a763, + 0x00000536, 0x00000566, 0x00000166, 0x00000167, + 0x0000a74e, 0x0000a74f, 0x0000ff25, 0x0000ff45, + 0x00010406, 0x0001042e, 0x0000041a, 0x0000043a, + 0x0000a7ab, 0x0000025c, 0x0000ff2d, 0x0000ff4d, + 0x00016ea4, 0x00016ebf, 0x00001f3e, 0x00001f36, + 0x00002cd4, 0x00002cd5, 0x0001e91f, 0x0001e941, + 0x0001041b, 0x00010443, 0x00001c99, 0x000010d9, + 0x000104d1, 0x000104f9, 0x0001e911, 0x0001e933, + 0x00016e4c, 0x00016e6c, 0x00001e34, 0x00001e35, 0x000004d4, 0x000004d5, 0x00001f0b, 0x00001f03, - 0x0000054e, 0x0000057e, 0x000001ae, 0x00000288, - 0x000013b5, 0x0000ab85, 0x0000021e, 0x0000021f, - 0x00001ee4, 0x00001ee5, 0x00000394, 0x000003b4, - 0x00002c16, 0x00002c46, 0x0001e91c, 0x0001e93e, - 0x00002cc0, 0x00002cc1, 0x00002c01, 0x00002c31, - 0x00000189, 0x00000256, 0x000000ca, 0x000000ea, - 0x00001fdb, 0x00001f77, 0x00000502, 0x00000503, - 0x000118a6, 0x000118c6, 0x000001fa, 0x000001fb, - 0x000000de, 0x000000fe, 0x000010a3, 0x00002d03, - 0x00010d5e, 0x00010d7e, 0x000004c5, 0x000004c6, - 0x00001fba, 0x00001f70, 0x0000a7a2, 0x0000a7a3, - 0x00002cd8, 0x00002cd9, 0x00002c82, 0x00002c83, - 0x00000478, 0x00000479, 0x00001f6a, 0x00001f62, - 0x00010c8e, 0x00010cce, 0x00000106, 0x00000107, - 0x000004da, 0x000004db, 0x00001e88, 0x00001e89, - 0x00001ed8, 0x00001ed9, 0x00000551, 0x00000581, - 0x000013c6, 0x0000ab96, 0x000013e8, 0x0000abb8, - 0x00002cdc, 0x00002cdd, 0x00002c0f, 0x00002c3f, - 0x00001c9b, 0x000010db, 0x00016e42, 0x00016e62, - 0x00000496, 0x00000497, 0x0000040c, 0x0000045c, - 0x000004f6, 0x000004f7, 0x00010cab, 0x00010ceb, - 0x0000015c, 0x0000015d, 0x00010d55, 0x00010d75, - 0x00001e4c, 0x00001e4d, 0x00001cad, 0x000010ed, - 0x00000248, 0x00000249, 0x000013aa, 0x0000ab7a, - 0x0001e91d, 0x0001e93f, 0x00016e45, 0x00016e65, - 0x00000404, 0x00000454, 0x00001f29, 0x00001f21, - 0x00001cb2, 0x000010f2, 0x0001041f, 0x00010447, - 0x000001cb, 0x000001cc, 0x000104c9, 0x000104f1, - 0x000010b0, 0x00002d10, 0x00010573, 0x0001059a, - 0x000024b9, 0x000024d3, 0x0000a736, 0x0000a737, - 0x00001eb0, 0x00001eb1, 0x0000a7a8, 0x0000a7a9, - 0x000013d8, 0x0000aba8, 0x000024b6, 0x000024d0, - 0x00001c98, 0x000010d8, 0x000013e7, 0x0000abb7, - 0x000001f2, 0x000001f3, 0x000118bc, 0x000118dc, - 0x0000040f, 0x0000045f, 0x00010d5c, 0x00010d7c, - 0x0000a658, 0x0000a659, 0x00010cac, 0x00010cec, - 0x0000ff24, 0x0000ff44, 0x0000a74a, 0x0000a74b, - 0x00001fea, 0x00001f7a, 0x00002c1c, 0x00002c4c, - 0x0001e904, 0x0001e926, 0x000024c8, 0x000024e2, - 0x00000116, 0x00000117, 0x00010d50, 0x00010d70, - 0x000010bc, 0x00002d1c, 0x000104d0, 0x000104f8, - 0x0000014e, 0x0000014f, 0x00010d5d, 0x00010d7d, - 0x00001e1c, 0x00001e1d, 0x00001eea, 0x00001eeb, - 0x000003a9, 0x000003c9, 0x00000415, 0x00000435, - 0x0000ff30, 0x0000ff50, 0x00010c9e, 0x00010cde, - 0x00001f68, 0x00001f60, 0x000000d1, 0x000000f1, - 0x000001cd, 0x000001ce, 0x00000480, 0x00000481, - 0x000118b1, 0x000118d1, 0x00000047, 0x00000067, - 0x000001e2, 0x000001e3, 0x00001e5a, 0x00001e5b, - 0x0000049a, 0x0000049b, 0x00001ea0, 0x00001ea1, - 0x00001fa9, 0x00001fa1, 0x00000555, 0x00000585, - 0x0001e90c, 0x0001e92e, 0x00002ca8, 0x00002ca9, - 0x0000ff36, 0x0000ff56, 0x00001f6f, 0x00001f67, - 0x00000049, 0x00000069, 0x0000049c, 0x0000049d, - 0x000013f3, 0x000013fb, 0x0000014a, 0x0000014b, - 0x0000054a, 0x0000057a, 0x0000a698, 0x0000a699, - 0x00001caf, 0x000010ef, 0x0000a742, 0x0000a743, - 0x00010582, 0x000105a9, 0x00000210, 0x00000211, - 0x000013e2, 0x0000abb2, 0x00002ccc, 0x00002ccd, - 0x00002c8e, 0x00002c8f, 0x00016e4d, 0x00016e6d, - 0x0000042a, 0x0000044a, 0x00010ca5, 0x00010ce5, - 0x00001e4e, 0x00001e4f, 0x00000100, 0x00000101, - 0x0000a7b2, 0x0000029d, 0x000013df, 0x0000abaf, - 0x0001e90b, 0x0001e92d, 0x000003f7, 0x000003f8, - 0x00010c80, 0x00010cc0, 0x00001fec, 0x00001fe5, - 0x000001b1, 0x0000028a, 0x00010594, 0x000105bb, - 0x000010c1, 0x00002d21, 0x00010d5a, 0x00010d7a, - 0x0000054f, 0x0000057f, 0x000004ec, 0x000004ed, - 0x00010583, 0x000105aa, 0x00000150, 0x00000151, - 0x00010d5b, 0x00010d7b, 0x00001ede, 0x00001edf, - 0x000004c3, 0x000004c4, 0x00000413, 0x00000433, - 0x0000a668, 0x0000a669, 0x0001e900, 0x0001e922, - 0x00000128, 0x00000129, 0x00001f59, 0x00001f51, - 0x00000492, 0x00000493, 0x00010cae, 0x00010cee, - 0x00010405, 0x0001042d, 0x00001e82, 0x00001e83, - 0x0000050e, 0x0000050f, 0x00001e48, 0x00001e49, - 0x00010579, 0x000105a0, 0x0000024c, 0x0000024d, - 0x0000a768, 0x0000a769, 0x00001fd8, 0x00001fd0, - 0x00001ee8, 0x00001ee9, 0x000013a9, 0x0000ab79, - 0x000010bb, 0x00002d1b, 0x00016e4c, 0x00016e6c, - 0x000010a4, 0x00002d04, 0x0001e91a, 0x0001e93c, - 0x00010c96, 0x00010cd6, 0x00010421, 0x00010449, - 0x00000057, 0x00000077, 0x000104cb, 0x000104f3, - 0x00010595, 0x000105bc, 0x00010c9a, 0x00010cda, - 0x0000022e, 0x0000022f, 0x00001e7e, 0x00001e7f, - 0x0000a652, 0x0000a653, 0x00010c88, 0x00010cc8, - 0x00002c7f, 0x00000240, 0x000024ce, 0x000024e8, - 0x000004f0, 0x000004f1, 0x0000041f, 0x0000043f, - 0x000104b4, 0x000104dc, 0x00002c90, 0x00002c91, - 0x00000246, 0x00000247, 0x0001040e, 0x00010436, - 0x00001ed0, 0x00001ed1, 0x00010d58, 0x00010d78, - 0x00001f2a, 0x00001f22, 0x0001e917, 0x0001e939, - 0x0000ff22, 0x0000ff42, 0x000000c7, 0x000000e7, - 0x000003e2, 0x000003e3, 0x000003dc, 0x000003dd, - 0x0000048c, 0x0000048d, 0x000118a5, 0x000118c5, - 0x00010caf, 0x00010cef, 0x00001e40, 0x00001e41, - 0x0000a752, 0x0000a753, 0x0000013f, 0x00000140, - 0x00001f6d, 0x00001f65, 0x000013cd, 0x0000ab9d, - 0x00002c0d, 0x00002c3d, 0x000013b6, 0x0000ab86, - 0x000013a7, 0x0000ab77, 0x00001f0d, 0x00001f05, - 0x000118a0, 0x000118c0, 0x00000418, 0x00000438, - 0x0000212a, 0x0000006b, 0x00010ca2, 0x00010ce2, - 0x000010b1, 0x00002d11, 0x0000a7c2, 0x0000a7c3, - 0x0000019d, 0x00000272, 0x0000050a, 0x0000050b, - 0x000118a4, 0x000118c4, 0x0000a76c, 0x0000a76d, - 0x00016e5f, 0x00016e7f, 0x00001f6e, 0x00001f66, - 0x00002161, 0x00002171, 0x00001e20, 0x00001e21, - 0x000118bb, 0x000118db, 0x0000a784, 0x0000a785, - 0x000010b6, 0x00002d16, 0x00001f2d, 0x00001f25, - 0x0001057e, 0x000105a5, 0x0000a726, 0x0000a727, - 0x00001e92, 0x00001e93, 0x0000a680, 0x0000a681, - 0x00002c6e, 0x00000271, 0x0000a744, 0x0000a745, - 0x00001e8c, 0x00001e8d, 0x00001f9d, 0x00001f95, - 0x000118bd, 0x000118dd, 0x00002c86, 0x00002c87, - 0x00000110, 0x00000111, 0x00002132, 0x0000214e, - 0x000000d8, 0x000000f8, 0x00010c95, 0x00010cd5, - 0x00001e38, 0x00001e39, 0x000024cb, 0x000024e5, - 0x00001ee2, 0x00001ee3, 0x00001ea4, 0x00001ea5, - 0x00001fc9, 0x00001f73, 0x0000a77d, 0x00001d79, - 0x000013ae, 0x0000ab7e, 0x00002c80, 0x00002c81, - 0x000104b2, 0x000104da, 0x000003f4, 0x000003b8, - 0x00000416, 0x00000436, 0x00010409, 0x00010431, - 0x00001ecc, 0x00001ecd, 0x000104b3, 0x000104db, - 0x00001eb6, 0x00001eb7, 0x00000194, 0x00000263, - 0x000000d5, 0x000000f5, 0x0000023e, 0x00002c66, - 0x00001f8f, 0x00001f87, 0x00002c1e, 0x00002c4e, - 0x0000a7da, 0x0000a7db, 0x00000392, 0x000003b2, - 0x000004ee, 0x000004ef, 0x0000ff28, 0x0000ff48, - 0x000000cd, 0x000000ed, 0x00010427, 0x0001044f, - 0x000004cd, 0x000004ce, 0x00000104, 0x00000105, - 0x00001e76, 0x00001e77, 0x000003a5, 0x000003c5, - 0x00001c89, 0x00001c8a, 0x0001058c, 0x000105b3, - 0x0001e902, 0x0001e924, 0x0000a7c7, 0x0000a7c8, - 0x00002c28, 0x00002c58, 0x00002cd0, 0x00002cd1 + 0x000004c1, 0x000004c2, 0x00001e44, 0x00001e45, + 0x00002cd8, 0x00002cd9, 0x000013ea, 0x0000abba, + 0x000118bf, 0x000118df, 0x00001e3c, 0x00001e3d, + 0x00000468, 0x00000469, 0x0001e91d, 0x0001e93f, + 0x000003a9, 0x000003c9, 0x00001f0a, 0x00001f02, + 0x00010d61, 0x00010d81, 0x0000a66c, 0x0000a66d, + 0x000010c3, 0x00002d23, 0x000013de, 0x0000abae, + 0x0000054e, 0x0000057e, 0x0000a650, 0x0000a651, + 0x00010402, 0x0001042a, 0x000013aa, 0x0000ab7a, + 0x0001058f, 0x000105b6, 0x00002c20, 0x00002c50, + 0x00016eb2, 0x00016ecd, 0x000010ad, 0x00002d0d, + 0x00010582, 0x000105a9, 0x0000a7b6, 0x0000a7b7, + 0x000001b3, 0x000001b4, 0x00001e36, 0x00001e37, + 0x00010c9c, 0x00010cdc, 0x00010c8e, 0x00010cce, + 0x00002c15, 0x00002c45, 0x00000556, 0x00000586, + 0x00010c97, 0x00010cd7, 0x0000a744, 0x0000a745, + 0x00000049, 0x00000069, 0x00001c97, 0x000010d7, + 0x00000224, 0x00000225, 0x0000a728, 0x0000a729, + 0x00000406, 0x00000456, 0x00001c95, 0x000010d5, + 0x00010caa, 0x00010cea, 0x00001ee8, 0x00001ee9, + 0x00000181, 0x00000253, 0x00001eda, 0x00001edb, + 0x000004cd, 0x000004ce, 0x0000a690, 0x0000a691, + 0x00000170, 0x00000171, 0x000004f2, 0x000004f3, + 0x00001cb7, 0x000010f7, 0x0000a7b0, 0x0000029e, + 0x00000178, 0x000000ff, 0x00001f0d, 0x00001f05, + 0x00002167, 0x00002177, 0x0000a742, 0x0000a743, + 0x0000016a, 0x0000016b, 0x00000246, 0x00000247, + 0x00016e5e, 0x00016e7e, 0x000010a5, 0x00002d05, + 0x0000004f, 0x0000006f, 0x000104bd, 0x000104e5, + 0x000003e6, 0x000003e7, 0x00001ca6, 0x000010e6, + 0x000003e2, 0x000003e3, 0x00000548, 0x00000578, + 0x0000022c, 0x0000022d, 0x00001e70, 0x00001e71, + 0x0000020e, 0x0000020f, 0x0001057e, 0x000105a5, + 0x00010583, 0x000105aa, 0x00001e30, 0x00001e31, + 0x000003e4, 0x000003e5, 0x0000053f, 0x0000056f, + 0x00001feb, 0x00001f7b, 0x000010bb, 0x00002d1b, + 0x0000a7aa, 0x00000266, 0x0000040a, 0x0000045a, + 0x00001fe8, 0x00001fe0, 0x00002c0a, 0x00002c3a, + 0x00002132, 0x0000214e, 0x00016e5d, 0x00016e7d, + 0x00001e26, 0x00001e27, 0x000024cc, 0x000024e6, + 0x0000ff24, 0x0000ff44, 0x00010403, 0x0001042b, + 0x00001eea, 0x00001eeb, 0x000024bd, 0x000024d7, + 0x00001e5a, 0x00001e5b, 0x00010418, 0x00010440, + 0x00001eb4, 0x00001eb5, 0x0000024c, 0x0000024d, + 0x00001e56, 0x00001e57, 0x0000040d, 0x0000045d, + 0x00001cb4, 0x000010f4, 0x0001e913, 0x0001e935, + 0x0000a7a8, 0x0000a7a9, 0x000118a7, 0x000118c7, + 0x000001cb, 0x000001cc, 0x00001eec, 0x00001eed, + 0x00002c69, 0x00002c6a, 0x000118a3, 0x000118c3, + 0x0000041c, 0x0000043c, 0x00001cb5, 0x000010f5, + 0x00001fbc, 0x00001fb3, 0x0000038f, 0x000003ce, + 0x00001e42, 0x00001e43, 0x00010c8a, 0x00010cca, + 0x000013ec, 0x0000abbc, 0x0000039c, 0x000003bc, + 0x000104b4, 0x000104dc, 0x00000551, 0x00000581, + 0x000013b0, 0x0000ab80, 0x0000a686, 0x0000a687, + 0x00001fc8, 0x00001f72, 0x00010d65, 0x00010d85, + 0x000104c0, 0x000104e8, 0x000001b7, 0x00000292, + 0x0000022a, 0x0000022b, 0x00016ea3, 0x00016ebe, + 0x0000a7ac, 0x00000261, 0x00016eaa, 0x00016ec5, + 0x0000053d, 0x0000056d, 0x000013bb, 0x0000ab8b, + 0x0000a7b1, 0x00000287, 0x000104b3, 0x000104db, + 0x00000476, 0x00000477, 0x0001e915, 0x0001e937, + 0x00002c1a, 0x00002c4a, 0x00000391, 0x000003b1, + 0x00001eba, 0x00001ebb, 0x000000cb, 0x000000eb, + 0x000013bc, 0x0000ab8c, 0x0000015a, 0x0000015b, + 0x00000552, 0x00000582, 0x0000017b, 0x0000017c, + 0x0000a66a, 0x0000a66b, 0x00000158, 0x00000159, + 0x000118bb, 0x000118db, 0x00002183, 0x00002184, + 0x0000a69a, 0x0000a69b, 0x0000013d, 0x0000013e, + 0x00001cb1, 0x000010f1, 0x000013e3, 0x0000abb3, + 0x0000a7a2, 0x0000a7a3, 0x0000013b, 0x0000013c, + 0x0000048a, 0x0000048b, 0x0000216d, 0x0000217d, + 0x00002c01, 0x00002c31, 0x00001e90, 0x00001e91, + 0x0000053e, 0x0000056e, 0x00000187, 0x00000188, + 0x0000a780, 0x0000a781, 0x000000dd, 0x000000fd, + 0x00000412, 0x00000432, 0x000000c4, 0x000000e4, + 0x00016eb7, 0x00016ed2, 0x000001ac, 0x000001ad, + 0x000004a2, 0x000004a3, 0x00002c2d, 0x00002c5d, + 0x00001ee4, 0x00001ee5, 0x00000046, 0x00000066, + 0x0000040c, 0x0000045c, 0x0000022e, 0x0000022f, + 0x000013a8, 0x0000ab78, 0x00000104, 0x00000105, + 0x00000540, 0x00000570, 0x00002c84, 0x00002c85, + 0x000001fc, 0x000001fd, 0x000003fd, 0x0000037b, + 0x00000538, 0x00000568, 0x00001f6a, 0x00001f62, + 0x000024b8, 0x000024d2, 0x00001fca, 0x00001f74, + 0x0000046a, 0x0000046b, 0x00001e24, 0x00001e25, + 0x000024b6, 0x000024d0, 0x0000ff2f, 0x0000ff4f, + 0x00000413, 0x00000433, 0x00001f3c, 0x00001f34, + 0x000024c1, 0x000024db, 0x00001e9e, 0x000000df, + 0x00000411, 0x00000431, 0x0000012c, 0x0000012d, + 0x000013c3, 0x0000ab93, 0x00001cab, 0x000010eb, + 0x0000042a, 0x0000044a, 0x000004e6, 0x000004e7, + 0x000004be, 0x000004bf, 0x00001fba, 0x00001f70, + 0x000004ba, 0x000004bb, 0x00001eb0, 0x00001eb1, + 0x000003a0, 0x000003c0, 0x000013b6, 0x0000ab86, + 0x000118bd, 0x000118dd, 0x00001f8c, 0x00001f84, + 0x00010d60, 0x00010d80, 0x0000a7ad, 0x0000026c, + 0x00002c13, 0x00002c43, 0x00001e08, 0x00001e09, + 0x00010c84, 0x00010cc4, 0x00001efc, 0x00001efd, + 0x00000386, 0x000003ac, 0x000000d3, 0x000000f3, + 0x00010d58, 0x00010d78, 0x00002c19, 0x00002c49, + 0x00000102, 0x00000103, 0x000010b6, 0x00002d16, + 0x00010ca0, 0x00010ce0, 0x00016e43, 0x00016e63, + 0x00000143, 0x00000144, 0x000013e1, 0x0000abb1, + 0x000104b6, 0x000104de, 0x0000a790, 0x0000a791, + 0x00000212, 0x00000213, 0x00010588, 0x000105af, + 0x000013b1, 0x0000ab81, 0x0001e912, 0x0001e934, + 0x00016e58, 0x00016e78, 0x000003a1, 0x000003c1, + 0x00010c9e, 0x00010cde, 0x0000a73a, 0x0000a73b, + 0x00000372, 0x00000373, 0x0000046e, 0x0000046f, + 0x00010cb1, 0x00010cf1, 0x0000a724, 0x0000a725, + 0x000004e8, 0x000004e9, 0x00001c9f, 0x000010df, + 0x00010404, 0x0001042c, 0x00001e52, 0x00001e53, + 0x000001e4, 0x000001e5, 0x00001ea2, 0x00001ea3, + 0x0001e900, 0x0001e922, 0x00001e54, 0x00001e55, + 0x00000154, 0x00000155, 0x000004a6, 0x000004a7, + 0x00002169, 0x00002179, 0x000013c5, 0x0000ab95, + 0x000000d8, 0x000000f8, 0x00010c82, 0x00010cc2, + 0x0001e90a, 0x0001e92c, 0x000013a4, 0x0000ab74, + 0x00002c70, 0x00000252, 0x000104b1, 0x000104d9, + 0x00000132, 0x00000133, 0x000024cd, 0x000024e7, + 0x000000d6, 0x000000f6, 0x0001058e, 0x000105b5, + 0x000104ba, 0x000104e2, 0x000013a0, 0x0000ab70, + 0x0000a7a6, 0x0000a7a7, 0x00010c81, 0x00010cc1, + 0x000104be, 0x000104e6, 0x0001e910, 0x0001e932, + 0x0000ff29, 0x0000ff49, 0x0000050e, 0x0000050f, + 0x000004e4, 0x000004e5, 0x00010c94, 0x00010cd4, + 0x00016e50, 0x00016e70, 0x00016e5b, 0x00016e7b, + 0x00016eb5, 0x00016ed0, 0x0000a754, 0x0000a755, + 0x000013a1, 0x0000ab71, 0x00000528, 0x00000529, + 0x00000244, 0x00000289, 0x000024c9, 0x000024e3, + 0x0001e90f, 0x0001e931, 0x000004a0, 0x000004a1, + 0x00001fd8, 0x00001fd0, 0x000024ba, 0x000024d4, + 0x0000ff38, 0x0000ff58, 0x00002c25, 0x00002c55, + 0x000010b5, 0x00002d15, 0x000024c7, 0x000024e1, + 0x00002cd6, 0x00002cd7, 0x0001041d, 0x00010445, + 0x000001a7, 0x000001a8, 0x00002c2b, 0x00002c5b, + 0x00001e58, 0x00001e59, 0x0000040b, 0x0000045b, + 0x00001eca, 0x00001ecb, 0x00016eaf, 0x00016eca, + 0x000013f3, 0x000013fb, 0x000003ee, 0x000003ef, + 0x000010ae, 0x00002d0e, 0x00002c86, 0x00002c87, + 0x000013c2, 0x0000ab92, 0x000118a1, 0x000118c1, + 0x00001ed0, 0x00001ed1, 0x00010d62, 0x00010d82, + 0x0000ff35, 0x0000ff55, 0x000003ab, 0x000003cb, + 0x00001e94, 0x00001e95, 0x00010ca3, 0x00010ce3, + 0x0001e909, 0x0001e92b, 0x00002c0f, 0x00002c3f, + 0x00001e8a, 0x00001e8b, 0x0000050c, 0x0000050d, + 0x0001e90b, 0x0001e92d, 0x0000a760, 0x0000a761, + 0x0000004d, 0x0000006d, 0x00001f2f, 0x00001f27, + 0x00002c1f, 0x00002c4f, 0x00002cb6, 0x00002cb7, + 0x00001e8c, 0x00001e8d, 0x0000a73e, 0x0000a73f, + 0x0000a7b8, 0x0000a7b9, 0x000004e2, 0x000004e3, + 0x0001058a, 0x000105b1, 0x0000a662, 0x0000a663, + 0x0000a79a, 0x0000a79b, 0x0000a64a, 0x0000a64b, + 0x0000048e, 0x0000048f, 0x0000a768, 0x0000a769, + 0x0000a72a, 0x0000a72b, 0x00000214, 0x00000215, + 0x00001c9e, 0x000010de, 0x000001b8, 0x000001b9, + 0x0000ff36, 0x0000ff56, 0x00002c27, 0x00002c57, + 0x00001e72, 0x00001e73, 0x00000460, 0x00000461, + 0x0000a646, 0x0000a647, 0x00002c64, 0x0000027d, + 0x00001ea0, 0x00001ea1, 0x0000a756, 0x0000a757, + 0x0000a784, 0x0000a785, 0x0000014e, 0x0000014f, + 0x000010cd, 0x00002d2d, 0x000104b8, 0x000104e0, + 0x000013eb, 0x0000abbb, 0x000001ec, 0x000001ed, + 0x0000004b, 0x0000006b, 0x000001ae, 0x00000288, + 0x00016e51, 0x00016e71, 0x000003da, 0x000003db, + 0x0001057a, 0x000105a1, 0x00000189, 0x00000256, + 0x000024c5, 0x000024df, 0x00016e4e, 0x00016e6e, + 0x00010d55, 0x00010d75, 0x00002c02, 0x00002c32, + 0x000010a2, 0x00002d02, 0x00000200, 0x00000201, + 0x000118a4, 0x000118c4, 0x00010d54, 0x00010d74, + 0x000013bf, 0x0000ab8f, 0x00000044, 0x00000064, + 0x00016ea2, 0x00016ebd, 0x000004ea, 0x000004eb, + 0x0000a74a, 0x0000a74b, 0x00000051, 0x00000071, + 0x00000522, 0x00000523, 0x00001e2c, 0x00001e2d, + 0x00010586, 0x000105ad, 0x00001f8e, 0x00001f86, + 0x00000542, 0x00000572, 0x00001eb2, 0x00001eb3, + 0x000024c2, 0x000024dc, 0x00016e56, 0x00016e76, + 0x00000480, 0x00000481, 0x00001f4b, 0x00001f43, + 0x000024cb, 0x000024e5, 0x0000ff26, 0x0000ff46, + 0x00010409, 0x00010431, 0x00001f3a, 0x00001f32, + 0x00002cd2, 0x00002cd3, 0x00001f0f, 0x00001f07, + 0x00010407, 0x0001042f, 0x00001e02, 0x00001e03, + 0x00010cab, 0x00010ceb, 0x00001e60, 0x00001e61, + 0x00000407, 0x00000457, 0x00001faf, 0x00001fa7, + 0x00002c1e, 0x00002c4e, 0x00001e6a, 0x00001e6b, + 0x000118ad, 0x000118cd, 0x00001e00, 0x00001e01, + 0x00010d63, 0x00010d83, 0x000013c4, 0x0000ab94, + 0x000118ab, 0x000118cb, 0x000013dd, 0x0000abad, + 0x0000a64c, 0x0000a64d, 0x000010b1, 0x00002d11, + 0x00000396, 0x000003b6, 0x00001e16, 0x00001e17, + 0x00010578, 0x0001059f, 0x0000ff2b, 0x0000ff4b, + 0x0000a7dc, 0x0000019b, 0x00010571, 0x00010598, + 0x000001fa, 0x000001fb, 0x00002c22, 0x00002c52, + 0x000118aa, 0x000118ca, 0x000010ab, 0x00002d0b, + 0x00010ca5, 0x00010ce5, 0x00002c1d, 0x00002c4d, + 0x0000a758, 0x0000a759, 0x00001e84, 0x00001e85, + 0x0001e919, 0x0001e93b, 0x0000a7b3, 0x0000ab53, + 0x000004f0, 0x000004f1, 0x00010c80, 0x00010cc0, + 0x000104cc, 0x000104f4, 0x0000a77b, 0x0000a77c, + 0x00000043, 0x00000063, 0x00000124, 0x00000125, + 0x000000c6, 0x000000e6, 0x0000a658, 0x0000a659, + 0x00002cde, 0x00002cdf, 0x00001ebc, 0x00001ebd, + 0x00010424, 0x0001044c, 0x0000a734, 0x0000a735, + 0x000001d9, 0x000001da, 0x00001c90, 0x000010d0, + 0x0000018a, 0x00000257, 0x000010bc, 0x00002d1c, + 0x00002c62, 0x0000026b, 0x00000112, 0x00000113, + 0x00000186, 0x00000254, 0x0000a68c, 0x0000a68d, + 0x00002c60, 0x00002c61, 0x00000404, 0x00000454, + 0x00010577, 0x0001059e, 0x0000a75e, 0x0000a75f, + 0x00000420, 0x00000440, 0x00000401, 0x00000451, + 0x000001cf, 0x000001d0, 0x00002c2f, 0x00002c5f, + 0x0000039e, 0x000003be, 0x000010bf, 0x00002d1f, + 0x00010576, 0x0001059d, 0x00016e45, 0x00016e65, + 0x000004fc, 0x000004fd, 0x00000414, 0x00000434, + 0x00002cae, 0x00002caf, 0x00002c92, 0x00002c93, + 0x00016e4f, 0x00016e6f, 0x0001041f, 0x00010447, + 0x0000038a, 0x000003af, 0x000013c0, 0x0000ab90, + 0x0000004e, 0x0000006e, 0x00016ea0, 0x00016ebb, + 0x00010d5f, 0x00010d7f, 0x0001e918, 0x0001e93a, + 0x00000059, 0x00000079, 0x0000052a, 0x0000052b, + 0x000013e9, 0x0000abb9, 0x000010af, 0x00002d0f, + 0x00016e54, 0x00016e74, 0x00000526, 0x00000527, + 0x00001f1c, 0x00001f14, 0x00010c95, 0x00010cd5, + 0x0000ff22, 0x0000ff42, 0x0000047c, 0x0000047d, + 0x00000130, 0x02000142, 0x00002cda, 0x00002cdb, + 0x00001ef4, 0x00001ef5, 0x00010427, 0x0001044f, + 0x00001f49, 0x00001f41, 0x000104ce, 0x000104f6, + 0x000010ac, 0x00002d0c, 0x0001040b, 0x00010433, + 0x000003cf, 0x000003d7, 0x000004dc, 0x000004dd, + 0x0000a7d6, 0x0000a7d7, 0x00000415, 0x00000435, + 0x00001e0c, 0x00001e0d, 0x00001cbd, 0x000010fd, + 0x000013e6, 0x0000abb6, 0x0000040f, 0x0000045f, + 0x00001c98, 0x000010d8, 0x00000228, 0x00000229, + 0x000013ef, 0x0000abbf, 0x000118af, 0x000118cf, + 0x00001cb3, 0x000010f3, 0x00010d5b, 0x00010d7b, + 0x000013b3, 0x0000ab83, 0x000118bc, 0x000118dc, + 0x00001e38, 0x00001e39, 0x00001f88, 0x00001f80, + 0x0001e90e, 0x0001e930, 0x00001ef8, 0x00001ef9, + 0x000001f8, 0x000001f9, 0x0000212b, 0x000000e5, + 0x00002c1b, 0x00002c4b, 0x000003a7, 0x000003c7, + 0x00001ea4, 0x00001ea5, 0x00000464, 0x00000465, + 0x0000a7c5, 0x00000282, 0x0000a7d8, 0x0000a7d9, + 0x00010570, 0x00010597, 0x00002c88, 0x00002c89, + 0x000013d4, 0x0000aba4, 0x00016ea6, 0x00016ec1, + 0x00010417, 0x0001043f, 0x00010ca2, 0x00010ce2, + 0x00001ca4, 0x000010e4, 0x00001e7a, 0x00001e7b, + 0x00001e1e, 0x00001e1f, 0x00010c87, 0x00010cc7, + 0x0000a7c4, 0x0000a794, 0x00016e44, 0x00016e64, + 0x00001c92, 0x000010d2, 0x0000047a, 0x0000047b, + 0x00002cc6, 0x00002cc7, 0x000001a0, 0x000001a1, + 0x00000474, 0x00000475, 0x00010c9b, 0x00010cdb, + 0x00010c96, 0x00010cd6, 0x000001c7, 0x000001c9, + 0x00001f1a, 0x00001f12, 0x00002cbc, 0x00002cbd, + 0x00002cc2, 0x00002cc3, 0x00000176, 0x00000177, + 0x00001ca5, 0x000010e5, 0x0000041f, 0x0000043f, + 0x0000a77e, 0x0000a77f, 0x000003e0, 0x000003e1, + 0x00001e1c, 0x00001e1d, 0x0000012a, 0x0000012b, + 0x000118a8, 0x000118c8, 0x0000024e, 0x0000024f, + 0x00000520, 0x00000521, 0x000001af, 0x000001b0, + 0x00002c04, 0x00002c34, 0x00010c9a, 0x00010cda, + 0x00000204, 0x00000205, 0x00010426, 0x0001044e, + 0x000010a6, 0x00002d06, 0x000010be, 0x00002d1e, + 0x000118b9, 0x000118d9, 0x00002c8a, 0x00002c8b, + 0x000010a7, 0x00002d07, 0x00000052, 0x00000072, + 0x000118b8, 0x000118d8, 0x000004c9, 0x000004ca, + 0x0000a668, 0x0000a669, 0x00016e57, 0x00016e77, + 0x00000555, 0x00000585, 0x000004ac, 0x000004ad, + 0x0000021c, 0x0000021d, 0x00001f2e, 0x00001f26, + 0x0000053a, 0x0000056a, 0x00001f9a, 0x00001f92, + 0x00000218, 0x00000219, 0x0000ff27, 0x0000ff47, + 0x0000047e, 0x0000047f, 0x000003e8, 0x000003e9, + 0x000024bb, 0x000024d5, 0x00001ef0, 0x00001ef1, + 0x00010413, 0x0001043b, 0x00001f48, 0x00001f40, + 0x000104cd, 0x000104f5, 0x0000a7d4, 0x0000a7d5, + 0x0001041a, 0x00010442, 0x00001f0c, 0x00001f04, + 0x0001e91b, 0x0001e93d, 0x00001f5f, 0x00001f57, + 0x0000042f, 0x0000044f, 0x00001f98, 0x00001f90, + 0x00010ca1, 0x00010ce1, 0x000013d1, 0x0000aba1, + 0x0000039a, 0x000003ba, 0x00001eac, 0x00001ead, + 0x00002c8c, 0x00002c8d, 0x00002c8e, 0x00002c8f, + 0x000118be, 0x000118de, 0x00001e50, 0x00001e51, + 0x000104c4, 0x000104ec, 0x00002cb4, 0x00002cb5, + 0x000118b7, 0x000118d7, 0x00001ec6, 0x00001ec7, + 0x0000a72c, 0x0000a72d, 0x00002cb2, 0x00002cb3, + 0x000003fa, 0x000003fb, 0x00000226, 0x00000227, + 0x00010d64, 0x00010d84, 0x00001ee6, 0x00001ee7, + 0x000003a4, 0x000003c4, 0x00001f6c, 0x00001f64, + 0x000104c2, 0x000104ea, 0x00001ee2, 0x00001ee3, + 0x00001fa8, 0x00001fa0, 0x000003f7, 0x000003f8, + 0x000104d0, 0x000104f8, 0x00016e40, 0x00016e60, + 0x0000a75c, 0x0000a75d, 0x0000051e, 0x0000051f, + 0x0000a660, 0x0000a661, 0x00002168, 0x00002178, + 0x00000393, 0x000003b3, 0x000001a4, 0x000001a5, + 0x00002c29, 0x00002c59, 0x0000a79e, 0x0000a79f, + 0x00002c75, 0x00002c76, 0x00001e1a, 0x00001e1b, + 0x00002c0d, 0x00002c3d, 0x00016ea5, 0x00016ec0, + 0x00002c6f, 0x00000250, 0x00000502, 0x00000503, + 0x00000220, 0x0000019e, 0x0000a68e, 0x0000a68f, + 0x00000160, 0x00000161, 0x0000053b, 0x0000056b, + 0x000004bc, 0x000004bd, 0x0000a68a, 0x0000a68b, + 0x00002c17, 0x00002c47, 0x00000472, 0x00000473, + 0x00002165, 0x00002175, 0x00002c00, 0x00002c30, + 0x00000156, 0x00000157, 0x00010412, 0x0001043a, + 0x00001f8b, 0x00001f83, 0x00010c90, 0x00010cd0, + 0x00001ed2, 0x00001ed3, 0x0001057c, 0x000105a3, + 0x0000018f, 0x00000259, 0x0000a76e, 0x0000a76f, + 0x00000202, 0x00000203, 0x000004f4, 0x000004f5, + 0x000000c3, 0x000000e3, 0x000010a3, 0x00002d03, + 0x0000005a, 0x0000007a, 0x00000417, 0x00000437, + 0x00000114, 0x00000115, 0x000104c8, 0x000104f0, + 0x000004f8, 0x000004f9, 0x0000049c, 0x0000049d, + 0x0000a654, 0x0000a655, 0x00010d52, 0x00010d72, + 0x0000020c, 0x0000020d, 0x0000054a, 0x0000057a, + 0x00001fcc, 0x00001fc3, 0x000013bd, 0x0000ab8d, + 0x0000a7a4, 0x0000a7a5, 0x00000524, 0x00000525, + 0x00001f69, 0x00001f61, 0x00002c08, 0x00002c38, + 0x0000ff2c, 0x0000ff4c, 0x000104b9, 0x000104e1, + 0x00001f28, 0x00001f20, 0x000024bf, 0x000024d9, + 0x0000ff28, 0x0000ff48, 0x00000402, 0x00000452, + 0x00001f59, 0x00001f51, 0x0000a656, 0x0000a657, + 0x0001e91c, 0x0001e93e, 0x0001040c, 0x00010434, + 0x000013a5, 0x0000ab75, 0x00010cad, 0x00010ced, + 0x00001fb9, 0x00001fb1, 0x00000427, 0x00000447, + 0x00001cb6, 0x000010f6, 0x00010c9d, 0x00010cdd, + 0x000013b2, 0x0000ab82, 0x00000400, 0x00000450, + 0x00001e10, 0x00001e11, 0x00010c98, 0x00010cd8, + 0x000013c9, 0x0000ab99, 0x00000394, 0x000003b4, + 0x00001f1b, 0x00001f13, 0x00001f2d, 0x00001f25, + 0x00002c18, 0x00002c48, 0x0000039b, 0x000003bb, + 0x00001e3e, 0x00001e3f, 0x00002166, 0x00002176, + 0x000013d5, 0x0000aba5, 0x0000a7cb, 0x00000264, + 0x00001ffc, 0x00001ff3, 0x00001cb9, 0x000010f9, + 0x00001cba, 0x000010fa, 0x000001d1, 0x000001d2, + 0x000004ae, 0x000004af, 0x00000516, 0x00000517, + 0x00016e47, 0x00016e67, 0x00002c26, 0x00002c56, + 0x0000012e, 0x0000012f, 0x00010ca7, 0x00010ce7, + 0x0000a732, 0x0000a733, 0x00001e66, 0x00001e67, + 0x0000051c, 0x0000051d, 0x0000021e, 0x0000021f, + 0x0000a779, 0x0000a77a, 0x00002cdc, 0x00002cdd, + 0x00001fac, 0x00001fa4, 0x00010c8b, 0x00010ccb, + 0x00001ec4, 0x00001ec5, 0x00002ceb, 0x00002cec, + 0x00001ca7, 0x000010e7, 0x000000c9, 0x000000e9, + 0x00001f29, 0x00001f21, 0x000001de, 0x000001df, + 0x00001ca1, 0x000010e1, 0x00010cb0, 0x00010cf0, + 0x000013d6, 0x0000aba6, 0x00010421, 0x00010449, + 0x00000408, 0x00000458, 0x00016ea9, 0x00016ec4, + 0x000013f4, 0x000013fc, 0x00000162, 0x00000163, + 0x00001e28, 0x00001e29, 0x00016ead, 0x00016ec8, + 0x0000a740, 0x0000a741, 0x000001c5, 0x000001c6, + 0x000004a4, 0x000004a5, 0x00002c2a, 0x00002c5a, + 0x00001efa, 0x00001efb, 0x00000136, 0x00000137, + 0x00000504, 0x00000505, 0x000001a9, 0x00000283, + 0x000013a2, 0x0000ab72, 0x00000128, 0x00000129, + 0x00000409, 0x00000459, 0x000000c5, 0x000000e5, + 0x000010a0, 0x00002d00, 0x00000150, 0x00000151, + 0x0000054c, 0x0000057c, 0x000004d0, 0x000004d1, + 0x00001ff9, 0x00001f79, 0x00000055, 0x00000075, + 0x00000510, 0x00000511, 0x000000c1, 0x000000e1, + 0x0000a746, 0x0000a747, 0x0000011a, 0x0000011b, + 0x00000546, 0x00000576, 0x00001c9b, 0x000010db, + 0x0000a684, 0x0000a685, 0x0000a76a, 0x0000a76b, + 0x0000052e, 0x0000052f, 0x00001f3d, 0x00001f35, + 0x00002c72, 0x00002c73, 0x00002c11, 0x00002c41, + 0x0000049e, 0x0000049f, 0x000013df, 0x0000abaf, + 0x000024bc, 0x000024d6, 0x0000ff23, 0x0000ff43, + 0x00000418, 0x00000438, 0x000013c7, 0x0000ab97, + 0x000001f6, 0x00000195, 0x00001e5e, 0x00001e5f, + 0x0001040a, 0x00010432, 0x00001eb6, 0x00001eb7, + 0x000004de, 0x000004df, 0x0000a7cc, 0x0000a7cd, + 0x0000042c, 0x0000044c, 0x00000419, 0x00000439, + 0x000104d2, 0x000104fa, 0x00001e64, 0x00001e65, + 0x000003f4, 0x000003b8, 0x00001eaa, 0x00001eab, + 0x0001e901, 0x0001e923, 0x0000a7d0, 0x0000a7d1, + 0x000118ae, 0x000118ce, 0x00001ed8, 0x00001ed9, + 0x0000a7be, 0x0000a7bf, 0x000013cf, 0x0000ab9f, + 0x00000398, 0x000003b8, 0x00000403, 0x00000453, + 0x000003ea, 0x000003eb, 0x000013c6, 0x0000ab96, + 0x000003d8, 0x000003d9, 0x0000041b, 0x0000043b, + 0x00001f6e, 0x00001f66, 0x000013f2, 0x000013fa, + 0x000001d3, 0x000001d4, 0x00001e12, 0x00001e13, + 0x0000a65c, 0x0000a65d, 0x000013e2, 0x0000abb2, + 0x00002c28, 0x00002c58, 0x00001f6d, 0x00001f65, + 0x00010585, 0x000105ac, 0x0000ff33, 0x0000ff53, + 0x000000d2, 0x000000f2, 0x00001f18, 0x00001f10, + 0x00002c9a, 0x00002c9b, 0x0000a648, 0x0000a649, + 0x00016e48, 0x00016e68, 0x000004b2, 0x000004b3, + 0x000013ab, 0x0000ab7b, 0x000013b9, 0x0000ab89, + 0x0000019c, 0x0000026f, 0x00001c9d, 0x000010dd, + 0x00010ca8, 0x00010ce8, 0x000013da, 0x0000abaa, + 0x000001e8, 0x000001e9, 0x0000046c, 0x0000046d, + 0x0000a664, 0x0000a665, 0x000024c3, 0x000024dd, + 0x000001e6, 0x000001e7, 0x00001e76, 0x00001e77, + 0x00002164, 0x00002174, 0x0000a688, 0x0000a689, + 0x0000016e, 0x0000016f, 0x000004c5, 0x000004c6, + 0x00002163, 0x00002173, 0x0000a682, 0x0000a683, + 0x00000139, 0x0000013a, 0x00000243, 0x00000180, + 0x0000216e, 0x0000217e, 0x00001f9c, 0x00001f94, + 0x000001f7, 0x000001bf, 0x00010d56, 0x00010d76, + 0x00002ccc, 0x00002ccd, 0x000010c4, 0x00002d24, + 0x000013ca, 0x0000ab9a, 0x00000248, 0x00000249, + 0x00000118, 0x00000119, 0x000010a8, 0x00002d08, + 0x000000ce, 0x000000ee, 0x00010425, 0x0001044d, + 0x00000514, 0x00000515, 0x00016e42, 0x00016e62, + 0x00000053, 0x00000073, 0x0000040e, 0x0000045e, + 0x00002c12, 0x00002c42, 0x000010b0, 0x00002d10, + 0x00000042, 0x00000062, 0x00000541, 0x00000571, + 0x000000c0, 0x000000e0, 0x0000a752, 0x0000a753, + 0x0000ff31, 0x0000ff51, 0x00000532, 0x00000562, + 0x00000206, 0x00000207, 0x000024b9, 0x000024d3, + 0x0000ff2e, 0x0000ff4e, 0x000004f6, 0x000004f7, + 0x00001f99, 0x00001f91, 0x0001e907, 0x0001e929, + 0x0000ff21, 0x0000ff41, 0x000004b8, 0x000004b9, + 0x00001f4c, 0x00001f44, 0x00000216, 0x00000217, + 0x00001e7e, 0x00001e7f, 0x0001040e, 0x00010436, + 0x000013e0, 0x0000abb0, 0x00000518, 0x00000519, + 0x000003ff, 0x0000037d, 0x000004b0, 0x000004b1, + 0x00001fad, 0x00001fa5, 0x00002c6e, 0x00000271, + 0x000013cb, 0x0000ab9b, 0x00000426, 0x00000446, + 0x00001e2e, 0x00001e2f, 0x0001e90d, 0x0001e92f, + 0x00001e4a, 0x00001e4b, 0x000118b2, 0x000118d2, + 0x00001f19, 0x00001f11, 0x0001e905, 0x0001e927, + 0x000013b8, 0x0000ab88, 0x00000395, 0x000003b5, + 0x000000d9, 0x000000f9, 0x0001e921, 0x0001e943, + 0x000013dc, 0x0000abac, 0x00002cb8, 0x00002cb9, + 0x0000019f, 0x00000275, 0x00010cae, 0x00010cee, + 0x000013ba, 0x0000ab8a, 0x00016e5a, 0x00016e7a, + 0x000013af, 0x0000ab7f, 0x000003a3, 0x000003c3, + 0x00001e32, 0x00001e33, 0x0000a75a, 0x0000a75b, + 0x00001e4e, 0x00001e4f, 0x00010c8c, 0x00010ccc, + 0x0000a796, 0x0000a797, 0x00000110, 0x00000111, + 0x00001f39, 0x00001f31, 0x0001e914, 0x0001e936, + 0x0000a7b2, 0x0000029d, 0x00002c24, 0x00002c54, + 0x000104c3, 0x000104eb, 0x00010c99, 0x00010cd9, + 0x000010bd, 0x00002d1d, 0x00002ca4, 0x00002ca5, + 0x00001ed6, 0x00001ed7, 0x00002c05, 0x00002c35, + 0x00016e41, 0x00016e61, 0x000001d7, 0x000001d8, + 0x0001041e, 0x00010446, 0x00010579, 0x000105a0, + 0x0000a694, 0x0000a695, 0x00002ca2, 0x00002ca3, + 0x000104bf, 0x000104e7, 0x0000011e, 0x0000011f, + 0x0000a692, 0x0000a693, 0x00000182, 0x00000183, + 0x00010415, 0x0001043d, 0x0000216b, 0x0000217b, + 0x00001f2a, 0x00001f22, 0x00002c21, 0x00002c51, + 0x0000038e, 0x000003cd, 0x000000d4, 0x000000f4, + 0x0000a7ae, 0x0000026a, 0x0000a7da, 0x0000a7db, + 0x00001e6c, 0x00001e6d, 0x00000392, 0x000003b2, + 0x00016ea1, 0x00016ebc, 0x000000d0, 0x000000f0, + 0x000104b5, 0x000104dd, 0x00000388, 0x000003ad, + 0x000010b9, 0x00002d19, 0x0000013f, 0x00000140, + 0x00010595, 0x000105bc, 0x0000011c, 0x0000011d, + 0x00001cbe, 0x000010fe, 0x00000057, 0x00000077, + 0x00000553, 0x00000583, 0x00002c14, 0x00002c44, + 0x00010d50, 0x00010d70, 0x0000004a, 0x0000006a, + 0x00000512, 0x00000513, 0x0000041d, 0x0000043d, + 0x00002cbe, 0x00002cbf, 0x0000ff37, 0x0000ff57, + 0x00016e4a, 0x00016e6a, 0x00001f9b, 0x00001f93, + 0x00002c06, 0x00002c36, 0x0001e906, 0x0001e928, + 0x00000490, 0x00000491, 0x00001fd9, 0x00001fd1, + 0x000024be, 0x000024d8, 0x0000ff39, 0x0000ff59, + 0x000004b4, 0x000004b5, 0x00001f4d, 0x00001f45, + 0x00002cb0, 0x00002cb1, 0x00001f9d, 0x00001f95, + 0x0001040d, 0x00010435, 0x00001e20, 0x00001e21, + 0x00002c9c, 0x00002c9d, 0x00002162, 0x00002172, + 0x00000428, 0x00000448, 0x00001ece, 0x00001ecf, + 0x000024b7, 0x000024d1, 0x000013f1, 0x000013f9, + 0x000004aa, 0x000004ab, 0x00001ea8, 0x00001ea9, + 0x0000a782, 0x0000a783, 0x000013d3, 0x0000aba3, + 0x000118b1, 0x000118d1, 0x00001c9a, 0x000010da, + 0x00000462, 0x00000463, 0x000013d9, 0x0000aba9, + 0x00000389, 0x000003ae, 0x00001ca8, 0x000010e8, + 0x00002c90, 0x00002c91, 0x000013e8, 0x0000abb8, + 0x0000023b, 0x0000023c, 0x000000d1, 0x000000f1, + 0x0000a640, 0x0000a641, 0x00016e46, 0x00016e66, + 0x00000164, 0x00000165, 0x00001e82, 0x00001e83, + 0x00010c91, 0x00010cd1, 0x000013ce, 0x0000ab9e, + 0x00016eb4, 0x00016ecf, 0x00010575, 0x0001059c, + 0x000013b5, 0x0000ab85, 0x0000a7ba, 0x0000a7bb, + 0x0000010a, 0x0000010b, 0x00001f6f, 0x00001f67, + 0x00010cb2, 0x00010cf2, 0x000013d2, 0x0000aba2, + 0x00002c67, 0x00002c68, 0x0000054d, 0x0000057d, + 0x00010c8d, 0x00010ccd, 0x0000a7c2, 0x0000a7c3, + 0x00002caa, 0x00002cab, 0x00001ca0, 0x000010e0, + 0x000104ca, 0x000104f2, 0x00002cc4, 0x00002cc5, + 0x00002ce2, 0x00002ce3, 0x00001cb2, 0x000010f2, + 0x00010c8f, 0x00010ccf, 0x000013d8, 0x0000aba8, + 0x00010c83, 0x00010cc3, 0x00001cb0, 0x000010f0, + 0x00002c07, 0x00002c37, 0x0000a696, 0x0000a697, + 0x00002cce, 0x00002ccf, 0x00001ca9, 0x000010e9, + 0x00002161, 0x00002171, 0x0000a65a, 0x0000a65b, + 0x00000147, 0x00000148, 0x000004c7, 0x000004c8, + 0x00000191, 0x00000192, 0x000013c8, 0x0000ab98, + 0x000000db, 0x000000fb, 0x000104d3, 0x000104fb, + 0x0001e917, 0x0001e939, 0x000010ba, 0x00002d1a, + 0x000000dc, 0x000000fc, 0x00001f9f, 0x00001f97, + 0x00002cca, 0x00002ccb, 0x000010a4, 0x00002d04, + 0x000003de, 0x000003df, 0x00000416, 0x00000436, + 0x00002c82, 0x00002c83, 0x000024ce, 0x000024e8, + 0x00000054, 0x00000074, 0x000118b6, 0x000118d6, + 0x00000376, 0x00000377, 0x00001f2b, 0x00001f23, + 0x0001e908, 0x0001e92a, 0x00000544, 0x00000574, + 0x00001fea, 0x00001f7a, 0x00000190, 0x0000025b, + 0x0001e91a, 0x0001e93c, 0x00000535, 0x00000565, + 0x00001e22, 0x00001e23, 0x00010d5c, 0x00010d7c, + 0x0000ff30, 0x0000ff50, 0x0000041e, 0x0000043e, + 0x000010c7, 0x00002d27, 0x000104bc, 0x000104e4, + 0x0000ff32, 0x0000ff52, 0x00010408, 0x00010430, + 0x00001f6b, 0x00001f63, 0x000104cf, 0x000104f7, + 0x00001e78, 0x00001e79, 0x00010405, 0x0001042d, + 0x00001fae, 0x00001fa6, 0x000001c8, 0x000001c9, + 0x00001cae, 0x000010ee, 0x00000421, 0x00000441, + 0x000118a6, 0x000118c6, 0x00000466, 0x00000467, + 0x00001f89, 0x00001f81, 0x000118ac, 0x000118cc, + 0x000013a3, 0x0000ab73, 0x00001ede, 0x00001edf, + 0x000013ee, 0x0000abbe, 0x000118a9, 0x000118c9, + 0x00001ec0, 0x00001ec1, 0x0001e904, 0x0001e926, + 0x000013b4, 0x0000ab84, 0x000118b0, 0x000118d0, + 0x00001e14, 0x00001e15, 0x00002c0e, 0x00002c3e, + 0x00016eac, 0x00016ec7, 0x000118a2, 0x000118c2, + 0x00001ff8, 0x00001f78, 0x00010589, 0x000105b0, + 0x000013be, 0x0000ab8e, 0x000001bc, 0x000001bd, + 0x00000045, 0x00000065, 0x00010d51, 0x00010d71, + 0x0000ff34, 0x0000ff54, 0x00000208, 0x00000209, + 0x00001f68, 0x00001f60, 0x00010cac, 0x00010cec, + 0x0000a7a0, 0x0000a7a1, 0x0000054f, 0x0000057f, + 0x00000197, 0x00000268, 0x00010ca6, 0x00010ce6, + 0x000024c6, 0x000024e0, 0x00000210, 0x00000211, + 0x000010b8, 0x00002d18, 0x0001058d, 0x000105b4, + 0x0000a738, 0x0000a739, 0x0000020a, 0x0000020b, + 0x00001e46, 0x00001e47, 0x00000184, 0x00000185, + 0x0000a722, 0x0000a723, 0x00002ca8, 0x00002ca9, + 0x00001c94, 0x000010d4, 0x0000021a, 0x0000021b, + 0x00002cac, 0x00002cad, 0x00000141, 0x00000142, + 0x000004ee, 0x000004ef, 0x000003aa, 0x000003ca, + 0x00001cbf, 0x000010ff, 0x00000172, 0x00000173, + 0x000004c0, 0x000004cf, 0x00010580, 0x000105a7, + 0x0000a764, 0x0000a765, 0x000001f1, 0x000001f3, + 0x000104b0, 0x000104d8, 0x00010581, 0x000105a8, + 0x000013a7, 0x0000ab77, 0x00000100, 0x00000101, + 0x00001f0e, 0x00001f06, 0x000004cb, 0x000004cc, + 0x000010aa, 0x00002d0a, 0x00000047, 0x00000067, + 0x00000425, 0x00000445, 0x00000230, 0x00000231, + 0x00001ca2, 0x000010e2, 0x000004fa, 0x000004fb, + 0x00010594, 0x000105bb, 0x00000116, 0x00000117, + 0x00016e4d, 0x00016e6d, 0x0000004c, 0x0000006c, + 0x00000506, 0x00000507, 0x000104c6, 0x000104ee, + 0x000010b2, 0x00002d12, 0x000000cd, 0x000000ed, + 0x00000410, 0x00000430, 0x00001fe9, 0x00001fe1, + 0x0000018e, 0x000001dd, 0x0000a76c, 0x0000a76d, + 0x00000533, 0x00000563, 0x000003f9, 0x000003f2, + 0x000024c8, 0x000024e2, 0x0000a736, 0x0000a737, + 0x000004c3, 0x000004c4, 0x00001f9e, 0x00001f96, + 0x000024c0, 0x000024da, 0x00001e7c, 0x00001e7d, + 0x00010410, 0x00010438, 0x000010c5, 0x00002d25, + 0x00000550, 0x00000580, 0x0001e91e, 0x0001e940, + 0x0001040f, 0x00010437, 0x00001eae, 0x00001eaf, + 0x0001e902, 0x0001e924, 0x00001ffb, 0x00001f7d, + 0x0000042b, 0x0000044b, 0x00001caf, 0x000010ef, + 0x000001ca, 0x000001cc, 0x00001fbb, 0x00001f71, + 0x000118b4, 0x000118d4, 0x00001e18, 0x00001e19, + 0x00002c7e, 0x0000023f, 0x000013f5, 0x000013fd, + 0x000118b3, 0x000118d3, 0x00001ecc, 0x00001ecd, + 0x00010d53, 0x00010d73, 0x00016eb0, 0x00016ecb, + 0x0000039d, 0x000003bd, 0x00001e04, 0x00001e05, + 0x00010587, 0x000105ae, 0x0001e903, 0x0001e925, + 0x00002c23, 0x00002c53, 0x00010573, 0x0001059a, + 0x0001e90c, 0x0001e92e, 0x000013ae, 0x0000ab7e, + 0x000003a5, 0x000003c5, 0x000013e7, 0x0000abb7, + 0x0000014a, 0x0000014b, 0x00002126, 0x000003c9, + 0x00001e74, 0x00001e75, 0x00010591, 0x000105b8, + 0x00016e53, 0x00016e73, 0x000013b7, 0x0000ab87, + 0x000104c5, 0x000104ed, 0x000104c9, 0x000104f1, + 0x0000050a, 0x0000050b, 0x0000a792, 0x0000a793, + 0x00002ce0, 0x00002ce1, 0x00000108, 0x00000109, + 0x00010c89, 0x00010cc9, 0x0000a7f5, 0x0000a7f6, + 0x0000023d, 0x0000019a, 0x00001c96, 0x000010d6, + 0x00002c0b, 0x00002c3b, 0x000013db, 0x0000abab, + 0x00002ca6, 0x00002ca7, 0x00001c91, 0x000010d1, + 0x00010c93, 0x00010cd3, 0x000010c2, 0x00002d22, + 0x000001ee, 0x000001ef, 0x0001058c, 0x000105b3, + 0x0001e916, 0x0001e938, 0x00002cc8, 0x00002cc9, + 0x00000168, 0x00000169, 0x00001e88, 0x00001e89, + 0x0000216f, 0x0000217f, 0x0000a73c, 0x0000a73d, + 0x000001db, 0x000001dc, 0x0000048c, 0x0000048d, + 0x0000038c, 0x000003cc, 0x000013ed, 0x0000abbd, + 0x00000152, 0x00000153, 0x0001041c, 0x00010444, + 0x000001a6, 0x00000280, 0x000013e4, 0x0000abb4, + 0x000001b2, 0x0000028b, 0x000013ac, 0x0000ab7c, + 0x00002c98, 0x00002c99, 0x000010b4, 0x00002d14, + 0x0000015e, 0x0000015f, 0x00000554, 0x00000584, + 0x00002c7f, 0x00000240, 0x00002c0c, 0x00002c3c, + 0x00000056, 0x00000076, 0x00001fcb, 0x00001f75, + 0x000000c7, 0x000000e7, 0x00010d5d, 0x00010d7d }; static const unsigned _uccase_title_g_size = 35; @@ -4359,828 +4431,843 @@ static const unsigned _uccase_title_table[] = { 0x00001f93, 0x00001f9b }; -static const unsigned _uccase_fold_g_size = 293; +static const unsigned _uccase_fold_g_size = 298; static const short _uccase_fold_g[] = { - 3432, 570, 1, 102, 547, 152, 440, 46, - 546, 468, 6, 769, 1, 581, -753, 2134, - 130, 743, 372, 238, 1, 829, 1, 1007, - 158, 1146, 174, 1077, 760, 1041, 1091, 567, - 1591, 817, 630, 711, 225, 1808, 121, 2595, - 2831, 363, 601, 2677, 86, 1013, 12, 186, - 10, 201, 544, 2, 252, 4, 666, 1, - -297, 131, 173, 811, 461, 2, 355, 1, - 478, 8, 1544, 16, 531, 61, 1109, 1061, - 518, 926, 1380, 875, 1302, 1996, 109, 13793, - 119, -916, -870, 401, 2098, 551, 546, 83, - 521, 3, 512, 533, 167, 4, 20, 252, - 87, -1534, 51, -835, 129, 781, 323, 428, - 1, 397, 1, 1662, 78, 1120, 32, 232, - 59, 1673, 250, 976, 1486, 1526, 718, 2892, - 2869, 1306, 1, -1412, 2428, 5542, 519, 7772, - 459, 590, 1, 143, 2, 484, 247, 9, - 514, 1, 704, 7, -591, 744, 143, 168, - 266, 368, 913, 1, 86, 1, 1012, 140, - 796, 48, 842, 1049, 3775, 815, 714, 1421, - 182, 2899, 4758, 2493, 1590, -1189, 3441, 867, - 538, 520, 605, 4, 635, 249, 220, 516, - 166, 183, 6, 583, 63, 706, 121, 633, - 271, 1577, 5, 274, 1, 2442, 1, 535, - 413, 307, 787, 192, 857, 3329, 375, 1223, - 131, 790, 1785, 4374, 2147, 2028, 2317, -1449, - 4982, 4893, 325, 7004, 93, 256, 108, 513, - 1, 182, 2, 116, 390, 1, 322, 2182, - 313, 554, 15407, 12, 63, 22, 404, 1, - 405, 8, 3674, 203, 880, 581, 803, 214, - 2925, 191, 2747, 556, 1638, 2864, 2687, 2635, - 2450, 1845, 445, 2093, 4633, 52, 676, 1, - 536, 1, 4, 1, 5, 340, 1, 226, - 4, -151, -782, 502, 283, 75, 15, 300, - 16, 539, 1, 1128, 3, 1625, 1138, 1245, - 391, 2421, 1347, 1362, 1439, 136, 1598, 212, - 3221, 2388, 1158, 3173, 666 + 1, 400, 2, 1637, 933, 1790, 18, 1934, + 361, 1515, 1, 459, 1040, 1561, 90, 3805, + 669, 1434, 1, 505, 387, 1581, 273, 1308, + 24, 164, 1, 1334, 1323, 1895, 675, -1011, + 32, 3373, 1, 1069, 166, 272, 338, 8497, + 196, 1451, 266, 1106, 27, 1596, 535, -780, + 222, 944, 1114, 191, 51, 32, 732, 1298, + 472, 710, 38, 1116, 136, 1, 344, 1485, + 425, 637, 697, 151, 89, 1, 3, -1475, + 524, 596, 2993, 3024, 170, 9, 3, 14122, + 1183, 3845, 1269, 715, 67, 93, 6, -626, + 26, 653, 425, 1349, 10, 390, 8, 17497, + 1, -406, 1157, 1669, 28, -103, 1, 8908, + 1, 581, 1166, 1550, 1, 1327, 50, 1446, + 1, 370, 3278, 1168, 210, -1251, 394, 1217, + 1, -186, 747, 1383, 3229, -1174, 110, 619, + 1, 1507, 334, 1866, 257, 1062, 36, 78, + 38, 1092, 24, 1549, 464, 1704, 53, 569, + 77, 58, 1, 1387, 3244, -739, 127, 347, + 659, 1146, 5, 1, 16327, -1575, 524, 603, + 3461, 76, 26, 1, 33, 2536, 87, 538, + 266, 10827, 90, 40, 402, 1060, 1096, 266, + 1668, 1431, 11, 7, 857, 6023, 873, 2019, + 1254, 177, 70, 223, 1, -454, 30, 2530, + 545, 848, 124, 999, 2, 1169, 6, -208, + 788, 2073, 24, -72, 395, 218, 1, 152, + 618, 1550, 15, 1544, 641, 1186, 1, 359, + 6367, 348, 52, 1218, 731, 1457, 1, 692, + 10945, 1561, 604, -1124, 85, 179, 1, 717, + 168, 4645, 592, 1028, 439, 1155, 320, 829, + 322, 1896, 515, -853, 83, 1580, 6713, 339, + 179, 55, 1055, 1768, 900, 1001, 1494, 218, + 146, 1, 603, 1474, 17, 527, 4, 889, + 160, 48, 367, -1477, 925, 924, -1214, 4802, + 90, 1, 3, 6489, 1055, 167, 1483, 99, + 26, 3, 3, -699, 737, 3023, 94, 13291, + 67, 744, 1, 8829, 42, 1558, 933, 1449, + 66, -1368 }; -static const unsigned _uccase_fold_table_size = 1557; +static const unsigned _uccase_fold_table_size = 1585; static const unsigned _uccase_fold_table[] = { - 0x000024b9, 0x000024d3, 0x0000aba6, 0x000013d6, - 0x0000ab94, 0x000013c4, 0x00000045, 0x00000065, - 0x0000018e, 0x000001dd, 0x00001e10, 0x00001e11, - 0x000004ba, 0x000004bb, 0x000003e6, 0x000003e7, - 0x000010a3, 0x00002d03, 0x00000224, 0x00000225, - 0x00010c8b, 0x00010ccb, 0x00001fe9, 0x00001fe1, - 0x00001e5e, 0x00001e5f, 0x0000ff36, 0x0000ff56, - 0x0000a754, 0x0000a755, 0x0000020c, 0x0000020d, - 0x0000a642, 0x0000a643, 0x00001eaa, 0x00001eab, - 0x00001ed8, 0x00001ed9, 0x0000023e, 0x00002c66, - 0x00001c9b, 0x000010db, 0x00000187, 0x00000188, - 0x000010a2, 0x00002d02, 0x00001fbe, 0x000003b9, - 0x000004e0, 0x000004e1, 0x00001e12, 0x00001e13, - 0x000001f8, 0x000001f9, 0x000000c3, 0x000000e3, - 0x00001f8f, 0x020001f4, 0x00001e00, 0x00001e01, - 0x00001e1a, 0x00001e1b, 0x00010c8c, 0x00010ccc, - 0x0000a750, 0x0000a751, 0x000010a0, 0x00002d00, - 0x00002c80, 0x00002c81, 0x0000ff33, 0x0000ff53, - 0x00001c9a, 0x000010da, 0x00001fcc, 0x0200027a, - 0x0000011c, 0x0000011d, 0x0000053d, 0x0000056d, - 0x0000ff2b, 0x0000ff4b, 0x00001f2e, 0x00001f26, - 0x000000d4, 0x000000f4, 0x00010cb2, 0x00010cf2, - 0x000001b2, 0x0000028b, 0x0000a72a, 0x0000a72b, - 0x0000abb8, 0x000013e8, 0x0000ab91, 0x000013c1, - 0x00010c8d, 0x00010ccd, 0x00001ea8, 0x00001ea9, - 0x0000041b, 0x0000043b, 0x0000a728, 0x0000a729, - 0x00001e38, 0x00001e39, 0x000003d8, 0x000003d9, - 0x0000a77b, 0x0000a77c, 0x0000a792, 0x0000a793, - 0x00001e02, 0x00001e03, 0x0000a666, 0x0000a667, - 0x00001ed0, 0x00001ed1, 0x00000466, 0x00000467, - 0x00001fc8, 0x00001f72, 0x00000152, 0x00000153, - 0x000001f6, 0x00000195, 0x00010c89, 0x00010cc9, - 0x0000aba7, 0x000013d7, 0x000104c3, 0x000104eb, - 0x0000fb00, 0x020002b1, 0x000001ec, 0x000001ed, - 0x0000a79c, 0x0000a79d, 0x00000538, 0x00000568, - 0x00001e26, 0x00001e27, 0x00001e9b, 0x00001e61, - 0x0000a779, 0x0000a77a, 0x0000a76c, 0x0000a76d, - 0x00000421, 0x00000441, 0x0000a644, 0x0000a645, - 0x0000041a, 0x0000043a, 0x0001e901, 0x0001e923, - 0x0000a734, 0x0000a735, 0x00000141, 0x00000142, - 0x0000a680, 0x0000a681, 0x00001f08, 0x00001f00, - 0x000004a8, 0x000004a9, 0x0000a7b1, 0x00000287, - 0x0000053c, 0x0000056c, 0x0001058c, 0x000105b3, - 0x000000c2, 0x000000e2, 0x00001fa0, 0x02000227, - 0x000118ab, 0x000118cb, 0x00001c86, 0x0000044a, - 0x00000222, 0x00000223, 0x0000a7be, 0x0000a7bf, - 0x00001f4b, 0x00001f43, 0x00001e6a, 0x00001e6b, - 0x000003a9, 0x000003c9, 0x00016e41, 0x00016e61, - 0x000001b1, 0x0000028a, 0x00000134, 0x00000135, - 0x0000a68c, 0x0000a68d, 0x00001ef6, 0x00001ef7, - 0x00001f6b, 0x00001f63, 0x000001cb, 0x000001cc, - 0x00016e5f, 0x00016e7f, 0x0000a744, 0x0000a745, - 0x0000ab80, 0x000013b0, 0x000004ea, 0x000004eb, - 0x00000197, 0x00000268, 0x0000013f, 0x00000140, - 0x0000022c, 0x0000022d, 0x00001f89, 0x020001e2, - 0x00001fd8, 0x00001fd0, 0x000003a0, 0x000003c0, - 0x00001ee0, 0x00001ee1, 0x00002167, 0x00002177, - 0x000000d3, 0x000000f3, 0x00002c86, 0x00002c87, - 0x0000ff39, 0x0000ff59, 0x0000ab74, 0x000013a4, - 0x0000aba3, 0x000013d3, 0x000013f8, 0x000013f0, - 0x0000018b, 0x0000018c, 0x000010b5, 0x00002d15, - 0x00001f3a, 0x00001f32, 0x00001fa3, 0x02000230, - 0x0001e917, 0x0001e939, 0x00002c0d, 0x00002c3d, - 0x0000ff2c, 0x0000ff4c, 0x0000abb6, 0x000013e6, - 0x0001057f, 0x000105a6, 0x0000039e, 0x000003be, - 0x00010586, 0x000105ad, 0x000010be, 0x00002d1e, - 0x00001fc9, 0x00001f73, 0x00001e3a, 0x00001e3b, - 0x0000aba5, 0x000013d5, 0x00001ff8, 0x00001f78, - 0x0001e919, 0x0001e93b, 0x0000010e, 0x0000010f, - 0x00002cc8, 0x00002cc9, 0x0000ab88, 0x000013b8, - 0x00000470, 0x00000471, 0x00000394, 0x000003b4, - 0x00000156, 0x00000157, 0x000024ba, 0x000024d4, - 0x00000043, 0x00000063, 0x000004be, 0x000004bf, - 0x00000130, 0x02000192, 0x0001e911, 0x0001e933, - 0x00000132, 0x00000133, 0x0000a780, 0x0000a781, - 0x00001fb7, 0x03000263, 0x000001cd, 0x000001ce, - 0x000003c2, 0x000003c3, 0x00010583, 0x000105aa, - 0x00001cb5, 0x000010f5, 0x000004cd, 0x000004ce, - 0x0000a654, 0x0000a655, 0x00000412, 0x00000432, - 0x00001cb6, 0x000010f6, 0x00001c90, 0x000010d0, - 0x00010411, 0x00010439, 0x0000a7d6, 0x0000a7d7, - 0x00001f0a, 0x00001f02, 0x0000ab95, 0x000013c5, - 0x0000013d, 0x0000013e, 0x000001e4, 0x000001e5, - 0x000001de, 0x000001df, 0x0000004f, 0x0000006f, - 0x00010417, 0x0001043f, 0x00001ee2, 0x00001ee3, - 0x00002c0c, 0x00002c3c, 0x00000226, 0x00000227, - 0x0000216d, 0x0000217d, 0x00001f49, 0x00001f41, - 0x00001c9f, 0x000010df, 0x000118ac, 0x000118cc, - 0x00000050, 0x00000070, 0x000024b6, 0x000024d0, - 0x0000a64c, 0x0000a64d, 0x000118a9, 0x000118c9, - 0x00001e94, 0x00001e95, 0x00001e08, 0x00001e09, - 0x00010ca5, 0x00010ce5, 0x00000179, 0x0000017a, - 0x00001ca2, 0x000010e2, 0x00010c87, 0x00010cc7, - 0x000004e2, 0x000004e3, 0x00001c98, 0x000010d8, - 0x000001c8, 0x000001c9, 0x00001c9e, 0x000010de, - 0x000001c5, 0x000001c6, 0x00001fda, 0x00001f76, - 0x00001c95, 0x000010d5, 0x00001cb8, 0x000010f8, - 0x000024c6, 0x000024e0, 0x00000191, 0x00000192, - 0x00002c90, 0x00002c91, 0x0000ff2d, 0x0000ff4d, - 0x00010c9e, 0x00010cde, 0x0000abb5, 0x000013e5, - 0x0000aba1, 0x000013d1, 0x00002cde, 0x00002cdf, - 0x00001ee4, 0x00001ee5, 0x00001f86, 0x020001d9, - 0x000004c0, 0x000004cf, 0x00000370, 0x00000371, - 0x0000041f, 0x0000043f, 0x0000017d, 0x0000017e, - 0x000024c5, 0x000024df, 0x00010424, 0x0001044c, - 0x0000a7da, 0x0000a7db, 0x0000004c, 0x0000006c, - 0x00000041, 0x00000061, 0x000104b0, 0x000104d8, - 0x00001e36, 0x00001e37, 0x000003da, 0x000003db, - 0x000004b8, 0x000004b9, 0x00001c81, 0x00000434, - 0x00000118, 0x00000119, 0x0000a668, 0x0000a669, - 0x00010592, 0x000105b9, 0x000004ec, 0x000004ed, - 0x00010c96, 0x00010cd6, 0x0000014c, 0x0000014d, - 0x0000016a, 0x0000016b, 0x000000ca, 0x000000ea, - 0x000004b6, 0x000004b7, 0x0000054f, 0x0000057f, - 0x0000ab7b, 0x000013ab, 0x00000587, 0x020001a3, - 0x00010ca3, 0x00010ce3, 0x00001fb4, 0x0200025d, - 0x00001f29, 0x00001f21, 0x000003f7, 0x000003f8, - 0x00002c69, 0x00002c6a, 0x0000a7b8, 0x0000a7b9, - 0x000010c1, 0x00002d21, 0x00002cb2, 0x00002cb3, - 0x0000042b, 0x0000044b, 0x0001e903, 0x0001e925, - 0x0001041d, 0x00010445, 0x000118b8, 0x000118d8, - 0x00010595, 0x000105bc, 0x0000ff24, 0x0000ff44, - 0x000004aa, 0x000004ab, 0x00010c80, 0x00010cc0, - 0x00000196, 0x00000269, 0x000024ca, 0x000024e4, - 0x0000a738, 0x0000a739, 0x00001fa7, 0x0200023c, - 0x00001e99, 0x020001af, 0x00000243, 0x00000180, - 0x000104cb, 0x000104f3, 0x00010c91, 0x00010cd1, - 0x0000ff30, 0x0000ff50, 0x00001fb6, 0x02000260, - 0x00000400, 0x00000450, 0x0000a76a, 0x0000a76b, - 0x00010c95, 0x00010cd5, 0x0000a652, 0x0000a653, - 0x00002ce0, 0x00002ce1, 0x00001ca0, 0x000010e0, - 0x0000a736, 0x0000a737, 0x00000372, 0x00000373, - 0x000000c6, 0x000000e6, 0x000104b1, 0x000104d9, - 0x00001fb2, 0x02000257, 0x000004f4, 0x000004f5, - 0x000010a4, 0x00002d04, 0x00001e7e, 0x00001e7f, - 0x0000041d, 0x0000043d, 0x0000016c, 0x0000016d, - 0x00002cd8, 0x00002cd9, 0x00001fab, 0x02000248, - 0x0001e906, 0x0001e928, 0x0001e902, 0x0001e924, - 0x0000a768, 0x0000a769, 0x0000a7ac, 0x00000261, - 0x00001e98, 0x020001ac, 0x0000abbc, 0x000013ec, - 0x0000fb17, 0x020002d4, 0x00010d59, 0x00010d79, - 0x00002cd6, 0x00002cd7, 0x00001eba, 0x00001ebb, - 0x00001ee6, 0x00001ee7, 0x000004d0, 0x000004d1, - 0x00001cb7, 0x000010f7, 0x000118b3, 0x000118d3, - 0x0000a724, 0x0000a725, 0x0000a7c2, 0x0000a7c3, - 0x0000051c, 0x0000051d, 0x00000392, 0x000003b2, - 0x00010d64, 0x00010d84, 0x00000056, 0x00000076, - 0x00001fcb, 0x00001f75, 0x00002161, 0x00002171, - 0x00001e8c, 0x00001e8d, 0x000001cf, 0x000001d0, - 0x00010576, 0x0001059d, 0x0000015a, 0x0000015b, - 0x00002cca, 0x00002ccb, 0x00001e82, 0x00001e83, - 0x00000472, 0x00000473, 0x00001c88, 0x0000a64b, - 0x00000158, 0x00000159, 0x00010c84, 0x00010cc4, - 0x00001f2c, 0x00001f24, 0x00001f68, 0x00001f60, - 0x000003b0, 0x0300019f, 0x000104be, 0x000104e6, - 0x00000147, 0x00000148, 0x0000a78d, 0x00000265, - 0x00002c20, 0x00002c50, 0x00001ca6, 0x000010e6, - 0x0000abb3, 0x000013e3, 0x00010413, 0x0001043b, - 0x00000395, 0x000003b5, 0x00010418, 0x00010440, - 0x0000a656, 0x0000a657, 0x00000414, 0x00000434, - 0x00000462, 0x00000463, 0x000003ff, 0x0000037d, - 0x00000534, 0x00000564, 0x00010d62, 0x00010d82, - 0x00001fba, 0x00001f70, 0x000118a4, 0x000118c4, - 0x00010c8f, 0x00010ccf, 0x00000128, 0x00000129, - 0x00001c87, 0x00000463, 0x00001f5d, 0x00001f55, - 0x00001f9b, 0x02000218, 0x00010581, 0x000105a8, - 0x000001f1, 0x000001f3, 0x00000228, 0x00000229, - 0x000104cc, 0x000104f4, 0x00002c11, 0x00002c41, - 0x00001e9a, 0x020001b2, 0x0000048e, 0x0000048f, - 0x000104c6, 0x000104ee, 0x0000ff32, 0x0000ff52, - 0x00002c0e, 0x00002c3e, 0x000010bd, 0x00002d1d, - 0x00001e62, 0x00001e63, 0x00000547, 0x00000577, - 0x0000abab, 0x000013db, 0x00016e49, 0x00016e69, - 0x00016e54, 0x00016e74, 0x00016e40, 0x00016e60, - 0x000004e4, 0x000004e5, 0x000024c3, 0x000024dd, - 0x00000102, 0x00000103, 0x00000214, 0x00000215, - 0x00001f93, 0x02000200, 0x0000050a, 0x0000050b, - 0x00001e5c, 0x00001e5d, 0x000024cf, 0x000024e9, - 0x00002169, 0x00002179, 0x0000005a, 0x0000007a, - 0x00002c92, 0x00002c93, 0x00001e90, 0x00001e91, - 0x0000ab78, 0x000013a8, 0x00001f9a, 0x02000215, - 0x00000120, 0x00000121, 0x00000168, 0x00000169, - 0x00001fbc, 0x02000267, 0x0000a7c4, 0x0000a794, - 0x00000399, 0x000003b9, 0x00001e40, 0x00001e41, - 0x000004fe, 0x000004ff, 0x0000a7aa, 0x00000266, - 0x0000abbe, 0x000013ee, 0x00001c99, 0x000010d9, - 0x000024cd, 0x000024e7, 0x000104bc, 0x000104e4, - 0x00010570, 0x00010597, 0x000000c1, 0x000000e1, - 0x00002c82, 0x00002c83, 0x000003dc, 0x000003dd, - 0x00000424, 0x00000444, 0x0000aba2, 0x000013d2, - 0x00000506, 0x00000507, 0x0000ff2f, 0x0000ff4f, - 0x00001f6d, 0x00001f65, 0x000118af, 0x000118cf, - 0x000003e8, 0x000003e9, 0x0000015e, 0x0000015f, - 0x0000012a, 0x0000012b, 0x0000004b, 0x0000006b, - 0x00002c2b, 0x00002c5b, 0x00000536, 0x00000566, - 0x00010d5f, 0x00010d7f, 0x000001f0, 0x02000198, - 0x000000d2, 0x000000f2, 0x00001eec, 0x00001eed, - 0x00001e2a, 0x00001e2b, 0x00001e04, 0x00001e05, - 0x00001cb2, 0x000010f2, 0x00010c88, 0x00010cc8, - 0x00002ce2, 0x00002ce3, 0x00016e48, 0x00016e68, - 0x00000406, 0x00000456, 0x0001e905, 0x0001e927, - 0x0000abb7, 0x000013e7, 0x00001ca7, 0x000010e7, - 0x00016e56, 0x00016e76, 0x00001ff2, 0x0200029e, - 0x000004ac, 0x000004ad, 0x00010cad, 0x00010ced, - 0x00010cac, 0x00010cec, 0x00016e46, 0x00016e66, - 0x00001f5b, 0x00001f53, 0x0000abb0, 0x000013e0, - 0x00001e4e, 0x00001e4f, 0x000001b5, 0x000001b6, - 0x0000022e, 0x0000022f, 0x0000a74c, 0x0000a74d, - 0x000104b2, 0x000104da, 0x00001ca3, 0x000010e3, - 0x00000402, 0x00000452, 0x0000a732, 0x0000a733, - 0x00010d51, 0x00010d71, 0x000000d0, 0x000000f0, - 0x0000a690, 0x0000a691, 0x00001efa, 0x00001efb, - 0x0000aba4, 0x000013d4, 0x0000a7ad, 0x0000026c, - 0x00016e5d, 0x00016e7d, 0x0001058e, 0x000105b5, - 0x0000ab84, 0x000013b4, 0x0001040c, 0x00010434, - 0x00001e56, 0x00001e57, 0x0000017b, 0x0000017c, - 0x00000212, 0x00000213, 0x00001f6a, 0x00001f62, - 0x00001cb3, 0x000010f3, 0x000003a4, 0x000003c4, - 0x0000037f, 0x000003f3, 0x000118a8, 0x000118c8, - 0x00000420, 0x00000440, 0x00002cda, 0x00002cdb, - 0x0000ab9e, 0x000013ce, 0x00000492, 0x00000493, - 0x00010c9c, 0x00010cdc, 0x0000fb04, 0x030002be, - 0x00016e4f, 0x00016e6f, 0x0000a646, 0x0000a647, - 0x0000ab73, 0x000013a3, 0x000004d2, 0x000004d3, - 0x000003ee, 0x000003ef, 0x000001b8, 0x000001b9, - 0x00002132, 0x0000214e, 0x00001f84, 0x020001d3, - 0x00000549, 0x00000579, 0x00001fea, 0x00001f7a, - 0x0000fb15, 0x020002ce, 0x00002166, 0x00002176, - 0x0000a7ae, 0x0000026a, 0x00000428, 0x00000448, - 0x00001ea4, 0x00001ea5, 0x00001c84, 0x00000442, - 0x000004c5, 0x000004c6, 0x000000db, 0x000000fb, - 0x00002ccc, 0x00002ccd, 0x00001ed4, 0x00001ed5, - 0x00000474, 0x00000475, 0x00000245, 0x0000028c, - 0x00010cb0, 0x00010cf0, 0x00002162, 0x00002172, - 0x00001f0c, 0x00001f04, 0x00001f6c, 0x00001f64, - 0x0000a7cc, 0x0000a7cd, 0x00000391, 0x000003b1, - 0x0001e91b, 0x0001e93d, 0x00010d58, 0x00010d78, - 0x00002c22, 0x00002c52, 0x00001e18, 0x00001e19, - 0x00001e76, 0x00001e77, 0x00016e58, 0x00016e78, - 0x0000020a, 0x0000020b, 0x0001041f, 0x00010447, - 0x0000a658, 0x0000a659, 0x00001ec2, 0x00001ec3, - 0x00002183, 0x00002184, 0x000000d1, 0x000000f1, - 0x0000014e, 0x0000014f, 0x000004c3, 0x000004c4, - 0x00001f0b, 0x00001f03, 0x0000a726, 0x0000a727, - 0x00001ca8, 0x000010e8, 0x00001e7a, 0x00001e7b, - 0x0000ab99, 0x000013c9, 0x00000053, 0x00000073, - 0x00001fa4, 0x02000233, 0x00001fa1, 0x0200022a, - 0x00001eac, 0x00001ead, 0x00010d57, 0x00010d77, - 0x000104b4, 0x000104dc, 0x0001040d, 0x00010435, - 0x00000405, 0x00000455, 0x00001edc, 0x00001edd, - 0x000118bb, 0x000118db, 0x000001d3, 0x000001d4, - 0x00002c05, 0x00002c35, 0x00002cf2, 0x00002cf3, - 0x0000041e, 0x0000043e, 0x00001f6f, 0x00001f67, - 0x0000ab71, 0x000013a1, 0x00016e5b, 0x00016e7b, - 0x000104d2, 0x000104fa, 0x00001f4d, 0x00001f45, - 0x00001ffc, 0x020002ae, 0x00010421, 0x00010449, - 0x000001ca, 0x000001cc, 0x0000021e, 0x0000021f, - 0x00001f95, 0x02000206, 0x00001fdb, 0x00001f77, - 0x00001eca, 0x00001ecb, 0x00001fc4, 0x02000270, - 0x00010578, 0x0001059f, 0x000000de, 0x000000fe, - 0x00002c94, 0x00002c95, 0x00000554, 0x00000584, - 0x000118ae, 0x000118ce, 0x0000aba0, 0x000013d0, - 0x00000122, 0x00000123, 0x0000a7b3, 0x0000ab53, - 0x0000040d, 0x0000045d, 0x0000048a, 0x0000048b, - 0x00001fac, 0x0200024b, 0x00000248, 0x00000249, - 0x00000166, 0x00000167, 0x00000541, 0x00000571, - 0x00001f83, 0x020001d0, 0x00002c26, 0x00002c56, - 0x00001e72, 0x00001e73, 0x000104bd, 0x000104e5, - 0x0000a78b, 0x0000a78c, 0x000000c5, 0x000000e5, - 0x00000522, 0x00000523, 0x000003de, 0x000003df, - 0x00001c82, 0x0000043e, 0x0000ab9d, 0x000013cd, - 0x00000116, 0x00000117, 0x0000a66c, 0x0000a66d, - 0x00001ed6, 0x00001ed7, 0x0000047e, 0x0000047f, - 0x00000198, 0x00000199, 0x000118a7, 0x000118c7, - 0x000001ae, 0x00000288, 0x00000047, 0x00000067, - 0x00001f92, 0x020001fd, 0x0000050c, 0x0000050d, - 0x00000396, 0x000003b6, 0x000001f2, 0x000001f3, - 0x00002c25, 0x00002c55, 0x000000b5, 0x000003bc, - 0x00001e97, 0x020001a9, 0x00001e4c, 0x00001e4d, - 0x00000393, 0x000003b3, 0x00010caa, 0x00010cea, - 0x000118bf, 0x000118df, 0x00002cb4, 0x00002cb5, - 0x00001ec0, 0x00001ec1, 0x0001e907, 0x0001e929, - 0x0001e918, 0x0001e93a, 0x0000fb01, 0x020002b4, - 0x00002c08, 0x00002c38, 0x000000ce, 0x000000ee, - 0x000004ae, 0x000004af, 0x00001cac, 0x000010ec, - 0x00000194, 0x00000263, 0x000001e6, 0x000001e7, - 0x0000a73c, 0x0000a73d, 0x00001fa6, 0x02000239, - 0x0000054e, 0x0000057e, 0x0000ff2e, 0x0000ff4e, - 0x000003a1, 0x000003c1, 0x000004c7, 0x000004c8, - 0x00001f87, 0x020001dc, 0x00001efe, 0x00001eff, - 0x00000404, 0x00000454, 0x00001f2d, 0x00001f25, - 0x00002c2d, 0x00002c5d, 0x00002caa, 0x00002cab, - 0x0000a692, 0x0000a693, 0x00000200, 0x00000201, - 0x0000048c, 0x0000048d, 0x00010d65, 0x00010d85, - 0x00000186, 0x00000254, 0x00010ca9, 0x00010ce9, - 0x0000053f, 0x0000056f, 0x000001d1, 0x000001d2, - 0x00010401, 0x00010429, 0x00010c9a, 0x00010cda, - 0x000024c9, 0x000024e3, 0x00001f91, 0x020001fa, - 0x00000504, 0x00000505, 0x000003a6, 0x000003c6, - 0x00001cab, 0x000010eb, 0x0000216f, 0x0000217f, - 0x000024b7, 0x000024d1, 0x00002c9e, 0x00002c9f, - 0x00001e66, 0x00001e67, 0x0000a7dc, 0x0000019b, - 0x0000ab9c, 0x000013cc, 0x00016e57, 0x00016e77, - 0x00016e4b, 0x00016e6b, 0x00001f0f, 0x00001f07, - 0x00000422, 0x00000442, 0x000004d4, 0x000004d5, - 0x0000abaf, 0x000013df, 0x00000508, 0x00000509, - 0x0000a7b6, 0x0000a7b7, 0x00001f80, 0x020001c7, - 0x000004bc, 0x000004bd, 0x00001e2c, 0x00001e2d, - 0x00001ea6, 0x00001ea7, 0x00010d54, 0x00010d74, - 0x00001f99, 0x02000212, 0x000004f0, 0x000004f1, - 0x0000a786, 0x0000a787, 0x0001041e, 0x00010446, - 0x00001c80, 0x00000432, 0x00000551, 0x00000581, - 0x00002cce, 0x00002ccf, 0x00001ed2, 0x00001ed3, - 0x00000476, 0x00000477, 0x000118a0, 0x000118c0, - 0x00001e0e, 0x00001e0f, 0x00010589, 0x000105b0, - 0x00002c12, 0x00002c42, 0x0000042d, 0x0000044d, - 0x000104ce, 0x000104f6, 0x00001e0c, 0x00001e0d, - 0x00001ca1, 0x000010e1, 0x000010c7, 0x00002d27, - 0x00002c24, 0x00002c54, 0x00000552, 0x00000582, - 0x000010cd, 0x00002d2d, 0x0000ab77, 0x000013a7, - 0x00010cae, 0x00010cee, 0x000010ac, 0x00002d0c, - 0x0000052a, 0x0000052b, 0x00000418, 0x00000438, - 0x0000a764, 0x0000a765, 0x0001e904, 0x0001e926, - 0x0000053a, 0x0000056a, 0x000024bb, 0x000024d5, - 0x00001fe6, 0x02000297, 0x0000ab90, 0x000013c0, - 0x000010a6, 0x00002d06, 0x00001e4a, 0x00001e4b, - 0x000118bc, 0x000118dc, 0x0000a7b2, 0x0000029d, - 0x00001fa2, 0x0200022d, 0x00000546, 0x00000576, - 0x000003f1, 0x000003c1, 0x00002c75, 0x00002c76, - 0x000104bb, 0x000104e3, 0x000010c0, 0x00002d20, - 0x00001e64, 0x00001e65, 0x00001eb0, 0x00001eb1, - 0x000003a7, 0x000003c7, 0x00010d56, 0x00010d76, - 0x00002ca2, 0x00002ca3, 0x00000537, 0x00000567, - 0x0001057a, 0x000105a1, 0x0000049c, 0x0000049d, - 0x00002c0f, 0x00002c3f, 0x0000017f, 0x00000073, - 0x00002cdc, 0x00002cdd, 0x00010c92, 0x00010cd2, - 0x000004e8, 0x000004e9, 0x00001f8e, 0x020001f1, - 0x00002c27, 0x00002c57, 0x0000a782, 0x0000a783, - 0x00001f97, 0x0200020c, 0x00001f3d, 0x00001f35, - 0x0000052e, 0x0000052f, 0x000010a5, 0x00002d05, - 0x00000044, 0x00000064, 0x000000dd, 0x000000fd, - 0x00002c96, 0x00002c97, 0x0000a7ba, 0x0000a7bb, - 0x000010b8, 0x00002d18, 0x00001c91, 0x000010d1, - 0x00000124, 0x00000125, 0x00016e4d, 0x00016e6d, - 0x00001ee8, 0x00001ee9, 0x0000ab8c, 0x000013bc, - 0x000118a5, 0x000118c5, 0x00001c94, 0x000010d4, - 0x00010590, 0x000105b7, 0x00000049, 0x00000069, - 0x000000c0, 0x000000e0, 0x00001ff4, 0x020002a4, - 0x0000ab7f, 0x000013af, 0x0000021c, 0x0000021d, - 0x0000a75e, 0x0000a75f, 0x00001fbb, 0x00001f71, - 0x00016e50, 0x00016e70, 0x000003e0, 0x000003e1, - 0x0000042e, 0x0000044e, 0x0001e91f, 0x0001e941, - 0x00000110, 0x00000111, 0x00000403, 0x00000453, - 0x00001e8a, 0x00001e8b, 0x000104c0, 0x000104e8, - 0x00001fd2, 0x0300027d, 0x000104b9, 0x000104e1, - 0x0000a686, 0x0000a687, 0x0000a7d0, 0x0000a7d1, - 0x00010c90, 0x00010cd0, 0x0000050e, 0x0000050f, - 0x000001c7, 0x000001c9, 0x000001f4, 0x000001f5, - 0x000000df, 0x0200018f, 0x00001fb8, 0x00001fb0, - 0x0000a7a6, 0x0000a7a7, 0x00000189, 0x00000256, - 0x0000a684, 0x0000a685, 0x00002ced, 0x00002cee, - 0x0000a796, 0x0000a797, 0x00002cbc, 0x00002cbd, - 0x0000ab8b, 0x000013bb, 0x0001e909, 0x0001e92b, - 0x0000abb9, 0x000013e9, 0x00010d61, 0x00010d81, - 0x00010584, 0x000105ab, 0x00001f9d, 0x0200021e, - 0x000004b0, 0x000004b1, 0x0001e90c, 0x0001e92e, - 0x00010caf, 0x00010cef, 0x000001e0, 0x000001e1, - 0x00001f5f, 0x00001f57, 0x00002c16, 0x00002c46, - 0x00010425, 0x0001044d, 0x00001cb0, 0x000010f0, - 0x00001cae, 0x000010ee, 0x000004c1, 0x000004c2, - 0x00010cb1, 0x00010cf1, 0x000013f9, 0x000013f1, - 0x00001eee, 0x00001eef, 0x00010585, 0x000105ac, - 0x000000c4, 0x000000e4, 0x0000a65a, 0x0000a65b, - 0x0000a694, 0x0000a695, 0x00010c85, 0x00010cc5, - 0x0001e900, 0x0001e922, 0x00010587, 0x000105ae, - 0x00000182, 0x00000183, 0x00002c21, 0x00002c51, - 0x0000ab8a, 0x000013ba, 0x00000202, 0x00000203, - 0x00000555, 0x00000585, 0x00001e46, 0x00001e47, - 0x00000046, 0x00000066, 0x00001e06, 0x00001e07, - 0x0000ab97, 0x000013c7, 0x000003a8, 0x000003c8, - 0x000003a3, 0x000003c3, 0x00002c23, 0x00002c53, - 0x00000162, 0x00000163, 0x00010415, 0x0001043d, - 0x00001ef2, 0x00001ef3, 0x00001fd6, 0x02000285, - 0x0001e921, 0x0001e943, 0x0000038a, 0x000003af, - 0x0000a648, 0x0000a649, 0x00000540, 0x00000570, - 0x0000049a, 0x0000049b, 0x00002c6b, 0x00002c6c, - 0x00001e16, 0x00001e17, 0x000001bc, 0x000001bd, - 0x0001057e, 0x000105a5, 0x00001f81, 0x020001ca, - 0x00000429, 0x00000449, 0x000010b6, 0x00002d16, - 0x0000039d, 0x000003bd, 0x0000fb13, 0x020002c8, - 0x000003ec, 0x000003ed, 0x0000216b, 0x0000217b, - 0x00000208, 0x00000209, 0x0000ff3a, 0x0000ff5a, - 0x0000ab83, 0x000013b3, 0x0000a7c6, 0x00001d8e, - 0x00002cd0, 0x00002cd1, 0x00001ebc, 0x00001ebd, - 0x00000478, 0x00000479, 0x00000048, 0x00000068, - 0x000001f7, 0x000001bf, 0x0000010c, 0x0000010d, - 0x00000149, 0x02000195, 0x00000542, 0x00000572, - 0x00010406, 0x0001042e, 0x00000181, 0x00000253, - 0x00010412, 0x0001043a, 0x000010c5, 0x00002d25, - 0x00001f4a, 0x00001f42, 0x0000a760, 0x0000a761, - 0x000104ba, 0x000104e2, 0x000010bf, 0x00002d1f, - 0x0001e916, 0x0001e938, 0x00000535, 0x00000565, - 0x0000a65c, 0x0000a65d, 0x00001ec6, 0x00001ec7, - 0x0000ab70, 0x000013a0, 0x0000ab9a, 0x000013ca, - 0x0000014a, 0x0000014b, 0x0000a72e, 0x0000a72f, - 0x0000039b, 0x000003bb, 0x000004a2, 0x000004a3, - 0x0000a7cb, 0x00000264, 0x0000019c, 0x0000026f, - 0x0001e91d, 0x0001e93f, 0x00001f59, 0x00001f51, - 0x00001f56, 0x030001c3, 0x00000548, 0x00000578, - 0x00002c09, 0x00002c39, 0x00000054, 0x00000074, - 0x0000039f, 0x000003bf, 0x00001ff7, 0x030002aa, - 0x00001e68, 0x00001e69, 0x00001e80, 0x00001e81, - 0x0001041c, 0x00010444, 0x00000244, 0x00000289, - 0x0000216e, 0x0000217e, 0x00002c19, 0x00002c49, - 0x000004fa, 0x000004fb, 0x0000049e, 0x0000049f, - 0x0001e90d, 0x0001e92f, 0x00000184, 0x00000185, - 0x00000531, 0x00000561, 0x00000042, 0x00000062, - 0x00001faa, 0x02000245, 0x000003ab, 0x000003cb, - 0x00001ca9, 0x000010e9, 0x0000021a, 0x0000021b, - 0x00002cae, 0x00002caf, 0x00001fe2, 0x0300028c, - 0x00001f82, 0x020001cd, 0x00000376, 0x00000377, - 0x0000a77d, 0x00001d79, 0x000000d9, 0x000000f9, - 0x00002c98, 0x00002c99, 0x00001ea0, 0x00001ea1, - 0x00001ebe, 0x00001ebf, 0x0000ff2a, 0x0000ff4a, - 0x000003f5, 0x000003b5, 0x00000500, 0x00000501, - 0x0000216a, 0x0000217a, 0x00001f38, 0x00001f30, - 0x0000ab98, 0x000013c8, 0x0000ff26, 0x0000ff46, - 0x000003a5, 0x000003c5, 0x000001b7, 0x00000292, - 0x000118bd, 0x000118dd, 0x00002ca4, 0x00002ca5, - 0x00001e1e, 0x00001e1f, 0x00000423, 0x00000443, - 0x00002cb8, 0x00002cb9, 0x000000cc, 0x000000ec, - 0x00002c04, 0x00002c34, 0x00001e8e, 0x00001e8f, - 0x00001f98, 0x0200020f, 0x0000aba9, 0x000013d9, - 0x000001a2, 0x000001a3, 0x00002cc2, 0x00002cc3, - 0x00001e86, 0x00001e87, 0x000004f6, 0x000004f7, - 0x00001c93, 0x000010d3, 0x00001c83, 0x00000441, - 0x000001a9, 0x00000283, 0x00002c72, 0x00002c73, - 0x000004d6, 0x000004d7, 0x00000510, 0x00000511, - 0x00000388, 0x000003ad, 0x00010405, 0x0001042d, - 0x000024c0, 0x000024da, 0x00002c17, 0x00002c47, - 0x000013fd, 0x000013f5, 0x000010b2, 0x00002d12, - 0x0000023a, 0x00002c65, 0x0000a7b0, 0x0000029e, - 0x000001a6, 0x00000280, 0x00002cbe, 0x00002cbf, - 0x00001ec4, 0x00001ec5, 0x00001f3b, 0x00001f33, - 0x000000cf, 0x000000ef, 0x00010404, 0x0001042c, - 0x00016e5e, 0x00016e7e, 0x00001f1d, 0x00001f15, - 0x0000a790, 0x0000a791, 0x00001c92, 0x000010d2, - 0x00001e42, 0x00001e43, 0x00002c14, 0x00002c44, - 0x00001fa9, 0x02000242, 0x000104d1, 0x000104f9, - 0x00001ca5, 0x000010e5, 0x00001f90, 0x020001f7, - 0x0001057d, 0x000105a4, 0x000024c7, 0x000024e1, - 0x00002c60, 0x00002c61, 0x00002cba, 0x00002cbb, - 0x00000408, 0x00000458, 0x00016e43, 0x00016e63, - 0x00000246, 0x00000247, 0x0000013b, 0x0000013c, - 0x0000a696, 0x0000a697, 0x00001e44, 0x00001e45, - 0x000004ee, 0x000004ef, 0x0001e90f, 0x0001e931, - 0x000004cb, 0x000004cc, 0x00001cad, 0x000010ed, - 0x000001a0, 0x000001a1, 0x0000abba, 0x000013ea, - 0x00010572, 0x00010599, 0x00000174, 0x00000175, - 0x0001040a, 0x00010432, 0x00010c93, 0x00010cd3, - 0x00000528, 0x00000529, 0x0000042f, 0x0000044f, - 0x0000ab92, 0x000013c2, 0x00000417, 0x00000437, - 0x0000a74a, 0x0000a74b, 0x000010ad, 0x00002d0d, - 0x00001ea2, 0x00001ea3, 0x00001e88, 0x00001e89, - 0x0000ab87, 0x000013b7, 0x00010426, 0x0001044e, - 0x00000176, 0x00000177, 0x00010594, 0x000105bb, - 0x00001fc6, 0x02000273, 0x000004d8, 0x000004d9, - 0x000118a2, 0x000118c2, 0x00010d53, 0x00010d73, - 0x0000ff38, 0x0000ff58, 0x00001fa8, 0x0200023f, - 0x00000526, 0x00000527, 0x00001fc2, 0x0200026a, - 0x0000ab96, 0x000013c6, 0x0000a758, 0x0000a759, - 0x00001fd3, 0x03000281, 0x00002c06, 0x00002c36, - 0x00001efc, 0x00001efd, 0x0000042a, 0x0000044a, - 0x0000ab8d, 0x000013bd, 0x00010423, 0x0001044b, - 0x00000114, 0x00000115, 0x00001f88, 0x020001df, - 0x0000047a, 0x0000047b, 0x000118ba, 0x000118da, - 0x0001e910, 0x0001e932, 0x00002c15, 0x00002c45, - 0x000013fb, 0x000013f3, 0x00001eb8, 0x00001eb9, - 0x0000051a, 0x0000051b, 0x00010c8a, 0x00010cca, - 0x00010ca0, 0x00010ce0, 0x000118be, 0x000118de, - 0x00002c28, 0x00002c58, 0x00001e54, 0x00001e55, - 0x000003d0, 0x000003b2, 0x0000a7ab, 0x0000025c, - 0x0000ff29, 0x0000ff49, 0x000024cc, 0x000024e6, - 0x0000a65e, 0x0000a65f, 0x0000abbd, 0x000013ed, - 0x00010580, 0x000105a7, 0x0000a7c5, 0x00000282, - 0x0000004e, 0x0000006e, 0x000118b2, 0x000118d2, - 0x00001fb3, 0x0200025a, 0x00000494, 0x00000495, - 0x00001f94, 0x02000203, 0x0000fb05, 0x020002c2, - 0x000013fc, 0x000013f4, 0x00010403, 0x0001042b, - 0x0000ab86, 0x000013b6, 0x0000054a, 0x0000057a, - 0x0000a7d8, 0x0000a7d9, 0x00000230, 0x00000231, - 0x00001c89, 0x00001c8a, 0x000010a1, 0x00002d01, - 0x0000a64e, 0x0000a64f, 0x00001e2e, 0x00001e2f, - 0x0000022a, 0x0000022b, 0x000000c8, 0x000000e8, - 0x00000553, 0x00000583, 0x000024c2, 0x000024dc, - 0x00010ca2, 0x00010ce2, 0x000004a0, 0x000004a1, - 0x0000ab85, 0x000013b5, 0x00001e14, 0x00001e15, - 0x0000a64a, 0x0000a64b, 0x00001f4c, 0x00001f44, - 0x00001fe3, 0x03000290, 0x00001e60, 0x00001e61, - 0x000003aa, 0x000003ca, 0x0000212b, 0x000000e5, - 0x00010c99, 0x00010cd9, 0x00001f52, 0x030001bb, - 0x00000409, 0x00000459, 0x0000abad, 0x000013dd, - 0x00001cb4, 0x000010f4, 0x00002c02, 0x00002c32, - 0x00002c9a, 0x00002c9b, 0x00001ec8, 0x00001ec9, - 0x000118b7, 0x000118d7, 0x00000210, 0x00000211, - 0x00010422, 0x0001044a, 0x00016e51, 0x00016e71, - 0x0000ff22, 0x0000ff42, 0x00001f3f, 0x00001f37, - 0x000010c3, 0x00002d23, 0x0000ab8f, 0x000013bf, - 0x00010402, 0x0001042a, 0x00010d52, 0x00010d72, - 0x000000d8, 0x000000f8, 0x0001058a, 0x000105b1, - 0x00000398, 0x000003b8, 0x000104c2, 0x000104ea, - 0x00002165, 0x00002175, 0x000000cb, 0x000000eb, - 0x00002c07, 0x00002c37, 0x0000ff31, 0x0000ff51, - 0x000104c9, 0x000104f1, 0x0001040f, 0x00010437, - 0x00010d55, 0x00010d75, 0x00000544, 0x00000574, - 0x000118a1, 0x000118c1, 0x00001fca, 0x00001f74, - 0x000003fd, 0x0000037b, 0x0001041a, 0x00010442, - 0x0000010a, 0x0000010b, 0x0000ff34, 0x0000ff54, - 0x00001f96, 0x02000209, 0x00000512, 0x00000513, - 0x000001a4, 0x000001a5, 0x000001fe, 0x000001ff, - 0x00002c1b, 0x00002c4b, 0x0000aba8, 0x000013d8, - 0x00001e30, 0x00001e31, 0x0000a7a8, 0x0000a7a9, - 0x000003d1, 0x000003b8, 0x00001cbd, 0x000010fd, - 0x00010582, 0x000105a9, 0x00002cc0, 0x00002cc1, - 0x00000416, 0x00000436, 0x00000468, 0x00000469, - 0x00010ca1, 0x00010ce1, 0x000001b3, 0x000001b4, - 0x00010400, 0x00010428, 0x0000a75a, 0x0000a75b, - 0x000004b4, 0x000004b5, 0x0000a79e, 0x0000a79f, - 0x0001e91c, 0x0001e93e, 0x0000053b, 0x0000056b, - 0x00002c29, 0x00002c59, 0x00002c18, 0x00002c48, - 0x00001e24, 0x00001e25, 0x0000004a, 0x0000006a, - 0x0000a7a4, 0x0000a7a5, 0x00002168, 0x00002178, - 0x00002c62, 0x0000026b, 0x0000a72c, 0x0000a72d, - 0x0000040a, 0x0000045a, 0x00001c97, 0x000010d7, - 0x00002c6f, 0x00000250, 0x00000345, 0x000003b9, - 0x0000a698, 0x0000a699, 0x0000ff23, 0x0000ff43, - 0x0000a766, 0x0000a767, 0x0000abb1, 0x000013e1, - 0x00010420, 0x00010448, 0x0000a762, 0x0000a763, - 0x00001e84, 0x00001e85, 0x000004e6, 0x000004e7, - 0x00000160, 0x00000161, 0x00016e52, 0x00016e72, - 0x00000216, 0x00000217, 0x00001e50, 0x00001e51, - 0x00001f69, 0x00001f61, 0x00001eae, 0x00001eaf, - 0x000003fa, 0x000003fb, 0x00010c94, 0x00010cd4, - 0x000000dc, 0x000000fc, 0x00000545, 0x00000575, - 0x0000040f, 0x0000045f, 0x00001ef4, 0x00001ef5, - 0x000003f4, 0x000003b8, 0x0000023b, 0x0000023c, - 0x0000216c, 0x0000217c, 0x00002c1f, 0x00002c4f, - 0x0000ab7e, 0x000013ae, 0x000004da, 0x000004db, - 0x000001d5, 0x000001d6, 0x00010d5a, 0x00010d7a, - 0x00002c70, 0x00000252, 0x0000a682, 0x0000a683, - 0x0000fb06, 0x020002c5, 0x00001e20, 0x00001e21, - 0x000003e4, 0x000003e5, 0x000003d5, 0x000003c6, - 0x000000c9, 0x000000e9, 0x00002c88, 0x00002c89, - 0x00000520, 0x00000521, 0x00001caf, 0x000010ef, - 0x0001e91e, 0x0001e940, 0x0000040b, 0x0000045b, - 0x00002cd4, 0x00002cd5, 0x00001f9c, 0x0200021b, - 0x0000047c, 0x0000047d, 0x00016e4a, 0x00016e6a, - 0x00016e47, 0x00016e67, 0x000001ac, 0x000001ad, - 0x00002c1c, 0x00002c4c, 0x0000ff27, 0x0000ff47, - 0x00000464, 0x00000465, 0x00001e7c, 0x00001e7d, - 0x000104b5, 0x000104dd, 0x0000054d, 0x0000057d, - 0x00002c2a, 0x00002c5a, 0x000024bf, 0x000024d9, - 0x0000ab76, 0x000013a6, 0x00001c85, 0x00000442, - 0x00010ca4, 0x00010ce4, 0x00000100, 0x00000101, - 0x0000a660, 0x0000a661, 0x00001e32, 0x00001e33, - 0x0001e908, 0x0001e92a, 0x00010c8e, 0x00010cce, - 0x000001a7, 0x000001a8, 0x000024bd, 0x000024d7, - 0x00000533, 0x00000563, 0x000118b9, 0x000118d9, - 0x00010c86, 0x00010cc6, 0x00001e3e, 0x00001e3f, - 0x00010ca8, 0x00010ce8, 0x00000059, 0x00000079, - 0x00002c1a, 0x00002c4a, 0x0000054c, 0x0000057c, - 0x000010a9, 0x00002d09, 0x000104c5, 0x000104ed, - 0x00002c2f, 0x00002c5f, 0x00001ffb, 0x00001f7d, - 0x00001cbe, 0x000010fe, 0x00010cab, 0x00010ceb, - 0x00000206, 0x00000207, 0x000010a7, 0x00002d07, - 0x000010aa, 0x00002d0a, 0x000104cf, 0x000104f7, - 0x0000ff21, 0x0000ff41, 0x00010427, 0x0001044f, - 0x00001c9d, 0x000010dd, 0x000104bf, 0x000104e7, - 0x00002ceb, 0x00002cec, 0x0000ab82, 0x000013b2, - 0x0000a75c, 0x0000a75d, 0x00001e96, 0x020001a6, - 0x00000172, 0x00000173, 0x0000a73a, 0x0000a73b, - 0x00002c13, 0x00002c43, 0x00001ff3, 0x020002a1, - 0x00000413, 0x00000433, 0x000001d9, 0x000001da, - 0x00000218, 0x00000219, 0x000000da, 0x000000fa, - 0x00002c9c, 0x00002c9d, 0x00002ca6, 0x00002ca7, - 0x0000ab7c, 0x000013ac, 0x0000ab81, 0x000013b1, - 0x000010b4, 0x00002d14, 0x00016e53, 0x00016e73, - 0x000024c8, 0x000024e2, 0x00001e78, 0x00001e79, - 0x000004fc, 0x000004fd, 0x0000018f, 0x00000259, - 0x000010bc, 0x00002d1c, 0x0000a722, 0x0000a723, - 0x00010c83, 0x00010cc3, 0x000104d0, 0x000104f8, - 0x0000039a, 0x000003ba, 0x00001eb2, 0x00001eb3, - 0x0000a756, 0x0000a757, 0x00001f09, 0x00001f01, - 0x00002163, 0x00002173, 0x00001e92, 0x00001e93, - 0x0000ab7a, 0x000013aa, 0x00010574, 0x0001059b, - 0x000001af, 0x000001b0, 0x0000015c, 0x0000015d, - 0x00001ede, 0x00001edf, 0x0000046e, 0x0000046f, - 0x000003ea, 0x000003eb, 0x000104d3, 0x000104fb, - 0x00000190, 0x0000025b, 0x0000a742, 0x0000a743, - 0x00001f8a, 0x020001e5, 0x00000514, 0x00000515, - 0x00001e0a, 0x00001e0b, 0x000001c4, 0x000001c6, - 0x0000a748, 0x0000a749, 0x00001fc3, 0x0200026d, - 0x00001e34, 0x00001e35, 0x00001eb4, 0x00001eb5, - 0x000010b9, 0x00002d19, 0x0000a784, 0x0000a785, - 0x00000407, 0x00000457, 0x0000a66a, 0x0000a66b, - 0x000010a8, 0x00002d08, 0x0000046a, 0x0000046b, - 0x00010c9f, 0x00010cdf, 0x00000150, 0x00000151, - 0x00002c1d, 0x00002c4d, 0x00001f1c, 0x00001f14, - 0x0000ff25, 0x0000ff45, 0x00000108, 0x00000109, - 0x00002c00, 0x00002c30, 0x0001040e, 0x00010436, - 0x0000a746, 0x0000a747, 0x00001fae, 0x02000251, - 0x0001058d, 0x000105b4, 0x00010c98, 0x00010cd8, - 0x00016e44, 0x00016e64, 0x00002c67, 0x00002c68, - 0x00002c64, 0x0000027d, 0x00001e6c, 0x00001e6d, - 0x0000040c, 0x0000045c, 0x000104b7, 0x000104df, - 0x0000a640, 0x0000a641, 0x000118b4, 0x000118d4, - 0x0000a69a, 0x0000a69b, 0x00001fd9, 0x00001fd1, - 0x0001e90b, 0x0001e92d, 0x000003f9, 0x000003f2, - 0x00016e59, 0x00016e79, 0x0000ab9f, 0x000013cf, - 0x0000ab8e, 0x000013be, 0x00001fe4, 0x02000294, - 0x00001e52, 0x00001e53, 0x00016e4e, 0x00016e6e, - 0x00000220, 0x0000019e, 0x000104c4, 0x000104ec, - 0x00001fec, 0x00001fe5, 0x00001e5a, 0x00001e5b, - 0x00001cb9, 0x000010f9, 0x0000ab75, 0x000013a5, - 0x00000104, 0x00000105, 0x00002c8e, 0x00002c8f, - 0x000118ad, 0x000118cd, 0x0000abbf, 0x000013ef, - 0x0000abbb, 0x000013eb, 0x0001e90e, 0x0001e930, - 0x00010d60, 0x00010d80, 0x00002ca8, 0x00002ca9, - 0x00001f3c, 0x00001f34, 0x000004dc, 0x000004dd, - 0x00010591, 0x000105b8, 0x00001e48, 0x00001e49, - 0x0000a650, 0x0000a651, 0x0000abae, 0x000013de, - 0x000118b0, 0x000118d0, 0x0001e914, 0x0001e936, - 0x00001cba, 0x000010fa, 0x0001e91a, 0x0001e93c, - 0x000000c7, 0x000000e7, 0x00002c8a, 0x00002c8b, - 0x00001e9e, 0x020001b5, 0x000004f8, 0x000004f9, - 0x000104b6, 0x000104de, 0x00010407, 0x0001042f, - 0x000104ca, 0x000104f2, 0x00001eb6, 0x00001eb7, - 0x00001f2a, 0x00001f22, 0x00001f9f, 0x02000224, - 0x00000139, 0x0000013a, 0x00000106, 0x00000107, - 0x000118b1, 0x000118d1, 0x0000abb4, 0x000013e4, - 0x0000051e, 0x0000051f, 0x00010d50, 0x00010d70, - 0x000001e8, 0x000001e9, 0x00016e4c, 0x00016e6c, - 0x00002c2c, 0x00002c5c, 0x00000401, 0x00000451, - 0x00001f39, 0x00001f31, 0x0000024e, 0x0000024f, - 0x000024ce, 0x000024e8, 0x0000a7c0, 0x0000a7c1, - 0x0000a662, 0x0000a663, 0x00000539, 0x00000569, - 0x000104c1, 0x000104e9, 0x000104b8, 0x000104e0, - 0x00000543, 0x00000573, 0x00010410, 0x00010438, - 0x00001f1b, 0x00001f13, 0x00001f6e, 0x00001f66, - 0x00001fd7, 0x03000288, 0x00001c96, 0x000010d6, - 0x000118aa, 0x000118ca, 0x00010414, 0x0001043c, - 0x00001fb9, 0x00001fb1, 0x0000abaa, 0x000013da, - 0x00000389, 0x000003ae, 0x00000232, 0x00000233, - 0x00002cb0, 0x00002cb1, 0x00002c6e, 0x00000271, - 0x00001e6e, 0x00001e6f, 0x0000ab93, 0x000013c3, - 0x0001e90a, 0x0001e92c, 0x0000a740, 0x0000a741, - 0x000118a3, 0x000118c3, 0x0000052c, 0x0000052d, - 0x00001ffa, 0x00001f7c, 0x000004a4, 0x000004a5, - 0x00010d5d, 0x00010d7d, 0x0000018a, 0x00000257, - 0x000001d7, 0x000001d8, 0x0000004d, 0x0000006d, - 0x000004f2, 0x000004f3, 0x00000164, 0x00000165, - 0x000010b7, 0x00002d17, 0x00002160, 0x00002170, - 0x0000a7b4, 0x0000a7b5, 0x00001feb, 0x00001f7b, - 0x00001e58, 0x00001e59, 0x00001eda, 0x00001edb, - 0x00010d5c, 0x00010d7c, 0x000010ae, 0x00002d0e, - 0x000001db, 0x000001dc, 0x0000a688, 0x0000a689, - 0x00000411, 0x00000431, 0x000104b3, 0x000104db, - 0x00002c01, 0x00002c31, 0x00016e55, 0x00016e75, - 0x0000a7a2, 0x0000a7a3, 0x00001f3e, 0x00001f36, - 0x0000054b, 0x0000057b, 0x0000024a, 0x0000024b, - 0x00001e74, 0x00001e75, 0x000118a6, 0x000118c6, - 0x00001f8d, 0x020001ee, 0x00002c7f, 0x00000240, - 0x0000039c, 0x000003bc, 0x000003fe, 0x0000037c, - 0x00000052, 0x00000072, 0x000024cb, 0x000024e5, - 0x00016e5a, 0x00016e7a, 0x0000ff35, 0x0000ff55, - 0x00001f2b, 0x00001f23, 0x000104c7, 0x000104ef, - 0x0000011e, 0x0000011f, 0x00002164, 0x00002174, - 0x0000a7c9, 0x0000a7ca, 0x00001f28, 0x00001f20, - 0x0000ab79, 0x000013a9, 0x00000126, 0x00000127, - 0x00010588, 0x000105af, 0x0000020e, 0x0000020f, - 0x0000abb2, 0x000013e2, 0x00000516, 0x00000517, - 0x0000019f, 0x00000275, 0x000001fc, 0x000001fd, - 0x0000a7a0, 0x0000a7a1, 0x00001f0d, 0x00001f05, - 0x00001ece, 0x00001ecf, 0x00000193, 0x00000260, - 0x0000ab7d, 0x000013ad, 0x00001ca4, 0x000010e4, - 0x000010b0, 0x00002d10, 0x00002cc4, 0x00002cc5, - 0x00001f1a, 0x00001f12, 0x0000046c, 0x0000046d, - 0x00002126, 0x000003c9, 0x00016e45, 0x00016e65, - 0x00002c0a, 0x00002c3a, 0x00001f18, 0x00001f10, - 0x00000524, 0x00000525, 0x0001041b, 0x00010443, - 0x00001caa, 0x000010ea, 0x000001ee, 0x000001ef, - 0x00000051, 0x00000071, 0x0000053e, 0x0000056e, - 0x00001e28, 0x00001e29, 0x0001e915, 0x0001e937, - 0x000010c4, 0x00002d24, 0x00002c84, 0x00002c85, - 0x00001ff9, 0x00001f79, 0x00001ff6, 0x020002a7, - 0x0000040e, 0x0000045e, 0x0000fb14, 0x020002cb, - 0x00001cb1, 0x000010f1, 0x00010d63, 0x00010d83, - 0x00000498, 0x00000499, 0x000010b1, 0x00002d11, - 0x0000a79a, 0x0000a79b, 0x0000a7bc, 0x0000a7bd, - 0x00010d5b, 0x00010d7b, 0x00010d5e, 0x00010d7e, - 0x00010ca7, 0x00010ce7, 0x00002c1e, 0x00002c4e, - 0x000024c4, 0x000024de, 0x0000038f, 0x000003ce, - 0x0000a7f5, 0x0000a7f6, 0x0000012e, 0x0000012f, - 0x00001fe8, 0x00001fe0, 0x00001eea, 0x00001eeb, - 0x000003f0, 0x000003ba, 0x00001f0e, 0x00001f06, - 0x00000058, 0x00000078, 0x00002cac, 0x00002cad, - 0x00010575, 0x0001059c, 0x00001ef8, 0x00001ef9, - 0x00000397, 0x000003b7, 0x00010c82, 0x00010cc2, - 0x000024c1, 0x000024db, 0x00000532, 0x00000562, - 0x00000496, 0x00000497, 0x000004de, 0x000004df, - 0x00000170, 0x00000171, 0x00000415, 0x00000435, - 0x00000241, 0x00000242, 0x00001f85, 0x020001d6, - 0x00001e1c, 0x00001e1d, 0x000013fa, 0x000013f2, - 0x0001058f, 0x000105b6, 0x00010c97, 0x00010cd7, - 0x00000057, 0x00000077, 0x00002c8c, 0x00002c8d, - 0x00001ef0, 0x00001ef1, 0x000104c8, 0x000104f0, - 0x00001f2f, 0x00001f27, 0x00000112, 0x00000113, - 0x00010419, 0x00010441, 0x00000419, 0x00000439, - 0x00000480, 0x00000481, 0x0000ab9b, 0x000013cb, - 0x00010573, 0x0001059a, 0x00010409, 0x00010431, - 0x0000fb02, 0x020002b7, 0x00001fa5, 0x02000236, - 0x00000556, 0x00000586, 0x0000038e, 0x000003cd, - 0x000001fa, 0x000001fb, 0x000000d6, 0x000000f6, - 0x00002c2e, 0x00002c5e, 0x0000a76e, 0x0000a76f, - 0x000003d6, 0x000003c0, 0x00010577, 0x0001059e, - 0x000010ab, 0x00002d0b, 0x0000a77e, 0x0000a77f, - 0x0000a664, 0x0000a665, 0x00001ecc, 0x00001ecd, - 0x00000425, 0x00000445, 0x00001faf, 0x02000254, - 0x000024bc, 0x000024d6, 0x00016e42, 0x00016e62, - 0x00001fad, 0x0200024e, 0x000004b2, 0x000004b3, - 0x0000012c, 0x0000012d, 0x000104cd, 0x000104f5, - 0x000001e2, 0x000001e3, 0x000003cf, 0x000003d7, - 0x00002c10, 0x00002c40, 0x00000550, 0x00000580, - 0x0001057c, 0x000105a3, 0x00000204, 0x00000205, - 0x00002c03, 0x00002c33, 0x0000fb03, 0x030002ba, - 0x00001e22, 0x00001e23, 0x000010ba, 0x00002d1a, - 0x00000490, 0x00000491, 0x0000a74e, 0x0000a74f, - 0x00000145, 0x00000146, 0x0000a68e, 0x0000a68f, - 0x0000ab72, 0x000013a2, 0x000004a6, 0x000004a7, - 0x0000fb16, 0x020002d1, 0x0001e913, 0x0001e935, - 0x0000016e, 0x0000016f, 0x00001f50, 0x020001b8, - 0x00001f8b, 0x020001e8, 0x00001e3c, 0x00001e3d, - 0x00010c9b, 0x00010cdb, 0x0000a73e, 0x0000a73f, - 0x00000143, 0x00000144, 0x00000502, 0x00000503, - 0x00001e70, 0x00001e71, 0x00001cbf, 0x000010ff, - 0x00010ca6, 0x00010ce6, 0x000000cd, 0x000000ed, - 0x00002ca0, 0x00002ca1, 0x0000a68a, 0x0000a68b, - 0x0000ab89, 0x000013b9, 0x00001f48, 0x00001f40, - 0x00002c6d, 0x00000251, 0x00000178, 0x000000ff, - 0x0000212a, 0x0000006b, 0x00001fe7, 0x0300029a, - 0x0000a798, 0x0000a799, 0x0001e920, 0x0001e942, - 0x0001040b, 0x00010433, 0x00000055, 0x00000075, - 0x00010416, 0x0001043e, 0x00001f54, 0x030001bf, - 0x00000390, 0x0300019b, 0x000003e2, 0x000003e3, - 0x000024b8, 0x000024d2, 0x00010571, 0x00010598, - 0x0001e912, 0x0001e934, 0x0000ff37, 0x0000ff57, - 0x0000023d, 0x0000019a, 0x000024be, 0x000024d8, - 0x0000011a, 0x0000011b, 0x00002cd2, 0x00002cd3, - 0x000118b6, 0x000118d6, 0x0000041c, 0x0000043c, - 0x000000d5, 0x000000f5, 0x00010579, 0x000105a0, - 0x0000019d, 0x00000272, 0x000010b3, 0x00002d13, - 0x00010c81, 0x00010cc1, 0x00000518, 0x00000519, - 0x0000a752, 0x0000a753, 0x00000136, 0x00000137, - 0x00002c63, 0x00001d7d, 0x00001fc7, 0x03000276, - 0x00002c7e, 0x0000023f, 0x0000a7c7, 0x0000a7c8, - 0x0000042c, 0x0000044c, 0x00010408, 0x00010430, - 0x00010c9d, 0x00010cdd, 0x00002cc6, 0x00002cc7, - 0x00016e5c, 0x00016e7c, 0x00000460, 0x00000461, - 0x00001f8c, 0x020001eb, 0x00000154, 0x00000155, - 0x000004c9, 0x000004ca, 0x00001f19, 0x00001f11, - 0x00001f9e, 0x02000221, 0x00000386, 0x000003ac, - 0x00002c0b, 0x00002c3b, 0x000001ea, 0x000001eb, - 0x000010bb, 0x00002d1b, 0x0000abac, 0x000013dc, - 0x00000426, 0x00000446, 0x000118b5, 0x000118d5, - 0x0000024c, 0x0000024d, 0x000010af, 0x00002d0f, - 0x00001c9c, 0x000010dc, 0x00002cb6, 0x00002cb7, - 0x00000410, 0x00000430, 0x0000ff28, 0x0000ff48, - 0x0000038c, 0x000003cc, 0x000010c2, 0x00002d22, - 0x00000427, 0x00000447 + 0x00010d53, 0x00010d73, 0x000118b4, 0x000118d4, + 0x00001ca4, 0x000010e4, 0x00001ff2, 0x0200029e, + 0x0001057f, 0x000105a6, 0x00000149, 0x02000195, + 0x00001e44, 0x00001e45, 0x0000a768, 0x0000a769, + 0x000004dc, 0x000004dd, 0x00000506, 0x00000507, + 0x00000230, 0x00000231, 0x00001c92, 0x000010d2, + 0x0000051c, 0x0000051d, 0x00001f8f, 0x020001f4, + 0x000001d7, 0x000001d8, 0x0000abac, 0x000013dc, + 0x00001f3b, 0x00001f33, 0x00010ca9, 0x00010ce9, + 0x0000a7ac, 0x00000261, 0x00002c98, 0x00002c99, + 0x0000046a, 0x0000046b, 0x00016e53, 0x00016e73, + 0x00000549, 0x00000579, 0x0000a780, 0x0000a781, + 0x00001f52, 0x030001bb, 0x0001e904, 0x0001e926, + 0x0000aba0, 0x000013d0, 0x00001fae, 0x02000251, + 0x0000a7c2, 0x0000a7c3, 0x00000394, 0x000003b4, + 0x0001040f, 0x00010437, 0x00001eb4, 0x00001eb5, + 0x000001e4, 0x000001e5, 0x00010c9b, 0x00010cdb, + 0x000000cd, 0x000000ed, 0x00000386, 0x000003ac, + 0x0001041d, 0x00010445, 0x000104d3, 0x000104fb, + 0x000024c5, 0x000024df, 0x0000a7ab, 0x0000025c, + 0x00010d54, 0x00010d74, 0x00010caa, 0x00010cea, + 0x00001fe8, 0x00001fe0, 0x0000a694, 0x0000a695, + 0x00010580, 0x000105a7, 0x00002cb2, 0x00002cb3, + 0x00002cb4, 0x00002cb5, 0x00000553, 0x00000583, + 0x0000ff2f, 0x0000ff4f, 0x00000510, 0x00000511, + 0x0000a7dc, 0x0000019b, 0x00000170, 0x00000171, + 0x00001cbd, 0x000010fd, 0x00001f8e, 0x020001f1, + 0x00000132, 0x00000133, 0x0001041e, 0x00010446, + 0x0000047e, 0x0000047f, 0x00001ebc, 0x00001ebd, + 0x000118af, 0x000118cf, 0x000003d1, 0x000003b8, + 0x00000370, 0x00000371, 0x00016e54, 0x00016e74, + 0x000003d0, 0x000003b2, 0x00002c08, 0x00002c38, + 0x00010ca7, 0x00010ce7, 0x00000126, 0x00000127, + 0x00000423, 0x00000443, 0x00000428, 0x00000448, + 0x000010af, 0x00002d0f, 0x0000013d, 0x0000013e, + 0x00001f1b, 0x00001f13, 0x0000013f, 0x00000140, + 0x000001b5, 0x000001b6, 0x00010c9d, 0x00010cdd, + 0x00000147, 0x00000148, 0x00002cdc, 0x00002cdd, + 0x0000a734, 0x0000a735, 0x000004cb, 0x000004cc, + 0x0000fb16, 0x020002d1, 0x0000a72a, 0x0000a72b, + 0x00010d55, 0x00010d75, 0x0000019d, 0x00000272, + 0x000004c9, 0x000004ca, 0x000000dd, 0x000000fd, + 0x00010581, 0x000105a8, 0x000024c6, 0x000024e0, + 0x00000191, 0x00000192, 0x000118ab, 0x000118cb, + 0x0000ab74, 0x000013a4, 0x00000174, 0x00000175, + 0x0000a76e, 0x0000a76f, 0x0000011e, 0x0000011f, + 0x00000404, 0x00000454, 0x00001f91, 0x020001fa, + 0x00000134, 0x00000135, 0x00000399, 0x000003b9, + 0x00001e60, 0x00001e61, 0x00001f0b, 0x00001f03, + 0x0000004d, 0x0000006d, 0x000003f7, 0x000003f8, + 0x00001ef4, 0x00001ef5, 0x00016e55, 0x00016e75, + 0x00001fda, 0x00001f76, 0x000001b7, 0x00000292, + 0x00001f50, 0x020001b8, 0x00001ea6, 0x00001ea7, + 0x000024cc, 0x000024e6, 0x00000429, 0x00000449, + 0x000010a3, 0x00002d03, 0x0000021e, 0x0000021f, + 0x00002166, 0x00002176, 0x000000cb, 0x000000eb, + 0x00016e44, 0x00016e64, 0x0000ff30, 0x0000ff50, + 0x00000470, 0x00000471, 0x00001e58, 0x00001e59, + 0x00016e5c, 0x00016e7c, 0x000104c9, 0x000104f1, + 0x000010ba, 0x00002d1a, 0x0000a7d4, 0x0000a7d5, + 0x00010d56, 0x00010d76, 0x00001f1c, 0x00001f14, + 0x00001fd6, 0x02000285, 0x000001f6, 0x00000195, + 0x00010582, 0x000105a9, 0x0000ab97, 0x000013c7, + 0x000004e0, 0x000004e1, 0x00010c9f, 0x00010cdf, + 0x000104bc, 0x000104e4, 0x00002ceb, 0x00002cec, + 0x0000a758, 0x0000a759, 0x000000d9, 0x000000f9, + 0x0000051e, 0x0000051f, 0x00001f90, 0x020001f7, + 0x00010d5a, 0x00010d7a, 0x00001ffb, 0x00001f7d, + 0x00001fbe, 0x000003b9, 0x00002c26, 0x00002c56, + 0x000000c1, 0x000000e1, 0x00002c96, 0x00002c97, + 0x00000372, 0x00000373, 0x00016e56, 0x00016e76, + 0x0000a74a, 0x0000a74b, 0x000003a5, 0x000003c5, + 0x0001e913, 0x0001e935, 0x0000012a, 0x0000012b, + 0x00001f09, 0x00001f01, 0x0000042a, 0x0000044a, + 0x00002c1c, 0x00002c4c, 0x000001a4, 0x000001a5, + 0x000118a9, 0x000118c9, 0x000004a2, 0x000004a3, + 0x00001cb2, 0x000010f2, 0x00001c91, 0x000010d1, + 0x00002ca4, 0x00002ca5, 0x00010cab, 0x00010ceb, + 0x000003a9, 0x000003c9, 0x0000ab7f, 0x000013af, + 0x00010426, 0x0001044e, 0x00000206, 0x00000207, + 0x00010d57, 0x00010d77, 0x00002cc2, 0x00002cc3, + 0x00001fca, 0x00001f74, 0x0000a698, 0x0000a699, + 0x00010583, 0x000105aa, 0x000004ae, 0x000004af, + 0x00010412, 0x0001043a, 0x00001e34, 0x00001e35, + 0x00001f9b, 0x02000218, 0x00002c11, 0x00002c41, + 0x0001041f, 0x00010447, 0x0000a650, 0x0000a651, + 0x00002c69, 0x00002c6a, 0x00001f93, 0x02000200, + 0x00010d63, 0x00010d83, 0x0000abb0, 0x000013e0, + 0x000001a2, 0x000001a3, 0x0000ab95, 0x000013c5, + 0x00010413, 0x0001043b, 0x00016eae, 0x00016ec9, + 0x000004e8, 0x000004e9, 0x00016e57, 0x00016e77, + 0x0000a7b1, 0x00000287, 0x0000017d, 0x0000017e, + 0x00001f56, 0x030001c3, 0x0000017b, 0x0000017c, + 0x000003fd, 0x0000037b, 0x0000042b, 0x0000044b, + 0x000010a5, 0x00002d05, 0x00000041, 0x00000061, + 0x00001e66, 0x00001e67, 0x0001e917, 0x0001e939, + 0x00001ff6, 0x020002a7, 0x0000023a, 0x00002c65, + 0x00002c27, 0x00002c57, 0x00002c70, 0x00000252, + 0x00010cb1, 0x00010cf1, 0x000104cb, 0x000104f3, + 0x000003ee, 0x000003ef, 0x00001e32, 0x00001e33, + 0x00010d5b, 0x00010d7b, 0x00001e26, 0x00001e27, + 0x00001fac, 0x0200024b, 0x00016e40, 0x00016e60, + 0x00010584, 0x000105ab, 0x00000537, 0x00000567, + 0x00001eda, 0x00001edb, 0x00016e4a, 0x00016e6a, + 0x0000040d, 0x0000045d, 0x00002ced, 0x00002cee, + 0x0000a7da, 0x0000a7db, 0x00001c82, 0x0000043e, + 0x000003a1, 0x000003c1, 0x00001f92, 0x020001fd, + 0x00000136, 0x00000137, 0x0000a786, 0x0000a787, + 0x00001fbc, 0x02000267, 0x00001e3e, 0x00001e3f, + 0x000003da, 0x000003db, 0x00001cad, 0x000010ed, + 0x00002cac, 0x00002cad, 0x00016e58, 0x00016e78, + 0x0000038c, 0x000003cc, 0x00000508, 0x00000509, + 0x00001fe7, 0x0300029a, 0x000003f5, 0x000003b5, + 0x000003f9, 0x000003f2, 0x0000042c, 0x0000044c, + 0x000010a2, 0x00002d02, 0x00000042, 0x00000062, + 0x000004d0, 0x000004d1, 0x000001a6, 0x00000280, + 0x000001ec, 0x000001ed, 0x00010c88, 0x00010cc8, + 0x0000053d, 0x0000056d, 0x0000022a, 0x0000022b, + 0x00000392, 0x000003b2, 0x000104cd, 0x000104f5, + 0x00010424, 0x0001044c, 0x000004cd, 0x000004ce, + 0x00010d59, 0x00010d79, 0x0000ab94, 0x000013c4, + 0x000010b8, 0x00002d18, 0x0000a69a, 0x0000a69b, + 0x00010585, 0x000105ac, 0x0000aba9, 0x000013d9, + 0x0000aba1, 0x000013d1, 0x00010c96, 0x00010cd6, + 0x00002c13, 0x00002c43, 0x0000abbb, 0x000013eb, + 0x0000a752, 0x0000a753, 0x0000a78d, 0x00000265, + 0x00002cca, 0x00002ccb, 0x00001f95, 0x02000206, + 0x00016ea7, 0x00016ec2, 0x00016e42, 0x00016e62, + 0x00000460, 0x00000461, 0x00000197, 0x00000268, + 0x0001e912, 0x0001e934, 0x0000abb3, 0x000013e3, + 0x00001e54, 0x00001e55, 0x00016e59, 0x00016e79, + 0x000004d2, 0x000004d3, 0x0000fb15, 0x020002ce, + 0x000003a4, 0x000003c4, 0x00001e5e, 0x00001e5f, + 0x0000aba4, 0x000013d4, 0x0000042f, 0x0000044f, + 0x00002c14, 0x00002c44, 0x00000043, 0x00000063, + 0x00000189, 0x00000256, 0x00002ccc, 0x00002ccd, + 0x000001bc, 0x000001bd, 0x000104d2, 0x000104fa, + 0x0000046e, 0x0000046f, 0x00001cab, 0x000010eb, + 0x00000176, 0x00000177, 0x000104d1, 0x000104f9, + 0x000003f0, 0x000003ba, 0x00010caf, 0x00010cef, + 0x00010d5d, 0x00010d7d, 0x00000535, 0x00000565, + 0x00000222, 0x00000223, 0x0000abb1, 0x000013e1, + 0x00010586, 0x000105ad, 0x000004a8, 0x000004a9, + 0x0000fb14, 0x020002cb, 0x00010ca3, 0x00010ce3, + 0x000104b8, 0x000104e0, 0x00001cb4, 0x000010f4, + 0x0000a756, 0x0000a757, 0x0000ab90, 0x000013c0, + 0x0000216a, 0x0000217a, 0x00001f94, 0x02000203, + 0x0000a65a, 0x0000a65b, 0x00001f2f, 0x00001f27, + 0x00001faa, 0x02000245, 0x00001efa, 0x00001efb, + 0x00000492, 0x00000493, 0x000118a5, 0x000118c5, + 0x00000376, 0x00000377, 0x00016e5a, 0x00016e7a, + 0x0000ff2b, 0x0000ff4b, 0x00010414, 0x0001043c, + 0x00002cc6, 0x00002cc7, 0x00000130, 0x02000192, + 0x0000ab89, 0x000013b9, 0x0000042e, 0x0000044e, + 0x000010a4, 0x00002d04, 0x00000044, 0x00000064, + 0x00001ee6, 0x00001ee7, 0x00001ef0, 0x00001ef1, + 0x000001ea, 0x000001eb, 0x00001e2a, 0x00001e2b, + 0x00000550, 0x00000580, 0x000003aa, 0x000003ca, + 0x000000dc, 0x000000fc, 0x0000ff37, 0x0000ff57, + 0x00001f6a, 0x00001f62, 0x0000a64a, 0x0000a64b, + 0x0000054d, 0x0000057d, 0x00001ff3, 0x020002a1, + 0x00001e2e, 0x00001e2f, 0x000000da, 0x000000fa, + 0x00010587, 0x000105ae, 0x00002c6e, 0x00000271, + 0x00001ed8, 0x00001ed9, 0x00001c9c, 0x000010dc, + 0x000024cf, 0x000024e9, 0x000003b0, 0x0300019f, + 0x0000a754, 0x0000a755, 0x00001f3d, 0x00001f35, + 0x000118ac, 0x000118cc, 0x00002c06, 0x00002c36, + 0x0000a72e, 0x0000a72f, 0x0001e919, 0x0001e93b, + 0x00000420, 0x00000440, 0x00001fdb, 0x00001f77, + 0x00016ea1, 0x00016ebc, 0x00001cbf, 0x000010ff, + 0x000003a6, 0x000003c6, 0x00016e5b, 0x00016e7b, + 0x00016eb7, 0x00016ed2, 0x00001ca5, 0x000010e5, + 0x00000345, 0x000003b9, 0x0000016e, 0x0000016f, + 0x0000aba2, 0x000013d2, 0x00001fb6, 0x02000260, + 0x00002c28, 0x00002c58, 0x00000047, 0x00000067, + 0x00001e9e, 0x020001b5, 0x00001f3c, 0x00001f34, + 0x0000a750, 0x0000a751, 0x00002168, 0x00002178, + 0x0000038f, 0x000003ce, 0x00002c72, 0x00002c73, + 0x00001cbe, 0x000010fe, 0x0000ab7c, 0x000013ac, + 0x00016eaf, 0x00016eca, 0x0001058c, 0x000105b3, + 0x0000ff39, 0x0000ff59, 0x00000532, 0x00000562, + 0x00002c20, 0x00002c50, 0x0000a696, 0x0000a697, + 0x00000059, 0x00000079, 0x000004aa, 0x000004ab, + 0x0000ab70, 0x000013a0, 0x000000c0, 0x000000e0, + 0x00001e70, 0x00001e71, 0x00002cf2, 0x00002cf3, + 0x0000040b, 0x0000045b, 0x0000ab9c, 0x000013cc, + 0x00010592, 0x000105b9, 0x00001f96, 0x02000209, + 0x0000a660, 0x0000a661, 0x000118ba, 0x000118da, + 0x00002ca2, 0x00002ca3, 0x00016e41, 0x00016e61, + 0x000004de, 0x000004df, 0x0000054b, 0x0000057b, + 0x00002cb0, 0x00002cb1, 0x00016e5f, 0x00016e7f, + 0x0000ff27, 0x0000ff47, 0x00002cbc, 0x00002cbd, + 0x00001fc8, 0x00001f72, 0x00000122, 0x00000123, + 0x00010ca6, 0x00010ce6, 0x00000468, 0x00000469, + 0x000010a6, 0x00002d06, 0x00000046, 0x00000066, + 0x000118bf, 0x000118df, 0x00002c7f, 0x00000240, + 0x0000015c, 0x0000015d, 0x00001ca0, 0x000010e0, + 0x000010bd, 0x00002d1d, 0x0001e920, 0x0001e942, + 0x000000c5, 0x000000e5, 0x0000ab7d, 0x000013ad, + 0x000000c9, 0x000000e9, 0x0001e918, 0x0001e93a, + 0x00000198, 0x00000199, 0x00002c1d, 0x00002c4d, + 0x00001e48, 0x00001e49, 0x000001f4, 0x000001f5, + 0x00010589, 0x000105b0, 0x0000ab9b, 0x000013cb, + 0x0000040f, 0x0000045f, 0x00001c94, 0x000010d4, + 0x00002c23, 0x00002c53, 0x00001c83, 0x00000441, + 0x00002163, 0x00002173, 0x000104c6, 0x000104ee, + 0x00000424, 0x00000444, 0x00001f59, 0x00001f51, + 0x0000ff35, 0x0000ff55, 0x0000038e, 0x000003cd, + 0x00001e99, 0x020001af, 0x00010408, 0x00010430, + 0x0001e90d, 0x0001e92f, 0x00016ea0, 0x00016ebb, + 0x00001edc, 0x00001edd, 0x00016e5d, 0x00016e7d, + 0x00001cb8, 0x000010f8, 0x0000053c, 0x0000056c, + 0x0000fb01, 0x020002b4, 0x0000ff25, 0x0000ff45, + 0x00001e5a, 0x00001e5b, 0x00001f99, 0x02000212, + 0x000010a9, 0x00002d09, 0x00002c29, 0x00002c59, + 0x0000ff2c, 0x0000ff4c, 0x00001e98, 0x020001ac, + 0x0001e91d, 0x0001e93f, 0x00016eb3, 0x00016ece, + 0x00001fab, 0x02000248, 0x00001c9d, 0x000010dd, + 0x00001ea0, 0x00001ea1, 0x0000ab7e, 0x000013ae, + 0x0001041c, 0x00010444, 0x00001f5b, 0x00001f53, + 0x00000396, 0x000003b6, 0x0000018f, 0x00000259, + 0x0000a7b2, 0x0000029d, 0x000001e2, 0x000001e3, + 0x0001058d, 0x000105b4, 0x00001ca1, 0x000010e1, + 0x000104ca, 0x000104f2, 0x000000c2, 0x000000e2, + 0x00001ee8, 0x00001ee9, 0x00002ce0, 0x00002ce1, + 0x0000a75e, 0x0000a75f, 0x0001e901, 0x0001e923, + 0x000024c7, 0x000024e1, 0x00001e30, 0x00001e31, + 0x0000053f, 0x0000056f, 0x00000413, 0x00000433, + 0x00000193, 0x00000260, 0x0001e91a, 0x0001e93c, + 0x00001e68, 0x00001e69, 0x00001ca3, 0x000010e3, + 0x000118a4, 0x000118c4, 0x0000039a, 0x000003ba, + 0x00001f49, 0x00001f41, 0x00000422, 0x00000442, + 0x00001e1c, 0x00001e1d, 0x00000124, 0x00000125, + 0x000024b9, 0x000024d3, 0x00001fa0, 0x02000227, + 0x000010a8, 0x00002d08, 0x00000048, 0x00000068, + 0x00000551, 0x00000581, 0x000010a1, 0x00002d01, + 0x0000a656, 0x0000a657, 0x0000a682, 0x0000a683, + 0x000004ea, 0x000004eb, 0x00001fbb, 0x00001f71, + 0x0001e90b, 0x0001e92d, 0x00000415, 0x00000435, + 0x00001f69, 0x00001f61, 0x000010be, 0x00002d1e, + 0x00010d5f, 0x00010d7f, 0x00002160, 0x00002170, + 0x00001e7c, 0x00001e7d, 0x000001f7, 0x000001bf, + 0x00010423, 0x0001044b, 0x000004ac, 0x000004ad, + 0x00001e3c, 0x00001e3d, 0x00010c8c, 0x00010ccc, + 0x00016eb4, 0x00016ecf, 0x00001ca8, 0x000010e8, + 0x0000023d, 0x0000019a, 0x0001e900, 0x0001e922, + 0x00000401, 0x00000451, 0x00001f98, 0x0200020f, + 0x0000a726, 0x0000a727, 0x0001e90e, 0x0001e930, + 0x0000ab9f, 0x000013cf, 0x00002c2d, 0x00002c5d, + 0x00001ee2, 0x00001ee3, 0x00001e24, 0x00001e25, + 0x00001c93, 0x000010d3, 0x0000a73c, 0x0000a73d, + 0x0000ff26, 0x0000ff46, 0x00000522, 0x00000523, + 0x00001e02, 0x00001e03, 0x0000a74e, 0x0000a74f, + 0x0000040a, 0x0000045a, 0x00001f18, 0x00001f10, + 0x00000228, 0x00000229, 0x0000004b, 0x0000006b, + 0x000118b9, 0x000118d9, 0x00010d62, 0x00010d82, + 0x000001fc, 0x000001fd, 0x0000abb6, 0x000013e6, + 0x00001e64, 0x00001e65, 0x00001fe4, 0x02000294, + 0x000004b8, 0x000004b9, 0x0000ab80, 0x000013b0, + 0x000003f4, 0x000003b8, 0x0000a796, 0x0000a797, + 0x0000aba8, 0x000013d8, 0x000004c3, 0x000004c4, + 0x00001ff4, 0x020002a4, 0x00010ca2, 0x00010ce2, + 0x000013fb, 0x000013f3, 0x000004e2, 0x000004e3, + 0x0000abad, 0x000013dd, 0x00010ca1, 0x00010ce1, + 0x0000024c, 0x0000024d, 0x00001f2e, 0x00001f26, + 0x0000a742, 0x0000a743, 0x0001e903, 0x0001e925, + 0x00001faf, 0x02000254, 0x000010ab, 0x00002d0b, + 0x0000014e, 0x0000014f, 0x0001057e, 0x000105a5, + 0x00001e36, 0x00001e37, 0x00001efc, 0x00001efd, + 0x00010c81, 0x00010cc1, 0x00001f2b, 0x00001f23, + 0x00001e4a, 0x00001e4b, 0x00001e2c, 0x00001e2d, + 0x0000a748, 0x0000a749, 0x0001040c, 0x00010434, + 0x00001e1e, 0x00001e1f, 0x00000158, 0x00000159, + 0x0000abb4, 0x000013e4, 0x00001eb0, 0x00001eb1, + 0x000010aa, 0x00002d0a, 0x0000004a, 0x0000006a, + 0x000001b8, 0x000001b9, 0x00001cb0, 0x000010f0, + 0x000001f2, 0x000001f3, 0x00000390, 0x0300019b, + 0x000004ec, 0x000004ed, 0x00002cde, 0x00002cdf, + 0x00000102, 0x00000103, 0x0000ab83, 0x000013b3, + 0x0000a684, 0x0000a685, 0x00002c09, 0x00002c39, + 0x000024c1, 0x000024db, 0x00001f6d, 0x00001f65, + 0x00001e7e, 0x00001e7f, 0x000001f8, 0x000001f9, + 0x000003d6, 0x000003c0, 0x00010cac, 0x00010cec, + 0x00002ca6, 0x00002ca7, 0x000000c4, 0x000000e4, + 0x00000406, 0x00000456, 0x00001c99, 0x000010d9, + 0x0000a75a, 0x0000a75b, 0x0001e902, 0x0001e924, + 0x00010cae, 0x00010cee, 0x00001f9a, 0x02000215, + 0x00001c86, 0x0000044a, 0x00002164, 0x00002174, + 0x00001cb9, 0x000010f9, 0x00001efe, 0x00001eff, + 0x00010c80, 0x00010cc0, 0x00001ea2, 0x00001ea3, + 0x00001ee0, 0x00001ee1, 0x0000a73a, 0x0000a73b, + 0x0000ff28, 0x0000ff48, 0x00001f6c, 0x00001f64, + 0x00001e04, 0x00001e05, 0x00010d61, 0x00010d81, + 0x0000ab9a, 0x000013ca, 0x00001eb8, 0x00001eb9, + 0x000010ad, 0x00002d0d, 0x00000045, 0x00000065, + 0x000118bb, 0x000118db, 0x0001041a, 0x00010442, + 0x00016eac, 0x00016ec7, 0x0000abbe, 0x000013ee, + 0x00016eb5, 0x00016ed0, 0x0000fb00, 0x020002b1, + 0x00010cb2, 0x00010cf2, 0x0000ab82, 0x000013b2, + 0x000003fa, 0x000003fb, 0x0000a798, 0x0000a799, + 0x00001cb5, 0x000010f5, 0x000004e6, 0x000004e7, + 0x00002c22, 0x00002c52, 0x000000db, 0x000000fb, + 0x00010595, 0x000105bc, 0x000004b0, 0x000004b1, + 0x00016ead, 0x00016ec8, 0x0000ff24, 0x0000ff44, + 0x0000216b, 0x0000217b, 0x000003e2, 0x000003e3, + 0x000004d6, 0x000004d7, 0x0001e905, 0x0001e927, + 0x000010bb, 0x00002d1b, 0x00001e46, 0x00001e47, + 0x00000490, 0x00000491, 0x00002132, 0x0000214e, + 0x00001e97, 0x020001a9, 0x00002c24, 0x00002c54, + 0x00010c83, 0x00010cc3, 0x000004a0, 0x000004a1, + 0x00001eb6, 0x00001eb7, 0x00016e45, 0x00016e65, + 0x0000ab7a, 0x000013aa, 0x000004be, 0x000004bf, + 0x000003ec, 0x000003ed, 0x0000023b, 0x0000023c, + 0x00000541, 0x00000571, 0x00001fb8, 0x00001fb0, + 0x000010ac, 0x00002d0c, 0x0000004c, 0x0000006c, + 0x00000542, 0x00000572, 0x00001c87, 0x00000463, + 0x000001e8, 0x000001e9, 0x00002c82, 0x00002c83, + 0x000004ee, 0x000004ef, 0x00001e6c, 0x00001e6d, + 0x00000104, 0x00000105, 0x0000a7f5, 0x0000a7f6, + 0x00000419, 0x00000439, 0x0000a7ae, 0x0000026a, + 0x0000015e, 0x0000015f, 0x00000421, 0x00000441, + 0x0000a644, 0x0000a645, 0x00000187, 0x00000188, + 0x0001058f, 0x000105b6, 0x000004b4, 0x000004b5, + 0x0001e916, 0x0001e938, 0x000001af, 0x000001b0, + 0x0000fb13, 0x020002c8, 0x00001f0a, 0x00001f02, + 0x0000a75c, 0x0000a75d, 0x0001e906, 0x0001e928, + 0x00000516, 0x00000517, 0x000010a0, 0x00002d00, + 0x00010d58, 0x00010d78, 0x0001e911, 0x0001e933, + 0x00001e7a, 0x00001e7b, 0x0000aba5, 0x000013d5, + 0x00010c82, 0x00010cc2, 0x00001cb1, 0x000010f1, + 0x00001fa7, 0x0200023c, 0x00016e52, 0x00016e72, + 0x0000ff2a, 0x0000ff4a, 0x000004a6, 0x000004a7, + 0x00001e06, 0x00001e07, 0x00001cae, 0x000010ee, + 0x00000141, 0x00000142, 0x00001fa8, 0x0200023f, + 0x000010a7, 0x00002d07, 0x0000004f, 0x0000006f, + 0x000000d3, 0x000000f3, 0x00001ebe, 0x00001ebf, + 0x00016ea2, 0x00016ebd, 0x000118a0, 0x000118c0, + 0x00002cc0, 0x00002cc1, 0x00002cd6, 0x00002cd7, + 0x00001c88, 0x0000a64b, 0x0000ab84, 0x000013b4, + 0x000003a8, 0x000003c8, 0x0000a79a, 0x0000a79b, + 0x0001e91f, 0x0001e941, 0x000118b3, 0x000118d3, + 0x00001e80, 0x00001e81, 0x00000160, 0x00000161, + 0x00000181, 0x00000253, 0x000004b2, 0x000004b3, + 0x00001ee4, 0x00001ee5, 0x000000c8, 0x000000e8, + 0x0000ff31, 0x0000ff51, 0x00002c6f, 0x00000250, + 0x00010420, 0x00010448, 0x0001e907, 0x0001e929, + 0x000001a9, 0x00000283, 0x00001e3a, 0x00001e3b, + 0x00001caa, 0x000010ea, 0x0001057a, 0x000105a1, + 0x0000046c, 0x0000046d, 0x00001ca6, 0x000010e6, + 0x00010c85, 0x00010cc5, 0x00000543, 0x00000573, + 0x00001ef6, 0x00001ef7, 0x0000abab, 0x000013db, + 0x000104b1, 0x000104d9, 0x000118b8, 0x000118d8, + 0x000003c2, 0x000003c3, 0x000000d6, 0x000000f6, + 0x0000ff36, 0x0000ff56, 0x00001ff9, 0x00001f79, + 0x000010ae, 0x00002d0e, 0x0000004e, 0x0000006e, + 0x000118bd, 0x000118dd, 0x00001ede, 0x00001edf, + 0x0000015a, 0x0000015b, 0x00000243, 0x00000180, + 0x000004f0, 0x000004f1, 0x0000fb04, 0x030002be, + 0x00000106, 0x00000107, 0x0000ab87, 0x000013b7, + 0x0001040a, 0x00010432, 0x00001e1a, 0x00001e1b, + 0x00010570, 0x00010597, 0x00002cb8, 0x00002cb9, + 0x000010c4, 0x00002d24, 0x00001f19, 0x00001f11, + 0x0000a7c9, 0x0000a7ca, 0x00002cb6, 0x00002cb7, + 0x00000208, 0x00000209, 0x000000cc, 0x000000ec, + 0x0000048a, 0x0000048b, 0x00000216, 0x00000217, + 0x00000224, 0x00000225, 0x00010ca8, 0x00010ce8, + 0x000104ce, 0x000104f6, 0x000010bc, 0x00002d1c, + 0x00001eae, 0x00001eaf, 0x00002cba, 0x00002cbb, + 0x00000472, 0x00000473, 0x00002c2a, 0x00002c5a, + 0x00010c86, 0x00010cc6, 0x000024bb, 0x000024d5, + 0x00001e56, 0x00001e57, 0x0000a66c, 0x0000a66d, + 0x000104b0, 0x000104d8, 0x000010b9, 0x00002d19, + 0x00001e08, 0x00001e09, 0x00001e20, 0x00001e21, + 0x0000039b, 0x000003bb, 0x00001fa4, 0x02000233, + 0x000010b1, 0x00002d11, 0x00000051, 0x00000071, + 0x00000145, 0x00000146, 0x00001ec0, 0x00001ec1, + 0x00001ff8, 0x00001f78, 0x00010c98, 0x00010cd8, + 0x00016ea4, 0x00016ebf, 0x00010d64, 0x00010d84, + 0x00001c9e, 0x000010de, 0x0000ab86, 0x000013b6, + 0x000003fe, 0x0000037c, 0x0000a79c, 0x0000a79d, + 0x0000040c, 0x0000045c, 0x000118a3, 0x000118c3, + 0x00002c18, 0x00002c48, 0x000001c7, 0x000001c9, + 0x000013f8, 0x000013f0, 0x000004b6, 0x000004b7, + 0x00000226, 0x00000227, 0x000000ca, 0x000000ea, + 0x0000ab98, 0x000013c8, 0x00002ce2, 0x00002ce3, + 0x000003a0, 0x000003c0, 0x0001e909, 0x0001e92b, + 0x00002c07, 0x00002c37, 0x00000397, 0x000003b7, + 0x00000182, 0x00000183, 0x0000a686, 0x0000a687, + 0x00001fb2, 0x02000257, 0x00002c2c, 0x00002c5c, + 0x00010c87, 0x00010cc7, 0x000118b0, 0x000118d0, + 0x000024bd, 0x000024d7, 0x0000a722, 0x0000a723, + 0x000104b3, 0x000104db, 0x00002c17, 0x00002c47, + 0x0000a7d6, 0x0000a7d7, 0x00001c98, 0x000010d8, + 0x00010c9e, 0x00010cde, 0x00001f97, 0x0200020c, + 0x000010b0, 0x00002d10, 0x00000050, 0x00000070, + 0x000118a2, 0x000118c2, 0x00002cda, 0x00002cdb, + 0x00001e6e, 0x00001e6f, 0x0000a648, 0x0000a649, + 0x000004f2, 0x000004f3, 0x0000fb06, 0x020002c5, + 0x00000108, 0x00000109, 0x0000ab81, 0x000013b1, + 0x00001eaa, 0x00001eab, 0x0000018b, 0x0000018c, + 0x00000156, 0x00000157, 0x00002126, 0x000003c9, + 0x00001e84, 0x00001e85, 0x0000ff23, 0x0000ff43, + 0x000013fa, 0x000013f2, 0x000104cc, 0x000104f4, + 0x00001f9f, 0x02000224, 0x000003d8, 0x000003d9, + 0x0000a78b, 0x0000a78c, 0x00016ea3, 0x00016ebe, + 0x00001ca9, 0x000010e9, 0x00001fd3, 0x03000281, + 0x00002c63, 0x00001d7d, 0x0000a792, 0x0000a793, + 0x00000186, 0x00000254, 0x00010571, 0x00010598, + 0x00000478, 0x00000479, 0x00001eee, 0x00001eef, + 0x00010588, 0x000105af, 0x00002c6d, 0x00000251, + 0x00001e92, 0x00001e93, 0x00016e4e, 0x00016e6e, + 0x000104b2, 0x000104da, 0x00000534, 0x00000564, + 0x00001e0a, 0x00001e0b, 0x00001c9a, 0x000010da, + 0x0000ab72, 0x000013a2, 0x00000466, 0x00000467, + 0x000010b3, 0x00002d13, 0x00000053, 0x00000073, + 0x00000533, 0x00000563, 0x00001ec2, 0x00001ec3, + 0x000003de, 0x000003df, 0x00010421, 0x00010449, + 0x0000212b, 0x000000e5, 0x0000ab73, 0x000013a3, + 0x00000120, 0x00000121, 0x0000ab88, 0x000013b8, + 0x00010422, 0x0001044a, 0x0000a79e, 0x0000a79f, + 0x00000393, 0x000003b3, 0x000118a1, 0x000118c1, + 0x00002c64, 0x0000027d, 0x0000019c, 0x0000026f, + 0x000118b1, 0x000118d1, 0x0000ab77, 0x000013a7, + 0x0001e915, 0x0001e937, 0x000000ce, 0x000000ee, + 0x00002c8a, 0x00002c8b, 0x00000547, 0x00000577, + 0x0000a7b0, 0x0000029e, 0x0000ab9e, 0x000013ce, + 0x00000400, 0x00000450, 0x000024bf, 0x000024d9, + 0x00000184, 0x00000185, 0x0000a680, 0x0000a681, + 0x00000427, 0x00000447, 0x0000014a, 0x0000014b, + 0x00010c89, 0x00010cc9, 0x00016eb0, 0x00016ecb, + 0x0001e90f, 0x0001e931, 0x00016e5e, 0x00016e7e, + 0x000104b5, 0x000104dd, 0x000000d1, 0x000000f1, + 0x0000a7cb, 0x00000264, 0x0001e908, 0x0001e92a, + 0x000024ca, 0x000024e4, 0x00001fec, 0x00001fe5, + 0x000010b2, 0x00002d12, 0x00000052, 0x00000072, + 0x00010404, 0x0001042c, 0x0000037f, 0x000003f3, + 0x00000179, 0x0000017a, 0x000001b3, 0x000001b4, + 0x000004f4, 0x000004f5, 0x0001e90a, 0x0001e92c, + 0x0000010a, 0x0000010b, 0x0000ab8b, 0x000013bb, + 0x00000426, 0x00000446, 0x0000a7bc, 0x0000a7bd, + 0x0000021a, 0x0000021b, 0x00002c86, 0x00002c87, + 0x00001e86, 0x00001e87, 0x0000040e, 0x0000045e, + 0x0000a688, 0x0000a689, 0x0000a77d, 0x00001d79, + 0x00002c0d, 0x00002c3d, 0x000000c6, 0x000000e6, + 0x000118b7, 0x000118d7, 0x00001f3e, 0x00001f36, + 0x0000a760, 0x0000a761, 0x0000abaa, 0x000013da, + 0x000010c7, 0x00002d27, 0x00001e52, 0x00001e53, + 0x000000de, 0x000000fe, 0x00001e28, 0x00001e29, + 0x00001fb4, 0x0200025d, 0x00002c2e, 0x00002c5e, + 0x00010c8a, 0x00010cca, 0x0000a7ad, 0x0000026c, + 0x00002c03, 0x00002c33, 0x0000a664, 0x0000a665, + 0x000104b6, 0x000104de, 0x00002cce, 0x00002ccf, + 0x00001e0c, 0x00001e0d, 0x0000014c, 0x0000014d, + 0x00002c2f, 0x00002c5f, 0x00000464, 0x00000465, + 0x000010b5, 0x00002d15, 0x00000055, 0x00000075, + 0x0001040d, 0x00010435, 0x00001ec4, 0x00001ec5, + 0x00016eb8, 0x00016ed3, 0x0000ab7b, 0x000013ab, + 0x0000abb5, 0x000013e5, 0x0000fb02, 0x020002b7, + 0x000004da, 0x000004db, 0x0000ab8a, 0x000013ba, + 0x00002c92, 0x00002c93, 0x0000a7a0, 0x0000a7a1, + 0x00002c9a, 0x00002c9b, 0x00002c8c, 0x00002c8d, + 0x00002c62, 0x0000026b, 0x0000aba7, 0x000013d7, + 0x000013fc, 0x000013f4, 0x000004ba, 0x000004bb, + 0x0001041b, 0x00010443, 0x00002c25, 0x00002c55, + 0x000004c7, 0x000004c8, 0x0000021c, 0x0000021d, + 0x0000a7ce, 0x0000a7cf, 0x00002165, 0x00002175, + 0x00000403, 0x00000453, 0x0000a7b6, 0x0000a7b7, + 0x0000a65c, 0x0000a65d, 0x00000414, 0x00000434, + 0x0000053e, 0x0000056e, 0x0000a66a, 0x0000a66b, + 0x00010c8b, 0x00010ccb, 0x000024b7, 0x000024d1, + 0x0001e91c, 0x0001e93e, 0x000024c4, 0x000024de, + 0x000104b7, 0x000104df, 0x0000052e, 0x0000052f, + 0x0000a77e, 0x0000a77f, 0x00001c84, 0x00000442, + 0x00010c9c, 0x00010cdc, 0x0000041b, 0x0000043b, + 0x000010b4, 0x00002d14, 0x00000054, 0x00000074, + 0x00000544, 0x00000574, 0x00001f54, 0x030001bf, + 0x000000cf, 0x000000ef, 0x0000ff38, 0x0000ff58, + 0x000004f6, 0x000004f7, 0x00001f68, 0x00001f60, + 0x0000010c, 0x0000010d, 0x0000ab8d, 0x000013bd, + 0x00002cae, 0x00002caf, 0x0000a7ba, 0x0000a7bb, + 0x00016ea9, 0x00016ec4, 0x000118bc, 0x000118dc, + 0x00001e8a, 0x00001e8b, 0x000001c4, 0x000001c6, + 0x000003cf, 0x000003d7, 0x0000041d, 0x0000043d, + 0x00001fad, 0x0200024e, 0x00001fa5, 0x02000236, + 0x0000050c, 0x0000050d, 0x00010418, 0x00010440, + 0x0000a766, 0x0000a767, 0x0000ab96, 0x000013c6, + 0x00000528, 0x00000529, 0x00002cd8, 0x00002cd9, + 0x0000018e, 0x000001dd, 0x00010400, 0x00010428, + 0x00001e96, 0x020001a6, 0x00001ef2, 0x00001ef3, + 0x00010c84, 0x00010cc4, 0x000004d4, 0x000004d5, + 0x00001fb7, 0x03000263, 0x00001e38, 0x00001e39, + 0x00000545, 0x00000575, 0x00010416, 0x0001043e, + 0x00001e0e, 0x00001e0f, 0x0000216d, 0x0000217d, + 0x00000391, 0x000003b1, 0x00002c21, 0x00002c51, + 0x000010b7, 0x00002d17, 0x00010572, 0x00010599, + 0x00001ca7, 0x000010e7, 0x00001ec6, 0x00001ec7, + 0x00001f0f, 0x00001f07, 0x00002162, 0x00002172, + 0x00000496, 0x00000497, 0x00001fb9, 0x00001fb1, + 0x00001c90, 0x000010d0, 0x0000ab8c, 0x000013bc, + 0x00001f2a, 0x00001f22, 0x0000a7a2, 0x0000a7a3, + 0x0000abba, 0x000013ea, 0x00001cb3, 0x000010f3, + 0x00001e82, 0x00001e83, 0x000001c5, 0x000001c6, + 0x0000049e, 0x0000049f, 0x000001a7, 0x000001a8, + 0x00016e46, 0x00016e66, 0x000000d2, 0x000000f2, + 0x00000512, 0x00000513, 0x00001f2c, 0x00001f24, + 0x00001fa1, 0x0200022a, 0x000024c9, 0x000024e3, + 0x0000052a, 0x0000052b, 0x00001e4c, 0x00001e4d, + 0x00001cac, 0x000010ec, 0x00010401, 0x00010429, + 0x00001eba, 0x00001ebb, 0x000118be, 0x000118de, + 0x00010c8d, 0x00010ccd, 0x0000abb7, 0x000013e7, + 0x000000d0, 0x000000f0, 0x0000abb9, 0x000013e9, + 0x000104b9, 0x000104e1, 0x00000555, 0x00000585, + 0x00001e16, 0x00001e17, 0x0000016c, 0x0000016d, + 0x00002161, 0x00002171, 0x00001f8d, 0x020001ee, + 0x000010b6, 0x00002d16, 0x00000056, 0x00000076, + 0x000004e4, 0x000004e5, 0x00002183, 0x00002184, + 0x00001f4d, 0x00001f45, 0x0000049a, 0x0000049b, + 0x000004f8, 0x000004f9, 0x0000a724, 0x0000a725, + 0x0000010e, 0x0000010f, 0x0000ab8f, 0x000013bf, + 0x00001f3f, 0x00001f37, 0x0000a782, 0x0000a783, + 0x0000abaf, 0x000013df, 0x00002ca8, 0x00002ca9, + 0x000010c2, 0x00002d22, 0x00002167, 0x00002177, + 0x00001caf, 0x000010ef, 0x000024b6, 0x000024d0, + 0x00000417, 0x00000437, 0x00002c6b, 0x00002c6c, + 0x0000048c, 0x0000048d, 0x0001040e, 0x00010436, + 0x0000a764, 0x0000a765, 0x00002c1f, 0x00002c4f, + 0x00000554, 0x00000584, 0x00002c1e, 0x00002c4e, + 0x00000139, 0x0000013a, 0x00010402, 0x0001042a, + 0x0000ff33, 0x0000ff53, 0x0001e91e, 0x0001e940, + 0x00010c8e, 0x00010cce, 0x00002c80, 0x00002c81, + 0x00002c16, 0x00002c46, 0x0000024a, 0x0000024b, + 0x000104ba, 0x000104e2, 0x00016ea6, 0x00016ec1, + 0x00001e10, 0x00001e11, 0x00001cb6, 0x000010f6, + 0x0000054e, 0x0000057e, 0x00001fa6, 0x02000239, + 0x00000245, 0x0000028c, 0x00010574, 0x0001059b, + 0x000000c7, 0x000000e7, 0x00001ec8, 0x00001ec9, + 0x0000a65e, 0x0000a65f, 0x0000041e, 0x0000043e, + 0x00000425, 0x00000445, 0x00000202, 0x00000203, + 0x00010427, 0x0001044f, 0x0000ab8e, 0x000013be, + 0x00001f80, 0x020001c7, 0x0000a7a4, 0x0000a7a5, + 0x0000abb8, 0x000013e8, 0x0000a779, 0x0000a77a, + 0x000024c2, 0x000024dc, 0x0001e90c, 0x0001e92e, + 0x00001eea, 0x00001eeb, 0x000024bc, 0x000024d6, + 0x00010d60, 0x00010d80, 0x000001d9, 0x000001da, + 0x000010c1, 0x00002d21, 0x000001f1, 0x000001f3, + 0x00000100, 0x00000101, 0x00001e62, 0x00001e63, + 0x00002c0c, 0x00002c3c, 0x0000a7b4, 0x0000a7b5, + 0x0000018a, 0x00000257, 0x00010403, 0x0001042b, + 0x00000498, 0x00000499, 0x000118b2, 0x000118d2, + 0x00010c8f, 0x00010ccf, 0x00002cd2, 0x00002cd3, + 0x0000053b, 0x0000056b, 0x00000214, 0x00000215, + 0x000104bb, 0x000104e3, 0x000004c1, 0x000004c2, + 0x0000a74c, 0x0000a74d, 0x0000016a, 0x0000016b, + 0x00000538, 0x00000568, 0x00001f0c, 0x00001f04, + 0x00000587, 0x020001a3, 0x00010573, 0x0001059a, + 0x000118a7, 0x000118c7, 0x00001e42, 0x00001e43, + 0x000003ff, 0x0000037d, 0x00016ea5, 0x00016ec0, + 0x000004fa, 0x000004fb, 0x00001e8c, 0x00001e8d, + 0x00000110, 0x00000111, 0x00002c05, 0x00002c35, + 0x00001f81, 0x020001ca, 0x00001eec, 0x00001eed, + 0x00000210, 0x00000211, 0x0000ab91, 0x000013c1, + 0x00001e8e, 0x00001e8f, 0x000001c8, 0x000001c9, + 0x000024cb, 0x000024e5, 0x00010590, 0x000105b7, + 0x00016e47, 0x00016e67, 0x0000a7b3, 0x0000ab53, + 0x00002c10, 0x00002c40, 0x00002c12, 0x00002c42, + 0x0000a76a, 0x0000a76b, 0x0000ab79, 0x000013a9, + 0x00000552, 0x00000582, 0x0000a7c0, 0x0000a7c1, + 0x000001f0, 0x02000198, 0x00010407, 0x0001042f, + 0x00001fb3, 0x0200025a, 0x0000ff2d, 0x0000ff4d, + 0x00010c90, 0x00010cd0, 0x00002c9e, 0x00002c9f, + 0x00001f28, 0x00001f20, 0x000010cd, 0x00002d2d, + 0x000104b4, 0x000104dc, 0x00000546, 0x00000576, + 0x00001e12, 0x00001e13, 0x00000154, 0x00000155, + 0x0000052c, 0x0000052d, 0x00001f6f, 0x00001f67, + 0x00000166, 0x00000167, 0x00000058, 0x00000078, + 0x00002c8e, 0x00002c8f, 0x00001eca, 0x00001ecb, + 0x00000411, 0x00000431, 0x00001f1d, 0x00001f15, + 0x0000ab99, 0x000013c9, 0x00000200, 0x00000201, + 0x00001ff7, 0x030002aa, 0x000104cf, 0x000104f7, + 0x00001f82, 0x020001cd, 0x0000a7a6, 0x0000a7a7, + 0x0000aba6, 0x000013d6, 0x00002c84, 0x00002c85, + 0x00001e88, 0x00001e89, 0x000001cb, 0x000001cc, + 0x00000410, 0x00000430, 0x000004bc, 0x000004bd, + 0x0000a68e, 0x0000a68f, 0x0000048e, 0x0000048f, + 0x00000518, 0x00000519, 0x00010cad, 0x00010ced, + 0x0000020a, 0x0000020b, 0x0000041c, 0x0000043c, + 0x00002c90, 0x00002c91, 0x00001fe6, 0x02000297, + 0x000024cd, 0x000024e7, 0x00010405, 0x0001042d, + 0x00001eac, 0x00001ead, 0x000001fa, 0x000001fb, + 0x00010c91, 0x00010cd1, 0x00002c15, 0x00002c45, + 0x0000039c, 0x000003bc, 0x00000244, 0x00000289, + 0x000104bd, 0x000104e5, 0x00000520, 0x00000521, + 0x0000a7c6, 0x00001d8e, 0x00001c96, 0x000010d6, + 0x00002cc4, 0x00002cc5, 0x000010c5, 0x00002d25, + 0x0000a68c, 0x0000a68d, 0x00010575, 0x0001059c, + 0x000024c3, 0x000024dd, 0x0000013b, 0x0000013c, + 0x0000022c, 0x0000022d, 0x000024ce, 0x000024e8, + 0x000004fc, 0x000004fd, 0x00001e72, 0x00001e73, + 0x00000112, 0x00000113, 0x0000ab78, 0x000013a8, + 0x00001f83, 0x020001d0, 0x0000a654, 0x0000a655, + 0x0000abbc, 0x000013ec, 0x00001fe2, 0x0300028c, + 0x00016eb6, 0x00016ed1, 0x000001ca, 0x000001cc, + 0x0000ff34, 0x0000ff54, 0x000024be, 0x000024d8, + 0x00016e49, 0x00016e69, 0x000003f1, 0x000003c1, + 0x0000ff21, 0x0000ff41, 0x00002c0f, 0x00002c3f, + 0x0000a73e, 0x0000a73f, 0x0000abb2, 0x000013e2, + 0x0001058e, 0x000105b5, 0x00001ef8, 0x00001ef9, + 0x00002ca0, 0x00002ca1, 0x0001e914, 0x0001e936, + 0x00001fcc, 0x0200027a, 0x000001d1, 0x000001d2, + 0x00010c92, 0x00010cd2, 0x00010c9a, 0x00010cda, + 0x00001f38, 0x00001f30, 0x0000a740, 0x0000a741, + 0x000104be, 0x000104e6, 0x0000053a, 0x0000056a, + 0x00000389, 0x000003ae, 0x00000164, 0x00000165, + 0x00000524, 0x00000525, 0x00001e9a, 0x020001b2, + 0x00016eab, 0x00016ec6, 0x0000005a, 0x0000007a, + 0x00002c88, 0x00002c89, 0x00001ecc, 0x00001ecd, + 0x00000218, 0x00000219, 0x00002cbe, 0x00002cbf, + 0x000004d8, 0x000004d9, 0x00000232, 0x00000233, + 0x000000df, 0x0200018f, 0x000118a8, 0x000118c8, + 0x00001f84, 0x020001d3, 0x0000a7a8, 0x0000a7a9, + 0x00000494, 0x00000495, 0x0000212a, 0x0000006b, + 0x0000a7be, 0x0000a7bf, 0x00010419, 0x00010441, + 0x00001fe3, 0x03000290, 0x000024c8, 0x000024e2, + 0x000118ae, 0x000118ce, 0x000000d4, 0x000000f4, + 0x0000050a, 0x0000050b, 0x00001f6e, 0x00001f66, + 0x00001fd8, 0x00001fd0, 0x0000a77b, 0x0000a77c, + 0x0000054c, 0x0000057c, 0x00001f3a, 0x00001f32, + 0x00000212, 0x00000213, 0x0000216c, 0x0000217c, + 0x00001e5c, 0x00001e5d, 0x0000a658, 0x0000a659, + 0x00010c93, 0x00010cd3, 0x00000408, 0x00000458, + 0x000001db, 0x000001dc, 0x00000246, 0x00000247, + 0x000104bf, 0x000104e7, 0x00001fd7, 0x03000288, + 0x00001e14, 0x00001e15, 0x0000012e, 0x0000012f, + 0x00001fc7, 0x03000276, 0x00000474, 0x00000475, + 0x0000017f, 0x00000073, 0x00010577, 0x0001059e, + 0x00002c04, 0x00002c34, 0x00002caa, 0x00002cab, + 0x0000a652, 0x0000a653, 0x00001e6a, 0x00001e6b, + 0x000004fe, 0x000004ff, 0x00000204, 0x00000205, + 0x00000114, 0x00000115, 0x00002cd0, 0x00002cd1, + 0x00001f87, 0x020001dc, 0x0000a7b8, 0x0000a7b9, + 0x00001f0d, 0x00001f05, 0x000004c5, 0x000004c6, + 0x000001ac, 0x000001ad, 0x0000a736, 0x0000a737, + 0x0000ff3a, 0x0000ff5a, 0x000024b8, 0x000024d2, + 0x00016e4b, 0x00016e6b, 0x0000fb17, 0x020002d4, + 0x0000041f, 0x0000043f, 0x00001f48, 0x00001f40, + 0x00001e00, 0x00001e01, 0x00002c75, 0x00002c76, + 0x00001ca2, 0x000010e2, 0x00001f1a, 0x00001f12, + 0x000000c3, 0x000000e3, 0x000004a4, 0x000004a5, + 0x00001c89, 0x00001c8a, 0x00000150, 0x00000151, + 0x00010c94, 0x00010cd4, 0x0000a762, 0x0000a763, + 0x00002c94, 0x00002c95, 0x0000a728, 0x0000a729, + 0x000104c0, 0x000104e8, 0x0000a7c5, 0x00000282, + 0x00000241, 0x00000242, 0x00000152, 0x00000153, + 0x0000216f, 0x0000217f, 0x00001f9e, 0x02000221, + 0x00001fe9, 0x00001fe1, 0x00010578, 0x0001059f, + 0x00010406, 0x0001042e, 0x00001ece, 0x00001ecf, + 0x0000020e, 0x0000020f, 0x00000418, 0x00000438, + 0x00000502, 0x00000503, 0x00001c81, 0x00000434, + 0x0000fb03, 0x030002ba, 0x000024ba, 0x000024d4, + 0x00001f86, 0x020001d9, 0x0000a7aa, 0x00000266, + 0x0000abae, 0x000013de, 0x00000395, 0x000003b5, + 0x000118b6, 0x000118d6, 0x000001cf, 0x000001d0, + 0x0000ab75, 0x000013a5, 0x000004c0, 0x000004cf, + 0x00016e4c, 0x00016e6c, 0x00001e74, 0x00001e75, + 0x0000049c, 0x0000049d, 0x00001f29, 0x00001f21, + 0x0000a64e, 0x0000a64f, 0x000104c8, 0x000104f0, + 0x00001f9c, 0x0200021b, 0x00001e4e, 0x00001e4f, + 0x0000a662, 0x0000a663, 0x00000405, 0x00000455, + 0x000024c0, 0x000024da, 0x0000a746, 0x0000a747, + 0x00010c95, 0x00010cd5, 0x00000143, 0x00000144, + 0x00001f08, 0x00001f00, 0x000003e0, 0x000003e1, + 0x000104c1, 0x000104e9, 0x0000047c, 0x0000047d, + 0x0000a72c, 0x0000a72d, 0x000001fe, 0x000001ff, + 0x0000039f, 0x000003bf, 0x0000a784, 0x0000a785, + 0x0000a738, 0x0000a739, 0x00010579, 0x000105a0, + 0x00001c9f, 0x000010df, 0x000013fd, 0x000013f5, + 0x0000023e, 0x00002c66, 0x00010d5e, 0x00010d7e, + 0x00000500, 0x00000501, 0x00000220, 0x0000019e, + 0x00000116, 0x00000117, 0x00016eb1, 0x00016ecc, + 0x00001feb, 0x00001f7b, 0x00000172, 0x00000173, + 0x000000b5, 0x000003bc, 0x0000019f, 0x00000275, + 0x00001e90, 0x00001e91, 0x00001e22, 0x00001e23, + 0x00001c85, 0x00000442, 0x00002169, 0x00002179, + 0x00016e4d, 0x00016e6d, 0x00000531, 0x00000561, + 0x0000ab71, 0x000013a1, 0x00000398, 0x000003b8, + 0x0000a642, 0x0000a643, 0x00001fc3, 0x0200026d, + 0x00000526, 0x00000527, 0x0000a7d8, 0x0000a7d9, + 0x0000039e, 0x000003be, 0x00010411, 0x00010439, + 0x0000a732, 0x0000a733, 0x000001cd, 0x000001ce, + 0x00001fa9, 0x02000242, 0x000010c3, 0x00002d23, + 0x00000388, 0x000003ad, 0x00000248, 0x00000249, + 0x000104c2, 0x000104ea, 0x00000178, 0x000000ff, + 0x00001e18, 0x00001e19, 0x0001e91b, 0x0001e93d, + 0x00010ca0, 0x00010ce0, 0x00001ea4, 0x00001ea5, + 0x00000539, 0x00000569, 0x00001f2d, 0x00001f25, + 0x00002c60, 0x00002c61, 0x00001ed0, 0x00001ed1, + 0x00002c0b, 0x00002c3b, 0x00010594, 0x000105bb, + 0x00000504, 0x00000505, 0x0000abbd, 0x000013ed, + 0x0000011a, 0x0000011b, 0x000001a0, 0x000001a1, + 0x00001f88, 0x020001df, 0x0000038a, 0x000003af, + 0x000003e4, 0x000003e5, 0x00002cc8, 0x00002cc9, + 0x00010cb0, 0x00010cf0, 0x0000a68a, 0x0000a68b, + 0x000003ab, 0x000003cb, 0x00000476, 0x00000477, + 0x00016e48, 0x00016e68, 0x000000d8, 0x000000f8, + 0x00002c0e, 0x00002c3e, 0x00001f4a, 0x00001f42, + 0x0000a64c, 0x0000a64d, 0x0000ab85, 0x000013b5, + 0x00000402, 0x00000452, 0x00002c1a, 0x00002c4a, + 0x00000190, 0x0000025b, 0x0001040b, 0x00010433, + 0x00002c7e, 0x0000023f, 0x0000a668, 0x0000a669, + 0x00010c97, 0x00010cd7, 0x000003a3, 0x000003c3, + 0x00001f0e, 0x00001f06, 0x00016e43, 0x00016e63, + 0x000104c3, 0x000104eb, 0x00001fc2, 0x0200026a, + 0x0000020c, 0x0000020d, 0x0001e921, 0x0001e943, + 0x0000039d, 0x000003bd, 0x00001f5f, 0x00001f57, + 0x0000a690, 0x0000a691, 0x00000049, 0x00000069, + 0x000001b1, 0x0000028a, 0x0000abbf, 0x000013ef, + 0x0000022e, 0x0000022f, 0x00001eb2, 0x00001eb3, + 0x00000556, 0x00000586, 0x000000d5, 0x000000f5, + 0x00000118, 0x00000119, 0x00000514, 0x00000515, + 0x00001f8b, 0x020001e8, 0x00010d65, 0x00010d85, + 0x0000024e, 0x0000024f, 0x0000047a, 0x0000047b, + 0x00001ffc, 0x020002ae, 0x00000057, 0x00000077, + 0x000003a7, 0x000003c7, 0x00001f6b, 0x00001f63, + 0x00016e4f, 0x00016e6f, 0x0000fb05, 0x020002c2, + 0x0000054a, 0x0000057a, 0x00002c0a, 0x00002c3a, + 0x00001ea8, 0x00001ea9, 0x00010410, 0x00010438, + 0x0000042d, 0x0000044d, 0x000010c0, 0x00002d20, + 0x000001b2, 0x0000028b, 0x0000ff2e, 0x0000ff4e, + 0x00001c97, 0x000010d7, 0x000001e6, 0x000001e7, + 0x000118a6, 0x000118c6, 0x00002c19, 0x00002c49, + 0x00001fba, 0x00001f70, 0x00010ca5, 0x00010ce5, + 0x000104c4, 0x000104ec, 0x000003e6, 0x000003e7, + 0x0000a7c4, 0x0000a794, 0x00010d50, 0x00010d70, + 0x0000ab76, 0x000013a6, 0x00001ffa, 0x00001f7c, + 0x000001ae, 0x00000288, 0x0001057c, 0x000105a3, + 0x00000407, 0x00000457, 0x00001ed2, 0x00001ed3, + 0x00001c95, 0x000010d5, 0x00000409, 0x00000459, + 0x000010bf, 0x00002d1f, 0x00016ea8, 0x00016ec3, + 0x0000011c, 0x0000011d, 0x00016eaa, 0x00016ec5, + 0x00001f8a, 0x020001e5, 0x00001cba, 0x000010fa, + 0x0000ff32, 0x0000ff52, 0x00001fc4, 0x02000270, + 0x00001f5d, 0x00001f55, 0x000001d3, 0x000001d4, + 0x00001fcb, 0x00001f75, 0x00002c02, 0x00002c32, + 0x00016e50, 0x00016e70, 0x00002c01, 0x00002c31, + 0x0001e910, 0x0001e932, 0x00001fc6, 0x02000273, + 0x00000128, 0x00000129, 0x000003d5, 0x000003c6, + 0x00001f89, 0x020001e2, 0x000013f9, 0x000013f1, + 0x00000196, 0x00000269, 0x0000216e, 0x0000217e, + 0x00001fd9, 0x00001fd1, 0x0000a790, 0x0000a791, + 0x00010591, 0x000105b8, 0x00002c00, 0x00002c30, + 0x00001e78, 0x00001e79, 0x0000ff29, 0x0000ff49, + 0x000104c5, 0x000104ed, 0x000003ea, 0x000003eb, + 0x0000a7d2, 0x0000a7d3, 0x00010d51, 0x00010d71, + 0x00001cb7, 0x000010f7, 0x00001fd2, 0x0300027d, + 0x0000a692, 0x0000a693, 0x0001057d, 0x000105a4, + 0x00010425, 0x0001044d, 0x00001ed6, 0x00001ed7, + 0x00002c67, 0x00002c68, 0x00002c2b, 0x00002c5b, + 0x00000536, 0x00000566, 0x00010415, 0x0001043d, + 0x0000a76c, 0x0000a76d, 0x00000540, 0x00000570, + 0x00001f85, 0x020001d6, 0x0000012c, 0x0000012d, + 0x000118b5, 0x000118d5, 0x00001e76, 0x00001e77, + 0x00001e94, 0x00001e95, 0x000003dc, 0x000003dd, + 0x0000aba3, 0x000013d3, 0x00000462, 0x00000463, + 0x00016e51, 0x00016e71, 0x00002c9c, 0x00002c9d, + 0x0000041a, 0x0000043a, 0x00001f4c, 0x00001f44, + 0x00000162, 0x00000163, 0x00001f39, 0x00001f31, + 0x00000480, 0x00000481, 0x00001e40, 0x00001e41, + 0x0000a666, 0x0000a667, 0x00010409, 0x00010431, + 0x00002cd4, 0x00002cd5, 0x00001fa3, 0x02000230, + 0x00010c99, 0x00010cd9, 0x0000ab9d, 0x000013cd, + 0x00001e50, 0x00001e51, 0x00010417, 0x0001043f, + 0x0000054f, 0x0000057f, 0x000003e8, 0x000003e9, + 0x0000a7c7, 0x0000a7c8, 0x00010d52, 0x00010d72, + 0x00000548, 0x00000578, 0x00001fea, 0x00001f7a, + 0x000001ee, 0x000001ef, 0x00010576, 0x0001059d, + 0x000104d0, 0x000104f8, 0x00001ed4, 0x00001ed5, + 0x0000a744, 0x0000a745, 0x000118ad, 0x000118cd, + 0x00002c1b, 0x00002c4b, 0x00001f9d, 0x0200021e, + 0x00001c80, 0x00000432, 0x0000051a, 0x0000051b, + 0x00001f8c, 0x020001eb, 0x0000a646, 0x0000a647, + 0x0000ff22, 0x0000ff42, 0x00001c9b, 0x000010db, + 0x00010d5c, 0x00010d7c, 0x000001d5, 0x000001d6, + 0x00000412, 0x00000432, 0x00010ca4, 0x00010ce4, + 0x0000ab92, 0x000013c2, 0x00000168, 0x00000169, + 0x0000050e, 0x0000050f, 0x00001e9b, 0x00001e61, + 0x000001e0, 0x000001e1, 0x00001f4b, 0x00001f43, + 0x00001fa2, 0x0200022d, 0x0000a7cc, 0x0000a7cd, + 0x00000194, 0x00000263, 0x00016eb2, 0x00016ecd, + 0x000118aa, 0x000118ca, 0x000001de, 0x000001df, + 0x0001058a, 0x000105b1, 0x0000ab93, 0x000013c3, + 0x00001fc9, 0x00001f73, 0x0000a640, 0x0000a641, + 0x000104c7, 0x000104ef, 0x00000416, 0x00000436, + 0x0000a7d0, 0x0000a7d1 }; static const unsigned _uccase_extra_table[] = { diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index a8a75eff70863..26264aa2b170f 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -136,10 +136,6 @@ void php_clear_mysql(MY_MYSQL *mysql) { zend_string_release_ex(mysql->hash_key, 0); mysql->hash_key = NULL; } - if (!Z_ISUNDEF(mysql->li_read)) { - zval_ptr_dtor(&(mysql->li_read)); - ZVAL_UNDEF(&mysql->li_read); - } } /* }}} */ @@ -316,7 +312,7 @@ static int mysqli_object_has_property(zend_object *object, zend_string *name, in zval rv; zval *value = mysqli_read_property(object, name, BP_VAR_IS, cache_slot, &rv); if (value != &EG(uninitialized_zval)) { - has_property = zval_is_true(value); + has_property = zend_is_true(value); zval_ptr_dtor(value); } break; @@ -424,6 +420,19 @@ static const MYSQLND_REVERSE_API mysqli_reverse_api = { mysqli_convert_zv_to_mysqlnd }; +static PHP_INI_MH(OnUpdateDefaultPort) +{ + zend_long value = ZEND_ATOL(ZSTR_VAL(new_value)); + + if (value < 0 || value > USHRT_MAX) { + return FAILURE; + } + + MyG(default_port) = (unsigned short)value; + + return SUCCESS; +} + /* {{{ PHP_INI_BEGIN */ PHP_INI_BEGIN() STD_PHP_INI_ENTRY_EX("mysqli.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_links, zend_mysqli_globals, mysqli_globals, display_link_numbers) @@ -433,7 +442,7 @@ PHP_INI_BEGIN() STD_PHP_INI_ENTRY("mysqli.default_host", NULL, PHP_INI_ALL, OnUpdateString, default_host, zend_mysqli_globals, mysqli_globals) STD_PHP_INI_ENTRY("mysqli.default_user", NULL, PHP_INI_ALL, OnUpdateString, default_user, zend_mysqli_globals, mysqli_globals) STD_PHP_INI_ENTRY("mysqli.default_pw", NULL, PHP_INI_ALL, OnUpdateString, default_pw, zend_mysqli_globals, mysqli_globals) - STD_PHP_INI_ENTRY("mysqli.default_port", "3306", PHP_INI_ALL, OnUpdateLong, default_port, zend_mysqli_globals, mysqli_globals) + STD_PHP_INI_ENTRY("mysqli.default_port", "3306", PHP_INI_ALL, OnUpdateDefaultPort, default_port, zend_mysqli_globals, mysqli_globals) #ifdef PHP_MYSQL_UNIX_SOCK_ADDR STD_PHP_INI_ENTRY("mysqli.default_socket", MYSQL_UNIX_ADDR,PHP_INI_ALL,OnUpdateStringUnempty, default_socket, zend_mysqli_globals, mysqli_globals) #else @@ -775,7 +784,7 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags } } } - MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); + MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, MYSQLI_STATUS_VALID); if (fetchtype < MYSQLI_ASSOC || fetchtype > MYSQLI_BOTH) { zend_argument_value_error(ERROR_ARG_POS(2), "must be one of MYSQLI_NUM, MYSQLI_ASSOC, or MYSQLI_BOTH"); diff --git a/ext/mysqli/mysqli.stub.php b/ext/mysqli/mysqli.stub.php index 06db6ac26860b..370da77e62a25 100644 --- a/ext/mysqli/mysqli.stub.php +++ b/ext/mysqli/mysqli.stub.php @@ -589,9 +589,6 @@ */ const MYSQLI_TRANS_COR_NO_RELEASE = UNKNOWN; -/** - * @var bool - */ #[\Deprecated(since: '8.2', message: 'as it is always false')] const MYSQLI_IS_MARIADB = false; @@ -1383,6 +1380,7 @@ function mysqli_error_list(mysqli $mysql): array {} function mysqli_stmt_execute(mysqli_stmt $statement, ?array $params = null): bool {} /** @alias mysqli_stmt_execute */ +#[\Deprecated(since: '8.5', message: "use mysqli_stmt_execute() instead")] function mysqli_execute(mysqli_stmt $statement, ?array $params = null): bool {} function mysqli_execute_query(mysqli $mysql, string $query, ?array $params = null): mysqli_result|bool {} diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index 2a20919eee45e..1bf74dd77eeab 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -324,7 +324,7 @@ PHP_FUNCTION(mysqli_data_seek) RETURN_THROWS(); } - MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); + MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, MYSQLI_STATUS_VALID); if (mysqli_result_is_unbuffered(result)) { if (hasThis()) { @@ -670,7 +670,7 @@ PHP_FUNCTION(mysqli_fetch_field) RETURN_THROWS(); } - MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); + MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, MYSQLI_STATUS_VALID); if (!(field = mysql_fetch_field(result))) { RETURN_FALSE; @@ -694,7 +694,7 @@ PHP_FUNCTION(mysqli_fetch_fields) RETURN_THROWS(); } - MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); + MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, MYSQLI_STATUS_VALID); array_init(return_value); num_fields = mysql_num_fields(result); @@ -727,7 +727,7 @@ PHP_FUNCTION(mysqli_fetch_field_direct) RETURN_THROWS(); } - MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); + MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, MYSQLI_STATUS_VALID); if (offset >= (zend_long) mysql_num_fields(result)) { zend_argument_value_error(ERROR_ARG_POS(2), "must be less than the number of fields for this result set"); @@ -755,7 +755,7 @@ PHP_FUNCTION(mysqli_fetch_lengths) RETURN_THROWS(); } - MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); + MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, MYSQLI_STATUS_VALID); // TODO Warning? if (!(ret = mysql_fetch_lengths(result))) { @@ -809,7 +809,7 @@ PHP_FUNCTION(mysqli_field_seek) RETURN_THROWS(); } - MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); + MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, MYSQLI_STATUS_VALID); if ((uint32_t)fieldnr >= mysql_num_fields(result)) { zend_argument_value_error(ERROR_ARG_POS(2), "must be less than the number of fields for this result set"); @@ -830,7 +830,7 @@ PHP_FUNCTION(mysqli_field_tell) if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) { RETURN_THROWS(); } - MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); + MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, MYSQLI_STATUS_VALID); RETURN_LONG(mysql_field_tell(result)); } @@ -845,7 +845,7 @@ PHP_FUNCTION(mysqli_free_result) if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) { RETURN_THROWS(); } - MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); + MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, MYSQLI_STATUS_VALID); mysqli_free_result(result, false); MYSQLI_CLEAR_RESOURCE(mysql_result); @@ -1123,7 +1123,7 @@ PHP_FUNCTION(mysqli_num_fields) if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) { RETURN_THROWS(); } - MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); + MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, MYSQLI_STATUS_VALID); RETURN_LONG(mysql_num_fields(result)); } @@ -1138,7 +1138,7 @@ PHP_FUNCTION(mysqli_num_rows) if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) { RETURN_THROWS(); } - MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); + MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, MYSQLI_STATUS_VALID); if (mysqli_result_is_unbuffered_and_not_everything_is_fetched(result)) { zend_throw_error(NULL, "mysqli_num_rows() cannot be used in MYSQLI_USE_RESULT mode"); @@ -1343,9 +1343,6 @@ PHP_FUNCTION(mysqli_real_query) } /* }}} */ -# define mysql_real_escape_string_quote(mysql, to, from, length, quote) \ - mysql_real_escape_string(mysql, to, from, length) - PHP_FUNCTION(mysqli_real_escape_string) { MY_MYSQL *mysql; zval *mysql_link = NULL; @@ -1359,7 +1356,7 @@ PHP_FUNCTION(mysqli_real_escape_string) { MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID); newstr = zend_string_safe_alloc(2, escapestr_len, 0, 0); - ZSTR_LEN(newstr) = mysql_real_escape_string_quote(mysql->mysql, ZSTR_VAL(newstr), escapestr, escapestr_len, '\''); + ZSTR_LEN(newstr) = mysql_real_escape_string(mysql->mysql, ZSTR_VAL(newstr), escapestr, escapestr_len); newstr = zend_string_truncate(newstr, ZSTR_LEN(newstr), 0); RETURN_NEW_STR(newstr); diff --git a/ext/mysqli/mysqli_arginfo.h b/ext/mysqli/mysqli_arginfo.h index a0871cb9883f2..789464a762538 100644 --- a/ext/mysqli/mysqli_arginfo.h +++ b/ext/mysqli/mysqli_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 2547f63fd024fd5f4fecc574bbcff1301d1d36e5 */ + * Stub hash: fecde55745fb219cb15fd35a54a71371ef2b8b7d */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mysqli_affected_rows, 0, 1, MAY_BE_LONG|MAY_BE_STRING) ZEND_ARG_OBJ_INFO(0, mysql, mysqli, 0) @@ -837,7 +837,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(mysqli_error, arginfo_mysqli_error) ZEND_FE(mysqli_error_list, arginfo_mysqli_error_list) ZEND_FE(mysqli_stmt_execute, arginfo_mysqli_stmt_execute) - ZEND_RAW_FENTRY("mysqli_execute", zif_mysqli_stmt_execute, arginfo_mysqli_execute, 0, NULL, NULL) + ZEND_RAW_FENTRY("mysqli_execute", zif_mysqli_stmt_execute, arginfo_mysqli_execute, ZEND_ACC_DEPRECATED, NULL, NULL) ZEND_FE(mysqli_execute_query, arginfo_mysqli_execute_query) ZEND_FE(mysqli_fetch_field, arginfo_mysqli_fetch_field) ZEND_FE(mysqli_fetch_fields, arginfo_mysqli_fetch_fields) @@ -1150,22 +1150,25 @@ static void register_mysqli_symbols(int module_number) zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "mysqli_connect", sizeof("mysqli_connect") - 1), 2, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); + zend_attribute *attribute_Deprecated_func_mysqli_execute_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mysqli_execute", sizeof("mysqli_execute") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_func_mysqli_execute_0->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_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_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); @@ -1173,172 +1176,120 @@ static void register_mysqli_symbols(int module_number) 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_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); - zval attribute_Deprecated_const_MYSQLI_STORE_RESULT_COPY_DATA_0_arg1; 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_arg1, attribute_Deprecated_const_MYSQLI_STORE_RESULT_COPY_DATA_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_MYSQLI_STORE_RESULT_COPY_DATA_0->args[1].value, &attribute_Deprecated_const_MYSQLI_STORE_RESULT_COPY_DATA_0_arg1); + 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); - zval attribute_Deprecated_const_MYSQLI_NO_DATA_0_arg1; 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_arg1, attribute_Deprecated_const_MYSQLI_NO_DATA_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_MYSQLI_NO_DATA_0->args[1].value, &attribute_Deprecated_const_MYSQLI_NO_DATA_0_arg1); + 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 attribute_Deprecated_const_MYSQLI_DATA_TRUNCATED_0_arg1; - zend_string *attribute_Deprecated_const_MYSQLI_DATA_TRUNCATED_0_arg1_str = zend_string_init("as it was unused", strlen("as it was unused"), 1); - ZVAL_STR(&attribute_Deprecated_const_MYSQLI_DATA_TRUNCATED_0_arg1, attribute_Deprecated_const_MYSQLI_DATA_TRUNCATED_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_MYSQLI_DATA_TRUNCATED_0->args[1].value, &attribute_Deprecated_const_MYSQLI_DATA_TRUNCATED_0_arg1); + 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 attribute_Deprecated_const_MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED_0_arg1; - zend_string *attribute_Deprecated_const_MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED_0_arg1_str = zend_string_init("as it was unused", strlen("as it was unused"), 1); - ZVAL_STR(&attribute_Deprecated_const_MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED_0_arg1, attribute_Deprecated_const_MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED_0->args[1].value, &attribute_Deprecated_const_MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED_0_arg1); + 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 attribute_Deprecated_const_MYSQLI_SERVER_QUERY_NO_INDEX_USED_0_arg1; - zend_string *attribute_Deprecated_const_MYSQLI_SERVER_QUERY_NO_INDEX_USED_0_arg1_str = zend_string_init("as it was unused", strlen("as it was unused"), 1); - ZVAL_STR(&attribute_Deprecated_const_MYSQLI_SERVER_QUERY_NO_INDEX_USED_0_arg1, attribute_Deprecated_const_MYSQLI_SERVER_QUERY_NO_INDEX_USED_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_MYSQLI_SERVER_QUERY_NO_INDEX_USED_0->args[1].value, &attribute_Deprecated_const_MYSQLI_SERVER_QUERY_NO_INDEX_USED_0_arg1); + 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 attribute_Deprecated_const_MYSQLI_SERVER_QUERY_WAS_SLOW_0_arg1; - zend_string *attribute_Deprecated_const_MYSQLI_SERVER_QUERY_WAS_SLOW_0_arg1_str = zend_string_init("as it was unused", strlen("as it was unused"), 1); - ZVAL_STR(&attribute_Deprecated_const_MYSQLI_SERVER_QUERY_WAS_SLOW_0_arg1, attribute_Deprecated_const_MYSQLI_SERVER_QUERY_WAS_SLOW_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_MYSQLI_SERVER_QUERY_WAS_SLOW_0->args[1].value, &attribute_Deprecated_const_MYSQLI_SERVER_QUERY_WAS_SLOW_0_arg1); + 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 attribute_Deprecated_const_MYSQLI_SERVER_PS_OUT_PARAMS_0_arg1; - zend_string *attribute_Deprecated_const_MYSQLI_SERVER_PS_OUT_PARAMS_0_arg1_str = zend_string_init("as it was unused", strlen("as it was unused"), 1); - ZVAL_STR(&attribute_Deprecated_const_MYSQLI_SERVER_PS_OUT_PARAMS_0_arg1, attribute_Deprecated_const_MYSQLI_SERVER_PS_OUT_PARAMS_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_MYSQLI_SERVER_PS_OUT_PARAMS_0->args[1].value, &attribute_Deprecated_const_MYSQLI_SERVER_PS_OUT_PARAMS_0_arg1); + 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); - zval attribute_Deprecated_const_MYSQLI_REFRESH_GRANT_0_arg1; 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_arg1, attribute_Deprecated_const_MYSQLI_REFRESH_GRANT_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_MYSQLI_REFRESH_GRANT_0->args[1].value, &attribute_Deprecated_const_MYSQLI_REFRESH_GRANT_0_arg1); + 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 attribute_Deprecated_const_MYSQLI_REFRESH_LOG_0_arg1; - zend_string *attribute_Deprecated_const_MYSQLI_REFRESH_LOG_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_LOG_0_arg1, attribute_Deprecated_const_MYSQLI_REFRESH_LOG_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_MYSQLI_REFRESH_LOG_0->args[1].value, &attribute_Deprecated_const_MYSQLI_REFRESH_LOG_0_arg1); + 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 attribute_Deprecated_const_MYSQLI_REFRESH_TABLES_0_arg1; - zend_string *attribute_Deprecated_const_MYSQLI_REFRESH_TABLES_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_TABLES_0_arg1, attribute_Deprecated_const_MYSQLI_REFRESH_TABLES_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_MYSQLI_REFRESH_TABLES_0->args[1].value, &attribute_Deprecated_const_MYSQLI_REFRESH_TABLES_0_arg1); + 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 attribute_Deprecated_const_MYSQLI_REFRESH_HOSTS_0_arg1; - zend_string *attribute_Deprecated_const_MYSQLI_REFRESH_HOSTS_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_HOSTS_0_arg1, attribute_Deprecated_const_MYSQLI_REFRESH_HOSTS_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_MYSQLI_REFRESH_HOSTS_0->args[1].value, &attribute_Deprecated_const_MYSQLI_REFRESH_HOSTS_0_arg1); + 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 attribute_Deprecated_const_MYSQLI_REFRESH_STATUS_0_arg1; - zend_string *attribute_Deprecated_const_MYSQLI_REFRESH_STATUS_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_STATUS_0_arg1, attribute_Deprecated_const_MYSQLI_REFRESH_STATUS_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_MYSQLI_REFRESH_STATUS_0->args[1].value, &attribute_Deprecated_const_MYSQLI_REFRESH_STATUS_0_arg1); + 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 attribute_Deprecated_const_MYSQLI_REFRESH_THREADS_0_arg1; - zend_string *attribute_Deprecated_const_MYSQLI_REFRESH_THREADS_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_THREADS_0_arg1, attribute_Deprecated_const_MYSQLI_REFRESH_THREADS_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_MYSQLI_REFRESH_THREADS_0->args[1].value, &attribute_Deprecated_const_MYSQLI_REFRESH_THREADS_0_arg1); + 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 attribute_Deprecated_const_MYSQLI_REFRESH_REPLICA_0_arg1; - zend_string *attribute_Deprecated_const_MYSQLI_REFRESH_REPLICA_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_REPLICA_0_arg1, attribute_Deprecated_const_MYSQLI_REFRESH_REPLICA_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_MYSQLI_REFRESH_REPLICA_0->args[1].value, &attribute_Deprecated_const_MYSQLI_REFRESH_REPLICA_0_arg1); + 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 attribute_Deprecated_const_MYSQLI_REFRESH_SLAVE_0_arg1; - zend_string *attribute_Deprecated_const_MYSQLI_REFRESH_SLAVE_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_SLAVE_0_arg1, attribute_Deprecated_const_MYSQLI_REFRESH_SLAVE_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_MYSQLI_REFRESH_SLAVE_0->args[1].value, &attribute_Deprecated_const_MYSQLI_REFRESH_SLAVE_0_arg1); + 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 attribute_Deprecated_const_MYSQLI_REFRESH_MASTER_0_arg1; - zend_string *attribute_Deprecated_const_MYSQLI_REFRESH_MASTER_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_MASTER_0_arg1, attribute_Deprecated_const_MYSQLI_REFRESH_MASTER_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_MYSQLI_REFRESH_MASTER_0->args[1].value, &attribute_Deprecated_const_MYSQLI_REFRESH_MASTER_0_arg1); + 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 attribute_Deprecated_const_MYSQLI_REFRESH_BACKUP_LOG_0_arg1; - zend_string *attribute_Deprecated_const_MYSQLI_REFRESH_BACKUP_LOG_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_BACKUP_LOG_0_arg1, attribute_Deprecated_const_MYSQLI_REFRESH_BACKUP_LOG_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_MYSQLI_REFRESH_BACKUP_LOG_0->args[1].value, &attribute_Deprecated_const_MYSQLI_REFRESH_BACKUP_LOG_0_arg1); + 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); - zval attribute_Deprecated_const_MYSQLI_IS_MARIADB_0_arg1; 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_arg1, attribute_Deprecated_const_MYSQLI_IS_MARIADB_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_MYSQLI_IS_MARIADB_0->args[1].value, &attribute_Deprecated_const_MYSQLI_IS_MARIADB_0_arg1); + 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); } @@ -1351,27 +1302,27 @@ static zend_class_entry *register_class_mysqli_driver(void) zval property_client_info_default_value; ZVAL_UNDEF(&property_client_info_default_value); - zend_string *property_client_info_name = zend_string_init("client_info", sizeof("client_info") - 1, 1); + zend_string *property_client_info_name = zend_string_init("client_info", sizeof("client_info") - 1, true); zend_declare_typed_property(class_entry, property_client_info_name, &property_client_info_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_client_info_name); + zend_string_release_ex(property_client_info_name, true); zval property_client_version_default_value; ZVAL_UNDEF(&property_client_version_default_value); - zend_string *property_client_version_name = zend_string_init("client_version", sizeof("client_version") - 1, 1); + zend_string *property_client_version_name = zend_string_init("client_version", sizeof("client_version") - 1, true); zend_declare_typed_property(class_entry, property_client_version_name, &property_client_version_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_client_version_name); + zend_string_release_ex(property_client_version_name, true); zval property_driver_version_default_value; ZVAL_UNDEF(&property_driver_version_default_value); - zend_string *property_driver_version_name = zend_string_init("driver_version", sizeof("driver_version") - 1, 1); + zend_string *property_driver_version_name = zend_string_init("driver_version", sizeof("driver_version") - 1, true); zend_declare_typed_property(class_entry, property_driver_version_name, &property_driver_version_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_driver_version_name); + zend_string_release_ex(property_driver_version_name, true); zval property_report_mode_default_value; ZVAL_LONG(&property_report_mode_default_value, 0); - zend_string *property_report_mode_name = zend_string_init("report_mode", sizeof("report_mode") - 1, 1); + zend_string *property_report_mode_name = zend_string_init("report_mode", sizeof("report_mode") - 1, true); zend_declare_typed_property(class_entry, property_report_mode_name, &property_report_mode_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_report_mode_name); + zend_string_release_ex(property_report_mode_name, true); return class_entry; } @@ -1385,111 +1336,111 @@ static zend_class_entry *register_class_mysqli(void) zval property_affected_rows_default_value; ZVAL_UNDEF(&property_affected_rows_default_value); - zend_string *property_affected_rows_name = zend_string_init("affected_rows", sizeof("affected_rows") - 1, 1); + zend_string *property_affected_rows_name = zend_string_init("affected_rows", sizeof("affected_rows") - 1, true); zend_declare_typed_property(class_entry, property_affected_rows_name, &property_affected_rows_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG|MAY_BE_STRING)); - zend_string_release(property_affected_rows_name); + zend_string_release_ex(property_affected_rows_name, true); zval property_client_info_default_value; ZVAL_UNDEF(&property_client_info_default_value); - zend_string *property_client_info_name = zend_string_init("client_info", sizeof("client_info") - 1, 1); + zend_string *property_client_info_name = zend_string_init("client_info", sizeof("client_info") - 1, true); zend_declare_typed_property(class_entry, property_client_info_name, &property_client_info_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_client_info_name); + zend_string_release_ex(property_client_info_name, true); zval property_client_version_default_value; ZVAL_UNDEF(&property_client_version_default_value); - zend_string *property_client_version_name = zend_string_init("client_version", sizeof("client_version") - 1, 1); + zend_string *property_client_version_name = zend_string_init("client_version", sizeof("client_version") - 1, true); zend_declare_typed_property(class_entry, property_client_version_name, &property_client_version_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_client_version_name); + zend_string_release_ex(property_client_version_name, true); zval property_connect_errno_default_value; ZVAL_UNDEF(&property_connect_errno_default_value); - zend_string *property_connect_errno_name = zend_string_init("connect_errno", sizeof("connect_errno") - 1, 1); + zend_string *property_connect_errno_name = zend_string_init("connect_errno", sizeof("connect_errno") - 1, true); zend_declare_typed_property(class_entry, property_connect_errno_name, &property_connect_errno_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_connect_errno_name); + zend_string_release_ex(property_connect_errno_name, true); zval property_connect_error_default_value; ZVAL_UNDEF(&property_connect_error_default_value); - zend_string *property_connect_error_name = zend_string_init("connect_error", sizeof("connect_error") - 1, 1); + zend_string *property_connect_error_name = zend_string_init("connect_error", sizeof("connect_error") - 1, true); zend_declare_typed_property(class_entry, property_connect_error_name, &property_connect_error_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_connect_error_name); + zend_string_release_ex(property_connect_error_name, true); zval property_errno_default_value; ZVAL_UNDEF(&property_errno_default_value); - zend_string *property_errno_name = zend_string_init("errno", sizeof("errno") - 1, 1); + zend_string *property_errno_name = zend_string_init("errno", sizeof("errno") - 1, true); zend_declare_typed_property(class_entry, property_errno_name, &property_errno_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_errno_name); + zend_string_release_ex(property_errno_name, true); zval property_error_default_value; ZVAL_UNDEF(&property_error_default_value); - zend_string *property_error_name = zend_string_init("error", sizeof("error") - 1, 1); + zend_string *property_error_name = zend_string_init("error", sizeof("error") - 1, true); zend_declare_typed_property(class_entry, property_error_name, &property_error_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_error_name); + zend_string_release_ex(property_error_name, true); zval property_error_list_default_value; ZVAL_UNDEF(&property_error_list_default_value); - zend_string *property_error_list_name = zend_string_init("error_list", sizeof("error_list") - 1, 1); + zend_string *property_error_list_name = zend_string_init("error_list", sizeof("error_list") - 1, true); zend_declare_typed_property(class_entry, property_error_list_name, &property_error_list_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ARRAY)); - zend_string_release(property_error_list_name); + zend_string_release_ex(property_error_list_name, true); zval property_field_count_default_value; ZVAL_UNDEF(&property_field_count_default_value); - zend_string *property_field_count_name = zend_string_init("field_count", sizeof("field_count") - 1, 1); + zend_string *property_field_count_name = zend_string_init("field_count", sizeof("field_count") - 1, true); zend_declare_typed_property(class_entry, property_field_count_name, &property_field_count_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_field_count_name); + zend_string_release_ex(property_field_count_name, true); zval property_host_info_default_value; ZVAL_UNDEF(&property_host_info_default_value); - zend_string *property_host_info_name = zend_string_init("host_info", sizeof("host_info") - 1, 1); + zend_string *property_host_info_name = zend_string_init("host_info", sizeof("host_info") - 1, true); zend_declare_typed_property(class_entry, property_host_info_name, &property_host_info_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_host_info_name); + zend_string_release_ex(property_host_info_name, true); zval property_info_default_value; ZVAL_UNDEF(&property_info_default_value); - zend_string *property_info_name = zend_string_init("info", sizeof("info") - 1, 1); + zend_string *property_info_name = zend_string_init("info", sizeof("info") - 1, true); zend_declare_typed_property(class_entry, property_info_name, &property_info_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_info_name); + zend_string_release_ex(property_info_name, true); zval property_insert_id_default_value; ZVAL_UNDEF(&property_insert_id_default_value); - zend_string *property_insert_id_name = zend_string_init("insert_id", sizeof("insert_id") - 1, 1); + zend_string *property_insert_id_name = zend_string_init("insert_id", sizeof("insert_id") - 1, true); zend_declare_typed_property(class_entry, property_insert_id_name, &property_insert_id_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG|MAY_BE_STRING)); - zend_string_release(property_insert_id_name); + zend_string_release_ex(property_insert_id_name, true); zval property_server_info_default_value; ZVAL_UNDEF(&property_server_info_default_value); - zend_string *property_server_info_name = zend_string_init("server_info", sizeof("server_info") - 1, 1); + zend_string *property_server_info_name = zend_string_init("server_info", sizeof("server_info") - 1, true); zend_declare_typed_property(class_entry, property_server_info_name, &property_server_info_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_server_info_name); + zend_string_release_ex(property_server_info_name, true); zval property_server_version_default_value; ZVAL_UNDEF(&property_server_version_default_value); - zend_string *property_server_version_name = zend_string_init("server_version", sizeof("server_version") - 1, 1); + zend_string *property_server_version_name = zend_string_init("server_version", sizeof("server_version") - 1, true); zend_declare_typed_property(class_entry, property_server_version_name, &property_server_version_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_server_version_name); + zend_string_release_ex(property_server_version_name, true); zval property_sqlstate_default_value; ZVAL_UNDEF(&property_sqlstate_default_value); - zend_string *property_sqlstate_name = zend_string_init("sqlstate", sizeof("sqlstate") - 1, 1); + zend_string *property_sqlstate_name = zend_string_init("sqlstate", sizeof("sqlstate") - 1, true); zend_declare_typed_property(class_entry, property_sqlstate_name, &property_sqlstate_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_sqlstate_name); + zend_string_release_ex(property_sqlstate_name, true); zval property_protocol_version_default_value; ZVAL_UNDEF(&property_protocol_version_default_value); - zend_string *property_protocol_version_name = zend_string_init("protocol_version", sizeof("protocol_version") - 1, 1); + zend_string *property_protocol_version_name = zend_string_init("protocol_version", sizeof("protocol_version") - 1, true); zend_declare_typed_property(class_entry, property_protocol_version_name, &property_protocol_version_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_protocol_version_name); + zend_string_release_ex(property_protocol_version_name, true); zval property_thread_id_default_value; ZVAL_UNDEF(&property_thread_id_default_value); - zend_string *property_thread_id_name = zend_string_init("thread_id", sizeof("thread_id") - 1, 1); + zend_string *property_thread_id_name = zend_string_init("thread_id", sizeof("thread_id") - 1, true); zend_declare_typed_property(class_entry, property_thread_id_name, &property_thread_id_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_thread_id_name); + zend_string_release_ex(property_thread_id_name, true); zval property_warning_count_default_value; ZVAL_UNDEF(&property_warning_count_default_value); - zend_string *property_warning_count_name = zend_string_init("warning_count", sizeof("warning_count") - 1, 1); + zend_string *property_warning_count_name = zend_string_init("warning_count", sizeof("warning_count") - 1, true); zend_declare_typed_property(class_entry, property_warning_count_name, &property_warning_count_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_warning_count_name); + zend_string_release_ex(property_warning_count_name, true); zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "__construct", sizeof("__construct") - 1), 2, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); @@ -1501,37 +1452,29 @@ static zend_class_entry *register_class_mysqli(void) 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_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_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_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_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); @@ -1539,10 +1482,8 @@ static zend_class_entry *register_class_mysqli(void) 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_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; @@ -1558,27 +1499,27 @@ static zend_class_entry *register_class_mysqli_result(zend_class_entry *class_en zval property_current_field_default_value; ZVAL_UNDEF(&property_current_field_default_value); - zend_string *property_current_field_name = zend_string_init("current_field", sizeof("current_field") - 1, 1); + zend_string *property_current_field_name = zend_string_init("current_field", sizeof("current_field") - 1, true); zend_declare_typed_property(class_entry, property_current_field_name, &property_current_field_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_current_field_name); + zend_string_release_ex(property_current_field_name, true); zval property_field_count_default_value; ZVAL_UNDEF(&property_field_count_default_value); - zend_string *property_field_count_name = zend_string_init("field_count", sizeof("field_count") - 1, 1); + zend_string *property_field_count_name = zend_string_init("field_count", sizeof("field_count") - 1, true); zend_declare_typed_property(class_entry, property_field_count_name, &property_field_count_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_field_count_name); + zend_string_release_ex(property_field_count_name, true); zval property_lengths_default_value; ZVAL_UNDEF(&property_lengths_default_value); - zend_string *property_lengths_name = zend_string_init("lengths", sizeof("lengths") - 1, 1); + zend_string *property_lengths_name = zend_string_init("lengths", sizeof("lengths") - 1, true); zend_declare_typed_property(class_entry, property_lengths_name, &property_lengths_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ARRAY|MAY_BE_NULL)); - zend_string_release(property_lengths_name); + zend_string_release_ex(property_lengths_name, true); zval property_num_rows_default_value; ZVAL_UNDEF(&property_num_rows_default_value); - zend_string *property_num_rows_name = zend_string_init("num_rows", sizeof("num_rows") - 1, 1); + zend_string *property_num_rows_name = zend_string_init("num_rows", sizeof("num_rows") - 1, true); zend_declare_typed_property(class_entry, property_num_rows_name, &property_num_rows_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG|MAY_BE_STRING)); - zend_string_release(property_num_rows_name); + zend_string_release_ex(property_num_rows_name, true); zval property_type_default_value; ZVAL_UNDEF(&property_type_default_value); @@ -1596,63 +1537,63 @@ static zend_class_entry *register_class_mysqli_stmt(void) zval property_affected_rows_default_value; ZVAL_UNDEF(&property_affected_rows_default_value); - zend_string *property_affected_rows_name = zend_string_init("affected_rows", sizeof("affected_rows") - 1, 1); + zend_string *property_affected_rows_name = zend_string_init("affected_rows", sizeof("affected_rows") - 1, true); zend_declare_typed_property(class_entry, property_affected_rows_name, &property_affected_rows_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG|MAY_BE_STRING)); - zend_string_release(property_affected_rows_name); + zend_string_release_ex(property_affected_rows_name, true); zval property_insert_id_default_value; ZVAL_UNDEF(&property_insert_id_default_value); - zend_string *property_insert_id_name = zend_string_init("insert_id", sizeof("insert_id") - 1, 1); + zend_string *property_insert_id_name = zend_string_init("insert_id", sizeof("insert_id") - 1, true); zend_declare_typed_property(class_entry, property_insert_id_name, &property_insert_id_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG|MAY_BE_STRING)); - zend_string_release(property_insert_id_name); + zend_string_release_ex(property_insert_id_name, true); zval property_num_rows_default_value; ZVAL_UNDEF(&property_num_rows_default_value); - zend_string *property_num_rows_name = zend_string_init("num_rows", sizeof("num_rows") - 1, 1); + zend_string *property_num_rows_name = zend_string_init("num_rows", sizeof("num_rows") - 1, true); zend_declare_typed_property(class_entry, property_num_rows_name, &property_num_rows_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG|MAY_BE_STRING)); - zend_string_release(property_num_rows_name); + zend_string_release_ex(property_num_rows_name, true); zval property_param_count_default_value; ZVAL_UNDEF(&property_param_count_default_value); - zend_string *property_param_count_name = zend_string_init("param_count", sizeof("param_count") - 1, 1); + zend_string *property_param_count_name = zend_string_init("param_count", sizeof("param_count") - 1, true); zend_declare_typed_property(class_entry, property_param_count_name, &property_param_count_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_param_count_name); + zend_string_release_ex(property_param_count_name, true); zval property_field_count_default_value; ZVAL_UNDEF(&property_field_count_default_value); - zend_string *property_field_count_name = zend_string_init("field_count", sizeof("field_count") - 1, 1); + zend_string *property_field_count_name = zend_string_init("field_count", sizeof("field_count") - 1, true); zend_declare_typed_property(class_entry, property_field_count_name, &property_field_count_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_field_count_name); + zend_string_release_ex(property_field_count_name, true); zval property_errno_default_value; ZVAL_UNDEF(&property_errno_default_value); - zend_string *property_errno_name = zend_string_init("errno", sizeof("errno") - 1, 1); + zend_string *property_errno_name = zend_string_init("errno", sizeof("errno") - 1, true); zend_declare_typed_property(class_entry, property_errno_name, &property_errno_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_errno_name); + zend_string_release_ex(property_errno_name, true); zval property_error_default_value; ZVAL_UNDEF(&property_error_default_value); - zend_string *property_error_name = zend_string_init("error", sizeof("error") - 1, 1); + zend_string *property_error_name = zend_string_init("error", sizeof("error") - 1, true); zend_declare_typed_property(class_entry, property_error_name, &property_error_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_error_name); + zend_string_release_ex(property_error_name, true); zval property_error_list_default_value; ZVAL_UNDEF(&property_error_list_default_value); - zend_string *property_error_list_name = zend_string_init("error_list", sizeof("error_list") - 1, 1); + zend_string *property_error_list_name = zend_string_init("error_list", sizeof("error_list") - 1, true); zend_declare_typed_property(class_entry, property_error_list_name, &property_error_list_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ARRAY)); - zend_string_release(property_error_list_name); + zend_string_release_ex(property_error_list_name, true); zval property_sqlstate_default_value; ZVAL_UNDEF(&property_sqlstate_default_value); - zend_string *property_sqlstate_name = zend_string_init("sqlstate", sizeof("sqlstate") - 1, 1); + zend_string *property_sqlstate_name = zend_string_init("sqlstate", sizeof("sqlstate") - 1, true); zend_declare_typed_property(class_entry, property_sqlstate_name, &property_sqlstate_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_sqlstate_name); + zend_string_release_ex(property_sqlstate_name, true); 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_string *property_id_name = zend_string_init("id", sizeof("id") - 1, true); zend_declare_typed_property(class_entry, property_id_name, &property_id_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_id_name); + zend_string_release_ex(property_id_name, true); return class_entry; } @@ -1670,15 +1611,15 @@ static zend_class_entry *register_class_mysqli_warning(void) zval property_sqlstate_default_value; ZVAL_UNDEF(&property_sqlstate_default_value); - zend_string *property_sqlstate_name = zend_string_init("sqlstate", sizeof("sqlstate") - 1, 1); + zend_string *property_sqlstate_name = zend_string_init("sqlstate", sizeof("sqlstate") - 1, true); zend_declare_typed_property(class_entry, property_sqlstate_name, &property_sqlstate_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_sqlstate_name); + zend_string_release_ex(property_sqlstate_name, true); zval property_errno_default_value; ZVAL_UNDEF(&property_errno_default_value); - zend_string *property_errno_name = zend_string_init("errno", sizeof("errno") - 1, 1); + zend_string *property_errno_name = zend_string_init("errno", sizeof("errno") - 1, true); zend_declare_typed_property(class_entry, property_errno_name, &property_errno_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_errno_name); + zend_string_release_ex(property_errno_name, true); return class_entry; } @@ -1693,9 +1634,9 @@ static zend_class_entry *register_class_mysqli_sql_exception(zend_class_entry *c zval property_sqlstate_default_value; zend_string *property_sqlstate_default_value_str = zend_string_init("00000", strlen("00000"), 1); ZVAL_STR(&property_sqlstate_default_value, property_sqlstate_default_value_str); - zend_string *property_sqlstate_name = zend_string_init("sqlstate", sizeof("sqlstate") - 1, 1); + zend_string *property_sqlstate_name = zend_string_init("sqlstate", sizeof("sqlstate") - 1, true); zend_declare_typed_property(class_entry, property_sqlstate_name, &property_sqlstate_default_value, ZEND_ACC_PROTECTED, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_sqlstate_name); + zend_string_release_ex(property_sqlstate_name, true); return class_entry; } diff --git a/ext/mysqli/mysqli_nonapi.c b/ext/mysqli/mysqli_nonapi.c index e0e14eeccbc92..a3208b41574b1 100644 --- a/ext/mysqli/mysqli_nonapi.c +++ b/ext/mysqli/mysqli_nonapi.c @@ -56,12 +56,12 @@ void mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS, bool is_real_connect, b size_t hostname_len = 0, username_len = 0, passwd_len = 0, dbname_len = 0, socket_len = 0; bool persistent = false, ssl = false; zend_long port = 0, flags = 0; - bool port_is_null = 1; + bool port_is_null = true; zend_string *hash_key = NULL; bool new_connection = false; zend_resource *le; mysqli_plist_entry *plist = NULL; - bool self_alloced = 0; + bool self_alloced = false; #if !defined(MYSQL_USE_MYSQLND) @@ -105,9 +105,8 @@ void mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS, bool is_real_connect, b } if (!mysql) { mysql = (MY_MYSQL *) ecalloc(1, sizeof(MY_MYSQL)); - self_alloced = 1; + self_alloced = true; } - flags |= CLIENT_MULTI_RESULTS; /* needed for mysql_multi_query() */ } else { /* We have flags too */ if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|s!s!s!s!l!s!l", &object, mysqli_link_class_entry, @@ -118,11 +117,10 @@ void mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS, bool is_real_connect, b mysqli_resource = (Z_MYSQLI_P(object))->ptr; MYSQLI_FETCH_RESOURCE_CONN(mysql, object, MYSQLI_STATUS_INITIALIZED); - /* set some required options */ - flags |= CLIENT_MULTI_RESULTS; /* needed for mysql_multi_query() */ /* remove some insecure options */ flags &= ~CLIENT_MULTI_STATEMENTS; /* don't allow multi_queries via connect parameter */ } + flags |= CLIENT_MULTI_RESULTS; /* needed for mysql_multi_query() */ if (!socket_len || !socket) { socket = MyG(default_socket); @@ -316,7 +314,7 @@ void mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS, bool is_real_connect, b mysql->hash_key = NULL; mysql->persistent = false; } - if (!is_real_connect && self_alloced) { + if (self_alloced) { efree(mysql); } RETVAL_FALSE; @@ -393,7 +391,7 @@ PHP_FUNCTION(mysqli_fetch_column) if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|l", &mysql_result, mysqli_result_class_entry, &col_no) == FAILURE) { RETURN_THROWS(); } - MYSQLI_FETCH_RESOURCE(result, MYSQL_RES*, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); + MYSQLI_FETCH_RESOURCE(result, MYSQL_RES*, mysql_result, MYSQLI_STATUS_VALID); if (col_no < 0) { zend_argument_value_error(ERROR_ARG_POS(2), "must be greater than or equal to 0"); @@ -425,7 +423,7 @@ PHP_FUNCTION(mysqli_fetch_all) if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|l", &mysql_result, mysqli_result_class_entry, &mode) == FAILURE) { RETURN_THROWS(); } - MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); + MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, MYSQLI_STATUS_VALID); if (!mode || (mode & ~MYSQLI_BOTH)) { zend_argument_value_error(ERROR_ARG_POS(2), "must be one of MYSQLI_NUM, MYSQLI_ASSOC, or MYSQLI_BOTH"); @@ -1031,6 +1029,7 @@ PHP_FUNCTION(mysqli_begin_transaction) } if (FAIL == mysqlnd_begin_transaction(mysql->mysql, flags, name)) { + MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql); RETURN_FALSE; } RETURN_TRUE; @@ -1055,6 +1054,7 @@ PHP_FUNCTION(mysqli_savepoint) } if (FAIL == mysqlnd_savepoint(mysql->mysql, name)) { + MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql); RETURN_FALSE; } RETURN_TRUE; @@ -1078,6 +1078,7 @@ PHP_FUNCTION(mysqli_release_savepoint) RETURN_THROWS(); } if (FAIL == mysqlnd_release_savepoint(mysql->mysql, name)) { + MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql); RETURN_FALSE; } RETURN_TRUE; diff --git a/ext/mysqli/mysqli_priv.h b/ext/mysqli/mysqli_priv.h index f08d66b7287d9..5f7c49f0b2979 100644 --- a/ext/mysqli/mysqli_priv.h +++ b/ext/mysqli/mysqli_priv.h @@ -55,7 +55,6 @@ extern void php_clear_mysql(MY_MYSQL *); extern MYSQLI_WARNING *php_get_warnings(MYSQLND_CONN_DATA * mysql); extern void php_clear_warnings(MYSQLI_WARNING *w); -extern void php_free_stmt_bind_buffer(BIND_BUFFER bbuf, int type); extern void php_mysqli_report_error(const char *sqlstate, int errorno, const char *error); extern void php_mysqli_report_index(const char *query, unsigned int status); extern void php_mysqli_throw_sql_exception(char *sqlstate, int errorno, char *format, ...); diff --git a/ext/mysqli/mysqli_result_iterator.c b/ext/mysqli/mysqli_result_iterator.c index 3441e47d01a4c..5dbeaf1e3b22b 100644 --- a/ext/mysqli/mysqli_result_iterator.c +++ b/ext/mysqli/mysqli_result_iterator.c @@ -98,7 +98,7 @@ static void php_mysqli_result_iterator_move_forward(zend_object_iterator *iter) mysqli_object *intern = iterator->result; MYSQL_RES *result; - MYSQLI_FETCH_RESOURCE_BY_OBJ(result, MYSQL_RES *, intern, "mysqli_result", MYSQLI_STATUS_VALID); + MYSQLI_FETCH_RESOURCE_BY_OBJ(result, MYSQL_RES *, intern, MYSQLI_STATUS_VALID); zval_ptr_dtor(&iterator->current_row); php_mysqli_fetch_into_hash_aux(&iterator->current_row, result, MYSQLI_ASSOC); @@ -115,7 +115,7 @@ static void php_mysqli_result_iterator_rewind(zend_object_iterator *iter) mysqli_object *intern = iterator->result; MYSQL_RES *result; - MYSQLI_FETCH_RESOURCE_BY_OBJ(result, MYSQL_RES *, intern, "mysqli_result", MYSQLI_STATUS_VALID); + MYSQLI_FETCH_RESOURCE_BY_OBJ(result, MYSQL_RES *, intern, MYSQLI_STATUS_VALID); if (mysqli_result_is_unbuffered(result)) { if (result->unbuf->eof_reached) { diff --git a/ext/mysqli/mysqli_warning.c b/ext/mysqli/mysqli_warning.c index b1427495a5066..4b0792b9684b8 100644 --- a/ext/mysqli/mysqli_warning.c +++ b/ext/mysqli/mysqli_warning.c @@ -125,7 +125,7 @@ PHP_METHOD(mysqli_warning, next) } if (obj->ptr) { - MYSQLI_FETCH_RESOURCE(w, MYSQLI_WARNING *, ZEND_THIS, "mysqli_warning", MYSQLI_STATUS_VALID); + MYSQLI_FETCH_RESOURCE(w, MYSQLI_WARNING *, ZEND_THIS, MYSQLI_STATUS_VALID); if (w && w->next) { w = w->next; diff --git a/ext/mysqli/php_mysqli_structs.h b/ext/mysqli/php_mysqli_structs.h index c155281c8e4bc..ceab4a44f3953 100644 --- a/ext/mysqli/php_mysqli_structs.h +++ b/ext/mysqli/php_mysqli_structs.h @@ -38,32 +38,14 @@ enum mysqli_status { MYSQLI_STATUS_VALID }; -typedef struct { - char *val; - zend_ulong buflen; - zend_ulong output_len; - zend_ulong type; -} VAR_BUFFER; - -typedef struct { - unsigned int var_cnt; - VAR_BUFFER *buf; - zval *vars; - my_bool *is_null; -} BIND_BUFFER; - typedef struct { MYSQL_STMT *stmt; - BIND_BUFFER param; - BIND_BUFFER result; char *query; } MY_STMT; typedef struct { MYSQL *mysql; zend_string *hash_key; - zval li_read; - php_stream *li_stream; unsigned int multi_query; bool persistent; int async_result_fetch_type; @@ -177,7 +159,7 @@ extern void php_mysqli_fetch_into_hash_aux(zval *return_value, MYSQL_RES * resul MYSQLI_REGISTER_RESOURCE_EX(__ptr, object)\ } -#define MYSQLI_FETCH_RESOURCE(__ptr, __type, __id, __name, __check) \ +#define MYSQLI_FETCH_RESOURCE(__ptr, __type, __id, __check) \ { \ MYSQLI_RESOURCE *my_res; \ mysqli_object *intern = Z_MYSQLI_P(__id); \ @@ -192,7 +174,7 @@ extern void php_mysqli_fetch_into_hash_aux(zval *return_value, MYSQL_RES * resul }\ } -#define MYSQLI_FETCH_RESOURCE_BY_OBJ(__ptr, __type, __obj, __name, __check) \ +#define MYSQLI_FETCH_RESOURCE_BY_OBJ(__ptr, __type, __obj, __check) \ { \ MYSQLI_RESOURCE *my_res; \ if (!(my_res = (MYSQLI_RESOURCE *)(__obj->ptr))) {\ @@ -208,7 +190,7 @@ extern void php_mysqli_fetch_into_hash_aux(zval *return_value, MYSQL_RES * resul #define MYSQLI_FETCH_RESOURCE_CONN(__ptr, __id, __check) \ { \ - MYSQLI_FETCH_RESOURCE((__ptr), MY_MYSQL *, (__id), "mysqli_link", (__check)); \ + MYSQLI_FETCH_RESOURCE((__ptr), MY_MYSQL *, (__id), (__check)); \ if (!(__ptr)->mysql) { \ zend_throw_error(NULL, "%s object is not fully initialized", ZSTR_VAL(Z_OBJCE_P(__id)->name)); \ RETURN_THROWS(); \ @@ -217,7 +199,7 @@ extern void php_mysqli_fetch_into_hash_aux(zval *return_value, MYSQL_RES * resul #define MYSQLI_FETCH_RESOURCE_STMT(__ptr, __id, __check) \ { \ - MYSQLI_FETCH_RESOURCE((__ptr), MY_STMT *, (__id), "mysqli_stmt", (__check)); \ + MYSQLI_FETCH_RESOURCE((__ptr), MY_STMT *, (__id), (__check)); \ ZEND_ASSERT((__ptr)->stmt && "Missing statement?"); \ } @@ -236,21 +218,21 @@ extern void php_mysqli_fetch_into_hash_aux(zval *return_value, MYSQL_RES * resul ZEND_BEGIN_MODULE_GLOBALS(mysqli) - zend_long num_links; - zend_long max_links; - zend_long num_active_persistent; - zend_long num_inactive_persistent; - zend_long max_persistent; + unsigned short default_port; bool allow_persistent; - zend_ulong default_port; + bool allow_local_infile; char *default_host; char *default_user; char *default_pw; char *default_socket; - bool allow_local_infile; char *local_infile_directory; - zend_long error_no; char *error_msg; + zend_long num_links; + zend_long max_links; + zend_long num_active_persistent; + zend_long num_inactive_persistent; + zend_long max_persistent; + zend_long error_no; zend_long report_mode; bool rollback_on_cached_plink; ZEND_END_MODULE_GLOBALS(mysqli) diff --git a/ext/mysqli/tests/bug67563.phpt b/ext/mysqli/tests/bug67563.phpt new file mode 100644 index 0000000000000..275d79e30c795 --- /dev/null +++ b/ext/mysqli/tests/bug67563.phpt @@ -0,0 +1,37 @@ +--TEST-- +Fix bug #67563 (mysqli compiled with mysqlnd does not take ipv6 adress as parameter) +--EXTENSIONS-- +mysqli +--SKIPIF-- + +--INI-- +max_execution_time=240 +--FILE-- +close(); + } +} + +print "done!"; +?> +--EXPECT-- +done! 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/fetch/mysqli_fetch_all_data_types_variation.phpt b/ext/mysqli/tests/fetch/mysqli_fetch_all_data_types_variation.phpt index 594980ec0f829..81c15d53b84cb 100644 --- a/ext/mysqli/tests/fetch/mysqli_fetch_all_data_types_variation.phpt +++ b/ext/mysqli/tests/fetch/mysqli_fetch_all_data_types_variation.phpt @@ -4,6 +4,9 @@ mysqli_fetch_all() data types variation mysqli --SKIPIF-- diff --git a/ext/mysqli/tests/mysqli_begin_transaction_error.phpt b/ext/mysqli/tests/mysqli_begin_transaction_error.phpt new file mode 100644 index 0000000000000..e4d63f366e86b --- /dev/null +++ b/ext/mysqli/tests/mysqli_begin_transaction_error.phpt @@ -0,0 +1,42 @@ +--TEST-- +mysqli_begin_transaction() +--EXTENSIONS-- +mysqli +--SKIPIF-- +errno, $link->error)); +?> +--FILE-- + +--CLEAN-- + +--EXPECT-- +Expecting an exception. +done! diff --git a/ext/mysqli/tests/mysqli_connect_port.phpt b/ext/mysqli/tests/mysqli_connect_port.phpt new file mode 100644 index 0000000000000..cb7fd1d8d1628 --- /dev/null +++ b/ext/mysqli/tests/mysqli_connect_port.phpt @@ -0,0 +1,31 @@ +--TEST-- +mysqli_connect() with port in host +--EXTENSIONS-- +mysqli +--SKIPIF-- + +--FILE-- + +Done +--EXPECTF-- +Done diff --git a/ext/mysqli/tests/mysqli_default_port_error.phpt b/ext/mysqli/tests/mysqli_default_port_error.phpt new file mode 100644 index 0000000000000..7d3658417c96c --- /dev/null +++ b/ext/mysqli/tests/mysqli_default_port_error.phpt @@ -0,0 +1,21 @@ +--TEST-- +default_port ini setting +--EXTENSIONS-- +mysqli +--FILE-- + +--EXPECT-- +bool(true) +bool(true) +bool(false) diff --git a/ext/mysqli/tests/mysqli_fetch_field_types.phpt b/ext/mysqli/tests/mysqli_fetch_field_types.phpt index feb72cabf7a6c..80e5cda06e93a 100644 --- a/ext/mysqli/tests/mysqli_fetch_field_types.phpt +++ b/ext/mysqli/tests/mysqli_fetch_field_types.phpt @@ -90,6 +90,7 @@ require_once 'skipifconnectfailure.inc'; // MYSQLI_TYPE_GEOMETRY => array('GEOMETRY', 'TODO add testing'), MYSQLI_TYPE_NEWDECIMAL => array('DECIMAL', '1.1'), MYSQLI_TYPE_BIT => array('BIT', 0), + MYSQLI_TYPE_JSON => array('JSON', '[]'), ); foreach ($datatypes as $php_type => $datatype) { diff --git a/ext/mysqli/tests/mysqli_stmt_execute_bind.phpt b/ext/mysqli/tests/mysqli_stmt_execute_bind.phpt index 5005cbf5fb5d9..82d4be4ea18d3 100644 --- a/ext/mysqli/tests/mysqli_stmt_execute_bind.phpt +++ b/ext/mysqli/tests/mysqli_stmt_execute_bind.phpt @@ -118,7 +118,7 @@ $stmt = null; // 12. Only list arrays are allowed $stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?'); try { - $stmt->execute(['A'=>'abc', 2=>42, null=>$id]); + $stmt->execute(['A'=>'abc', 2=>42, ''=>$id]); } catch (ValueError $e) { echo '[008] '.$e->getMessage()."\n"; } diff --git a/ext/mysqlnd/mysqlnd_connection.c b/ext/mysqlnd/mysqlnd_connection.c index 42acb258665bc..9065aaf579df5 100644 --- a/ext/mysqlnd/mysqlnd_connection.c +++ b/ext/mysqlnd/mysqlnd_connection.c @@ -508,6 +508,16 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect_handshake)(MYSQLND_CONN_DATA * conn, } /* }}} */ +/* ipv6 addresses have at least two colons, which is how we can differentiate between domain names and addresses */ +static bool mysqlnd_fast_is_ipv6_address(const char *s) +{ + const char *first_colon = strchr(s, ':'); + if (!first_colon) { + return false; + } + return strchr(first_colon + 1, ':') != NULL; +} + /* {{{ mysqlnd_conn_data::get_scheme */ static MYSQLND_STRING MYSQLND_METHOD(mysqlnd_conn_data, get_scheme)(MYSQLND_CONN_DATA * conn, MYSQLND_CSTRING hostname, MYSQLND_CSTRING *socket_or_pipe, unsigned int port, bool * unix_socket, bool * named_pipe) @@ -537,7 +547,31 @@ MYSQLND_METHOD(mysqlnd_conn_data, get_scheme)(MYSQLND_CONN_DATA * conn, MYSQLND_ if (!port) { port = 3306; } - transport.l = mnd_sprintf(&transport.s, 0, "tcp://%s:%u", hostname.s, port); + + if (hostname.s[0] != '[' && mysqlnd_fast_is_ipv6_address(hostname.s)) { + /* IPv6 without square brackets so without port */ + transport.l = mnd_sprintf(&transport.s, 0, "tcp://[%s]:%u", hostname.s, port); + } else { + char *p; + + /* IPv6 addresses are in the format [address]:port */ + if (hostname.s[0] == '[') { /* IPv6 */ + p = strchr(hostname.s, ']'); + if (p && p[1] != ':') { + p = NULL; + } + } else { /* IPv4 or name */ + p = strchr(hostname.s, ':'); + } + /* Could already contain a port number, in which case we should not add an extra port. + * See GH-8978. In a port doubling scenario, the first port would be used so we do the same to keep BC. */ + if (p) { + /* TODO: Ideally we should be able to get rid of this workaround in the future. */ + transport.l = mnd_sprintf(&transport.s, 0, "tcp://%s", hostname.s); + } else { + transport.l = mnd_sprintf(&transport.s, 0, "tcp://%s:%u", hostname.s, port); + } + } } DBG_INF_FMT("transport=%s", transport.s? transport.s:"OOM"); DBG_RETURN(transport); 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_ps.c b/ext/mysqlnd/mysqlnd_ps.c index 5fad5281947ea..76a2eb640d1de 100644 --- a/ext/mysqlnd/mysqlnd_ps.c +++ b/ext/mysqlnd/mysqlnd_ps.c @@ -58,7 +58,7 @@ static bool mysqlnd_stmt_check_state(const MYSQLND_STMT_DATA *stmt) { const MYSQLND_CONN_DATA *conn = stmt->conn; if (stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE) { - return 0; + return false; } if (stmt->cursor_exists) { return GET_CONNECTION_STATE(&conn->state) == CONN_READY; diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index a2e98cf358bb4..c60e3d327a8d7 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -317,7 +317,7 @@ ps_fetch_date(zval * zv, const MYSQLND_FIELD * const field, const unsigned int p const zend_uchar * to = *row; t.time_type = MYSQLND_TIMESTAMP_DATE; - t.neg = 0; + t.neg = false; t.second_part = t.hour = t.minute = t.second = 0; @@ -354,7 +354,7 @@ ps_fetch_datetime(zval * zv, const MYSQLND_FIELD * const field, const unsigned i const zend_uchar * to = *row; t.time_type = MYSQLND_TIMESTAMP_DATETIME; - t.neg = 0; + t.neg = false; t.year = (unsigned int) sint2korr(to); t.month = (unsigned int) to[2]; 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 ddb6b35ab1af2..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,7 +390,6 @@ 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); diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c index 7bc3a8bc17d05..a6af7469cbac3 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,12 +1306,14 @@ PHP_FUNCTION(odbc_exec) } /* }}} */ -#ifdef PHP_ODBC_HAVE_FETCH_HASH -#define ODBC_NUM 1 -#define ODBC_OBJECT 2 +typedef enum php_odbc_fetch_result_type_t { + ODBC_NONE = 0, + ODBC_NUM = 1, + ODBC_OBJECT = 2, +} php_odbc_fetch_result_type_t; -/* {{{ php_odbc_fetch_hash */ -static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type) +/* {{{ php_odbc_fetch */ +static void php_odbc_fetch(INTERNAL_FUNCTION_PARAMETERS, bool return_array, php_odbc_fetch_result_type_t result_type) { int i; odbc_result *result; @@ -1372,63 +1322,85 @@ static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type) char *buf = NULL; 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 + zval *pv_res, *pv_res_arr, tmp; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|l!", &pv_res, odbc_result_ce, &pv_row, &pv_row_is_null) == FAILURE) { - RETURN_THROWS(); + if (return_array || result_type == ODBC_NONE) { + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_OBJECT_OF_CLASS(pv_res, odbc_result_ce) + Z_PARAM_OPTIONAL + Z_PARAM_LONG_OR_NULL(pv_row, pv_row_is_null) + ZEND_PARSE_PARAMETERS_END(); + /* So we can use pv_res_arr for both return value and passed */ + pv_res_arr = return_value; + } else { + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_OBJECT_OF_CLASS(pv_res, odbc_result_ce) + Z_PARAM_ZVAL(pv_res_arr) + Z_PARAM_OPTIONAL + Z_PARAM_LONG_OR_NULL(pv_row, pv_row_is_null) + ZEND_PARSE_PARAMETERS_END(); } result = Z_ODBC_RESULT_P(pv_res); CHECK_ODBC_RESULT(result); - /* 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"); + /* TODO deprecate $row argument values less than 1 after PHP 8.4 + * for functions other than odbc_fetch_row (see GH-13910) + */ + if (!result_type && !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 we're initializing a passed value into an array, do it before the fetch + * so that an empty result set will still be an array. + */ + if (!return_array && result_type) { + pv_res_arr = zend_try_array_init(pv_res_arr); + if (!pv_res_arr) { + RETURN_THROWS(); + } + } + if (result->fetch_abs) { if (!pv_row_is_null && pv_row > 0) { - rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,(SQLLEN)pv_row,&crow,RowStatus); + rc = SQLFetchScroll(result->stmt, SQL_FETCH_ABSOLUTE, (SQLLEN)pv_row); } else { - rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus); + rc = SQLFetchScroll(result->stmt, SQL_FETCH_NEXT, 1); } - } 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 + odbc_sql_error(result->conn_ptr, result->stmt, "SQLFetchScroll"); } RETURN_FALSE; } - array_init(return_value); + /* ...but if returning an array, init only if we have a result set */ + if (return_array && result_type) { + array_init(pv_res_arr); + } -#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 fetch_row, we don't return anything other than true, + * odbc_result will be used to fetch values instead. + */ + if (result_type == ODBC_NONE) { + RETURN_TRUE; + } + for(i = 0; i < result->numcols; i++) { sql_c_type = SQL_C_CHAR; @@ -1443,11 +1415,11 @@ static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type) if (result->binmode == 1) { sql_c_type = SQL_C_BINARY; } + + /* 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; @@ -1461,7 +1433,9 @@ static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type) if (rc == SQL_ERROR) { odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData"); efree(buf); - zval_ptr_dtor(return_value); + if (return_array) { + zval_ptr_dtor(pv_res_arr); + } RETURN_FALSE; } @@ -1495,18 +1469,23 @@ static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type) } if (result_type & ODBC_NUM) { - zend_hash_index_update(Z_ARRVAL_P(return_value), i, &tmp); + zend_hash_index_update(Z_ARRVAL_P(pv_res_arr), i, &tmp); } else { if (!*(result->values[i].name) && Z_TYPE(tmp) == IS_STRING) { - zend_hash_update(Z_ARRVAL_P(return_value), Z_STR(tmp), &tmp); + zend_hash_update(Z_ARRVAL_P(pv_res_arr), Z_STR(tmp), &tmp); } else { - zend_hash_str_update(Z_ARRVAL_P(return_value), result->values[i].name, strlen(result->values[i].name), &tmp); + zend_hash_str_update(Z_ARRVAL_P(pv_res_arr), result->values[i].name, strlen(result->values[i].name), &tmp); } } } if (buf) { efree(buf); } + + /* return_value was set to an array otherwise */ + if (!return_array) { + RETURN_LONG(result->numcols); + } } /* }}} */ @@ -1514,7 +1493,7 @@ static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type) /* {{{ Fetch a result row as an object */ PHP_FUNCTION(odbc_fetch_object) { - php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, ODBC_OBJECT); + php_odbc_fetch(INTERNAL_FUNCTION_PARAM_PASSTHRU, true, ODBC_OBJECT); if (Z_TYPE_P(return_value) == IS_ARRAY) { object_and_properties_init(return_value, ZEND_STANDARD_CLASS_DEF_PTR, Z_ARRVAL_P(return_value)); } @@ -1524,216 +1503,21 @@ PHP_FUNCTION(odbc_fetch_object) /* {{{ Fetch a result row as an associative array */ PHP_FUNCTION(odbc_fetch_array) { - php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, ODBC_OBJECT); + php_odbc_fetch(INTERNAL_FUNCTION_PARAM_PASSTHRU, true, ODBC_OBJECT); } /* }}} */ -#endif /* {{{ Fetch one result row into an array */ PHP_FUNCTION(odbc_fetch_into) { - int i; - odbc_result *result; - RETCODE rc; - SQLSMALLINT sql_c_type; - char *buf = NULL; - 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(); - } - - result = Z_ODBC_RESULT_P(pv_res); - CHECK_ODBC_RESULT(result); - - /* 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; - } - - pv_res_arr = zend_try_array_init(pv_res_arr); - if (!pv_res_arr) { - 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 - 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++) { - sql_c_type = SQL_C_CHAR; - - switch(result->values[i].coltype) { - case SQL_BINARY: - case SQL_VARBINARY: - case SQL_LONGVARBINARY: - if (result->binmode <= 0) { - ZVAL_EMPTY_STRING(&tmp); - break; - } - if (result->binmode == 1) sql_c_type = SQL_C_BINARY; - - /* 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; - } - - if (buf == NULL) { - buf = emalloc(result->longreadlen + 1); - } - rc = SQLGetData(result->stmt, (SQLUSMALLINT)(i + 1),sql_c_type, buf, result->longreadlen + 1, &result->values[i].vallen); - - if (rc == SQL_ERROR) { - odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData"); - efree(buf); - RETURN_FALSE; - } - if (rc == SQL_SUCCESS_WITH_INFO) { - ZVAL_STRINGL(&tmp, buf, result->longreadlen); - } else if (rc != SQL_SUCCESS) { - php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (retcode %u)", i + 1, rc); - ZVAL_FALSE(&tmp); - } else if (result->values[i].vallen == SQL_NULL_DATA) { - ZVAL_NULL(&tmp); - break; - } else if (result->values[i].vallen == SQL_NO_TOTAL) { - php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (driver cannot determine length)", i + 1); - ZVAL_FALSE(&tmp); - } else { - ZVAL_STRINGL(&tmp, buf, result->values[i].vallen); - } - break; - - default: - if (result->values[i].vallen == SQL_NULL_DATA) { - ZVAL_NULL(&tmp); - break; - } else if (result->values[i].vallen == SQL_NO_TOTAL) { - php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (driver cannot determine length)", i + 1); - ZVAL_FALSE(&tmp); - break; - } - ZVAL_STRINGL(&tmp, result->values[i].value, result->values[i].vallen); - break; - } - zend_hash_index_update(Z_ARRVAL_P(pv_res_arr), i, &tmp); - } - if (buf) efree(buf); - RETURN_LONG(result->numcols); + php_odbc_fetch(INTERNAL_FUNCTION_PARAM_PASSTHRU, false, ODBC_NUM); } /* }}} */ /* {{{ Fetch a row */ PHP_FUNCTION(odbc_fetch_row) { - odbc_result *result; - RETCODE rc; - 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(); - } - - 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 - 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 - result->fetched++; - - RETURN_TRUE; + php_odbc_fetch(INTERNAL_FUNCTION_PARAM_PASSTHRU, false, ODBC_NONE); } /* }}} */ @@ -1750,10 +1534,6 @@ 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 +1584,15 @@ 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 + if (result->fetch_abs) { + rc = SQLFetchScroll(result->stmt, SQL_FETCH_NEXT, 1); + } 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 + odbc_sql_error(result->conn_ptr, result->stmt, "SQLFetchScroll"); } RETURN_FALSE; } @@ -1839,9 +1614,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 +1622,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 +1658,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 +1735,6 @@ 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,12 +1747,11 @@ 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 + if (result->fetch_abs) { + rc = SQLFetchScroll(result->stmt, SQL_FETCH_NEXT, 1); + } else { rc = SQLFetch(result->stmt); + } if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { php_printf("

No rows found

\n"); @@ -2024,9 +1789,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,12 +1846,11 @@ 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 + if (result->fetch_abs) { + rc = SQLFetchScroll(result->stmt, SQL_FETCH_NEXT, 1); + } else { rc = SQLFetch(result->stmt); + } } php_printf("\n"); if (buf) efree(buf); @@ -2157,20 +1919,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 +1928,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 +1995,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 +2013,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 +2218,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 +2264,6 @@ PHP_FUNCTION(odbc_next_result) } } /* }}} */ -#endif /* {{{ Get number of columns in a result */ PHP_FUNCTION(odbc_num_fields) @@ -2602,7 +2346,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); } /* }}} */ @@ -2661,7 +2405,7 @@ PHP_FUNCTION(odbc_autocommit) { RETCODE rc; zval *pv_conn; - bool pv_onoff = 0; + bool pv_onoff = false; bool pv_onoff_is_null = true; if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|b!", &pv_conn, odbc_connection_ce, &pv_onoff, &pv_onoff_is_null) == FAILURE) { @@ -2672,7 +2416,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 +2425,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 +2527,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 +2541,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 +2581,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 +2646,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 +2693,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 +2713,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 +2752,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 +2767,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 +2785,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 +2826,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 +2848,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 +2903,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 +2942,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 +2962,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 +3001,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 +3021,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 +3059,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 +3086,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 +3152,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 +3193,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 +3212,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 +3250,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..7acb14b778f8d 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" @@ -88,7 +89,6 @@ typedef int gid_t; #ifndef ZEND_WIN32 # include # include -# include # include # include #endif @@ -102,15 +102,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 */ @@ -665,8 +663,7 @@ static void accel_copy_permanent_strings(zend_new_interned_string_func_t new_int if (Z_FUNC(p->val)->common.function_name) { Z_FUNC(p->val)->common.function_name = new_interned_string(Z_FUNC(p->val)->common.function_name); } - if (Z_FUNC(p->val)->common.arg_info && - (Z_FUNC(p->val)->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS))) { + if (Z_FUNC(p->val)->common.arg_info) { uint32_t i; uint32_t num_args = Z_FUNC(p->val)->common.num_args + 1; zend_arg_info *arg_info = Z_FUNC(p->val)->common.arg_info - 1; @@ -675,6 +672,12 @@ static void accel_copy_permanent_strings(zend_new_interned_string_func_t new_int num_args++; } for (i = 0 ; i < num_args; i++) { + if (i > 0) { + arg_info[i].name = new_interned_string(arg_info[i].name); + if (arg_info[i].default_value) { + arg_info[i].default_value = new_interned_string(arg_info[i].default_value); + } + } accel_copy_permanent_list_types(new_interned_string, arg_info[i].type); } } @@ -716,6 +719,24 @@ static void accel_copy_permanent_strings(zend_new_interned_string_func_t new_int if (Z_FUNC(q->val)->common.function_name) { Z_FUNC(q->val)->common.function_name = new_interned_string(Z_FUNC(q->val)->common.function_name); } + if (Z_FUNC(q->val)->common.scope == ce) { + uint32_t i; + uint32_t num_args = Z_FUNC(q->val)->common.num_args + 1; + zend_arg_info *arg_info = Z_FUNC(q->val)->common.arg_info - 1; + + if (Z_FUNC(q->val)->common.fn_flags & ZEND_ACC_VARIADIC) { + num_args++; + } + for (i = 0 ; i < num_args; i++) { + if (i > 0) { + arg_info[i].name = new_interned_string(arg_info[i].name); + if (arg_info[i].default_value) { + arg_info[i].default_value = new_interned_string(arg_info[i].default_value); + } + } + accel_copy_permanent_list_types(new_interned_string, arg_info[i].type); + } + } } ZEND_HASH_FOREACH_END(); ZEND_HASH_MAP_FOREACH_BUCKET(&ce->constants_table, q) { @@ -1736,19 +1757,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 +1829,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 +1858,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 +1878,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 +1959,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 +1968,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 +2185,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 +2198,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 +2215,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 +2230,16 @@ 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(); + + /* We may have switched to an existing persistent script that was persisted in + * the meantime. Make sure to use its warnings if available. */ + if (ZCG(accel_directives).record_warnings) { + EG(record_errors) = false; + zend_emit_recorded_errors_ex(persistent_script->num_warnings, persistent_script->warnings); + } else { + zend_emit_recorded_errors(); + } + zend_free_recorded_errors(); } else { #ifndef ZEND_WIN32 @@ -2248,7 +2282,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 +2349,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 +2503,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 +2871,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 +2973,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 +3003,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 +3071,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 +3188,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 +3211,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 +3230,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 +3301,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 +3542,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 +4233,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(); } @@ -4336,12 +4389,14 @@ static void preload_fix_trait_op_array(zend_op_array *op_array) zend_string *function_name = op_array->function_name; zend_class_entry *scope = op_array->scope; uint32_t fn_flags = op_array->fn_flags; + uint32_t fn_flags2 = op_array->fn_flags2; zend_function *prototype = op_array->prototype; HashTable *ht = op_array->static_variables; *op_array = *orig_op_array; op_array->function_name = function_name; op_array->scope = scope; op_array->fn_flags = fn_flags; + op_array->fn_flags2 = fn_flags2; op_array->prototype = prototype; op_array->static_variables = ht; } @@ -4491,16 +4546,6 @@ static void preload_load(size_t orig_map_ptr_static_last) } } - if (EG(zend_constants)) { - EG(persistent_constants_count) = EG(zend_constants)->nNumUsed; - } - if (EG(function_table)) { - EG(persistent_functions_count) = EG(function_table)->nNumUsed; - } - if (EG(class_table)) { - EG(persistent_classes_count) = EG(class_table)->nNumUsed; - } - size_t old_map_ptr_last = CG(map_ptr_last); if (zend_map_ptr_static_last != ZCSG(map_ptr_static_last) || old_map_ptr_last != ZCSG(map_ptr_last)) { CG(map_ptr_last) = ZCSG(map_ptr_last); @@ -4770,6 +4815,12 @@ static zend_result accel_preload(const char *config, bool in_child) preload_load(orig_map_ptr_static_last); + /* Update persistent counts, as shutdown will discard anything past + * that, and these tables are aliases to global ones at this point. */ + EG(persistent_functions_count) = EG(function_table)->nNumUsed; + EG(persistent_classes_count) = EG(class_table)->nNumUsed; + EG(persistent_constants_count) = EG(zend_constants)->nNumUsed; + /* Store individual scripts with unlinked classes */ HANDLE_BLOCK_INTERRUPTIONS(); SHM_UNPROTECT(); @@ -4858,6 +4909,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 +4992,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 +5060,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; @@ -5056,13 +5112,45 @@ static zend_result accel_finish_startup(void) exit(ret == SUCCESS ? 0 : 1); } else { /* parent */ - int status; +# ifdef HAVE_SIGPROCMASK + /* Interrupting the waitpid() call below with a signal would cause the + * process to exit. This is fine when the signal disposition is set to + * terminate the process, but not otherwise. + * When running the apache2handler, preloading is performed in the + * control process. SIGUSR1 and SIGHUP are used to tell the control + * process to restart children. Exiting when these signals are received + * would unexpectedly shutdown the server instead of restarting it. + * Block the USR1 and HUP signals from being delivered during the + * syscall when running the apache2handler SAPI, as these are not + * supposed to terminate the process. See GH-20051. */ + bool is_apache2handler = strcmp(sapi_module.name, "apache2handler") == 0; + sigset_t set, oldset; + if (is_apache2handler) { + if (sigemptyset(&set) + || sigaddset(&set, SIGUSR1) + || sigaddset(&set, SIGHUP)) { + ZEND_UNREACHABLE(); + } + if (sigprocmask(SIG_BLOCK, &set, &oldset)) { + ZEND_UNREACHABLE(); + } + } +# endif + int status; if (waitpid(pid, &status, 0) < 0) { zend_shared_alloc_unlock(); zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Preloading failed to waitpid(%d)", pid); } +# ifdef HAVE_SIGPROCMASK + if (is_apache2handler) { + if (sigprocmask(SIG_SETMASK, &oldset, NULL)) { + ZEND_UNREACHABLE(); + } + } +# endif + if (ZCSG(preload_script)) { preload_load(zend_map_ptr_static_last); } @@ -5084,7 +5172,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/LICENSE b/ext/opcache/jit/ir/LICENSE index c43a12a770f8f..340f9c37225f6 100644 --- a/ext/opcache/jit/ir/LICENSE +++ b/ext/opcache/jit/ir/LICENSE @@ -1,6 +1,7 @@ MIT License Copyright (c) 2022 Zend by Perforce +Copyright (c) 2025 Dmitry Stogov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/ext/opcache/jit/ir/ir.c b/ext/opcache/jit/ir/ir.c index a9f55cc0e466c..745a66b2163ae 100644 --- a/ext/opcache/jit/ir/ir.c +++ b/ext/opcache/jit/ir/ir.c @@ -118,7 +118,7 @@ void ir_print_const(const ir_ctx *ctx, const ir_insn *insn, FILE *f, bool quoted { char buf[128]; - if (insn->op == IR_FUNC || insn->op == IR_SYM) { + if (insn->op == IR_FUNC || insn->op == IR_SYM || insn->op == IR_LABEL) { fprintf(f, "%s", ir_get_str(ctx, insn->val.name)); return; } else if (insn->op == IR_STR) { @@ -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: @@ -227,6 +227,7 @@ void ir_print_const(const ir_ctx *ctx, const ir_insn *insn, FILE *f, bool quoted #define ir_op_flag_d0 ir_op_flag_d #define ir_op_flag_d1 (ir_op_flag_d | 1 | (1 << IR_OP_FLAG_OPERANDS_SHIFT)) #define ir_op_flag_d1X1 (ir_op_flag_d | 1 | (2 << IR_OP_FLAG_OPERANDS_SHIFT)) +#define ir_op_flag_d1X2 (ir_op_flag_d | 1 | (3 << IR_OP_FLAG_OPERANDS_SHIFT)) #define ir_op_flag_d2 (ir_op_flag_d | 2 | (2 << IR_OP_FLAG_OPERANDS_SHIFT)) #define ir_op_flag_d2C (ir_op_flag_d | IR_OP_FLAG_COMMUTATIVE | 2 | (2 << IR_OP_FLAG_OPERANDS_SHIFT)) #define ir_op_flag_d3 (ir_op_flag_d | 3 | (3 << IR_OP_FLAG_OPERANDS_SHIFT)) @@ -247,6 +248,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)) @@ -269,6 +271,7 @@ void ir_print_const(const ir_ctx *ctx, const ir_insn *insn, FILE *f, bool quoted #define ir_op_flag_s3 (ir_op_flag_s | 3 | (3 << IR_OP_FLAG_OPERANDS_SHIFT)) #define ir_op_flag_x1 (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_CALL | 1 | (1 << IR_OP_FLAG_OPERANDS_SHIFT)) #define ir_op_flag_x2 (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_CALL | 2 | (2 << IR_OP_FLAG_OPERANDS_SHIFT)) +#define ir_op_flag_x2X1 (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_CALL | 2 | (3 << IR_OP_FLAG_OPERANDS_SHIFT)) #define ir_op_flag_x3 (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_CALL | 3 | (3 << IR_OP_FLAG_OPERANDS_SHIFT)) #define ir_op_flag_xN (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_CALL | IR_OP_FLAG_VAR_INPUTS) #define ir_op_flag_a1 (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_ALLOC | 1 | (1 << IR_OP_FLAG_OPERANDS_SHIFT)) @@ -287,6 +290,7 @@ void ir_print_const(const ir_ctx *ctx, const ir_insn *insn, FILE *f, bool quoted #define ir_op_kind_prb IR_OPND_PROB #define ir_op_kind_opt IR_OPND_PROB #define ir_op_kind_pro IR_OPND_PROTO +#define ir_op_kind_lbl IR_OPND_LABEL_REF #define _IR_OP_FLAGS(name, flags, op1, op2, op3) \ IR_OP_FLAGS(ir_op_flag_ ## flags, ir_op_kind_ ## op1, ir_op_kind_ ## op2, ir_op_kind_ ## op3), @@ -391,6 +395,8 @@ void ir_init(ir_ctx *ctx, uint32_t flags, ir_ref consts_limit, ir_ref insns_limi ctx->insns_limit = insns_limit; ctx->consts_count = -(IR_TRUE - 1); ctx->consts_limit = consts_limit; + ctx->const_hash = ctx->_const_hash; + ctx->const_hash_mask = IR_CONST_HASH_SIZE - 1; ctx->fold_cse_limit = IR_UNUSED + 1; ctx->flags = flags; @@ -413,6 +419,9 @@ void ir_free(ir_ctx *ctx) { ir_insn *buf = ctx->ir_base - ctx->consts_limit; ir_mem_free(buf); + if (ctx->value_params) { + ir_mem_free(ctx->value_params); + } if (ctx->strtab.data) { ir_strtab_free(&ctx->strtab); } @@ -467,6 +476,10 @@ void ir_free(ir_ctx *ctx) ir_list_free((ir_list*)ctx->osr_entry_loads); ir_mem_free(ctx->osr_entry_loads); } + + if (ctx->const_hash_mask != IR_CONST_HASH_SIZE - 1) { + ir_mem_free(ctx->const_hash); + } } ir_ref ir_unique_const_addr(ir_ctx *ctx, uintptr_t addr) @@ -478,72 +491,64 @@ ir_ref ir_unique_const_addr(ir_ctx *ctx, uintptr_t addr) insn->val.u64 = addr; /* don't insert into constants chain */ insn->prev_const = IR_UNUSED; -#if 0 - insn->prev_const = ctx->prev_const_chain[IR_ADDR]; - ctx->prev_const_chain[IR_ADDR] = ref; -#endif -#if 0 - ir_insn *prev_insn, *next_insn; - ir_ref next; - - prev_insn = NULL; - next = ctx->prev_const_chain[IR_ADDR]; - while (next) { - next_insn = &ctx->ir_base[next]; - if (UNEXPECTED(next_insn->val.u64 >= addr)) { - break; - } - prev_insn = next_insn; - next = next_insn->prev_const; - } - - if (prev_insn) { - insn->prev_const = prev_insn->prev_const; - prev_insn->prev_const = ref; - } else { - insn->prev_const = ctx->prev_const_chain[IR_ADDR]; - ctx->prev_const_chain[IR_ADDR] = ref; - } -#endif return ref; } +IR_ALWAYS_INLINE uintptr_t ir_const_hash(ir_val val, uint32_t optx) +{ + return (val.u64 ^ (val.u64 >> 32) ^ optx); +} + +static IR_NEVER_INLINE void ir_const_hash_rehash(ir_ctx *ctx) +{ + ir_insn *insn; + ir_ref ref; + uintptr_t hash; + + if (ctx->const_hash_mask != IR_CONST_HASH_SIZE - 1) { + ir_mem_free(ctx->const_hash); + } + ctx->const_hash_mask = (ctx->const_hash_mask + 1) * 2 - 1; + ctx->const_hash = ir_mem_calloc(ctx->const_hash_mask + 1, sizeof(ir_ref)); + for (ref = IR_TRUE - 1; ref > -ctx->consts_count; ref--) { + insn = &ctx->ir_base[ref]; + hash = ir_const_hash(insn->val, insn->optx) & ctx->const_hash_mask; + insn->prev_const = ctx->const_hash[hash]; + ctx->const_hash[hash] = ref; + } +} + ir_ref ir_const_ex(ir_ctx *ctx, ir_val val, uint8_t type, uint32_t optx) { - ir_insn *insn, *prev_insn; + ir_insn *insn; ir_ref ref, prev; + uintptr_t hash; if (type == IR_BOOL) { return val.u64 ? IR_TRUE : IR_FALSE; } else if (type == IR_ADDR && val.u64 == 0) { return IR_NULL; } - prev_insn = NULL; - ref = ctx->prev_const_chain[type]; + + hash = ir_const_hash(val, optx) & ctx->const_hash_mask; + ref = ctx->const_hash[hash]; while (ref) { insn = &ctx->ir_base[ref]; - if (UNEXPECTED(insn->val.u64 >= val.u64)) { - if (insn->val.u64 == val.u64) { - if (insn->optx == optx) { - return ref; - } - } else { - break; - } + if (insn->val.u64 == val.u64 && insn->optx == optx) { + return ref; } - prev_insn = insn; ref = insn->prev_const; } - if (prev_insn) { - prev = prev_insn->prev_const; - prev_insn->prev_const = -ctx->consts_count; - } else { - prev = ctx->prev_const_chain[type]; - ctx->prev_const_chain[type] = -ctx->consts_count; + if ((uintptr_t)ctx->consts_count > ctx->const_hash_mask) { + ir_const_hash_rehash(ctx); + hash = ir_const_hash(val, optx) & ctx->const_hash_mask; } + prev = ctx->const_hash[hash]; + ctx->const_hash[hash] = -ctx->consts_count; + ref = ir_next_const(ctx); insn = &ctx->ir_base[ref]; insn->prev_const = prev; @@ -623,7 +628,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); } @@ -685,6 +690,13 @@ ir_ref ir_const_str(ir_ctx *ctx, ir_ref str) return ir_const_ex(ctx, val, IR_ADDR, IR_OPTX(IR_STR, IR_ADDR, 0)); } +ir_ref ir_const_label(ir_ctx *ctx, ir_ref str) +{ + ir_val val; + val.u64 = str; + return ir_const_ex(ctx, val, IR_ADDR, IR_OPTX(IR_LABEL, IR_ADDR, 0)); +} + ir_ref ir_str(ir_ctx *ctx, const char *s) { size_t len; @@ -803,7 +815,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); } @@ -873,6 +887,17 @@ static ir_ref _ir_fold_cse(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2, ir return IR_UNUSED; } +IR_ALWAYS_INLINE ir_ref _ir_fold_cast(ir_ctx *ctx, ir_ref ref, ir_type type) +{ + if (ctx->ir_base[ref].type == type) { + return ref; + } else if (IR_IS_CONST_REF(ref) && !IR_IS_SYM_CONST(ctx->ir_base[ref].op)) { + return ir_const(ctx, ctx->ir_base[ref].val, type); + } else { + return ir_emit1(ctx, IR_OPT(IR_BITCAST, type), ref); + } +} + #define IR_FOLD(X) IR_FOLD1(X, __LINE__) #define IR_FOLD1(X, Y) IR_FOLD2(X, Y) #define IR_FOLD2(X, Y) case IR_RULE_ ## Y: @@ -1080,7 +1105,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); } @@ -1152,7 +1177,7 @@ ir_ref ir_bind(ir_ctx *ctx, ir_ref var, ir_ref def) IR_ASSERT(var < 0); if (!ir_hashtab_add(ctx->binding, def, var)) { /* Add a copy with different binding */ - def = ir_emit2(ctx, IR_OPT(IR_COPY, ctx->ir_base[def].type), def, 1); + def = ir_emit2(ctx, IR_OPT(IR_COPY, ctx->ir_base[def].type), def, IR_COPY_HARD); ir_hashtab_add(ctx->binding, def, var); } return def; @@ -1830,8 +1855,49 @@ int ir_mem_flush(void *ptr, size_t size) return 1; } #else + +#if defined(__linux__) && defined(__x86_64__) && defined(PKEY_DISABLE_WRITE) +# define HAVE_PKEY_MPROTECT 1 +#endif + +#ifdef HAVE_PKEY_MPROTECT + +#ifndef PKEY_DISABLE_EXECUTE +# define PKEY_DISABLE_EXECUTE 0 +#endif + +int pkey_mprotect(void* addr, size_t len, int prot, int pkey) __attribute__((weak)); +int pkey_alloc(unsigned int, unsigned int) __attribute__((weak)); +int pkey_free(int) __attribute__((weak)); +int pkey_set(int, unsigned) __attribute__((weak)); + +static int ir_pkey = 0; +#endif + void *ir_mem_mmap(size_t size) { +#ifdef HAVE_PKEY_MPROTECT + if (!ir_pkey && pkey_mprotect) { + int key = pkey_alloc(0, PKEY_DISABLE_WRITE); + if (key > 0) { + ir_pkey = key; + } + } + if (ir_pkey > 0) { + void *ret = mmap(NULL, size, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (ret == MAP_FAILED) { + return NULL; + } + if (pkey_mprotect(ret, size, PROT_EXEC|PROT_READ|PROT_WRITE, ir_pkey) != 0) { +#ifdef IR_DEBUG + fprintf(stderr, "pkey_mprotect() failed\n"); +#endif + munmap(ret, size); + return NULL; + } + return ret; + } +#endif int prot_flags = PROT_EXEC; #if defined(__NetBSD__) prot_flags |= PROT_MPROTECT(PROT_READ|PROT_WRITE); @@ -1846,11 +1912,28 @@ void *ir_mem_mmap(size_t size) int ir_mem_unmap(void *ptr, size_t size) { munmap(ptr, size); +#ifdef HAVE_PKEY_MPROTECT +// if (ir_pkey > 0) { +// pkey_free(ir_pkey); +// ir_pkey = 0; +// } +#endif return 1; } int ir_mem_protect(void *ptr, size_t size) { +#ifdef HAVE_PKEY_MPROTECT + if (ir_pkey > 0) { + if (pkey_set(ir_pkey, PKEY_DISABLE_WRITE)) { +#ifdef IR_DEBUG + fprintf(stderr, "mprotect() failed\n"); +#endif + return 0; + } + return 1; + } +#endif if (mprotect(ptr, size, PROT_READ | PROT_EXEC) != 0) { #ifdef IR_DEBUG fprintf(stderr, "mprotect() failed\n"); @@ -1862,6 +1945,17 @@ int ir_mem_protect(void *ptr, size_t size) int ir_mem_unprotect(void *ptr, size_t size) { +#ifdef HAVE_PKEY_MPROTECT + if (ir_pkey > 0) { + if (pkey_set(ir_pkey, PKEY_DISABLE_EXECUTE)) { +#ifdef IR_DEBUG + fprintf(stderr, "mprotect() failed\n"); +#endif + return 0; + } + return 1; + } +#endif if (mprotect(ptr, size, PROT_READ | PROT_WRITE) != 0) { #ifdef IR_DEBUG fprintf(stderr, "mprotect() failed\n"); @@ -2064,7 +2158,26 @@ IR_ALWAYS_INLINE ir_ref ir_find_aliasing_load_i(ir_ctx *ctx, ir_ref ref, ir_type } } else if (insn->op == IR_RSTORE) { modified_regset |= (1 << insn->op3); - } else if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN || insn->op == IR_CALL || insn->op == IR_VSTORE) { + } else if (insn->op == IR_CALL) { + ir_insn *func = &ctx->ir_base[insn->op2]; + ir_ref func_proto; + const ir_proto_t *proto; + + if (func->op == IR_FUNC || func->op == IR_FUNC_ADDR) { + func_proto = func->proto; + } else if (func->op == IR_PROTO) { + func_proto = func->op2; + } else { + break; + } + if (!func_proto) { + break; + } + proto = (const ir_proto_t *)ir_get_str(ctx, func_proto); + if (!(proto->flags & (IR_CONST_FUNC|IR_PURE_FUNC))) { + break; + } + } else if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN || insn->op == IR_VSTORE) { return IR_UNUSED; } ref = insn->op1; @@ -2089,10 +2202,10 @@ IR_ALWAYS_INLINE ir_ref ir_find_aliasing_vload_i(ir_ctx *ctx, ir_ref ref, ir_typ if (insn->type == type) { return ref; /* load forwarding (L2L) */ } else if (ir_type_size[insn->type] == ir_type_size[type]) { - return ir_fold1(ctx, IR_OPT(IR_BITCAST, type), ref); /* load forwarding with bitcast (L2L) */ + return ref; /* load forwarding with bitcast (L2L) */ } else if (ir_type_size[insn->type] > ir_type_size[type] && IR_IS_TYPE_INT(type) && IR_IS_TYPE_INT(insn->type)) { - return ir_fold1(ctx, IR_OPT(IR_TRUNC, type), ref); /* partial load forwarding (L2L) */ + return ref; /* partial load forwarding (L2L) */ } } } else if (insn->op == IR_VSTORE) { @@ -2102,15 +2215,34 @@ IR_ALWAYS_INLINE ir_ref ir_find_aliasing_vload_i(ir_ctx *ctx, ir_ref ref, ir_typ if (type2 == type) { return insn->op3; /* store forwarding (S2L) */ } else if (ir_type_size[type2] == ir_type_size[type]) { - return ir_fold1(ctx, IR_OPT(IR_BITCAST, type), insn->op3); /* store forwarding with bitcast (S2L) */ + return insn->op3; /* store forwarding with bitcast (S2L) */ } else if (ir_type_size[type2] > ir_type_size[type] && IR_IS_TYPE_INT(type) && IR_IS_TYPE_INT(type2)) { - return ir_fold1(ctx, IR_OPT(IR_TRUNC, type), insn->op3); /* partial store forwarding (S2L) */ + return insn->op3; /* partial store forwarding (S2L) */ } else { break; } } - } else if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN || insn->op == IR_CALL || insn->op == IR_STORE) { + } else if (insn->op == IR_CALL) { + ir_insn *func = &ctx->ir_base[insn->op2]; + ir_ref func_proto; + const ir_proto_t *proto; + + if (func->op == IR_FUNC || func->op == IR_FUNC_ADDR) { + func_proto = func->proto; + } else if (func->op == IR_PROTO) { + func_proto = func->op2; + } else { + break; + } + if (!func_proto) { + break; + } + proto = (const ir_proto_t *)ir_get_str(ctx, func_proto); + if (!(proto->flags & (IR_CONST_FUNC|IR_PURE_FUNC))) { + break; + } + } else if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN || insn->op == IR_STORE) { break; } ref = insn->op1; @@ -2973,6 +3105,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); @@ -3001,6 +3139,16 @@ void _ir_IJMP(ir_ctx *ctx, ir_ref addr) ctx->control = IR_UNUSED; } +ir_ref _ir_IGOTO(ir_ctx *ctx, ir_ref addr) +{ + ir_ref ref; + + IR_ASSERT(ctx->control); + ctx->control = ref = ir_emit2(ctx, IR_IGOTO, ctx->control, addr); + ctx->control = IR_UNUSED; + return ref; +} + ir_ref _ir_ADD_OFFSET(ir_ctx *ctx, ir_ref addr, uintptr_t offset) { if (offset) { @@ -3123,6 +3271,18 @@ void _ir_VSTORE(ir_ctx *ctx, ir_ref var, ir_ref val) ctx->control = ir_emit3(ctx, IR_VSTORE, ctx->control, var, val); } +ir_ref _ir_VLOAD_v(ir_ctx *ctx, ir_type type, ir_ref var) +{ + IR_ASSERT(ctx->control); + return ctx->control = ir_emit2(ctx, IR_OPT(IR_VLOAD_v, type), ctx->control, var); +} + +void _ir_VSTORE_v(ir_ctx *ctx, ir_ref var, ir_ref val) +{ + IR_ASSERT(ctx->control); + ctx->control = ir_emit3(ctx, IR_VSTORE_v, ctx->control, var, val); +} + ir_ref _ir_TLS(ir_ctx *ctx, ir_ref index, ir_ref offset) { IR_ASSERT(ctx->control); @@ -3181,6 +3341,18 @@ void _ir_STORE(ir_ctx *ctx, ir_ref addr, ir_ref val) ctx->control = ir_emit3(ctx, IR_STORE, ctx->control, addr, val); } +ir_ref _ir_LOAD_v(ir_ctx *ctx, ir_type type, ir_ref addr) +{ + IR_ASSERT(ctx->control); + return ctx->control = ir_emit2(ctx, IR_OPT(IR_LOAD_v, type), ctx->control, addr); +} + +void _ir_STORE_v(ir_ctx *ctx, ir_ref addr, ir_ref val) +{ + IR_ASSERT(ctx->control); + ctx->control = ir_emit3(ctx, IR_STORE_v, ctx->control, addr, val); +} + void _ir_VA_START(ir_ctx *ctx, ir_ref list) { IR_ASSERT(ctx->control); @@ -3205,6 +3377,15 @@ ir_ref _ir_VA_ARG(ir_ctx *ctx, ir_type type, ir_ref list) return ctx->control = ir_emit2(ctx, IR_OPT(IR_VA_ARG, type), ctx->control, list); } +ir_ref _ir_VA_ARG_EX(ir_ctx *ctx, ir_type type, ir_ref list, size_t size, size_t align) +{ + IR_ASSERT(ctx->control); + IR_ASSERT(size <= 0x0fffffff); + IR_ASSERT(align != 0 && ((align & (align - 1)) == 0) && align <= 128); + return ctx->control = ir_emit3(ctx, IR_OPT(IR_VA_ARG, type), ctx->control, list, + (ir_ref)IR_VA_ARG_OP3(size, align)); +} + ir_ref _ir_BLOCK_BEGIN(ir_ctx *ctx) { IR_ASSERT(ctx->control); diff --git a/ext/opcache/jit/ir/ir.h b/ext/opcache/jit/ir/ir.h index ec5e57129c9ab..a96650597055a 100644 --- a/ext/opcache/jit/ir/ir.h +++ b/ext/opcache/jit/ir/ir.h @@ -216,6 +216,7 @@ typedef enum _ir_type { * prb - branch probability 1-99 (0 - unspecified): (IF_TRUE, IF_FALSE, CASE_VAL, CASE_DEFAULT) * opt - optional number * pro - function prototype + * lbl - label used as value (a reference to constant): (BEGIN) * * The order of IR opcodes is carefully selected for efficient folding. * - foldable instruction go first @@ -257,6 +258,8 @@ typedef enum _ir_type { _(UGE, d2, def, def, ___) /* unsigned greater or equal */ \ _(ULE, d2, def, def, ___) /* unsigned less or equal */ \ _(UGT, d2, def, def, ___) /* unsigned greater */ \ + _(ORDERED, d2, def, def, ___) /* both operands are not NAN */ \ + _(UNORDERED, d2, def, def, ___) /* one of operands is NAN */ \ \ /* arithmetic ops */ \ _(ADD, d2C, def, def, ___) /* addition */ \ @@ -310,6 +313,8 @@ typedef enum _ir_type { _(PHI, pN, reg, def, def) /* SSA Phi function */ \ _(COPY, d1X1, def, opt, ___) /* COPY (last foldable op) */ \ _(PI, p2, reg, def, ___) /* e-SSA Pi constraint ??? */ \ + _(ARGVAL, d1X2, def, num, num) /* pass struct arg by value */ \ + /* (op2 - size, op3 - align) */ \ /* (USE, RENAME) */ \ \ /* data ops */ \ @@ -318,6 +323,7 @@ typedef enum _ir_type { _(FUNC_ADDR, r0, ___, ___, ___) /* constant func ref */ \ _(FUNC, r0, ___, ___, ___) /* constant func ref */ \ _(SYM, r0, ___, ___, ___) /* constant symbol ref */ \ + _(LABEL, r0, ___, ___, ___) /* label address ref */ \ _(STR, r0, ___, ___, ___) /* constant str ref */ \ \ /* call ops */ \ @@ -330,11 +336,15 @@ typedef enum _ir_type { _(BLOCK_BEGIN, a1, src, ___, ___) /* stacksave */ \ _(BLOCK_END, a2, src, def, ___) /* stackrestore */ \ _(VLOAD, l2, src, var, ___) /* load value of local var */ \ + _(VLOAD_v, l2, src, var, ___) /* volatile variant of VLOAD */ \ _(VSTORE, s3, src, var, def) /* store value to local var */ \ + _(VSTORE_v, s3, src, var, def) /* volatile variant of VSTORE */ \ _(RLOAD, l1X2, src, num, opt) /* load value from register */ \ _(RSTORE, s2X1, src, def, num) /* store value into register */ \ _(LOAD, l2, src, ref, ___) /* load from memory */ \ + _(LOAD_v, l2, src, ref, ___) /* volatile variant of VLOAD */ \ _(STORE, s3, src, ref, def) /* store to memory */ \ + _(STORE_v, s3, src, ref, def) /* volatile variant of VSTORE */ \ _(TLS, l1X2, src, num, num) /* thread local variable */ \ _(TRAP, x1, src, ___, ___) /* DebugBreak */ \ /* memory reference ops (A, H, U, S, TMP, STR, NEW, X, V) ??? */ \ @@ -343,7 +353,8 @@ typedef enum _ir_type { _(VA_START, x2, src, def, ___) /* va_start(va_list) */ \ _(VA_END, x2, src, def, ___) /* va_end(va_list) */ \ _(VA_COPY, x3, src, def, def) /* va_copy(dst, stc) */ \ - _(VA_ARG, x2, src, def, ___) /* va_arg(va_list) */ \ + _(VA_ARG, x2X1, src, def, opt) /* va_arg(va_list) */ \ + /* op3 - (size<<3)+log2(align) */ \ \ /* guards */ \ _(GUARD, c3, src, def, def) /* IF without second successor */ \ @@ -355,10 +366,11 @@ typedef enum _ir_type { /* control-flow nodes */ \ _(START, S0X1, ret, ___, ___) /* function start */ \ _(ENTRY, S1X1, src, num, ___) /* entry with a fake src edge */ \ - _(BEGIN, S1, src, ___, ___) /* block start */ \ + _(BEGIN, S1X1, src, lbl, ___) /* block start, optional &&lbl */ \ _(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 */ \ @@ -366,8 +378,9 @@ typedef enum _ir_type { _(LOOP_END, E1, src, ___, ___) /* loop end */ \ _(IF, E2, src, def, ___) /* conditional control split */ \ _(SWITCH, E2, src, def, ___) /* multi-way control split */ \ + _(IGOTO, E2, src, def, ___) /* computed goto (internal) */ \ + _(IJMP, T2X1, src, def, ret) /* computed goto (terminating) */ \ _(RETURN, T2X1, src, def, ret) /* function return */ \ - _(IJMP, T2X1, src, def, ret) /* computed goto */ \ _(UNREACHABLE, T1X2, src, ___, ret) /* unreachable (tailcall, etc) */ \ \ /* deoptimization helper */ \ @@ -394,6 +407,13 @@ typedef enum _ir_op { #define IR_OPTX(op, type, n) ((uint32_t)(op) | ((uint32_t)(type) << IR_OPT_TYPE_SHIFT) | ((uint32_t)(n) << IR_OPT_INPUTS_SHIFT)) #define IR_OPT_TYPE(opt) (((opt) & IR_OPT_TYPE_MASK) >> IR_OPT_TYPE_SHIFT) +/* "opt" modifiers */ +#define IR_COPY_HARD (1<<0) + +#define IR_VA_ARG_SIZE(op3) (((uint32_t)(op3) >> 3)) +#define IR_VA_ARG_ALIGN(op3) (1U << ((uint32_t)(op3) & 0x7)) +#define IR_VA_ARG_OP3(s, a) (((s) << 3) | ir_ntzl(a)) + /* IR References */ typedef int32_t ir_ref; @@ -527,6 +547,9 @@ void ir_strtab_free(ir_strtab *strtab); #define IR_EXTERN (1<<5) #define IR_CONST (1<<6) +#define IR_CONST_FUNC (1<<6) +#define IR_PURE_FUNC (1<<7) + #define IR_INITIALIZED (1<<7) /* sym data flag: constant or an initialized variable */ #define IR_CONST_STRING (1<<8) /* sym data flag: constant string */ @@ -582,12 +605,22 @@ typedef struct _ir_code_buffer { void *pos; } ir_code_buffer; +typedef struct { + int size; + int align; + int offset; +} ir_value_param; + +#define IR_CONST_HASH_SIZE 64 + struct _ir_ctx { ir_insn *ir_base; /* two directional array - instructions grow down, constants grow up */ ir_ref insns_count; /* number of instructions stored in instructions buffer */ ir_ref insns_limit; /* size of allocated instructions buffer (it's extended when overflow) */ ir_ref consts_count; /* number of constants stored in constants buffer */ ir_ref consts_limit; /* size of allocated constants buffer (it's extended when overflow) */ + uintptr_t const_hash_mask; + ir_ref *const_hash; uint32_t flags; /* IR context flags (see IR_* defines above) */ uint32_t flags2; /* IR context private flags (see IR_* defines in ir_private.h) */ ir_type ret_type; /* Function return type */ @@ -595,6 +628,7 @@ struct _ir_ctx { int32_t status; /* non-zero error code (see IR_ERROR_... macros), app may use negative codes */ ir_ref fold_cse_limit; /* CSE finds identical insns backward from "insn_count" to "fold_cse_limit" */ ir_insn fold_insn; /* temporary storage for folding engine */ + ir_value_param *value_params; /* information about "by-val" struct parameters */ ir_hashtab *binding; ir_use_list *use_lists; /* def->use lists for each instruction */ ir_ref *use_edges; /* the actual uses: use = ctx->use_edges[ctx->use_lists[def].refs + n] */ @@ -631,7 +665,6 @@ struct _ir_ctx { ir_ref vars; /* list of VARs (used by register allocator) */ }; ir_snapshot_create_t snapshot_create; - int32_t stack_frame_alignment; int32_t stack_frame_size; /* spill stack frame size (used by register allocator and code generator) */ int32_t call_stack_size; /* stack for parameter passing (used by register allocator and code generator) */ uint64_t used_preserved_regs; @@ -654,7 +687,7 @@ struct _ir_ctx { ir_loader *loader; ir_strtab strtab; ir_ref prev_insn_chain[IR_LAST_FOLDABLE_OP + 1]; - ir_ref prev_const_chain[IR_LAST_TYPE]; + ir_ref _const_hash[IR_CONST_HASH_SIZE]; }; /* Basic IR Construction API (implementation in ir.c) */ @@ -681,6 +714,7 @@ ir_ref ir_const_func_addr(ir_ctx *ctx, uintptr_t c, ir_ref proto); ir_ref ir_const_func(ir_ctx *ctx, ir_ref str, ir_ref proto); ir_ref ir_const_sym(ir_ctx *ctx, ir_ref str); ir_ref ir_const_str(ir_ctx *ctx, ir_ref str); +ir_ref ir_const_label(ir_ctx *ctx, ir_ref str); ir_ref ir_unique_const_addr(ir_ctx *ctx, uintptr_t c); @@ -854,6 +888,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,9 +907,10 @@ 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); + bool (*add_label) (ir_loader *loader, const char *name, void *addr); }; void ir_loader_init(void); @@ -884,13 +922,15 @@ 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_print_proto_ex(uint8_t flags, ir_type ret_type, uint32_t params_count, const uint8_t *param_types, FILE *f); void ir_save(const ir_ctx *ctx, uint32_t save_flags, FILE *f); /* IR debug dump API (implementation in ir_dump.c) */ @@ -1012,6 +1052,7 @@ IR_ALWAYS_INLINE void *ir_jit_compile(ir_ctx *ctx, int opt_level, size_t *size) #define IR_ERROR_UNSUPPORTED_CODE_RULE 3 #define IR_ERROR_LINK 4 #define IR_ERROR_ENCODE 5 +#define IR_ERROR_TOO_LARGE 6 /* IR Memmory Allocation */ #ifndef ir_mem_malloc diff --git a/ext/opcache/jit/ir/ir_aarch64.dasc b/ext/opcache/jit/ir/ir_aarch64.dasc index 772eea7a5d78a..b553243309f54 100644 --- a/ext/opcache/jit/ir/ir_aarch64.dasc +++ b/ext/opcache/jit/ir/ir_aarch64.dasc @@ -218,6 +218,7 @@ typedef struct _ir_backend_data { dasm_State *dasm_state; ir_bitset emit_constants; int rodata_label, jmp_table_label; + bool resolved_label_syms; } ir_backend_data; #define IR_GP_REG_NAME(code, name64, name32) \ @@ -315,6 +316,7 @@ const char *ir_reg_name(int8_t reg, ir_type type) _(RETURN_VOID) \ _(RETURN_INT) \ _(RETURN_FP) \ + _(IGOTO_DUP) \ #define IR_RULE_ENUM(name) IR_ ## name, @@ -385,7 +387,7 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co n++; break; } - } else if (ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA) { + } else if (!IR_IS_CONST_REF(insn->op2) && ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA) { constraints->tmp_regs[n] = IR_TMP_REG(2, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); n++; } @@ -397,6 +399,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 +415,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; @@ -471,10 +480,16 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co if (IR_IS_CONST_REF(insn->op1)) { constraints->tmp_regs[n] = IR_TMP_REG(1, insn->type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); n++; + } else if (ir_rule(ctx, insn->op1) == IR_STATIC_ALLOCA) { + constraints->tmp_regs[n] = IR_TMP_REG(1, insn->type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); + n++; } if (IR_IS_CONST_REF(insn->op2) && insn->op1 != insn->op2) { constraints->tmp_regs[n] = IR_TMP_REG(2, insn->type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); n++; + } else if (!IR_IS_CONST_REF(insn->op2) && ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA) { + constraints->tmp_regs[n] = IR_TMP_REG(2, insn->type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); + n++; } break; case IR_CMP_INT: @@ -513,6 +528,7 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co } break; case IR_VSTORE: + case IR_VSTORE_v: insn = &ctx->ir_base[ref]; if (IR_IS_CONST_REF(insn->op3)) { insn = &ctx->ir_base[insn->op3]; @@ -567,6 +583,10 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co constraints->tmp_regs[n] = IR_TMP_REG(3, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); n++; break; + case IR_ARGVAL: + constraints->tmp_regs[0] = IR_SCRATCH_REG(IR_REG_SCRATCH, IR_DEF_SUB_REF - IR_SUB_REFS_COUNT, IR_USE_SUB_REF); + n = 1; + break; case IR_CALL: insn = &ctx->ir_base[ref]; constraints->def_reg = (IR_IS_TYPE_INT(insn->type)) ? IR_REG_INT_RET1 : IR_REG_FP_RET1; @@ -585,6 +605,19 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co } flags = IR_USE_SHOULD_BE_IN_REG | IR_OP2_MUST_BE_IN_REG | IR_OP3_SHOULD_BE_IN_REG; break; + case IR_IGOTO: + insn = &ctx->ir_base[ref]; + if (ctx->ir_base[insn->op1].op == IR_MERGE || ctx->ir_base[insn->op1].op == IR_LOOP_BEGIN) { + ir_insn *merge = &ctx->ir_base[insn->op1]; + ir_ref *p, n = merge->inputs_count; + + for (p = merge->ops + 1; n > 0; p++, n--) { + ir_ref input = *p; + IR_ASSERT(ctx->ir_base[input].op == IR_END || ctx->ir_base[input].op == IR_LOOP_END); + ctx->rules[input] = IR_IGOTO_DUP; + } + } + return insn->op; case IR_COND: insn = &ctx->ir_base[ref]; n = 0; @@ -647,16 +680,35 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co flags = IR_OP2_MUST_BE_IN_REG; constraints->tmp_regs[0] = IR_TMP_REG(3, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); n = 1; + insn = &ctx->ir_base[ref]; + if (IR_IS_CONST_REF(insn->op2)) { + constraints->tmp_regs[1] = IR_TMP_REG(2, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); + n = 2; + } break; case IR_VA_ARG: - flags = IR_USE_MUST_BE_IN_REG | IR_OP2_MUST_BE_IN_REG; + flags = IR_USE_MUST_BE_IN_REG | IR_OP2_MUST_BE_IN_REG | IR_DEF_CONFLICTS_WITH_INPUT_REGS; constraints->tmp_regs[0] = IR_TMP_REG(3, IR_ADDR, IR_LOAD_SUB_REF, IR_SAVE_SUB_REF); n = 1; + insn = &ctx->ir_base[ref]; + if (IR_IS_CONST_REF(insn->op2)) { + constraints->tmp_regs[1] = IR_TMP_REG(2, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); + n = 2; + } break; case IR_VA_COPY: flags = IR_OP2_MUST_BE_IN_REG | IR_OP3_MUST_BE_IN_REG; constraints->tmp_regs[0] = IR_TMP_REG(1, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); n = 1; + insn = &ctx->ir_base[ref]; + if (IR_IS_CONST_REF(insn->op2)) { + constraints->tmp_regs[n] = IR_TMP_REG(2, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); + n++; + } + if (IR_IS_CONST_REF(insn->op3)) { + constraints->tmp_regs[n] = IR_TMP_REG(3, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); + n++; + } break; } constraints->tmps_count = n; @@ -684,7 +736,8 @@ static void ir_match_fuse_addr(ir_ctx *ctx, ir_ref addr_ref, ir_type type) do { ir_insn *insn = &ctx->ir_base[*p]; - if (insn->op != IR_LOAD && (insn->op != IR_STORE || insn->op3 == addr_ref)) { + if (insn->op != IR_LOAD && insn->op != IR_LOAD_v + && ((insn->op != IR_STORE && insn->op != IR_STORE_v) || insn->op3 == addr_ref)) { return; } p++; @@ -717,6 +770,9 @@ static uint32_t ir_match_insn(ir_ctx *ctx, ir_ref ref) return IR_CMP_FP; } break; + case IR_ORDERED: + case IR_UNORDERED: + return IR_CMP_FP; case IR_ADD: case IR_SUB: if (IR_IS_TYPE_INT(insn->type)) { @@ -928,7 +984,7 @@ binop_fp: ctx->flags2 |= IR_HAS_CALLS; return IR_CALL; case IR_VAR: - return IR_SKIPPED | IR_VAR; + return IR_STATIC_ALLOCA; case IR_PARAM: return ctx->use_lists[ref].count > 0 ? IR_PARAM : IR_SKIPPED | IR_PARAM; case IR_ALLOCA: @@ -945,6 +1001,7 @@ binop_fp: } return IR_ALLOCA; case IR_LOAD: + case IR_LOAD_v: ir_match_fuse_addr(ctx, insn->op2, insn->type); if (IR_IS_TYPE_INT(insn->type)) { return IR_LOAD_INT; @@ -953,6 +1010,7 @@ binop_fp: } break; case IR_STORE: + case IR_STORE_v: ir_match_fuse_addr(ctx, insn->op2, ctx->ir_base[insn->op3].type); if (IR_IS_TYPE_INT(ctx->ir_base[insn->op3].type)) { return IR_STORE_INT; @@ -996,6 +1054,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: @@ -1012,7 +1071,7 @@ binop_fp: case IR_IF: if (!IR_IS_CONST_REF(insn->op2) && ctx->use_lists[insn->op2].count == 1) { op2_insn = &ctx->ir_base[insn->op2]; - if (op2_insn->op >= IR_EQ && op2_insn->op <= IR_UGT) { + if (op2_insn->op >= IR_EQ && op2_insn->op <= IR_UNORDERED) { if (IR_IS_TYPE_INT(ctx->ir_base[op2_insn->op1].type)) { ctx->rules[insn->op2] = IR_FUSED | IR_CMP_INT; return IR_CMP_AND_BRANCH_INT; @@ -1035,7 +1094,7 @@ binop_fp: case IR_GUARD_NOT: if (!IR_IS_CONST_REF(insn->op2) && ctx->use_lists[insn->op2].count == 1) { op2_insn = &ctx->ir_base[insn->op2]; - if (op2_insn->op >= IR_EQ && op2_insn->op <= IR_UGT + if (op2_insn->op >= IR_EQ && op2_insn->op <= IR_UNORDERED // TODO: register allocator may clobber operands of CMP before they are used in the GUARD_CMP && (insn->op2 == ref - 1 || (insn->op2 == ctx->prev_ref[ref] - 1 @@ -1079,6 +1138,9 @@ binop_fp: ctx->flags2 |= IR_HAS_VA_ARG_GP|IR_HAS_VA_ARG_FP; } } + } else { + /* va_list may escape */ + ctx->flags2 |= IR_HAS_VA_ARG_GP|IR_HAS_VA_ARG_FP; } return IR_VA_START; case IR_VA_END: @@ -1095,6 +1157,8 @@ binop_fp: } } return IR_SKIPPED | IR_NOP; + case IR_ARGVAL: + return IR_FUSED | IR_ARGVAL; case IR_NOP: return IR_SKIPPED | IR_NOP; default: @@ -1325,7 +1389,7 @@ static void ir_emit_load_imm_fp(ir_ctx *ctx, ir_type type, ir_reg reg, ir_ref sr } else if (type == IR_DOUBLE && insn->val.u64 == 0) { | fmov Rd(reg-IR_REG_FP_FIRST), xzr } else { - label = ir_const_label(ctx, src); + label = ir_get_const_label(ctx, src); if (type == IR_DOUBLE) { | ldr Rd(reg-IR_REG_FP_FIRST), =>label } else { @@ -1378,6 +1442,12 @@ static void ir_emit_load_mem(ir_ctx *ctx, ir_type type, ir_reg reg, ir_mem mem) } } +static int32_t ir_local_offset(ir_ctx *ctx, ir_insn *insn) +{ + IR_ASSERT(insn->op == IR_VAR || insn->op == IR_ALLOCA || insn->op == IR_VADDR); + return IR_SPILL_POS_TO_OFFSET(insn->op3); +} + static void ir_load_local_addr(ir_ctx *ctx, ir_reg reg, ir_ref src) { ir_backend_data *data = ctx->data; @@ -1391,16 +1461,46 @@ static void ir_load_local_addr(ir_ctx *ctx, ir_reg reg, ir_ref src) if (var_insn->op == IR_VADDR) { var_insn = &ctx->ir_base[var_insn->op1]; } - IR_ASSERT(var_insn->op == IR_VAR || var_insn->op == IR_ALLOCA); - offset = IR_SPILL_POS_TO_OFFSET(var_insn->op3); + offset = ir_local_offset(ctx, var_insn); if (aarch64_may_encode_imm12(offset)) { | 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), Rx(base), Rx(IR_REG_INT_TMP) } } +static void ir_resolve_label_syms(ir_ctx *ctx) +{ + uint32_t b; + ir_block *bb; + + for (b = 1, bb = &ctx->cfg_blocks[b]; b <= ctx->cfg_blocks_count; bb++, b++) { + ir_insn *insn = &ctx->ir_base[bb->start]; + + if (insn->op == IR_BEGIN && insn->op2) { + IR_ASSERT(ctx->ir_base[insn->op2].op == IR_LABEL); + ctx->ir_base[insn->op2].val.u32_hi = b; + } + } +} + +static void ir_emit_load_label_addr(ir_ctx *ctx, ir_reg reg, ir_insn *label) +{ + ir_backend_data *data = ctx->data; + dasm_State **Dst = &data->dasm_state; + + if (!data->resolved_label_syms) { + data->resolved_label_syms = 1; + ir_resolve_label_syms(ctx); + } + + IR_ASSERT(label->op == IR_LABEL); + int b = label->val.u32_hi; + + b = ir_skip_empty_target_blocks(ctx, b); + | adr Rx(reg), =>b +} static void ir_emit_load(ir_ctx *ctx, ir_type type, ir_reg reg, ir_ref src) { @@ -1415,9 +1515,11 @@ static void ir_emit_load(ir_ctx *ctx, ir_type type, ir_reg reg, ir_ref src) } else if (insn->op == IR_STR) { ir_backend_data *data = ctx->data; dasm_State **Dst = &data->dasm_state; - int label = ir_const_label(ctx, src); + int label = ir_get_const_label(ctx, src); | adr Rx(reg), =>label + } else if (insn->op == IR_LABEL) { + ir_emit_load_label_addr(ctx, reg, insn); } else { ir_emit_load_imm_int(ctx, type, reg, insn->val.i64); } @@ -1586,19 +1688,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 +1736,42 @@ 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); + offset -= sizeof(void*); + | 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 +1781,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 +1824,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 +1840,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*); } } @@ -1705,7 +1854,12 @@ static void ir_emit_prologue(ir_ctx *ctx) offset += 16 * ctx->fp_reg_params; for (i = ctx->fp_reg_params; i < IR_REG_FP_ARGS; i++) { // TODO: Rd->Rq stur->str ??? - | str Rd(fp_reg_params[i]-IR_REG_FP_FIRST), [Rx(fp), #offset] + if (aarch64_may_encode_addr_offset(offset, 8)) { + | str Rd(fp_reg_params[i]-IR_REG_FP_FIRST), [Rx(fp), #offset] + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset); + | str Rd(fp_reg_params[i]-IR_REG_FP_FIRST), [Rx(fp), Rx(IR_REG_INT_TMP)] + } offset += 16; } } @@ -1738,26 +1892,44 @@ static void ir_emit_epilogue(ir_ctx *ctx) offset -= sizeof(void*) * 2; if (aarch64_may_encode_imm7_addr_offset(offset, 8)) { | ldp 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)) { | ldr Rx(prev), [Rx(fp), #offset] | ldr Rx(i), [Rx(fp), #(offset+8)] + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset); + | ldr Rx(prev), [Rx(fp), Rx(IR_REG_INT_TMP)] + | add Rx(IR_REG_INT_TMP), Rx(IR_REG_INT_TMP), #8 + | ldr Rx(i), [Rx(fp), Rx(IR_REG_INT_TMP)] } prev = IR_REG_NONE; } else { if (prev < IR_REG_FP_FIRST) { offset -= sizeof(void*); - | ldr Rx(prev), [Rx(fp), #offset] + if (aarch64_may_encode_addr_offset(offset, 8)) { + | ldr Rx(prev), [Rx(fp), #offset] + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset); + | ldr Rx(prev), [Rx(fp), Rx(IR_REG_INT_TMP)] + } offset -= sizeof(void*); - | ldr Rd(i-IR_REG_FP_FIRST), [Rx(fp), #offset] + if (aarch64_may_encode_addr_offset(offset, 8)) { + | ldr Rd(i-IR_REG_FP_FIRST), [Rx(fp), #offset] + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset); + | ldr 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)) { | ldp 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)) { | ldr Rd(prev-IR_REG_FP_FIRST), [Rx(fp), #offset] | ldr Rd(i-IR_REG_FP_FIRST), [Rx(fp), #(offset+8)] + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset); + | ldr Rx(prev-IR_REG_FP_FIRST), [Rx(fp), Rx(IR_REG_INT_TMP)] + | add Rx(IR_REG_INT_TMP), Rx(IR_REG_INT_TMP), #8 + | ldr Rx(i-IR_REG_FP_FIRST), [Rx(fp), Rx(IR_REG_INT_TMP)] } } prev = IR_REG_NONE; @@ -1767,10 +1939,20 @@ static void ir_emit_epilogue(ir_ctx *ctx) if (prev != IR_REG_NONE) { if (prev < IR_REG_FP_FIRST) { offset -= sizeof(void*); - | ldr Rx(prev), [Rx(fp), #offset] + if (aarch64_may_encode_addr_offset(offset, 8)) { + | ldr Rx(prev), [Rx(fp), #offset] + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset); + | ldr Rx(prev), [Rx(fp), Rx(IR_REG_INT_TMP)] + } } else { offset -= sizeof(void*); - | ldr Rd(prev-IR_REG_FP_FIRST), [Rx(fp), #offset] + if (aarch64_may_encode_addr_offset(offset, 8)) { + | ldr Rd(prev-IR_REG_FP_FIRST), [Rx(fp), #offset] + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset); + | ldr Rd(prev-IR_REG_FP_FIRST), [Rx(fp), Rx(IR_REG_INT_TMP)] + } } } } @@ -1781,15 +1963,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) } } } @@ -1812,6 +2001,9 @@ static void ir_emit_binop_int(ir_ctx *ctx, ir_ref def, ir_insn *insn) op1_reg = IR_REG_NUM(op1_reg); ir_emit_load(ctx, type, op1_reg, op1); } + if (op2_reg == IR_REG_NONE && op1 == op2) { + op2_reg = op1_reg; + } if (op2_reg != IR_REG_NONE) { if (IR_REG_SPILLED(op2_reg)) { op2_reg = IR_REG_NUM(op2_reg); @@ -2900,6 +3092,12 @@ static void ir_emit_cmp_fp(ir_ctx *ctx, ir_ref def, ir_insn *insn) case IR_UGT: | cset Rw(def_reg), hi break; + case IR_ORDERED: + | cset Rw(def_reg), vc + break; + case IR_UNORDERED: + | cset Rw(def_reg), vs + break; } if (IR_REG_SPILLED(ctx->regs[def][0])) { ir_emit_store(ctx, insn->type, def, def_reg); @@ -2974,7 +3172,7 @@ static void ir_emit_jcc(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn, uint ir_get_true_false_blocks(ctx, b, &true_block, &false_block); if (true_block == next_block) { /* swap to avoid unconditional JMP */ - if (int_cmp || op == IR_EQ || op == IR_NE) { + if (int_cmp || op == IR_EQ || op == IR_NE || op == IR_ORDERED || op == IR_UNORDERED) { op ^= 1; // reverse } else { op ^= 5; // reverse @@ -3054,6 +3252,11 @@ static void ir_emit_jcc(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn, uint case IR_UGT: | bhi =>true_block break; + case IR_ORDERED: + | bvc =>true_block + break; + case IR_UNORDERED: + | bvs =>true_block // case IR_ULT: fprintf(stderr, "\tjb .LL%d\n", true_block); break; // case IR_UGE: fprintf(stderr, "\tjae .LL%d\n", true_block); break; // case IR_ULE: fprintf(stderr, "\tjbe .LL%d\n", true_block); break; @@ -3307,25 +3510,52 @@ static void ir_emit_sext(ir_ctx *ctx, ir_ref def, ir_insn *insn) int32_t offset = ir_ref_spill_slot_offset(ctx, insn->op1, &fp); if (ir_type_size[src_type] == 1) { - if (ir_type_size[dst_type] == 2) { - | ldrsb Rw(def_reg), [Rx(fp), #offset] - } else if (ir_type_size[dst_type] == 4) { - | ldrsb Rw(def_reg), [Rx(fp), #offset] + if (aarch64_may_encode_addr_offset(offset, ir_type_size[src_type])) { + if (ir_type_size[dst_type] == 2) { + | ldrsb Rw(def_reg), [Rx(fp), #offset] + } else if (ir_type_size[dst_type] == 4) { + | ldrsb Rw(def_reg), [Rx(fp), #offset] + } else { + IR_ASSERT(ir_type_size[dst_type] == 8); + | ldrsb Rx(def_reg), [Rx(fp), #offset] + } } else { - IR_ASSERT(ir_type_size[dst_type] == 8); - | ldrsb Rx(def_reg), [Rx(fp), #offset] + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset); + if (ir_type_size[dst_type] == 2) { + | ldrsb Rw(def_reg), [Rx(fp), Rx(IR_REG_INT_TMP)] + } else if (ir_type_size[dst_type] == 4) { + | ldrsb Rw(def_reg), [Rx(fp), Rx(IR_REG_INT_TMP)] + } else { + IR_ASSERT(ir_type_size[dst_type] == 8); + | ldrsb Rx(def_reg), [Rx(fp), Rx(IR_REG_INT_TMP)] + } } } else if (ir_type_size[src_type] == 2) { - if (ir_type_size[dst_type] == 4) { - | ldrsh Rw(def_reg), [Rx(fp), #offset] + if (aarch64_may_encode_addr_offset(offset, ir_type_size[src_type])) { + if (ir_type_size[dst_type] == 4) { + | ldrsh Rw(def_reg), [Rx(fp), #offset] + } else { + IR_ASSERT(ir_type_size[dst_type] == 8); + | ldrsh Rx(def_reg), [Rx(fp), #offset] + } } else { - IR_ASSERT(ir_type_size[dst_type] == 8); - | ldrsh Rx(def_reg), [Rx(fp), #offset] + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset); + if (ir_type_size[dst_type] == 4) { + | ldrsh Rw(def_reg), [Rx(fp), Rx(IR_REG_INT_TMP)] + } else { + IR_ASSERT(ir_type_size[dst_type] == 8); + | ldrsh Rx(def_reg), [Rx(fp), Rx(IR_REG_INT_TMP)] + } } } else { IR_ASSERT(ir_type_size[src_type] == 4); IR_ASSERT(ir_type_size[dst_type] == 8); - | ldrsw Rx(def_reg), [Rx(fp), #offset] + if (aarch64_may_encode_addr_offset(offset, ir_type_size[src_type])) { + | ldrsw Rx(def_reg), [Rx(fp), #offset] + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset); + | ldrsw Rx(def_reg), [Rx(fp), Rx(IR_REG_INT_TMP)] + } } } if (IR_REG_SPILLED(ctx->regs[def][0])) { @@ -3365,14 +3595,27 @@ static void ir_emit_zext(ir_ctx *ctx, ir_ref def, ir_insn *insn) ir_reg fp; int32_t offset = ir_ref_spill_slot_offset(ctx, insn->op1, &fp); - if (ir_type_size[src_type] == 1) { - | ldrb Rw(def_reg), [Rx(fp), #offset] - } else if (ir_type_size[src_type] == 2) { - | ldrh Rw(def_reg), [Rx(fp), #offset] + if (aarch64_may_encode_addr_offset(offset, ir_type_size[src_type])) { + if (ir_type_size[src_type] == 1) { + | ldrb Rw(def_reg), [Rx(fp), #offset] + } else if (ir_type_size[src_type] == 2) { + | ldrh Rw(def_reg), [Rx(fp), #offset] + } else { + IR_ASSERT(ir_type_size[src_type] == 4); + IR_ASSERT(ir_type_size[dst_type] == 8); + | ldr Rw(def_reg), [Rx(fp), #offset] + } } else { - IR_ASSERT(ir_type_size[src_type] == 4); - IR_ASSERT(ir_type_size[dst_type] == 8); - | ldr Rw(def_reg), [Rx(fp), #offset] + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset); + if (ir_type_size[src_type] == 1) { + | ldrb Rw(def_reg), [Rx(fp), Rx(IR_REG_INT_TMP)] + } else if (ir_type_size[src_type] == 2) { + | ldrh Rw(def_reg), [Rx(fp), Rx(IR_REG_INT_TMP)] + } else { + IR_ASSERT(ir_type_size[src_type] == 4); + IR_ASSERT(ir_type_size[dst_type] == 8); + | ldr Rw(def_reg), [Rx(fp), Rx(IR_REG_INT_TMP)] + } } } if (IR_REG_SPILLED(ctx->regs[def][0])) { @@ -3471,11 +3714,21 @@ static void ir_emit_bitcast(ir_ctx *ctx, ir_ref def, ir_insn *insn) ir_reg fp; int32_t offset = ir_ref_spill_slot_offset(ctx, insn->op1, &fp); - if (src_type == IR_DOUBLE) { - | ldr Rx(def_reg), [Rx(fp), #offset] + if (aarch64_may_encode_addr_offset(offset, ir_type_size[src_type])) { + if (src_type == IR_DOUBLE) { + | ldr Rx(def_reg), [Rx(fp), #offset] + } else { + IR_ASSERT(src_type == IR_FLOAT); + | ldr Rw(def_reg), [Rx(fp), #offset] + } } else { - IR_ASSERT(src_type == IR_FLOAT); - | ldr Rw(def_reg), [Rx(fp), #offset] + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset); + if (src_type == IR_DOUBLE) { + | ldr Rx(def_reg), [Rx(fp), Rx(IR_REG_INT_TMP)] + } else { + IR_ASSERT(src_type == IR_FLOAT); + | ldr Rw(def_reg), [Rx(fp), Rx(IR_REG_INT_TMP)] + } } } } else if (IR_IS_TYPE_FP(dst_type)) { @@ -3497,12 +3750,22 @@ static void ir_emit_bitcast(ir_ctx *ctx, ir_ref def, ir_insn *insn) ir_reg fp; int32_t offset = ir_ref_spill_slot_offset(ctx, insn->op1, &fp); - if (dst_type == IR_DOUBLE) { - | ldr Rd(def_reg), [Rx(fp), #offset] - } else { - IR_ASSERT(src_type == IR_FLOAT); - | ldr Rs(def_reg), [Rx(fp), #offset] - } + if (aarch64_may_encode_addr_offset(offset, ir_type_size[src_type])) { + if (dst_type == IR_DOUBLE) { + | ldr Rd(def_reg), [Rx(fp), #offset] + } else { + IR_ASSERT(dst_type == IR_FLOAT); + | ldr Rs(def_reg), [Rx(fp), #offset] + } + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset); + if (dst_type == IR_DOUBLE) { + | ldr Rd(def_reg), [Rx(fp), Rx(IR_REG_INT_TMP)] + } else { + IR_ASSERT(dst_type == IR_FLOAT); + | ldr Rs(def_reg), [Rx(fp), Rx(IR_REG_INT_TMP)] + } + } } } if (IR_REG_SPILLED(ctx->regs[def][0])) { @@ -3725,7 +3988,12 @@ static void ir_emit_vaddr(ir_ctx *ctx, ir_ref def, ir_insn *insn) IR_ASSERT(def_reg != IR_REG_NONE); offset = ir_var_spill_slot(ctx, insn->op1, &fp); - | add Rx(def_reg), Rx(fp), #offset + if (aarch64_may_encode_imm12(offset)) { + | add Rx(def_reg), Rx(fp), #offset + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset); + | add Rx(def_reg), Rx(fp), Rx(IR_REG_INT_TMP) + } if (IR_REG_SPILLED(ctx->regs[def][0])) { ir_emit_store(ctx, type, def, def_reg); } @@ -3797,7 +4065,7 @@ static ir_mem ir_fuse_addr(ir_ctx *ctx, ir_ref root, ir_ref ref) IR_ASSERT(!IR_IS_SYM_CONST(ctx->ir_base[addr_insn->op2].op)); if (ir_rule(ctx, addr_insn->op1) == IR_STATIC_ALLOCA) { reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[addr_insn->op1].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[addr_insn->op1]); offset += ctx->ir_base[addr_insn->op2].val.i32; return IR_MEM_BO(reg, offset); } else { @@ -3815,7 +4083,7 @@ static ir_mem ir_fuse_addr(ir_ctx *ctx, ir_ref root, ir_ref ref) } else { IR_ASSERT(addr_insn->op == IR_ALLOCA || addr_insn->op == IR_VADDR); reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[ref].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[ref]); return IR_MEM_BO(reg, offset); } } @@ -4113,7 +4381,12 @@ static void ir_emit_afree(ir_ctx *ctx, ir_ref def, ir_insn *insn) /* Stack must be 16 byte aligned */ size = IR_ALIGNED_SIZE(size, 16); - | add sp, sp, #size + if (aarch64_may_encode_imm12(size)) { + | add sp, sp, #size + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, size); + | add sp, sp, Rx(IR_REG_INT_TMP) + } if (!(ctx->flags & IR_USE_FRAME_POINTER)) { ctx->call_stack_size -= size; } @@ -4175,8 +4448,11 @@ static void ir_emit_frame_addr(ir_ctx *ctx, ir_ref def) if (ctx->flags & IR_USE_FRAME_POINTER) { | mov Rx(def_reg), Rx(IR_REG_X29) - } else { + } else if (aarch64_may_encode_imm12(ctx->stack_frame_size + ctx->call_stack_size)) { | add Rx(def_reg), Rx(IR_REG_X31), #(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 Rx(def_reg), Rx(IR_REG_X31), Rx(IR_REG_INT_TMP) } if (IR_REG_SPILLED(ctx->regs[def][0])) { ir_emit_store(ctx, IR_ADDR, def, def_reg); @@ -4204,7 +4480,7 @@ static void ir_emit_va_start(ir_ctx *ctx, ir_ref def, ir_insn *insn) } else { IR_ASSERT(ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA); op2_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op2].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[insn->op2]); } if (ctx->flags & IR_USE_FRAME_POINTER) { @@ -4236,7 +4512,7 @@ static void ir_emit_va_start(ir_ctx *ctx, ir_ref def, ir_insn *insn) } else { IR_ASSERT(ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA); op2_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op2].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[insn->op2]); } if (ctx->flags & IR_USE_FRAME_POINTER) { @@ -4269,7 +4545,7 @@ static void ir_emit_va_start(ir_ctx *ctx, ir_ref def, ir_insn *insn) if ((ctx->flags2 & (IR_HAS_VA_ARG_FP|IR_HAS_VA_COPY)) && ctx->fp_reg_params < IR_REG_FP_ARGS) { reg_save_area_offset += 16 * IR_REG_FP_ARGS; /* Set va_list.vr_top */ - if (overflow_arg_area_offset != reg_save_area_offset) { + if (overflow_arg_area_offset != reg_save_area_offset || ctx->gp_reg_params < IR_REG_INT_ARGS) { | add Rx(tmp_reg), Rx(fp), #reg_save_area_offset } | str Rx(tmp_reg), [Rx(op2_reg), #(offset+offsetof(ir_va_list, vr_top))] @@ -4303,7 +4579,7 @@ static void ir_emit_va_copy(ir_ctx *ctx, ir_ref def, ir_insn *insn) } else { IR_ASSERT(ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA); op2_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; - op2_offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op2].op3); + op2_offset = ir_local_offset(ctx, &ctx->ir_base[insn->op2]); } if (op3_reg != IR_REG_NONE) { if (IR_REG_SPILLED(op3_reg)) { @@ -4314,7 +4590,7 @@ static void ir_emit_va_copy(ir_ctx *ctx, ir_ref def, ir_insn *insn) } else { IR_ASSERT(ir_rule(ctx, insn->op3) == IR_STATIC_ALLOCA); op3_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; - op3_offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op3].op3); + op3_offset = ir_local_offset(ctx, &ctx->ir_base[insn->op3]); } | ldr Rx(tmp_reg), [Rx(op3_reg), #op3_offset] | str Rx(tmp_reg), [Rx(op2_reg), #op2_offset] @@ -4336,7 +4612,7 @@ static void ir_emit_va_copy(ir_ctx *ctx, ir_ref def, ir_insn *insn) } else { IR_ASSERT(ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA); op2_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; - op2_offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op2].op3); + op2_offset = ir_local_offset(ctx, &ctx->ir_base[insn->op2]); } if (op3_reg != IR_REG_NONE) { if (IR_REG_SPILLED(op3_reg)) { @@ -4347,7 +4623,7 @@ static void ir_emit_va_copy(ir_ctx *ctx, ir_ref def, ir_insn *insn) } else { IR_ASSERT(ir_rule(ctx, insn->op3) == IR_STATIC_ALLOCA); op3_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; - op3_offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op3].op3); + op3_offset = ir_local_offset(ctx, &ctx->ir_base[insn->op3]); } | ldr Rx(tmp_reg), [Rx(op3_reg), #op3_offset] | str Rx(tmp_reg), [Rx(op2_reg), #op2_offset] @@ -4366,12 +4642,12 @@ 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; - IR_ASSERT(def_reg != IR_REG_NONE && tmp_reg != IR_REG_NONE); + IR_ASSERT((def_reg != IR_REG_NONE || ctx->use_lists[def].count == 1) && tmp_reg != IR_REG_NONE); if (op2_reg != IR_REG_NONE) { if (IR_REG_SPILLED(op2_reg)) { op2_reg = IR_REG_NUM(op2_reg); @@ -4381,25 +4657,27 @@ static void ir_emit_va_arg(ir_ctx *ctx, ir_ref def, ir_insn *insn) } else { IR_ASSERT(ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA); op2_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op2].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[insn->op2]); } | ldr Rx(tmp_reg), [Rx(op2_reg), #offset] - ir_emit_load_mem(ctx, type, def_reg, IR_MEM_BO(tmp_reg, 0)); + if (def_reg != IR_REG_NONE) { + ir_emit_load_mem(ctx, type, def_reg, IR_MEM_BO(tmp_reg, 0)); + } | add Rx(tmp_reg), Rx(tmp_reg), #IR_MAX(ir_type_size[type], sizeof(void*)) | str Rx(tmp_reg), [Rx(op2_reg), #offset] - if (IR_REG_SPILLED(ctx->regs[def][0])) { + if (def_reg != IR_REG_NONE && IR_REG_SPILLED(ctx->regs[def][0])) { ir_emit_store(ctx, type, def, def_reg); } #else 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; - IR_ASSERT(def_reg != IR_REG_NONE && tmp_reg != IR_REG_NONE); + IR_ASSERT((def_reg != IR_REG_NONE || ctx->use_lists[def].count == 1) && tmp_reg != IR_REG_NONE); if (op2_reg != IR_REG_NONE) { if (IR_REG_SPILLED(op2_reg)) { op2_reg = IR_REG_NUM(op2_reg); @@ -4409,7 +4687,7 @@ static void ir_emit_va_arg(ir_ctx *ctx, ir_ref def, ir_insn *insn) } else { IR_ASSERT(ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA); op2_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op2].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[insn->op2]); } if (IR_IS_TYPE_INT(type)) { | ldr Rw(tmp_reg), [Rx(op2_reg), #(offset+offsetof(ir_va_list, gr_offset))] @@ -4418,13 +4696,17 @@ static void ir_emit_va_arg(ir_ctx *ctx, ir_ref def, ir_insn *insn) | ldr Rx(IR_REG_INT_TMP), [Rx(op2_reg), #(offset+offsetof(ir_va_list, gr_top))] | sxtw Rx(tmp_reg), Rw(tmp_reg) | add Rx(IR_REG_INT_TMP), Rx(tmp_reg), Rx(IR_REG_INT_TMP) - | ldr Rx(def_reg), [Rx(IR_REG_INT_TMP)] + if (def_reg != IR_REG_NONE) { + | ldr Rx(def_reg), [Rx(IR_REG_INT_TMP)] + } | add Rw(tmp_reg), Rw(tmp_reg), #sizeof(void*) | str Rw(tmp_reg), [Rx(op2_reg), #(offset+offsetof(ir_va_list, gr_offset))] | b >2 |1: | ldr Rx(tmp_reg), [Rx(op2_reg), #(offset+offsetof(ir_va_list, stack))] - | ldr Rx(def_reg), [Rx(tmp_reg)] + if (def_reg != IR_REG_NONE) { + | ldr Rx(def_reg), [Rx(tmp_reg)] + } | add Rx(tmp_reg), Rx(tmp_reg), #sizeof(void*) | str Rx(tmp_reg), [Rx(op2_reg), #(offset+offsetof(ir_va_list, stack))] |2: @@ -4435,18 +4717,22 @@ static void ir_emit_va_arg(ir_ctx *ctx, ir_ref def, ir_insn *insn) | ldr Rx(IR_REG_INT_TMP), [Rx(op2_reg), #(offset+offsetof(ir_va_list, vr_top))] | sxtw Rx(tmp_reg), Rw(tmp_reg) | add Rx(IR_REG_INT_TMP), Rx(tmp_reg), Rx(IR_REG_INT_TMP) - | ldr Rd(def_reg-IR_REG_FP_FIRST), [Rx(IR_REG_INT_TMP)] + if (def_reg != IR_REG_NONE) { + | ldr Rd(def_reg-IR_REG_FP_FIRST), [Rx(IR_REG_INT_TMP)] + } | add Rw(tmp_reg), Rw(tmp_reg), #16 | str Rw(tmp_reg), [Rx(op2_reg), #(offset+offsetof(ir_va_list, vr_offset))] | b >2 |1: | ldr Rx(tmp_reg), [Rx(op2_reg), #(offset+offsetof(ir_va_list, stack))] - | ldr Rd(def_reg-IR_REG_FP_FIRST), [Rx(tmp_reg)] + if (def_reg != IR_REG_NONE) { + | ldr Rd(def_reg-IR_REG_FP_FIRST), [Rx(tmp_reg)] + } | add Rx(tmp_reg), Rx(tmp_reg), #sizeof(void*) | str Rx(tmp_reg), [Rx(op2_reg), #(offset+offsetof(ir_va_list, stack))] |2: } - if (IR_REG_SPILLED(ctx->regs[def][0])) { + if (def_reg != IR_REG_NONE && IR_REG_SPILLED(ctx->regs[def][0])) { ir_emit_store(ctx, type, def, def_reg); } #endif @@ -4465,6 +4751,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 +4780,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 +4813,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 +4918,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) { @@ -4623,7 +4958,7 @@ static void ir_emit_switch(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn) } } -static int32_t ir_call_used_stack(ir_ctx *ctx, ir_insn *insn) +static int32_t ir_call_used_stack(ir_ctx *ctx, ir_insn *insn, int32_t *copy_stack_ptr) { int j, n; ir_type type; @@ -4631,7 +4966,7 @@ static int32_t ir_call_used_stack(ir_ctx *ctx, ir_insn *insn) int fp_param = 0; int int_reg_params_count = IR_REG_INT_ARGS; int fp_reg_params_count = IR_REG_FP_ARGS; - int32_t used_stack = 0; + int32_t used_stack = 0, copy_stack = 0; #ifdef __APPLE__ const ir_proto_t *proto = ir_call_proto(ctx, insn); int last_named_input = (proto && (proto->flags & IR_VARARG_FUNC)) ? proto->params_count + 2 : insn->inputs_count; @@ -4639,7 +4974,16 @@ static int32_t ir_call_used_stack(ir_ctx *ctx, ir_insn *insn) n = insn->inputs_count; for (j = 3; j <= n; j++) { - type = ctx->ir_base[ir_insn_op(insn, j)].type; + ir_insn *arg = &ctx->ir_base[ir_insn_op(insn, j)]; + type = arg->type; + if (arg->op == IR_ARGVAL) { + int size = arg->op2; + int align = arg->op3; + copy_stack += size; + align = IR_MAX((int)sizeof(void*), align); + copy_stack = IR_ALIGNED_SIZE(copy_stack, align); + type = IR_ADDR; + } #ifdef __APPLE__ if (j > last_named_input) { used_stack += IR_MAX(sizeof(void*), ir_type_size[type]); @@ -4659,7 +5003,9 @@ static int32_t ir_call_used_stack(ir_ctx *ctx, ir_insn *insn) } } - return used_stack; + copy_stack = IR_ALIGNED_SIZE(copy_stack, 16); + *copy_stack_ptr = copy_stack; + return used_stack + copy_stack; } static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg tmp_reg) @@ -4678,7 +5024,7 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg int fp_reg_params_count = IR_REG_FP_ARGS; const int8_t *int_reg_params = _ir_int_reg_params; const int8_t *fp_reg_params = _ir_fp_reg_params; - int32_t used_stack, stack_offset = 0; + int32_t used_stack, copy_stack = 0, stack_offset = 0, copy_stack_offset = 0; ir_copy *copies; bool do_pass3 = 0; /* For temporaries we may use any scratch registers except for registers used for parameters */ @@ -4697,7 +5043,7 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg // TODO: support for preallocated stack used_stack = 0; } else { - used_stack = ir_call_used_stack(ctx, insn); + used_stack = ir_call_used_stack(ctx, insn, ©_stack); /* Stack must be 16 byte aligned */ used_stack = IR_ALIGNED_SIZE(used_stack, 16); if (ctx->fixed_call_stack_size && used_stack <= ctx->fixed_call_stack_size) { @@ -4720,6 +5066,48 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg int last_named_input = (proto && (proto->flags & IR_VARARG_FUNC)) ? proto->params_count + 2 : insn->inputs_count; #endif + if (copy_stack) { + /* Copy struct arguments */ + for (j = 3; j <= n; j++) { + arg = ir_insn_op(insn, j); + src_reg = ir_get_alocated_reg(ctx, def, j); + arg_insn = &ctx->ir_base[arg]; + type = arg_insn->type; + + if (arg_insn->op == IR_ARGVAL) { + /* make a stack copy */ + void *addr = memcpy; + int size = arg_insn->op2; + int align = arg_insn->op3; + + copy_stack_offset += size; + align = IR_MAX((int)sizeof(void*), align); + copy_stack_offset = IR_ALIGNED_SIZE(copy_stack_offset, align); + src_reg = ctx->regs[arg][1]; + + | add Rx(IR_REG_INT_ARG1), sp, #(used_stack - copy_stack_offset) + if (src_reg != IR_REG_NONE) { + if (IR_REG_SPILLED(src_reg)) { + src_reg = IR_REG_NUM(src_reg); + ir_emit_load(ctx, IR_ADDR, src_reg, arg_insn->op1); + } + | mov Rx(IR_REG_INT_ARG2), Rx(src_reg) + } else { + ir_emit_load(ctx, IR_ADDR, IR_REG_INT_ARG2, arg_insn->op1); + } + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_ARG3, size); + + if (aarch64_may_use_b(ctx->code_buffer, addr)) { + | bl &addr + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, (intptr_t)addr); + | blr Rx(IR_REG_INT_TMP) + } + } + } + copy_stack_offset = 0; + } + /* 1. move all register arguments that should be passed through stack * and collect arguments that should be passed through registers */ copies = ir_mem_malloc((n - 2) * sizeof(ir_copy)); @@ -4728,8 +5116,13 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg src_reg = ir_get_alocated_reg(ctx, def, j); arg_insn = &ctx->ir_base[arg]; type = arg_insn->type; + #ifdef __APPLE__ if (j > last_named_input) { + if (arg_insn->op == IR_ARGVAL) { + do_pass3 = 1; + continue; + } dst_reg = IR_REG_NONE; /* pass argument through stack */ } else #endif @@ -4740,6 +5133,10 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg dst_reg = IR_REG_NONE; /* pass argument through stack */ } int_param++; + if (arg_insn->op == IR_ARGVAL) { + do_pass3 = 1; + continue; + } } else { IR_ASSERT(IR_IS_TYPE_FP(type)); if (fp_param < fp_reg_params_count) { @@ -4750,7 +5147,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 { @@ -4794,6 +5193,31 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg src_reg = ir_get_alocated_reg(ctx, def, j); arg_insn = &ctx->ir_base[arg]; type = arg_insn->type; + if (arg_insn->op == IR_ARGVAL) { + /* pass pointer to the copy on stack */ + int size = arg_insn->op2; + int align = arg_insn->op3; + + copy_stack_offset += size; + align = IR_MAX((int)sizeof(void*), align); + copy_stack_offset = IR_ALIGNED_SIZE(copy_stack_offset, align); +#ifdef __APPLE__ + if (j > last_named_input) { + | add Rx(tmp_reg), sp, #(used_stack - copy_stack_offset) + ir_emit_store_mem_int(ctx, IR_ADDR, IR_MEM_BO(IR_REG_STACK_POINTER, stack_offset), tmp_reg); + } else +#endif + if (int_param < int_reg_params_count) { + dst_reg = int_reg_params[int_param]; + | add Rx(dst_reg), sp, #(used_stack - copy_stack_offset) + } else { + | add Rx(tmp_reg), sp, #(used_stack - copy_stack_offset) + ir_emit_store_mem_int(ctx, IR_ADDR, IR_MEM_BO(IR_REG_STACK_POINTER, stack_offset), tmp_reg); + stack_offset += sizeof(void*); + } + int_param++; + continue; + } #ifdef __APPLE__ if (j > last_named_input) { dst_reg = IR_REG_NONE; /* pass argument through stack */ @@ -4816,7 +5240,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 +5361,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 +5395,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) } } @@ -4971,6 +5414,19 @@ static void ir_emit_ijmp(ir_ctx *ctx, ir_ref def, ir_insn *insn) } | br Rx(op2_reg) } else if (IR_IS_CONST_REF(insn->op2)) { + if (ctx->ir_base[insn->op2].op == IR_LABEL) { + if (!data->resolved_label_syms) { + data->resolved_label_syms = 1; + ir_resolve_label_syms(ctx); + } + + uint32_t target = ctx->ir_base[insn->op2].val.u32_hi; + target = ir_skip_empty_target_blocks(ctx, target); + + | b =>target + return; + } + void *addr = ir_jmp_addr(ctx, insn, &ctx->ir_base[insn->op2]); if (aarch64_may_use_b(ctx->code_buffer, addr)) { @@ -5122,6 +5578,11 @@ static void ir_emit_guard_jcc(ir_ctx *ctx, uint8_t op, void *addr, bool int_cmp) case IR_GT: | bgt &addr break; + case IR_ORDERED: + | bvc &addr + break; + case IR_UNORDERED: + | bvs &addr // case IR_ULT: fprintf(stderr, "\tjb .LL%d\n", true_block); break; // case IR_UGE: fprintf(stderr, "\tjae .LL%d\n", true_block); break; // case IR_ULE: fprintf(stderr, "\tjbe .LL%d\n", true_block); break; @@ -5356,6 +5817,7 @@ static void ir_emit_param_move(ir_ctx *ctx, uint8_t type, ir_reg from_reg, ir_re { ir_reg fp = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; + offset = IR_SPILL_POS_TO_OFFSET(offset); IR_ASSERT(from_reg != IR_REG_NONE || to_reg != IR_REG_NONE); if (IR_IS_TYPE_INT(type)) { @@ -5396,12 +5858,8 @@ static void ir_emit_load_params(ir_ctx *ctx) const int8_t *int_reg_params = _ir_int_reg_params; const int8_t *fp_reg_params = _ir_fp_reg_params; int32_t stack_offset = 0; + int32_t stack_start = ctx->stack_frame_size; - if (ctx->flags & IR_USE_FRAME_POINTER) { - stack_offset = sizeof(void*) * 2; /* skip old frame pointer and return address */ - } else { - stack_offset = ctx->stack_frame_size + ctx->call_stack_size; - } n = use_list->count; for (i = 0, p = &ctx->use_edges[use_list->refs]; i < n; i++, p++) { use = *p; @@ -5425,12 +5883,9 @@ static void ir_emit_load_params(ir_ctx *ctx) if (ctx->vregs[use]) { dst_reg = IR_REG_NUM(ctx->regs[use][0]); IR_ASSERT(src_reg != IR_REG_NONE || dst_reg != IR_REG_NONE || - stack_offset == ctx->live_intervals[ctx->vregs[use]]->stack_spill_pos + - ((ctx->flags & IR_USE_FRAME_POINTER) ? - -(ctx->stack_frame_size - ctx->stack_frame_alignment) : - ctx->call_stack_size)); + stack_start + stack_offset == ctx->live_intervals[ctx->vregs[use]]->stack_spill_pos); if (src_reg != dst_reg) { - ir_emit_param_move(ctx, insn->type, src_reg, dst_reg, use, stack_offset); + ir_emit_param_move(ctx, insn->type, src_reg, dst_reg, use, stack_start + stack_offset); } if (dst_reg != IR_REG_NONE && IR_REG_SPILLED(ctx->regs[use][0])) { ir_emit_store(ctx, insn->type, use, dst_reg); @@ -5504,14 +5959,8 @@ static void ir_fix_param_spills(ir_ctx *ctx) const int8_t *int_reg_params = _ir_int_reg_params; const int8_t *fp_reg_params = _ir_fp_reg_params; int32_t stack_offset = 0; - int32_t param_stack_size = 0; + int32_t stack_start = ctx->stack_frame_size; - if (ctx->flags & IR_USE_FRAME_POINTER) { - /* skip old frame pointer and return address */ - stack_offset = sizeof(void*) * 2 + (ctx->stack_frame_size - ctx->stack_frame_alignment); - } else { - stack_offset = ctx->stack_frame_size; - } n = use_list->count; for (i = 0, p = &ctx->use_edges[use_list->refs]; i < n; i++, p++) { use = *p; @@ -5538,15 +5987,13 @@ static void ir_fix_param_spills(ir_ctx *ctx) if ((ival->flags & IR_LIVE_INTERVAL_MEM_PARAM) && ival->stack_spill_pos == -1 && (ival->next || ival->reg == IR_REG_NONE)) { - ival->stack_spill_pos = stack_offset; + ival->stack_spill_pos = stack_start + stack_offset; } } if (sizeof(void*) == 8) { stack_offset += sizeof(void*); - param_stack_size += sizeof(void*); } else { stack_offset += IR_MAX(sizeof(void*), ir_type_size[insn->type]); - param_stack_size += IR_MAX(sizeof(void*), ir_type_size[insn->type]); } } } @@ -5554,7 +6001,7 @@ static void ir_fix_param_spills(ir_ctx *ctx) ctx->gp_reg_params = IR_MIN(int_param_num, int_reg_params_count); ctx->fp_reg_params = IR_MIN(fp_param_num, fp_reg_params_count); - ctx->param_stack_size = param_stack_size; + ctx->param_stack_size = stack_offset; } static void ir_allocate_unique_spill_slots(ir_ctx *ctx) @@ -5590,10 +6037,12 @@ 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: case IR_LOOP_END: + case IR_IGOTO_DUP: break; default: def_flags = ir_get_target_constraints(ctx, i, &constraints); @@ -5610,7 +6059,7 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx) IR_REGSET_EXCL(available, reg); ctx->regs[i][0] = reg | IR_REG_SPILL_STORE; } else if (def_flags & IR_USE_MUST_BE_IN_REG) { - if (insn->op == IR_VLOAD + if ((insn->op == IR_VLOAD || insn->op == IR_VLOAD_v) && ctx->live_intervals[ctx->vregs[i]] && ctx->live_intervals[ctx->vregs[i]]->stack_spill_pos != -1 && ir_is_same_mem_var(ctx, i, ctx->ir_base[insn->op2].op3)) { @@ -5650,7 +6099,7 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx) for (i = 0, p = &ctx->use_edges[use_list->refs]; i < n; i++, p++) { use = *p; use_insn = &ctx->ir_base[use]; - if (use_insn->op == IR_VLOAD) { + if (use_insn->op == IR_VLOAD || use_insn->op == IR_VLOAD_v) { if (ctx->vregs[use] && !ctx->live_intervals[ctx->vregs[use]]) { ir_live_interval *ival = ir_arena_alloc(&ctx->arena, sizeof(ir_live_interval)); @@ -5661,7 +6110,7 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx) ival->vreg = ctx->vregs[use]; ival->stack_spill_pos = stack_spill_pos; } - } else if (use_insn->op == IR_VSTORE) { + } else if (use_insn->op == IR_VSTORE || use_insn->op == IR_STORE_v) { if (!IR_IS_CONST_REF(use_insn->op3) && ctx->vregs[use_insn->op3] && !ctx->live_intervals[ctx->vregs[use_insn->op3]]) { @@ -5755,7 +6204,8 @@ static void ir_preallocate_call_stack(ir_ctx *ctx) for (i = 1, insn = ctx->ir_base + 1; i < ctx->insns_count;) { if (insn->op == IR_CALL) { - call_stack_size = ir_call_used_stack(ctx, insn); + int32_t copy_stack; + call_stack_size = ir_call_used_stack(ctx, insn, ©_stack); if (call_stack_size > peak_call_stack_size) { peak_call_stack_size = call_stack_size; } @@ -5797,25 +6247,21 @@ void ir_fix_stack_frame(ir_ctx *ctx) ctx->stack_frame_size = IR_ALIGNED_SIZE(ctx->stack_frame_size, sizeof(void*)); ctx->stack_frame_size += additional_size; - ctx->stack_frame_alignment = 0; ctx->call_stack_size = 0; if (!(ctx->flags & IR_FUNCTION)) { while (IR_ALIGNED_SIZE(ctx->stack_frame_size, 16) != ctx->stack_frame_size) { ctx->stack_frame_size += sizeof(void*); - ctx->stack_frame_alignment += sizeof(void*); } } else { /* Stack must be 16 byte aligned */ if (!(ctx->flags & IR_FUNCTION)) { while (IR_ALIGNED_SIZE(ctx->stack_frame_size, 16) != ctx->stack_frame_size) { ctx->stack_frame_size += sizeof(void*); - ctx->stack_frame_alignment += sizeof(void*); } } else if (ctx->flags & IR_USE_FRAME_POINTER) { while (IR_ALIGNED_SIZE(ctx->stack_frame_size + sizeof(void*) * 2, 16) != ctx->stack_frame_size + sizeof(void*) * 2) { ctx->stack_frame_size += sizeof(void*); - ctx->stack_frame_alignment += sizeof(void*); } } else { if (!(ctx->flags & IR_NO_STACK_COMBINE)) { @@ -5824,7 +6270,6 @@ void ir_fix_stack_frame(ir_ctx *ctx) while (IR_ALIGNED_SIZE(ctx->stack_frame_size + ctx->call_stack_size, 16) != ctx->stack_frame_size + ctx->call_stack_size) { ctx->stack_frame_size += sizeof(void*); - ctx->stack_frame_alignment += sizeof(void*); } } } @@ -5860,6 +6305,8 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr) int ret; void *entry; size_t size; + ir_ref igoto_dup_ref = IR_UNUSED; + uint32_t igoto_dup_block = 0; data.ra_data.unused_slot_4 = 0; data.ra_data.unused_slot_2 = 0; @@ -5867,11 +6314,11 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr) data.ra_data.handled = NULL; data.rodata_label = 0; data.jmp_table_label = 0; + data.resolved_label_syms = 0; ctx->data = &data; if (!ctx->live_intervals) { ctx->stack_frame_size = 0; - ctx->stack_frame_alignment = 0; ctx->call_stack_size = 0; ctx->used_preserved_regs = 0; ir_allocate_unique_spill_slots(ctx); @@ -5893,7 +6340,6 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr) } ctx->stack_frame_size = ctx->fixed_stack_frame_size; ctx->call_stack_size = ctx->fixed_call_stack_size; - ctx->stack_frame_alignment = 0; } Dst = &data.dasm_state; @@ -5903,6 +6349,14 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr) dasm_setup(&data.dasm_state, dasm_actions); /* labels for each block + for each constant + rodata label + jmp_table label + for each entry + exit_table label */ dasm_growpc(&data.dasm_state, ctx->cfg_blocks_count + 1 + ctx->consts_count + 1 + 1 + 1 + ctx->entries_count + 1); + if (data.dasm_state->status != DASM_S_OK) { + IR_ASSERT(data.dasm_state->status == DASM_S_NOMEM); + dasm_free(&data.dasm_state); + ctx->data = NULL; + ctx->status = IR_ERROR_TOO_LARGE; + return NULL; + } + data.emit_constants = ir_bitset_malloc(ctx->consts_count); if (!(ctx->flags & IR_SKIP_PROLOGUE)) { @@ -6095,6 +6549,35 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr) case IR_TAILCALL: ir_emit_tailcall(ctx, i, insn); break; + case IR_IGOTO_DUP: + if (bb->flags & IR_BB_DESSA_MOVES) { + ir_emit_dessa_moves(ctx, b, bb); + } + IR_ASSERT(!igoto_dup_ref && !igoto_dup_block); + igoto_dup_ref = i; + igoto_dup_block = b; + b = ctx->cfg_edges[bb->successors]; + bb = &ctx->cfg_blocks[b]; + i = bb->start; + insn = &ctx->ir_base[i]; + rule = &ctx->rules[i]; + break; + case IR_IGOTO: + if ((ctx->ir_base[insn->op1].op == IR_MERGE || ctx->ir_base[insn->op1].op == IR_LOOP_BEGIN) + && (ctx->rules[ctx->ir_base[insn->op1].op1] & IR_RULE_MASK) == IR_IGOTO_DUP + && igoto_dup_ref) { + ir_emit_ijmp(ctx, i, insn); + b = igoto_dup_block; + bb = &ctx->cfg_blocks[b]; + i = igoto_dup_ref; + insn = &ctx->ir_base[i]; + rule = &ctx->rules[i]; + igoto_dup_block= 0; + igoto_dup_ref = 0; + break; + } + IR_ASSERT(!igoto_dup_ref && !igoto_dup_block); + IR_FALLTHROUGH; case IR_IJMP: ir_emit_ijmp(ctx, i, insn); break; @@ -6105,9 +6588,11 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr) ir_emit_vaddr(ctx, i, insn); break; case IR_VLOAD: + case IR_VLOAD_v: ir_emit_vload(ctx, i, insn); break; case IR_VSTORE: + case IR_VSTORE_v: ir_emit_vstore(ctx, i, insn); break; case IR_RLOAD: @@ -6269,12 +6754,20 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr) return NULL; } + if (data.dasm_state->status != DASM_S_OK) { + IR_ASSERT(data.dasm_state->status == DASM_S_NOMEM); + dasm_free(&data.dasm_state); + ctx->data = NULL; + ctx->status = IR_ERROR_TOO_LARGE; + return NULL; + } + ret = dasm_link(&data.dasm_state, size_ptr); if (ret != DASM_S_OK) { - IR_ASSERT(0); + IR_ASSERT(ret == DASM_S_NOMEM); dasm_free(&data.dasm_state); ctx->data = NULL; - ctx->status = IR_ERROR_LINK; + ctx->status = (ret == DASM_S_NOMEM) ? IR_ERROR_TOO_LARGE : IR_ERROR_LINK; return NULL; } size = *size_ptr; @@ -6346,6 +6839,28 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr) } while (i != 0); } + if ((ctx->flags2 & IR_HAS_BLOCK_ADDR) && ctx->loader && ctx->loader->add_label) { + for (b = 1, bb = &ctx->cfg_blocks[b]; b <= ctx->cfg_blocks_count; bb++, b++) { + ir_insn *insn = &ctx->ir_base[bb->start]; + + if (insn->op == IR_BEGIN && insn->op2) { + IR_ASSERT(ctx->ir_base[insn->op2].op == IR_LABEL); + ctx->ir_base[insn->op2].val.u32_hi = 0; + ctx->loader->add_label(ctx->loader, ir_get_str(ctx, ctx->ir_base[insn->op2].val.str), + (char*)entry + dasm_getpclabel(&data.dasm_state, ir_skip_empty_target_blocks(ctx, b))); + } + } + } else if (data.resolved_label_syms) { + for (b = 1, bb = &ctx->cfg_blocks[b]; b <= ctx->cfg_blocks_count; bb++, b++) { + ir_insn *insn = &ctx->ir_base[bb->start]; + + if (insn->op == IR_BEGIN && insn->op2) { + IR_ASSERT(ctx->ir_base[insn->op2].op == IR_LABEL); + ctx->ir_base[insn->op2].val.u32_hi = 0; + } + } + } + dasm_free(&data.dasm_state); if (ctx->code_buffer) { 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..03add75906553 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), IR_COPY_HARD) +#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)) @@ -544,6 +544,8 @@ extern "C" { #define ir_VLOAD_D(_var) _ir_VLOAD(_ir_CTX, IR_DOUBLE, (_var)) #define ir_VLOAD_F(_var) _ir_VLOAD(_ir_CTX, IR_FLOAT, (_var)) #define ir_VSTORE(_var, _val) _ir_VSTORE(_ir_CTX, (_var), (_val)) +#define ir_VLOAD_v(_type, _var) _ir_VLOAD_v(_ir_CTX, (_type), (_var)) +#define ir_VSTORE_v(_var, _val) _ir_VSTORE_v(_ir_CTX, (_var), (_val)) #define ir_RLOAD(_type, _reg) _ir_RLOAD(_ir_CTX, (_type), (_reg)) #define ir_RLOAD_B(_reg) _ir_RLOAD(_ir_CTX, IR_BOOL, (_reg)) #define ir_RLOAD_U8(_reg) _ir_RLOAD(_ir_CTX, IR_U8, (_reg)) @@ -574,6 +576,8 @@ extern "C" { #define ir_LOAD_D(_addr) _ir_LOAD(_ir_CTX, IR_DOUBLE, (_addr)) #define ir_LOAD_F(_addr) _ir_LOAD(_ir_CTX, IR_FLOAT, (_addr)) #define ir_STORE(_addr, _val) _ir_STORE(_ir_CTX, (_addr), (_val)) +#define ir_LOAD_v(_type, _addr) _ir_LOAD_v(_ir_CTX, (_type), (_addr)) +#define ir_STORE_v(_addr, _val) _ir_STORE_v(_ir_CTX, (_addr), (_val)) #define ir_TLS(_index, _offset) _ir_TLS(_ir_CTX, (_index), (_offset)) #define ir_TRAP() do {_ir_CTX->control = ir_emit1(_ir_CTX, IR_TRAP, _ir_CTX->control);} while (0) @@ -586,6 +590,7 @@ extern "C" { #define ir_VA_END(_list) _ir_VA_END(_ir_CTX, _list) #define ir_VA_COPY(_dst, _src) _ir_VA_COPY(_ir_CTX, _dst, _src) #define ir_VA_ARG(_list, _type) _ir_VA_ARG(_ir_CTX, _type, _list) +#define ir_VA_ARG_EX(_list, _type, s, a) _ir_VA_ARG_EX(_ir_CTX, _type, _list, s, a) #define ir_START() _ir_START(_ir_CTX) #define ir_ENTRY(_src, _num) _ir_ENTRY(_ir_CTX, (_src), (_num)) @@ -603,8 +608,10 @@ 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_IGOTO(_addr) _ir_IGOTO(_ir_CTX, (_addr)) #define ir_IJMP(_addr) _ir_IJMP(_ir_CTX, (_addr)) #define ir_UNREACHABLE() _ir_UNREACHABLE(_ir_CTX) @@ -652,14 +659,19 @@ ir_ref _ir_ALLOCA(ir_ctx *ctx, ir_ref size); void _ir_AFREE(ir_ctx *ctx, ir_ref size); ir_ref _ir_VLOAD(ir_ctx *ctx, ir_type type, ir_ref var); void _ir_VSTORE(ir_ctx *ctx, ir_ref var, ir_ref val); +ir_ref _ir_VLOAD_v(ir_ctx *ctx, ir_type type, ir_ref var); +void _ir_VSTORE_v(ir_ctx *ctx, ir_ref var, ir_ref val); ir_ref _ir_RLOAD(ir_ctx *ctx, ir_type type, ir_ref reg); void _ir_RSTORE(ir_ctx *ctx, ir_ref reg, ir_ref val); ir_ref _ir_LOAD(ir_ctx *ctx, ir_type type, ir_ref addr); void _ir_STORE(ir_ctx *ctx, ir_ref addr, ir_ref val); +ir_ref _ir_LOAD_v(ir_ctx *ctx, ir_type type, ir_ref addr); +void _ir_STORE_v(ir_ctx *ctx, ir_ref addr, ir_ref val); void _ir_VA_START(ir_ctx *ctx, ir_ref list); void _ir_VA_END(ir_ctx *ctx, ir_ref list); void _ir_VA_COPY(ir_ctx *ctx, ir_ref dst, ir_ref src); ir_ref _ir_VA_ARG(ir_ctx *ctx, ir_type type, ir_ref list); +ir_ref _ir_VA_ARG_EX(ir_ctx *ctx, ir_type type, ir_ref list, size_t size, size_t align); void _ir_START(ir_ctx *ctx); void _ir_ENTRY(ir_ctx *ctx, ir_ref src, ir_ref num); void _ir_BEGIN(ir_ctx *ctx, ir_ref src); @@ -682,8 +694,10 @@ 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); +ir_ref _ir_IGOTO(ir_ctx *ctx, ir_ref addr); void _ir_IJMP(ir_ctx *ctx, ir_ref addr); void _ir_GUARD(ir_ctx *ctx, ir_ref condition, ir_ref addr); void _ir_GUARD_NOT(ir_ctx *ctx, ir_ref condition, ir_ref addr); diff --git a/ext/opcache/jit/ir/ir_cfg.c b/ext/opcache/jit/ir/ir_cfg.c index 01532c8ea3e30..46755067b2444 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 IR_NEVER_INLINE 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,38 @@ int ir_build_dominators_tree(ir_ctx *ctx) } } } while (changed); + + /* Build dominators tree */ blocks[1].idom = 0; blocks[1].dom_depth = 0; - /* Construct dominators tree */ + /* Construct children lists sorted by block number */ + for (b = blocks_count, bb = &blocks[b]; b >= 2; b--, bb--) { + ir_block *idom_bb = &blocks[bb->idom]; + bb->dom_depth = 0; + bb->dom_next_child = idom_bb->dom_child; + idom_bb->dom_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 +752,12 @@ 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)) { +slow_case: + ir_list_free(&worklist); + return ir_build_dominators_tree_slow(ctx); + } ir_list_push(&worklist, idom); while (1) { k--; @@ -756,7 +766,9 @@ int ir_build_dominators_tree(ir_ctx *ctx) if (idom < b) { break; } - IR_ASSERT(k > 0); + if (UNEXPECTED(k == 0)) { + goto slow_case; + } ir_list_push(&worklist, idom); } } @@ -784,25 +796,14 @@ int ir_build_dominators_tree(ir_ctx *ctx) } bb->idom = idom; idom_bb = &blocks[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; - } 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; - } + /* Construct children lists sorted by block number */ + for (b = blocks_count, bb = &blocks[b]; b >= 2; b--, bb--) { + ir_block *idom_bb = &blocks[bb->idom]; + bb->dom_next_child = idom_bb->dom_child; + idom_bb->dom_child = b; } blocks[1].idom = 0; @@ -819,11 +820,14 @@ int ir_build_dominators_tree(ir_ctx *ctx) succ_b = ctx->cfg_edges[bb->successors]; if (bb->successors_count != 1) { /* LOOP_END/END may be linked with the following ENTRY by a fake edge */ - IR_ASSERT(bb->successors_count == 2); - if (blocks[succ_b].flags & IR_BB_ENTRY) { + if (bb->successors_count != 2) { + complete = 0; + break; + } else if (blocks[succ_b].flags & IR_BB_ENTRY) { succ_b = ctx->cfg_edges[bb->successors + 1]; - } else { - IR_ASSERT(blocks[ctx->cfg_edges[bb->successors + 1]].flags & IR_BB_ENTRY); + } else if (!(blocks[ctx->cfg_edges[bb->successors + 1]].flags & IR_BB_ENTRY)) { + complete = 0; + break; } } dom_depth = blocks[succ_b].dom_depth;; @@ -921,28 +925,17 @@ static int ir_build_dominators_tree_iterative(ir_ctx *ctx) ir_block *idom_bb = &blocks[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; - } 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; - } + /* Construct children lists sorted by block number */ + for (b = blocks_count, bb = &blocks[b]; b >= 2; b--, bb--) { + ir_block *idom_bb = &blocks[bb->idom]; + bb->dom_next_child = idom_bb->dom_child; + idom_bb->dom_child = b; } return 1; } -#endif static bool ir_dominates(const ir_block *blocks, uint32_t b1, uint32_t b2) { @@ -958,7 +951,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 +976,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 +992,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 +1011,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 +1023,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 +1113,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 +1122,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 +1132,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 +1466,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..ee951291b1b05 100644 --- a/ext/opcache/jit/ir/ir_check.c +++ b/ext/opcache/jit/ir/ir_check.c @@ -36,16 +36,46 @@ void ir_consistency_check(void) IR_ASSERT((IR_UGT ^ 3) == IR_ULT); IR_ASSERT((IR_ULE ^ 3) == IR_UGE); IR_ASSERT((IR_UGE ^ 3) == IR_ULE); + IR_ASSERT((IR_ORDERED ^ 1) == IR_UNORDERED); IR_ASSERT(IR_ADD + 1 == IR_SUB); } -static bool ir_check_use_list(const ir_ctx *ctx, ir_ref from, ir_ref to) +typedef struct { + ir_arena *arena; + ir_bitset *use_set; + ir_bitset *input_set; +} ir_check_ctx; + +static bool ir_check_use_list(ir_check_ctx *check_ctx, const ir_ctx *ctx, ir_ref from, ir_ref to) { ir_ref n, *p; ir_use_list *use_list = &ctx->use_lists[from]; n = use_list->count; + if (n > 16) { + /* Avoid quadratic complexity by maintaining a temporary bit-set */ + ir_bitset set; + + if (!check_ctx->use_set || !(set = check_ctx->use_set[from])) { + if (!check_ctx->arena) { + check_ctx->arena = ir_arena_create(sizeof(ir_arena) + + ctx->insns_count * sizeof(ir_bitset) + + ir_bitset_len(ctx->insns_count) * sizeof(ir_bitset_base_t)); + } + if (!check_ctx->use_set) { + check_ctx->use_set = ir_arena_alloc(&check_ctx->arena, ctx->insns_count * sizeof(ir_bitset)); + memset(check_ctx->use_set, 0, ctx->insns_count * sizeof(ir_bitset)); + } + check_ctx->use_set[from] = set = (ir_bitset)ir_arena_alloc(&check_ctx->arena, + ir_bitset_len(ctx->insns_count) * sizeof(ir_bitset_base_t)); + memset(set, 0, ir_bitset_len(ctx->insns_count) * sizeof(ir_bitset_base_t)); + for (p = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) { + ir_bitset_incl(set, *p); + } + } + return ir_bitset_in(set, to); + } for (p = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) { if (*p == to) { return 1; @@ -54,12 +84,35 @@ static bool ir_check_use_list(const ir_ctx *ctx, ir_ref from, ir_ref to) return 0; } -static bool ir_check_input_list(const ir_ctx *ctx, ir_ref from, ir_ref to) +static bool ir_check_input_list(ir_check_ctx *check_ctx, const ir_ctx *ctx, ir_ref from, ir_ref to) { ir_insn *insn = &ctx->ir_base[to]; ir_ref n, j, *p; n = ir_input_edges_count(ctx, insn); + if (n > 16) { + /* Avoid quadratic complexity by maintaining a temporary bit-set */ + ir_bitset set; + + if (!check_ctx->input_set || !(set = check_ctx->input_set[to])) { + if (!check_ctx->arena) { + check_ctx->arena = ir_arena_create(sizeof(ir_arena) + + ctx->insns_count * sizeof(ir_bitset) + + ir_bitset_len(ctx->insns_count) * sizeof(ir_bitset_base_t)); + } + if (!check_ctx->input_set) { + check_ctx->input_set = ir_arena_alloc(&check_ctx->arena, ctx->insns_count * sizeof(ir_bitset)); + memset(check_ctx->input_set, 0, ctx->insns_count * sizeof(ir_bitset)); + } + check_ctx->input_set[to] = set = (ir_bitset)ir_arena_alloc(&check_ctx->arena, + ir_bitset_len(ctx->insns_count) * sizeof(ir_bitset_base_t)); + memset(set, 0, ir_bitset_len(ctx->insns_count) * sizeof(ir_bitset_base_t)); + for (j = 1, p = insn->ops + 1; j <= n; j++, p++) { + if (*p > 0) ir_bitset_incl(set, *p); + } + } + return ir_bitset_in(set, from); + } for (j = 1, p = insn->ops + 1; j <= n; j++, p++) { if (*p == from) { return 1; @@ -93,6 +146,11 @@ bool ir_check(const ir_ctx *ctx) ir_type type; uint32_t flags; bool ok = 1; + ir_check_ctx check_ctx; + + check_ctx.arena = NULL; + check_ctx.use_set = NULL; + check_ctx.input_set = NULL; for (i = IR_UNUSED + 1, insn = ctx->ir_base + i; i < ctx->insns_count;) { if (insn->op >= IR_LAST_OP) { @@ -213,13 +271,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) { @@ -250,7 +313,7 @@ bool ir_check(const ir_ctx *ctx) } if (ctx->use_lists && use > 0 - && !ir_check_use_list(ctx, use, i)) { + && !ir_check_use_list(&check_ctx, ctx, use, i)) { fprintf(stderr, "ir_base[%d].ops[%d] is not in use list (%d)\n", i, j, use); ok = 0; } @@ -265,7 +328,9 @@ bool ir_check(const ir_ctx *ctx) } break; case IR_LOAD: + case IR_LOAD_v: case IR_STORE: + case IR_STORE_v: type = ctx->ir_base[insn->op2].type; if (type != IR_ADDR && (!IR_IS_TYPE_INT(type) || ir_type_size[type] != ir_type_size[IR_ADDR])) { @@ -275,7 +340,9 @@ bool ir_check(const ir_ctx *ctx) } break; case IR_VLOAD: + case IR_VLOAD_v: case IR_VSTORE: + case IR_VSTORE_v: if (ctx->ir_base[insn->op2].op != IR_VAR) { fprintf(stderr, "ir_base[%d].op2 must be 'VAR' (%s)\n", i, ir_op_name[ctx->ir_base[insn->op2].op]); @@ -308,7 +375,7 @@ bool ir_check(const ir_ctx *ctx) for (p = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) { use = *p; - if (!ir_check_input_list(ctx, i, use)) { + if (!ir_check_input_list(&check_ctx, ctx, i, use)) { fprintf(stderr, "ir_base[%d] is in use list of ir_base[%d]\n", use, i); ok = 0; } @@ -345,6 +412,8 @@ bool ir_check(const ir_ctx *ctx) ok = 0; } break; + case IR_IGOTO: + break; default: /* skip data references */ count = n = use_list->count; @@ -388,6 +457,10 @@ bool ir_check(const ir_ctx *ctx) insn += n; } + if (check_ctx.arena) { + ir_arena_free(check_ctx.arena); + } + // if (!ok) { // ir_dump_codegen(ctx, stderr); // } diff --git a/ext/opcache/jit/ir/ir_dump.c b/ext/opcache/jit/ir/ir_dump.c index 54fddf50ac066..5cc732927d412 100644 --- a/ext/opcache/jit/ir/ir_dump.c +++ b/ext/opcache/jit/ir/ir_dump.c @@ -129,6 +129,11 @@ void ir_dump_dot(const ir_ctx *ctx, const char *name, FILE *f) case IR_OPND_CONTROL_REF: fprintf(f, "\tn%d -> n%d [style=dashed,dir=back,weight=%d];\n", ref, i, REF_WEIGHT); break; + case IR_OPND_LABEL_REF: + if (ref) { + fprintf(f, "\tc%d -> n%d [color=blue,weight=%d];\n", -ref, i, REF_WEIGHT); + } + break; } } } @@ -491,6 +496,8 @@ void ir_dump_codegen(const ir_ctx *ctx, FILE *f) ir_print_proto(ctx, insn->proto, f); } else if (insn->op == IR_SYM) { fprintf(f, "sym(%s)", ir_get_str(ctx, insn->val.name)); + } else if (insn->op == IR_LABEL) { + fprintf(f, "label(%s)", ir_get_str(ctx, insn->val.name)); } else if (insn->op == IR_FUNC_ADDR) { fprintf(f, "func *"); ir_print_const(ctx, insn, f, true); @@ -648,6 +655,12 @@ void ir_dump_codegen(const ir_ctx *ctx, FILE *f) fprintf(f, "%s%d", first ? "(" : ", ", ref); first = 0; break; + case IR_OPND_LABEL_REF: + if (ref) { + IR_ASSERT(IR_IS_CONST_REF(ref)); + fprintf(f, "%sc_%d", first ? "(" : ", ", -ref); + } + break; } } else if (opnd_kind == IR_OPND_NUM) { fprintf(f, "%s%d", first ? "(" : ", ", ref); @@ -660,6 +673,12 @@ void ir_dump_codegen(const ir_ctx *ctx, FILE *f) } if (first) { fprintf(f, ";"); + } else if (ctx->value_params + && insn->op == IR_PARAM + && ctx->value_params[insn->op3 - 1].align) { + fprintf(f, ") ByVal(%d, %d);", + ctx->value_params[insn->op3 - 1].size, + ctx->value_params[insn->op3 - 1].align); } else { fprintf(f, ");"); } diff --git a/ext/opcache/jit/ir/ir_emit.c b/ext/opcache/jit/ir/ir_emit.c index c82655daf48db..847ca375b5bd0 100644 --- a/ext/opcache/jit/ir/ir_emit.c +++ b/ext/opcache/jit/ir/ir_emit.c @@ -32,8 +32,14 @@ do { \ size_t _sz = (sz), _need = (need); \ if (_sz < _need) { \ + size_t _limit = sizeof(t) * DASM_SEC2POS(1); \ + if (_need > _limit) { \ + Dst_REF->status = DASM_S_NOMEM; \ + return; \ + } \ if (_sz < 16) _sz = 16; \ while (_sz < _need) _sz += _sz; \ + if (_sz > _limit) _sz = _limit; \ (p) = (t *)ir_mem_realloc((p), _sz); \ (sz) = _sz; \ } \ @@ -167,11 +173,24 @@ static ir_reg ir_get_param_reg(const ir_ctx *ctx, ir_ref ref) if (insn->op == IR_PARAM) { if (IR_IS_TYPE_INT(insn->type)) { if (use == ref) { +#if defined(IR_TARGET_X64) || defined(IR_TARGET_X86) + if (ctx->value_params && ctx->value_params[insn->op3 - 1].align) { + /* struct passed by value on stack */ + return IR_REG_NONE; + } else +#endif if (int_param < int_reg_params_count) { return int_reg_params[int_param]; } else { return IR_REG_NONE; } +#if defined(IR_TARGET_X64) || defined(IR_TARGET_X86) + } else { + if (ctx->value_params && ctx->value_params[insn->op3 - 1].align) { + /* struct passed by value on stack */ + continue; + } +#endif } int_param++; #ifdef _WIN64 @@ -222,32 +241,33 @@ static int ir_get_args_regs(const ir_ctx *ctx, const ir_insn *insn, int8_t *regs n = insn->inputs_count; n = IR_MIN(n, IR_MAX_REG_ARGS + 2); for (j = 3; j <= n; j++) { - type = ctx->ir_base[ir_insn_op(insn, j)].type; + ir_insn *arg = &ctx->ir_base[ir_insn_op(insn, j)]; + type = arg->type; if (IR_IS_TYPE_INT(type)) { - if (int_param < int_reg_params_count) { + if (int_param < int_reg_params_count && arg->op != IR_ARGVAL) { regs[j] = int_reg_params[int_param]; count = j + 1; + int_param++; +#ifdef _WIN64 + /* WIN64 calling convention use common couter for int and fp registers */ + fp_param++; +#endif } else { regs[j] = IR_REG_NONE; } - int_param++; -#ifdef _WIN64 - /* WIN64 calling convention use common couter for int and fp registers */ - fp_param++; -#endif } else { IR_ASSERT(IR_IS_TYPE_FP(type)); if (fp_param < fp_reg_params_count) { regs[j] = fp_reg_params[fp_param]; count = j + 1; + fp_param++; +#ifdef _WIN64 + /* WIN64 calling convention use common couter for int and fp registers */ + int_param++; +#endif } else { regs[j] = IR_REG_NONE; } - fp_param++; -#ifdef _WIN64 - /* WIN64 calling convention use common couter for int and fp registers */ - int_param++; -#endif } } return count; @@ -309,7 +329,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 +340,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); @@ -404,7 +424,7 @@ typedef struct _ir_common_backend_data { ir_bitset emit_constants; } ir_common_backend_data; -static int ir_const_label(ir_ctx *ctx, ir_ref ref) +static int ir_get_const_label(ir_ctx *ctx, ir_ref ref) { ir_common_backend_data *data = ctx->data; int label = ctx->cfg_blocks_count - ref; @@ -993,11 +1013,16 @@ int ir_match(ir_ctx *ctx) entries_count++; } ctx->rules[start] = IR_SKIPPED | IR_NOP; + if (ctx->ir_base[start].op == IR_BEGIN && ctx->ir_base[start].op2) { + ctx->flags2 |= IR_HAS_BLOCK_ADDR; + } ref = bb->end; if (bb->successors_count == 1) { insn = &ctx->ir_base[ref]; if (insn->op == IR_END || insn->op == IR_LOOP_END) { - ctx->rules[ref] = insn->op; + if (!ctx->rules[ref]) { + ctx->rules[ref] = insn->op; + } ref = prev_ref[ref]; if (ref == start && ctx->cfg_edges[bb->successors] != b) { if (EXPECTED(!(bb->flags & IR_BB_ENTRY))) { diff --git a/ext/opcache/jit/ir/ir_fold.h b/ext/opcache/jit/ir/ir_fold.h index 88539e52ab085..bab6b2916075f 100644 --- a/ext/opcache/jit/ir/ir_fold.h +++ b/ext/opcache/jit/ir/ir_fold.h @@ -274,6 +274,106 @@ IR_FOLD(UGT(C_FLOAT, C_FLOAT)) IR_FOLD_BOOL(!(op1_insn->val.f <= op2_insn->val.f)); } +IR_FOLD(ORDERED(C_FLOAT, C_FLOAT)) +{ + IR_FOLD_BOOL(!isnan(op1_insn->val.f) && !isnan(op2_insn->val.f)); +} + +IR_FOLD(ORDERED(C_DOUBLE, C_DOUBLE)) +{ + IR_FOLD_BOOL(!isnan(op1_insn->val.d) && !isnan(op2_insn->val.d)); +} + +IR_FOLD(UNORDERED(C_FLOAT, C_FLOAT)) +{ + IR_FOLD_BOOL(isnan(op1_insn->val.f) || isnan(op2_insn->val.f)); +} + +IR_FOLD(UNORDERED(C_DOUBLE, C_DOUBLE)) +{ + IR_FOLD_BOOL(isnan(op1_insn->val.d) || isnan(op2_insn->val.d)); +} + +IR_FOLD(EQ(_, C_FLOAT)) +IR_FOLD(LT(_, C_FLOAT)) +IR_FOLD(GE(_, C_FLOAT)) +IR_FOLD(LE(_, C_FLOAT)) +IR_FOLD(GT(_, C_FLOAT)) +{ + if (isnan(op2_insn->val.f)) { + IR_FOLD_COPY(IR_FALSE); + } + IR_FOLD_NEXT; +} + +IR_FOLD(NE(_, C_FLOAT)) +{ + if (isnan(op2_insn->val.f)) { + IR_FOLD_COPY(IR_TRUE); + } + IR_FOLD_NEXT; +} + +IR_FOLD(ORDERED(_, C_FLOAT)) +{ + if (isnan(op2_insn->val.f)) { + IR_FOLD_COPY(IR_FALSE); + } else { + op2 = op1; + IR_FOLD_RESTART; + } +} + +IR_FOLD(UNORDERED(_, C_FLOAT)) +{ + if (isnan(op2_insn->val.f)) { + IR_FOLD_COPY(IR_TRUE); + } else { + op2 = op1; + IR_FOLD_RESTART; + } +} + +IR_FOLD(EQ(_, C_DOUBLE)) +IR_FOLD(LT(_, C_DOUBLE)) +IR_FOLD(GE(_, C_DOUBLE)) +IR_FOLD(LE(_, C_DOUBLE)) +IR_FOLD(GT(_, C_DOUBLE)) +{ + if (isnan(op2_insn->val.d)) { + IR_FOLD_COPY(IR_FALSE); + } + IR_FOLD_NEXT; +} + +IR_FOLD(NE(_, C_DOUBLE)) +{ + if (isnan(op2_insn->val.d)) { + IR_FOLD_COPY(IR_TRUE); + } + IR_FOLD_NEXT; +} + +IR_FOLD(ORDERED(_, C_DOUBLE)) +{ + if (isnan(op2_insn->val.d)) { + IR_FOLD_COPY(IR_FALSE); + } else { + op2 = op1; + IR_FOLD_RESTART; + } +} + +IR_FOLD(UNORDERED(_, C_DOUBLE)) +{ + if (isnan(op2_insn->val.d)) { + IR_FOLD_COPY(IR_TRUE); + } else { + op2 = op1; + IR_FOLD_RESTART; + } +} + IR_FOLD(ADD(C_U8, C_U8)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); @@ -538,7 +638,8 @@ IR_FOLD(DIV(C_ADDR, C_ADDR)) IR_FOLD(DIV(C_I8, C_I8)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - if (op2_insn->val.i64 == 0) { + if (op2_insn->val.i64 == 0 + || (op2_insn->val.i64 == -1 && op1_insn->val.u8 == 0x80)) { /* division by zero */ IR_FOLD_EMIT; } @@ -548,7 +649,8 @@ IR_FOLD(DIV(C_I8, C_I8)) IR_FOLD(DIV(C_I16, C_I16)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - if (op2_insn->val.i64 == 0) { + if (op2_insn->val.i64 == 0 + || (op2_insn->val.i64 == -1 && op1_insn->val.u16 == 0x8000)) { /* division by zero */ IR_FOLD_EMIT; } @@ -558,7 +660,8 @@ IR_FOLD(DIV(C_I16, C_I16)) IR_FOLD(DIV(C_I32, C_I32)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - if (op2_insn->val.i64 == 0) { + if (op2_insn->val.i64 == 0 + || (op2_insn->val.i64 == -1 && op1_insn->val.u32 == 0x80000000)) { /* division by zero */ IR_FOLD_EMIT; } @@ -568,7 +671,8 @@ IR_FOLD(DIV(C_I32, C_I32)) IR_FOLD(DIV(C_I64, C_I64)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - if (op2_insn->val.i64 == 0) { + if (op2_insn->val.i64 == 0 + || (op2_insn->val.i64 == -1 && op1_insn->val.u64 == 0x8000000000000000)) { /* division by zero */ IR_FOLD_EMIT; } @@ -615,12 +719,27 @@ IR_FOLD(MOD(C_I64, C_I64)) } IR_FOLD(NEG(C_I8)) +{ + IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); + IR_FOLD_CONST_I((int8_t)(0 - op1_insn->val.u8)); +} + IR_FOLD(NEG(C_I16)) +{ + IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); + IR_FOLD_CONST_I((int16_t)(0 -op1_insn->val.u16)); +} + IR_FOLD(NEG(C_I32)) +{ + IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); + IR_FOLD_CONST_I((int32_t)(0 - op1_insn->val.u32)); +} + IR_FOLD(NEG(C_I64)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_I(-op1_insn->val.u64); + IR_FOLD_CONST_I(0 - op1_insn->val.u64); } IR_FOLD(NEG(C_DOUBLE)) @@ -636,8 +755,35 @@ IR_FOLD(NEG(C_FLOAT)) } IR_FOLD(ABS(C_I8)) +{ + IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); + if (op1_insn->val.i64 >= 0) { + IR_FOLD_COPY(op1); + } else { + IR_FOLD_CONST_I(-op1_insn->val.i8); + } +} + IR_FOLD(ABS(C_I16)) +{ + IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); + if (op1_insn->val.i64 >= 0) { + IR_FOLD_COPY(op1); + } else { + IR_FOLD_CONST_I(-op1_insn->val.i16); + } +} + IR_FOLD(ABS(C_I32)) +{ + IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); + if (op1_insn->val.i64 >= 0) { + IR_FOLD_COPY(op1); + } else { + IR_FOLD_CONST_I((int32_t)-op1_insn->val.u32); + } +} + IR_FOLD(ABS(C_I64)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); @@ -728,7 +874,7 @@ IR_FOLD(MUL_OV(C_U64, C_U64)) uint64_t res; IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); res = op1_insn->val.u64 * op2_insn->val.u64; - if (op1_insn->val.u64 != 0 && res / op1_insn->val.u64 != op2_insn->val.u64 && res <= max) { + if ((op1_insn->val.u64 != 0 && res / op1_insn->val.u64 != op2_insn->val.u64) || res > max) { IR_FOLD_NEXT; } IR_FOLD_CONST_U(res); @@ -745,7 +891,7 @@ IR_FOLD(MUL_OV(C_I64, C_I64)) int64_t res; IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); res = op1_insn->val.u64 * op2_insn->val.u64; - if (op1_insn->val.i64 != 0 && res / op1_insn->val.i64 != op2_insn->val.i64 && res >= min && res <= max) { + if ((op1_insn->val.i64 != 0 && res / op1_insn->val.i64 != op2_insn->val.i64) || res < min || res > max) { IR_FOLD_NEXT; } IR_FOLD_CONST_U(res); @@ -918,220 +1064,220 @@ IR_FOLD(SHL(C_U8, C_U8)) IR_FOLD(SHL(C_CHAR, C_CHAR)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_U(op1_insn->val.u8 << op2_insn->val.u8); + IR_FOLD_CONST_U(op1_insn->val.u8 << (op2_insn->val.u8 & 0x7)); } 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 & 0x7))); } IR_FOLD(SHL(C_U16, C_U16)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_U(op1_insn->val.u16 << op2_insn->val.u16); + IR_FOLD_CONST_U(op1_insn->val.u16 << (op2_insn->val.u16 & 0xf)); } 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 & 0xf))); } IR_FOLD(SHL(C_U32, C_U32)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_U(op1_insn->val.u32 << op2_insn->val.u32); + IR_FOLD_CONST_U(op1_insn->val.u32 << (op2_insn->val.u32 & 0x1f)); } 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 & 0x1f))); } IR_FOLD(SHL(C_U64, C_U64)) IR_FOLD(SHL(C_I64, C_I64)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_U(op1_insn->val.u64 << op2_insn->val.u64); + IR_FOLD_CONST_U(op1_insn->val.u64 << (op2_insn->val.u64 & 0x3f)); } IR_FOLD(SHR(C_U8, C_U8)) IR_FOLD(SHR(C_CHAR, C_CHAR)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_U(op1_insn->val.u8 >> op2_insn->val.u8); + IR_FOLD_CONST_U(op1_insn->val.u8 >> (op2_insn->val.u8 & 0x7)); } IR_FOLD(SHR(C_I8, C_I8)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_I((int8_t)(op1_insn->val.u8 >> op2_insn->val.u8)); + IR_FOLD_CONST_I((int8_t)(op1_insn->val.u8 >> (op2_insn->val.u8 & 0x7))); } IR_FOLD(SHR(C_U16, C_U16)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_U(op1_insn->val.u16 >> op2_insn->val.u16); + IR_FOLD_CONST_U(op1_insn->val.u16 >> (op2_insn->val.u16 & 0xf)); } 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 & 0xf))); } IR_FOLD(SHR(C_U32, C_U32)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_U(op1_insn->val.u32 >> op2_insn->val.u32); + IR_FOLD_CONST_U(op1_insn->val.u32 >> (op2_insn->val.u32 & 0x1f)); } 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 & 0x1f))); } IR_FOLD(SHR(C_U64, C_U64)) IR_FOLD(SHR(C_I64, C_I64)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_U(op1_insn->val.u64 >> op2_insn->val.u64); + IR_FOLD_CONST_U(op1_insn->val.u64 >> (op2_insn->val.u64 & 0x3f)); } IR_FOLD(SAR(C_U8, C_U8)) IR_FOLD(SAR(C_CHAR, C_CHAR)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_U((uint8_t)(op1_insn->val.i8 >> op2_insn->val.i8)); + IR_FOLD_CONST_U((uint8_t)(op1_insn->val.i8 >> (op2_insn->val.i8 & 0x7))); } IR_FOLD(SAR(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(op1_insn->val.i8 >> (op2_insn->val.i8 & 0x7)); } IR_FOLD(SAR(C_U16, C_U16)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_U((uint16_t)(op1_insn->val.i16 >> op2_insn->val.i16)); + IR_FOLD_CONST_U((uint16_t)(op1_insn->val.i16 >> (op2_insn->val.i16 & 0xf))); } IR_FOLD(SAR(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(op1_insn->val.i16 >> (op2_insn->val.i16 & 0xf)); } IR_FOLD(SAR(C_U32, C_U32)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_U((uint32_t)(op1_insn->val.i32 >> op2_insn->val.i32)); + IR_FOLD_CONST_U((uint32_t)(op1_insn->val.i32 >> (op2_insn->val.i32 & 0x1f))); } IR_FOLD(SAR(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(op1_insn->val.i32 >> (op2_insn->val.i32 & 0x1f)); } IR_FOLD(SAR(C_U64, C_U64)) IR_FOLD(SAR(C_I64, C_I64)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_I(op1_insn->val.i64 >> op2_insn->val.i64); + IR_FOLD_CONST_I(op1_insn->val.i64 >> (op2_insn->val.i64 & 0x3f)); } IR_FOLD(ROL(C_U8, C_U8)) IR_FOLD(ROL(C_CHAR, C_CHAR)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_U(ir_rol8(op1_insn->val.u8, op2_insn->val.u8)); + IR_FOLD_CONST_U(ir_rol8(op1_insn->val.u8, (op2_insn->val.u8 & 0x7))); } IR_FOLD(ROL(C_I8, C_I8)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_I((int8_t)ir_rol8(op1_insn->val.u8, op2_insn->val.u8)); + IR_FOLD_CONST_I((int8_t)ir_rol8(op1_insn->val.u8, (op2_insn->val.u8 & 0x7))); } IR_FOLD(ROL(C_U16, C_U16)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_U(ir_rol16(op1_insn->val.u16, op2_insn->val.u16)); + IR_FOLD_CONST_U(ir_rol16(op1_insn->val.u16, (op2_insn->val.u16 & 0xf))); } IR_FOLD(ROL(C_I16, C_I16)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_I((int16_t)ir_rol16(op1_insn->val.u16, op2_insn->val.u16)); + IR_FOLD_CONST_I((int16_t)ir_rol16(op1_insn->val.u16, (op2_insn->val.u16 & 0xf))); } IR_FOLD(ROL(C_U32, C_U32)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_U(ir_rol32(op1_insn->val.u32, op2_insn->val.u32)); + IR_FOLD_CONST_U(ir_rol32(op1_insn->val.u32, (op2_insn->val.u32 & 0x1f))); } IR_FOLD(ROL(C_I32, C_I32)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_I((int32_t)ir_rol32(op1_insn->val.u32, op2_insn->val.u32)); + IR_FOLD_CONST_I((int32_t)ir_rol32(op1_insn->val.u32, (op2_insn->val.u32 & 0x1f))); } IR_FOLD(ROL(C_U64, C_U64)) IR_FOLD(ROL(C_I64, C_I64)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_U(ir_rol64(op1_insn->val.u64, op2_insn->val.u64)); + IR_FOLD_CONST_U(ir_rol64(op1_insn->val.u64, (op2_insn->val.u64 & 0x3f))); } IR_FOLD(ROR(C_U8, C_U8)) IR_FOLD(ROR(C_CHAR, C_CHAR)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_U(ir_ror8(op1_insn->val.u8, op2_insn->val.u8)); + IR_FOLD_CONST_U(ir_ror8(op1_insn->val.u8, (op2_insn->val.u8 & 0x7))); } IR_FOLD(ROR(C_I8, C_I8)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_I((int8_t)ir_ror8(op1_insn->val.u8, op2_insn->val.u8)); + IR_FOLD_CONST_I((int8_t)ir_ror8(op1_insn->val.u8, (op2_insn->val.u8 & 0x7))); } IR_FOLD(ROR(C_U16, C_U16)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_U(ir_ror16(op1_insn->val.u16, op2_insn->val.u16)); + IR_FOLD_CONST_U(ir_ror16(op1_insn->val.u16, (op2_insn->val.u16 & 0xf))); } IR_FOLD(ROR(C_I16, C_I16)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_I((int16_t)ir_ror16(op1_insn->val.u16, op2_insn->val.u16)); + IR_FOLD_CONST_I((int16_t)ir_ror16(op1_insn->val.u16, (op2_insn->val.u16 & 0xf))); } IR_FOLD(ROR(C_U32, C_U32)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_U(ir_ror32(op1_insn->val.u32, op2_insn->val.u32)); + IR_FOLD_CONST_U(ir_ror32(op1_insn->val.u32, (op2_insn->val.u32 & 0x1f))); } IR_FOLD(ROR(C_I32, C_I32)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_I((int32_t)ir_ror32(op1_insn->val.u32, op2_insn->val.u32)); + IR_FOLD_CONST_I((int32_t)ir_ror32(op1_insn->val.u32, (op2_insn->val.u32 & 0x1f))); } IR_FOLD(ROR(C_U64, C_U64)) IR_FOLD(ROR(C_I64, C_I64)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_U(ir_ror64(op1_insn->val.u64, op2_insn->val.u64)); + IR_FOLD_CONST_U(ir_ror64(op1_insn->val.u64, (op2_insn->val.u64 & 0x3f))); } //IR_FOLD(BSWAP(CONST)) @@ -1273,6 +1419,9 @@ IR_FOLD(TRUNC(C_U64)) IR_FOLD_CONST_U(op1_insn->val.u16); case IR_U32: IR_FOLD_CONST_U(op1_insn->val.u32); + case IR_ADDR: + IR_ASSERT(sizeof(void*) == 4); + IR_FOLD_CONST_U(op1_insn->val.u32); } } @@ -1426,7 +1575,7 @@ IR_FOLD(FP2FP(C_DOUBLE)) IR_FOLD(COPY(_)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - if (!op2) { + if (!(op2 & IR_COPY_HARD)) { IR_FOLD_COPY(op1); } /* skip CSE */ @@ -1626,6 +1775,8 @@ IR_FOLD(NOT(ULT)) IR_FOLD(NOT(UGE)) IR_FOLD(NOT(ULE)) IR_FOLD(NOT(UGT)) +IR_FOLD(NOT(ORDERED)) +IR_FOLD(NOT(UNORDERED)) { if (IR_IS_TYPE_INT(ctx->ir_base[op1_insn->op1].type)) { opt = op1_insn->opt ^ 1; @@ -1703,6 +1854,11 @@ IR_FOLD(SUB_OV(_, C_ADDR)) { if (op2_insn->val.u64 == 0) { /* a +/- 0 => a */ + if (op1_insn->type != IR_OPT_TYPE(opt)) { + opt = IR_BITCAST | (opt & IR_OPT_TYPE_MASK); + op2 = IR_UNUSED; + IR_FOLD_RESTART; + } IR_FOLD_COPY(op1); } IR_FOLD_NEXT; @@ -1721,6 +1877,12 @@ IR_FOLD(ADD(C_ADDR, _)) { if (op1_insn->val.u64 == 0) { /* 0 + a => a */ + if (op2_insn->type != IR_OPT_TYPE(opt)) { + opt = IR_BITCAST | (opt & IR_OPT_TYPE_MASK); + op1 = op2; + op2 = IR_UNUSED; + IR_FOLD_RESTART; + } IR_FOLD_COPY(op2); } IR_FOLD_NEXT; @@ -1830,6 +1992,12 @@ IR_FOLD(ADD(SUB, _)) if (IR_IS_TYPE_INT(IR_OPT_TYPE(opt))) { if (op1_insn->op2 == op2) { /* (a - b) + b => a */ + if (ctx->ir_base[op1_insn->op1].type != IR_OPT_TYPE(opt)) { + opt = IR_BITCAST | (opt & IR_OPT_TYPE_MASK); + op1 = op1_insn->op1; + op2 = IR_UNUSED; + IR_FOLD_RESTART; + } IR_FOLD_COPY(op1_insn->op1); } } @@ -1841,6 +2009,12 @@ IR_FOLD(ADD(_, SUB)) if (IR_IS_TYPE_INT(IR_OPT_TYPE(opt))) { if (op2_insn->op2 == op1) { /* a + (b - a) => b */ + if (ctx->ir_base[op2_insn->op1].type != IR_OPT_TYPE(opt)) { + opt = IR_BITCAST | (opt & IR_OPT_TYPE_MASK); + op1 = op2_insn->op1; + op2 = IR_UNUSED; + IR_FOLD_RESTART; + } IR_FOLD_COPY(op2_insn->op1); } } @@ -1852,9 +2026,21 @@ IR_FOLD(SUB(ADD, _)) if (IR_IS_TYPE_INT(IR_OPT_TYPE(opt))) { if (op1_insn->op1 == op2) { /* (a + b) - a => b */ + if (ctx->ir_base[op1_insn->op2].type != IR_OPT_TYPE(opt)) { + opt = IR_BITCAST | (opt & IR_OPT_TYPE_MASK); + op1 = op1_insn->op2; + op2 = IR_UNUSED; + IR_FOLD_RESTART; + } IR_FOLD_COPY(op1_insn->op2); } else if (op1_insn->op2 == op2) { /* (a + b) - a => b */ + if (ctx->ir_base[op1_insn->op1].type != IR_OPT_TYPE(opt)) { + opt = IR_BITCAST | (opt & IR_OPT_TYPE_MASK); + op1 = op1_insn->op1; + op2 = IR_UNUSED; + IR_FOLD_RESTART; + } IR_FOLD_COPY(op1_insn->op1); } } @@ -1900,6 +2086,12 @@ IR_FOLD(SUB(_, SUB)) if (IR_IS_TYPE_INT(IR_OPT_TYPE(opt))) { if (op2_insn->op1 == op1) { /* a - (a - b) => b */ + if (ctx->ir_base[op2_insn->op2].type != IR_OPT_TYPE(opt)) { + opt = IR_BITCAST | (opt & IR_OPT_TYPE_MASK); + op1 = op2_insn->op2; + op2 = IR_UNUSED; + IR_FOLD_RESTART; + } IR_FOLD_COPY(op2_insn->op2); } } @@ -1909,25 +2101,27 @@ 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; + op1 = _ir_fold_cast(ctx, op1_insn->op2, IR_OPT_TYPE(opt)); + op2 = _ir_fold_cast(ctx, op2_insn->op2, IR_OPT_TYPE(opt)); IR_FOLD_RESTART; } else if (op1_insn->op1 == op2_insn->op2) { /* (a + b) - (c + a) => b - c */ - op1 = op1_insn->op2; - op2 = op2_insn->op1; + op1 = _ir_fold_cast(ctx, op1_insn->op2, IR_OPT_TYPE(opt)); + op2 = _ir_fold_cast(ctx, op2_insn->op1, IR_OPT_TYPE(opt)); IR_FOLD_RESTART; } else if (op1_insn->op2 == op2_insn->op1) { /* (a + b) - (b + c) => a - c */ - op1 = op1_insn->op1; - op2 = op2_insn->op2; + op1 = _ir_fold_cast(ctx, op1_insn->op1, IR_OPT_TYPE(opt)); + op2 = _ir_fold_cast(ctx, op2_insn->op2, IR_OPT_TYPE(opt)); IR_FOLD_RESTART; } else if (op1_insn->op2 == op2_insn->op2) { /* (a + b) - (c + b) => a - c */ - op1 = op1_insn->op1; - op2 = op2_insn->op1; + op1 = _ir_fold_cast(ctx, op1_insn->op1, IR_OPT_TYPE(opt)); + op2 = _ir_fold_cast(ctx, op2_insn->op1, IR_OPT_TYPE(opt)); IR_FOLD_RESTART; } } @@ -2726,7 +2920,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 +2935,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 +2951,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 +2977,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 +3001,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 +3021,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 +3037,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 +3052,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 +3072,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 +3097,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 +3119,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->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) */ @@ -2935,7 +3129,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 +3144,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 +3154,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 +3170,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 +3185,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 +3205,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 +3225,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 +3245,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; @@ -3120,6 +3314,8 @@ IR_FOLD(ADD(SHR, SHL)) /* Swap operands (move lower ref to op2) for better CSE */ IR_FOLD(MUL(_, _)) +IR_FOLD(ORDERED(_, _)) +IR_FOLD(UNORDERED(_, _)) IR_FOLD_NAMED(swap_ops) { if (op1 < op2) { /* move lower ref to op2 */ diff --git a/ext/opcache/jit/ir/ir_gcm.c b/ext/opcache/jit/ir/ir_gcm.c index 8bd6be5d10aa0..e6486ba64a1c5 100644 --- a/ext/opcache/jit/ir/ir_gcm.c +++ b/ext/opcache/jit/ir/ir_gcm.c @@ -361,20 +361,20 @@ static bool ir_split_partially_dead_node(ir_ctx *ctx, ir_ref ref, uint32_t b) while (ir_sparse_set_in(&data->totally_useful, ctx->cfg_blocks[j].idom)) { j = ctx->cfg_blocks[j].idom; } + clone = ir_hashtab_find(&hash, j); + if (clone == IR_INVALID_VAL) { + clone = clones_count++; + ir_hashtab_add(&hash, j, clone); + clones[clone].block = j; + clones[clone].use_count = 0; + clones[clone].use = -1; + } + uses[uses_count].ref = use; + uses[uses_count].block = i; + uses[uses_count].next = clones[clone].use; + clones[clone].use_count++; + clones[clone].use = uses_count++; } - clone = ir_hashtab_find(&hash, j); - if (clone == IR_INVALID_VAL) { - clone = clones_count++; - ir_hashtab_add(&hash, j, clone); - clones[clone].block = j; - clones[clone].use_count = 0; - clones[clone].use = -1; - } - uses[uses_count].ref = use; - uses[uses_count].block = i; - uses[uses_count].next = clones[clone].use; - clones[clone].use_count++; - clones[clone].use = uses_count++; } } @@ -785,6 +785,144 @@ 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 ctx->cfg_map[*p] < b; + } else { + IR_ASSERT(n > 1); + for (; n > 0; p++, n--) { + ir_ref input = *p; + + if (!IR_IS_CONST_REF(input)) { + uint32_t input_b = ctx->cfg_map[input]; + + if (input_b < b) { + /* ordered */ + } else if ((bb->flags & IR_BB_LOOP_HEADER) + && (input_b == b || ctx->cfg_blocks[input_b].loop_header == b)) { + /* back-edge of reducible loop */ + } else if ((bb->flags & IR_BB_IRREDUCIBLE_LOOP) + && (ctx->cfg_blocks[input_b].loop_header == bb->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; @@ -792,86 +930,54 @@ int ir_schedule(ir_ctx *ctx) ir_ref *_xlat; ir_ref *edges; ir_ref prev_b_end; - uint32_t b, prev_b; + uint32_t b; uint32_t *_blocks = ctx->cfg_map; ir_ref *_next = ir_mem_malloc(ctx->insns_count * sizeof(ir_ref)); ir_ref *_prev = ir_mem_malloc(ctx->insns_count * sizeof(ir_ref)); - ir_ref _move_down = 0; 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); - prev_b = 1; - prev_b_end = ctx->cfg_blocks[1].end; + + /* link BB boundaries */ _prev[1] = 0; - _prev[prev_b_end] = 0; - for (i = 2, j = 1; i < ctx->insns_count; i++) { - b = _blocks[i]; - IR_ASSERT((int32_t)b >= 0); - if (b == prev_b && i <= prev_b_end) { - /* add to the end of the list */ - _next[j] = i; - _prev[i] = j; - j = i; - } 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); - /* move down late (see the following loop) */ - _next[i] = _move_down; - _move_down = i; - } - } else if (b) { - bb = &ctx->cfg_blocks[b]; - IR_ASSERT(i != bb->start); - if (_prev[bb->end]) { - /* move up, insert before the end of the already scheduled BB */ - k = bb->end; - } else { - /* move up, insert at the end of the block */ - k = ctx->cfg_blocks[b + 1].start; - } - /* insert before "k" */ - _prev[i] = _prev[k]; - _next[i] = k; - _next[_prev[k]] = i; - _prev[k] = i; + prev_b_end = ctx->cfg_blocks[1].end; + _next[1] = prev_b_end; + _prev[prev_b_end] = 1; + for (b = 2, bb = ctx->cfg_blocks + 2; b <= ctx->cfg_blocks_count; b++, bb++) { + _next[prev_b_end] = bb->start; + _prev[bb->start] = prev_b_end; + _next[bb->start] = bb->end; + _prev[bb->end] = bb->start; + prev_b_end = bb->end; + if (!ir_is_good_bb_order(ctx, b, bb, bb->start)) { + bad_bb_order = 1; } } - _next[j] = 0; + _next[prev_b_end] = 0; - while (_move_down) { - i = _move_down; - _move_down = _next[i]; + /* insert intermediate BB nodes */ + for (i = 2, j = 1; i < ctx->insns_count; i++) { b = _blocks[i]; + if (!b) continue; bb = &ctx->cfg_blocks[b]; - k = _next[bb->start]; - - if (bb->flags & (IR_BB_HAS_PHI|IR_BB_HAS_PI|IR_BB_HAS_PARAM|IR_BB_HAS_VAR)) { - /* insert after the start of the block and all PARAM, VAR, PI, PHI */ - insn = &ctx->ir_base[k]; - while (insn->op == IR_PHI || insn->op == IR_PARAM || insn->op == IR_VAR || insn->op == IR_PI) { - k = _next[k]; - insn = &ctx->ir_base[k]; - } + if (i != bb->start && i != bb->end) { + /* insert before "end" */ + ir_ref n = bb->end; + ir_ref p = _prev[n]; + _prev[i] = p; + _next[i] = n; + _next[p] = i; + _prev[n] = i; } + } - /* insert before "k" */ - _prev[i] = _prev[k]; - _next[i] = k; - _next[_prev[k]] = i; - _prev[k] = i; + if (bad_bb_order) { + ir_fix_bb_order(ctx, _prev, _next); } #ifdef IR_DEBUG @@ -901,9 +1007,18 @@ int ir_schedule(ir_ctx *ctx) start = i = bb->start; _xlat[i] = bb->start = insns_count; insn = &ctx->ir_base[i]; - if (insn->op == IR_CASE_VAL) { + if (insn->op == IR_BEGIN) { + if (insn->op2) { + consts_count += ir_count_constant(_xlat, insn->op2); + } + } else 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); @@ -991,7 +1106,11 @@ int ir_schedule(ir_ctx *ctx) if (end->op == IR_IF) { /* Move condition closer to IF */ input = end->op2; - if (input > 0 && _blocks[input] == b && !_xlat[input] && _prev[j] != input) { + if (input > 0 + && _blocks[input] == b + && !_xlat[input] + && _prev[j] != input + && (!(ir_op_flags[ctx->ir_base[input].op] & IR_OP_FLAG_CONTROL) || end->op1 == input)) { if (input == i) { i = _next[i]; insn = &ctx->ir_base[i]; @@ -1011,6 +1130,7 @@ int ir_schedule(ir_ctx *ctx) ir_ref n, j, *p, input; restart: + IR_ASSERT(_blocks[i] == b); n = insn->inputs_count; for (j = n, p = insn->ops + 1; j > 0; p++, j--) { input = *p; @@ -1044,6 +1164,7 @@ int ir_schedule(ir_ctx *ctx) } _xlat[i] = insns_count; insns_count += ir_insn_inputs_to_len(n); + IR_ASSERT(_next[i] != IR_UNUSED); i = _next[i]; insn = &ctx->ir_base[i]; } @@ -1097,6 +1218,7 @@ int ir_schedule(ir_ctx *ctx) new_ctx.insns_count = insns_count; new_ctx.flags2 = ctx->flags2; new_ctx.ret_type = ctx->ret_type; + new_ctx.value_params = ctx->value_params; new_ctx.mflags = ctx->mflags; new_ctx.spill_base = ctx->spill_base; new_ctx.fixed_stack_red_zone = ctx->fixed_stack_red_zone; @@ -1130,14 +1252,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)); + } else if (new_insn->op == IR_SYM || new_insn->op == IR_STR || new_insn->op == IR_LABEL) { + 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 +1287,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)); + } else if (insn->op == IR_SYM || insn->op == IR_STR || insn->op == IR_LABEL) { + 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 +1364,12 @@ 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 if (new_insn->op == IR_BEGIN && insn->op2) { + new_insn->op2 = _xlat[insn->op2]; } else { new_insn->op2 = insn->op2; } @@ -1257,6 +1385,8 @@ int ir_schedule(ir_ctx *ctx) switch (new_insn->op) { case IR_EQ: case IR_NE: + case IR_ORDERED: + case IR_UNORDERED: case IR_ADD: case IR_MUL: case IR_ADD_OV: @@ -1330,6 +1460,7 @@ int ir_schedule(ir_ctx *ctx) new_ctx.cfg_edges = ctx->cfg_edges; ctx->cfg_blocks = NULL; ctx->cfg_edges = NULL; + ctx->value_params = NULL; ir_code_buffer *saved_code_buffer = ctx->code_buffer; ir_free(ctx); diff --git a/ext/opcache/jit/ir/ir_private.h b/ext/opcache/jit/ir/ir_private.h index 69a0101d24ee2..dbacc3967d0f7 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) @@ -237,6 +238,7 @@ IR_ALWAYS_INLINE ir_arena* ir_arena_create(size_t size) IR_ASSERT(size >= IR_ALIGNED_SIZE(sizeof(ir_arena), 8)); arena = (ir_arena*)ir_mem_malloc(size); + if (UNEXPECTED(!arena))return NULL; arena->ptr = (char*) arena + IR_ALIGNED_SIZE(sizeof(ir_arena), 8); arena->end = (char*) arena + size; arena->prev = NULL; @@ -257,7 +259,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 = @@ -266,6 +268,7 @@ IR_ALWAYS_INLINE void* ir_arena_alloc(ir_arena **arena_ptr, size_t size) (size_t)(arena->end - (char*) arena); ir_arena *new_arena = (ir_arena*)ir_mem_malloc(arena_size); + if (UNEXPECTED(!new_arena)) return NULL; ptr = (char*) new_arena + IR_ALIGNED_SIZE(sizeof(ir_arena), 8); new_arena->ptr = (char*) new_arena + IR_ALIGNED_SIZE(sizeof(ir_arena), 8) + size; new_arena->end = (char*) new_arena + arena_size; @@ -884,7 +887,7 @@ void ir_print_escaped_str(const char *s, size_t len, FILE *f); #define IR_IS_CONST_OP(op) ((op) > IR_NOP && (op) <= IR_C_FLOAT) #define IR_IS_FOLDABLE_OP(op) ((op) <= IR_LAST_FOLDABLE_OP) -#define IR_IS_SYM_CONST(op) ((op) == IR_STR || (op) == IR_SYM || (op) == IR_FUNC) +#define IR_IS_SYM_CONST(op) ((op) == IR_STR || (op) == IR_SYM || (op) == IR_FUNC || (op) == IR_LABEL) ir_ref ir_const_ex(ir_ctx *ctx, ir_val val, uint8_t type, uint32_t optx); @@ -943,12 +946,13 @@ IR_ALWAYS_INLINE bool ir_ref_is_true(ir_ctx *ctx, ir_ref ref) #define IR_OPND_UNUSED 0x0 #define IR_OPND_DATA 0x1 #define IR_OPND_CONTROL 0x2 -#define IR_OPND_CONTROL_DEP 0x3 -#define IR_OPND_CONTROL_REF 0x4 -#define IR_OPND_STR 0x5 -#define IR_OPND_NUM 0x6 -#define IR_OPND_PROB 0x7 -#define IR_OPND_PROTO 0x8 +#define IR_OPND_LABEL_REF 0x3 +#define IR_OPND_CONTROL_DEP 0x4 +#define IR_OPND_CONTROL_REF 0x5 +#define IR_OPND_STR 0x6 +#define IR_OPND_NUM 0x7 +#define IR_OPND_PROB 0x8 +#define IR_OPND_PROTO 0x9 #define IR_OP_FLAGS(op_flags, op1_flags, op2_flags, op3_flags) \ ((op_flags) | ((op1_flags) << 20) | ((op2_flags) << 24) | ((op3_flags) << 28)) @@ -1010,6 +1014,7 @@ IR_ALWAYS_INLINE uint32_t ir_insn_len(const ir_insn *insn) #define IR_HAS_VA_ARG_FP (1<<9) #define IR_HAS_FP_RET_SLOT (1<<10) #define IR_16B_FRAME_ALIGNMENT (1<<11) +#define IR_HAS_BLOCK_ADDR (1<<12) /* Temporary: MEM2SSA -> SCCP */ #define IR_MEM2SSA_VARS (1<<25) @@ -1245,11 +1250,10 @@ struct _ir_live_range { #define IR_LIVE_INTERVAL_HAS_HINT_REGS (1<<2) #define IR_LIVE_INTERVAL_HAS_HINT_REFS (1<<3) #define IR_LIVE_INTERVAL_MEM_PARAM (1<<4) -#define IR_LIVE_INTERVAL_MEM_LOAD (1<<5) -#define IR_LIVE_INTERVAL_COALESCED (1<<6) -#define IR_LIVE_INTERVAL_SPILL_SPECIAL (1<<7) /* spill slot is pre-allocated in a special area (see ir_ctx.spill_reserved_base) */ -#define IR_LIVE_INTERVAL_SPILLED (1<<8) -#define IR_LIVE_INTERVAL_SPLIT_CHILD (1<<9) +#define IR_LIVE_INTERVAL_COALESCED (1<<5) +#define IR_LIVE_INTERVAL_SPILL_SPECIAL (1<<6) /* spill slot is pre-allocated in a special area (see ir_ctx.spill_reserved_base) */ +#define IR_LIVE_INTERVAL_SPILLED (1<<7) +#define IR_LIVE_INTERVAL_SPLIT_CHILD (1<<8) struct _ir_live_interval { uint8_t type; diff --git a/ext/opcache/jit/ir/ir_ra.c b/ext/opcache/jit/ir/ir_ra.c index 0c0e8dec3b47a..2e8a8e3f34f3f 100644 --- a/ext/opcache/jit/ir/ir_ra.c +++ b/ext/opcache/jit/ir/ir_ra.c @@ -776,9 +776,6 @@ int ir_compute_live_ranges(ir_ctx *ctx) if (insn->op == IR_PARAM) { /* We may reuse parameter stack slot for spilling */ ctx->live_intervals[v]->flags |= IR_LIVE_INTERVAL_MEM_PARAM; - } else if (insn->op == IR_VLOAD) { - /* Load may be fused into the usage instruction */ - ctx->live_intervals[v]->flags |= IR_LIVE_INTERVAL_MEM_LOAD; } def_pos = IR_DEF_LIVE_POS_FROM_REF(ref); } @@ -845,11 +842,17 @@ int ir_compute_live_ranges(ir_ctx *ctx) ival = ctx->live_intervals[v]; } ir_add_use(ctx, ival, j, use_pos, reg, IR_USE_FLAGS(def_flags, j), hint_ref); - } else if (ctx->rules) { - if (ctx->rules[input] & IR_FUSED) { - ir_add_fusion_ranges(ctx, ref, input, bb, live); - } else if (ctx->rules[input] == (IR_SKIPPED|IR_RLOAD)) { - ir_set_alocated_reg(ctx, ref, j, ctx->ir_base[input].op2); + } else { + if (ctx->rules) { + if ((ctx->rules[input] & (IR_FUSED|IR_SKIPPED)) == IR_FUSED) { + ir_add_fusion_ranges(ctx, ref, input, bb, live); + } else if (ctx->rules[input] == (IR_SKIPPED|IR_RLOAD)) { + ir_set_alocated_reg(ctx, ref, j, ctx->ir_base[input].op2); + } + } + if (reg != IR_REG_NONE) { + use_pos = IR_LOAD_LIVE_POS_FROM_REF(ref); + ir_add_fixed_live_range(ctx, reg, use_pos, use_pos + IR_USE_SUB_REF); } } } else if (reg != IR_REG_NONE) { @@ -1193,7 +1196,7 @@ static void ir_add_fusion_ranges(ir_ctx *ctx, ir_ref ref, ir_ref input, ir_block n = IR_INPUT_EDGES_COUNT(flags); j = 1; p = insn->ops + j; - if (flags & IR_OP_FLAG_CONTROL) { + if (flags & (IR_OP_FLAG_CONTROL|IR_OP_FLAG_PINNED)) { j++; p++; } @@ -1340,7 +1343,7 @@ int ir_compute_live_ranges(ir_ctx *ctx) || (ctx->rules[ref] & IR_RULE_MASK) == IR_ALLOCA) && ctx->use_lists[ref].count > 0) { insn = &ctx->ir_base[ref]; - if (insn->op != IR_VADDR) { + if (insn->op != IR_VADDR && insn->op != IR_PARAM) { insn->op3 = ctx->vars; ctx->vars = ref; } @@ -1396,9 +1399,6 @@ int ir_compute_live_ranges(ir_ctx *ctx) if (insn->op == IR_PARAM) { /* We may reuse parameter stack slot for spilling */ ctx->live_intervals[v]->flags |= IR_LIVE_INTERVAL_MEM_PARAM; - } else if (insn->op == IR_VLOAD) { - /* Load may be fused into the usage instruction */ - ctx->live_intervals[v]->flags |= IR_LIVE_INTERVAL_MEM_LOAD; } def_pos = IR_DEF_LIVE_POS_FROM_REF(ref); } @@ -1465,17 +1465,17 @@ int ir_compute_live_ranges(ir_ctx *ctx) ival = ctx->live_intervals[v]; } ir_add_use(ctx, ival, j, use_pos, reg, IR_USE_FLAGS(def_flags, j), hint_ref); - } else if (ctx->rules) { - if (ctx->rules[input] & IR_FUSED) { - ir_add_fusion_ranges(ctx, ref, input, bb, live_in_block, b); - } else { - if (ctx->rules[input] == (IR_SKIPPED|IR_RLOAD)) { + } else { + if (ctx->rules) { + if ((ctx->rules[input] & (IR_FUSED|IR_SKIPPED)) == IR_FUSED) { + ir_add_fusion_ranges(ctx, ref, input, bb, live_in_block, b); + } else if (ctx->rules[input] == (IR_SKIPPED|IR_RLOAD)) { ir_set_alocated_reg(ctx, ref, j, ctx->ir_base[input].op2); } - if (reg != IR_REG_NONE) { - use_pos = IR_LOAD_LIVE_POS_FROM_REF(ref); - ir_add_fixed_live_range(ctx, reg, use_pos, use_pos + IR_USE_SUB_REF); - } + } + if (reg != IR_REG_NONE) { + use_pos = IR_LOAD_LIVE_POS_FROM_REF(ref); + ir_add_fixed_live_range(ctx, reg, use_pos, use_pos + IR_USE_SUB_REF); } } } else if (reg != IR_REG_NONE) { @@ -1605,7 +1605,7 @@ static void ir_vregs_join(ir_ctx *ctx, uint32_t r1, uint32_t r2) } while (*prev && ((*prev)->pos < use_pos->pos || ((*prev)->pos == use_pos->pos && - (use_pos->op_num == 0 || (*prev)->op_num < use_pos->op_num)))) { + (use_pos->op_num == 0 || ((*prev)->op_num != 0 && (*prev)->op_num < use_pos->op_num))))) { if ((*prev)->hint_ref > 0 && ctx->vregs[(*prev)->hint_ref] == r2) { (*prev)->hint_ref = 0; } @@ -1627,8 +1627,9 @@ static void ir_vregs_join(ir_ctx *ctx, uint32_t r1, uint32_t r2) ctx->live_intervals[r1]->flags |= IR_LIVE_INTERVAL_COALESCED | (ival->flags & (IR_LIVE_INTERVAL_HAS_HINT_REGS|IR_LIVE_INTERVAL_HAS_HINT_REFS)); - if (ctx->ir_base[IR_LIVE_POS_TO_REF(ctx->live_intervals[r1]->use_pos->pos)].op != IR_VLOAD) { - ctx->live_intervals[r1]->flags &= ~IR_LIVE_INTERVAL_MEM_LOAD; + if (ival->flags & IR_LIVE_INTERVAL_MEM_PARAM) { + IR_ASSERT(!(ctx->live_intervals[r1]->flags & IR_LIVE_INTERVAL_MEM_PARAM)); + ctx->live_intervals[r1]->flags |= IR_LIVE_INTERVAL_MEM_PARAM; } ctx->live_intervals[r2] = NULL; @@ -2339,16 +2340,6 @@ static ir_live_pos ir_first_use_pos_after(ir_live_interval *ival, ir_live_pos po return p ? p->pos : 0x7fffffff; } -static ir_live_pos ir_first_use_pos(ir_live_interval *ival, uint8_t flags) -{ - ir_use_pos *p = ival->use_pos; - - while (p && !(p->flags & flags)) { - p = p->next; - } - return p ? p->pos : 0x7fffffff; -} - static ir_block *ir_block_from_live_pos(ir_ctx *ctx, ir_live_pos pos) { ir_ref ref = IR_LIVE_POS_TO_REF(pos); @@ -3190,7 +3181,6 @@ static ir_reg ir_allocate_blocked_reg(ir_ctx *ctx, ir_live_interval *ival, ir_li /* split current before its first use position that requires a register */ ir_live_pos split_pos; -spill_current: if (next_use_pos == ival->range.start) { IR_ASSERT(ival->use_pos && ival->use_pos->op_num == 0); /* split right after definition */ @@ -3224,7 +3214,6 @@ static ir_reg ir_allocate_blocked_reg(ir_ctx *ctx, ir_live_interval *ival, ir_li return IR_REG_NONE; } if (split_pos >= blockPos[reg]) { -try_next_available_register: IR_REGSET_EXCL(available, reg); if (IR_REGSET_IS_EMPTY(available)) { fprintf(stderr, "LSRA Internal Error: Unsolvable conflict. Allocation is not possible\n"); @@ -3270,23 +3259,6 @@ static ir_reg ir_allocate_blocked_reg(ir_ctx *ctx, ir_live_interval *ival, ir_li } IR_LOG_LSRA(" ---- Finish", other, ""); } else { - if (ir_first_use_pos(other, IR_USE_MUST_BE_IN_REG) <= other->end) { - if (!(ival->flags & IR_LIVE_INTERVAL_TEMP)) { - next_use_pos = ir_first_use_pos(ival, IR_USE_MUST_BE_IN_REG); - if (next_use_pos == ival->range.start) { - IR_ASSERT(ival->use_pos && ival->use_pos->op_num == 0); - /* split right after definition */ - split_pos = next_use_pos + 1; - } else { - split_pos = ir_find_optimal_split_position(ctx, ival, ival->range.start, next_use_pos - 1, 1); - } - - if (split_pos > ival->range.start) { - goto spill_current; - } - } - goto try_next_available_register; - } child = other; other->reg = IR_REG_NONE; if (prev) { @@ -3396,12 +3368,13 @@ static int ir_fix_dessa_tmps(ir_ctx *ctx, uint8_t type, ir_ref from, ir_ref to) static bool ir_ival_spill_for_fuse_load(ir_ctx *ctx, ir_live_interval *ival, ir_reg_alloc_data *data) { ir_use_pos *use_pos = ival->use_pos; - ir_insn *insn; if (ival->flags & IR_LIVE_INTERVAL_MEM_PARAM) { IR_ASSERT(!ival->next && use_pos && use_pos->op_num == 0); - insn = &ctx->ir_base[IR_LIVE_POS_TO_REF(use_pos->pos)]; +#if IR_DEBUG + ir_insn *insn = &ctx->ir_base[IR_LIVE_POS_TO_REF(use_pos->pos)]; IR_ASSERT(insn->op == IR_PARAM); +#endif use_pos = use_pos->next; if (use_pos && (use_pos->next || (use_pos->flags & IR_USE_MUST_BE_IN_REG))) { return 0; @@ -3414,38 +3387,6 @@ static bool ir_ival_spill_for_fuse_load(ir_ctx *ctx, ir_live_interval *ival, ir_ } } - return 1; - } else if (ival->flags & IR_LIVE_INTERVAL_MEM_LOAD) { - insn = &ctx->ir_base[IR_LIVE_POS_TO_REF(use_pos->pos)]; - IR_ASSERT(insn->op == IR_VLOAD); - IR_ASSERT(ctx->ir_base[insn->op2].op == IR_VAR); - use_pos = use_pos->next; - if (use_pos && (use_pos->next || (use_pos->flags & IR_USE_MUST_BE_IN_REG))) { - return 0; - } - - if (use_pos) { - ir_block *bb = ir_block_from_live_pos(ctx, use_pos->pos); - if (bb->loop_depth && bb != ir_block_from_live_pos(ctx, ival->use_pos->pos)) { - return 0; - } - /* check if VAR may be clobbered between VLOAD and use */ - ir_use_list *use_list = &ctx->use_lists[insn->op2]; - ir_ref n = use_list->count; - ir_ref *p = &ctx->use_edges[use_list->refs]; - for (; n > 0; p++, n--) { - ir_ref use = *p; - if (ctx->ir_base[use].op == IR_VSTORE) { - if (use > IR_LIVE_POS_TO_REF(ival->use_pos->pos) && use < IR_LIVE_POS_TO_REF(use_pos->pos)) { - return 0; - } - } else if (ctx->ir_base[use].op == IR_VADDR) { - return 0; - } - } - } - ival->stack_spill_pos = ctx->ir_base[insn->op2].op3; - return 1; } return 0; @@ -3550,7 +3491,7 @@ static int ir_linear_scan(ir_ctx *ctx) for (j = ctx->vregs_count; j != 0; j--) { ival = ctx->live_intervals[j]; if (ival) { - if (!(ival->flags & (IR_LIVE_INTERVAL_MEM_PARAM|IR_LIVE_INTERVAL_MEM_LOAD)) + if (!(ival->flags & IR_LIVE_INTERVAL_MEM_PARAM) || !ir_ival_spill_for_fuse_load(ctx, ival, &data)) { ir_add_to_unhandled(&unhandled, ival); } diff --git a/ext/opcache/jit/ir/ir_save.c b/ext/opcache/jit/ir/ir_save.c index b12cc267af607..dd955172950c8 100644 --- a/ext/opcache/jit/ir/ir_save.c +++ b/ext/opcache/jit/ir/ir_save.c @@ -10,31 +10,40 @@ void ir_print_proto(const ir_ctx *ctx, ir_ref func_proto, FILE *f) { - ir_ref j; - if (func_proto) { const ir_proto_t *proto = (const ir_proto_t *)ir_get_str(ctx, func_proto); + ir_print_proto_ex(proto->flags, proto->ret_type, proto->params_count, proto->param_types, f); + } else { + fprintf(f, "(): int32_t"); + } +} - fprintf(f, "("); - if (proto->params_count > 0) { - fprintf(f, "%s", ir_type_cname[proto->param_types[0]]); - for (j = 1; j < proto->params_count; j++) { - fprintf(f, ", %s", ir_type_cname[proto->param_types[j]]); - } - if (proto->flags & IR_VARARG_FUNC) { - fprintf(f, ", ..."); - } - } else if (proto->flags & IR_VARARG_FUNC) { - fprintf(f, "..."); +void ir_print_proto_ex(uint8_t flags, ir_type ret_type, uint32_t params_count, const uint8_t *param_types, FILE *f) +{ + uint32_t j; + + fprintf(f, "("); + if (params_count > 0) { + fprintf(f, "%s", ir_type_cname[param_types[0]]); + for (j = 1; j < params_count; j++) { + fprintf(f, ", %s", ir_type_cname[param_types[j]]); } - fprintf(f, "): %s", ir_type_cname[proto->ret_type]); - if (proto->flags & IR_FASTCALL_FUNC) { - fprintf(f, " __fastcall"); - } else if (proto->flags & IR_BUILTIN_FUNC) { - fprintf(f, " __builtin"); + if (flags & IR_VARARG_FUNC) { + fprintf(f, ", ..."); } - } else { - fprintf(f, "(): int32_t"); + } else if (flags & IR_VARARG_FUNC) { + fprintf(f, "..."); + } + fprintf(f, "): %s", ir_type_cname[ret_type]); + if (flags & IR_FASTCALL_FUNC) { + fprintf(f, " __fastcall"); + } else if (flags & IR_BUILTIN_FUNC) { + fprintf(f, " __builtin"); + } + if (flags & IR_CONST_FUNC) { + fprintf(f, " __const"); + } else if (flags & IR_PURE_FUNC) { + fprintf(f, " __pure"); } } @@ -97,10 +106,18 @@ 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_LABEL) { + fprintf(f, "label(%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 +157,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; @@ -261,6 +281,13 @@ void ir_save(const ir_ctx *ctx, uint32_t save_flags, FILE *f) fprintf(f, "%s%d", first ? "(" : ", ", ref); first = 0; break; + case IR_OPND_LABEL_REF: + if (ref) { + IR_ASSERT(IR_IS_CONST_REF(ref)); + fprintf(f, "%sc_%d", first ? "(" : ", ", -ref); + first = 0; + } + break; } } else if (opnd_kind == IR_OPND_NUM) { fprintf(f, "%s%d", first ? "(" : ", ", ref); @@ -273,6 +300,12 @@ void ir_save(const ir_ctx *ctx, uint32_t save_flags, FILE *f) } if (first) { fprintf(f, ";"); + } else if (ctx->value_params + && insn->op == IR_PARAM + && ctx->value_params[insn->op3 - 1].align) { + fprintf(f, ") ByVal(%d, %d);", + ctx->value_params[insn->op3 - 1].size, + ctx->value_params[insn->op3 - 1].align); } else { fprintf(f, ");"); } diff --git a/ext/opcache/jit/ir/ir_sccp.c b/ext/opcache/jit/ir/ir_sccp.c index 2e006516df818..e2f38a058aeba 100644 --- a/ext/opcache/jit/ir/ir_sccp.c +++ b/ext/opcache/jit/ir/ir_sccp.c @@ -12,6 +12,8 @@ #include "ir.h" #include "ir_private.h" +#include + #define IR_COMBO_COPY_PROPAGATION 1 #define IR_TOP IR_UNUSED @@ -420,11 +422,12 @@ static bool ir_is_dead_load_ex(ir_ctx *ctx, ir_ref ref, uint32_t flags, ir_insn static bool ir_is_dead_load(ir_ctx *ctx, ir_ref ref) { if (ctx->use_lists[ref].count == 1) { - uint32_t flags = ir_op_flags[ctx->ir_base[ref].op]; + ir_insn *insn = &ctx->ir_base[ref]; + uint32_t flags = ir_op_flags[insn->op]; if ((flags & (IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_MASK)) == (IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_LOAD)) { return 1; - } else if (ctx->ir_base[ref].op == IR_ALLOCA) { + } else if (insn->op == IR_ALLOCA || insn->op == IR_BLOCK_BEGIN) { return 1; } } @@ -458,6 +461,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) { @@ -567,6 +586,15 @@ static IR_NEVER_INLINE void ir_sccp_analyze(ir_ctx *ctx, ir_insn *_values, ir_bi } } else { IR_MAKE_BOTTOM_EX(i); + n = IR_INPUT_EDGES_COUNT(flags); + for (p = insn->ops + 1; n > 0; p++, n--) { + ir_ref input = *p; + if (input > 0) { + if (_values[input].op == IR_TOP) { + ir_sccp_add_input(ctx, _values, worklist, input); + } + } + } } } else if (flags & IR_OP_FLAG_BB_START) { if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN || insn->op == IR_BEGIN) { @@ -676,6 +704,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) { @@ -696,52 +729,32 @@ static IR_NEVER_INLINE void ir_sccp_analyze(ir_ctx *ctx, ir_insn *_values, ir_bi ir_bitqueue_add(iter_worklist, i); IR_MAKE_BOTTOM(i); } else { - if (_values[i].op == IR_TOP) { - bool has_top = 0; - - /* control, call, load and store instructions may have unprocessed inputs */ - n = IR_INPUT_EDGES_COUNT(flags); - if (IR_OP_HAS_VAR_INPUTS(flags) && (n = insn->inputs_count) > 3) { - for (j = 0; j < (n>>2); j++) { - _values[i+j+1].optx = IR_BOTTOM; /* keep the tail of a long multislot instruction */ - } - for (j = 2, p = insn->ops + j; j <= n; j++, p++) { - IR_ASSERT(IR_OPND_KIND(flags, j) == IR_OPND_DATA); - use = *p; - if (use > 0 && _values[use].op == IR_TOP) { - has_top = 1; - ir_sccp_add_input(ctx, _values, worklist, use); - } - } - } else if (n >= 2) { - IR_ASSERT(IR_OPND_KIND(flags, 2) == IR_OPND_DATA); - use = insn->op2; + /* control, call, load and store instructions may have unprocessed inputs */ + n = IR_INPUT_EDGES_COUNT(flags); + if (IR_OP_HAS_VAR_INPUTS(flags) && (n = insn->inputs_count) > 3) { + for (j = 0; j < (n>>2); j++) { + _values[i+j+1].optx = IR_BOTTOM; /* keep the tail of a long multislot instruction */ + } + for (j = 2, p = insn->ops + j; j <= n; j++, p++) { + IR_ASSERT(IR_OPND_KIND(flags, j) == IR_OPND_DATA); + use = *p; if (use > 0 && _values[use].op == IR_TOP) { - has_top = 1; ir_sccp_add_input(ctx, _values, worklist, use); } - if (n > 2) { - IR_ASSERT(n == 3); - IR_ASSERT(IR_OPND_KIND(flags, 3) == IR_OPND_DATA); - use = insn->op3; - if (use > 0 && _values[use].op == IR_TOP) { - has_top = 1; - ir_sccp_add_input(ctx, _values, worklist, use); - } - } } - - if (has_top && !(flags & IR_OP_FLAG_BB_END)) { - use = ir_next_control(ctx, i); - if (_values[use].op == IR_TOP) { - has_top = 1; - /* do forward control propagaton only once */ - if (!_values[use].op1) { - _values[use].op1 = 1; - ir_bitqueue_add(worklist, use); - } + } else if (n >= 2) { + IR_ASSERT(IR_OPND_KIND(flags, 2) == IR_OPND_DATA); + use = insn->op2; + if (use > 0 && _values[use].op == IR_TOP) { + ir_sccp_add_input(ctx, _values, worklist, use); + } + if (n > 2) { + IR_ASSERT(n == 3); + IR_ASSERT(IR_OPND_KIND(flags, 3) == IR_OPND_DATA); + use = insn->op3; + if (use > 0 && _values[use].op == IR_TOP) { + ir_sccp_add_input(ctx, _values, worklist, use); } - continue; } } IR_MAKE_BOTTOM(i); @@ -1304,8 +1317,8 @@ static ir_ref ir_iter_find_cse(ir_ctx *ctx, ir_ref ref, uint32_t opt, ir_ref op1 } } } else if (n < 2) { - IR_ASSERT(n == 1); - if (!IR_IS_CONST_REF(op1)) { + if (op1 > 0) { + IR_ASSERT(n == 1); use_list = &ctx->use_lists[op1]; n = use_list->count; for (p = ctx->use_edges + use_list->refs; n > 0; p++, n--) { @@ -1495,8 +1508,8 @@ static bool ir_may_promote_f2d(ir_ctx *ctx, ir_ref ref) switch (insn->op) { case IR_FP2FP: return 1; - case IR_INT2FP: - return ctx->use_lists[ref].count == 1; +// case IR_INT2FP: +// return ctx->use_lists[ref].count == 1; case IR_NEG: case IR_ABS: return ctx->use_lists[ref].count == 1 && @@ -1732,7 +1745,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) { @@ -1841,6 +1867,7 @@ static ir_ref ir_ext_const(ir_ctx *ctx, ir_insn *val_insn, ir_op op, ir_type typ case IR_I8: case IR_U8: case IR_BOOL: + case IR_CHAR: if (op == IR_SEXT) { new_val.i64 = (int64_t)val_insn->val.i8; } else { @@ -1894,7 +1921,7 @@ static ir_ref ir_ext_ref(ir_ctx *ctx, ir_ref var_ref, ir_ref src_ref, ir_op op, return ref; } -static uint32_t _ir_estimated_control(ir_ctx *ctx, ir_ref val) +static uint32_t _ir_estimated_control(ir_ctx *ctx, ir_ref val, ir_ref loop) { ir_insn *insn; ir_ref n, *p, input, result, ctrl; @@ -1919,7 +1946,8 @@ static uint32_t _ir_estimated_control(ir_ctx *ctx, ir_ref val) result = 1; for (; n > 0; p++, n--) { input = *p; - ctrl = _ir_estimated_control(ctx, input); + ctrl = _ir_estimated_control(ctx, input, loop); + if (ctrl >= loop) return ctrl; if (ctrl > result) { // TODO: check dominance depth instead of order result = ctrl; } @@ -1929,7 +1957,7 @@ static uint32_t _ir_estimated_control(ir_ctx *ctx, ir_ref val) static bool ir_is_loop_invariant(ir_ctx *ctx, ir_ref ref, ir_ref loop) { - ref = _ir_estimated_control(ctx, ref); + ref = _ir_estimated_control(ctx, ref, loop); return ref < loop; // TODO: check dominance instead of order } @@ -2082,7 +2110,9 @@ static bool ir_try_promote_induction_var_ext(ir_ctx *ctx, ir_ref ext_ref, ir_ref && !IR_IS_SYM_CONST(ctx->ir_base[use_insn->op1].op)) { ctx->ir_base[use].op1 = ir_ext_const(ctx, &ctx->ir_base[use_insn->op1], op, type); } else { - ctx->ir_base[use].op1 = ir_ext_ref(ctx, use, use_insn->op1, op, type, worklist); + ir_ref tmp = ir_ext_ref(ctx, use, use_insn->op1, op, type, worklist); + use_insn = &ctx->ir_base[use]; + use_insn->op1 = tmp; } ir_bitqueue_add(worklist, use); } @@ -2091,7 +2121,9 @@ static bool ir_try_promote_induction_var_ext(ir_ctx *ctx, ir_ref ext_ref, ir_ref && !IR_IS_SYM_CONST(ctx->ir_base[use_insn->op2].op)) { ctx->ir_base[use].op2 = ir_ext_const(ctx, &ctx->ir_base[use_insn->op2], op, type); } else { - ctx->ir_base[use].op2 = ir_ext_ref(ctx, use, use_insn->op2, op, type, worklist); + ir_ref tmp = ir_ext_ref(ctx, use, use_insn->op2, op, type, worklist); + use_insn = &ctx->ir_base[use]; + use_insn->op2 = tmp; } ir_bitqueue_add(worklist, use); } @@ -2119,7 +2151,9 @@ static bool ir_try_promote_induction_var_ext(ir_ctx *ctx, ir_ref ext_ref, ir_ref && !IR_IS_SYM_CONST(ctx->ir_base[use_insn->op1].op)) { ctx->ir_base[use].op1 = ir_ext_const(ctx, &ctx->ir_base[use_insn->op1], op, type); } else { - ctx->ir_base[use].op1 = ir_ext_ref(ctx, use, use_insn->op1, op, type, worklist); + ir_ref tmp = ir_ext_ref(ctx, use, use_insn->op1, op, type, worklist); + use_insn = &ctx->ir_base[use]; + use_insn->op1 = tmp; } ir_bitqueue_add(worklist, use); } @@ -2128,7 +2162,9 @@ static bool ir_try_promote_induction_var_ext(ir_ctx *ctx, ir_ref ext_ref, ir_ref && !IR_IS_SYM_CONST(ctx->ir_base[use_insn->op2].op)) { ctx->ir_base[use].op2 = ir_ext_const(ctx, &ctx->ir_base[use_insn->op2], op, type); } else { - ctx->ir_base[use].op2 = ir_ext_ref(ctx, use, use_insn->op2, op, type, worklist); + ir_ref tmp = ir_ext_ref(ctx, use, use_insn->op2, op, type, worklist); + use_insn = &ctx->ir_base[use]; + use_insn->op2 = tmp; } ir_bitqueue_add(worklist, use); } @@ -2150,7 +2186,8 @@ static bool ir_try_promote_induction_var_ext(ir_ctx *ctx, ir_ref ext_ref, ir_ref && !IR_IS_SYM_CONST(ctx->ir_base[phi_insn->op2].op)) { ctx->ir_base[phi_ref].op2 = ir_ext_const(ctx, &ctx->ir_base[phi_insn->op2], op, type); } else { - ctx->ir_base[phi_ref].op2 = ir_ext_ref(ctx, phi_ref, phi_insn->op2, op, type, worklist); + ir_ref tmp = ir_ext_ref(ctx, phi_ref, phi_insn->op2, op, type, worklist); + ctx->ir_base[phi_ref].op2 = tmp; } return 1; @@ -2223,42 +2260,6 @@ static void ir_merge_blocks(ir_ctx *ctx, ir_ref end, ir_ref begin, ir_bitqueue * ir_ref prev, next; ir_use_list *use_list; - if (ctx->use_lists[begin].count > 1) { - ir_ref *p, n, i, use; - ir_insn *use_insn; - ir_ref region = end; - ir_ref next = IR_UNUSED; - - while (!IR_IS_BB_START(ctx->ir_base[region].op)) { - region = ctx->ir_base[region].op1; - } - - use_list = &ctx->use_lists[begin]; - n = use_list->count; - for (p = &ctx->use_edges[use_list->refs], i = 0; i < n; p++, i++) { - use = *p; - use_insn = &ctx->ir_base[use]; - if (ir_op_flags[use_insn->op] & IR_OP_FLAG_CONTROL) { - IR_ASSERT(!next); - next = use; - } else { - IR_ASSERT(use_insn->op == IR_VAR); - IR_ASSERT(use_insn->op1 == begin); - use_insn->op1 = region; - if (ir_use_list_add(ctx, region, use)) { - /* restore after reallocation */ - use_list = &ctx->use_lists[begin]; - n = use_list->count; - p = &ctx->use_edges[use_list->refs + i]; - } - } - } - - IR_ASSERT(next); - ctx->use_edges[use_list->refs] = next; - use_list->count = 1; - } - IR_ASSERT(ctx->ir_base[begin].op == IR_BEGIN); IR_ASSERT(ctx->ir_base[end].op == IR_END); IR_ASSERT(ctx->ir_base[begin].op1 == end); @@ -2391,7 +2392,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) { @@ -2783,6 +2784,10 @@ static bool ir_cmp_is_true(ir_op op, ir_insn *op1, ir_insn *op2) return !(op1->val.d > op2->val.d); } else if (op == IR_UGT) { return !(op1->val.d <= op2->val.d); + } else if (op == IR_ORDERED) { + return !isnan(op1->val.d) && !isnan(op2->val.d); + } else if (op == IR_UNORDERED) { + return isnan(op1->val.d) || isnan(op2->val.d); } else { IR_ASSERT(0); return 0; @@ -2809,6 +2814,10 @@ static bool ir_cmp_is_true(ir_op op, ir_insn *op1, ir_insn *op2) return !(op1->val.f > op2->val.f); } else if (op == IR_UGT) { return !(op1->val.f <= op2->val.f); + } else if (op == IR_ORDERED) { + return !isnan(op1->val.f) && !isnan(op2->val.f); + } else if (op == IR_UNORDERED) { + return isnan(op1->val.f) || isnan(op2->val.f); } else { IR_ASSERT(0); return 0; @@ -2961,6 +2970,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 +3166,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; @@ -3438,9 +3449,18 @@ static void ir_iter_optimize_guard(ir_ctx *ctx, ir_ref ref, ir_insn *insn, ir_bi remove_guard: prev = insn->op1; next = ir_next_control(ctx, ref); + if (ctx->ir_base[prev].op == IR_SNAPSHOT) { + ir_ref snapshot = prev; + prev = ctx->ir_base[prev].op1; + ir_use_list_remove_one(ctx, snapshot, ref); + ir_use_list_remove_one(ctx, ref, next); + ir_use_list_replace_one(ctx, prev, snapshot, next); + ir_iter_remove_insn(ctx, snapshot, worklist); + } else { + ir_use_list_remove_one(ctx, ref, next); + ir_use_list_replace_one(ctx, prev, ref, next); + } ctx->ir_base[next].op1 = prev; - ir_use_list_remove_one(ctx, ref, next); - ir_use_list_replace_one(ctx, prev, ref, next); insn->op1 = IR_UNUSED; if (!IR_IS_CONST_REF(insn->op2)) { @@ -3451,9 +3471,12 @@ static void ir_iter_optimize_guard(ir_ctx *ctx, ir_ref ref, ir_insn *insn, ir_bi } } - if (insn->op3) { - /* SNAPSHOT */ - ir_iter_remove_insn(ctx, insn->op3, worklist); + if (!IR_IS_CONST_REF(insn->op3)) { + ir_use_list_remove_one(ctx, insn->op3, ref); + if (ir_is_dead(ctx, insn->op3)) { + /* schedule DCE */ + ir_bitqueue_add(worklist, insn->op3); + } } MAKE_NOP(insn); @@ -3545,7 +3568,10 @@ void ir_iter_opt(ir_ctx *ctx, ir_bitqueue *worklist) if (!(ctx->flags & IR_OPT_CFG)) { /* pass */ } else if (insn->op == IR_BEGIN) { - if (insn->op1 && ctx->ir_base[insn->op1].op == IR_END) { + if (insn->op1 + && !insn->op2 /* no computed goto label */ + && ctx->use_lists[i].count == 1 + && ctx->ir_base[insn->op1].op == IR_END) { ir_merge_blocks(ctx, insn->op1, i, worklist); } } else if (insn->op == IR_MERGE) { diff --git a/ext/opcache/jit/ir/ir_x86.dasc b/ext/opcache/jit/ir/ir_x86.dasc index 76602c2b4bcf5..7f714dd11d27c 100644 --- a/ext/opcache/jit/ir/ir_x86.dasc +++ b/ext/opcache/jit/ir/ir_x86.dasc @@ -66,7 +66,7 @@ IR_ALWAYS_INLINE ir_mem IR_MEM(ir_reg base, int32_t offset, ir_reg index, int32_ #define IR_SPILL_POS_TO_OFFSET(offset) \ ((ctx->flags & IR_USE_FRAME_POINTER) ? \ - ((offset) - (ctx->stack_frame_size - ctx->stack_frame_alignment)) : \ + ((offset) - ctx->stack_frame_size) : \ ((offset) + ctx->call_stack_size)) |.macro ASM_EXPAND_OP_MEM, MACRO, op, type, op1 @@ -892,6 +892,9 @@ typedef struct _ir_backend_data { bool double_abs_const; bool float_abs_const; bool double_zero_const; + bool u2d_const; + bool u2f_const; + bool resolved_label_syms; } ir_backend_data; #define IR_GP_REG_NAME(code, name64, name32, name16, name8, name8h) \ @@ -1087,6 +1090,7 @@ const char *ir_reg_name(int8_t reg, ir_type type) _(SSE_TRUNC) \ _(SSE_NEARBYINT) \ _(BIT_OP) \ + _(IGOTO_DUP) \ #define IR_LEA_FIRST IR_LEA_OB #define IR_LEA_LAST IR_LEA_O_SYM @@ -1110,35 +1114,24 @@ const char *ir_rule_name[IR_LAST_OP] = { static bool ir_may_fuse_addr(ir_ctx *ctx, const ir_insn *addr_insn) { - if (sizeof(void*) == 4) { - return 1; + if (addr_insn->op == IR_LABEL) { + return 0; } else if (IR_IS_SYM_CONST(addr_insn->op)) { void *addr = ir_sym_addr(ctx, addr_insn); if (!addr) { return 0; } - return IR_IS_SIGNED_32BIT((int64_t)(intptr_t)addr); + return (sizeof(void*) == 4) || IR_IS_SIGNED_32BIT((int64_t)(intptr_t)addr); } else { - return IR_IS_SIGNED_32BIT(addr_insn->val.i64); + return (sizeof(void*) == 4) || IR_IS_SIGNED_32BIT(addr_insn->val.i64); } } static bool ir_may_fuse_imm(ir_ctx *ctx, const ir_insn *val_insn) { if (val_insn->type == IR_ADDR) { - if (sizeof(void*) == 4) { - return 1; - } else if (IR_IS_SYM_CONST(val_insn->op)) { - void *addr = ir_sym_addr(ctx, val_insn); - - if (!addr) { - return 0; - } - return IR_IS_SIGNED_32BIT((intptr_t)addr); - } else { - return IR_IS_SIGNED_32BIT(val_insn->val.i64); - } + return ir_may_fuse_addr(ctx, val_insn); } else { return (ir_type_size[val_insn->type] <= 4 || IR_IS_SIGNED_32BIT(val_insn->val.i64)); } @@ -1238,6 +1231,9 @@ op2_const: if (IR_IS_CONST_REF(insn->op2) && insn->op1 != insn->op2) { constraints->tmp_regs[n] = IR_TMP_REG(2, insn->type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); n++; + } else if (ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA) { + constraints->tmp_regs[n] = IR_TMP_REG(2, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); + n = 1; } break; case IR_CMP_INT: @@ -1387,6 +1383,12 @@ op2_const: constraints->tmp_regs[n] = IR_TMP_REG(3, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); n++; break; + case IR_ARGVAL: + constraints->tmp_regs[0] = IR_SCRATCH_REG(IR_REG_RSI, IR_DEF_SUB_REF - IR_SUB_REFS_COUNT, IR_USE_SUB_REF); + constraints->tmp_regs[1] = IR_SCRATCH_REG(IR_REG_RDI, IR_DEF_SUB_REF - IR_SUB_REFS_COUNT, IR_USE_SUB_REF); + constraints->tmp_regs[2] = IR_SCRATCH_REG(IR_REG_RCX, IR_DEF_SUB_REF - IR_SUB_REFS_COUNT, IR_USE_SUB_REF); + n = 3; + break; case IR_CALL: insn = &ctx->ir_base[ref]; if (IR_IS_TYPE_INT(insn->type)) { @@ -1508,6 +1510,11 @@ op2_const: constraints->tmp_regs[0] = IR_TMP_REG(1, ctx->ir_base[insn->op1].type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); n = 1; } + if (IR_IS_TYPE_UNSIGNED(ctx->ir_base[insn->op1].type) + && ir_type_size[ctx->ir_base[insn->op1].type] >= sizeof(void*)) { + constraints->tmp_regs[n] = IR_TMP_REG(2, ctx->ir_base[insn->op1].type, IR_USE_SUB_REF, IR_DEF_SUB_REF); + n++; + } break; case IR_ABS_INT: flags = IR_DEF_CONFLICTS_WITH_INPUT_REGS | IR_USE_MUST_BE_IN_REG | IR_OP1_MUST_BE_IN_REG; @@ -1533,6 +1540,7 @@ op2_const: case IR_GUARD_NOT: flags = IR_OP2_SHOULD_BE_IN_REG; break; + case IR_IGOTO: case IR_IJMP: flags = IR_OP2_SHOULD_BE_IN_REG; break; @@ -1558,16 +1566,49 @@ op2_const: flags = IR_OP2_MUST_BE_IN_REG; constraints->tmp_regs[0] = IR_TMP_REG(3, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); n = 1; + insn = &ctx->ir_base[ref]; + if (IR_IS_CONST_REF(insn->op2)) { + constraints->tmp_regs[1] = IR_TMP_REG(2, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); + n = 2; + } break; case IR_VA_ARG: - flags = IR_USE_MUST_BE_IN_REG | IR_OP2_MUST_BE_IN_REG; + flags = IR_USE_MUST_BE_IN_REG | IR_OP2_MUST_BE_IN_REG | IR_DEF_CONFLICTS_WITH_INPUT_REGS; constraints->tmp_regs[0] = IR_TMP_REG(3, IR_ADDR, IR_LOAD_SUB_REF, IR_SAVE_SUB_REF); n = 1; + insn = &ctx->ir_base[ref]; + if (IR_IS_CONST_REF(insn->op2)) { + constraints->tmp_regs[1] = IR_TMP_REG(2, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); + n = 2; + } break; case IR_VA_COPY: flags = IR_OP2_MUST_BE_IN_REG | IR_OP3_MUST_BE_IN_REG; constraints->tmp_regs[0] = IR_TMP_REG(1, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); n = 1; + insn = &ctx->ir_base[ref]; + if (IR_IS_CONST_REF(insn->op2)) { + constraints->tmp_regs[n] = IR_TMP_REG(2, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); + n++; + } + if (IR_IS_CONST_REF(insn->op3)) { + constraints->tmp_regs[n] = IR_TMP_REG(3, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); + n++; + } + 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; @@ -1627,7 +1668,9 @@ static void ir_match_fuse_addr(ir_ctx *ctx, ir_ref addr_ref) do { ir_insn *insn = &ctx->ir_base[*p]; - if (insn->op != IR_LOAD && (insn->op != IR_STORE || insn->op3 == addr_ref)) { + if (insn->op != IR_LOAD + && insn->op != IR_LOAD_v + && ((insn->op != IR_STORE && insn->op != IR_STORE_v) || insn->op3 == addr_ref)) { return; } p++; @@ -1710,7 +1753,7 @@ static bool ir_match_has_mem_deps(ir_ctx *ctx, ir_ref ref, ir_ref root) do { ir_insn *insn = &ctx->ir_base[pos]; - if (insn->op == IR_STORE) { + if (insn->op == IR_STORE || insn->op == IR_STORE_v || insn->op == IR_VSTORE || insn->op == IR_VSTORE_v) { // TODO: check if LOAD and STORE addresses may alias return 1; } else if (insn->op == IR_CALL) { @@ -1724,8 +1767,9 @@ static bool ir_match_has_mem_deps(ir_ctx *ctx, ir_ref ref, ir_ref root) static void ir_match_fuse_load(ir_ctx *ctx, ir_ref ref, ir_ref root) { - if (ir_in_same_block(ctx, ref) - && ctx->ir_base[ref].op == IR_LOAD) { + if (ir_in_same_block(ctx, ref) && + (ctx->ir_base[ref].op == IR_LOAD || ctx->ir_base[ref].op == IR_LOAD_v || + ctx->ir_base[ref].op == IR_VLOAD || ctx->ir_base[ref].op == IR_VLOAD_v)) { if (ctx->use_lists[ref].count == 2 && !ir_match_has_mem_deps(ctx, ref, root)) { ir_ref addr_ref = ctx->ir_base[ref].op2; @@ -1750,7 +1794,7 @@ static bool ir_match_try_fuse_load(ir_ctx *ctx, ir_ref ref, ir_ref root) ir_insn *insn = &ctx->ir_base[ref]; if (ir_in_same_block(ctx, ref) - && insn->op == IR_LOAD) { + && (insn->op == IR_LOAD || insn->op == IR_LOAD_v || insn->op == IR_VLOAD || insn->op == IR_VLOAD_v)) { if (ctx->use_lists[ref].count == 2 && !ir_match_has_mem_deps(ctx, ref, root)) { ir_ref addr_ref = ctx->ir_base[ref].op2; @@ -1772,8 +1816,6 @@ static bool ir_match_try_fuse_load(ir_ctx *ctx, ir_ref ref, ir_ref root) && ir_get_param_reg(ctx, ref) == IR_REG_NONE) { return 1; } - } else if (ctx->ir_base[ref].op == IR_VLOAD) { - return 1; } return 0; } @@ -1839,7 +1881,8 @@ static void ir_match_fuse_load_cmp_fp(ir_ctx *ctx, ir_insn *insn, ir_ref root) /* pass */ } else if ((IR_IS_CONST_REF(insn->op1) && !IR_IS_FP_ZERO(ctx->ir_base[insn->op1])) || ir_match_try_fuse_load(ctx, insn->op1, root)) { ir_swap_ops(insn); - if (insn->op != IR_EQ && insn->op != IR_NE) { + if (insn->op != IR_EQ && insn->op != IR_NE + && insn->op != IR_ORDERED && insn->op != IR_UNORDERED) { insn->op ^= 3; } } @@ -1866,7 +1909,8 @@ static void ir_match_fuse_load_cmp_fp_br(ir_ctx *ctx, ir_insn *insn, ir_ref root /* pass */ } else if ((IR_IS_CONST_REF(insn->op1) && !IR_IS_FP_ZERO(ctx->ir_base[insn->op1])) || ir_match_try_fuse_load(ctx, insn->op1, root)) { ir_swap_ops(insn); - if (insn->op != IR_EQ && insn->op != IR_NE) { + if (insn->op != IR_EQ && insn->op != IR_NE + && insn->op != IR_ORDERED && insn->op != IR_UNORDERED) { insn->op ^= 3; } } @@ -1993,6 +2037,10 @@ static uint32_t ir_match_insn(ir_ctx *ctx, ir_ref ref) return IR_CMP_FP; } break; + case IR_ORDERED: + case IR_UNORDERED: + ir_match_fuse_load_cmp_fp(ctx, insn, ref); + return IR_CMP_FP; case IR_ADD: case IR_SUB: if (IR_IS_TYPE_INT(insn->type)) { @@ -2414,9 +2462,27 @@ binop_fp: case IR_IJMP: ir_match_fuse_load(ctx, insn->op2, ref); return insn->op; + case IR_IGOTO: + if (ctx->ir_base[insn->op1].op == IR_MERGE || ctx->ir_base[insn->op1].op == IR_LOOP_BEGIN) { + ir_insn *merge = &ctx->ir_base[insn->op1]; + ir_ref *p, n = merge->inputs_count; + + for (p = merge->ops + 1; n > 0; p++, n--) { + ir_ref input = *p; + IR_ASSERT(ctx->ir_base[input].op == IR_END || ctx->ir_base[input].op == IR_LOOP_END); + ctx->rules[input] = IR_IGOTO_DUP; + } + } + ir_match_fuse_load(ctx, insn->op2, ref); + return insn->op; case IR_VAR: - return IR_SKIPPED | IR_VAR; + return IR_STATIC_ALLOCA; case IR_PARAM: +#ifndef _WIN64 + if (ctx->value_params && ctx->value_params[insn->op3 - 1].align) { + return IR_STATIC_ALLOCA; + } +#endif return ctx->use_lists[ref].count > 0 ? IR_PARAM : IR_SKIPPED | IR_PARAM; case IR_ALLOCA: /* alloca() may be used only in functions */ @@ -2564,7 +2630,15 @@ store_int: return IR_VSTORE_FP; } break; + case IR_VSTORE_v: + if (IR_IS_TYPE_INT(ctx->ir_base[insn->op3].type)) { + return IR_VSTORE_INT; + } else { + return IR_VSTORE_FP; + } + break; case IR_LOAD: + case IR_LOAD_v: ir_match_fuse_addr(ctx, insn->op2); if (IR_IS_TYPE_INT(insn->type)) { return IR_LOAD_INT; @@ -2582,6 +2656,14 @@ store_int: return IR_STORE_FP; } break; + case IR_STORE_v: + ir_match_fuse_addr(ctx, insn->op2); + if (IR_IS_TYPE_INT(ctx->ir_base[insn->op3].type)) { + return IR_STORE_INT; + } else { + return IR_STORE_FP; + } + break; case IR_RLOAD: if (IR_REGSET_IN(IR_REGSET_UNION((ir_regset)ctx->fixed_regset, IR_REGSET_FIXED), insn->op2)) { return IR_SKIPPED | IR_RLOAD; @@ -2630,6 +2712,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: @@ -2646,7 +2729,7 @@ store_int: case IR_IF: if (!IR_IS_CONST_REF(insn->op2) && ctx->use_lists[insn->op2].count == 1) { op2_insn = &ctx->ir_base[insn->op2]; - if (op2_insn->op >= IR_EQ && op2_insn->op <= IR_UGT) { + if (op2_insn->op >= IR_EQ && op2_insn->op <= IR_UNORDERED) { if (IR_IS_TYPE_INT(ctx->ir_base[op2_insn->op1].type)) { if (IR_IS_CONST_REF(op2_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[op2_insn->op2].op) @@ -2775,7 +2858,7 @@ store_int: if (!IR_IS_CONST_REF(insn->op1) && ctx->use_lists[insn->op1].count == 1) { ir_insn *op1_insn = &ctx->ir_base[insn->op1]; - if (op1_insn->op >= IR_EQ && op1_insn->op <= IR_UGT) { + if (op1_insn->op >= IR_EQ && op1_insn->op <= IR_UNORDERED) { if (IR_IS_TYPE_INT(ctx->ir_base[op1_insn->op1].type)) { ir_match_fuse_load_cmp_int(ctx, op1_insn, ref); ctx->rules[insn->op1] = IR_FUSED | IR_CMP_INT; @@ -2792,7 +2875,7 @@ store_int: case IR_GUARD_NOT: if (!IR_IS_CONST_REF(insn->op2) && ctx->use_lists[insn->op2].count == 1) { op2_insn = &ctx->ir_base[insn->op2]; - if (op2_insn->op >= IR_EQ && op2_insn->op <= IR_UGT + if (op2_insn->op >= IR_EQ && op2_insn->op <= IR_UNORDERED // TODO: register allocator may clobber operands of CMP before they are used in the GUARD_CMP && (insn->op2 == ref - 1 || (insn->op2 == ctx->prev_ref[ref] - 1 @@ -2945,6 +3028,9 @@ store_int: ctx->flags2 |= IR_HAS_VA_ARG_GP|IR_HAS_VA_ARG_FP; } } + } else { + /* va_list may escape */ + ctx->flags2 |= IR_HAS_VA_ARG_GP|IR_HAS_VA_ARG_FP; } return IR_VA_START; case IR_VA_END: @@ -2961,6 +3047,8 @@ store_int: } } return IR_SKIPPED | IR_NOP; + case IR_ARGVAL: + return IR_FUSED | IR_ARGVAL; case IR_NOP: return IR_SKIPPED | IR_NOP; default: @@ -3116,7 +3204,7 @@ static void ir_emit_load_imm_fp(ir_ctx *ctx, ir_type type, ir_reg reg, ir_ref sr | xorpd xmm(reg-IR_REG_FP_FIRST), xmm(reg-IR_REG_FP_FIRST) } } else { - label = ir_const_label(ctx, src); + label = ir_get_const_label(ctx, src); | ASM_FP_REG_TXT_OP movs, type, reg, [=>label] } } @@ -3138,6 +3226,17 @@ static void ir_emit_load_mem(ir_ctx *ctx, ir_type type, ir_reg reg, ir_mem mem) } } +static int32_t ir_local_offset(ir_ctx *ctx, ir_insn *insn) +{ + if (insn->op != IR_PARAM) { + IR_ASSERT(insn->op == IR_VAR || insn->op == IR_ALLOCA || insn->op == IR_VADDR); + return IR_SPILL_POS_TO_OFFSET(insn->op3); + } else { + IR_ASSERT(ctx->value_params && ctx->value_params[insn->op3 - 1].align); + return IR_SPILL_POS_TO_OFFSET(ctx->value_params[insn->op3 - 1].offset); + } +} + static void ir_load_local_addr(ir_ctx *ctx, ir_reg reg, ir_ref src) { ir_backend_data *data = ctx->data; @@ -3151,8 +3250,7 @@ static void ir_load_local_addr(ir_ctx *ctx, ir_reg reg, ir_ref src) if (var_insn->op == IR_VADDR) { var_insn = &ctx->ir_base[var_insn->op1]; } - IR_ASSERT(var_insn->op == IR_VAR || var_insn->op == IR_ALLOCA); - offset = IR_SPILL_POS_TO_OFFSET(var_insn->op3); + offset = ir_local_offset(ctx, var_insn); if (offset == 0) { | mov Ra(reg), Ra(base) } else { @@ -3160,6 +3258,38 @@ static void ir_load_local_addr(ir_ctx *ctx, ir_reg reg, ir_ref src) } } +static void ir_resolve_label_syms(ir_ctx *ctx) +{ + uint32_t b; + ir_block *bb; + + for (b = 1, bb = &ctx->cfg_blocks[b]; b <= ctx->cfg_blocks_count; bb++, b++) { + ir_insn *insn = &ctx->ir_base[bb->start]; + + if (insn->op == IR_BEGIN && insn->op2) { + IR_ASSERT(ctx->ir_base[insn->op2].op == IR_LABEL); + ctx->ir_base[insn->op2].val.u32_hi = b; + } + } +} + +static void ir_emit_load_label_addr(ir_ctx *ctx, ir_reg reg, ir_insn *label) +{ + ir_backend_data *data = ctx->data; + dasm_State **Dst = &data->dasm_state; + + if (!data->resolved_label_syms) { + data->resolved_label_syms = 1; + ir_resolve_label_syms(ctx); + } + + IR_ASSERT(label->op == IR_LABEL); + int b = label->val.u32_hi; + + b = ir_skip_empty_target_blocks(ctx, b); + | lea Ra(reg), aword [=>b] +} + static void ir_emit_load(ir_ctx *ctx, ir_type type, ir_reg reg, ir_ref src) { if (IR_IS_CONST_REF(src)) { @@ -3172,9 +3302,11 @@ static void ir_emit_load(ir_ctx *ctx, ir_type type, ir_reg reg, ir_ref src) } else if (insn->op == IR_STR) { ir_backend_data *data = ctx->data; dasm_State **Dst = &data->dasm_state; - int label = ir_const_label(ctx, src); + int label = ir_get_const_label(ctx, src); | lea Ra(reg), aword [=>label] + } else if (insn->op == IR_LABEL) { + ir_emit_load_label_addr(ctx, reg, insn); } else { ir_emit_load_imm_int(ctx, type, reg, insn->val.i64); } @@ -3220,7 +3352,7 @@ static void ir_emit_store_mem_int_const(ir_ctx *ctx, ir_type type, ir_mem mem, i IR_ASSERT(IR_IS_CONST_REF(src)); if (val_insn->op == IR_STR) { - int label = ir_const_label(ctx, src); + int label = ir_get_const_label(ctx, src); IR_ASSERT(tmp_reg != IR_REG_NONE); |.if X64 @@ -3229,6 +3361,11 @@ static void ir_emit_store_mem_int_const(ir_ctx *ctx, ir_type type, ir_mem mem, i |.else | ASM_TMEM_TXT_OP mov, aword, mem, =>label |.endif + } else if (val_insn->op == IR_LABEL) { + IR_ASSERT(tmp_reg != IR_REG_NONE); + tmp_reg = IR_REG_NUM(tmp_reg); + ir_emit_load_label_addr(ctx, tmp_reg, val_insn); + ir_emit_store_mem_int(ctx, type, mem, tmp_reg); } else { int64_t val = val_insn->val.i64; @@ -3370,7 +3507,7 @@ static ir_mem ir_fuse_addr(ir_ctx *ctx, ir_ref root, ir_ref ref) case IR_LEA_OB: offset_insn = insn; if (ir_rule(ctx, insn->op1) == IR_STATIC_ALLOCA) { - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op1].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[insn->op1]); base_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; base_reg_ref = IR_UNUSED; } else { @@ -3392,12 +3529,12 @@ static ir_mem ir_fuse_addr(ir_ctx *ctx, ir_ref root, ir_ref ref) break; case IR_LEA_IB: if (ir_rule(ctx, insn->op1) == IR_STATIC_ALLOCA) { - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op1].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[insn->op1]); base_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; base_reg_ref = IR_UNUSED; index_reg_ref = ref * sizeof(ir_ref) + 2; } else if (ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA) { - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op2].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[insn->op2]); base_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; base_reg_ref = IR_UNUSED; index_reg_ref = ref * sizeof(ir_ref) + 1; @@ -3413,12 +3550,12 @@ static ir_mem ir_fuse_addr(ir_ctx *ctx, ir_ref root, ir_ref ref) offset_insn = op1_insn; scale = 1; if (ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA) { - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op2].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[insn->op2]); base_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; base_reg_ref = IR_UNUSED; index_reg_ref = insn->op1 * sizeof(ir_ref) + 1; } else if (ir_rule(ctx, op1_insn->op1) == IR_STATIC_ALLOCA) { - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[op1_insn->op1].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[op1_insn->op1]); base_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; base_reg_ref = IR_UNUSED; index_reg_ref = ref * sizeof(ir_ref) + 2; @@ -3432,12 +3569,12 @@ static ir_mem ir_fuse_addr(ir_ctx *ctx, ir_ref root, ir_ref ref) offset_insn = op2_insn; scale = 1; if (ir_rule(ctx, insn->op1) == IR_STATIC_ALLOCA) { - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op1].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[insn->op1]); base_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; base_reg_ref = IR_UNUSED; index_reg_ref = insn->op2 * sizeof(ir_ref) + 1; } else if (ir_rule(ctx, op2_insn->op1) == IR_STATIC_ALLOCA) { - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[op2_insn->op1].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[op2_insn->op1]); base_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; base_reg_ref = IR_UNUSED; index_reg_ref = ref * sizeof(ir_ref) + 1; @@ -3464,12 +3601,12 @@ static ir_mem ir_fuse_addr(ir_ctx *ctx, ir_ref root, ir_ref ref) offset_insn = insn; scale = 1; if (ir_rule(ctx, op1_insn->op2) == IR_STATIC_ALLOCA) { - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[op1_insn->op2].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[op1_insn->op2]); base_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; base_reg_ref = IR_UNUSED; index_reg_ref = insn->op1 * sizeof(ir_ref) + 1; } else if (ir_rule(ctx, op1_insn->op1) == IR_STATIC_ALLOCA) { - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[op1_insn->op1].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[op1_insn->op1]); base_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; base_reg_ref = IR_UNUSED; index_reg_ref = insn->op1 * sizeof(ir_ref) + 2; @@ -3485,7 +3622,7 @@ static ir_mem ir_fuse_addr(ir_ctx *ctx, ir_ref root, ir_ref ref) op2_insn = &ctx->ir_base[insn->op2]; scale = ctx->ir_base[op2_insn->op2].val.i32; if (ir_rule(ctx, op1_insn->op1) == IR_STATIC_ALLOCA) { - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[op1_insn->op1].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[op1_insn->op1]); base_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; base_reg_ref = IR_UNUSED; } else { @@ -3499,7 +3636,7 @@ static ir_mem ir_fuse_addr(ir_ctx *ctx, ir_ref root, ir_ref ref) op2_insn = &ctx->ir_base[insn->op2]; offset_insn = op2_insn; if (ir_rule(ctx, op2_insn->op1) == IR_STATIC_ALLOCA) { - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[op2_insn->op1].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[op2_insn->op1]); base_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; base_reg_ref = IR_UNUSED; } else { @@ -3508,7 +3645,7 @@ static ir_mem ir_fuse_addr(ir_ctx *ctx, ir_ref root, ir_ref ref) break; case IR_LEA_B_SI: if (ir_rule(ctx, insn->op1) == IR_STATIC_ALLOCA) { - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op1].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[insn->op1]); base_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; base_reg_ref = IR_UNUSED; } else { @@ -3522,7 +3659,7 @@ static ir_mem ir_fuse_addr(ir_ctx *ctx, ir_ref root, ir_ref ref) case IR_LEA_SI_B: index_reg_ref = insn->op1 * sizeof(ir_ref) + 1; if (ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA) { - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op2].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[insn->op2]); base_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; base_reg_ref = IR_UNUSED; } else { @@ -3535,7 +3672,13 @@ static ir_mem ir_fuse_addr(ir_ctx *ctx, ir_ref root, ir_ref ref) case IR_LEA_B_SI_O: offset_insn = insn; op1_insn = &ctx->ir_base[insn->op1]; - base_reg_ref = insn->op1 * sizeof(ir_ref) + 1; + if (ir_rule(ctx, op1_insn->op1) == IR_STATIC_ALLOCA) { + offset = ir_local_offset(ctx, &ctx->ir_base[op1_insn->op1]); + base_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; + base_reg_ref = IR_UNUSED; + } else { + base_reg_ref = insn->op1 * sizeof(ir_ref) + 1; + } index_reg_ref = op1_insn->op2 * sizeof(ir_ref) + 1; op2_insn = &ctx->ir_base[op1_insn->op2]; scale = ctx->ir_base[op2_insn->op2].val.i32; @@ -3544,7 +3687,13 @@ static ir_mem ir_fuse_addr(ir_ctx *ctx, ir_ref root, ir_ref ref) offset_insn = insn; op1_insn = &ctx->ir_base[insn->op1]; index_reg_ref = op1_insn->op1 * sizeof(ir_ref) + 1; - base_reg_ref = insn->op1 * sizeof(ir_ref) + 2; + if (ir_rule(ctx, op1_insn->op2) == IR_STATIC_ALLOCA) { + offset = ir_local_offset(ctx, &ctx->ir_base[op1_insn->op2]); + base_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; + base_reg_ref = IR_UNUSED; + } else { + base_reg_ref = insn->op1 * sizeof(ir_ref) + 2; + } op1_insn = &ctx->ir_base[op1_insn->op1]; scale = ctx->ir_base[op1_insn->op2].val.i32; break; @@ -3565,7 +3714,7 @@ static ir_mem ir_fuse_addr(ir_ctx *ctx, ir_ref root, ir_ref ref) offset_insn = NULL; break; case IR_ALLOCA: - offset = IR_SPILL_POS_TO_OFFSET(insn->op3); + offset = ir_local_offset(ctx, insn); base_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; base_reg_ref = index_reg_ref = IR_UNUSED; scale = 1; @@ -3582,7 +3731,7 @@ static ir_mem ir_fuse_addr(ir_ctx *ctx, ir_ref root, ir_ref ref) offset += (int64_t)(intptr_t)(addr); } else { if (offset_insn->op == IR_SUB) { - offset = -addr_insn->val.i32; + offset -= addr_insn->val.i32; } else { offset += addr_insn->val.i32; } @@ -3645,7 +3794,8 @@ static ir_mem ir_fuse_load(ir_ctx *ctx, ir_ref root, ir_ref ref) ir_insn *load_insn = &ctx->ir_base[ref]; ir_reg reg; - IR_ASSERT(load_insn->op == IR_LOAD); + IR_ASSERT(load_insn->op == IR_LOAD || load_insn->op == IR_LOAD_v || + load_insn->op == IR_VLOAD || load_insn->op == IR_VLOAD_v); if (UNEXPECTED(ctx->rules[ref] & IR_FUSED_REG)) { reg = ir_get_fused_reg(ctx, root, ref * sizeof(ir_ref) + 2); } else { @@ -3681,9 +3831,11 @@ static void ir_emit_load_ex(ir_ctx *ctx, ir_type type, ir_reg reg, ir_ref src, i } else if (insn->op == IR_STR) { ir_backend_data *data = ctx->data; dasm_State **Dst = &data->dasm_state; - int label = ir_const_label(ctx, src); + int label = ir_get_const_label(ctx, src); | lea Ra(reg), aword [=>label] + } else if (insn->op == IR_LABEL) { + ir_emit_load_label_addr(ctx, reg, insn); } else { ir_emit_load_imm_int(ctx, type, reg, insn->val.i64); } @@ -3781,7 +3933,7 @@ static void ir_emit_prologue(ir_ctx *ctx) if (ctx->flags & IR_USE_FRAME_POINTER) { fp = IR_REG_FRAME_POINTER; - offset = -(ctx->stack_frame_size - ctx->stack_frame_alignment - ctx->locals_area_size); + offset = -(ctx->stack_frame_size - ctx->locals_area_size); } else { fp = IR_REG_STACK_POINTER; offset = ctx->locals_area_size + ctx->call_stack_size; @@ -5526,7 +5678,7 @@ static void ir_emit_binop_sse2(ir_ctx *ctx, ir_ref def, ir_insn *insn) break; } } else if (IR_IS_CONST_REF(op2)) { - int label = ir_const_label(ctx, op2); + int label = ir_get_const_label(ctx, op2); switch (insn->op) { default: @@ -5633,7 +5785,7 @@ static void ir_emit_binop_avx(ir_ctx *ctx, ir_ref def, ir_insn *insn) break; } } else if (IR_IS_CONST_REF(op2)) { - int label = ir_const_label(ctx, op2); + int label = ir_get_const_label(ctx, op2); switch (insn->op) { default: @@ -6045,7 +6197,7 @@ static ir_op ir_emit_cmp_fp_common(ir_ctx *ctx, ir_ref root, ir_ref cmp_ref, ir_ } | ASM_FP_REG_REG_OP ucomis, type, op1_reg, op2_reg } else if (IR_IS_CONST_REF(op2)) { - int label = ir_const_label(ctx, op2); + int label = ir_get_const_label(ctx, op2); | ASM_FP_REG_TXT_OP ucomis, type, op1_reg, [=>label] } else { @@ -6115,6 +6267,12 @@ static void ir_emit_cmp_fp(ir_ctx *ctx, ir_ref def, ir_insn *insn) | mov Rd(tmp_reg), 1 | cmova Rd(def_reg), Rd(tmp_reg) break; + case IR_ORDERED: + | setnp Rb(def_reg) + break; + case IR_UNORDERED: + | setp Rb(def_reg) + break; } if (IR_REG_SPILLED(ctx->regs[def][0])) { ir_emit_store(ctx, insn->type, def, def_reg); @@ -6154,7 +6312,7 @@ static void ir_emit_jcc(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn, uint ir_get_true_false_blocks(ctx, b, &true_block, &false_block); if (true_block == next_block) { /* swap to avoid unconditional JMP */ - if (int_cmp || op == IR_EQ || op == IR_NE) { + if (int_cmp || op == IR_EQ || op == IR_NE || op == IR_ORDERED || op == IR_UNORDERED) { op ^= 1; // reverse } else { op ^= 5; // reverse @@ -6266,6 +6424,12 @@ static void ir_emit_jcc(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn, uint | jp =>true_block | ja =>true_block break; + case IR_ORDERED: + | jnp =>true_block + break; + case IR_UNORDERED: + | jp =>true_block + break; } } if (false_block) { @@ -6784,6 +6948,12 @@ static void ir_emit_cond_cmp_fp(ir_ctx *ctx, ir_ref def, ir_insn *insn) | jp >1 | jbe >2 break; + case IR_ORDERED: + | jp >2 + break; + case IR_UNORDERED: + | jnp >2 + break; } |1: @@ -6868,7 +7038,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_get_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); @@ -7144,7 +7331,20 @@ static void ir_emit_trunc(ir_ctx *ctx, ir_ref def, ir_insn *insn) ir_emit_load(ctx, src_type, op1_reg, insn->op1); } if (op1_reg != def_reg) { +#ifdef IR_TARGET_X86 + if (ir_type_size[dst_type] == 1 + && (op1_reg == IR_REG_RBP || op1_reg == IR_REG_RSI || op1_reg == IR_REG_RDI)) { + ir_backend_data *data = ctx->data; + dasm_State **Dst = &data->dasm_state; + + ir_emit_mov(ctx, src_type, def_reg, op1_reg); + | and Rb(def_reg), 0xff + } else { + ir_emit_mov(ctx, dst_type, def_reg, op1_reg); + } +#else ir_emit_mov(ctx, dst_type, def_reg, op1_reg); +#endif } } else { ir_emit_load_ex(ctx, dst_type, def_reg, insn->op1, def); @@ -7269,7 +7469,7 @@ static void ir_emit_bitcast(ir_ctx *ctx, ir_ref def, ir_insn *insn) } } } else if (IR_IS_CONST_REF(insn->op1)) { - int label = ir_const_label(ctx, insn->op1); + int label = ir_get_const_label(ctx, insn->op1); | ASM_FP_REG_TXT_OP movs, dst_type, def_reg, [=>label] } else { @@ -7301,13 +7501,80 @@ static void ir_emit_int2fp(ir_ctx *ctx, ir_ref def, ir_insn *insn) IR_ASSERT(IR_IS_TYPE_INT(src_type)); IR_ASSERT(IR_IS_TYPE_FP(dst_type)); IR_ASSERT(def_reg != IR_REG_NONE); + + if (op1_reg != IR_REG_NONE && IR_REG_SPILLED(op1_reg)) { + op1_reg = IR_REG_NUM(op1_reg); + ir_emit_load(ctx, src_type, op1_reg, insn->op1); + } + + if (IR_IS_TYPE_UNSIGNED(src_type) && ir_type_size[src_type] >= sizeof(void*)) { + ir_reg tmp_reg = ctx->regs[def][2]; + + IR_ASSERT(tmp_reg != IR_REG_NONE); + if (op1_reg == IR_REG_NONE) { + if (IR_IS_CONST_REF(insn->op1)) { + IR_ASSERT(0); + } else { + ir_mem mem; + + if (ir_rule(ctx, insn->op1) & IR_FUSED) { + mem = ir_fuse_load(ctx, def, insn->op1); + } else { + mem = ir_ref_spill_slot(ctx, insn->op1); + } + ir_emit_load_mem_int(ctx, src_type, tmp_reg, mem); + op1_reg = tmp_reg; + } + } + if (sizeof(void*) == 4) { + if (tmp_reg == op1_reg) { + | add Rd(op1_reg), 0x80000000 + } else { + | lea Rd(tmp_reg), dword [Rd(op1_reg)+0x80000000] + op1_reg = tmp_reg; + } + } else { +|.if X64 + | test Rq(op1_reg), Rq(op1_reg) + | js >1 + |.cold_code + |1: + if (tmp_reg != op1_reg) { + | mov Rq(tmp_reg), Rq(op1_reg) + } + | shr Rq(tmp_reg), 1 + | adc Rq(tmp_reg), 0 + if (dst_type == IR_DOUBLE) { + if (ctx->mflags & IR_X86_AVX) { + | vxorps xmm(def_reg-IR_REG_FP_FIRST), xmm(def_reg-IR_REG_FP_FIRST), xmm(def_reg-IR_REG_FP_FIRST) + | vcvtsi2sd xmm(def_reg-IR_REG_FP_FIRST), xmm(def_reg-IR_REG_FP_FIRST), Rq(tmp_reg) + | vaddsd xmm(def_reg-IR_REG_FP_FIRST), xmm(def_reg-IR_REG_FP_FIRST), xmm(def_reg-IR_REG_FP_FIRST) + } else { + | pxor xmm(def_reg-IR_REG_FP_FIRST), xmm(def_reg-IR_REG_FP_FIRST) + | cvtsi2sd xmm(def_reg-IR_REG_FP_FIRST), Rq(tmp_reg) + | addsd xmm(def_reg-IR_REG_FP_FIRST), xmm(def_reg-IR_REG_FP_FIRST) + } + } else { + IR_ASSERT(dst_type == IR_FLOAT); + if (ctx->mflags & IR_X86_AVX) { + | vxorps xmm(def_reg-IR_REG_FP_FIRST), xmm(def_reg-IR_REG_FP_FIRST), xmm(def_reg-IR_REG_FP_FIRST) + | vcvtsi2ss xmm(def_reg-IR_REG_FP_FIRST), xmm(def_reg-IR_REG_FP_FIRST), Rq(tmp_reg) + | vaddss xmm(def_reg-IR_REG_FP_FIRST), xmm(def_reg-IR_REG_FP_FIRST), xmm(def_reg-IR_REG_FP_FIRST) + } else { + | pxor xmm(def_reg-IR_REG_FP_FIRST), xmm(def_reg-IR_REG_FP_FIRST) + | cvtsi2ss xmm(def_reg-IR_REG_FP_FIRST), Rq(tmp_reg) + | addss xmm(def_reg-IR_REG_FP_FIRST), xmm(def_reg-IR_REG_FP_FIRST) + } + } + | jmp >2 + |.code +|.endif + } + } + if (op1_reg != IR_REG_NONE) { bool src64 = 0; - if (IR_REG_SPILLED(op1_reg)) { - op1_reg = IR_REG_NUM(op1_reg); - ir_emit_load(ctx, src_type, op1_reg, insn->op1); - } if (IR_IS_TYPE_SIGNED(src_type)) { if (ir_type_size[src_type] < 4) { |.if X64 @@ -7346,7 +7613,6 @@ static void ir_emit_int2fp(ir_ctx *ctx, ir_ref def, ir_insn *insn) || } |.endif } else { - // TODO: uint64_t -> double src64 = 1; } } @@ -7392,6 +7658,40 @@ static void ir_emit_int2fp(ir_ctx *ctx, ir_ref def, ir_insn *insn) } |.endif } + |2: + if (sizeof(void*) == 4 && IR_IS_TYPE_UNSIGNED(src_type) && ir_type_size[src_type] >= sizeof(void*)) { + if (dst_type == IR_DOUBLE) { + uint32_t c = (sizeof(void*) == 4) ? 0x41e00000 : 0x43e00000; + if (!data->u2d_const) { + data->u2d_const = 1; + ir_rodata(ctx); + |.align 8 + |->u2d_const: + |.dword 0, c + |.code + } + if (ctx->mflags & IR_X86_AVX) { + | vaddsd xmm(def_reg-IR_REG_FP_FIRST), xmm(def_reg-IR_REG_FP_FIRST), qword [->u2d_const] + } else { + | addsd xmm(def_reg-IR_REG_FP_FIRST), qword [->u2d_const] + } + } else { + uint32_t c = (sizeof(void*) == 4) ? 0x4f000000 : 0x5f000000; + if (!data->u2f_const) { + data->u2f_const = 1; + ir_rodata(ctx); + |.align 4 + |->u2f_const: + |.dword c + |.code + } + if (ctx->mflags & IR_X86_AVX) { + | vaddss xmm(def_reg-IR_REG_FP_FIRST), xmm(def_reg-IR_REG_FP_FIRST), dword [->u2f_const] + } else { + | addss xmm(def_reg-IR_REG_FP_FIRST), dword [->u2f_const] + } + } + } } else if (IR_IS_CONST_REF(insn->op1)) { IR_ASSERT(0); } else { @@ -7509,7 +7809,7 @@ static void ir_emit_fp2int(ir_ctx *ctx, ir_ref def, ir_insn *insn) |.endif } } else if (IR_IS_CONST_REF(insn->op1)) { - int label = ir_const_label(ctx, insn->op1); + int label = ir_get_const_label(ctx, insn->op1); if (!dst64) { if (src_type == IR_DOUBLE) { @@ -7630,7 +7930,7 @@ static void ir_emit_fp2fp(ir_ctx *ctx, ir_ref def, ir_insn *insn) } } } else if (IR_IS_CONST_REF(insn->op1)) { - int label = ir_const_label(ctx, insn->op1); + int label = ir_get_const_label(ctx, insn->op1); if (src_type == IR_DOUBLE) { if (ctx->mflags & IR_X86_AVX) { @@ -8274,7 +8574,7 @@ static void ir_emit_va_start(ir_ctx *ctx, ir_ref def, ir_insn *insn) } else { IR_ASSERT(ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA); op2_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op2].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[insn->op2]); } if (ctx->flags & IR_USE_FRAME_POINTER) { @@ -8308,12 +8608,12 @@ static void ir_emit_va_start(ir_ctx *ctx, ir_ref def, ir_insn *insn) } else { IR_ASSERT(ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA); op2_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op2].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[insn->op2]); } if (ctx->flags & IR_USE_FRAME_POINTER) { fp = IR_REG_FRAME_POINTER; - reg_save_area_offset = -(ctx->stack_frame_size - ctx->stack_frame_alignment - ctx->locals_area_size); + reg_save_area_offset = -(ctx->stack_frame_size - ctx->locals_area_size); overflow_arg_area_offset = sizeof(void*) * 2 + ctx->param_stack_size; } else { fp = IR_REG_STACK_POINTER; @@ -8375,7 +8675,7 @@ static void ir_emit_va_copy(ir_ctx *ctx, ir_ref def, ir_insn *insn) } else { IR_ASSERT(ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA); op2_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; - op2_offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op2].op3); + op2_offset = ir_local_offset(ctx, &ctx->ir_base[insn->op2]); } if (op3_reg != IR_REG_NONE) { if (IR_REG_SPILLED(op3_reg)) { @@ -8386,7 +8686,7 @@ static void ir_emit_va_copy(ir_ctx *ctx, ir_ref def, ir_insn *insn) } else { IR_ASSERT(ir_rule(ctx, insn->op3) == IR_STATIC_ALLOCA); op3_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; - op3_offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op3].op3); + op3_offset = ir_local_offset(ctx, &ctx->ir_base[insn->op3]); } | mov Ra(tmp_reg), aword [Ra(op3_reg)+op3_offset] | mov aword [Ra(op2_reg)+op2_offset], Ra(tmp_reg) @@ -8409,7 +8709,7 @@ static void ir_emit_va_copy(ir_ctx *ctx, ir_ref def, ir_insn *insn) } else { IR_ASSERT(ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA); op2_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; - op2_offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op2].op3); + op2_offset = ir_local_offset(ctx, &ctx->ir_base[insn->op2]); } if (op3_reg != IR_REG_NONE) { if (IR_REG_SPILLED(op3_reg)) { @@ -8420,7 +8720,7 @@ static void ir_emit_va_copy(ir_ctx *ctx, ir_ref def, ir_insn *insn) } else { IR_ASSERT(ir_rule(ctx, insn->op3) == IR_STATIC_ALLOCA); op3_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; - op3_offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op3].op3); + op3_offset = ir_local_offset(ctx, &ctx->ir_base[insn->op3]); } | mov Rd(tmp_reg), dword [Ra(op3_reg)+(op3_offset+offsetof(ir_va_list, gp_offset))] | mov dword [Ra(op2_reg)+(op2_offset+offsetof(ir_va_list, gp_offset))], Rd(tmp_reg) @@ -8442,12 +8742,12 @@ 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; - IR_ASSERT(def_reg != IR_REG_NONE && tmp_reg != IR_REG_NONE); + IR_ASSERT((def_reg != IR_REG_NONE || ctx->use_lists[def].count == 1) && tmp_reg != IR_REG_NONE); if (op2_reg != IR_REG_NONE) { if (IR_REG_SPILLED(op2_reg)) { op2_reg = IR_REG_NUM(op2_reg); @@ -8457,13 +8757,38 @@ static void ir_emit_va_arg(ir_ctx *ctx, ir_ref def, ir_insn *insn) } else { IR_ASSERT(ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA); op2_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op2].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[insn->op2]); } | mov Ra(tmp_reg), aword [Ra(op2_reg)+offset] - ir_emit_load_mem(ctx, type, def_reg, IR_MEM_B(tmp_reg)); +#ifdef _WIN64 + if (def_reg != IR_REG_NONE) { + ir_emit_load_mem(ctx, type, def_reg, IR_MEM_B(tmp_reg)); + } | add Ra(tmp_reg), IR_MAX(ir_type_size[type], sizeof(void*)) +#else + if (!insn->op3) { + if (def_reg != IR_REG_NONE) { + ir_emit_load_mem(ctx, type, def_reg, IR_MEM_B(tmp_reg)); + } + | add Ra(tmp_reg), IR_MAX(ir_type_size[type], sizeof(void*)) + } else { + int size = IR_VA_ARG_SIZE(insn->op3); + + if (def_reg != IR_REG_NONE) { + IR_ASSERT(type == IR_ADDR); + int align = IR_VA_ARG_ALIGN(insn->op3); + + if (align > (int)sizeof(void*)) { + | add Ra(tmp_reg), (align-1) + | and Ra(tmp_reg), ~(align-1) + } + | mov Ra(def_reg), Ra(tmp_reg) + } + | add Ra(tmp_reg), IR_ALIGNED_SIZE(size, sizeof(void*)) + } +#endif | mov aword [Ra(op2_reg)+offset], Ra(tmp_reg) - if (IR_REG_SPILLED(ctx->regs[def][0])) { + if (def_reg != IR_REG_NONE && IR_REG_SPILLED(ctx->regs[def][0])) { ir_emit_store(ctx, type, def, def_reg); } #elif defined(IR_TARGET_X64) @@ -8471,12 +8796,12 @@ 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; - IR_ASSERT(def_reg != IR_REG_NONE&& tmp_reg != IR_REG_NONE); + IR_ASSERT((def_reg != IR_REG_NONE || ctx->use_lists[def].count == 1) && tmp_reg != IR_REG_NONE); if (op2_reg != IR_REG_NONE) { if (IR_REG_SPILLED(op2_reg)) { op2_reg = IR_REG_NUM(op2_reg); @@ -8486,9 +8811,25 @@ static void ir_emit_va_arg(ir_ctx *ctx, ir_ref def, ir_insn *insn) } else { IR_ASSERT(ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA); op2_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; - offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[insn->op2].op3); + offset = ir_local_offset(ctx, &ctx->ir_base[insn->op2]); } - if (IR_IS_TYPE_INT(type)) { + if (insn->op3) { + /* long struct arguemnt */ + IR_ASSERT(type == IR_ADDR); + int align = IR_VA_ARG_ALIGN(insn->op3); + int size = IR_VA_ARG_SIZE(insn->op3); + + | mov Ra(tmp_reg), aword [Ra(op2_reg)+(offset+offsetof(ir_va_list, overflow_arg_area))] + if (align > (int)sizeof(void*)) { + | add Ra(tmp_reg), (align-1) + | and Ra(tmp_reg), ~(align-1) + } + if (def_reg != IR_REG_NONE) { + | mov Ra(def_reg), Ra(tmp_reg) + } + | add Ra(tmp_reg), IR_ALIGNED_SIZE(size, sizeof(void*)) + | mov aword [Ra(op2_reg)+(offset+offsetof(ir_va_list, overflow_arg_area))], Ra(tmp_reg) + } else if (IR_IS_TYPE_INT(type)) { | mov Rd(tmp_reg), dword [Ra(op2_reg)+(offset+offsetof(ir_va_list, gp_offset))] | cmp Rd(tmp_reg), sizeof(void*)*IR_REG_INT_ARGS | jge >1 @@ -8501,7 +8842,13 @@ static void ir_emit_va_arg(ir_ctx *ctx, ir_ref def, ir_insn *insn) | add Ra(tmp_reg), sizeof(void*) | mov aword [Ra(op2_reg)+(offset+offsetof(ir_va_list, overflow_arg_area))], Ra(tmp_reg) |2: - | mov Ra(def_reg), aword [Ra(tmp_reg)-sizeof(void*)] + if (def_reg != IR_REG_NONE) { + if (ir_type_size[type] == 8) { + | mov Rq(def_reg), qword [Ra(tmp_reg)-sizeof(void*)] + } else { + | mov Rd(def_reg), dword [Ra(tmp_reg)-sizeof(void*)] + } + } } else { | mov Rd(tmp_reg), dword [Ra(op2_reg)+(offset+offsetof(ir_va_list, fp_offset))] | cmp Rd(tmp_reg), sizeof(void*) * IR_REG_INT_ARGS + 16 * IR_REG_FP_ARGS @@ -8509,16 +8856,20 @@ static void ir_emit_va_arg(ir_ctx *ctx, ir_ref def, ir_insn *insn) | add Rd(tmp_reg), 16 | mov dword [Ra(op2_reg)+(offset+offsetof(ir_va_list, fp_offset))], Rd(tmp_reg) | add Ra(tmp_reg), aword [Ra(op2_reg)+(offset+offsetof(ir_va_list, reg_save_area))] - ir_emit_load_mem_fp(ctx, type, def_reg, IR_MEM_BO(tmp_reg, -16)); + if (def_reg != IR_REG_NONE) { + ir_emit_load_mem_fp(ctx, type, def_reg, IR_MEM_BO(tmp_reg, -16)); + } | jmp >2 |1: | mov Ra(tmp_reg), aword [Ra(op2_reg)+(offset+offsetof(ir_va_list, overflow_arg_area))] - ir_emit_load_mem_fp(ctx, type, def_reg, IR_MEM_BO(tmp_reg, 0)); + if (def_reg != IR_REG_NONE) { + ir_emit_load_mem_fp(ctx, type, def_reg, IR_MEM_BO(tmp_reg, 0)); + } | add Ra(tmp_reg), 8 | mov aword [Ra(op2_reg)+(offset+offsetof(ir_va_list, overflow_arg_area))], Ra(tmp_reg) |2: } - if (IR_REG_SPILLED(ctx->regs[def][0])) { + if (def_reg != IR_REG_NONE && IR_REG_SPILLED(ctx->regs[def][0])) { ir_emit_store(ctx, type, def, def_reg); } |.endif @@ -8541,6 +8892,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 +8922,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 +8950,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 +9114,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) { @@ -8755,7 +9158,7 @@ static void ir_emit_switch(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn) } } -static int32_t ir_call_used_stack(ir_ctx *ctx, ir_insn *insn) +static int32_t ir_call_used_stack(ir_ctx *ctx, ir_insn *insn, int *copy_stack_ptr) { int j, n; ir_type type; @@ -8764,6 +9167,9 @@ static int32_t ir_call_used_stack(ir_ctx *ctx, ir_insn *insn) int int_reg_params_count = IR_REG_INT_ARGS; int fp_reg_params_count = IR_REG_FP_ARGS; int32_t used_stack = 0; +#ifdef _WIN64 + int32_t copy_stack = 0; +#endif #ifdef IR_HAVE_FASTCALL if (sizeof(void*) == 4 && ir_is_fastcall(ctx, insn)) { @@ -8774,8 +9180,26 @@ static int32_t ir_call_used_stack(ir_ctx *ctx, ir_insn *insn) n = insn->inputs_count; for (j = 3; j <= n; j++) { - type = ctx->ir_base[ir_insn_op(insn, j)].type; + ir_insn *arg = &ctx->ir_base[ir_insn_op(insn, j)]; + type = arg->type; if (IR_IS_TYPE_INT(type)) { + if (arg->op == IR_ARGVAL) { + int size = arg->op2; + int align = arg->op3; + +#ifdef _WIN64 + copy_stack += size; + align = IR_MAX((int)sizeof(void*), align); + copy_stack = IR_ALIGNED_SIZE(copy_stack, align); + type = IR_ADDR; +#else + align = IR_MAX((int)sizeof(void*), align); + used_stack = IR_ALIGNED_SIZE(used_stack, align); + used_stack += size; + used_stack = IR_ALIGNED_SIZE(used_stack, sizeof(void*)); + continue; +#endif + } if (int_param >= int_reg_params_count) { used_stack += IR_MAX(sizeof(void*), ir_type_size[type]); } @@ -8800,6 +9224,14 @@ static int32_t ir_call_used_stack(ir_ctx *ctx, ir_insn *insn) /* Reserved "home space" or "shadow store" for register arguments (used in Windows64 ABI) */ used_stack += IR_SHADOW_ARGS; +#ifdef _WIN64 + copy_stack = IR_ALIGNED_SIZE(copy_stack, 16); + used_stack += copy_stack; + *copy_stack_ptr = copy_stack; +#else + *copy_stack_ptr = 0; +#endif + return used_stack; } @@ -8819,7 +9251,7 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg int fp_reg_params_count = IR_REG_FP_ARGS; const int8_t *int_reg_params = _ir_int_reg_params; const int8_t *fp_reg_params = _ir_fp_reg_params; - int32_t used_stack, stack_offset = IR_SHADOW_ARGS; + int32_t used_stack, copy_stack = 0, stack_offset = IR_SHADOW_ARGS; ir_copy *copies; bool do_pass3 = 0; /* For temporaries we may use any scratch registers except for registers used for parameters */ @@ -8850,9 +9282,13 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg #endif ) { // TODO: support for preallocated stack +#ifdef _WIN64 + used_stack = ir_call_used_stack(ctx, insn, ©_stack); +#else used_stack = 0; +#endif } else { - used_stack = ir_call_used_stack(ctx, insn); + used_stack = ir_call_used_stack(ctx, insn, ©_stack); if (IR_SHADOW_ARGS && insn->op == IR_TAILCALL && used_stack == IR_SHADOW_ARGS) { @@ -8875,6 +9311,46 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg } } +#ifdef _WIN64 +|.if X64 + if (copy_stack) { + /* Copy struct arguments */ + int copy_stack_offset = 0; + + for (j = 3; j <= n; j++) { + arg = ir_insn_op(insn, j); + src_reg = ir_get_alocated_reg(ctx, def, j); + arg_insn = &ctx->ir_base[arg]; + type = arg_insn->type; + + if (arg_insn->op == IR_ARGVAL) { + /* make a stack copy */ + int size = arg_insn->op2; + int align = arg_insn->op3; + + copy_stack_offset += size; + align = IR_MAX((int)sizeof(void*), align); + copy_stack_offset = IR_ALIGNED_SIZE(copy_stack_offset, align); + src_reg = ctx->regs[arg][1]; + + | lea rdi, [rsp + (used_stack - copy_stack_offset)] + if (src_reg != IR_REG_NONE) { + if (IR_REG_SPILLED(src_reg)) { + src_reg = IR_REG_NUM(src_reg); + ir_emit_load(ctx, IR_ADDR, src_reg, arg_insn->op1); + } + | mov rsi, Ra(src_reg) + } else { + ir_emit_load(ctx, IR_ADDR, IR_REG_RSI, arg_insn->op1); + } + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_RCX, size); + | rep; movsb + } + } + } +|.endif +#endif + /* 1. move all register arguments that should be passed through stack * and collect arguments that should be passed through registers */ copies = ir_mem_malloc((n - 2) * sizeof(ir_copy)); @@ -8884,6 +9360,55 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg arg_insn = &ctx->ir_base[arg]; type = arg_insn->type; if (IR_IS_TYPE_INT(type)) { +#ifndef _WIN64 + if (arg_insn->op == IR_ARGVAL) { + int size = arg_insn->op2; + int align = arg_insn->op3; + align = IR_MAX((int)sizeof(void*), align); + stack_offset = IR_ALIGNED_SIZE(stack_offset, align); + if (size) { + src_reg = ctx->regs[arg][1]; + if (src_reg != IR_REG_NONE) { + if (IR_REG_SPILLED(src_reg)) { + src_reg = IR_REG_NUM(src_reg); + ir_emit_load(ctx, IR_ADDR, src_reg, arg_insn->op1); + } + if (src_reg != IR_REG_RSI) { + |.if X64 + | mov rsi, Ra(src_reg) + |.else + | mov esi, Ra(src_reg) + |.endif + } + } else { + ir_emit_load(ctx, IR_ADDR, IR_REG_RSI, arg_insn->op1); + } + if (stack_offset == 0) { + |.if X64 + | mov rdi, rsp + |.else + | mov edi, esp + |.endif + } else { + |.if X64 + | lea rdi, [rsp+stack_offset] + |.else + | lea edi, [esp+stack_offset] + |.endif + } + |.if X64 + | mov rcx, size + | rep; movsb + |.else + | mov ecx, size + | rep; movsb + |.endif + } + stack_offset += size; + stack_offset = IR_ALIGNED_SIZE(stack_offset, sizeof(void*)); + continue; + } +#endif if (int_param < int_reg_params_count) { dst_reg = int_reg_params[int_param]; } else { @@ -8893,6 +9418,10 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg #ifdef _WIN64 /* WIN64 calling convention use common couter for int and fp registers */ fp_param++; + if (arg_insn->op == IR_ARGVAL) { + do_pass3 = 3; + continue; + } #endif } else { IR_ASSERT(IR_IS_TYPE_FP(type)); @@ -8908,7 +9437,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 { @@ -8943,6 +9474,10 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg /* 3. move the remaining memory and immediate values */ if (do_pass3) { +#ifdef _WIN64 + int copy_stack_offset = 0; +#endif + stack_offset = IR_SHADOW_ARGS; int_param = 0; fp_param = 0; @@ -8952,6 +9487,37 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg arg_insn = &ctx->ir_base[arg]; type = arg_insn->type; if (IR_IS_TYPE_INT(type)) { + if (arg_insn->op == IR_ARGVAL) { + int size = arg_insn->op2; + int align = arg_insn->op3; + +#ifndef _WIN64 + align = IR_MAX((int)sizeof(void*), align); + stack_offset = IR_ALIGNED_SIZE(stack_offset, align); + stack_offset += size; + stack_offset = IR_ALIGNED_SIZE(stack_offset, sizeof(void*)); + continue; +#else +|.if X64 + /* pass pointer to the copy on stack */ + copy_stack_offset += size; + align = IR_MAX((int)sizeof(void*), align); + copy_stack_offset = IR_ALIGNED_SIZE(copy_stack_offset, align); + if (int_param < int_reg_params_count) { + dst_reg = int_reg_params[int_param]; + | lea Ra(dst_reg), [rsp + (used_stack - copy_stack_offset)] + } else { + | lea Ra(tmp_reg), [rsp + (used_stack - copy_stack_offset)] + ir_emit_store_mem_int(ctx, IR_ADDR, IR_MEM_BO(IR_REG_STACK_POINTER, stack_offset), tmp_reg); + stack_offset += sizeof(void*); + } + int_param++; + /* WIN64 calling convention use common couter for int and fp registers */ + fp_param++; + continue; +|.endif +#endif + } if (int_param < int_reg_params_count) { dst_reg = int_reg_params[int_param]; } else { @@ -8976,7 +9542,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) { @@ -9065,6 +9633,9 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg } } } + if (insn->op == IR_CALL && (ctx->flags & IR_PREALLOCATED_STACK)) { + used_stack = 0; + } #endif #ifdef IR_REG_VARARG_FP_REGS /* set hidden argument to specify the number of vector registers used */ @@ -9221,6 +9792,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 +9869,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 } } @@ -9274,6 +9885,19 @@ static void ir_emit_ijmp(ir_ctx *ctx, ir_ref def, ir_insn *insn) ir_reg op2_reg = ctx->regs[def][2]; if (IR_IS_CONST_REF(insn->op2)) { + if (ctx->ir_base[insn->op2].op == IR_LABEL) { + if (!data->resolved_label_syms) { + data->resolved_label_syms = 1; + ir_resolve_label_syms(ctx); + } + + uint32_t target = ctx->ir_base[insn->op2].val.u32_hi; + target = ir_skip_empty_target_blocks(ctx, target); + + | jmp =>target + return; + } + void *addr = ir_jmp_addr(ctx, insn, &ctx->ir_base[insn->op2]); if (sizeof(void*) == 4 || IR_MAY_USE_32BIT_ADDR(ctx->code_buffer, addr)) { @@ -9396,6 +10020,12 @@ static bool ir_emit_guard_jcc(ir_ctx *ctx, uint32_t b, ir_ref def, uint32_t next | jp &addr | jbe =>target break; + case IR_ORDERED: + | jnp =>target + break; + case IR_UNORDERED: + | jp =>target + break; } } | jmp &addr @@ -9475,6 +10105,12 @@ static bool ir_emit_guard_jcc(ir_ctx *ctx, uint32_t b, ir_ref def, uint32_t next | jp &addr | jbe &target_addr break; + case IR_ORDERED: + | jnp &target_addr + break; + case IR_UNORDERED: + | jp &target_addr + break; } } | jmp &addr @@ -9554,6 +10190,12 @@ static bool ir_emit_guard_jcc(ir_ctx *ctx, uint32_t b, ir_ref def, uint32_t next case IR_GT: | ja &addr break; + case IR_ORDERED: + | jp &addr + break; + case IR_UNORDERED: + | jnp &addr + break; // case IR_ULT: fprintf(stderr, "\tjb .LL%d\n", true_block); break; // case IR_UGE: fprintf(stderr, "\tjae .LL%d\n", true_block); break; // case IR_ULE: fprintf(stderr, "\tjbe .LL%d\n", true_block); break; @@ -10033,6 +10675,7 @@ static void ir_emit_param_move(ir_ctx *ctx, uint8_t type, ir_reg from_reg, ir_re { ir_reg fp = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; + offset = IR_SPILL_POS_TO_OFFSET(offset); IR_ASSERT(from_reg != IR_REG_NONE || to_reg != IR_REG_NONE); if (IR_IS_TYPE_INT(type)) { @@ -10073,6 +10716,7 @@ static void ir_emit_load_params(ir_ctx *ctx) const int8_t *int_reg_params = _ir_int_reg_params; const int8_t *fp_reg_params = _ir_fp_reg_params; int32_t stack_offset = 0; + int32_t stack_start = 0; #ifdef IR_TARGET_X86 if (sizeof(void*) == 4 && (ctx->flags & IR_FASTCALL_FUNC)) { @@ -10084,9 +10728,11 @@ static void ir_emit_load_params(ir_ctx *ctx) #endif 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_start = sizeof(void*) * 2 + ctx->stack_frame_size; } else { - stack_offset = sizeof(void*) + ctx->stack_frame_size + ctx->call_stack_size; /* skip return address */ + /* skip return address */ + stack_start = sizeof(void*) + ctx->stack_frame_size; } n = use_list->count; for (i = 0, p = &ctx->use_edges[use_list->refs]; i < n; i++, p++) { @@ -10094,7 +10740,16 @@ static void ir_emit_load_params(ir_ctx *ctx) insn = &ctx->ir_base[use]; if (insn->op == IR_PARAM) { if (IR_IS_TYPE_INT(insn->type)) { - if (int_param_num < int_reg_params_count) { + if (ctx->value_params && ctx->value_params[insn->op3 - 1].align) { + /* struct passed by value on stack */ + size_t align = ctx->value_params[insn->op3 - 1].align; + + align = IR_MAX(sizeof(void*), align); + stack_offset = IR_ALIGNED_SIZE(stack_offset, align); + stack_offset += ctx->value_params[insn->op3 - 1].size; + stack_offset = IR_ALIGNED_SIZE(stack_offset, sizeof(void*)); + continue; + } else if (int_param_num < int_reg_params_count) { src_reg = int_reg_params[int_param_num]; } else { src_reg = IR_REG_NONE; @@ -10119,12 +10774,9 @@ static void ir_emit_load_params(ir_ctx *ctx) if (ctx->vregs[use]) { dst_reg = IR_REG_NUM(ctx->regs[use][0]); IR_ASSERT(src_reg != IR_REG_NONE || dst_reg != IR_REG_NONE || - stack_offset == ctx->live_intervals[ctx->vregs[use]]->stack_spill_pos + - ((ctx->flags & IR_USE_FRAME_POINTER) ? - -(ctx->stack_frame_size - ctx->stack_frame_alignment) : - ctx->call_stack_size)); + stack_start + stack_offset == ctx->live_intervals[ctx->vregs[use]]->stack_spill_pos); if (src_reg != dst_reg) { - ir_emit_param_move(ctx, insn->type, src_reg, dst_reg, use, stack_offset); + ir_emit_param_move(ctx, insn->type, src_reg, dst_reg, use, stack_start + stack_offset); } if (dst_reg != IR_REG_NONE && IR_REG_SPILLED(ctx->regs[use][0])) { ir_emit_store(ctx, insn->type, use, dst_reg); @@ -10211,7 +10863,7 @@ static void ir_fix_param_spills(ir_ctx *ctx) if (ctx->flags & IR_USE_FRAME_POINTER) { /* skip old frame pointer and return address */ - stack_start = sizeof(void*) * 2 + (ctx->stack_frame_size - ctx->stack_frame_alignment); + stack_start = sizeof(void*) * 2 + ctx->stack_frame_size; } else { /* skip return address */ stack_start = sizeof(void*) + ctx->stack_frame_size; @@ -10222,6 +10874,19 @@ static void ir_fix_param_spills(ir_ctx *ctx) insn = &ctx->ir_base[use]; if (insn->op == IR_PARAM) { if (IR_IS_TYPE_INT(insn->type)) { +#ifndef _WIN64 + if (ctx->value_params && ctx->value_params[insn->op3 - 1].align) { + /* struct passed by value on stack */ + size_t align = ctx->value_params[insn->op3 - 1].align; + + align = IR_MAX(sizeof(void*), align); + stack_offset = IR_ALIGNED_SIZE(stack_offset, align); + ctx->value_params[insn->op3 - 1].offset = stack_start + stack_offset; + stack_offset += ctx->value_params[insn->op3 - 1].size; + stack_offset = IR_ALIGNED_SIZE(stack_offset, sizeof(void*)); + continue; + } +#endif if (int_param_num < int_reg_params_count) { src_reg = int_reg_params[int_param_num]; } else { @@ -10314,10 +10979,12 @@ 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: case IR_LOOP_END: + case IR_IGOTO_DUP: break; #ifndef IR_REG_FP_RET1 case IR_CALL: @@ -10342,7 +11009,7 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx) IR_REGSET_EXCL(available, reg); ctx->regs[i][0] = reg | IR_REG_SPILL_STORE; } else if (def_flags & IR_USE_MUST_BE_IN_REG) { - if (insn->op == IR_VLOAD + if ((insn->op == IR_VLOAD || insn->op == IR_VLOAD_v) && ctx->live_intervals[ctx->vregs[i]] && ctx->live_intervals[ctx->vregs[i]]->stack_spill_pos != -1 && ir_is_same_mem_var(ctx, i, ctx->ir_base[insn->op2].op3)) { @@ -10382,7 +11049,7 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx) for (i = 0, p = &ctx->use_edges[use_list->refs]; i < n; i++, p++) { use = *p; use_insn = &ctx->ir_base[use]; - if (use_insn->op == IR_VLOAD) { + if (use_insn->op == IR_VLOAD || use_insn->op == IR_VLOAD_v) { if (ctx->vregs[use] && !ctx->live_intervals[ctx->vregs[use]]) { ir_live_interval *ival = ir_arena_alloc(&ctx->arena, sizeof(ir_live_interval)); @@ -10393,7 +11060,7 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx) ival->vreg = ctx->vregs[use]; ival->stack_spill_pos = stack_spill_pos; } - } else if (use_insn->op == IR_VSTORE) { + } else if (use_insn->op == IR_VSTORE || use_insn->op == IR_VSTORE_v) { if (!IR_IS_CONST_REF(use_insn->op3) && ctx->vregs[use_insn->op3] && !ctx->live_intervals[ctx->vregs[use_insn->op3]]) { @@ -10481,13 +11148,13 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx) static void ir_preallocate_call_stack(ir_ctx *ctx) { - int call_stack_size, peak_call_stack_size = 0; + int call_stack_size, copy_stack, peak_call_stack_size = 0; ir_ref i, n; ir_insn *insn; for (i = 1, insn = ctx->ir_base + 1; i < ctx->insns_count;) { if (insn->op == IR_CALL) { - call_stack_size = ir_call_used_stack(ctx, insn); + call_stack_size = ir_call_used_stack(ctx, insn, ©_stack); if (call_stack_size > peak_call_stack_size #ifdef IR_HAVE_FASTCALL && !ir_is_fastcall(ctx, insn) /* fast call functions restore stack pointer */ @@ -10538,7 +11205,6 @@ void ir_fix_stack_frame(ir_ctx *ctx) ctx->stack_frame_size = IR_ALIGNED_SIZE(ctx->stack_frame_size, sizeof(void*)); ctx->stack_frame_size += additional_size; - ctx->stack_frame_alignment = 0; ctx->call_stack_size = 0; if (ctx->flags2 & IR_16B_FRAME_ALIGNMENT) { @@ -10546,12 +11212,10 @@ void ir_fix_stack_frame(ir_ctx *ctx) if (!(ctx->flags & IR_FUNCTION)) { while (IR_ALIGNED_SIZE(ctx->stack_frame_size, 16) != ctx->stack_frame_size) { ctx->stack_frame_size += sizeof(void*); - ctx->stack_frame_alignment += sizeof(void*); } } else if (ctx->flags & IR_USE_FRAME_POINTER) { while (IR_ALIGNED_SIZE(ctx->stack_frame_size + sizeof(void*) * 2, 16) != ctx->stack_frame_size + sizeof(void*) * 2) { ctx->stack_frame_size += sizeof(void*); - ctx->stack_frame_alignment += sizeof(void*); } } else { if (!(ctx->flags & IR_NO_STACK_COMBINE)) { @@ -10560,7 +11224,6 @@ void ir_fix_stack_frame(ir_ctx *ctx) while (IR_ALIGNED_SIZE(ctx->stack_frame_size + ctx->call_stack_size + sizeof(void*), 16) != ctx->stack_frame_size + ctx->call_stack_size + sizeof(void*)) { ctx->stack_frame_size += sizeof(void*); - ctx->stack_frame_alignment += sizeof(void*); } } } @@ -10593,6 +11256,8 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr) int ret; void *entry; size_t size; + ir_ref igoto_dup_ref = IR_UNUSED; + uint32_t igoto_dup_block = 0; data.ra_data.unused_slot_4 = 0; data.ra_data.unused_slot_2 = 0; @@ -10605,11 +11270,13 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr) data.double_abs_const = 0; data.float_abs_const = 0; data.double_zero_const = 0; + data.u2d_const = 0; + data.u2f_const = 0; + data.resolved_label_syms = 0; ctx->data = &data; if (!ctx->live_intervals) { ctx->stack_frame_size = 0; - ctx->stack_frame_alignment = 0; ctx->call_stack_size = 0; ctx->used_preserved_regs = 0; ir_allocate_unique_spill_slots(ctx); @@ -10631,7 +11298,6 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr) } ctx->stack_frame_size = ctx->fixed_stack_frame_size; ctx->call_stack_size = ctx->fixed_call_stack_size; - ctx->stack_frame_alignment = 0; } Dst = &data.dasm_state; @@ -10641,6 +11307,14 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr) dasm_setup(&data.dasm_state, dasm_actions); /* labels for each block + for each constant + rodata label + jmp_table label + for each entry */ dasm_growpc(&data.dasm_state, ctx->cfg_blocks_count + 1 + ctx->consts_count + 1 + 1 + 1 + ctx->entries_count); + if (data.dasm_state->status != DASM_S_OK) { + IR_ASSERT(data.dasm_state->status == DASM_S_NOMEM); + dasm_free(&data.dasm_state); + ctx->data = NULL; + ctx->status = IR_ERROR_TOO_LARGE; + return NULL; + } + data.emit_constants = ir_bitset_malloc(ctx->consts_count); if ((ctx->flags & IR_GEN_ENDBR) && (ctx->flags & IR_START_BR_TARGET)) { @@ -10944,6 +11618,35 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr) case IR_TAILCALL: ir_emit_tailcall(ctx, i, insn); break; + case IR_IGOTO_DUP: + if (bb->flags & IR_BB_DESSA_MOVES) { + ir_emit_dessa_moves(ctx, b, bb); + } + IR_ASSERT(!igoto_dup_ref && !igoto_dup_block); + igoto_dup_ref = i; + igoto_dup_block = b; + b = ctx->cfg_edges[bb->successors]; + bb = &ctx->cfg_blocks[b]; + i = bb->start; + insn = &ctx->ir_base[i]; + rule = &ctx->rules[i]; + break; + case IR_IGOTO: + if ((ctx->ir_base[insn->op1].op == IR_MERGE || ctx->ir_base[insn->op1].op == IR_LOOP_BEGIN) + && (ctx->rules[ctx->ir_base[insn->op1].op1] & IR_RULE_MASK) == IR_IGOTO_DUP + && igoto_dup_ref) { + ir_emit_ijmp(ctx, i, insn); + b = igoto_dup_block; + bb = &ctx->cfg_blocks[b]; + i = igoto_dup_ref; + insn = &ctx->ir_base[i]; + rule = &ctx->rules[i]; + igoto_dup_block= 0; + igoto_dup_ref = 0; + break; + } + IR_ASSERT(!igoto_dup_ref && !igoto_dup_block); + IR_FALLTHROUGH; case IR_IJMP: ir_emit_ijmp(ctx, i, insn); break; @@ -10973,6 +11676,7 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr) ir_emit_vaddr(ctx, i, insn); break; case IR_VLOAD: + case IR_VLOAD_v: ir_emit_vload(ctx, i, insn); break; case IR_VSTORE_INT: @@ -11137,12 +11841,20 @@ next_block:; return NULL; } + if (data.dasm_state->status != DASM_S_OK) { + IR_ASSERT(data.dasm_state->status == DASM_S_NOMEM); + dasm_free(&data.dasm_state); + ctx->data = NULL; + ctx->status = IR_ERROR_TOO_LARGE; + return NULL; + } + ret = dasm_link(&data.dasm_state, size_ptr); if (ret != DASM_S_OK) { - IR_ASSERT(0); + IR_ASSERT(ret == DASM_S_NOMEM); dasm_free(&data.dasm_state); ctx->data = NULL; - ctx->status = IR_ERROR_LINK; + ctx->status = (ret == DASM_S_NOMEM) ? IR_ERROR_TOO_LARGE : IR_ERROR_LINK; return NULL; } size = *size_ptr; @@ -11207,6 +11919,28 @@ next_block:; } while (i != 0); } + if ((ctx->flags2 & IR_HAS_BLOCK_ADDR) && ctx->loader && ctx->loader->add_label) { + for (b = 1, bb = &ctx->cfg_blocks[b]; b <= ctx->cfg_blocks_count; bb++, b++) { + ir_insn *insn = &ctx->ir_base[bb->start]; + + if (insn->op == IR_BEGIN && insn->op2) { + IR_ASSERT(ctx->ir_base[insn->op2].op == IR_LABEL); + ctx->ir_base[insn->op2].val.u32_hi = 0; + ctx->loader->add_label(ctx->loader, ir_get_str(ctx, ctx->ir_base[insn->op2].val.str), + (char*)entry + dasm_getpclabel(&data.dasm_state, ir_skip_empty_target_blocks(ctx, b))); + } + } + } else if (data.resolved_label_syms) { + for (b = 1, bb = &ctx->cfg_blocks[b]; b <= ctx->cfg_blocks_count; bb++, b++) { + ir_insn *insn = &ctx->ir_base[bb->start]; + + if (insn->op == IR_BEGIN && insn->op2) { + IR_ASSERT(ctx->ir_base[insn->op2].op == IR_LABEL); + ctx->ir_base[insn->op2].val.u32_hi = 0; + } + } + } + dasm_free(&data.dasm_state); ir_mem_flush(entry, size); 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..ee8a572e04a05 --- /dev/null +++ b/ext/opcache/jit/tls/zend_jit_tls_darwin.c @@ -0,0 +1,122 @@ +/* + * +----------------------------------------------------------------------+ + * | 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 +#include + +TSRMLS_CACHE_EXTERN(); + +/* Thunk format used since dydl 1284 (approx. MacOS 15) + * https://github.com/apple-oss-distributions/dyld/blob/9307719dd8dc9b385daa412b03cfceb897b2b398/libdyld/ThreadLocalVariables.h#L146 */ +#if defined(__x86_64__) || defined(__aarch64__) +struct TLV_Thunkv2 +{ + void* func; + uint32_t key; + uint32_t offset; +}; +#else +struct TLV_Thunkv2 +{ + void* func; + uint16_t key; + uint16_t offset; +}; +#endif + +/* Thunk format used in earlier versions */ +struct TLV_Thunkv1 +{ + void* func; + size_t key; + size_t offset; +}; + +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__) + struct TLV_Thunkv2 *thunk; + __asm__ __volatile__( + "leaq __tsrm_ls_cache(%%rip),%0" + : "=r" (thunk)); + + /* Detect dyld 1284: With dyld 1284, thunk->func will be _tlv_get_addr. + * Unfortunately this symbol is private, but we can find it + * as _tlv_bootstrap+8: https://github.com/apple-oss-distributions/dyld/blob/9307719dd8dc9b385daa412b03cfceb897b2b398/libdyld/threadLocalHelpers.s#L54 + * In earlier versions, thunk->func will be tlv_get_addr, which is not + * _tlv_bootstrap+8. + */ + if (thunk->func == (void*)((char*)_tlv_bootstrap + 8)) { + *module_offset = thunk->offset; + *module_index = (size_t)thunk->key * 8; + } else { + struct TLV_Thunkv1 *thunkv1 = (struct TLV_Thunkv1*) thunk; + *module_offset = thunkv1->offset; + *module_index = thunkv1->key * 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 fa2cc10e8b3a0..3ffb669e84742 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,19 +90,24 @@ 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); -static uint32_t zend_jit_trace_get_exit_point(const zend_op *to_opline, uint32_t flags); +static uint32_t _zend_jit_trace_get_exit_point(const zend_op *to_opline, uint32_t flags ZEND_FILE_LINE_DC); +#define zend_jit_trace_get_exit_point(to_opline, flags) _zend_jit_trace_get_exit_point(to_opline, flags ZEND_FILE_LINE_CC) static const void *zend_jit_trace_get_exit_addr(uint32_t n); static void zend_jit_trace_add_code(const void *start, uint32_t size); static zend_string *zend_jit_func_name(const zend_op_array *op_array); @@ -205,38 +210,38 @@ static int zend_jit_is_constant_cmp_long_long(const zend_op *opline, case ZEND_CASE: case ZEND_CASE_STRICT: if (op1_min == op1_max && op2_min == op2_max && op1_min == op2_min) { - *result = 1; + *result = true; return 1; } else if (op1_max < op2_min || op1_min > op2_max) { - *result = 0; + *result = false; return 1; } return 0; case ZEND_IS_NOT_EQUAL: case ZEND_IS_NOT_IDENTICAL: if (op1_min == op1_max && op2_min == op2_max && op1_min == op2_min) { - *result = 0; + *result = false; return 1; } else if (op1_max < op2_min || op1_min > op2_max) { - *result = 1; + *result = true; return 1; } return 0; case ZEND_IS_SMALLER: if (op1_max < op2_min) { - *result = 1; + *result = true; return 1; } else if (op1_min >= op2_max) { - *result = 0; + *result = false; return 1; } return 0; case ZEND_IS_SMALLER_OR_EQUAL: if (op1_max <= op2_min) { - *result = 1; + *result = true; return 1; } else if (op1_min > op2_max) { - *result = 0; + *result = false; return 1; } return 0; @@ -1233,13 +1238,13 @@ static void zend_jit_allocate_registers(zend_jit_ctx *ctx, const zend_op_array * ((ra[i].flags & ZREG_LOAD) || ((ra[i].flags & ZREG_STORE) && ssa->vars[i].definition >= 0)) && ssa->vars[i].use_chain < 0) { - bool may_remove = 1; + bool may_remove = true; zend_ssa_phi *phi = ssa->vars[i].phi_use_chain; while (phi) { if (ra[phi->ssa_var].ref && !(ra[phi->ssa_var].flags & ZREG_LOAD)) { - may_remove = 0; + may_remove = false; break; } phi = zend_ssa_next_use_phi(ssa, i, phi); @@ -1263,13 +1268,12 @@ static void zend_jit_allocate_registers(zend_jit_ctx *ctx, const zend_op_array * && ssa->vars[i].definition >= 0 && ssa->ops[op_num].result_def == i) { const zend_live_range *range = op_array->live_range; - int j; op_num++; if (op_array->opcodes[op_num].opcode == ZEND_OP_DATA) { op_num++; } - for (j = 0; j < op_array->last_live_range; range++, j++) { + for (uint32_t j = 0; j < op_array->last_live_range; range++, j++) { if (range->start > op_num) { /* further blocks will not be relevant... */ break; @@ -1294,13 +1298,13 @@ static void zend_jit_allocate_registers(zend_jit_ctx *ctx, const zend_op_array * && (ra[i].flags & ZREG_STORE) && (ssa->vars[i].use_chain < 0 || zend_ssa_next_use(ssa->ops, i, ssa->vars[i].use_chain) < 0)) { - bool may_remove = 1; + bool may_remove = true; zend_ssa_phi *phi = ssa->vars[i].phi_use_chain; while (phi) { if (ra[phi->ssa_var].ref && !(ra[phi->ssa_var].flags & ZREG_LOAD)) { - may_remove = 0; + may_remove = false; break; } phi = zend_ssa_next_use_phi(ssa, i, phi); @@ -1417,10 +1421,10 @@ 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 */ + bool recv_emitted = false; /* emitted at least one RECV opcode */ uint8_t smart_branch_opcode; uint32_t target_label, target_label2; uint32_t op1_info, op1_def_info, op2_info, res_info, res_use_info, op1_mem_info; @@ -1485,7 +1489,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op zend_jit_recv_entry(&ctx, b); } } - recv_emitted = 1; + recv_emitted = true; } else if (opline->opcode == ZEND_RECV) { if (!(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) { /* skip */ @@ -1495,7 +1499,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op } else if (recv_emitted) { zend_jit_recv_entry(&ctx, b); } else { - recv_emitted = 1; + recv_emitted = true; } } else { if (recv_emitted) { @@ -1878,8 +1882,8 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op break; } ce = NULL; - ce_is_instanceof = 0; - on_this = 0; + ce_is_instanceof = false; + on_this = false; if (opline->op1_type == IS_UNUSED) { op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN; ce = op_array->scope; @@ -1888,7 +1892,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op ce_is_instanceof = !(ce->ce_flags & ZEND_ACC_FINAL); } op1_addr = 0; - on_this = 1; + on_this = true; } else { op1_info = OP1_INFO(); if (!(op1_info & MAY_BE_OBJECT)) { @@ -1929,8 +1933,8 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op break; } ce = NULL; - ce_is_instanceof = 0; - on_this = 0; + ce_is_instanceof = false; + on_this = false; if (opline->op1_type == IS_UNUSED) { op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN; ce = op_array->scope; @@ -1939,7 +1943,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op ce_is_instanceof = !(ce->ce_flags & ZEND_ACC_FINAL); } op1_addr = 0; - on_this = 1; + on_this = true; } else { op1_info = OP1_INFO(); if (!(op1_info & MAY_BE_OBJECT)) { @@ -1973,8 +1977,8 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op break; } ce = NULL; - ce_is_instanceof = 0; - on_this = 0; + ce_is_instanceof = false; + on_this = false; if (opline->op1_type == IS_UNUSED) { op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN; ce = op_array->scope; @@ -1983,7 +1987,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op ce_is_instanceof = !(ce->ce_flags & ZEND_ACC_FINAL); } op1_addr = 0; - on_this = 1; + on_this = true; } else { op1_info = OP1_INFO(); if (!(op1_info & MAY_BE_OBJECT)) { @@ -2445,8 +2449,8 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op case ZEND_FETCH_OBJ_IS: case ZEND_FETCH_OBJ_W: ce = NULL; - ce_is_instanceof = 0; - on_this = 0; + ce_is_instanceof = false; + on_this = false; if (opline->op1_type == IS_UNUSED) { op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN; op1_addr = 0; @@ -2455,7 +2459,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op if (ce) { ce_is_instanceof = !(ce->ce_flags & ZEND_ACC_FINAL); } - on_this = 1; + on_this = true; } else { op1_info = OP1_INFO(); if (!(op1_info & MAY_BE_OBJECT)) { @@ -2625,8 +2629,8 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op break; } ce = NULL; - ce_is_instanceof = 0; - on_this = 0; + ce_is_instanceof = false; + on_this = false; if (opline->op1_type == IS_UNUSED) { op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN; op1_addr = 0; @@ -2635,7 +2639,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op if (ce) { ce_is_instanceof = !(ce->ce_flags & ZEND_ACC_FINAL); } - on_this = 1; + on_this = true; } else { op1_info = OP1_INFO(); if (!(op1_info & MAY_BE_OBJECT)) { @@ -2902,13 +2906,13 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op if (jit->return_inputs) { zend_jit_common_return(jit); - bool left_frame = 0; + bool left_frame = false; if (op_array->last_var > 100) { /* To many CVs to unroll */ if (!zend_jit_free_cvs(&ctx)) { goto jit_failure; } - left_frame = 1; + left_frame = true; } if (!left_frame) { int j; @@ -2918,7 +2922,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op if (info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) { if (!left_frame) { - left_frame = 1; + left_frame = true; if (!zend_jit_leave_frame(&ctx)) { goto jit_failure; } @@ -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; @@ -3090,8 +3098,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_runtime_jit(ZEND_OPCODE_HANDLE bool do_bailout = 0; zend_shared_alloc_lock(); + jit_extension = (zend_jit_op_array_extension*)ZEND_FUNC_INFO(op_array); - if (ZEND_FUNC_INFO(op_array)) { + if (jit_extension && !(jit_extension->func_info.flags & ZEND_FUNC_JITED)) { SHM_UNPROTECT(); zend_jit_unprotect(); @@ -3103,11 +3112,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_runtime_jit(ZEND_OPCODE_HANDLE opline++; } } - jit_extension = (zend_jit_op_array_extension*)ZEND_FUNC_INFO(op_array); ((zend_op*)opline)->handler = jit_extension->orig_handler; /* perform real JIT for this function */ zend_real_jit_func(op_array, NULL, NULL, ZEND_JIT_ON_FIRST_EXEC); + + jit_extension->func_info.flags |= ZEND_FUNC_JITED; } zend_catch { do_bailout = true; } zend_end_try(); @@ -3126,7 +3136,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 } @@ -3173,7 +3184,7 @@ void ZEND_FASTCALL zend_jit_hot_func(zend_execute_data *execute_data, const zend zend_shared_alloc_lock(); jit_extension = (zend_jit_op_array_hot_extension*)ZEND_FUNC_INFO(op_array); - if (jit_extension) { + if (jit_extension && !(jit_extension->func_info.flags & ZEND_FUNC_JITED)) { SHM_UNPROTECT(); zend_jit_unprotect(); @@ -3186,6 +3197,8 @@ void ZEND_FASTCALL zend_jit_hot_func(zend_execute_data *execute_data, const zend /* perform real JIT for this function */ zend_real_jit_func(op_array, NULL, opline, ZEND_JIT_ON_HOT_COUNTERS); + + jit_extension->func_info.flags |= ZEND_FUNC_JITED; } zend_catch { do_bailout = 1; } zend_end_try(); @@ -3213,7 +3226,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 +3236,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 +3327,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 +3357,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); } @@ -3566,23 +3579,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) @@ -3701,25 +3714,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."); @@ -3864,6 +3872,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) @@ -3904,12 +3920,12 @@ void zend_jit_deactivate(void) SHM_UNPROTECT(); zend_jit_unprotect(); - zend_jit_check_funcs(EG(function_table), 0); + zend_jit_check_funcs(EG(function_table), false); ZEND_HASH_MAP_REVERSE_FOREACH_PTR(EG(class_table), ce) { if (ce->type == ZEND_INTERNAL_CLASS) { break; } - zend_jit_check_funcs(&ce->function_table, 1); + zend_jit_check_funcs(&ce->function_table, true); } ZEND_HASH_FOREACH_END(); zend_jit_protect(); @@ -3920,8 +3936,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) { @@ -3945,37 +3963,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..9b8e054d2292f 100644 --- a/ext/opcache/jit/zend_jit.h +++ b/ext/opcache/jit/zend_jit.h @@ -64,15 +64,16 @@ #define ZEND_JIT_DEBUG_SIZE (1<<9) #define ZEND_JIT_DEBUG_ASM_ADDR (1<<10) -#define ZEND_JIT_DEBUG_TRACE_START (1<<12) -#define ZEND_JIT_DEBUG_TRACE_STOP (1<<13) -#define ZEND_JIT_DEBUG_TRACE_COMPILED (1<<14) -#define ZEND_JIT_DEBUG_TRACE_EXIT (1<<15) -#define ZEND_JIT_DEBUG_TRACE_ABORT (1<<16) -#define ZEND_JIT_DEBUG_TRACE_BLACKLIST (1<<17) -#define ZEND_JIT_DEBUG_TRACE_BYTECODE (1<<18) -#define ZEND_JIT_DEBUG_TRACE_TSSA (1<<19) -#define ZEND_JIT_DEBUG_TRACE_EXIT_INFO (1<<20) +#define ZEND_JIT_DEBUG_TRACE_START (1<<12) +#define ZEND_JIT_DEBUG_TRACE_STOP (1<<13) +#define ZEND_JIT_DEBUG_TRACE_COMPILED (1<<14) +#define ZEND_JIT_DEBUG_TRACE_EXIT (1<<15) +#define ZEND_JIT_DEBUG_TRACE_ABORT (1<<16) +#define ZEND_JIT_DEBUG_TRACE_BLACKLIST (1<<17) +#define ZEND_JIT_DEBUG_TRACE_BYTECODE (1<<18) +#define ZEND_JIT_DEBUG_TRACE_TSSA (1<<19) +#define ZEND_JIT_DEBUG_TRACE_EXIT_INFO (1<<20) +#define ZEND_JIT_DEBUG_TRACE_EXIT_INFO_SRC (1<<21) #define ZEND_JIT_DEBUG_IR_SRC (1<<24) #define ZEND_JIT_DEBUG_IR_FINAL (1<<25) @@ -145,8 +146,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..07f1b61c6b520 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -16,6 +16,8 @@ +----------------------------------------------------------------------+ */ +#include "Zend/zend_portability.h" +#include "Zend/zend_types.h" #include "Zend/zend_API.h" static ZEND_COLD void undef_result_after_exception(void) { @@ -500,36 +502,42 @@ 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)) { - /* The array may be destroyed while throwing the notice. - * Temporarily increase the refcount to detect this situation. */ - if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { - GC_ADDREF(ht); - } - execute_data = EG(current_execute_data); - opline = EX(opline); - zend_incompatible_double_to_long_error(Z_DVAL_P(dim)); - if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(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; - } - if (EG(exception)) { - if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + execute_data = EG(current_execute_data); + opline = EX(opline); + hval = zend_dval_to_lval_safe(Z_DVAL_P(dim)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(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; } + return; + } + if (EG(exception)) { + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + return; } goto num_index; case IS_RESOURCE: @@ -642,36 +650,41 @@ 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)) { - /* The array may be destroyed while throwing the notice. - * Temporarily increase the refcount to detect this situation. */ - if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { - GC_ADDREF(ht); - } - execute_data = EG(current_execute_data); - opline = EX(opline); - zend_incompatible_double_to_long_error(Z_DVAL_P(dim)); - if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(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; - } - if (EG(exception)) { - if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + execute_data = EG(current_execute_data); + opline = EX(opline); + hval = zend_dval_to_lval_safe(Z_DVAL_P(dim)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(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; } + return; + } + if (EG(exception)) { + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + return; } goto num_index; case IS_RESOURCE: @@ -769,25 +782,30 @@ 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)) { - /* The array may be destroyed while throwing the notice. - * Temporarily increase the refcount to detect this situation. */ - if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { - GC_ADDREF(ht); - } - zend_incompatible_double_to_long_error(Z_DVAL_P(dim)); - if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { - zend_array_destroy(ht); - return 0; - } - if (EG(exception)) { - return 0; - } + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + hval = zend_dval_to_lval_safe(Z_DVAL_P(dim)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + return 0; + } + if (EG(exception)) { + return 0; } goto num_index; case IS_RESOURCE: @@ -878,38 +896,61 @@ 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: - hval = zend_dval_to_lval(Z_DVAL_P(dim)); - if (!zend_is_long_compatible(Z_DVAL_P(dim), hval)) { - /* The array may be destroyed while throwing the notice. - * Temporarily increase the refcount to detect this situation. */ - if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { - GC_ADDREF(ht); - } - execute_data = EG(current_execute_data); - opline = EX(opline); - zend_incompatible_double_to_long_error(Z_DVAL_P(dim)); - 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; + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + execute_data = EG(current_execute_data); + opline = EX(opline); + hval = zend_dval_to_lval_safe(Z_DVAL_P(dim)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) { + if (!GC_REFCOUNT(ht)) { + zend_array_destroy(ht); } - if (EG(exception)) { - if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + 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; } + return NULL; + } + if (EG(exception)) { + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + return NULL; } goto num_index; case IS_RESOURCE: @@ -1011,38 +1052,65 @@ 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: - hval = zend_dval_to_lval(Z_DVAL_P(dim)); - if (!zend_is_long_compatible(Z_DVAL_P(dim), hval)) { - /* The array may be destroyed while throwing the notice. - * Temporarily increase the refcount to detect this situation. */ - if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { - GC_ADDREF(ht); - } - execute_data = EG(current_execute_data); - opline = EX(opline); - zend_incompatible_double_to_long_error(Z_DVAL_P(dim)); - 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; + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + execute_data = EG(current_execute_data); + opline = EX(opline); + hval = zend_dval_to_lval_safe(Z_DVAL_P(dim)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) { + if (!GC_REFCOUNT(ht)) { + zend_array_destroy(ht); } - if (EG(exception)) { - if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + 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; } + return NULL; + } + if (EG(exception)) { + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + return NULL; } goto num_index; case IS_RESOURCE: @@ -1129,10 +1197,13 @@ static zend_never_inline zend_long zend_check_string_offset(zval *dim, int type) zend_illegal_container_offset(ZSTR_KNOWN(ZEND_STR_STRING), dim, BP_VAR_R); return 0; } + case IS_DOUBLE: + /* Suppress potential double warning */ + zend_error(E_WARNING, "String offset cast occurred"); + return zend_dval_to_lval_silent(Z_DVAL_P(dim)); case IS_UNDEF: zend_jit_undefined_op_helper(EG(current_execute_data)->opline->op2.var); ZEND_FALLTHROUGH; - case IS_DOUBLE: case IS_NULL: case IS_FALSE: case IS_TRUE: @@ -1204,14 +1275,17 @@ static void ZEND_FASTCALL zend_jit_fetch_dim_str_is_helper(zend_string *str, zva switch (Z_TYPE_P(dim)) { /* case IS_LONG: */ case IS_STRING: - if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, false)) { - break; + if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), &offset, NULL, false)) { + goto out; } ZVAL_NULL(result); return; + case IS_DOUBLE: + offset = zend_dval_to_lval_silent(Z_DVAL_P(dim)); + goto out; case IS_UNDEF: zend_jit_undefined_op_helper(EG(current_execute_data)->opline->op2.var); - case IS_DOUBLE: + ZEND_FALLTHROUGH; case IS_NULL: case IS_FALSE: case IS_TRUE: @@ -1232,6 +1306,7 @@ static void ZEND_FASTCALL zend_jit_fetch_dim_str_is_helper(zend_string *str, zva offset = Z_LVAL_P(dim); } +out: if ((zend_ulong)offset >= (zend_ulong)ZSTR_LEN(str)) { if (offset < 0) { /* Handle negative offset */ @@ -1904,7 +1979,7 @@ static bool ZEND_FASTCALL zend_jit_verify_arg_slow(zval *arg, zend_arg_info *arg &arg_info->type, arg, /* ref */ NULL, /* is_return_type */ false); if (UNEXPECTED(!ret)) { zend_verify_arg_error(EX(func), arg_info, opline->op1.num, arg); - return 0; + return false; } return ret; } @@ -2045,8 +2120,13 @@ static zval* ZEND_FASTCALL zend_jit_fetch_obj_r_slow_ex(zend_object *zobj) void **cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS); retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, result); - if (retval == result && UNEXPECTED(Z_ISREF_P(retval))) { - zend_unwrap_reference(retval); + if (UNEXPECTED(Z_ISREF_P(retval))) { + if (retval == result) { + zend_unwrap_reference(retval); + } else { + retval = Z_REFVAL_P(retval); + } + ZEND_ASSERT(!Z_REFCOUNTED_P(retval)); } return retval; } @@ -2561,11 +2641,24 @@ 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)); } +static void ZEND_FASTCALL zend_jit_nan_coerced_to_type_warning(void) +{ + zend_nan_coerced_to_type_warning(_IS_BOOL); +} + static void ZEND_FASTCALL zend_jit_invalid_property_read(zval *container, const char *property_name) { zend_error(E_WARNING, "Attempt to read property \"%s\" on %s", property_name, 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..22bab1ddd7ffd 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; @@ -118,19 +119,19 @@ typedef uintptr_t zend_jit_addr; static zend_always_inline bool zend_jit_same_addr(zend_jit_addr addr1, zend_jit_addr addr2) { if (addr1 == addr2) { - return 1; + return true; } else if (Z_MODE(addr1) == IS_REG && Z_MODE(addr2) == IS_REG) { return Z_SSA_VAR(addr1) == Z_SSA_VAR(addr2); } else if (Z_MODE(addr1) == IS_REF_ZVAL && Z_MODE(addr2) == IS_REF_ZVAL) { return Z_IR_REF(addr1) == Z_IR_REF(addr2); } - return 0; + return false; } 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; }; @@ -453,6 +456,10 @@ typedef struct _zend_jit_trace_exit_info { uint32_t stack_offset; zend_jit_ref_snapshot poly_func; zend_jit_ref_snapshot poly_this; +#if ZEND_DEBUG + const char *filename; + int lineno; +#endif } zend_jit_trace_exit_info; typedef struct _zend_jit_trace_stack { @@ -668,9 +675,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, @@ -697,7 +706,7 @@ static zend_always_inline const zend_op* zend_jit_trace_get_exit_opline(zend_jit } else { ZEND_UNREACHABLE(); } - *exit_if_true = 0; + *exit_if_true = false; return NULL; } diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 6aa7896554920..1c5cab899e783 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -16,8 +16,11 @@ * +----------------------------------------------------------------------+ */ +#include "Zend/zend_types.h" +#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 +29,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 +58,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 +84,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)) @@ -168,18 +199,12 @@ static size_t zend_jit_trace_prologue_size = (size_t)-1; static uint32_t allowed_opt_flags = 0; static uint32_t default_mflags = 0; #endif -static bool delayed_call_chain = 0; // TODO: remove this var (use jit->delayed_call_level) ??? +static bool delayed_call_chain = false; // 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 +359,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); @@ -397,7 +424,7 @@ static bool zend_jit_set_veneer(ir_ctx *ctx, const void *addr, const void *venee uint32_t exit_point = zend_jit_exit_point_by_addr(addr); if (exit_point != (uint32_t)-1) { - return 1; + return true; } for (i = 0; i < count; i++) { if (zend_jit_stub_handlers[i] == addr) { @@ -422,11 +449,11 @@ static bool zend_jit_set_veneer(ir_ctx *ctx, const void *addr, const void *venee } } #endif - return 1; + return true; } } - return 0; + return false; } static void zend_jit_commit_veneers(void) @@ -445,7 +472,7 @@ static void zend_jit_commit_veneers(void) static bool zend_jit_prefer_const_addr_load(zend_jit_ctx *jit, uintptr_t addr) { #if defined(IR_TARGET_X86) - return 0; /* always use immediate value */ + return false; /* always use immediate value */ #elif defined(IR_TARGET_X64) return addr > 0xffffffff; /* prefer loading long constant from memery */ #elif defined(IR_TARGET_AARCH64) @@ -463,6 +490,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 +514,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 +579,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) { @@ -946,15 +989,15 @@ static void jit_LOAD_IP_ADDR(zend_jit_ctx *jit, const zend_op *target) static void zend_jit_track_last_valid_opline(zend_jit_ctx *jit) { - jit->use_last_valid_opline = 0; - jit->track_last_valid_opline = 1; + jit->use_last_valid_opline = false; + jit->track_last_valid_opline = true; } static void zend_jit_use_last_valid_opline(zend_jit_ctx *jit) { if (jit->track_last_valid_opline) { - jit->use_last_valid_opline = 1; - jit->track_last_valid_opline = 0; + jit->use_last_valid_opline = true; + jit->track_last_valid_opline = false; } } @@ -966,21 +1009,21 @@ static bool zend_jit_trace_uses_initial_ip(zend_jit_ctx *jit) static void zend_jit_set_last_valid_opline(zend_jit_ctx *jit, const zend_op *opline) { if (!jit->reuse_ip) { - jit->track_last_valid_opline = 1; + jit->track_last_valid_opline = true; jit->last_valid_opline = opline; } } static void zend_jit_reset_last_valid_opline(zend_jit_ctx *jit) { - jit->track_last_valid_opline = 0; + jit->track_last_valid_opline = false; jit->last_valid_opline = NULL; } static void zend_jit_start_reuse_ip(zend_jit_ctx *jit) { zend_jit_reset_last_valid_opline(jit); - jit->reuse_ip = 1; + jit->reuse_ip = true; } static int zend_jit_reuse_ip(zend_jit_ctx *jit) @@ -995,7 +1038,7 @@ static int zend_jit_reuse_ip(zend_jit_ctx *jit) static void zend_jit_stop_reuse_ip(zend_jit_ctx *jit) { - jit->reuse_ip = 0; + jit->reuse_ip = false; } static int zend_jit_save_call_chain(zend_jit_ctx *jit, uint32_t call_level) @@ -1019,7 +1062,7 @@ static int zend_jit_save_call_chain(zend_jit_ctx *jit, uint32_t call_level) ir_STORE(jit_EX(call), rx); jit->delayed_call_level = 0; - delayed_call_chain = 0; + delayed_call_chain = false; return 1; } @@ -1048,7 +1091,7 @@ static int zend_jit_set_ip(zend_jit_ctx *jit, const zend_op *target) } else { jit_STORE_IP(jit, ir_CONST_ADDR(target)); } - jit->reuse_ip = 0; + jit->reuse_ip = false; zend_jit_set_last_valid_opline(jit, target); return 1; } @@ -1266,7 +1309,7 @@ static bool zend_jit_spilling_may_cause_conflict(zend_jit_ctx *jit, int var, ir_ { if (jit->ctx.ir_base[val].op == IR_RLOAD) { /* Deoptimization */ - return 0; + return false; } // if (jit->ctx.ir_base[val].op == IR_LOAD // && jit->ctx.ir_base[jit->ctx.ir_base[val].op2].op == IR_ADD @@ -1288,7 +1331,7 @@ static bool zend_jit_spilling_may_cause_conflict(zend_jit_ctx *jit, int var, ir_ && jit->ctx.ir_base[jit->ctx.ir_base[jit->ctx.ir_base[val].op2].op2].val.addr != (uintptr_t)EX_NUM_TO_VAR(jit->ssa->vars[var].var) && EX_VAR_TO_NUM(jit->ctx.ir_base[jit->ctx.ir_base[jit->ctx.ir_base[val].op2].op2].val.addr) < jit->current_op_array->last_var) { /* binding between different CVs may cause spill conflict */ - return 1; + return true; } else if (jit->ssa->vars[var].definition >= 0 && jit->ssa->ops[jit->ssa->vars[var].definition].op1_def == var && jit->ssa->ops[jit->ssa->vars[var].definition].op1_use >= 0 @@ -1296,18 +1339,18 @@ static bool zend_jit_spilling_may_cause_conflict(zend_jit_ctx *jit, int var, ir_ && jit->ssa->vars[jit->ssa->ops[jit->ssa->vars[var].definition].op1_use].definition_phi && (jit->ssa->cfg.blocks[jit->ssa->vars[jit->ssa->ops[jit->ssa->vars[var].definition].op1_use].definition_phi->block].flags & ZEND_BB_LOOP_HEADER)) { /* Avoid moving spill store out of loop */ - return 1; + return true; } else if (jit->ssa->vars[var].definition >= 0 && jit->ssa->ops[jit->ssa->vars[var].definition].op1_def == var && jit->ssa->ops[jit->ssa->vars[var].definition].op1_use >= 0 && jit->ssa->ops[jit->ssa->vars[var].definition].op2_use >= 0 && jit->ra[jit->ssa->ops[jit->ssa->vars[var].definition].op2_use].ref == val) { /* Avoid spill conflict between of ASSIGN.op1_def and ASSIGN.op1_use */ - return 1; + return true; } - return 0; + return false; } - return 1; + return true; } static void zend_jit_def_reg(zend_jit_ctx *jit, zend_jit_addr addr, ir_ref val) @@ -1442,7 +1485,7 @@ static void zend_jit_gen_phi(zend_jit_ctx *jit, zend_ssa_phi *phi) ir_ref ref; ir_ref old_insns_count = jit->ctx.insns_count; ir_ref same_src_ref = IR_UNUSED; - bool phi_inputs_are_the_same = 1; + bool phi_inputs_are_the_same = true; ZEND_ASSERT(phi->pi < 0); ZEND_ASSERT(!(jit->ra[dst_var].flags & ZREG_LOAD)); @@ -1459,13 +1502,13 @@ static void zend_jit_gen_phi(zend_jit_ctx *jit, zend_ssa_phi *phi) ZEND_ASSERT(jit->ra[src_var].ref); if (jit->ra[src_var].ref == IR_NULL) { jit->ra[src_var].flags |= ZREG_FORWARD; - phi_inputs_are_the_same = 0; + phi_inputs_are_the_same = false; } else { ir_ref src_ref = zend_jit_use_reg(jit, ZEND_ADDR_REG(src_var)); if (i == 0) { same_src_ref = src_ref; } else if (same_src_ref != src_ref) { - phi_inputs_are_the_same = 0; + phi_inputs_are_the_same = false; } ir_set_op(&jit->ctx, ref, i + 2, src_ref); } @@ -1854,7 +1897,7 @@ static void jit_FREE_OP(zend_jit_ctx *jit, if (op_type & (IS_VAR|IS_TMP_VAR)) { jit_ZVAL_PTR_DTOR(jit, ZEND_ADDR_MEM_ZVAL(ZREG_FP, op.var), - op_info, 0, opline); + op_info, false, opline); } } @@ -1914,24 +1957,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); } } @@ -1975,7 +2030,7 @@ static int zend_jit_exception_handler_free_op1_op2_stub(zend_jit_ctx *jit) } ref = ir_ADD_A(jit_FP(jit), ref); var_addr = ZEND_ADDR_REF_ZVAL(ref); - jit_ZVAL_PTR_DTOR(jit, var_addr, MAY_BE_ANY|MAY_BE_RC1|MAY_BE_RCN|MAY_BE_REF, 0, NULL); + jit_ZVAL_PTR_DTOR(jit, var_addr, MAY_BE_ANY|MAY_BE_RC1|MAY_BE_RCN|MAY_BE_REF, false, NULL); ir_MERGE_WITH_EMPTY_FALSE(if_dtor); ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler_free_op2)); @@ -1998,7 +2053,7 @@ static int zend_jit_exception_handler_free_op2_stub(zend_jit_ctx *jit) } ref = ir_ADD_A(jit_FP(jit), ref); var_addr = ZEND_ADDR_REF_ZVAL(ref); - jit_ZVAL_PTR_DTOR(jit, var_addr, MAY_BE_ANY|MAY_BE_RC1|MAY_BE_RCN|MAY_BE_REF, 0, NULL); + jit_ZVAL_PTR_DTOR(jit, var_addr, MAY_BE_ANY|MAY_BE_RC1|MAY_BE_RCN|MAY_BE_REF, false, NULL); ir_MERGE_WITH_EMPTY_FALSE(if_dtor); ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler_undef)); @@ -2030,8 +2085,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 +2095,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 +2117,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 +2127,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) @@ -2176,7 +2236,7 @@ static int zend_jit_throw_cannot_pass_by_ref_stub(zend_jit_ctx *jit) ref = ir_ADD_A(jit_FP(jit), ref); jit_ZVAL_PTR_DTOR(jit, ZEND_ADDR_REF_ZVAL(ref), - MAY_BE_ANY|MAY_BE_RC1|MAY_BE_RCN|MAY_BE_REF, 0, NULL); + MAY_BE_ANY|MAY_BE_RC1|MAY_BE_RCN|MAY_BE_REF, false, NULL); ir_MERGE_WITH_EMPTY_FALSE(if_tmp); ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler)); @@ -2228,7 +2288,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 +2302,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 +2315,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 +2371,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 +2381,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 +2436,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 +2453,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 +2463,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 +2473,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 +2486,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 +2513,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 +2533,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 +2551,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 +2562,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; @@ -2548,7 +2608,7 @@ static int zend_jit_assign_const_stub(zend_jit_ctx *jit) jit, NULL, var_addr, var_addr, -1, -1, IS_CONST, val_addr, val_info, - 0, 0, 0)) { + 0, 0, false)) { return 0; } ir_RETURN(IR_VOID); @@ -2568,7 +2628,7 @@ static int zend_jit_assign_tmp_stub(zend_jit_ctx *jit) jit, NULL, var_addr, var_addr, -1, -1, IS_TMP_VAR, val_addr, val_info, - 0, 0, 0)) { + 0, 0, false)) { return 0; } ir_RETURN(IR_VOID); @@ -2588,7 +2648,7 @@ static int zend_jit_assign_var_stub(zend_jit_ctx *jit) jit, NULL, var_addr, var_addr, -1, -1, IS_VAR, val_addr, val_info, - 0, 0, 0)) { + 0, 0, false)) { return 0; } ir_RETURN(IR_VOID); @@ -2608,7 +2668,7 @@ static int zend_jit_assign_cv_noref_stub(zend_jit_ctx *jit) jit, NULL, var_addr, var_addr, -1, -1, IS_CV, val_addr, val_info, - 0, 0, 0)) { + 0, 0, false)) { return 0; } ir_RETURN(IR_VOID); @@ -2640,7 +2700,7 @@ static int zend_jit_assign_cv_stub(zend_jit_ctx *jit) jit, NULL, var_addr, var_addr, -1, -1, IS_CV, val_addr, val_info, - 0, 0, 0)) { + 0, 0, false)) { return 0; } ir_RETURN(IR_VOID); @@ -2670,11 +2730,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 +2760,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 @@ -2727,11 +2814,11 @@ static void zend_jit_init_ctx(zend_jit_ctx *jit, uint32_t flags) jit->ssa = NULL; jit->name = NULL; jit->last_valid_opline = NULL; - jit->use_last_valid_opline = 0; - jit->track_last_valid_opline = 0; - jit->reuse_ip = 0; + jit->use_last_valid_opline = false; + jit->track_last_valid_opline = false; + jit->reuse_ip = false; jit->delayed_call_level = 0; - delayed_call_chain = 0; + delayed_call_chain = false; jit->b = -1; #ifdef ZTS jit->tls = IR_UNUSED; @@ -3127,6 +3214,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 +3227,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 +3384,6 @@ static void zend_jit_setup_unwinder(void) } #endif - static void zend_jit_setup(bool reattached) { #if defined(IR_TARGET_X86) @@ -3312,170 +3402,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 @@ -3729,7 +3670,7 @@ static void zend_jit_case_start(zend_jit_ctx *jit, int switch_b, int case_b, ir_ int default_b = jit->ssa->cfg.map[default_opline - jit->op_array->opcodes]; zval *zv; ir_ref list = IR_UNUSED, idx; - bool first = 1; + bool first = true; ZEND_HASH_FOREACH_VAL(jumptable, zv) { const zend_op *target = ZEND_OFFSET_TO_OPLINE(opline, Z_LVAL_P(zv)); @@ -3745,7 +3686,7 @@ static void zend_jit_case_start(zend_jit_ctx *jit, int switch_b, int case_b, ir_ idx = ir_CONST_LONG((Bucket*)zv - jumptable->arData); } ir_CASE_VAL(switch_ref, idx); - first = 0; + first = false; } } ZEND_HASH_FOREACH_END(); if (default_b == case_b) { @@ -4125,7 +4066,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 +4087,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 +4103,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 +4117,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 +4156,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 +4186,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 +4264,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)) { @@ -4565,7 +4509,7 @@ static int zend_jit_store_var_if_necessary(zend_jit_ctx *jit, int var, zend_jit_ { if (Z_MODE(src) == IS_REG && Z_STORE(src)) { zend_jit_addr dst = ZEND_ADDR_MEM_ZVAL(ZREG_FP, var); - return zend_jit_spill_store(jit, src, dst, info, 1); + return zend_jit_spill_store(jit, src, dst, info, true); } return 1; } @@ -4574,7 +4518,7 @@ static int zend_jit_store_var_if_necessary_ex(zend_jit_ctx *jit, int var, zend_j { if (Z_MODE(src) == IS_REG && Z_STORE(src)) { zend_jit_addr dst = ZEND_ADDR_MEM_ZVAL(ZREG_FP, var); - bool set_type = 1; + bool set_type = true; if ((info & (MAY_BE_ANY|MAY_BE_REF|MAY_BE_UNDEF)) == (old_info & (MAY_BE_ANY|MAY_BE_REF|MAY_BE_UNDEF))) { @@ -4584,10 +4528,10 @@ static int zend_jit_store_var_if_necessary_ex(zend_jit_ctx *jit, int var, zend_j if (mem_type != IS_UNKNOWN && (info & (MAY_BE_ANY|MAY_BE_REF|MAY_BE_UNDEF)) == (1 << mem_type)) { - set_type = 0; + set_type = false; } } else { - set_type = 0; + set_type = false; } } } @@ -4865,33 +4809,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); @@ -5041,7 +4982,7 @@ static int zend_jit_inc_dec(zend_jit_ctx *jit, const zend_op *opline, uint32_t o jit_ZVAL_COPY(jit, res_addr, res_use_info, - ZEND_ADDR_REF_ZVAL(ref), op1_info, 1); + ZEND_ADDR_REF_ZVAL(ref), op1_info, true); } if (opline->opcode == ZEND_PRE_INC || opline->opcode == ZEND_POST_INC) { if (opline->opcode == ZEND_PRE_INC && opline->result_type != IS_UNUSED) { @@ -6332,16 +6273,16 @@ static int zend_jit_simple_assign(zend_jit_ctx *jit, jit_ZVAL_COPY_CONST(jit, var_addr, var_info, var_def_info, - zv, 1); + zv, true); } else { jit_ZVAL_COPY_CONST(jit, var_addr, var_info, var_def_info, - zv, 1); + zv, true); jit_ZVAL_COPY_CONST(jit, res_addr, -1, var_def_info, - zv, 1); + zv, true); } } else { if (val_info & MAY_BE_UNDEF) { @@ -6386,7 +6327,7 @@ static int zend_jit_simple_assign(zend_jit_ctx *jit, jit_ZVAL_COPY(jit, var_addr, var_info, - ZEND_ADDR_REF_ZVAL(ref2), val_info, 1); + ZEND_ADDR_REF_ZVAL(ref2), val_info, true); } else { jit_ZVAL_COPY_2(jit, res_addr, @@ -6527,7 +6468,7 @@ static int zend_jit_assign_to_variable(zend_jit_ctx *jit, { ir_ref if_refcounted = IR_UNUSED; ir_ref simple_inputs = IR_UNUSED; - bool done = 0; + bool done = false; zend_jit_addr real_res_addr = 0; ir_refs *end_inputs; ir_refs *res_inputs; @@ -6637,11 +6578,11 @@ static int zend_jit_assign_to_variable(zend_jit_ctx *jit, ir_END_list(simple_inputs); ir_IF_TRUE_cold(if_refcounted); } else if (RC_MAY_BE_1(var_info)) { - done = 1; + done = true; } ref = jit_Z_PTR(jit, var_use_addr); if (RC_MAY_BE_1(var_info)) { - if (!zend_jit_simple_assign(jit, opline, var_addr, var_info, var_def_info, val_type, val_addr, val_info, res_addr, 0)) { + if (!zend_jit_simple_assign(jit, opline, var_addr, var_info, var_def_info, val_type, val_addr, val_info, res_addr, false)) { return 0; } counter = jit_GC_DELREF(jit, ref); @@ -6759,7 +6700,7 @@ static int zend_jit_qm_assign(zend_jit_ctx *jit, const zend_op *opline, uint32_t } } - if (!zend_jit_simple_assign(jit, opline, res_addr, res_use_info, res_info, opline->op1_type, op1_addr, op1_info, 0, 1)) { + if (!zend_jit_simple_assign(jit, opline, res_addr, res_use_info, res_info, opline->op1_type, op1_addr, op1_info, 0, true)) { return 0; } if (!zend_jit_store_var_if_necessary(jit, opline->result.var, res_addr, res_info)) { @@ -7265,11 +7206,11 @@ static int zend_jit_cmp(zend_jit_ctx *jit, op1 = jit_ZVAL_ADDR(jit, op1_addr); if (opline->op1_type == IS_CV && (op1_info & MAY_BE_UNDEF)) { - op1 = zend_jit_zval_check_undef(jit, op1, opline->op1.var, NULL, 0); + op1 = zend_jit_zval_check_undef(jit, op1, opline->op1.var, NULL, false); } op2 = jit_ZVAL_ADDR(jit, op2_addr); if (opline->op2_type == IS_CV && (op2_info & MAY_BE_UNDEF)) { - op2 = zend_jit_zval_check_undef(jit, op2, opline->op2.var, NULL, 0); + op2 = zend_jit_zval_check_undef(jit, op2, opline->op2.var, NULL, false); } ref = ir_CALL_2(IR_I32, ir_CONST_FC_FUNC(zend_compare), op1, op2); if (opline->opcode != ZEND_CASE) { @@ -7362,34 +7303,34 @@ static int zend_jit_identical(zend_jit_ctx *jit, const void *exit_addr, bool skip_comparison) { - bool always_false = 0, always_true = 0; + bool always_false = false, always_true = false; ir_ref ref = IR_UNUSED; if (opline->op1_type == IS_CV && (op1_info & MAY_BE_UNDEF)) { ir_ref op1 = jit_ZVAL_ADDR(jit, op1_addr); - op1 = zend_jit_zval_check_undef(jit, op1, opline->op1.var, opline, 0); + op1 = zend_jit_zval_check_undef(jit, op1, opline->op1.var, opline, false); op1_info |= MAY_BE_NULL; op1_addr = ZEND_ADDR_REF_ZVAL(op1); } if (opline->op2_type == IS_CV && (op2_info & MAY_BE_UNDEF)) { ir_ref op2 = jit_ZVAL_ADDR(jit, op2_addr); - op2 = zend_jit_zval_check_undef(jit, op2, opline->op2.var, opline, 0); + op2 = zend_jit_zval_check_undef(jit, op2, opline->op2.var, opline, false); op2_info |= MAY_BE_NULL; op2_addr = ZEND_ADDR_REF_ZVAL(op2); } if ((op1_info & op2_info & MAY_BE_ANY) == 0) { - always_false = 1; + always_false = true; } else if (has_concrete_type(op1_info) && has_concrete_type(op2_info) && concrete_type(op1_info) == concrete_type(op2_info) && concrete_type(op1_info) <= IS_TRUE) { - always_true = 1; + always_true = true; } else if (Z_MODE(op1_addr) == IS_CONST_ZVAL && Z_MODE(op2_addr) == IS_CONST_ZVAL) { if (zend_is_identical(Z_ZV(op1_addr), Z_ZV(op2_addr))) { - always_true = 1; + always_true = true; } else { - always_false = 1; + always_false = true; } } @@ -7591,17 +7532,17 @@ static int zend_jit_bool_jmpznz(zend_jit_ctx *jit, const zend_op *opline, uint32 { uint32_t true_label = -1; uint32_t false_label = -1; - bool set_bool = 0; - bool set_bool_not = 0; - bool always_true = 0, always_false = 0; + bool set_bool = false; + bool set_bool_not = false; + bool always_true = false, always_false = false; ir_ref ref, end_inputs = IR_UNUSED, true_inputs = IR_UNUSED, false_inputs = IR_UNUSED; ir_type type = IR_UNUSED; if (branch_opcode == ZEND_BOOL) { - set_bool = 1; + set_bool = true; } else if (branch_opcode == ZEND_BOOL_NOT) { - set_bool = 1; - set_bool_not = 1; + set_bool = true; + set_bool_not = true; } else if (branch_opcode == ZEND_JMPZ) { true_label = target_label2; false_label = target_label; @@ -7609,11 +7550,11 @@ static int zend_jit_bool_jmpznz(zend_jit_ctx *jit, const zend_op *opline, uint32 true_label = target_label; false_label = target_label2; } else if (branch_opcode == ZEND_JMPZ_EX) { - set_bool = 1; + set_bool = true; true_label = target_label2; false_label = target_label; } else if (branch_opcode == ZEND_JMPNZ_EX) { - set_bool = 1; + set_bool = true; true_label = target_label; false_label = target_label2; } else { @@ -7626,21 +7567,23 @@ static int zend_jit_bool_jmpznz(zend_jit_ctx *jit, const zend_op *opline, uint32 op1_addr = ZEND_ADDR_REF_ZVAL(ref); } - if (Z_MODE(op1_addr) == IS_CONST_ZVAL) { + if (Z_MODE(op1_addr) == IS_CONST_ZVAL + /* NAN Value must cause a warning to be emitted */ + && (Z_TYPE_P(Z_ZV(op1_addr)) != IS_DOUBLE || !zend_isnan(Z_DVAL_P(Z_ZV(op1_addr))))) { if (zend_is_true(Z_ZV(op1_addr))) { - always_true = 1; + always_true = true; } else { - always_false = 1; + always_false = true; } } else if (op1_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE)) { if (!(op1_info & ((MAY_BE_UNDEF|MAY_BE_ANY)-MAY_BE_TRUE))) { - always_true = 1; + always_true = true; } else if (!(op1_info & (MAY_BE_ANY-(MAY_BE_NULL|MAY_BE_FALSE)))) { if (opline->op1_type == IS_CV && (op1_info & MAY_BE_UNDEF)) { ref = jit_ZVAL_ADDR(jit, op1_addr); - zend_jit_zval_check_undef(jit, ref, opline->op1.var, opline, 0); + zend_jit_zval_check_undef(jit, ref, opline->op1.var, opline, false); } - always_false = 1; + always_false = true; } } @@ -7685,7 +7628,7 @@ static int zend_jit_bool_jmpznz(zend_jit_ctx *jit, const zend_op *opline, uint32 zend_jit_type_check_undef(jit, type, opline->op1.var, - opline, 1, 0, 1); + opline, true, false, true); } if (set_bool) { jit_set_Z_TYPE_INFO(jit, res_addr, set_bool_not ? IS_TRUE : IS_FALSE); @@ -7794,7 +7737,16 @@ static int zend_jit_bool_jmpznz(zend_jit_ctx *jit, const zend_op *opline, uint32 if_double = ir_IF(ir_EQ(type, ir_CONST_U8(IS_DOUBLE))); ir_IF_TRUE(if_double); } - ref = ir_NE(jit_Z_DVAL(jit, op1_addr), ir_CONST_DOUBLE(0.0)); + + ir_ref dval = jit_Z_DVAL(jit, op1_addr); + ir_ref is_nan = ir_NE(dval, dval); + ir_ref if_val = ir_IF(is_nan); + ir_IF_TRUE_cold(if_val); + jit_SET_EX_OPLINE(jit, opline); + ir_CALL(IR_VOID, ir_CONST_FC_FUNC(zend_jit_nan_coerced_to_type_warning)); + ir_MERGE_WITH_EMPTY_FALSE(if_val); + + ref = ir_NE(dval, ir_CONST_DOUBLE(0.0)); if (branch_opcode == ZEND_BOOL || branch_opcode == ZEND_BOOL_NOT) { if (set_bool_not) { jit_set_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit, res_addr), @@ -8033,7 +7985,7 @@ static int zend_jit_restore_zval(zend_jit_ctx *jit, int var, int8_t reg) zend_jit_addr reg_addr = ZEND_ADDR_REF_ZVAL(zend_jit_deopt_rload(jit, IR_ADDR, reg)); // JIT: ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), &c->value); (no dup) - jit_ZVAL_COPY(jit, var_addr, MAY_BE_ANY, reg_addr, MAY_BE_ANY, 1); + jit_ZVAL_COPY(jit, var_addr, MAY_BE_ANY, reg_addr, MAY_BE_ANY, true); return 1; } @@ -8170,7 +8122,7 @@ static int zend_jit_fetch_constant(zend_jit_ctx *jit, uint8_t type = concrete_type(res_info); zend_jit_addr const_addr = ZEND_ADDR_REF_ZVAL(ref); - const_addr = zend_jit_guard_fetch_result_type(jit, opline, const_addr, type, 0, 0, 0); + const_addr = zend_jit_guard_fetch_result_type(jit, opline, const_addr, type, false, 0, false); if (!const_addr) { return 0; } @@ -8179,7 +8131,7 @@ static int zend_jit_fetch_constant(zend_jit_ctx *jit, ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD; // JIT: ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), &c->value); (no dup) - jit_ZVAL_COPY(jit, res_addr, MAY_BE_ANY, const_addr, res_info, 1); + jit_ZVAL_COPY(jit, res_addr, MAY_BE_ANY, const_addr, res_info, true); if (!zend_jit_store_var_if_necessary(jit, opline->result.var, res_addr, res_info)) { return 0; } @@ -8187,7 +8139,7 @@ static int zend_jit_fetch_constant(zend_jit_ctx *jit, ir_ref const_addr = ZEND_ADDR_REF_ZVAL(ref); // JIT: ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), &c->value); (no dup) - jit_ZVAL_COPY(jit, res_addr, MAY_BE_ANY, const_addr, MAY_BE_ANY, 1); + jit_ZVAL_COPY(jit, res_addr, MAY_BE_ANY, const_addr, MAY_BE_ANY, true); } @@ -8298,7 +8250,7 @@ static int zend_jit_type_check(zend_jit_ctx *jit, const zend_op *opline, uint32_ } } else { ir_ref ref; - bool invert = 0; + bool invert = false; uint8_t type; switch (mask) { @@ -8310,15 +8262,15 @@ static int zend_jit_type_check(zend_jit_ctx *jit, const zend_op *opline, uint32_ case MAY_BE_STRING: type = IS_STRING; break; case MAY_BE_ARRAY: type = IS_ARRAY; break; case MAY_BE_OBJECT: type = IS_OBJECT; break; - case MAY_BE_ANY - MAY_BE_NULL: type = IS_NULL; invert = 1; break; - case MAY_BE_ANY - MAY_BE_FALSE: type = IS_FALSE; invert = 1; break; - case MAY_BE_ANY - MAY_BE_TRUE: type = IS_TRUE; invert = 1; break; - case MAY_BE_ANY - MAY_BE_LONG: type = IS_LONG; invert = 1; break; - case MAY_BE_ANY - MAY_BE_DOUBLE: type = IS_DOUBLE; invert = 1; break; - case MAY_BE_ANY - MAY_BE_STRING: type = IS_STRING; invert = 1; break; - case MAY_BE_ANY - MAY_BE_ARRAY: type = IS_ARRAY; invert = 1; break; - case MAY_BE_ANY - MAY_BE_OBJECT: type = IS_OBJECT; invert = 1; break; - case MAY_BE_ANY - MAY_BE_RESOURCE: type = IS_OBJECT; invert = 1; break; + case MAY_BE_ANY - MAY_BE_NULL: type = IS_NULL; invert = true; break; + case MAY_BE_ANY - MAY_BE_FALSE: type = IS_FALSE; invert = true; break; + case MAY_BE_ANY - MAY_BE_TRUE: type = IS_TRUE; invert = true; break; + case MAY_BE_ANY - MAY_BE_LONG: type = IS_LONG; invert = true; break; + case MAY_BE_ANY - MAY_BE_DOUBLE: type = IS_DOUBLE; invert = true; break; + case MAY_BE_ANY - MAY_BE_STRING: type = IS_STRING; invert = true; break; + case MAY_BE_ANY - MAY_BE_ARRAY: type = IS_ARRAY; invert = true; break; + case MAY_BE_ANY - MAY_BE_OBJECT: type = IS_OBJECT; invert = true; break; + case MAY_BE_ANY - MAY_BE_RESOURCE: type = IS_OBJECT; invert = true; break; default: type = 0; } @@ -8502,14 +8454,14 @@ static int zend_jit_push_call_frame(zend_jit_ctx *jit, const zend_op *opline, co { uint32_t used_stack; ir_ref used_stack_ref = IR_UNUSED; - bool stack_check = 1; + bool stack_check = true; ir_ref rx, ref, top, if_enough_stack, cold_path = IR_UNUSED; ZEND_ASSERT(func_ref != IR_NULL); if (func) { used_stack = zend_vm_calc_used_stack(opline->extended_value, func); if ((int)used_stack <= checked_stack) { - stack_check = 0; + stack_check = false; } used_stack_ref = ir_CONST_ADDR(used_stack); } else { @@ -8938,7 +8890,7 @@ jit_SET_EX_OPLINE(jit, opline); func_ref = ir_PHI_2(IR_ADDR, ref, func_ref); } - if (!zend_jit_push_call_frame(jit, opline, op_array, func, 0, 0, checked_stack, func_ref, IR_UNUSED)) { + if (!zend_jit_push_call_frame(jit, opline, op_array, func, false, false, checked_stack, func_ref, IR_UNUSED)) { return 0; } @@ -8949,7 +8901,7 @@ jit_SET_EX_OPLINE(jit, opline); } else { ZEND_ASSERT(call_level > 0); jit->delayed_call_level = call_level; - delayed_call_chain = 1; + delayed_call_chain = true; } if (trace @@ -9197,7 +9149,7 @@ static int zend_jit_init_method_call(zend_jit_ctx *jit, } if (!func || (func->common.fn_flags & ZEND_ACC_STATIC) == 0) { - if (!zend_jit_push_call_frame(jit, opline, NULL, func, 0, delayed_fetch_this, checked_stack, func_ref, this_ref)) { + if (!zend_jit_push_call_frame(jit, opline, NULL, func, false, delayed_fetch_this, checked_stack, func_ref, this_ref)) { return 0; } } @@ -9213,7 +9165,7 @@ static int zend_jit_init_method_call(zend_jit_ctx *jit, } } else { ZEND_ASSERT(call_level > 0); - delayed_call_chain = 1; + delayed_call_chain = true; jit->delayed_call_level = call_level; } @@ -9375,7 +9327,7 @@ static int zend_jit_init_static_method_call(zend_jit_ctx *jit, scope_ref = ir_LOAD_A(ir_ADD_OFFSET(ir_LOAD_A(jit_EX(This.value.ref)), offsetof(zend_object, ce))); } } - if (!zend_jit_push_call_frame(jit, opline, op_array, func, 0, 0, checked_stack, func_ref, scope_ref)) { + if (!zend_jit_push_call_frame(jit, opline, op_array, func, false, false, checked_stack, func_ref, scope_ref)) { return 0; } @@ -9392,7 +9344,7 @@ static int zend_jit_init_static_method_call(zend_jit_ctx *jit, } else { ZEND_ASSERT(call_level > 0); jit->delayed_call_level = call_level; - delayed_call_chain = 1; + delayed_call_chain = true; } if (trace @@ -9473,7 +9425,7 @@ static int zend_jit_init_closure_call(zend_jit_ctx *jit, } } - if (!zend_jit_push_call_frame(jit, opline, NULL, func, 1, 0, checked_stack, ref, IR_UNUSED)) { + if (!zend_jit_push_call_frame(jit, opline, NULL, func, true, false, checked_stack, ref, IR_UNUSED)) { return 0; } @@ -9483,7 +9435,7 @@ static int zend_jit_init_closure_call(zend_jit_ctx *jit, } } else { ZEND_ASSERT(call_level > 0); - delayed_call_chain = 1; + delayed_call_chain = true; jit->delayed_call_level = call_level; } @@ -9561,12 +9513,12 @@ static int zend_jit_send_val(zend_jit_ctx *jit, const zend_op *opline, uint32_t jit_ZVAL_COPY_CONST(jit, arg_addr, MAY_BE_ANY, MAY_BE_ANY, - zv, 1); + zv, true); } else { jit_ZVAL_COPY(jit, arg_addr, MAY_BE_ANY, - op1_addr, op1_info, 0); + op1_addr, op1_info, false); } return 1; @@ -9640,7 +9592,7 @@ static int zend_jit_send_ref(zend_jit_ctx *jit, const zend_op *opline, const zen jit_ZVAL_COPY(jit, ref_addr, MAY_BE_ANY, - op1_addr, op1_info, 0); + op1_addr, op1_info, false); // JIT: ZVAL_REFERENCE(arg, ref) jit_set_Z_PTR(jit, op1_addr, ref); @@ -9714,7 +9666,7 @@ static int zend_jit_send_var(zend_jit_ctx *jit, const zend_op *opline, const zen jit_ZVAL_COPY(jit, arg_addr, MAY_BE_ANY, - op1_addr, op1_info, 0); + op1_addr, op1_info, false); if (!ARG_MAY_BE_SENT_BY_REF(JIT_G(current_frame)->call->func, arg_num)) { if (!(op1_info & MAY_BE_REF)) { @@ -9751,7 +9703,7 @@ static int zend_jit_send_var(zend_jit_ctx *jit, const zend_op *opline, const zen jit_ZVAL_COPY(jit, arg_addr, MAY_BE_ANY, - op1_addr, op1_info, 0); + op1_addr, op1_info, false); if (op1_info & MAY_BE_REF) { ir_ref if_ref = jit_if_Z_TYPE(jit, arg_addr, IS_REFERENCE); @@ -9848,7 +9800,7 @@ static int zend_jit_send_var(zend_jit_ctx *jit, const zend_op *opline, const zen jit_ZVAL_COPY(jit, arg_addr, MAY_BE_ANY, - op1_addr, op1_info, 0); + op1_addr, op1_info, false); if (op1_info & MAY_BE_REF) { // JIT: if (Z_TYPE_P(arg) == IS_REFERENCE) ir_ref if_ref = jit_if_Z_TYPE(jit, arg_addr, IS_REFERENCE); @@ -9883,7 +9835,7 @@ static int zend_jit_send_var(zend_jit_ctx *jit, const zend_op *opline, const zen jit_ZVAL_COPY(jit, arg_addr, MAY_BE_ANY, - op1_addr, op1_info, 1); + op1_addr, op1_info, true); } else { ir_ref if_ref, ref, ref2, refcount, if_not_zero, if_refcounted; zend_jit_addr ref_addr; @@ -9901,7 +9853,7 @@ static int zend_jit_send_var(zend_jit_ctx *jit, const zend_op *opline, const zen jit_ZVAL_COPY(jit, arg_addr, MAY_BE_ANY, - ref_addr, op1_info, 0); + ref_addr, op1_info, false); // JIT: if (GC_DELREF(ref) != 0) refcount = jit_GC_DELREF(jit, ref); @@ -9929,7 +9881,7 @@ static int zend_jit_send_var(zend_jit_ctx *jit, const zend_op *opline, const zen jit_ZVAL_COPY(jit, arg_addr, MAY_BE_ANY, - op1_addr, op1_info, 0); + op1_addr, op1_info, false); } } else { if (op1_addr != op1_def_addr) { @@ -10055,7 +10007,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen const zend_function *func = NULL; uint32_t i; uint32_t call_num_args = 0; - bool unknown_num_args = 0; + bool unknown_num_args = false; const void *exit_addr = NULL; const zend_op *prev_opline; ir_ref rx, func_ref = IR_UNUSED, if_user = IR_UNUSED, user_path = IR_UNUSED; @@ -10066,7 +10018,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen } if (prev_opline->opcode == ZEND_SEND_UNPACK || prev_opline->opcode == ZEND_SEND_ARRAY || prev_opline->opcode == ZEND_CHECK_UNDEF_ARGS) { - unknown_num_args = 1; + unknown_num_args = true; } if (info) { @@ -10107,7 +10059,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen TRACE_FRAME_NUM_ARGS(JIT_G(current_frame)->call) >= 0) { call_num_args = TRACE_FRAME_NUM_ARGS(JIT_G(current_frame)->call); } else { - unknown_num_args = 1; + unknown_num_args = true; } #endif } else if (trace->op == ZEND_JIT_TRACE_ENTER) { @@ -10119,7 +10071,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen TRACE_FRAME_NUM_ARGS(JIT_G(current_frame)->call) >= 0) { call_num_args = TRACE_FRAME_NUM_ARGS(JIT_G(current_frame)->call); } else { - unknown_num_args = 1; + unknown_num_args = true; } } } @@ -10164,7 +10116,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen ir_STORE(jit_EX(call), (call_level == 1) ? IR_NULL : ir_LOAD_A(jit_CALL(rx, prev_execute_data))); } - delayed_call_chain = 0; + delayed_call_chain = false; jit->delayed_call_level = 0; // JIT: call->prev_execute_data = execute_data; @@ -10232,7 +10184,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen if ((!func || func->type == ZEND_USER_FUNCTION) && opline->opcode != ZEND_DO_ICALL) { - bool recursive_call_through_jmp = 0; + bool recursive_call_through_jmp = false; uint32_t num_args = 0; // JIT: EX(call) = NULL; @@ -10324,7 +10276,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen if (!trace && op_array == &func->op_array && call_num_args >= op_array->required_num_args) { /* recursive call */ - recursive_call_through_jmp = 1; + recursive_call_through_jmp = true; } } } else { @@ -10348,6 +10300,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 +10476,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)); } @@ -10639,7 +10593,8 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen uint32_t offset = EX_NUM_TO_VAR(i); zend_jit_addr var_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, offset); - jit_ZVAL_PTR_DTOR(jit, var_addr, MAY_BE_ANY|MAY_BE_RC1|MAY_BE_RCN, 0, opline); + jit_ZVAL_PTR_DTOR(jit, var_addr, MAY_BE_ANY|MAY_BE_RC1|MAY_BE_RCN, false, + opline); } } } else { @@ -10726,7 +10681,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen #endif } res_addr = ZEND_ADDR_REF_ZVAL(sp); - jit_ZVAL_PTR_DTOR(jit, res_addr, func_info, 1, opline); + jit_ZVAL_PTR_DTOR(jit, res_addr, func_info, true, opline); } if (!jit->ctx.fixed_call_stack_size) { // JIT: revert alloca @@ -10909,7 +10864,7 @@ static int zend_jit_recv(zend_jit_ctx *jit, const zend_op *opline, const zend_op } if (arg_info) { - if (!zend_jit_verify_arg_type(jit, opline, arg_info, 1)) { + if (!zend_jit_verify_arg_type(jit, opline, arg_info, true)) { return 0; } } @@ -10931,7 +10886,7 @@ static int zend_jit_recv_init(zend_jit_ctx *jit, const zend_op *opline, const ze jit_ZVAL_COPY_CONST(jit, res_addr, -1, -1, - zv, 1); + zv, true); } } else { if (JIT_G(trigger) != ZEND_JIT_ON_HOT_TRACE || @@ -10944,7 +10899,7 @@ static int zend_jit_recv_init(zend_jit_ctx *jit, const zend_op *opline, const ze jit_ZVAL_COPY_CONST(jit, res_addr, -1, -1, - zv, 1); + zv, true); } if (Z_CONSTANT_P(zv)) { @@ -10955,7 +10910,7 @@ static int zend_jit_recv_init(zend_jit_ctx *jit, const zend_op *opline, const ze if_fail = ir_IF(ref); ir_IF_TRUE_cold(if_fail); - jit_ZVAL_PTR_DTOR(jit, res_addr, MAY_BE_ANY|MAY_BE_RC1|MAY_BE_RCN, 1, opline); + jit_ZVAL_PTR_DTOR(jit, res_addr, MAY_BE_ANY|MAY_BE_RC1|MAY_BE_RCN, true, opline); ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler)); ir_IF_FALSE(if_fail); } @@ -10992,7 +10947,7 @@ static bool zend_jit_verify_return_type(zend_jit_ctx *jit, const zend_op *opline zend_arg_info *arg_info = &op_array->arg_info[-1]; ZEND_ASSERT(ZEND_TYPE_IS_SET(arg_info->type)); zend_jit_addr op1_addr = OP1_ADDR(); - bool needs_slow_check = 1; + bool needs_slow_check = true; uint32_t type_mask = ZEND_TYPE_PURE_MASK(arg_info->type) & MAY_BE_ANY; ir_ref fast_path = IR_UNUSED; @@ -11000,7 +10955,7 @@ static bool zend_jit_verify_return_type(zend_jit_ctx *jit, const zend_op *opline if (((op1_info & MAY_BE_ANY) & type_mask) == 0) { /* pass */ } else if (((op1_info & MAY_BE_ANY) | type_mask) == type_mask) { - needs_slow_check = 0; + needs_slow_check = false; } else if (is_power_of_two(type_mask)) { uint32_t type_code = concrete_type(type_mask); ir_ref if_ok = jit_if_Z_TYPE(jit, op1_addr, type_code); @@ -11024,7 +10979,7 @@ static bool zend_jit_verify_return_type(zend_jit_ctx *jit, const zend_op *opline jit_SET_EX_OPLINE(jit, opline); ref = jit_ZVAL_ADDR(jit, op1_addr); if (op1_info & MAY_BE_UNDEF) { - ref = zend_jit_zval_check_undef(jit, ref, opline->op1.var, NULL, 1); + ref = zend_jit_zval_check_undef(jit, ref, opline->op1.var, NULL, true); } ir_CALL_3(IR_VOID, ir_CONST_FC_FUNC(zend_jit_verify_return_slow), @@ -11039,7 +10994,7 @@ static bool zend_jit_verify_return_type(zend_jit_ctx *jit, const zend_op *opline } } - return 1; + return true; } static int zend_jit_leave_frame(zend_jit_ctx *jit) @@ -11064,7 +11019,7 @@ static int zend_jit_free_cv(zend_jit_ctx *jit, uint32_t info, uint32_t var) if (info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) { zend_jit_addr var_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, EX_NUM_TO_VAR(var)); - jit_ZVAL_PTR_DTOR(jit, var_addr, info, 1, NULL); + jit_ZVAL_PTR_DTOR(jit, var_addr, info, true, NULL); } return 1; } @@ -11072,7 +11027,7 @@ static int zend_jit_free_cv(zend_jit_ctx *jit, uint32_t info, uint32_t var) static int zend_jit_free_op(zend_jit_ctx *jit, const zend_op *opline, uint32_t info, uint32_t var_offset) { if (info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) { - jit_ZVAL_PTR_DTOR(jit, ZEND_ADDR_MEM_ZVAL(ZREG_FP, var_offset), info, 0, opline); + jit_ZVAL_PTR_DTOR(jit, ZEND_ADDR_MEM_ZVAL(ZREG_FP, var_offset), info, false, opline); } return 1; } @@ -11111,7 +11066,7 @@ static int zend_jit_leave_func(zend_jit_ctx *jit, if (may_need_call_helper) { if (!left_frame) { - left_frame = 1; + left_frame = true; if (!zend_jit_leave_frame(jit)) { return 0; } @@ -11132,7 +11087,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 @@ -11159,7 +11114,7 @@ static int zend_jit_leave_func(zend_jit_ctx *jit, if ((op_array->fn_flags & (ZEND_ACC_CLOSURE|ZEND_ACC_FAKE_CLOSURE)) == ZEND_ACC_CLOSURE) { if (!left_frame) { - left_frame = 1; + left_frame = true; if (!zend_jit_leave_frame(jit)) { return 0; } @@ -11170,7 +11125,7 @@ static int zend_jit_leave_func(zend_jit_ctx *jit, ir_ref if_release, fast_path = IR_UNUSED; if (!left_frame) { - left_frame = 1; + left_frame = true; if (!zend_jit_leave_frame(jit)) { return 0; } @@ -11290,8 +11245,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)); } @@ -11396,9 +11351,9 @@ static int zend_jit_return(zend_jit_ctx *jit, const zend_op *opline, const zend_ if (opline->op1_type == IS_CONST) { zval *zv = RT_CONSTANT(opline, opline->op1); - jit_ZVAL_COPY_CONST(jit, ret_addr, MAY_BE_ANY, MAY_BE_ANY, zv, 1); + jit_ZVAL_COPY_CONST(jit, ret_addr, MAY_BE_ANY, MAY_BE_ANY, zv, true); } else if (opline->op1_type == IS_TMP_VAR) { - jit_ZVAL_COPY(jit, ret_addr, MAY_BE_ANY, op1_addr, op1_info, 0); + jit_ZVAL_COPY(jit, ret_addr, MAY_BE_ANY, op1_addr, op1_info, false); } else if (opline->op1_type == IS_CV) { if (op1_info & MAY_BE_REF) { ref = jit_ZVAL_ADDR(jit, op1_addr); @@ -11410,16 +11365,16 @@ static int zend_jit_return(zend_jit_ctx *jit, const zend_op *opline, const zend_ if (JIT_G(trigger) != ZEND_JIT_ON_HOT_TRACE || (op1_info & (MAY_BE_REF|MAY_BE_OBJECT)) || !op_array->function_name) { - jit_ZVAL_COPY(jit, ret_addr, MAY_BE_ANY, op1_addr, op1_info, 1); + jit_ZVAL_COPY(jit, ret_addr, MAY_BE_ANY, op1_addr, op1_info, true); } else if (return_value_used != 1) { - jit_ZVAL_COPY(jit, ret_addr, MAY_BE_ANY, op1_addr, op1_info, 0); + jit_ZVAL_COPY(jit, ret_addr, MAY_BE_ANY, op1_addr, op1_info, false); // JIT: if (EXPECTED(!(EX_CALL_INFO() & ZEND_CALL_CODE))) ZVAL_NULL(retval_ptr); jit_set_Z_TYPE_INFO(jit, op1_addr, IS_NULL); } else { - jit_ZVAL_COPY(jit, ret_addr, MAY_BE_ANY, op1_addr, op1_info, 0); + jit_ZVAL_COPY(jit, ret_addr, MAY_BE_ANY, op1_addr, op1_info, false); } } else { - jit_ZVAL_COPY(jit, ret_addr, MAY_BE_ANY, op1_addr, op1_info, 0); + jit_ZVAL_COPY(jit, ret_addr, MAY_BE_ANY, op1_addr, op1_info, false); } } else { if (op1_info & MAY_BE_REF) { @@ -11435,7 +11390,7 @@ static int zend_jit_return(zend_jit_ctx *jit, const zend_op *opline, const zend_ // JIT: ZVAL_COPY_VALUE(return_value, &ref->value) ref2 = ir_ADD_OFFSET(ref, offsetof(zend_reference, val)); ref_addr = ZEND_ADDR_REF_ZVAL(ref2); - jit_ZVAL_COPY(jit, ret_addr, MAY_BE_ANY, ref_addr, op1_info, 0); + jit_ZVAL_COPY(jit, ret_addr, MAY_BE_ANY, ref_addr, op1_info, false); ref2 = jit_GC_DELREF(jit, ref); if_non_zero = ir_IF(ref2); ir_IF_TRUE(if_non_zero); @@ -11458,7 +11413,7 @@ static int zend_jit_return(zend_jit_ctx *jit, const zend_op *opline, const zend_ ir_IF_FALSE(if_ref); } - jit_ZVAL_COPY(jit, ret_addr, MAY_BE_ANY, op1_addr, op1_info, 0); + jit_ZVAL_COPY(jit, ret_addr, MAY_BE_ANY, op1_addr, op1_info, false); } if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) { @@ -11614,7 +11569,7 @@ static int zend_jit_free(zend_jit_ctx *jit, const zend_op *opline, uint32_t op1_ ir_MERGE_list(end_inputs); } - jit_ZVAL_PTR_DTOR(jit, op1_addr, op1_info, 0, opline); + jit_ZVAL_PTR_DTOR(jit, op1_addr, op1_info, false, opline); if (may_throw) { zend_jit_check_exception(jit); @@ -11657,7 +11612,7 @@ static int zend_jit_echo(zend_jit_ctx *jit, const zend_op *opline, uint32_t op1_ ir_LOAD_A(ir_ADD_OFFSET(ref, offsetof(zend_string, len)))); if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { - jit_ZVAL_PTR_DTOR(jit, op1_addr, op1_info, 0, opline); + jit_ZVAL_PTR_DTOR(jit, op1_addr, op1_info, false, opline); } zend_jit_check_exception(jit); @@ -11996,9 +11951,9 @@ static int zend_jit_fetch_dimension_address_inner(zend_jit_ctx *jit, } if (op2_info & MAY_BE_LONG) { - bool op2_loaded = 0; - bool packed_loaded = 0; - bool bad_packed_key = 0; + bool op2_loaded = false; + bool packed_loaded = false; + bool bad_packed_key = false; ir_ref if_packed = IS_UNDEF; ir_ref h = IR_UNUSED; ir_ref idx_not_found_inputs = IR_UNUSED; @@ -12027,7 +11982,7 @@ static int zend_jit_fetch_dimension_address_inner(zend_jit_ctx *jit, if (type == BP_VAR_W) { // JIT: hval = Z_LVAL_P(dim); h = jit_Z_LVAL(jit, op2_addr); - op2_loaded = 1; + op2_loaded = true; } if (op1_info & MAY_BE_ARRAY_PACKED) { zend_long val = -1; @@ -12035,23 +11990,23 @@ static int zend_jit_fetch_dimension_address_inner(zend_jit_ctx *jit, if (Z_MODE(op2_addr) == IS_CONST_ZVAL) { val = Z_LVAL_P(Z_ZV(op2_addr)); if (val >= 0 && val < HT_MAX_SIZE) { - packed_loaded = 1; + packed_loaded = true; } else { - bad_packed_key = 1; + bad_packed_key = true; } h = ir_CONST_LONG(val); } else { if (!op2_loaded) { // JIT: hval = Z_LVAL_P(dim); h = jit_Z_LVAL(jit, op2_addr); - op2_loaded = 1; + op2_loaded = true; } - packed_loaded = 1; + packed_loaded = true; } if (dim_type == IS_UNDEF && type == BP_VAR_W && packed_loaded) { /* don't generate "fast" code for packed array */ - packed_loaded = 0; + packed_loaded = false; } if (packed_loaded) { @@ -12122,7 +12077,7 @@ static int zend_jit_fetch_dimension_address_inner(zend_jit_ctx *jit, if (!op2_loaded) { // JIT: hval = Z_LVAL_P(dim); h = jit_Z_LVAL(jit, op2_addr); - op2_loaded = 1; + op2_loaded = true; } if (packed_loaded) { ref = ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(_zend_hash_index_find), ht_ref, h); @@ -12172,7 +12127,7 @@ static int zend_jit_fetch_dimension_address_inner(zend_jit_ctx *jit, if (!op2_loaded) { // JIT: hval = Z_LVAL_P(dim); h = jit_Z_LVAL(jit, op2_addr); - op2_loaded = 1; + op2_loaded = true; } if (packed_loaded) { ref = ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(_zend_hash_index_find), ht_ref, h); @@ -12572,8 +12527,8 @@ static int zend_jit_fetch_dim_read(zend_jit_ctx *jit, zend_jit_addr orig_op1_addr; const void *exit_addr = NULL; const void *not_found_exit_addr = NULL; - bool result_type_guard = 0; - bool result_avoid_refcounting = 0; + bool result_type_guard = false; + bool result_avoid_refcounting = false; uint32_t may_be_string = (opline->opcode != ZEND_FETCH_LIST_R) ? MAY_BE_STRING : 0; int may_throw = 0; ir_ref if_type = IR_UNUSED; @@ -12597,7 +12552,7 @@ static int zend_jit_fetch_dim_read(zend_jit_ctx *jit, && (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) { if (!(op2_info & ((MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF) - (MAY_BE_STRING|MAY_BE_LONG)))) { - result_type_guard = 1; + result_type_guard = true; res_info &= ~MAY_BE_GUARD; ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD; } @@ -12610,7 +12565,7 @@ static int zend_jit_fetch_dim_read(zend_jit_ctx *jit, && (ssa_op+1)->op1_use == ssa_op->result_def && !(op2_info & ((MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF) - (MAY_BE_STRING|MAY_BE_LONG))) && zend_jit_may_avoid_refcounting(opline+1, res_info)) { - result_avoid_refcounting = 1; + result_avoid_refcounting = true; ssa->var_info[ssa_op->result_def].avoid_refcounting = 1; } @@ -12734,7 +12689,7 @@ static int zend_jit_fetch_dim_read(zend_jit_ctx *jit, } } else { // ZVAL_COPY - jit_ZVAL_COPY(jit, res_addr, -1, val_addr, res_info, 1); + jit_ZVAL_COPY(jit, res_addr, -1, val_addr, res_info, true); } ir_END_list(end_inputs); @@ -12841,16 +12796,18 @@ static int zend_jit_fetch_dim_read(zend_jit_ctx *jit, jit_SET_EX_OPLINE(jit, opline); if (opline->opcode != ZEND_FETCH_DIM_IS && (op1_info & MAY_BE_UNDEF)) { may_throw = 1; - zend_jit_type_check_undef(jit, jit_Z_TYPE(jit, op1_addr), opline->op1.var, NULL, 0, 1, 0); + zend_jit_type_check_undef(jit, jit_Z_TYPE(jit, op1_addr), opline->op1.var, NULL, + false, true, false); } if (op2_info & MAY_BE_UNDEF) { may_throw = 1; - zend_jit_type_check_undef(jit, jit_Z_TYPE(jit, op2_addr), opline->op2.var, NULL, 0, 1, 0); + zend_jit_type_check_undef(jit, jit_Z_TYPE(jit, op2_addr), opline->op2.var, NULL, + false, true, false); } } - 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 +12817,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); @@ -13092,7 +13053,7 @@ static int zend_jit_fetch_dim(zend_jit_ctx *jit, } if (!zend_jit_fetch_dimension_address_inner(jit, opline, type, op1_info, op2_info, op2_addr, op2_range, dim_type, NULL, NULL, NULL, - 0, ht_ref, found_inputs, found_vals, &end_inputs, NULL)) { + false, ht_ref, found_inputs, found_vals, &end_inputs, NULL)) { return 0; } @@ -13253,7 +13214,7 @@ static int zend_jit_isset_isempty_dim(zend_jit_ctx *jit, } if (!zend_jit_fetch_dimension_address_inner(jit, opline, BP_JIT_IS, op1_info, op2_info, op2_addr, op2_range, dim_type, found_exit_addr, not_found_exit_addr, NULL, - 0, ht_ref, true_inputs, NULL, &false_inputs, NULL)) { + false, ht_ref, true_inputs, NULL, &false_inputs, NULL)) { return 0; } @@ -13454,7 +13415,7 @@ static int zend_jit_assign_dim(zend_jit_ctx *jit, ir_IF_TRUE(if_ok); var_addr = ZEND_ADDR_REF_ZVAL(ref); - if (!zend_jit_simple_assign(jit, opline, var_addr, var_info, -1, (opline+1)->op1_type, op3_addr, val_info, res_addr, 0)) { + if (!zend_jit_simple_assign(jit, opline, var_addr, var_info, -1, (opline+1)->op1_type, op3_addr, val_info, res_addr, false)) { return 0; } } else { @@ -13468,7 +13429,7 @@ static int zend_jit_assign_dim(zend_jit_ctx *jit, if (!zend_jit_fetch_dimension_address_inner(jit, opline, BP_VAR_W, op1_info, op2_info, op2_addr, op2_range, dim_type, NULL, NULL, NULL, - 0, ht_ref, found_inputs, found_values, &end_inputs, NULL)) { + false, ht_ref, found_inputs, found_values, &end_inputs, NULL)) { return 0; } @@ -13489,11 +13450,11 @@ static int zend_jit_assign_dim(zend_jit_ctx *jit, && Z_MODE(op3_addr) != IS_REG && opline->result_type == IS_UNUSED && (res_addr == 0 || Z_MODE(res_addr) != IS_REG)) { - if (!zend_jit_assign_to_variable_call(jit, opline, var_addr, var_addr, var_info, -1, (opline+1)->op1_type, op3_addr, val_info, res_addr, 0)) { + if (!zend_jit_assign_to_variable_call(jit, opline, var_addr, var_addr, var_info, -1, (opline+1)->op1_type, op3_addr, val_info, res_addr, false)) { return 0; } } else { - if (!zend_jit_assign_to_variable(jit, opline, var_addr, var_addr, var_info, -1, (opline+1)->op1_type, op3_addr, val_info, res_addr, 0, 0)) { + if (!zend_jit_assign_to_variable(jit, opline, var_addr, var_addr, var_info, -1, (opline+1)->op1_type, op3_addr, val_info, res_addr, 0, false)) { return 0; } } @@ -13586,7 +13547,7 @@ static int zend_jit_assign_dim_op(zend_jit_ctx *jit, uint32_t var_info = MAY_BE_NULL; ir_ref if_type = IS_UNUSED; ir_ref end_inputs = IR_UNUSED, ht_ref; - bool emit_fast_path = 1; + bool emit_fast_path = true; ZEND_ASSERT(opline->result_type == IS_UNUSED); @@ -13654,7 +13615,7 @@ static int zend_jit_assign_dim_op(zend_jit_ctx *jit, if (!zend_jit_fetch_dimension_address_inner(jit, opline, BP_VAR_RW, op1_info, op2_info, op2_addr, op2_range, dim_type, NULL, not_found_exit_addr, NULL, - 0, ht_ref, found_inputs, found_values, &end_inputs, NULL)) { + false, ht_ref, found_inputs, found_values, &end_inputs, NULL)) { return 0; } @@ -13702,7 +13663,7 @@ static int zend_jit_assign_dim_op(zend_jit_ctx *jit, var_addr = ZEND_ADDR_REF_ZVAL(ref); } } else { - emit_fast_path = 0; + emit_fast_path = false; } } @@ -13802,7 +13763,7 @@ static int zend_jit_fe_reset(zend_jit_ctx *jit, const zend_op *opline, uint32_t if (opline->op1_type == IS_CONST) { zval *zv = RT_CONSTANT(opline, opline->op1); - jit_ZVAL_COPY_CONST(jit, res_addr, MAY_BE_ANY, MAY_BE_ANY, zv, 1); + jit_ZVAL_COPY_CONST(jit, res_addr, MAY_BE_ANY, MAY_BE_ANY, zv, true); } else { zend_jit_addr op1_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->op1.var); @@ -14140,12 +14101,12 @@ static int zend_jit_fe_fetch(zend_jit_ctx *jit, const zend_op *opline, uint32_t val_addr = ZEND_ADDR_REF_ZVAL(p_ref); if (opline->op2_type == IS_CV) { // JIT: zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - if (!zend_jit_assign_to_variable(jit, opline, var_addr, var_addr, op2_info, -1, IS_CV, val_addr, val_info, 0, 0, 1)) { + if (!zend_jit_assign_to_variable(jit, opline, var_addr, var_addr, op2_info, -1, IS_CV, val_addr, val_info, 0, 0, true)) { return 0; } } else { // JIT: ZVAL_COPY(res, value); - jit_ZVAL_COPY(jit, var_addr, -1, val_addr, val_info, 1); + jit_ZVAL_COPY(jit, var_addr, -1, val_addr, val_info, true); } if (!exit_addr) { @@ -14264,7 +14225,7 @@ static int zend_jit_fetch_obj(zend_jit_ctx *jit, { zval *member; zend_property_info *prop_info; - bool may_be_dynamic = 1; + bool may_be_dynamic = true; zend_jit_addr prop_addr; uint32_t res_info = RES_INFO(); ir_ref prop_type_ref = IR_UNUSED; @@ -14355,7 +14316,7 @@ static int zend_jit_fetch_obj(zend_jit_ctx *jit, prop_info = zend_get_known_property_info(op_array, trace_ce, Z_STR_P(member), on_this, op_array->filename); if (prop_info) { ce = trace_ce; - ce_is_instanceof = 0; + ce_is_instanceof = false; if (!(op1_info & MAY_BE_CLASS_GUARD)) { if (on_this && JIT_G(current_frame) && TRACE_FRAME_IS_THIS_CLASS_CHECKED(JIT_G(current_frame))) { @@ -14680,7 +14641,7 @@ static int zend_jit_fetch_obj(zend_jit_ctx *jit, if (end_values) { ir_ref val_ref = ir_PHI_list(end_values); zend_jit_addr val_addr = ZEND_ADDR_REF_ZVAL(val_ref); - bool result_avoid_refcounting = 0; + bool result_avoid_refcounting = false; ZEND_ASSERT(opline->opcode == ZEND_FETCH_OBJ_R || opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG @@ -14701,12 +14662,12 @@ static int zend_jit_fetch_obj(zend_jit_ctx *jit, && (res_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) && (ssa_op+1)->op1_use == ssa_op->result_def && zend_jit_may_avoid_refcounting(opline+1, res_info)) { - result_avoid_refcounting = 1; + result_avoid_refcounting = true; ssa->var_info[ssa_op->result_def].avoid_refcounting = 1; } val_addr = zend_jit_guard_fetch_result_type(jit, opline, val_addr, type, - 1, flags, op1_avoid_refcounting); + true, flags, op1_avoid_refcounting); if (!val_addr) { return 0; } @@ -14806,6 +14767,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; @@ -14870,7 +14838,7 @@ static int zend_jit_assign_obj(zend_jit_ctx *jit, prop_info = zend_get_known_property_info(op_array, trace_ce, name, on_this, op_array->filename); if (prop_info) { ce = trace_ce; - ce_is_instanceof = 0; + ce_is_instanceof = false; if (!(op1_info & MAY_BE_CLASS_GUARD)) { if (on_this && JIT_G(current_frame) && TRACE_FRAME_IS_THIS_CLASS_CHECKED(JIT_G(current_frame))) { @@ -15035,7 +15003,7 @@ static int zend_jit_assign_obj(zend_jit_ctx *jit, if (Z_MODE(val_addr) != IS_REG && (res_addr == 0 || Z_MODE(res_addr) != IS_REG) && opline->result_type == IS_UNUSED) { - if (!zend_jit_assign_to_variable_call(jit, opline, prop_addr, prop_addr, -1, -1, (opline+1)->op1_type, val_addr, val_info, res_addr, 0)) { + if (!zend_jit_assign_to_variable_call(jit, opline, prop_addr, prop_addr, -1, -1, (opline+1)->op1_type, val_addr, val_info, res_addr, false)) { return 0; } } else { @@ -15046,7 +15014,7 @@ static int zend_jit_assign_obj(zend_jit_ctx *jit, } else { real_res_addr = res_addr; } - if (!zend_jit_assign_to_variable(jit, opline, prop_addr, prop_addr, -1, -1, (opline+1)->op1_type, val_addr, val_info, real_res_addr, 0, 0)) { + if (!zend_jit_assign_to_variable(jit, opline, prop_addr, prop_addr, -1, -1, (opline+1)->op1_type, val_addr, val_info, real_res_addr, 0, false)) { return 0; } } @@ -15152,8 +15120,8 @@ static int zend_jit_assign_obj_op(zend_jit_ctx *jit, zend_string *name; zend_property_info *prop_info; zend_jit_addr prop_addr; - bool use_prop_guard = 0; - bool may_throw = 0; + bool use_prop_guard = false; + bool may_throw = false; binary_op_type binary_op = get_binary_op(opline->extended_value); ir_ref obj_ref = IR_UNUSED; ir_ref prop_ref = IR_UNUSED; @@ -15202,7 +15170,7 @@ static int zend_jit_assign_obj_op(zend_jit_ctx *jit, jit_ZVAL_ADDR(jit, op1_addr), ir_CONST_ADDR(ZSTR_VAL(name))); - may_throw = 1; + may_throw = true; ir_END_list(end_inputs); ir_IF_TRUE(if_obj); @@ -15216,7 +15184,7 @@ static int zend_jit_assign_obj_op(zend_jit_ctx *jit, prop_info = zend_get_known_property_info(op_array, trace_ce, name, on_this, op_array->filename); if (prop_info) { ce = trace_ce; - ce_is_instanceof = 0; + ce_is_instanceof = false; if (!(op1_info & MAY_BE_CLASS_GUARD)) { if (on_this && JIT_G(current_frame) && TRACE_FRAME_IS_THIS_CLASS_CHECKED(JIT_G(current_frame))) { @@ -15314,7 +15282,7 @@ static int zend_jit_assign_obj_op(zend_jit_ctx *jit, if (ZEND_TYPE_IS_SET(prop_info->type)) { ir_ref if_ref, if_typed, noref_path, ref_path, reference, ref, arg2; - may_throw = 1; + may_throw = true; jit_SET_EX_OPLINE(jit, opline); @@ -15392,7 +15360,7 @@ static int zend_jit_assign_obj_op(zend_jit_ctx *jit, if (var_info & MAY_BE_REF) { ir_ref if_ref, if_typed, noref_path, ref_path, reference, ref, arg2; - may_throw = 1; + may_throw = true; if_ref = jit_if_Z_TYPE(jit, prop_addr, IS_REFERENCE); ir_IF_FALSE(if_ref); @@ -15446,7 +15414,7 @@ static int zend_jit_assign_obj_op(zend_jit_ctx *jit, if (opline->extended_value != ZEND_ADD || (var_info & MAY_BE_ANY) != MAY_BE_ARRAY || (val_info & MAY_BE_ANY) == MAY_BE_ARRAY) { - may_throw = 1; + may_throw = true; } } if (!zend_jit_math_helper(jit, opline, opline->extended_value, IS_CV, opline->op1, var_addr, var_info, val_op_type, (opline+1)->op1, val_addr, val_info, 0, var_addr, var_def_info, var_info, @@ -15461,7 +15429,7 @@ static int zend_jit_assign_obj_op(zend_jit_ctx *jit, (val_info & (MAY_BE_STRING|MAY_BE_DOUBLE|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) { if ((var_info & MAY_BE_ANY) != MAY_BE_STRING || (val_info & MAY_BE_ANY) != MAY_BE_STRING) { - may_throw = 1; + may_throw = true; } } goto long_math; @@ -15469,23 +15437,23 @@ static int zend_jit_assign_obj_op(zend_jit_ctx *jit, case ZEND_SR: if ((var_info & (MAY_BE_STRING|MAY_BE_DOUBLE|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) || (val_info & (MAY_BE_STRING|MAY_BE_DOUBLE|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) { - may_throw = 1; + may_throw = true; } if (val_op_type != IS_CONST || Z_TYPE_P(RT_CONSTANT((opline+1), (opline+1)->op1)) != IS_LONG || Z_LVAL_P(RT_CONSTANT((opline+1), (opline+1)->op1)) < 0) { - may_throw = 1; + may_throw = true; } goto long_math; case ZEND_MOD: if ((var_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) || (val_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) { - may_throw = 1; + may_throw = true; } if (val_op_type != IS_CONST || Z_TYPE_P(RT_CONSTANT((opline+1), (opline+1)->op1)) != IS_LONG || Z_LVAL_P(RT_CONSTANT((opline+1), (opline+1)->op1)) == 0) { - may_throw = 1; + may_throw = true; } long_math: if (!zend_jit_long_math_helper(jit, opline, opline->extended_value, @@ -15497,7 +15465,7 @@ static int zend_jit_assign_obj_op(zend_jit_ctx *jit, } break; case ZEND_CONCAT: - may_throw = 1; + may_throw = true; if (!zend_jit_concat_helper(jit, opline, IS_CV, opline->op1, var_addr, var_info, val_op_type, (opline+1)->op1, val_addr, val_info, var_addr, 0)) { return 0; @@ -15516,7 +15484,7 @@ static int zend_jit_assign_obj_op(zend_jit_ctx *jit, ir_MERGE_list(slow_inputs); - may_throw = 1; + may_throw = true; if (Z_MODE(val_addr) == IS_REG) { zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, (opline+1)->op1.var); @@ -15552,7 +15520,7 @@ static int zend_jit_assign_obj_op(zend_jit_ctx *jit, if (opline->op1_type != IS_UNUSED && !delayed_fetch_this && !op1_indirect) { if ((op1_info & MAY_HAVE_DTOR) && (op1_info & MAY_BE_RC1)) { - may_throw = 1; + may_throw = true; } jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, opline); } @@ -15584,8 +15552,8 @@ static int zend_jit_incdec_obj(zend_jit_ctx *jit, zend_property_info *prop_info; zend_jit_addr res_addr = 0; zend_jit_addr prop_addr; - bool use_prop_guard = 0; - bool may_throw = 0; + bool use_prop_guard = false; + bool may_throw = false; uint32_t res_info = (opline->result_type != IS_UNDEF) ? RES_INFO() : 0; ir_ref obj_ref = IR_UNUSED; ir_ref prop_ref = IR_UNUSED; @@ -15646,7 +15614,7 @@ static int zend_jit_incdec_obj(zend_jit_ctx *jit, prop_info = zend_get_known_property_info(op_array, trace_ce, name, on_this, op_array->filename); if (prop_info) { ce = trace_ce; - ce_is_instanceof = 0; + ce_is_instanceof = false; if (!(op1_info & MAY_BE_CLASS_GUARD)) { if (on_this && JIT_G(current_frame) && TRACE_FRAME_IS_THIS_CLASS_CHECKED(JIT_G(current_frame))) { @@ -15739,7 +15707,7 @@ static int zend_jit_incdec_obj(zend_jit_ctx *jit, const void *func; ir_ref ref; - may_throw = 1; + may_throw = true; jit_SET_EX_OPLINE(jit, opline); if (ce && ce->ce_flags & ZEND_ACC_IMMUTABLE) { @@ -15844,7 +15812,7 @@ static int zend_jit_incdec_obj(zend_jit_ctx *jit, ZEND_UNREACHABLE(); } - may_throw = 1; + may_throw = true; jit_SET_EX_OPLINE(jit, opline); ir_CALL_2(IR_VOID, ir_CONST_FC_FUNC(func), reference, @@ -15896,13 +15864,13 @@ static int zend_jit_incdec_obj(zend_jit_ctx *jit, if (var_info & (MAY_BE_ANY - MAY_BE_LONG)) { if (var_info & (MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) { - may_throw = 1; + may_throw = true; } if (if_long) { ir_IF_FALSE_cold(if_long); } if (opline->opcode == ZEND_POST_INC_OBJ || opline->opcode == ZEND_POST_DEC_OBJ) { - jit_ZVAL_COPY(jit, res_addr, -1, var_addr, var_info, 1); + jit_ZVAL_COPY(jit, res_addr, -1, var_addr, var_info, true); } if (opline->opcode == ZEND_PRE_INC_OBJ || opline->opcode == ZEND_POST_INC_OBJ) { if (opline->opcode == ZEND_PRE_INC_OBJ && opline->result_type != IS_UNUSED) { @@ -16012,7 +15980,7 @@ static int zend_jit_incdec_obj(zend_jit_ctx *jit, ZEND_UNREACHABLE(); } - may_throw = 1; + may_throw = true; jit_SET_EX_OPLINE(jit, opline); ir_ref run_time_cache = ir_LOAD_A(jit_EX(run_time_cache)); ir_CALL_4(IR_VOID, ir_CONST_FC_FUNC(func), @@ -16030,7 +15998,7 @@ static int zend_jit_incdec_obj(zend_jit_ctx *jit, if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) && !delayed_fetch_this && !op1_indirect) { if ((op1_info & MAY_HAVE_DTOR) && (op1_info & MAY_BE_RC1)) { - may_throw = 1; + may_throw = true; } jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, opline); } @@ -16714,7 +16682,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 +16699,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 +16762,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 +16795,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 +16829,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) @@ -16928,11 +16898,11 @@ static bool zend_jit_noref_guard(zend_jit_ctx *jit, const zend_op *opline, zend_ const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point); if (!exit_addr) { - return 0; + return false; } ir_GUARD(ir_NE(jit_Z_TYPE(jit, var_addr), ir_CONST_U8(IS_REFERENCE)), ir_CONST_ADDR(exit_addr)); - return 1; + return true; } static int zend_jit_trace_opline_guard(zend_jit_ctx *jit, const zend_op *opline) @@ -16965,7 +16935,7 @@ static bool zend_jit_guard_reference(zend_jit_ctx *jit, exit_addr = zend_jit_trace_get_exit_addr(exit_point); if (!exit_addr) { - return 0; + return false; } ref = jit_Z_TYPE(jit, var_addr); @@ -16978,7 +16948,7 @@ static bool zend_jit_guard_reference(zend_jit_ctx *jit, var_addr = ZEND_ADDR_REF_ZVAL(ref); *var_addr_ptr = var_addr; - return 1; + return true; } static bool zend_jit_fetch_reference(zend_jit_ctx *jit, @@ -16999,7 +16969,7 @@ static bool zend_jit_fetch_reference(zend_jit_ctx *jit, exit_addr = zend_jit_trace_get_exit_addr(exit_point); if (!exit_addr) { - return 0; + return false; } } @@ -17044,7 +17014,7 @@ static bool zend_jit_fetch_reference(zend_jit_ctx *jit, } *var_info_ptr |= MAY_BE_GUARD; /* prevent generation of specialized zval dtor */ - return 1; + return true; } static bool zend_jit_fetch_indirect_var(zend_jit_ctx *jit, const zend_op *opline, uint8_t var_type, uint32_t *var_info_ptr, zend_jit_addr *var_addr_ptr, bool add_indirect_guard) @@ -17060,7 +17030,7 @@ static bool zend_jit_fetch_indirect_var(zend_jit_ctx *jit, const zend_op *opline const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point); if (!exit_addr) { - return 0; + return false; } jit_guard_Z_TYPE(jit, var_addr, IS_INDIRECT, exit_addr); ref = jit_Z_PTR(jit, var_addr); @@ -17083,7 +17053,7 @@ static bool zend_jit_fetch_indirect_var(zend_jit_ctx *jit, const zend_op *opline exit_addr = zend_jit_trace_get_exit_addr(exit_point); if (!exit_addr) { - return 0; + return false; } jit_guard_Z_TYPE(jit, var_addr, var_type, exit_addr); @@ -17101,7 +17071,7 @@ static bool zend_jit_fetch_indirect_var(zend_jit_ctx *jit, const zend_op *opline *var_info_ptr = var_info; } - return 1; + return true; } static int zend_jit_trace_handler(zend_jit_ctx *jit, const zend_op_array *op_array, const zend_op *opline, int may_throw, zend_jit_trace_rec *trace) @@ -17109,8 +17079,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 +17093,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 +17111,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 +17133,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)) { @@ -17191,7 +17164,7 @@ static int zend_jit_trace_handler(zend_jit_ctx *jit, const zend_op_array *op_arr zend_jit_trace_stack *stack = JIT_G(current_frame)->stack; if (zend_is_smart_branch(opline)) { - bool exit_if_true = 0; + bool exit_if_true = false; exit_opline = zend_jit_trace_get_exit_opline(trace, opline + 1, &exit_if_true); } else { switch (opline->opcode) { @@ -17274,7 +17247,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 +17268,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 +17279,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 +17387,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 +17402,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)); } @@ -17481,14 +17448,14 @@ static bool zend_jit_opline_supports_reg(const zend_op_array *op_array, zend_ssa case ZEND_IS_IDENTICAL: case ZEND_IS_NOT_IDENTICAL: case ZEND_CASE: - return 1; + return true; case ZEND_RETURN: return (op_array->type != ZEND_EVAL_CODE && op_array->function_name); case ZEND_ASSIGN: return (opline->op1_type == IS_CV); case ZEND_ASSIGN_OP: if (opline->op1_type != IS_CV || opline->result_type != IS_UNUSED) { - return 0; + return false; } op1_info = OP1_INFO(); op2_info = OP2_INFO(); @@ -17499,7 +17466,7 @@ static bool zend_jit_opline_supports_reg(const zend_op_array *op_array, zend_ssa op1_info = OP1_INFO(); op2_info = OP2_INFO(); if ((op1_info & MAY_BE_UNDEF) || (op2_info & MAY_BE_UNDEF)) { - return 0; + return false; } if (trace && trace->op1_type != IS_UNKNOWN) { op1_info &= 1U << (trace->op1_type & ~(IS_TRACE_REFERENCE|IS_TRACE_INDIRECT|IS_TRACE_PACKED)); @@ -17547,11 +17514,11 @@ static bool zend_jit_opline_supports_reg(const zend_op_array *op_array, zend_ssa case ZEND_JMPNZ: if (JIT_G(trigger) != ZEND_JIT_ON_HOT_TRACE) { if (!ssa->cfg.map) { - return 0; + return false; } if (opline > op_array->opcodes + ssa->cfg.blocks[ssa->cfg.map[opline-op_array->opcodes]].start && ((opline-1)->result_type & (IS_SMART_BRANCH_JMPZ|IS_SMART_BRANCH_JMPNZ)) != 0) { - return 0; + return false; } } ZEND_FALLTHROUGH; @@ -17559,12 +17526,12 @@ static bool zend_jit_opline_supports_reg(const zend_op_array *op_array, zend_ssa case ZEND_BOOL_NOT: case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: - return 1; + return true; case ZEND_FETCH_CONSTANT: - return 1; + return true; case ZEND_ISSET_ISEMPTY_DIM_OBJ: if ((opline->extended_value & ZEND_ISEMPTY)) { - return 0; + return false; } ZEND_FALLTHROUGH; case ZEND_FETCH_DIM_R: @@ -17582,10 +17549,10 @@ static bool zend_jit_opline_supports_reg(const zend_op_array *op_array, zend_ssa ((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_STRING)); case ZEND_ASSIGN_DIM_OP: if (opline->result_type != IS_UNUSED) { - return 0; + return false; } if (!zend_jit_supported_binary_op(opline->extended_value, MAY_BE_ANY, OP1_DATA_INFO())) { - return 0; + return false; } ZEND_FALLTHROUGH; case ZEND_ASSIGN_DIM: @@ -17601,13 +17568,13 @@ static bool zend_jit_opline_supports_reg(const zend_op_array *op_array, zend_ssa && (opline+1)->op1_type == IS_CV && (opline+1)->op1.var == opline->op1.var) { /* skip $a[x] = $a; */ - return 0; + return false; } } else if (opline->op1_type == IS_VAR) { if (trace->op1_type == IS_UNKNOWN || !(trace->op1_type & IS_TRACE_INDIRECT) || opline->result_type != IS_UNUSED) { - return 0; + return false; } } if (trace->op1_type != IS_UNKNOWN @@ -17616,7 +17583,7 @@ static bool zend_jit_opline_supports_reg(const zend_op_array *op_array, zend_ssa } } else { if (opline->op1_type != IS_CV) { - return 0; + return false; } } return ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) && @@ -17624,10 +17591,10 @@ static bool zend_jit_opline_supports_reg(const zend_op_array *op_array, zend_ssa ((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_STRING)); case ZEND_ASSIGN_OBJ_OP: if (opline->result_type != IS_UNUSED) { - return 0; + return false; } if (!zend_jit_supported_binary_op(opline->extended_value, MAY_BE_ANY, OP1_DATA_INFO())) { - return 0; + return false; } ZEND_FALLTHROUGH; case ZEND_FETCH_OBJ_R: @@ -17635,19 +17602,19 @@ static bool zend_jit_opline_supports_reg(const zend_op_array *op_array, zend_ssa if (opline->op2_type != IS_CONST || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING || Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') { - return 0; + return false; } op1_info = OP1_INFO(); return opline->op1_type == IS_UNUSED || (op1_info & MAY_BE_OBJECT); } - return 0; + return false; } static bool zend_jit_var_supports_reg(zend_ssa *ssa, int var) { if (ssa->vars[var].no_val) { /* we don't need the value */ - return 0; + return false; } if (!(JIT_G(opt_flags) & ZEND_JIT_REG_ALLOC_GLOBAL)) { @@ -17655,13 +17622,13 @@ static bool zend_jit_var_supports_reg(zend_ssa *ssa, int var) * register allocation for SSA variables connected through Phi functions */ if (ssa->vars[var].definition_phi) { - return 0; + return false; } if (ssa->vars[var].phi_use_chain) { zend_ssa_phi *phi = ssa->vars[var].phi_use_chain; do { if (!ssa->vars[phi->ssa_var].no_val) { - return 0; + return false; } phi = zend_ssa_next_use_phi(ssa, var, phi); } while (phi); @@ -17671,22 +17638,22 @@ static bool zend_jit_var_supports_reg(zend_ssa *ssa, int var) if (((ssa->var_info[var].type & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) != MAY_BE_DOUBLE) && ((ssa->var_info[var].type & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) != MAY_BE_LONG)) { /* bad type */ - return 0; + return false; } - return 1; + return true; } static bool zend_jit_may_be_in_reg(const zend_op_array *op_array, zend_ssa *ssa, int var) { if (!zend_jit_var_supports_reg(ssa, var)) { - return 0; + return false; } if (ssa->vars[var].definition >= 0) { uint32_t def = ssa->vars[var].definition; if (!zend_jit_opline_supports_reg(op_array, ssa, op_array->opcodes + def, ssa->ops + def, NULL)) { - return 0; + return false; } } @@ -17696,7 +17663,7 @@ static bool zend_jit_may_be_in_reg(const zend_op_array *op_array, zend_ssa *ssa, do { if (!zend_ssa_is_no_val_use(op_array->opcodes + use, ssa->ops + use, var) && !zend_jit_opline_supports_reg(op_array, ssa, op_array->opcodes + use, ssa->ops + use, NULL)) { - return 0; + return false; } use = zend_ssa_next_use(ssa->ops, var, use); } while (use >= 0); @@ -17706,7 +17673,7 @@ static bool zend_jit_may_be_in_reg(const zend_op_array *op_array, zend_ssa *ssa, int def_block, use_block, b, use, j; zend_basic_block *bb; zend_ssa_phi *p; - bool ret = 1; + bool ret = true; zend_worklist worklist; ALLOCA_FLAG(use_heap) @@ -17752,7 +17719,7 @@ static bool zend_jit_may_be_in_reg(const zend_op_array *op_array, zend_ssa *ssa, b = zend_worklist_pop(&worklist); bb = &ssa->cfg.blocks[b]; if (bb->flags & (ZEND_BB_ENTRY|ZEND_BB_RECV_ENTRY)) { - ret = 0; + ret = false; break; } for (j = 0; j < bb->predecessors_count; j++) { @@ -17768,7 +17735,7 @@ static bool zend_jit_may_be_in_reg(const zend_op_array *op_array, zend_ssa *ssa, return ret; } - return 1; + return true; } static ir_ref jit_frameless_observer(zend_jit_ctx *jit, const zend_op *opline) { @@ -17825,7 +17792,7 @@ static void jit_frameless_icall1(zend_jit_ctx *jit, const zend_op *opline, uint3 ir_ref op1_ref = jit_ZVAL_ADDR(jit, op1_addr); jit_set_Z_TYPE_INFO(jit, res_addr, IS_NULL); if (opline->op1_type == IS_CV && (op1_info & MAY_BE_UNDEF)) { - op1_ref = zend_jit_zval_check_undef(jit, op1_ref, opline->op1.var, opline, 1); + op1_ref = zend_jit_zval_check_undef(jit, op1_ref, opline->op1.var, opline, true); op1_info &= ~MAY_BE_UNDEF; op1_info |= MAY_BE_NULL; op1_addr = ZEND_ADDR_REF_ZVAL(op1_ref); @@ -17870,13 +17837,13 @@ static void jit_frameless_icall2(zend_jit_ctx *jit, const zend_op *opline, uint3 ir_ref op2_ref = jit_ZVAL_ADDR(jit, op2_addr); jit_set_Z_TYPE_INFO(jit, res_addr, IS_NULL); if (opline->op1_type == IS_CV && (op1_info & MAY_BE_UNDEF)) { - op1_ref = zend_jit_zval_check_undef(jit, op1_ref, opline->op1.var, opline, 1); + op1_ref = zend_jit_zval_check_undef(jit, op1_ref, opline->op1.var, opline, true); op1_info &= ~MAY_BE_UNDEF; op1_info |= MAY_BE_NULL; op1_addr = ZEND_ADDR_REF_ZVAL(op1_ref); } if (opline->op2_type == IS_CV && (op2_info & MAY_BE_UNDEF)) { - op2_ref = zend_jit_zval_check_undef(jit, op2_ref, opline->op2.var, opline, 1); + op2_ref = zend_jit_zval_check_undef(jit, op2_ref, opline->op2.var, opline, true); op2_info &= ~MAY_BE_UNDEF; op2_info |= MAY_BE_NULL; op2_addr = ZEND_ADDR_REF_ZVAL(op2_ref); @@ -17942,19 +17909,19 @@ static void jit_frameless_icall3(zend_jit_ctx *jit, const zend_op *opline, uint3 ir_ref op3_ref = jit_ZVAL_ADDR(jit, op3_addr); jit_set_Z_TYPE_INFO(jit, res_addr, IS_NULL); if (opline->op1_type == IS_CV && (op1_info & MAY_BE_UNDEF)) { - op1_ref = zend_jit_zval_check_undef(jit, op1_ref, opline->op1.var, opline, 1); + op1_ref = zend_jit_zval_check_undef(jit, op1_ref, opline->op1.var, opline, true); op1_info &= ~MAY_BE_UNDEF; op1_info |= MAY_BE_NULL; op1_addr = ZEND_ADDR_REF_ZVAL(op1_ref); } if (opline->op2_type == IS_CV && (op2_info & MAY_BE_UNDEF)) { - op2_ref = zend_jit_zval_check_undef(jit, op2_ref, opline->op2.var, opline, 1); + op2_ref = zend_jit_zval_check_undef(jit, op2_ref, opline->op2.var, opline, true); op2_info &= ~MAY_BE_UNDEF; op2_info |= MAY_BE_NULL; op2_addr = ZEND_ADDR_REF_ZVAL(op2_ref); } if ((opline+1)->op1_type == IS_CV && (op1_data_info & MAY_BE_UNDEF)) { - op3_ref = zend_jit_zval_check_undef(jit, op3_ref, (opline+1)->op1.var, opline, 1); + op3_ref = zend_jit_zval_check_undef(jit, op3_ref, (opline+1)->op1.var, opline, true); op1_data_info &= ~MAY_BE_UNDEF; op1_data_info |= MAY_BE_NULL; op3_addr = ZEND_ADDR_REF_ZVAL(op3_ref); diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index aeec674d60f3e..10be237d06b8e 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; @@ -131,7 +132,7 @@ static uint32_t zend_jit_exit_point_by_addr(const void *addr) return (uint32_t)-1; } -static uint32_t zend_jit_trace_get_exit_point(const zend_op *to_opline, uint32_t flags) +static uint32_t _zend_jit_trace_get_exit_point(const zend_op *to_opline, uint32_t flags ZEND_FILE_LINE_DC) { zend_jit_trace_info *t = &zend_jit_traces[ZEND_JIT_TRACE_NUM]; uint32_t exit_point; @@ -177,7 +178,13 @@ static uint32_t zend_jit_trace_get_exit_point(const zend_op *to_opline, uint32_t && memcmp(t->stack_map + t->exit_info[i].stack_offset, stack, stack_size * sizeof(zend_jit_trace_stack)) == 0)) { if (t->exit_info[i].opline == to_opline && t->exit_info[i].flags == flags - && t->exit_info[i].stack_size == stack_size) { + && t->exit_info[i].stack_size == stack_size +#if ZEND_DEBUG + && (((JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_EXIT_INFO_SRC) == 0) + || (strcmp(t->exit_info[i].filename, __zend_filename) == 0 + && t->exit_info[i].lineno == __zend_lineno)) +#endif + ) { return i; } } @@ -201,6 +208,15 @@ static uint32_t zend_jit_trace_get_exit_point(const zend_op *to_opline, uint32_t t->exit_info[exit_point].stack_offset = stack_offset; t->exit_info[exit_point].poly_func = (zend_jit_ref_snapshot){.reg = ZREG_NONE}; t->exit_info[exit_point].poly_this = (zend_jit_ref_snapshot){.reg = ZREG_NONE}; +#if ZEND_DEBUG + if ((JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_EXIT_INFO_SRC) != 0) { + t->exit_info[exit_point].filename = __zend_filename; + t->exit_info[exit_point].lineno = __zend_lineno; + } else { + t->exit_info[exit_point].filename = NULL; + t->exit_info[exit_point].lineno = 0; + } +#endif } return exit_point; @@ -477,7 +493,7 @@ static bool zend_jit_needs_arg_dtor(const zend_function *func, uint32_t arg_num, && func->type == ZEND_INTERNAL_FUNCTION && (func->internal_function.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0 && arg_num < func->internal_function.num_args) { - const zend_internal_arg_info *arg_info = &func->internal_function.arg_info[arg_num]; + const zend_arg_info *arg_info = &func->internal_function.arg_info[arg_num]; if (ZEND_ARG_SEND_MODE(arg_info) == ZEND_SEND_BY_VAL && ZEND_TYPE_IS_SET(arg_info->type) @@ -491,7 +507,7 @@ static bool zend_jit_needs_arg_dtor(const zend_function *func, uint32_t arg_num, if (type != IS_UNKNOWN && type < IS_STRING && ZEND_TYPE_FULL_MASK(arg_info->type) & (1u << type)) { - return 0; + return false; } } if (call_info && arg_num < call_info->num_args && call_info->arg_info[arg_num].opline) { @@ -506,7 +522,7 @@ static bool zend_jit_needs_arg_dtor(const zend_function *func, uint32_t arg_num, // TODO: few functions (e.g. pcntl_exec) modify arrays in-place ??? if (type != IS_ARRAY && (ZEND_TYPE_FULL_MASK(arg_info->type) & (1u << type))) { - return 0; + return false; } } } @@ -514,7 +530,7 @@ static bool zend_jit_needs_arg_dtor(const zend_function *func, uint32_t arg_num, } } - return 1; + return true; } static zend_ssa *zend_jit_trace_build_ssa(const zend_op_array *op_array, zend_script *script) @@ -801,7 +817,7 @@ static bool zend_jit_trace_is_false_loop(const zend_op_array *op_array, const ze bb = ssa->cfg.blocks + ssa->cfg.map[opline - op_array->opcodes]; return bb->loop_header != b; } else { - return 0; + return false; } } @@ -2949,7 +2965,7 @@ static zend_jit_reg_var* zend_jit_trace_allocate_registers(zend_jit_trace_rec *t && ssa_op->op1_def >= 0 && ssa->vars[ssa_op->op1_def].alias != NO_ALIAS) { /* avoid register allocation in case of possibility of indirect modification*/ - support_opline = 0; + support_opline = false; } if (ssa_op->op1_use >= 0 @@ -3409,7 +3425,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; } } @@ -3424,7 +3440,7 @@ static bool zend_jit_may_delay_fetch_this(const zend_op_array *op_array, zend_ss || ssa->vars[var].phi_use_chain || ssa->ops[use].op1_use != var || ssa->ops[use].op1_use_chain != -1) { - return 0; + return false; } opline = ssa_opcodes[use]; @@ -3436,7 +3452,7 @@ static bool zend_jit_may_delay_fetch_this(const zend_op_array *op_array, zend_ss || !JIT_G(current_frame)->call || !JIT_G(current_frame)->call->func || !TRACE_FRAME_IS_LAST_SEND_BY_VAL(JIT_G(current_frame)->call)) { - return 0; + return false; } } else if (opline->opcode != ZEND_FETCH_OBJ_R && opline->opcode != ZEND_FETCH_OBJ_IS @@ -3447,13 +3463,13 @@ static bool zend_jit_may_delay_fetch_this(const zend_op_array *op_array, zend_ss && opline->opcode != ZEND_PRE_DEC_OBJ && opline->opcode != ZEND_POST_INC_OBJ && opline->opcode != ZEND_POST_DEC_OBJ) { - return 0; + return false; } if (opline->op2_type != IS_CONST || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING || Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') { - return 0; + return false; } if (opline->opcode == ZEND_ASSIGN_OBJ_OP) { @@ -3461,11 +3477,11 @@ static bool zend_jit_may_delay_fetch_this(const zend_op_array *op_array, zend_ss && (opline+1)->op1_type == IS_CV && (opline+1)->op1.var == opline->op1.var) { /* skip $a->prop += $a; */ - return 0; + return false; } if (!zend_jit_supported_binary_op( opline->extended_value, MAY_BE_ANY, OP1_DATA_INFO())) { - return 0; + return false; } } @@ -3474,11 +3490,11 @@ static bool zend_jit_may_delay_fetch_this(const zend_op_array *op_array, zend_ss || ssa_opcodes[i]->opcode == ZEND_DO_FCALL_BY_NAME || ssa_opcodes[i]->opcode == ZEND_DO_FCALL || ssa_opcodes[i]->opcode == ZEND_INCLUDE_OR_EVAL) { - return 0; + return false; } } - return 1; + return true; } static int zend_jit_trace_stack_needs_deoptimization(zend_jit_trace_stack *stack, uint32_t stack_size) @@ -3888,19 +3904,19 @@ static bool zend_jit_may_skip_comparison(const zend_op *opline, const zend_ssa_o || prev_opcode == ZEND_CASE_STRICT) { if (ssa_op->op1_use < 0) { if (RT_CONSTANT(opline, opline->op1) != RT_CONSTANT(&ssa_opcodes[prev_ssa_op - ssa->ops], ssa_opcodes[prev_ssa_op - ssa->ops]->op1)) { - return 0; + return false; } } if (ssa_op->op2_use < 0) { if (RT_CONSTANT(opline, opline->op2) != RT_CONSTANT(&ssa_opcodes[prev_ssa_op - ssa->ops], ssa_opcodes[prev_ssa_op - ssa->ops]->op2)) { - return 0; + return false; } } - return 1; + return true; } } } - return 0; + return false; } static bool zend_jit_trace_next_is_send_result(const zend_op *opline, @@ -3927,9 +3943,9 @@ static bool zend_jit_trace_next_is_send_result(const zend_op *oplin zend_jit_trace_send_type(opline+1, frame->call, res_type); } } - return 1; + return true; } - return 0; + return false; } static int zend_jit_find_ssa_var(const zend_op_array *op_array, @@ -4045,11 +4061,11 @@ static bool zend_jit_trace_must_store_type(const zend_op_array *op_array, if (ssa_var >= 0) { if ((ssa->var_info[ssa_var].type & (MAY_BE_ANY|MAY_BE_UNDEF)) != (1U << type)) { - return 0; + return false; } } } - return 1; + return true; } static bool zend_jit_trace_may_throw(const zend_op *opline, @@ -4070,7 +4086,7 @@ static bool zend_jit_trace_may_throw(const zend_op *opline, && !(t1 & MAY_BE_ARRAY_OF_REF) && (t2 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) == MAY_BE_LONG && (t3 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) == MAY_BE_LONG) { - return 0; + return false; } break; default: @@ -4079,9 +4095,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 +4110,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 +4141,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) { @@ -6564,10 +6583,9 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par uint32_t var_num = opline->result.var; uint32_t op_num = opline - op_array->opcodes; const zend_live_range *range = op_array->live_range; - int j; op_num += zend_jit_trace_op_len(opline); - for (j = 0; j < op_array->last_live_range; range++, j++) { + for (uint32_t j = 0; j < op_array->last_live_range; range++, j++) { if (range->start > op_num) { /* further blocks will not be relevant... */ break; @@ -7357,6 +7375,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 +7399,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,16 +7418,16 @@ 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; const zend_op *opline; uint32_t stack_size; zend_jit_trace_stack *stack; - bool original_handler = 0; + bool original_handler = false; if (!zend_jit_trace_exit_needs_deoptimization(trace_num, exit_num)) { return zend_jit_stub_handlers[jit_stub_trace_escape]; @@ -7426,7 +7452,7 @@ static const void *zend_jit_trace_exit_to_vm(uint32_t trace_num, uint32_t exit_n &zend_jit_traces[trace_num].exit_info[exit_num], stack, stack_size, NULL, NULL, zend_jit_traces[trace_num].constants, - 0)) { + false)) { goto jit_failure; } @@ -7438,7 +7464,7 @@ static const void *zend_jit_trace_exit_to_vm(uint32_t trace_num, uint32_t exit_n if (ZEND_OP_TRACE_INFO(opline, jit_extension->offset)->orig_handler != opline->handler) { /* prevent endless loop */ - original_handler = 1; + original_handler = true; } } zend_jit_set_ip(&ctx, opline); @@ -7458,7 +7484,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]; @@ -7747,7 +7773,7 @@ static bool zend_jit_trace_is_bad_root(const zend_op *opline, zend_jit_trace_sto if (cache_opline[i] == opline) { if (cache_count[i] >= JIT_G(blacklist_root_trace) - 1) { cache_opline[i] = NULL; - return 1; + return true; } else { #if 0 if (ZEND_OP_TRACE_INFO(opline, offset)->counter) { @@ -7757,7 +7783,7 @@ static bool zend_jit_trace_is_bad_root(const zend_op *opline, zend_jit_trace_sto #endif cache_count[i]++; cache_stop[i] = stop; - return 0; + return false; } } } @@ -7767,7 +7793,7 @@ static bool zend_jit_trace_is_bad_root(const zend_op *opline, zend_jit_trace_sto cache_stop[i] = stop; cache_slot = (i + 1) % ZEND_JIT_TRACE_BAD_ROOT_SLOTS; JIT_G(bad_root_slot) = cache_slot; - return 0; + return false; } static void zend_jit_dump_trace(zend_jit_trace_rec *trace_buffer, zend_ssa *tssa) @@ -8084,6 +8110,11 @@ static void zend_jit_dump_exit_info(zend_jit_trace_info *t) fprintf(stderr, ":unknown(zval_copy(%s))", zend_reg_name(STACK_REG(stack, j))); } } +#if ZEND_DEBUG + if ((JIT_G(debug) & ZEND_JIT_DEBUG_TRACE_EXIT_INFO_SRC) != 0) { + fprintf(stderr, " %s:%d", t->exit_info[i].filename, t->exit_info[i].lineno); + } +#endif fprintf(stderr, "\n"); } } @@ -8275,10 +8306,10 @@ static bool zend_jit_trace_exit_is_bad(uint32_t trace_num, uint32_t exit_num) zend_jit_traces[trace_num].exit_counters + exit_num; if (*counter + 1 >= JIT_G(hot_side_exit) + JIT_G(blacklist_side_trace)) { - return 1; + return true; } (*counter)++; - return 0; + return false; } static bool zend_jit_trace_exit_is_hot(uint32_t trace_num, uint32_t exit_num) @@ -8287,10 +8318,10 @@ static bool zend_jit_trace_exit_is_hot(uint32_t trace_num, uint32_t exit_num) zend_jit_traces[trace_num].exit_counters + exit_num; if (*counter + 1 >= JIT_G(hot_side_exit)) { - return 1; + return true; } (*counter)++; - return 0; + return false; } static zend_jit_trace_stop zend_jit_compile_side_trace(zend_jit_trace_rec *trace_buffer, uint32_t parent_num, uint32_t exit_num, uint32_t polymorphism) @@ -8832,11 +8863,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 +8920,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 +8948,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 +8970,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 +8995,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..bed5ab59992ed 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); } } @@ -199,9 +255,9 @@ bool ZEND_FASTCALL zend_jit_deprecated_helper(OPLINE_D) } zend_vm_stack_free_call_frame(call); - return 0; + return false; } - return 1; + return true; } bool ZEND_FASTCALL zend_jit_nodiscard_helper(OPLINE_D) @@ -227,9 +283,9 @@ bool ZEND_FASTCALL zend_jit_nodiscard_helper(OPLINE_D) } zend_vm_stack_free_call_frame(call); - return 0; + return false; } - return 1; + return true; } bool ZEND_FASTCALL zend_jit_deprecated_nodiscard_helper(OPLINE_D) @@ -239,17 +295,17 @@ bool ZEND_FASTCALL zend_jit_deprecated_nodiscard_helper(OPLINE_D) if (fbc->common.fn_flags & ZEND_ACC_DEPRECATED) { if (zend_jit_deprecated_helper(OPLINE_C) == 0) { - return 0; + return false; } } if (fbc->common.fn_flags & ZEND_ACC_NODISCARD) { if (zend_jit_nodiscard_helper(OPLINE_C) == 0) { - return 0; + return false; } } - return 1; + return true; } void ZEND_FASTCALL zend_jit_undefined_long_key(EXECUTE_DATA_D) @@ -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/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/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 @@ + fn($a, $b) => $a + $b; +?> +--EXPECTF-- +$_main: + ; (lines=%d, args=0, vars=%d, tmps=%d) + ; (after optimizer) + ; %s +0000 T0 = DECLARE_LAMBDA_FUNCTION 0 +0001 FREE T0 +0002 RETURN int(1) + +{closure:%s:%d}: + ; (lines=%d, args=0, vars=%d, tmps=%d) + ; (after optimizer) + ; %s +0000 T0 = DECLARE_LAMBDA_FUNCTION 0 +0001 RETURN T0 + +{closure:%s:%d}: + ; (lines=%d, args=2, vars=%d, tmps=%d) + ; (after optimizer) + ; %s +0000 CV0($a) = RECV 1 +0001 CV1($b) = RECV 2 +0002 T2 = ADD CV0($a) CV1($b) +0003 RETURN T2 diff --git a/ext/opcache/tests/gh19984.phpt b/ext/opcache/tests/gh19984.phpt new file mode 100644 index 0000000000000..cb49869f5cf05 --- /dev/null +++ b/ext/opcache/tests/gh19984.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-19984: Double-free of EG(errors)/persistent_script->warnings on persist of already persisted file +--EXTENSIONS-- +opcache +pcntl +--INI-- +opcache.enable_cli=1 +opcache.record_warnings=1 +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Warning: Unsupported declare 'unknown' in %s on line %d + +Warning: Unsupported declare 'unknown' in %s on line %d diff --git a/ext/opcache/tests/issue0057.phpt b/ext/opcache/tests/issue0057.phpt index 20c2f2a10558a..ac73859b0d36e 100644 --- a/ext/opcache/tests/issue0057.phpt +++ b/ext/opcache/tests/issue0057.phpt @@ -15,9 +15,9 @@ class ZException extends Exception { function dummy($query) { try { switch ($query) { - case 1; + case 1: break; - case 2; + case 2: break; default: throw new Exception('exception'); diff --git a/ext/opcache/tests/jit/add_011.phpt b/ext/opcache/tests/jit/add_011.phpt index 28c598c5540a0..17bd7be99d157 100644 --- a/ext/opcache/tests/jit/add_011.phpt +++ b/ext/opcache/tests/jit/add_011.phpt @@ -195,5 +195,6 @@ int(-9223371969208523780) Warning: Undefined variable $u in %sadd_011.php on line 5 -Deprecated: Implicit conversion from float %f to int loses precision in %sadd_011.php on line 5 -int(66572500992) \ No newline at end of file +Warning: The float %f is not representable as an int, cast occurred in %sadd_011.php on line 5 +int(66572500992) + diff --git a/ext/opcache/tests/jit/array_elem_002.phpt b/ext/opcache/tests/jit/array_elem_002.phpt index 250f54349051b..01de92acfccf8 100644 --- a/ext/opcache/tests/jit/array_elem_002.phpt +++ b/ext/opcache/tests/jit/array_elem_002.phpt @@ -11,7 +11,7 @@ $string_float= PHP_INT_MAX; $a = [$float => 'a', $string_float => 'b', 'c', 'd']; ?> --EXPECTF-- -Deprecated: Implicit conversion from float 1.0E+38 to int loses precision in %sarray_elem_002.php on line 4 +Warning: The float 1.0E+38 is not representable as an int, cast occurred in %sarray_elem_002.php on line 4 Fatal error: Uncaught Error: Cannot add element to the array as the next element is already occupied in %sarray_elem_002.php:4 Stack trace: diff --git a/ext/opcache/tests/jit/assign_obj_006.phpt b/ext/opcache/tests/jit/assign_obj_006.phpt new file mode 100644 index 0000000000000..a48299f040152 --- /dev/null +++ b/ext/opcache/tests/jit/assign_obj_006.phpt @@ -0,0 +1,37 @@ +--TEST-- +JIT ASSIGN_OBJ: violation of dominance +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- +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/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..e8c54c542c83c --- /dev/null +++ b/ext/opcache/tests/jit/gh19669-001.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-19669: assertion failure zend_jit_trace_type_to_info_ex +--CREDITS-- +YuanchengJiang +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Warning: The float -1.8446744073709552E+19 is not representable as an int, cast occurred in %s on line %d +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..3a1aa0aa958c9 --- /dev/null +++ b/ext/opcache/tests/jit/gh19669-002.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-19669 002: assertion failure zend_jit_trace_type_to_info_ex +--CREDITS-- +YuanchengJiang +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Warning: The float -1.8446744073709552E+19 is not representable as an int, cast occurred in %s on line %d +int(-10) diff --git a/ext/opcache/tests/jit/gh19831_001.phpt b/ext/opcache/tests/jit/gh19831_001.phpt new file mode 100644 index 0000000000000..c83ca6daa50d5 --- /dev/null +++ b/ext/opcache/tests/jit/gh19831_001.phpt @@ -0,0 +1,33 @@ +--TEST-- +GH-19831 001: fetch obj slow R REG + reference +--CREDITS-- +dktapps +--ENV-- +RT_COND=1 +--INI-- +opcache.jit=1203 +--FILE-- +layers; + } +} + +$t = new Test(); +$a = &$t->layers; +var_dump($t->getLayers()); + +?> +--EXPECT-- +int(1) diff --git a/ext/opcache/tests/jit/gh19831_002.phpt b/ext/opcache/tests/jit/gh19831_002.phpt new file mode 100644 index 0000000000000..25b596a3decb3 --- /dev/null +++ b/ext/opcache/tests/jit/gh19831_002.phpt @@ -0,0 +1,39 @@ +--TEST-- +GH-19831 002: fetch obj slow R REG + __get + reference +--CREDITS-- +dktapps +--ENV-- +RT_COND=1 +--INI-- +opcache.jit=1203 +--FILE-- +layers; + } +} + +$t = new Test(); +unset($t->layers); +var_dump($t->getLayers()); + +?> +--EXPECT-- +int(1) 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/jit/nan_001.phpt b/ext/opcache/tests/jit/nan_001.phpt index 3ff102745414f..5765adcf5f781 100644 --- a/ext/opcache/tests/jit/nan_001.phpt +++ b/ext/opcache/tests/jit/nan_001.phpt @@ -13,7 +13,12 @@ for ($i = 0; $i < 3; $i++) { else { echo "nan is false\n"; } } ?> ---EXPECT-- +--EXPECTF-- +Warning: unexpected NAN value was coerced to bool in %s on line 4 nan is true + +Warning: unexpected NAN value was coerced to bool in %s on line 4 nan is true + +Warning: unexpected NAN value was coerced to bool in %s on line 4 nan is true diff --git a/ext/opcache/tests/jit/nan_002.phpt b/ext/opcache/tests/jit/nan_002.phpt index 01cb1ebb40d40..8d6ac8e11111d 100644 --- a/ext/opcache/tests/jit/nan_002.phpt +++ b/ext/opcache/tests/jit/nan_002.phpt @@ -9,13 +9,13 @@ opcache.protect_memory=1 ---EXPECT-- +--EXPECTF-- +Warning: unexpected NAN value was coerced to bool in %s on line 3 string(1) "1" + +Warning: unexpected NAN value was coerced to bool in %s on line 4 + +Warning: unexpected NAN value was coerced to bool in %s on line 5 bool(true) + +Warning: unexpected NAN value was coerced to bool in %s on line 6 bool(false) string(1) "1" @@ -46,10 +53,14 @@ string(1) "2" bool(false) bool(true) + +Warning: unexpected NAN value was coerced to bool in %s on line 10 bool(true) bool(true) bool(false) + +Warning: unexpected NAN value was coerced to bool in %s on line 13 bool(true) bool(true) bool(false) diff --git a/ext/opcache/tests/jit/nan_bool_cast.phpt b/ext/opcache/tests/jit/nan_bool_cast.phpt new file mode 100644 index 0000000000000..0a68a682412f1 --- /dev/null +++ b/ext/opcache/tests/jit/nan_bool_cast.phpt @@ -0,0 +1,15 @@ +--TEST-- +Const NAN with bool cast should emit 1 warning +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +--EXTENSIONS-- +opcache +--FILE-- + +--EXPECTF-- +Warning: unexpected NAN value was coerced to bool in %s on line 2 +1 diff --git a/ext/opcache/tests/jit/reg_alloc_003_32bits.phpt b/ext/opcache/tests/jit/reg_alloc_003_32bits.phpt index 9b373c6230852..ecef070c3f2f5 100644 --- a/ext/opcache/tests/jit/reg_alloc_003_32bits.phpt +++ b/ext/opcache/tests/jit/reg_alloc_003_32bits.phpt @@ -23,5 +23,5 @@ function test($char_code) { echo test(65), "\n"; ?> --EXPECTF-- -Deprecated: Implicit conversion from float 4294967168 to int loses precision in %s on line %d +Warning: The float 4294967168 is not representable as an int, cast occurred in %s on line %d correct diff --git a/ext/opcache/tests/named_parameter_new.phpt b/ext/opcache/tests/named_parameter_new.phpt new file mode 100644 index 0000000000000..1f6f64333c988 --- /dev/null +++ b/ext/opcache/tests/named_parameter_new.phpt @@ -0,0 +1,72 @@ +--TEST-- +Named Parameters are optimized for known constructors +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +opcache.opt_debug_level=0x20000 +--SKIPIF-- + +--EXTENSIONS-- +opcache +--FILE-- + +--EXPECTF-- +$_main: + ; (lines=4, args=0, vars=0, tmps=%d) + ; (after optimizer) + ; %s +0000 INIT_STATIC_METHOD_CALL 1 string("MyClass") string("new") +0001 SEND_VAL int(1) 1 +0002 DO_UCALL +0003 RETURN int(1) + +MyClass::__construct: + ; (lines=7, args=2, vars=2, tmps=%d) + ; (after optimizer) + ; %s +0000 CV0($foo) = RECV 1 +0001 CV1($bar) = RECV_INIT 2 int(0) +0002 ASSIGN_OBJ THIS string("foo") +0003 OP_DATA CV0($foo) +0004 ASSIGN_OBJ THIS string("bar") +0005 OP_DATA CV1($bar) +0006 RETURN null + +MyClass::new: + ; (lines=10, args=1, vars=2, tmps=%d) + ; (after optimizer) + ; %s +0000 CV0($bar) = RECV 1 +0001 V2 = NEW 1 string("Random\\Engine\\Xoshiro256StarStar") +0002 SEND_VAL int(123) 1 +0003 DO_FCALL +0004 CV1($engine) = QM_ASSIGN V2 +0005 V2 = NEW 2 (self) (exception) +0006 SEND_VAR CV1($engine) 1 +0007 SEND_VAR CV0($bar) 2 +0008 DO_FCALL +0009 RETURN V2 +LIVE RANGES: + 2: 0002 - 0004 (new) + 2: 0006 - 0009 (new) 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..062ccd464559b 100644 --- a/ext/opcache/tests/opt/gh18107_1.phpt +++ b/ext/opcache/tests/opt/gh18107_1.phpt @@ -30,17 +30,18 @@ $_main: 0000 T1 = ISSET_ISEMPTY_CV (isset) CV0($badvar) 0001 JMPNZ T1 0006 0002 V3 = NEW 1 string("Exception") -0003 SEND_VAL_EX string("Should happen") 1 +0003 SEND_VAL%S string("Should happen") 1 0004 DO_FCALL 0005 THROW V3 0006 JMP 0006 0007 V6 = NEW 1 string("Exception") -0008 SEND_VAL_EX string("Should not happen") 1 +0008 SEND_VAL%S string("Should not happen") 1 0009 DO_FCALL 0010 THROW V6 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..bd34a54edf6e6 100644 --- a/ext/opcache/tests/opt/gh18107_2.phpt +++ b/ext/opcache/tests/opt/gh18107_2.phpt @@ -33,7 +33,7 @@ $_main: 0000 T2 = ISSET_ISEMPTY_CV (isset) CV0($badvar) 0001 JMPNZ T2 0008 0002 V4 = NEW 1 string("Exception") -0003 SEND_VAL_EX string("Should happen") 1 +0003 SEND_VAL%S string("Should happen") 1 0004 DO_FCALL 0005 THROW V4 0006 CV1($e) = CATCH string("Throwable") @@ -41,13 +41,14 @@ $_main: 0008 T6 = FAST_CALL 0010 0009 JMP 0015 0010 V7 = NEW 1 string("Exception") -0011 SEND_VAL_EX string("Should not happen") 1 +0011 SEND_VAL%S string("Should not happen") 1 0012 DO_FCALL 0013 THROW V7 0014 FAST_RET T6 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-- entries, *end = blacklist->entries + blacklist->pos; + const zend_blacklist_entry *p = blacklist->entries, *end = blacklist->entries + blacklist->pos; while (ppath); p++; @@ -336,14 +336,14 @@ void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename) zend_accel_blacklist_update_regexp(blacklist); } -bool zend_accel_blacklist_is_blacklisted(zend_blacklist *blacklist, char *verify_path, size_t verify_path_len) +bool zend_accel_blacklist_is_blacklisted(const zend_blacklist *blacklist, const char *verify_path, size_t verify_path_len) { int ret = 0; - zend_regexp_list *regexp_list_it = blacklist->regexp_list; + const zend_regexp_list *regexp_list_it = blacklist->regexp_list; pcre2_match_context *mctx = php_pcre_mctx(); if (regexp_list_it == NULL) { - return 0; + return false; } while (regexp_list_it != NULL) { pcre2_match_data *match_data = php_pcre_create_match_data(0, regexp_list_it->re); @@ -363,7 +363,7 @@ bool zend_accel_blacklist_is_blacklisted(zend_blacklist *blacklist, char *verify return ret; } -void zend_accel_blacklist_apply(zend_blacklist *blacklist, blacklist_apply_func_arg_t func, void *argument) +void zend_accel_blacklist_apply(const zend_blacklist *blacklist, blacklist_apply_func_arg_t func, void *argument) { int i; diff --git a/ext/opcache/zend_accelerator_blacklist.h b/ext/opcache/zend_accelerator_blacklist.h index 2a7921f63d947..da6e04e31b7ce 100644 --- a/ext/opcache/zend_accelerator_blacklist.h +++ b/ext/opcache/zend_accelerator_blacklist.h @@ -45,7 +45,7 @@ void zend_accel_blacklist_init(zend_blacklist *blacklist); void zend_accel_blacklist_shutdown(zend_blacklist *blacklist); void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename); -bool zend_accel_blacklist_is_blacklisted(zend_blacklist *blacklist, char *verify_path, size_t verify_path_len); -void zend_accel_blacklist_apply(zend_blacklist *blacklist, blacklist_apply_func_arg_t func, void *argument); +bool zend_accel_blacklist_is_blacklisted(const zend_blacklist *blacklist, const char *verify_path, size_t verify_path_len); +void zend_accel_blacklist_apply(const zend_blacklist *blacklist, blacklist_apply_func_arg_t func, void *argument); #endif /* ZEND_ACCELERATOR_BLACKLIST_H */ diff --git a/ext/opcache/zend_accelerator_hash.c b/ext/opcache/zend_accelerator_hash.c index 2fd3dfb5ed56e..5198c0b3b78c3 100644 --- a/ext/opcache/zend_accelerator_hash.c +++ b/ext/opcache/zend_accelerator_hash.c @@ -138,7 +138,7 @@ zend_accel_hash_entry* zend_accel_hash_update(zend_accel_hash *accel_hash, zend_ return entry; } -static zend_always_inline void* zend_accel_hash_find_ex(zend_accel_hash *accel_hash, zend_string *key, int data) +static zend_always_inline void* zend_accel_hash_find_ex(const zend_accel_hash *accel_hash, zend_string *key, bool data) { zend_ulong index; zend_accel_hash_entry *entry; @@ -176,20 +176,20 @@ static zend_always_inline void* zend_accel_hash_find_ex(zend_accel_hash *accel_h /* Returns the data associated with key on success * Returns NULL if data doesn't exist */ -void* zend_accel_hash_find(zend_accel_hash *accel_hash, zend_string *key) +void* zend_accel_hash_find(const zend_accel_hash *accel_hash, zend_string *key) { - return zend_accel_hash_find_ex(accel_hash, key, 1); + return zend_accel_hash_find_ex(accel_hash, key, true); } /* Returns the hash entry associated with key on success * Returns NULL if it doesn't exist */ -zend_accel_hash_entry* zend_accel_hash_find_entry(zend_accel_hash *accel_hash, zend_string *key) +zend_accel_hash_entry* zend_accel_hash_find_entry(const zend_accel_hash *accel_hash, zend_string *key) { - return (zend_accel_hash_entry *)zend_accel_hash_find_ex(accel_hash, key, 0); + return (zend_accel_hash_entry *)zend_accel_hash_find_ex(accel_hash, key, false); } -int zend_accel_hash_unlink(zend_accel_hash *accel_hash, zend_string *key) +zend_result zend_accel_hash_unlink(zend_accel_hash *accel_hash, zend_string *key) { zend_ulong hash_value; zend_ulong index; diff --git a/ext/opcache/zend_accelerator_hash.h b/ext/opcache/zend_accelerator_hash.h index 755d3f13ec516..2f91973853864 100644 --- a/ext/opcache/zend_accelerator_hash.h +++ b/ext/opcache/zend_accelerator_hash.h @@ -72,23 +72,23 @@ zend_accel_hash_entry* zend_accel_hash_update( void *data); void* zend_accel_hash_find( - zend_accel_hash *accel_hash, + const zend_accel_hash *accel_hash, zend_string *key); zend_accel_hash_entry* zend_accel_hash_find_entry( - zend_accel_hash *accel_hash, + const zend_accel_hash *accel_hash, zend_string *key); -int zend_accel_hash_unlink( +zend_result zend_accel_hash_unlink( zend_accel_hash *accel_hash, zend_string *key); -static inline bool zend_accel_hash_is_full(zend_accel_hash *accel_hash) +static inline bool zend_accel_hash_is_full(const zend_accel_hash *accel_hash) { if (accel_hash->num_entries == accel_hash->max_num_entries) { - return 1; + return true; } else { - return 0; + return false; } } diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index 56f9178ef0fca..a2569e07f14c9 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -25,6 +25,8 @@ #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" @@ -32,7 +34,6 @@ #include "SAPI.h" #include "zend_virtual_cwd.h" #include "ext/standard/info.h" -#include "ext/standard/php_filestat.h" #include "ext/date/php_date.h" #include "opcache_arginfo.h" @@ -60,7 +61,7 @@ static zif_handler orig_file_exists = NULL; static zif_handler orig_is_file = NULL; static zif_handler orig_is_readable = NULL; -static int validate_api_restriction(void) +static bool validate_api_restriction(void) { if (ZCG(accel_directives).restrict_api && *ZCG(accel_directives).restrict_api) { size_t len = strlen(ZCG(accel_directives).restrict_api); @@ -69,14 +70,23 @@ static int validate_api_restriction(void) strlen(SG(request_info).path_translated) < len || memcmp(SG(request_info).path_translated, ZCG(accel_directives).restrict_api, len) != 0) { zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " API is restricted by \"restrict_api\" configuration directive"); - return 0; + return false; } } - return 1; + return true; } 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 */ @@ -148,14 +158,27 @@ 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; - ZCG(accelerator_enabled) = 0; + *p = false; + ZCG(accelerator_enabled) = false; return SUCCESS; } } @@ -339,7 +362,7 @@ ZEND_INI_BEGIN() #endif ZEND_INI_END() -static int filename_is_in_cache(zend_string *filename) +static bool filename_is_in_cache(zend_string *filename) { zend_string *key; @@ -349,27 +372,26 @@ static int filename_is_in_cache(zend_string *filename) if (persistent_script && !persistent_script->corrupted) { if (ZCG(accel_directives).validate_timestamps) { zend_file_handle handle; - int ret; + bool ret; zend_stream_init_filename_ex(&handle, filename); - ret = validate_timestamp_and_record_ex(persistent_script, &handle) == SUCCESS - ? 1 : 0; + ret = validate_timestamp_and_record_ex(persistent_script, &handle) == SUCCESS; zend_destroy_file_handle(&handle); return ret; } - return 1; + return true; } } - return 0; + return false; } -static int filename_is_in_file_cache(zend_string *filename) +static bool filename_is_in_file_cache(zend_string *filename) { zend_string *realpath = zend_resolve_path(filename); if (!realpath) { - return 0; + return false; } zend_file_handle handle; @@ -382,7 +404,7 @@ static int filename_is_in_file_cache(zend_string *filename) return result != NULL; } -static int accel_file_in_cache(INTERNAL_FUNCTION_PARAMETERS) +static bool accel_file_in_cache(INTERNAL_FUNCTION_PARAMETERS) { if (ZEND_NUM_ARGS() == 1) { zval *zv = ZEND_CALL_ARG(execute_data , 1); @@ -391,7 +413,7 @@ static int accel_file_in_cache(INTERNAL_FUNCTION_PARAMETERS) return filename_is_in_cache(Z_STR_P(zv)); } } - return 0; + return false; } static ZEND_NAMED_FUNCTION(accel_file_exists) @@ -423,13 +445,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; @@ -460,6 +488,7 @@ static ZEND_MSHUTDOWN_FUNCTION(zend_accelerator) UNREGISTER_INI_ENTRIES(); accel_shutdown(); + return SUCCESS; } @@ -572,7 +601,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, @@ -587,11 +616,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) { @@ -599,8 +623,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; @@ -630,8 +652,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); @@ -648,7 +668,7 @@ ZEND_FUNCTION(opcache_get_status) { zend_long reqs; zval memory_usage, statistics, scripts; - bool fetch_scripts = 1; + bool fetch_scripts = true; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &fetch_scripts) == FAILURE) { RETURN_THROWS(); @@ -915,7 +935,7 @@ ZEND_FUNCTION(opcache_reset) ZEND_FUNCTION(opcache_invalidate) { zend_string *script_name; - bool force = 0; + bool force = false; if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|b", &script_name, &force) == FAILURE) { RETURN_THROWS(); @@ -925,11 +945,7 @@ ZEND_FUNCTION(opcache_invalidate) RETURN_FALSE; } - if (zend_accel_invalidate(script_name, force) == SUCCESS) { - RETURN_TRUE; - } else { - RETURN_FALSE; - } + RETURN_BOOL(zend_accel_invalidate(script_name, force) == SUCCESS); } /* {{{ Prevents JIT on function. Call it before the first invocation of the given function. */ 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_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c index 21f056901fd1b..2de7854fb14c5 100644 --- a/ext/opcache/zend_accelerator_util_funcs.c +++ b/ext/opcache/zend_accelerator_util_funcs.c @@ -47,7 +47,7 @@ zend_persistent_script* create_persistent_script(void) return persistent_script; } -void free_persistent_script(zend_persistent_script *persistent_script, int destroy_elements) +void free_persistent_script(zend_persistent_script *persistent_script, bool destroy_elements) { if (!destroy_elements) { /* Both the keys and values have been transferred into the global tables. @@ -65,16 +65,6 @@ void free_persistent_script(zend_persistent_script *persistent_script, int destr zend_string_release_ex(persistent_script->script.filename, 0); } - if (persistent_script->warnings) { - for (uint32_t i = 0; i < persistent_script->num_warnings; i++) { - zend_error_info *info = persistent_script->warnings[i]; - zend_string_release(info->filename); - zend_string_release(info->message); - efree(info); - } - efree(persistent_script->warnings); - } - zend_accel_free_delayed_early_binding_list(persistent_script); efree(persistent_script); @@ -115,7 +105,7 @@ void zend_accel_move_user_classes(HashTable *src, uint32_t count, zend_script *s { Bucket *p, *end; HashTable *dst; - zend_string *filename; + const zend_string *filename; dtor_func_t orig_dtor; zend_class_entry *ce; @@ -142,10 +132,10 @@ void zend_accel_move_user_classes(HashTable *src, uint32_t count, zend_script *s src->pDestructor = orig_dtor; } -static zend_always_inline void _zend_accel_function_hash_copy(HashTable *target, HashTable *source, bool call_observers) +static zend_always_inline void _zend_accel_function_hash_copy(HashTable *target, const HashTable *source, bool call_observers) { zend_function *function1, *function2; - Bucket *p, *end; + const Bucket *p, *end; zval *t; zend_hash_extend(target, target->nNumUsed + source->nNumUsed, 0); @@ -184,20 +174,20 @@ static zend_always_inline void _zend_accel_function_hash_copy(HashTable *target, } } -static zend_always_inline void zend_accel_function_hash_copy(HashTable *target, HashTable *source) +static zend_always_inline void zend_accel_function_hash_copy(HashTable *target, const HashTable *source) { - _zend_accel_function_hash_copy(target, source, 0); + _zend_accel_function_hash_copy(target, source, false); } -static zend_never_inline void zend_accel_function_hash_copy_notify(HashTable *target, HashTable *source) +static zend_never_inline void zend_accel_function_hash_copy_notify(HashTable *target, const HashTable *source) { - _zend_accel_function_hash_copy(target, source, 1); + _zend_accel_function_hash_copy(target, source, true); } -static zend_always_inline void _zend_accel_class_hash_copy(HashTable *target, HashTable *source, bool call_observers) +static zend_always_inline void _zend_accel_class_hash_copy(HashTable *target, const HashTable *source, bool call_observers) { - Bucket *p, *end; - zval *t; + const Bucket *p, *end; + const zval *t; zend_hash_extend(target, target->nNumUsed + source->nNumUsed, 0); p = source->arData; @@ -219,7 +209,7 @@ static zend_always_inline void _zend_accel_class_hash_copy(HashTable *target, Ha * value. */ continue; } else if (UNEXPECTED(!ZCG(accel_directives).ignore_dups)) { - zend_class_entry *ce1 = Z_PTR(p->val); + const zend_class_entry *ce1 = Z_PTR(p->val); if (!(ce1->ce_flags & ZEND_ACC_ANON_CLASS)) { CG(in_compilation) = 1; zend_set_compiled_filename(ce1->info.user.filename); @@ -245,25 +235,25 @@ static zend_always_inline void _zend_accel_class_hash_copy(HashTable *target, Ha target->nInternalPointer = 0; } -static zend_always_inline void zend_accel_class_hash_copy(HashTable *target, HashTable *source) +static zend_always_inline void zend_accel_class_hash_copy(HashTable *target, const HashTable *source) { - _zend_accel_class_hash_copy(target, source, 0); + _zend_accel_class_hash_copy(target, source, false); } -static zend_never_inline void zend_accel_class_hash_copy_notify(HashTable *target, HashTable *source) +static zend_never_inline void zend_accel_class_hash_copy_notify(HashTable *target, const HashTable *source) { - _zend_accel_class_hash_copy(target, source, 1); + _zend_accel_class_hash_copy(target, source, true); } void zend_accel_build_delayed_early_binding_list(zend_persistent_script *persistent_script) { - zend_op_array *op_array = &persistent_script->script.main_op_array; + const zend_op_array *op_array = &persistent_script->script.main_op_array; if (!(op_array->fn_flags & ZEND_ACC_EARLY_BINDING)) { return; } - zend_op *end = op_array->opcodes + op_array->last; - for (zend_op *opline = op_array->opcodes; opline < end; opline++) { + const zend_op *end = op_array->opcodes + op_array->last; + for (const zend_op *opline = op_array->opcodes; opline < end; opline++) { if (opline->opcode == ZEND_DECLARE_CLASS_DELAYED) { persistent_script->num_early_bindings++; } @@ -274,7 +264,7 @@ void zend_accel_build_delayed_early_binding_list(zend_persistent_script *persist for (zend_op *opline = op_array->opcodes; opline < end; opline++) { if (opline->opcode == ZEND_DECLARE_CLASS_DELAYED) { - zval *lcname = RT_CONSTANT(opline, opline->op1); + const zval *lcname = RT_CONSTANT(opline, opline->op1); early_binding->lcname = zend_string_copy(Z_STR_P(lcname)); early_binding->rtd_key = zend_string_copy(Z_STR_P(lcname + 1)); early_binding->lc_parent_name = @@ -285,19 +275,19 @@ void zend_accel_build_delayed_early_binding_list(zend_persistent_script *persist } } -void zend_accel_finalize_delayed_early_binding_list(zend_persistent_script *persistent_script) +void zend_accel_finalize_delayed_early_binding_list(const zend_persistent_script *persistent_script) { if (!persistent_script->num_early_bindings) { return; } zend_early_binding *early_binding = persistent_script->early_bindings; - zend_early_binding *early_binding_end = early_binding + persistent_script->num_early_bindings; - zend_op_array *op_array = &persistent_script->script.main_op_array; - zend_op *opline_end = op_array->opcodes + op_array->last; + const zend_early_binding *early_binding_end = early_binding + persistent_script->num_early_bindings; + const zend_op_array *op_array = &persistent_script->script.main_op_array; + const zend_op *opline_end = op_array->opcodes + op_array->last; for (zend_op *opline = op_array->opcodes; opline < opline_end; opline++) { if (opline->opcode == ZEND_DECLARE_CLASS_DELAYED) { - zend_string *rtd_key = Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1); + const zend_string *rtd_key = Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1); /* Skip early_binding entries that don't match, maybe their DECLARE_CLASS_DELAYED * was optimized away. */ while (!zend_string_equals(early_binding->rtd_key, rtd_key)) { @@ -320,7 +310,7 @@ void zend_accel_free_delayed_early_binding_list(zend_persistent_script *persiste { if (persistent_script->num_early_bindings) { for (uint32_t i = 0; i < persistent_script->num_early_bindings; i++) { - zend_early_binding *early_binding = &persistent_script->early_bindings[i]; + const zend_early_binding *early_binding = &persistent_script->early_bindings[i]; zend_string_release(early_binding->lcname); zend_string_release(early_binding->rtd_key); zend_string_release(early_binding->lc_parent_name); @@ -332,7 +322,7 @@ void zend_accel_free_delayed_early_binding_list(zend_persistent_script *persiste } static void zend_accel_do_delayed_early_binding( - zend_persistent_script *persistent_script, zend_op_array *op_array) + const zend_persistent_script *persistent_script, zend_op_array *op_array) { ZEND_ASSERT(!ZEND_MAP_PTR(op_array->run_time_cache)); ZEND_ASSERT(op_array->fn_flags & ZEND_ACC_HEAP_RT_CACHE); @@ -346,7 +336,7 @@ static void zend_accel_do_delayed_early_binding( CG(compiled_filename) = persistent_script->script.filename; CG(in_compilation) = 1; for (uint32_t i = 0; i < persistent_script->num_early_bindings; i++) { - zend_early_binding *early_binding = &persistent_script->early_bindings[i]; + const zend_early_binding *early_binding = &persistent_script->early_bindings[i]; zend_class_entry *ce = zend_hash_find_ex_ptr(EG(class_table), early_binding->lcname, 1); if (!ce) { zval *zv = zend_hash_find_known_hash(EG(class_table), early_binding->rtd_key); @@ -368,7 +358,7 @@ static void zend_accel_do_delayed_early_binding( CG(in_compilation) = orig_in_compilation; } -zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, int from_shared_memory) +zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, bool from_shared_memory) { zend_op_array *op_array; @@ -458,7 +448,7 @@ zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, #define ADLER32_SCALAR_DO8(buf, i) ADLER32_SCALAR_DO4(buf, i); ADLER32_SCALAR_DO4(buf, i + 4); #define ADLER32_SCALAR_DO16(buf) ADLER32_SCALAR_DO8(buf, 0); ADLER32_SCALAR_DO8(buf, 8); -static zend_always_inline void adler32_do16_loop(unsigned char *buf, unsigned char *end, unsigned int *s1_out, unsigned int *s2_out) +static zend_always_inline void adler32_do16_loop(unsigned char *buf, const unsigned char *end, unsigned int *s1_out, unsigned int *s2_out) { unsigned int s1 = *s1_out; unsigned int s2 = *s2_out; diff --git a/ext/opcache/zend_accelerator_util_funcs.h b/ext/opcache/zend_accelerator_util_funcs.h index 53cc1de9effaa..fa248edeef550 100644 --- a/ext/opcache/zend_accelerator_util_funcs.h +++ b/ext/opcache/zend_accelerator_util_funcs.h @@ -28,15 +28,15 @@ BEGIN_EXTERN_C() zend_persistent_script* create_persistent_script(void); -void free_persistent_script(zend_persistent_script *persistent_script, int destroy_elements); +void free_persistent_script(zend_persistent_script *persistent_script, bool destroy_elements); void zend_accel_move_user_functions(HashTable *str, uint32_t count, zend_script *script); void zend_accel_move_user_classes(HashTable *str, uint32_t count, zend_script *script); void zend_accel_build_delayed_early_binding_list(zend_persistent_script *persistent_script); -void zend_accel_finalize_delayed_early_binding_list(zend_persistent_script *persistent_script); +void zend_accel_finalize_delayed_early_binding_list(const zend_persistent_script *persistent_script); void zend_accel_free_delayed_early_binding_list(zend_persistent_script *persistent_script); -zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, int from_shared_memory); +zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, bool from_shared_memory); #define ADLER32_INIT 1 /* initial Adler-32 value */ diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index 4b47bb54e7acd..d430f4833d3ca 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -135,17 +135,13 @@ static int zend_file_cache_flock(int fd, int type) (ptr) = (void*)((char*)buf + (size_t)(ptr)); \ } \ } while (0) + #define SERIALIZE_STR(ptr) do { \ if (ptr) { \ if (IS_ACCEL_INTERNED(ptr)) { \ (ptr) = zend_file_cache_serialize_interned((zend_string*)(ptr), info); \ } else { \ ZEND_ASSERT(IS_UNSERIALIZED(ptr)); \ - /* script->corrupted shows if the script in SHM or not */ \ - if (EXPECTED(script->corrupted)) { \ - GC_ADD_FLAGS(ptr, IS_STR_INTERNED); \ - GC_DEL_FLAGS(ptr, IS_STR_PERMANENT); \ - } \ (ptr) = (void*)((char*)(ptr) - (char*)script->mem); \ } \ } \ @@ -164,6 +160,7 @@ static int zend_file_cache_flock(int fd, int type) GC_ADD_FLAGS(ptr, IS_STR_INTERNED); \ GC_DEL_FLAGS(ptr, IS_STR_PERMANENT); \ } \ + GC_DEL_FLAGS(ptr, IS_STR_CLASS_NAME_MAP_PTR); \ } \ } \ } while (0) @@ -461,6 +458,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); @@ -572,13 +570,32 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra } if (opline->op2_type == IS_CONST) { SERIALIZE_PTR(opline->op2.zv); + + /* See GH-17733. Reset Z_EXTRA_P(op2) of ZEND_INIT_FCALL, which + * is an offset into the global function table, to avoid calling + * incorrect functions when environment changes. This, and the + * equivalent code below, can be removed once proper system ID + * validation is implemented. */ + if (opline->opcode == ZEND_INIT_FCALL) { + zval *op2 = opline->op2.zv; + UNSERIALIZE_PTR(op2); + Z_EXTRA_P(op2) = 0; + ZEND_VM_SET_OPCODE_HANDLER(opline); + } } #else if (opline->op1_type == IS_CONST) { opline->op1.constant = RT_CONSTANT(opline, opline->op1) - literals; } if (opline->op2_type == IS_CONST) { - opline->op2.constant = RT_CONSTANT(opline, opline->op2) - literals; + zval *op2 = RT_CONSTANT(opline, opline->op2); + opline->op2.constant = op2 - literals; + + /* See GH-17733 and comment above. */ + if (opline->opcode == ZEND_INIT_FCALL) { + Z_EXTRA_P(op2) = 0; + ZEND_VM_SET_OPCODE_HANDLER(opline); + } } #endif #if ZEND_USE_ABS_JMP_ADDR @@ -1352,6 +1369,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); diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 05a7cb00077c1..ef69cceb0250b 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) { @@ -729,7 +732,7 @@ static void zend_persist_op_array(zval *zv) } } -static zend_op_array *zend_persist_class_method(zend_op_array *op_array, zend_class_entry *ce) +static zend_op_array *zend_persist_class_method(zend_op_array *op_array, const zend_class_entry *ce) { zend_op_array *old_op_array; @@ -831,7 +834,7 @@ static zend_property_info *zend_persist_property_info(zend_property_info *prop) prop->attributes = zend_persist_attributes(prop->attributes); } if (prop->prototype) { - zend_property_info *new_prototype = (zend_property_info *) zend_shared_alloc_get_xlat_entry(prop->prototype); + const zend_property_info *new_prototype = (const zend_property_info *) zend_shared_alloc_get_xlat_entry(prop->prototype); if (new_prototype) { prop->prototype = new_prototype; } @@ -851,7 +854,7 @@ static zend_property_info *zend_persist_property_info(zend_property_info *prop) } } #endif - zend_property_info *new_prop_info = (zend_property_info *) zend_shared_alloc_get_xlat_entry(hook->prop_info); + const zend_property_info *new_prop_info = (const zend_property_info *) zend_shared_alloc_get_xlat_entry(hook->prop_info); if (new_prop_info) { hook->prop_info = new_prop_info; } @@ -865,7 +868,7 @@ static zend_property_info *zend_persist_property_info(zend_property_info *prop) static void zend_persist_class_constant(zval *zv) { - zend_class_constant *orig_c = Z_PTR_P(zv); + const zend_class_constant *orig_c = Z_PTR_P(zv); zend_class_constant *c = zend_shared_alloc_get_xlat_entry(orig_c); zend_class_entry *ce; @@ -964,12 +967,11 @@ zend_class_entry *zend_persist_class_entry(zend_class_entry *orig_ce) } } if (ce->default_static_members_table) { - int i; ce->default_static_members_table = zend_shared_memdup_free(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count); /* Persist only static properties in this class. * Static properties from parent classes will be handled in class_copy_ctor and are marked with IS_INDIRECT */ - for (i = 0; i < ce->default_static_members_count; i++) { + for (uint32_t i = 0; i < ce->default_static_members_count; i++) { if (Z_TYPE(ce->default_static_members_table[i]) != IS_INDIRECT) { zend_persist_zval(&ce->default_static_members_table[i]); } @@ -1284,7 +1286,7 @@ 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) +static void zend_accel_persist_jit_op_array(zend_op_array *op_array, const zend_class_entry *ce) { if (op_array->type == ZEND_USER_FUNCTION) { if (op_array->scope == ce @@ -1298,7 +1300,7 @@ static void zend_accel_persist_jit_op_array(zend_op_array *op_array, zend_class_ } } -static void zend_accel_persist_link_func_info(zend_op_array *op_array, zend_class_entry *ce) +static void zend_accel_persist_link_func_info(zend_op_array *op_array, const zend_class_entry *ce) { if (op_array->type == ZEND_USER_FUNCTION && !(op_array->fn_flags & ZEND_ACC_ABSTRACT)) { @@ -1394,11 +1396,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; @@ -1418,7 +1420,7 @@ static zend_early_binding *zend_persist_early_bindings( return early_bindings; } -zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, int for_shm) +zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, bool for_shm) { Bucket *p; diff --git a/ext/opcache/zend_persist.h b/ext/opcache/zend_persist.h index 930430c9589b7..c8220217630e7 100644 --- a/ext/opcache/zend_persist.h +++ b/ext/opcache/zend_persist.h @@ -24,8 +24,8 @@ BEGIN_EXTERN_C() -uint32_t zend_accel_script_persist_calc(zend_persistent_script *script, int for_shm); -zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, int for_shm); +uint32_t zend_accel_script_persist_calc(zend_persistent_script *script, bool for_shm); +zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, bool for_shm); void zend_persist_class_entry_calc(zend_class_entry *ce); zend_class_entry *zend_persist_class_entry(zend_class_entry *ce); diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index 639d7d5446705..c638d66619d0f 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -47,9 +47,9 @@ } while (0) static void zend_persist_zval_calc(zval *z); -static void zend_persist_op_array_calc(zval *zv); +static void zend_persist_op_array_calc(const zval *zv); -static void zend_hash_persist_calc(HashTable *ht) +static void zend_hash_persist_calc(const HashTable *ht) { if ((HT_FLAGS(ht) & HASH_FLAG_UNINITIALIZED) || ht->nNumUsed == 0) { return; @@ -79,7 +79,7 @@ static void zend_persist_ast_calc(zend_ast *ast) ADD_SIZE(sizeof(zend_ast_zval)); zend_persist_zval_calc(&((zend_ast_zval*)(ast))->val); } 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); ADD_SIZE(sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * list->children); for (i = 0; i < list->children; i++) { if (list->child[i]) { @@ -125,7 +125,7 @@ static void zend_persist_zval_calc(zval *z) } size = zend_shared_memdup_size(Z_ARR_P(z), sizeof(zend_array)); if (size) { - HashTable *ht = Z_ARRVAL_P(z); + const HashTable *ht = Z_ARRVAL_P(z); ADD_SIZE(size); zend_hash_persist_calc(ht); @@ -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) { @@ -215,7 +218,7 @@ static void zend_persist_type_calc(zend_type *type) static void zend_persist_op_array_calc_ex(zend_op_array *op_array) { if (op_array->function_name) { - zend_string *old_name = op_array->function_name; + const zend_string *old_name = op_array->function_name; ADD_INTERNED_STRING(op_array->function_name); /* Remember old function name, so it can be released multiple times if shared. */ if (op_array->function_name != old_name @@ -255,7 +258,7 @@ static void zend_persist_op_array_calc_ex(zend_op_array *op_array) if (op_array->literals) { zval *p = op_array->literals; - zval *end = p + op_array->last_literal; + const zval *end = p + op_array->last_literal; ADD_SIZE(sizeof(zval) * op_array->last_literal); while (p < end) { zend_persist_zval_calc(p); @@ -269,7 +272,7 @@ static void zend_persist_op_array_calc_ex(zend_op_array *op_array) /* ZEND_ACC_PTR_OPS and ZEND_ACC_OVERRIDE use the same value */ if ((op_array->fn_flags & ZEND_ACC_PTR_OPS) && !op_array->function_name) { zend_op *op = op_array->opcodes; - zend_op *end = op + op_array->last; + const zend_op *end = op + op_array->last; while (op < end) { if (op->opcode == ZEND_DECLARE_ATTRIBUTED_CONST) { HashTable *attributes = Z_PTR_P(RT_CONSTANT(op+1, (op+1)->op1)); @@ -341,7 +344,7 @@ static void zend_persist_op_array_calc_ex(zend_op_array *op_array) ADD_SIZE(ZEND_ALIGNED_SIZE(zend_extensions_op_array_persist_calc(op_array))); } -static void zend_persist_op_array_calc(zval *zv) +static void zend_persist_op_array_calc(const zval *zv) { zend_op_array *op_array = Z_PTR_P(zv); ZEND_ASSERT(op_array->type == ZEND_USER_FUNCTION); @@ -414,7 +417,7 @@ static void zend_persist_property_info_calc(zend_property_info *prop) } } -static void zend_persist_class_constant_calc(zval *zv) +static void zend_persist_class_constant_calc(const zval *zv) { zend_class_constant *c = Z_PTR_P(zv); @@ -476,10 +479,8 @@ void zend_persist_class_entry_calc(zend_class_entry *ce) } } if (ce->default_static_members_table) { - int i; - ADD_SIZE(sizeof(zval) * ce->default_static_members_count); - for (i = 0; i < ce->default_static_members_count; i++) { + for (uint32_t i = 0; i < ce->default_static_members_count; i++) { if (Z_TYPE(ce->default_static_members_table[i]) != IS_INDIRECT) { zend_persist_zval_calc(&ce->default_static_members_table[i]); } @@ -593,7 +594,7 @@ void zend_persist_class_entry_calc(zend_class_entry *ce) } } -static void zend_accel_persist_class_table_calc(HashTable *class_table) +static void zend_accel_persist_class_table_calc(const HashTable *class_table) { Bucket *p; @@ -626,7 +627,7 @@ static void zend_persist_early_bindings_calc( } } -uint32_t zend_accel_script_persist_calc(zend_persistent_script *new_persistent_script, int for_shm) +uint32_t zend_accel_script_persist_calc(zend_persistent_script *new_persistent_script, bool for_shm) { Bucket *p; 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 6b2fcd7898b38..2c09b89e31200 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -53,11 +53,6 @@ #include #include #include -#if PHP_OPENSSL_API_VERSION >= 0x30000 -#include -#include -#include -#endif ZEND_DECLARE_MODULE_GLOBALS(openssl) @@ -308,7 +303,7 @@ bool php_openssl_check_path_ex( fs_file_path_len = file_path_len; } - if (CHECK_NULL_PATH(fs_file_path, fs_file_path_len)) { + if (zend_char_has_nul_byte(fs_file_path, fs_file_path_len)) { error_msg = "must not contain any null bytes"; error_type = E_ERROR; } else if (expand_filepath(fs_file_path, real_path) == NULL) { @@ -355,7 +350,15 @@ 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 { @@ -2348,6 +2351,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(); @@ -2410,9 +2421,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) { @@ -2733,7 +2744,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; @@ -3055,19 +3066,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(); @@ -3185,6 +3196,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; @@ -3194,11 +3206,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)); @@ -3257,7 +3274,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"); @@ -3382,7 +3403,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; @@ -3687,13 +3708,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"); @@ -3725,6 +3746,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) @@ -3780,10 +3824,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(); } @@ -3798,7 +3844,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; @@ -3820,6 +3866,7 @@ PHP_FUNCTION(openssl_private_decrypt) RETVAL_TRUE; cleanup: + php_openssl_release_evp_md(md); EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(pkey); } @@ -3831,9 +3878,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(); } @@ -3848,7 +3897,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; @@ -3869,6 +3918,7 @@ PHP_FUNCTION(openssl_public_encrypt) RETVAL_TRUE; cleanup: + php_openssl_release_evp_md(md); EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(pkey); } @@ -3879,7 +3929,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) { @@ -3952,6 +4002,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) { @@ -3964,14 +4038,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); @@ -3996,7 +4073,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)) { @@ -4029,14 +4107,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); @@ -4061,11 +4142,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); @@ -4102,7 +4197,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; @@ -4231,7 +4326,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; @@ -4275,7 +4370,7 @@ PHP_FUNCTION(openssl_open) /* {{{ Return array of available digest algorithms */ PHP_FUNCTION(openssl_get_md_methods) { - bool aliases = 0; + bool aliases = false; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &aliases) == FAILURE) { RETURN_THROWS(); @@ -4287,7 +4382,7 @@ PHP_FUNCTION(openssl_get_md_methods) /* {{{ Return array of available cipher algorithms */ PHP_FUNCTION(openssl_get_cipher_methods) { - bool aliases = 0; + bool aliases = false; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &aliases) == FAILURE) { RETURN_THROWS(); @@ -4329,7 +4424,7 @@ PHP_FUNCTION(openssl_get_curve_names) /* {{{ Computes digest hash value for given data using given method, returns raw or binhex encoded string */ PHP_FUNCTION(openssl_digest) { - bool raw_output = 0; + bool raw_output = false; char *data, *method; size_t data_len, method_len; const EVP_MD *mdtype; 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 75936b3671f2f..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); @@ -642,10 +651,8 @@ static void register_openssl_symbols(int module_number) 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_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); @@ -673,19 +680,14 @@ static void register_openssl_symbols(int module_number) 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_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_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 272ebd6915a46..611359cccaba6 100644 --- a/ext/openssl/openssl_backend_common.c +++ b/ext/openssl/openssl_backend_common.c @@ -473,23 +473,8 @@ zend_result php_openssl_write_rand_file(const char * file, int egdsocket, int se return SUCCESS; } -void php_openssl_backend_init(void) +void php_openssl_backend_init_common(void) { -#ifdef LIBRESSL_VERSION_NUMBER - OPENSSL_config(NULL); - SSL_library_init(); - OpenSSL_add_all_ciphers(); - OpenSSL_add_all_digests(); - OpenSSL_add_all_algorithms(); - SSL_load_error_strings(); -#else -#if PHP_OPENSSL_API_VERSION >= 0x30000 && defined(LOAD_OPENSSL_LEGACY_PROVIDER) - OSSL_PROVIDER_load(NULL, "legacy"); - OSSL_PROVIDER_load(NULL, "default"); -#endif - OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL); -#endif - /* Determine default SSL configuration file */ char *config_filename = getenv("OPENSSL_CONF"); if (config_filename == NULL) { @@ -541,18 +526,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)) { @@ -589,12 +570,12 @@ X509 *php_openssl_x509_from_zval( zval *val, bool *free_cert, uint32_t arg_num, bool is_from_array, const char *option_name) { if (php_openssl_is_certificate_ce(val)) { - *free_cert = 0; + *free_cert = false; return php_openssl_certificate_from_obj(Z_OBJ_P(val))->x509; } - *free_cert = 1; + *free_cert = true; zend_string *str = zval_try_get_string(val); if (str == NULL) { @@ -612,7 +593,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)) { @@ -730,7 +711,7 @@ STACK_OF(X509) *php_openssl_load_all_certs_from_file( } /* This loads from a file, a stack of x509/crl/pkey sets */ - if (!(sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL))) { + if (!(sk = php_openssl_pem_read_bio_x509_info(in))) { php_openssl_store_errors(); php_error_docref(NULL, E_WARNING, "Error reading the file, %s", cert_path); sk_X509_free(stack); @@ -1127,7 +1108,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 +1139,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; } @@ -1275,7 +1256,7 @@ EVP_PKEY *php_openssl_pkey_from_zval( cert = php_openssl_x509_from_str(val_str, arg_num, false, NULL); if (cert) { - free_cert = 1; + free_cert = true; } else { /* not a X509 certificate, try to retrieve public key */ php_openssl_errors_restore_mark(); @@ -1290,7 +1271,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 +1289,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 +1325,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 +1347,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(); @@ -1689,7 +1685,7 @@ zend_result php_openssl_validate_iv(const char **piv, size_t *piv_len, size_t iv /* BC behavior */ *piv_len = iv_required_len; *piv = iv_new; - *free_iv = 1; + *free_iv = true; return SUCCESS; } @@ -1701,7 +1697,7 @@ zend_result php_openssl_validate_iv(const char **piv, size_t *piv_len, size_t iv memcpy(iv_new, *piv, *piv_len); *piv_len = iv_required_len; *piv = iv_new; - *free_iv = 1; + *free_iv = true; return SUCCESS; } @@ -1711,7 +1707,7 @@ zend_result php_openssl_validate_iv(const char **piv, size_t *piv_len, size_t iv memcpy(iv_new, *piv, iv_required_len); *piv_len = iv_required_len; *piv = iv_new; - *free_iv = 1; + *free_iv = true; return SUCCESS; } @@ -1726,7 +1722,7 @@ zend_result php_openssl_cipher_init(const EVP_CIPHER *cipher_type, int key_len, password_len; size_t max_iv_len; - *free_password = 0; + *free_password = false; max_iv_len = EVP_CIPHER_iv_length(cipher_type); if (enc && *piv_len == 0 && max_iv_len > 0 && !mode->is_aead) { @@ -1769,7 +1765,7 @@ zend_result php_openssl_cipher_init(const EVP_CIPHER *cipher_type, memcpy(key, *ppassword, password_len); *ppassword = (char *) key; *ppassword_len = key_len; - *free_password = 1; + *free_password = true; } else { if (password_len > key_len && !EVP_CIPHER_CTX_set_key_length(cipher_ctx, password_len)) { php_openssl_store_errors(); @@ -1841,7 +1837,7 @@ PHP_OPENSSL_API zend_string* php_openssl_encrypt( EVP_CIPHER_CTX *cipher_ctx; struct php_openssl_cipher_mode mode; int i = 0, outlen; - bool free_iv = 0, free_password = 0; + bool free_iv = false, free_password = false; zend_string *outbuf = NULL; PHP_OPENSSL_CHECK_SIZE_T_TO_INT_NULL_RETURN(data_len, data); @@ -1935,7 +1931,7 @@ PHP_OPENSSL_API zend_string* php_openssl_decrypt( struct php_openssl_cipher_mode mode; int i = 0, outlen; zend_string *base64_str = NULL; - bool free_iv = 0, free_password = 0; + bool free_iv = false, free_password = false; zend_string *outbuf = NULL; PHP_OPENSSL_CHECK_SIZE_T_TO_INT_NULL_RETURN(data_len, data); diff --git a/ext/openssl/openssl_backend_v1.c b/ext/openssl/openssl_backend_v1.c index ea9bd2319155e..81c327dbfe34b 100644 --- a/ext/openssl/openssl_backend_v1.c +++ b/ext/openssl/openssl_backend_v1.c @@ -27,6 +27,22 @@ #include #endif +void php_openssl_backend_init(void) +{ +#ifdef LIBRESSL_VERSION_NUMBER + OPENSSL_config(NULL); + SSL_library_init(); + OpenSSL_add_all_ciphers(); + OpenSSL_add_all_digests(); + OpenSSL_add_all_algorithms(); + SSL_load_error_strings(); +#else + OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL); +#endif + + php_openssl_backend_init_common(); +} + void php_openssl_backend_shutdown(void) { #ifdef LIBRESSL_VERSION_NUMBER @@ -72,23 +88,23 @@ static bool php_openssl_pkey_init_rsa_data(RSA *rsa, zval *data) OPENSSL_PKEY_SET_BN(data, e); OPENSSL_PKEY_SET_BN(data, d); if (!n || !d || !RSA_set0_key(rsa, n, e, d)) { - return 0; + return false; } OPENSSL_PKEY_SET_BN(data, p); OPENSSL_PKEY_SET_BN(data, q); if ((p || q) && !RSA_set0_factors(rsa, p, q)) { - return 0; + return false; } OPENSSL_PKEY_SET_BN(data, dmp1); OPENSSL_PKEY_SET_BN(data, dmq1); OPENSSL_PKEY_SET_BN(data, iqmp); if ((dmp1 || dmq1 || iqmp) && !RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp)) { - return 0; + return false; } - return 1; + return true; } EVP_PKEY *php_openssl_pkey_init_rsa(zval *data) @@ -125,7 +141,7 @@ static bool php_openssl_pkey_init_dsa_data(DSA *dsa, zval *data, bool *is_privat OPENSSL_PKEY_SET_BN(data, q); OPENSSL_PKEY_SET_BN(data, g); if (!p || !q || !g || !DSA_set0_pqg(dsa, p, q, g)) { - return 0; + return false; } OPENSSL_PKEY_SET_BN(data, pub_key); @@ -138,18 +154,18 @@ static bool php_openssl_pkey_init_dsa_data(DSA *dsa, zval *data, bool *is_privat /* generate key */ if (!DSA_generate_key(dsa)) { php_openssl_store_errors(); - return 0; + return false; } /* if BN_mod_exp return -1, then DSA_generate_key succeed for failed key * so we need to double check that public key is created */ DSA_get0_key(dsa, &pub_key_const, &priv_key_const); if (!pub_key_const || BN_is_zero(pub_key_const)) { - return 0; + return false; } /* all good */ *is_private = true; - return 1; + return true; } EVP_PKEY *php_openssl_pkey_init_dsa(zval *data, bool *is_private) @@ -186,7 +202,7 @@ static bool php_openssl_pkey_init_dh_data(DH *dh, zval *data, bool *is_private) OPENSSL_PKEY_SET_BN(data, q); OPENSSL_PKEY_SET_BN(data, g); if (!p || !g || !DH_set0_pqg(dh, p, q, g)) { - return 0; + return false; } OPENSSL_PKEY_SET_BN(data, priv_key); @@ -198,7 +214,7 @@ static bool php_openssl_pkey_init_dh_data(DH *dh, zval *data, bool *is_private) if (priv_key) { pub_key = php_openssl_dh_pub_from_priv(priv_key, g, p); if (pub_key == NULL) { - return 0; + return false; } return DH_set0_key(dh, pub_key, priv_key); } @@ -206,11 +222,11 @@ static bool php_openssl_pkey_init_dh_data(DH *dh, zval *data, bool *is_private) /* generate key */ if (!DH_generate_key(dh)) { php_openssl_store_errors(); - return 0; + return false; } /* all good */ *is_private = true; - return 1; + return true; } EVP_PKEY *php_openssl_pkey_init_dh(zval *data, bool *is_private) @@ -692,4 +708,54 @@ 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); +} + +STACK_OF(X509_INFO) *php_openssl_pem_read_bio_x509_info(BIO *in) +{ + return PEM_X509_INFO_read_bio(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 1b00581e7df59..cd190546d5002 100644 --- a/ext/openssl/openssl_backend_v3.c +++ b/ext/openssl/openssl_backend_v3.c @@ -24,6 +24,18 @@ ZEND_EXTERN_MODULE_GLOBALS(openssl) +void php_openssl_backend_init(void) +{ +#if PHP_OPENSSL_API_VERSION >= 0x30000 && defined(LOAD_OPENSSL_LEGACY_PROVIDER) + OSSL_PROVIDER_load(NULL, "legacy"); + OSSL_PROVIDER_load(NULL, "default"); +#endif + + OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL); + + php_openssl_backend_init_common(); +} + void php_openssl_backend_shutdown(void) { (void) 0; @@ -713,6 +725,12 @@ 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) { + 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); } @@ -769,6 +787,12 @@ static const char *php_openssl_cipher_names[] = { const EVP_CIPHER *php_openssl_get_evp_cipher_by_name(const char *name) { + 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); } @@ -831,4 +855,131 @@ 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; +} + +STACK_OF(X509_INFO) *php_openssl_pem_read_bio_x509_info(BIO *in) +{ + return PEM_X509_INFO_read_bio_ex(in, NULL, NULL, NULL, PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ); +} + +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_backend.h b/ext/openssl/php_openssl_backend.h index 86111e2997d1a..00da5e74fc1b8 100644 --- a/ext/openssl/php_openssl_backend.h +++ b/ext/openssl/php_openssl_backend.h @@ -190,7 +190,18 @@ 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); +STACK_OF(X509_INFO) *php_openssl_pem_read_bio_x509_info(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) 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/gh19994.phpt b/ext/openssl/tests/gh19994.phpt new file mode 100644 index 0000000000000..3aa32cfb4d2b0 --- /dev/null +++ b/ext/openssl/tests/gh19994.phpt @@ -0,0 +1,17 @@ +--TEST-- +GH-19994: openssl_get_cipher_methods inconsistent with fetched methods +--EXTENSIONS-- +openssl +--FILE-- + +--EXPECT-- 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_decrypt_basic.phpt b/ext/openssl/tests/openssl_decrypt_basic.phpt index 6cb2297a979b1..0f674dbc1e348 100644 --- a/ext/openssl/tests/openssl_decrypt_basic.phpt +++ b/ext/openssl/tests/openssl_decrypt_basic.phpt @@ -10,8 +10,7 @@ $password = "openssl"; $ivlen = openssl_cipher_iv_length($method); $iv = ''; -srand(time() + ((int)(microtime(true) * 1000000) % 1000000)); -while(strlen($iv) < $ivlen) $iv .= chr(rand(0,255)); +while(strlen($iv) < $ivlen) $iv .= random_bytes(1); $encrypted = openssl_encrypt($data, $method, $password, 0, $iv); $output = openssl_decrypt($encrypted, $method, $password, 0, $iv); 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 d53e55aa15547..62929246a07f0 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,19 +239,19 @@ 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: /* SSL terminated (but socket may still be active) */ - retry = 0; + retry = false; break; case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: /* 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) { @@ -259,7 +261,7 @@ static int php_openssl_handle_ssl_error(php_stream *stream, int nr_bytes, bool i } SSL_set_shutdown(sslsock->ssl_handle, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); stream->eof = 1; - retry = 0; + retry = false; } else { char *estr = php_socket_strerror(php_socket_errno(), NULL, 0); @@ -267,7 +269,7 @@ static int php_openssl_handle_ssl_error(php_stream *stream, int nr_bytes, bool i "SSL: %s", estr); efree(estr); - retry = 0; + retry = false; } break; } @@ -283,7 +285,7 @@ static int php_openssl_handle_ssl_error(php_stream *stream, int nr_bytes, bool i "SSL_R_NO_SHARED_CIPHER: no suitable shared cipher could be used. " "This could be because the server is missing an SSL certificate " "(local_cert context option)"); - retry = 0; + retry = false; break; default: @@ -308,7 +310,7 @@ static int php_openssl_handle_ssl_error(php_stream *stream, int nr_bytes, bool i } } - retry = 0; + retry = false; errno = 0; } return retry; @@ -358,7 +360,7 @@ static int php_openssl_x509_fingerprint_cmp(X509 *peer, const char *method, cons zend_string *fingerprint; int result = -1; - fingerprint = php_openssl_x509_fingerprint(peer, method, 0); + fingerprint = php_openssl_x509_fingerprint(peer, method, false); if (fingerprint) { result = strcasecmp(expected, ZSTR_VAL(fingerprint)); zend_string_release_ex(fingerprint, 0); @@ -389,26 +391,26 @@ static bool php_openssl_x509_fingerprint_match(X509 *peer, zval *val) if (!zend_hash_num_elements(Z_ARRVAL_P(val))) { php_error_docref(NULL, E_WARNING, "Invalid peer_fingerprint array; [algo => fingerprint] form required"); - return 0; + return false; } ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(val), key, current) { if (key == NULL || Z_TYPE_P(current) != IS_STRING) { php_error_docref(NULL, E_WARNING, "Invalid peer_fingerprint array; [algo => fingerprint] form required"); - return 0; + return false; } if (php_openssl_x509_fingerprint_cmp(peer, ZSTR_VAL(key), Z_STRVAL_P(current)) != 0) { - return 0; + return false; } } ZEND_HASH_FOREACH_END(); - return 1; + return true; } else { php_error_docref(NULL, E_WARNING, "Invalid peer_fingerprint value; fingerprint string or array of the form [algo => fingerprint] required"); } - return 0; + return false; } static bool php_openssl_matches_wildcard_name(const char *subjectname, const char *certname) /* {{{ */ @@ -418,18 +420,18 @@ static bool php_openssl_matches_wildcard_name(const char *subjectname, const cha size_t suffix_len, subject_len; if (strcasecmp(subjectname, certname) == 0) { - return 1; + return true; } /* wildcard, if present, must only be present in the left-most component */ if (!(wildcard = strchr(certname, '*')) || memchr(certname, '.', wildcard - certname)) { - return 0; + return false; } /* 1) prefix, if not empty, must match subject */ prefix_len = wildcard - certname; if (prefix_len && strncasecmp(subjectname, certname, prefix_len) != 0) { - return 0; + return false; } suffix_len = strlen(wildcard + 1); @@ -442,7 +444,7 @@ static bool php_openssl_matches_wildcard_name(const char *subjectname, const cha memchr(subjectname + prefix_len, '.', subject_len - suffix_len - prefix_len) == NULL; } - return 0; + return false; } /* }}} */ @@ -489,7 +491,7 @@ static bool php_openssl_matches_san_list(X509 *peer, const char *subject_name) / OPENSSL_free(cert_name); sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); - return 1; + return true; } OPENSSL_free(cert_name); } else if (san->type == GEN_IPADD) { @@ -503,7 +505,7 @@ static bool php_openssl_matches_san_list(X509 *peer, const char *subject_name) / if (strcasecmp(subject_name, (const char*)ipbuffer) == 0) { sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); - return 1; + return true; } } #ifdef HAVE_IPV6_SAN @@ -513,7 +515,7 @@ static bool php_openssl_matches_san_list(X509 *peer, const char *subject_name) / if (strcasecmp((const char*)subject_name_ipv6_expanded, (const char*)ipbuffer) == 0) { sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); - return 1; + return true; } } #endif @@ -522,7 +524,7 @@ static bool php_openssl_matches_san_list(X509 *peer, const char *subject_name) / sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); - return 0; + return false; } /* }}} */ @@ -530,7 +532,7 @@ static bool php_openssl_matches_common_name(X509 *peer, const char *subject_name { char buf[1024]; X509_NAME *cert_name; - bool is_match = 0; + bool is_match = false; int cert_name_len; cert_name = X509_get_subject_name(peer); @@ -541,7 +543,7 @@ static bool php_openssl_matches_common_name(X509 *peer, const char *subject_name } else if ((size_t)cert_name_len != strlen(buf)) { php_error_docref(NULL, E_WARNING, "Peer certificate CN=`%.*s' is malformed", cert_name_len, buf); } else if (php_openssl_matches_wildcard_name(subject_name, buf)) { - is_match = 1; + is_match = true; } else { php_error_docref(NULL, E_WARNING, "Peer certificate CN=`%.*s' did not match expected CN=`%s'", @@ -677,7 +679,7 @@ static int php_openssl_win_cert_verify_callback(X509_STORE_CTX *x509_store_ctx, php_stream *stream; php_openssl_netstream_data_t *sslsock; zval *val; - bool is_self_signed = 0; + bool is_self_signed = false; stream = (php_stream*)arg; @@ -738,7 +740,7 @@ static int php_openssl_win_cert_verify_callback(X509_STORE_CTX *x509_store_ctx, /* check if the cert is self-signed */ if (cert_chain_ctx->cChain > 0 && cert_chain_ctx->rgpChain[0]->cElement > 0 && (cert_chain_ctx->rgpChain[0]->rgpElement[0]->TrustStatus.dwInfoStatus & CERT_TRUST_IS_SELF_SIGNED) != 0) { - is_self_signed = 1; + is_self_signed = true; } /* check the depth */ @@ -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)) { @@ -1699,7 +1701,7 @@ static zend_result php_openssl_setup_crypto(php_stream *stream, } if (!SSL_set_fd(sslsock->ssl_handle, sslsock->s.socket)) { - php_openssl_handle_ssl_error(stream, 0, 1); + php_openssl_handle_ssl_error(stream, 0, true); } #ifdef HAVE_TLS_SNI @@ -1806,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) { @@ -1946,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 */ @@ -1965,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); } @@ -1987,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; } } @@ -2018,7 +2020,7 @@ static ssize_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, si /* Get the error code from SSL, and check to see if it's an error or not. */ int err = SSL_get_error(sslsock->ssl_handle, nr_bytes ); - retry = php_openssl_handle_ssl_error(stream, nr_bytes, 0); + retry = php_openssl_handle_ssl_error(stream, nr_bytes, false); /* If we get this (the above doesn't check) then we'll retry as well. */ if (errno == EAGAIN && err == SSL_ERROR_WANT_READ && read) { @@ -2217,8 +2219,7 @@ static int php_openssl_sockop_stat(php_stream *stream, php_stream_statbuf *ssb) static inline int php_openssl_tcp_sockop_accept(php_stream *stream, php_openssl_netstream_data_t *sock, php_stream_xport_param *xparam STREAMS_DC) /* {{{ */ { - int clisock; - bool nodelay = 0; + bool nodelay = false; zval *tmpzval = NULL; xparam->outputs.client = NULL; @@ -2226,10 +2227,10 @@ static inline int php_openssl_tcp_sockop_accept(php_stream *stream, php_openssl_ if (PHP_STREAM_CONTEXT(stream) && (tmpzval = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "tcp_nodelay")) != NULL && zend_is_true(tmpzval)) { - nodelay = 1; + nodelay = true; } - clisock = php_network_accept_incoming(sock->s.socket, + php_socket_t clisock = php_network_accept_incoming(sock->s.socket, xparam->want_textaddr ? &xparam->outputs.textaddr : NULL, xparam->want_addr ? &xparam->outputs.addr : NULL, xparam->want_addr ? &xparam->outputs.addrlen : NULL, @@ -2238,7 +2239,7 @@ static inline int php_openssl_tcp_sockop_accept(php_stream *stream, php_openssl_ &xparam->outputs.error_code, nodelay); - if (clisock >= 0) { + if (clisock != SOCK_ERR) { php_openssl_netstream_data_t *clisockdata = (php_openssl_netstream_data_t*) emalloc(sizeof(*clisockdata)); /* copy underlying tcp fields */ @@ -2248,7 +2249,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+"); @@ -2273,6 +2274,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); + } } } } @@ -2379,8 +2386,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) { @@ -2392,7 +2399,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); } @@ -2414,7 +2421,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; } } @@ -2438,7 +2445,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; } @@ -2620,23 +2627,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; + } + + php_uri_internal *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] == '.') { @@ -2646,13 +2659,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; } /* }}} */ @@ -2668,7 +2680,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); @@ -2750,7 +2762,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/pcntl.c b/ext/pcntl/pcntl.c index e11de304b1b79..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 @@ -297,7 +298,7 @@ PHP_FUNCTION(pcntl_fork) } } else if (id == 0) { - zend_max_execution_timer_init(); + php_child_init(); } RETURN_LONG((zend_long) id); @@ -1560,7 +1561,7 @@ PHP_FUNCTION(pcntl_rfork) php_error_docref(NULL, E_WARNING, "Error %d", errno); } } else if (pid == 0) { - zend_max_execution_timer_init(); + php_child_init(); } RETURN_LONG((zend_long) pid); @@ -1605,7 +1606,7 @@ PHP_FUNCTION(pcntl_forkx) php_error_docref(NULL, E_WARNING, "Error %d", errno); } } else if (pid == 0) { - zend_max_execution_timer_init(); + php_child_init(); } RETURN_LONG((zend_long) pid); diff --git a/ext/pcre/config.w32 b/ext/pcre/config.w32 index d3c15160d0b0a..7c09456b89616 100644 --- a/ext/pcre/config.w32 +++ b/ext/pcre/config.w32 @@ -2,7 +2,7 @@ EXTENSION("pcre", "php_pcre.c", false /* never shared */, "-Iext/pcre/pcre2lib -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); -ADD_SOURCES("ext/pcre/pcre2lib", "pcre2_auto_possess.c pcre2_chartables.c pcre2_compile.c pcre2_compile_class.c pcre2_config.c pcre2_context.c pcre2_chkdint.c pcre2_dfa_match.c pcre2_error.c pcre2_jit_compile.c pcre2_maketables.c pcre2_match.c pcre2_match_data.c pcre2_newline.c pcre2_ord2utf.c pcre2_pattern_info.c pcre2_serialize.c pcre2_string_utils.c pcre2_study.c pcre2_substitute.c pcre2_substring.c pcre2_tables.c pcre2_ucd.c pcre2_valid_utf.c pcre2_xclass.c pcre2_find_bracket.c pcre2_convert.c pcre2_extuni.c pcre2_script_run.c", "pcre"); +ADD_SOURCES("ext/pcre/pcre2lib", "pcre2_auto_possess.c pcre2_chartables.c pcre2_compile.c pcre2_config.c pcre2_context.c pcre2_chkdint.c pcre2_dfa_match.c pcre2_error.c pcre2_jit_compile.c pcre2_maketables.c pcre2_match.c pcre2_match_data.c pcre2_newline.c pcre2_ord2utf.c pcre2_pattern_info.c pcre2_serialize.c pcre2_string_utils.c pcre2_study.c pcre2_substitute.c pcre2_substring.c pcre2_tables.c pcre2_ucd.c pcre2_valid_utf.c pcre2_xclass.c pcre2_find_bracket.c pcre2_convert.c pcre2_extuni.c pcre2_script_run.c", "pcre"); ADD_DEF_FILE("ext\\pcre\\php_pcre.def"); AC_DEFINE('HAVE_BUNDLED_PCRE', 1, 'Define to 1 if PHP uses the bundled PCRE library.'); diff --git a/ext/pcre/config0.m4 b/ext/pcre/config0.m4 index d049cc538c0f5..e71d9a7955743 100644 --- a/ext/pcre/config0.m4 +++ b/ext/pcre/config0.m4 @@ -68,7 +68,6 @@ else pcre2lib/pcre2_chartables.c pcre2lib/pcre2_chkdint.c pcre2lib/pcre2_compile.c - pcre2lib/pcre2_compile_class.c pcre2lib/pcre2_config.c pcre2lib/pcre2_context.c pcre2lib/pcre2_convert.c @@ -96,8 +95,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/config.h b/ext/pcre/pcre2lib/config.h index 368c6f9865951..859d76f24419d 100644 --- a/ext/pcre/pcre2lib/config.h +++ b/ext/pcre/pcre2lib/config.h @@ -104,32 +104,6 @@ #define MAX_VARLOOKBEHIND 255 #endif -/* The value of NEWLINE_DEFAULT determines the default newline character - sequence. PCRE2 client programs can override this by selecting other values - at run time. The valid values are 1 (CR), 2 (LF), 3 (CRLF), 4 (ANY), 5 - (ANYCRLF), and 6 (NUL). */ -#ifndef NEWLINE_DEFAULT -#define NEWLINE_DEFAULT 2 -#endif - -/* The value of PCRE2GREP_BUFSIZE is the starting size of the buffer used by - pcre2grep to hold parts of the file it is searching. The buffer will be - expanded up to PCRE2GREP_MAX_BUFSIZE if necessary, for files containing - very long lines. The actual amount of memory used by pcre2grep is three - times this number, because it allows for the buffering of "before" and - "after" lines. */ -#ifndef PCRE2GREP_BUFSIZE -#define PCRE2GREP_BUFSIZE 20480 -#endif - -/* The value of PCRE2GREP_MAX_BUFSIZE specifies the maximum size of the buffer - used by pcre2grep to hold parts of the file it is searching. The actual - amount of memory used by pcre2grep is three times this number, because it - allows for the buffering of "before" and "after" lines. */ -#ifndef PCRE2GREP_MAX_BUFSIZE -#define PCRE2GREP_MAX_BUFSIZE 1048576 -#endif - /* to make a symbol visible */ #ifndef PCRE2_EXPORT #define PCRE2_EXPORT diff --git a/ext/pcre/pcre2lib/pcre2.h b/ext/pcre/pcre2lib/pcre2.h index 6d1a8758ba966..a322d9f2d56f9 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 44 #define PCRE2_PRERELEASE -#define PCRE2_DATE 2025-02-05 +#define PCRE2_DATE 2024-06-07 /* 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 @@ -143,7 +143,6 @@ D is inspected during pcre2_dfa_match() execution #define PCRE2_EXTENDED_MORE 0x01000000u /* C */ #define PCRE2_LITERAL 0x02000000u /* C */ #define PCRE2_MATCH_INVALID_UTF 0x04000000u /* J M D */ -#define PCRE2_ALT_EXTENDED_CLASS 0x08000000u /* C */ /* An additional compile options word is available in the compile context. */ @@ -160,10 +159,6 @@ D is inspected during pcre2_dfa_match() execution #define PCRE2_EXTRA_ASCII_BSW 0x00000400u /* C */ #define PCRE2_EXTRA_ASCII_POSIX 0x00000800u /* C */ #define PCRE2_EXTRA_ASCII_DIGIT 0x00001000u /* C */ -#define PCRE2_EXTRA_PYTHON_OCTAL 0x00002000u /* C */ -#define PCRE2_EXTRA_NO_BS0 0x00004000u /* C */ -#define PCRE2_EXTRA_NEVER_CALLOUT 0x00008000u /* C */ -#define PCRE2_EXTRA_TURKISH_CASING 0x00010000u /* C */ /* These are for pcre2_jit_compile(). */ @@ -171,7 +166,6 @@ D is inspected during pcre2_dfa_match() execution #define PCRE2_JIT_PARTIAL_SOFT 0x00000002u #define PCRE2_JIT_PARTIAL_HARD 0x00000004u #define PCRE2_JIT_INVALID_UTF 0x00000100u -#define PCRE2_JIT_TEST_ALLOC 0x00000200u /* These are for pcre2_match(), pcre2_dfa_match(), pcre2_jit_match(), and pcre2_substitute(). Some are allowed only for one of the functions, and in @@ -326,23 +320,7 @@ pcre2_pattern_convert(). */ #define PCRE2_ERROR_TOO_MANY_CAPTURES 197 #define PCRE2_ERROR_CONDITION_ATOMIC_ASSERTION_EXPECTED 198 #define PCRE2_ERROR_BACKSLASH_K_IN_LOOKAROUND 199 -#define PCRE2_ERROR_MAX_VAR_LOOKBEHIND_EXCEEDED 200 -#define PCRE2_ERROR_PATTERN_COMPILED_SIZE_TOO_BIG 201 -#define PCRE2_ERROR_OVERSIZE_PYTHON_OCTAL 202 -#define PCRE2_ERROR_CALLOUT_CALLER_DISABLED 203 -#define PCRE2_ERROR_EXTRA_CASING_REQUIRES_UNICODE 204 -#define PCRE2_ERROR_TURKISH_CASING_REQUIRES_UTF 205 -#define PCRE2_ERROR_EXTRA_CASING_INCOMPATIBLE 206 -#define PCRE2_ERROR_ECLASS_NEST_TOO_DEEP 207 -#define PCRE2_ERROR_ECLASS_INVALID_OPERATOR 208 -#define PCRE2_ERROR_ECLASS_UNEXPECTED_OPERATOR 209 -#define PCRE2_ERROR_ECLASS_EXPECTED_OPERAND 210 -#define PCRE2_ERROR_ECLASS_MIXED_OPERATORS 211 -#define PCRE2_ERROR_ECLASS_HINT_SQUARE_BRACKET 212 -#define PCRE2_ERROR_PERL_ECLASS_UNEXPECTED_EXPR 213 -#define PCRE2_ERROR_PERL_ECLASS_EMPTY_EXPR 214 -#define PCRE2_ERROR_PERL_ECLASS_MISSING_CLOSE 215 -#define PCRE2_ERROR_PERL_ECLASS_UNEXPECTED_CHAR 216 + /* "Expected" matching error codes: no match and partial match. */ @@ -429,9 +407,6 @@ released, the numbers must not be changed. */ #define PCRE2_ERROR_INTERNAL_DUPMATCH (-65) #define PCRE2_ERROR_DFA_UINVALID_UTF (-66) #define PCRE2_ERROR_INVALIDOFFSET (-67) -#define PCRE2_ERROR_JIT_UNSUPPORTED (-68) -#define PCRE2_ERROR_REPLACECASE (-69) -#define PCRE2_ERROR_TOOLARGEREPLACE (-70) /* Request types for pcre2_pattern_info() */ @@ -485,30 +460,6 @@ released, the numbers must not be changed. */ #define PCRE2_CONFIG_COMPILED_WIDTHS 14 #define PCRE2_CONFIG_TABLES_LENGTH 15 -/* Optimization directives for pcre2_set_optimize(). -For binary compatibility, only add to this list; do not renumber. */ - -#define PCRE2_OPTIMIZATION_NONE 0 -#define PCRE2_OPTIMIZATION_FULL 1 - -#define PCRE2_AUTO_POSSESS 64 -#define PCRE2_AUTO_POSSESS_OFF 65 -#define PCRE2_DOTSTAR_ANCHOR 66 -#define PCRE2_DOTSTAR_ANCHOR_OFF 67 -#define PCRE2_START_OPTIMIZE 68 -#define PCRE2_START_OPTIMIZE_OFF 69 - -/* Types used in pcre2_set_substitute_case_callout(). - -PCRE2_SUBSTITUTE_CASE_LOWER and PCRE2_SUBSTITUTE_CASE_UPPER are passed to the -callout to indicate that the case of the entire callout input should be -case-transformed. PCRE2_SUBSTITUTE_CASE_TITLE_FIRST is passed to indicate that -only the first character or glyph should be transformed to Unicode titlecase, -and the rest to lowercase. */ - -#define PCRE2_SUBSTITUTE_CASE_LOWER 1 -#define PCRE2_SUBSTITUTE_CASE_UPPER 2 -#define PCRE2_SUBSTITUTE_CASE_TITLE_FIRST 3 /* Types for code units in patterns and subject strings. */ @@ -662,9 +613,7 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_set_parens_nest_limit(pcre2_compile_context *, uint32_t); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_set_compile_recursion_guard(pcre2_compile_context *, \ - int (*)(uint32_t, void *), void *); \ -PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ - pcre2_set_optimize(pcre2_compile_context *, uint32_t); + int (*)(uint32_t, void *), void *); #define PCRE2_MATCH_CONTEXT_FUNCTIONS \ PCRE2_EXP_DECL pcre2_match_context *PCRE2_CALL_CONVENTION \ @@ -679,11 +628,6 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_set_substitute_callout(pcre2_match_context *, \ int (*)(pcre2_substitute_callout_block *, void *), void *); \ -PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ - pcre2_set_substitute_case_callout(pcre2_match_context *, \ - PCRE2_SIZE (*)(PCRE2_SPTR, PCRE2_SIZE, PCRE2_UCHAR *, PCRE2_SIZE, int, \ - void *), \ - void *); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_set_depth_limit(pcre2_match_context *, uint32_t); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ @@ -796,7 +740,6 @@ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_substring_list_get(pcre2_match_data *, PCRE2_UCHAR ***, PCRE2_SIZE **); - /* Functions for serializing / deserializing compiled patterns. */ #define PCRE2_SERIALIZE_FUNCTIONS \ @@ -964,9 +907,7 @@ pcre2_compile are called by application code. */ #define pcre2_set_newline PCRE2_SUFFIX(pcre2_set_newline_) #define pcre2_set_parens_nest_limit PCRE2_SUFFIX(pcre2_set_parens_nest_limit_) #define pcre2_set_offset_limit PCRE2_SUFFIX(pcre2_set_offset_limit_) -#define pcre2_set_optimize PCRE2_SUFFIX(pcre2_set_optimize_) #define pcre2_set_substitute_callout PCRE2_SUFFIX(pcre2_set_substitute_callout_) -#define pcre2_set_substitute_case_callout PCRE2_SUFFIX(pcre2_set_substitute_case_callout_) #define pcre2_substitute PCRE2_SUFFIX(pcre2_substitute_) #define pcre2_substring_copy_byname PCRE2_SUFFIX(pcre2_substring_copy_byname_) #define pcre2_substring_copy_bynumber PCRE2_SUFFIX(pcre2_substring_copy_bynumber_) diff --git a/ext/pcre/pcre2lib/pcre2_auto_possess.c b/ext/pcre/pcre2lib/pcre2_auto_possess.c index 6d7f27b6904ca..210d13d37aa88 100644 --- a/ext/pcre/pcre2lib/pcre2_auto_possess.c +++ b/ext/pcre/pcre2lib/pcre2_auto_possess.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2024 University of Cambridge + New API code Copyright (c) 2016-2022 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -49,10 +49,6 @@ repeats into possessive repeats where possible. */ #include "pcre2_internal.h" -/* This macro represents the max size of list[] and that is used to keep -track of UCD info in several places, it should be kept on sync with the -value used by GenerateUcd.py */ -#define MAX_LIST 8 /************************************************* * Tables for auto-possessification * @@ -68,7 +64,7 @@ The Unicode property types (\P and \p) have to be present to fill out the table because of what their opcode values are, but the table values should always be zero because property types are handled separately in the code. The last four columns apply to items that cannot be repeated, so there is no need to have -rows for them. Note that OP_DIGIT etc. are generated only when PCRE2_UCP is +rows for them. Note that OP_DIGIT etc. are generated only when PCRE_UCP is *not* set. When it is set, \d etc. are converted into OP_(NOT_)PROP codes. */ #define APTROWS (LAST_AUTOTAB_LEFT_OP - FIRST_AUTOTAB_OP + 1) @@ -127,21 +123,21 @@ opcode is used to select the column. The values are as follows: */ static const uint8_t propposstab[PT_TABSIZE][PT_TABSIZE] = { -/* LAMP GC PC SC SCX ALNUM SPACE PXSPACE WORD CLIST UCNC BIDICL BOOL */ - { 3, 0, 0, 0, 0, 3, 1, 1, 0, 0, 0, 0, 0 }, /* PT_LAMP */ - { 0, 2, 4, 0, 0, 9, 10, 10, 11, 0, 0, 0, 0 }, /* PT_GC */ - { 0, 5, 2, 0, 0, 15, 16, 16, 17, 0, 0, 0, 0 }, /* PT_PC */ - { 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_SC */ - { 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_SCX */ - { 3, 6, 12, 0, 0, 3, 1, 1, 0, 0, 0, 0, 0 }, /* PT_ALNUM */ - { 1, 7, 13, 0, 0, 1, 3, 3, 1, 0, 0, 0, 0 }, /* PT_SPACE */ - { 1, 7, 13, 0, 0, 1, 3, 3, 1, 0, 0, 0, 0 }, /* PT_PXSPACE */ - { 0, 8, 14, 0, 0, 0, 1, 1, 3, 0, 0, 0, 0 }, /* PT_WORD */ - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_CLIST */ - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 }, /* PT_UCNC */ - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_BIDICL */ - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } /* PT_BOOL */ - /* PT_ANY does not need a record. */ +/* ANY LAMP GC PC SC SCX ALNUM SPACE PXSPACE WORD CLIST UCNC BIDICL BOOL */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_ANY */ + { 0, 3, 0, 0, 0, 0, 3, 1, 1, 0, 0, 0, 0, 0 }, /* PT_LAMP */ + { 0, 0, 2, 4, 0, 0, 9, 10, 10, 11, 0, 0, 0, 0 }, /* PT_GC */ + { 0, 0, 5, 2, 0, 0, 15, 16, 16, 17, 0, 0, 0, 0 }, /* PT_PC */ + { 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_SC */ + { 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_SCX */ + { 0, 3, 6, 12, 0, 0, 3, 1, 1, 0, 0, 0, 0, 0 }, /* PT_ALNUM */ + { 0, 1, 7, 13, 0, 0, 1, 3, 3, 1, 0, 0, 0, 0 }, /* PT_SPACE */ + { 0, 1, 7, 13, 0, 0, 1, 3, 3, 1, 0, 0, 0, 0 }, /* PT_PXSPACE */ + { 0, 0, 8, 14, 0, 0, 0, 1, 1, 3, 0, 0, 0, 0 }, /* PT_WORD */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_CLIST */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 }, /* PT_UCNC */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_BIDICL */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } /* PT_BOOL */ }; /* This table is used to check whether auto-possessification is possible @@ -203,7 +199,7 @@ static BOOL check_char_prop(uint32_t c, unsigned int ptype, unsigned int pdata, BOOL negated) { -BOOL ok, rc; +BOOL ok; const uint32_t *p; const ucd_record *prop = GET_UCD(c); @@ -244,13 +240,12 @@ switch(ptype) { HSPACE_CASES: VSPACE_CASES: - rc = negated; - break; + return negated; default: - rc = (PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == negated; + return (PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == negated; } - return rc; + break; /* Control never reaches here */ case PT_WORD: return (PRIV(ucp_gentype)[prop->chartype] == ucp_L || @@ -264,8 +259,7 @@ switch(ptype) if (c < *p) return !negated; if (c == *p++) return negated; } - PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */ - break; + break; /* Control never reaches here */ /* Haven't yet thought these through. */ @@ -334,7 +328,6 @@ get_chr_property_list(PCRE2_SPTR code, BOOL utf, BOOL ucp, const uint8_t *fcc, PCRE2_UCHAR c = *code; PCRE2_UCHAR base; PCRE2_SPTR end; -PCRE2_SPTR class_end; uint32_t chr; #ifdef SUPPORT_UNICODE @@ -457,12 +450,10 @@ switch(c) code += 2; do { - if (clist_dest >= list + MAX_LIST) + if (clist_dest >= list + 8) { - /* Early return if there is not enough space. GenerateUcd.py - generated a list with more than 5 characters and something - must be done about that going forward. */ - PCRE2_DEBUG_UNREACHABLE(); /* Remove if it ever triggers */ + /* Early return if there is not enough space. This should never + happen, since all clists are shorter than 5 character now. */ list[2] = code[0]; list[3] = code[1]; return code; @@ -482,13 +473,11 @@ switch(c) case OP_CLASS: #ifdef SUPPORT_WIDE_CHARS case OP_XCLASS: - case OP_ECLASS: - if (c == OP_XCLASS || c == OP_ECLASS) + if (c == OP_XCLASS) end = code + GET(code, 0) - 1; else #endif end = code + 32 / sizeof(PCRE2_UCHAR); - class_end = end; switch(*end) { @@ -516,7 +505,6 @@ switch(c) break; } list[2] = (uint32_t)(end - code); - list[3] = (uint32_t)(end - class_end); return end; } @@ -549,7 +537,7 @@ compare_opcodes(PCRE2_SPTR code, BOOL utf, BOOL ucp, const compile_block *cb, const uint32_t *base_list, PCRE2_SPTR base_end, int *rec_limit) { PCRE2_UCHAR c; -uint32_t list[MAX_LIST]; +uint32_t list[8]; const uint32_t *chr_ptr; const uint32_t *ochr_ptr; const uint32_t *list_ptr; @@ -593,7 +581,7 @@ for(;;) continue; } - /* At the end of a branch, skip to the end of the group and process it. */ + /* At the end of a branch, skip to the end of the group. */ if (c == OP_ALT) { @@ -650,29 +638,19 @@ for(;;) return FALSE; break; - /* Atomic sub-patterns and forward assertions can always auto-possessify - their last iterator. However, if the group was entered as a result of - checking a previous iterator, this is not possible. */ + /* Atomic sub-patterns and assertions can always auto-possessify their + last iterator except for variable length lookbehinds. However, if the + group was entered as a result of checking a previous iterator, this is + not possible. */ case OP_ASSERT: case OP_ASSERT_NOT: case OP_ONCE: return !entered_a_group; - /* Fixed-length lookbehinds can be treated the same way, but variable - length lookbehinds must not auto-possessify their last iterator. Note - that in order to identify a variable length lookbehind we must check - through all branches, because some may be of fixed length. */ - case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: - do - { - if (bracode[1+LINK_SIZE] == OP_VREVERSE) return FALSE; /* Variable */ - bracode += GET(bracode, 1); - } - while (*bracode == OP_ALT); - return !entered_a_group; /* Not variable length */ + return (bracode[1+LINK_SIZE] == OP_VREVERSE)? FALSE : !entered_a_group; /* Non-atomic assertions - don't possessify last iterator. This needs more thought. */ @@ -770,12 +748,12 @@ for(;;) if (base_list[0] == OP_CLASS) #endif { - set1 = (const uint8_t *)(base_end - base_list[2]); + set1 = (uint8_t *)(base_end - base_list[2]); list_ptr = list; } else { - set1 = (const uint8_t *)(code - list[2]); + set1 = (uint8_t *)(code - list[2]); list_ptr = base_list; } @@ -784,14 +762,13 @@ for(;;) { case OP_CLASS: case OP_NCLASS: - set2 = (const uint8_t *) + set2 = (uint8_t *) ((list_ptr == list ? code : base_end) - list_ptr[2]); break; #ifdef SUPPORT_WIDE_CHARS case OP_XCLASS: - xclass_flags = (list_ptr == list ? code : base_end) - - list_ptr[2] + LINK_SIZE; + xclass_flags = (list_ptr == list ? code : base_end) - list_ptr[2] + LINK_SIZE; if ((*xclass_flags & XCL_HASPROP) != 0) return FALSE; if ((*xclass_flags & XCL_MAP) == 0) { @@ -800,7 +777,7 @@ for(;;) /* Might be an empty repeat. */ continue; } - set2 = (const uint8_t *)(xclass_flags + 1); + set2 = (uint8_t *)(xclass_flags + 1); break; #endif @@ -808,21 +785,21 @@ for(;;) invert_bits = TRUE; /* Fall through */ case OP_DIGIT: - set2 = (const uint8_t *)(cb->cbits + cbit_digit); + set2 = (uint8_t *)(cb->cbits + cbit_digit); break; case OP_NOT_WHITESPACE: invert_bits = TRUE; /* Fall through */ case OP_WHITESPACE: - set2 = (const uint8_t *)(cb->cbits + cbit_space); + set2 = (uint8_t *)(cb->cbits + cbit_space); break; case OP_NOT_WORDCHAR: invert_bits = TRUE; /* Fall through */ case OP_WORDCHAR: - set2 = (const uint8_t *)(cb->cbits + cbit_word); + set2 = (uint8_t *)(cb->cbits + cbit_word); break; default: @@ -1107,7 +1084,7 @@ for(;;) case OP_CLASS: if (chr > 255) break; - class_bitset = (const uint8_t *) + class_bitset = (uint8_t *) ((list_ptr == list ? code : base_end) - list_ptr[2]); if ((class_bitset[chr >> 3] & (1u << (chr & 7))) != 0) return FALSE; break; @@ -1115,18 +1092,9 @@ for(;;) #ifdef SUPPORT_WIDE_CHARS case OP_XCLASS: if (PRIV(xclass)(chr, (list_ptr == list ? code : base_end) - - list_ptr[2] + LINK_SIZE, (const uint8_t*)cb->start_code, utf)) - return FALSE; - break; - - case OP_ECLASS: - if (PRIV(eclass)(chr, - (list_ptr == list ? code : base_end) - list_ptr[2] + LINK_SIZE, - (list_ptr == list ? code : base_end) - list_ptr[3], - (const uint8_t*)cb->start_code, utf)) - return FALSE; + list_ptr[2] + LINK_SIZE, utf)) return FALSE; break; -#endif /* SUPPORT_WIDE_CHARS */ +#endif default: return FALSE; @@ -1141,8 +1109,8 @@ for(;;) if (list[1] == 0) return TRUE; } -PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */ -return FALSE; /* Avoid compiler warnings */ +/* Control never reaches here. There used to be a fail-save return FALSE; here, +but some compilers complain about an unreachable statement. */ } @@ -1172,7 +1140,7 @@ PRIV(auto_possessify)(PCRE2_UCHAR *code, const compile_block *cb) PCRE2_UCHAR c; PCRE2_SPTR end; PCRE2_UCHAR *repeat_opcode; -uint32_t list[MAX_LIST]; +uint32_t list[8]; int rec_limit = 1000; /* Was 10,000 but clang+ASAN uses a lot of stack. */ BOOL utf = (cb->external_options & PCRE2_UTF) != 0; BOOL ucp = (cb->external_options & PCRE2_UCP) != 0; @@ -1181,11 +1149,7 @@ for (;;) { c = *code; - if (c >= OP_TABLE_LENGTH) - { - PCRE2_DEBUG_UNREACHABLE(); - return -1; /* Something gone wrong */ - } + if (c >= OP_TABLE_LENGTH) return -1; /* Something gone wrong */ if (c >= OP_STAR && c <= OP_TYPEPOSUPTO) { @@ -1234,14 +1198,10 @@ for (;;) } c = *code; } - else if (c == OP_CLASS || c == OP_NCLASS -#ifdef SUPPORT_WIDE_CHARS - || c == OP_XCLASS || c == OP_ECLASS -#endif - ) + else if (c == OP_CLASS || c == OP_NCLASS || c == OP_XCLASS) { #ifdef SUPPORT_WIDE_CHARS - if (c == OP_XCLASS || c == OP_ECLASS) + if (c == OP_XCLASS) repeat_opcode = code + GET(code, 1); else #endif @@ -1251,7 +1211,7 @@ for (;;) if (c >= OP_CRSTAR && c <= OP_CRMINRANGE) { /* The return from get_chr_property_list() will never be NULL when - *code (aka c) is one of the four class opcodes. However, gcc with + *code (aka c) is one of the three class opcodes. However, gcc with -fanalyzer notes that a NULL return is possible, and grumbles. Hence we put in a check. */ @@ -1319,7 +1279,6 @@ for (;;) #ifdef SUPPORT_WIDE_CHARS case OP_XCLASS: - case OP_ECLASS: code += GET(code, 1); break; #endif diff --git a/ext/pcre/pcre2lib/pcre2_chartables.c b/ext/pcre/pcre2lib/pcre2_chartables.c index 861914d1ac3ac..7362c3f2345ab 100644 --- a/ext/pcre/pcre2lib/pcre2_chartables.c +++ b/ext/pcre/pcre2lib/pcre2_chartables.c @@ -5,7 +5,8 @@ /* This file was automatically written by the pcre2_dftables auxiliary program. It contains character tables that are used when no external tables are passed to PCRE2 by the application that calls it. The tables -are used only for characters whose code values are less than 256. */ +are used only for characters whose code values are less than 256, and +only relevant if not in UCP mode. */ /* This set of tables was written in the C locale. */ @@ -18,13 +19,6 @@ PCRE2 is configured with --enable-rebuild-chartables. However, you can run pcre2_dftables manually with the -L option to build tables using the LC_ALL locale. */ -/* The following #include is present because without it gcc 4.x may remove -the array definition from the final binary if PCRE2 is built into a static -library and dead code stripping is activated. This leads to link errors. -Pulling in the header ensures that the array gets flagged as "someone -outside this compilation unit might reference this" and so it will always -be supplied to the linker. */ - #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -163,7 +157,7 @@ graph, print, punct, and cntrl. Other classes are built from combinations. */ 0x02 letter 0x04 lower case letter 0x08 decimal digit - 0x10 alphanumeric or '_' + 0x10 word (alphanumeric or '_') */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */ diff --git a/ext/pcre/pcre2lib/pcre2_chkdint.c b/ext/pcre/pcre2lib/pcre2_chkdint.c index 70830236999d8..d04f6f8cf1afa 100644 --- a/ext/pcre/pcre2lib/pcre2_chkdint.c +++ b/ext/pcre/pcre2lib/pcre2_chkdint.c @@ -74,7 +74,9 @@ if (__builtin_mul_overflow(a, b, &m)) return TRUE; #else INT64_OR_DOUBLE m; -PCRE2_ASSERT(a >= 0 && b >= 0); +#ifdef PCRE2_DEBUG +if (a < 0 || b < 0) abort(); +#endif m = (INT64_OR_DOUBLE)a * (INT64_OR_DOUBLE)b; @@ -91,4 +93,4 @@ if (m > PCRE2_SIZE_MAX) return TRUE; return FALSE; } -/* End of pcre2_chkdint.c */ +/* End of pcre_chkdint.c */ diff --git a/ext/pcre/pcre2lib/pcre2_compile.c b/ext/pcre/pcre2lib/pcre2_compile.c index 0ffac8939cb69..8e6787aba38ec 100644 --- a/ext/pcre/pcre2lib/pcre2_compile.c +++ b/ext/pcre/pcre2lib/pcre2_compile.c @@ -47,7 +47,7 @@ POSSIBILITY OF SUCH DAMAGE. #define PSSTART start_pattern /* Field containing processed string start */ #define PSEND end_pattern /* Field containing processed string end */ -#include "pcre2_compile.h" +#include "pcre2_internal.h" /* In rare error cases debugging might require calling pcre2_printint(). */ @@ -108,8 +108,20 @@ them will be able to (i.e. assume a 64-bit world). */ #define SIZEOFFSET 2 #endif +/* Macros for manipulating elements of the parsed pattern vector. */ + +#define META_CODE(x) (x & 0xffff0000u) +#define META_DATA(x) (x & 0x0000ffffu) +#define META_DIFF(x,y) ((x-y)>>16) + /* Function definitions to allow mutual recursion */ +#ifdef SUPPORT_UNICODE +static unsigned int + add_list_to_class_internal(uint8_t *, PCRE2_UCHAR **, uint32_t, uint32_t, + compile_block *, const uint32_t *, unsigned int); +#endif + static int compile_regex(uint32_t, uint32_t, PCRE2_UCHAR **, uint32_t **, int *, uint32_t, uint32_t *, uint32_t *, uint32_t *, uint32_t *, branch_chain *, @@ -187,6 +199,106 @@ don't have to check them every time. */ #define OFLOW_MAX (INT_MAX - 20) +/* Code values for parsed patterns, which are stored in a vector of 32-bit +unsigned ints. Values less than META_END are literal data values. The coding +for identifying the item is in the top 16-bits, leaving 16 bits for the +additional data that some of them need. The META_CODE, META_DATA, and META_DIFF +macros are used to manipulate parsed pattern elements. + +NOTE: When these definitions are changed, the table of extra lengths for each +code (meta_extra_lengths, just below) must be updated to remain in step. */ + +#define META_END 0x80000000u /* End of pattern */ + +#define META_ALT 0x80010000u /* alternation */ +#define META_ATOMIC 0x80020000u /* atomic group */ +#define META_BACKREF 0x80030000u /* Back ref */ +#define META_BACKREF_BYNAME 0x80040000u /* \k'name' */ +#define META_BIGVALUE 0x80050000u /* Next is a literal > META_END */ +#define META_CALLOUT_NUMBER 0x80060000u /* (?C with numerical argument */ +#define META_CALLOUT_STRING 0x80070000u /* (?C with string argument */ +#define META_CAPTURE 0x80080000u /* Capturing parenthesis */ +#define META_CIRCUMFLEX 0x80090000u /* ^ metacharacter */ +#define META_CLASS 0x800a0000u /* start non-empty class */ +#define META_CLASS_EMPTY 0x800b0000u /* empty class */ +#define META_CLASS_EMPTY_NOT 0x800c0000u /* negative empty class */ +#define META_CLASS_END 0x800d0000u /* end of non-empty class */ +#define META_CLASS_NOT 0x800e0000u /* start non-empty negative class */ +#define META_COND_ASSERT 0x800f0000u /* (?(?assertion)... */ +#define META_COND_DEFINE 0x80100000u /* (?(DEFINE)... */ +#define META_COND_NAME 0x80110000u /* (?()... */ +#define META_COND_NUMBER 0x80120000u /* (?(digits)... */ +#define META_COND_RNAME 0x80130000u /* (?(R&name)... */ +#define META_COND_RNUMBER 0x80140000u /* (?(Rdigits)... */ +#define META_COND_VERSION 0x80150000u /* (?(VERSIONx.y)... */ +#define META_DOLLAR 0x80160000u /* $ metacharacter */ +#define META_DOT 0x80170000u /* . metacharacter */ +#define META_ESCAPE 0x80180000u /* \d and friends */ +#define META_KET 0x80190000u /* closing parenthesis */ +#define META_NOCAPTURE 0x801a0000u /* no capture parens */ +#define META_OPTIONS 0x801b0000u /* (?i) and friends */ +#define META_POSIX 0x801c0000u /* POSIX class item */ +#define META_POSIX_NEG 0x801d0000u /* negative POSIX class item */ +#define META_RANGE_ESCAPED 0x801e0000u /* range with at least one escape */ +#define META_RANGE_LITERAL 0x801f0000u /* range defined literally */ +#define META_RECURSE 0x80200000u /* Recursion */ +#define META_RECURSE_BYNAME 0x80210000u /* (?&name) */ +#define META_SCRIPT_RUN 0x80220000u /* (*script_run:...) */ + +/* These must be kept together to make it easy to check that an assertion +is present where expected in a conditional group. */ + +#define META_LOOKAHEAD 0x80230000u /* (?= */ +#define META_LOOKAHEADNOT 0x80240000u /* (?! */ +#define META_LOOKBEHIND 0x80250000u /* (?<= */ +#define META_LOOKBEHINDNOT 0x80260000u /* (? */ CHAR_GREATER_THAN_SIGN, /* ? */ CHAR_QUESTION_MARK, - /* @ */ CHAR_COMMERCIAL_AT, /* A */ -ESC_A, - /* B */ -ESC_B, /* C */ -ESC_C, - /* D */ -ESC_D, /* E */ -ESC_E, - /* F */ 0, /* G */ -ESC_G, - /* H */ -ESC_H, /* I */ 0, - /* J */ 0, /* K */ -ESC_K, - /* L */ 0, /* M */ 0, - /* N */ -ESC_N, /* O */ 0, - /* P */ -ESC_P, /* Q */ -ESC_Q, - /* R */ -ESC_R, /* S */ -ESC_S, - /* T */ 0, /* U */ 0, - /* V */ -ESC_V, /* W */ -ESC_W, - /* X */ -ESC_X, /* Y */ 0, - /* Z */ -ESC_Z, /* [ */ CHAR_LEFT_SQUARE_BRACKET, - /* \ */ CHAR_BACKSLASH, /* ] */ CHAR_RIGHT_SQUARE_BRACKET, - /* ^ */ CHAR_CIRCUMFLEX_ACCENT, /* _ */ CHAR_UNDERSCORE, - /* ` */ CHAR_GRAVE_ACCENT, /* a */ CHAR_BEL, - /* b */ -ESC_b, /* c */ 0, - /* d */ -ESC_d, /* e */ CHAR_ESC, - /* f */ CHAR_FF, /* g */ 0, - /* h */ -ESC_h, /* i */ 0, - /* j */ 0, /* k */ -ESC_k, - /* l */ 0, /* m */ 0, - /* n */ CHAR_LF, /* o */ 0, - /* p */ -ESC_p, /* q */ 0, - /* r */ CHAR_CR, /* s */ -ESC_s, - /* t */ CHAR_HT, /* u */ 0, - /* v */ -ESC_v, /* w */ -ESC_w, - /* x */ 0, /* y */ 0, - /* z */ -ESC_z + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + CHAR_COLON, CHAR_SEMICOLON, + CHAR_LESS_THAN_SIGN, CHAR_EQUALS_SIGN, + CHAR_GREATER_THAN_SIGN, CHAR_QUESTION_MARK, + CHAR_COMMERCIAL_AT, -ESC_A, + -ESC_B, -ESC_C, + -ESC_D, -ESC_E, + 0, -ESC_G, + -ESC_H, 0, + 0, -ESC_K, + 0, 0, + -ESC_N, 0, + -ESC_P, -ESC_Q, + -ESC_R, -ESC_S, + 0, 0, + -ESC_V, -ESC_W, + -ESC_X, 0, + -ESC_Z, CHAR_LEFT_SQUARE_BRACKET, + CHAR_BACKSLASH, CHAR_RIGHT_SQUARE_BRACKET, + CHAR_CIRCUMFLEX_ACCENT, CHAR_UNDERSCORE, + CHAR_GRAVE_ACCENT, CHAR_BEL, + -ESC_b, 0, + -ESC_d, CHAR_ESC, + CHAR_FF, 0, + -ESC_h, 0, + 0, -ESC_k, + 0, 0, + CHAR_LF, 0, + -ESC_p, 0, + CHAR_CR, -ESC_s, + CHAR_HT, 0, + -ESC_v, -ESC_w, + 0, 0, + -ESC_z }; #else @@ -542,8 +656,6 @@ static const char alasnames[] = STRING_non_atomic_positive_lookbehind0 STRING_negative_lookahead0 STRING_negative_lookbehind0 - STRING_scs0 - STRING_scan_substring0 STRING_atomic0 STRING_sr0 STRING_asr0 @@ -563,8 +675,6 @@ static const alasitem alasmeta[] = { { 30, META_LOOKBEHIND_NA }, { 18, META_LOOKAHEADNOT }, { 19, META_LOOKBEHINDNOT }, - { 3, META_SCS }, - { 14, META_SCS }, { 6, META_ATOMIC }, { 2, META_SCRIPT_RUN }, /* sr = script run */ { 3, META_ATOMIC_SCRIPT_RUN }, /* asr = atomic script run */ @@ -584,11 +694,8 @@ static uint32_t chartypeoffset[] = { now all in a single string, to reduce the number of relocations when a shared library is dynamically loaded. The list of lengths is terminated by a zero length entry. The first three must be alpha, lower, upper, as this is assumed -for handling case independence. - -The indices for several classes are stored in pcre2_compile.h - these must -be kept in sync with posix_names, posix_name_lengths, posix_class_maps, -and posix_substitutes. */ +for handling case independence. The indices for several classes are needed, so +identify them. */ static const char posix_names[] = STRING_alpha0 STRING_lower0 STRING_upper0 STRING_alnum0 @@ -599,6 +706,12 @@ static const char posix_names[] = static const uint8_t posix_name_lengths[] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 }; +#define PC_DIGIT 7 +#define PC_GRAPH 8 +#define PC_PRINT 9 +#define PC_PUNCT 10 +#define PC_XDIGIT 13 + /* Table of class bit maps for each POSIX class. Each class is formed from a base map, with an optional addition or removal of another map. Then, for some classes, there is some additional tweaking: for [:blank:] the vertical space @@ -609,7 +722,7 @@ addition or a negative value for map subtraction (if there are two maps). The absolute value of the third field has these meanings: 0 => no tweaking, 1 => remove vertical space characters, 2 => remove underscore. */ -const int PRIV(posix_class_maps)[] = { +static const int posix_class_maps[] = { cbit_word, cbit_digit, -2, /* alpha */ cbit_lower, -1, 0, /* lower */ cbit_upper, -1, 0, /* upper */ @@ -647,6 +760,7 @@ static int posix_substitutes[] = { PT_WORD, 0, /* word */ /* Perl and POSIX space are the same */ PT_PXXDIGIT, 0 /* xdigit */ /* Perl has additional hex digits */ }; +#define POSIX_SUBSIZE (sizeof(posix_substitutes) / (2*sizeof(uint32_t))) #endif /* SUPPORT_UNICODE */ /* Masks for checking option settings. When PCRE2_LITERAL is set, only a subset @@ -664,11 +778,10 @@ are allowed. */ PCRE2_EXTENDED|PCRE2_EXTENDED_MORE|PCRE2_MATCH_UNSET_BACKREF| \ PCRE2_MULTILINE|PCRE2_NEVER_BACKSLASH_C|PCRE2_NEVER_UCP| \ PCRE2_NEVER_UTF|PCRE2_NO_AUTO_CAPTURE|PCRE2_NO_AUTO_POSSESS| \ - PCRE2_NO_DOTSTAR_ANCHOR|PCRE2_UCP|PCRE2_UNGREEDY|PCRE2_ALT_EXTENDED_CLASS) + PCRE2_NO_DOTSTAR_ANCHOR|PCRE2_UCP|PCRE2_UNGREEDY) #define PUBLIC_LITERAL_COMPILE_EXTRA_OPTIONS \ - (PCRE2_EXTRA_MATCH_LINE|PCRE2_EXTRA_MATCH_WORD| \ - PCRE2_EXTRA_CASELESS_RESTRICT|PCRE2_EXTRA_TURKISH_CASING) + (PCRE2_EXTRA_MATCH_LINE|PCRE2_EXTRA_MATCH_WORD|PCRE2_EXTRA_CASELESS_RESTRICT) #define PUBLIC_COMPILE_EXTRA_OPTIONS \ (PUBLIC_LITERAL_COMPILE_EXTRA_OPTIONS| \ @@ -676,8 +789,27 @@ are allowed. */ PCRE2_EXTRA_ESCAPED_CR_IS_LF|PCRE2_EXTRA_ALT_BSUX| \ PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK|PCRE2_EXTRA_ASCII_BSD| \ PCRE2_EXTRA_ASCII_BSS|PCRE2_EXTRA_ASCII_BSW|PCRE2_EXTRA_ASCII_POSIX| \ - PCRE2_EXTRA_ASCII_DIGIT|PCRE2_EXTRA_PYTHON_OCTAL|PCRE2_EXTRA_NO_BS0| \ - PCRE2_EXTRA_NEVER_CALLOUT) + PCRE2_EXTRA_ASCII_DIGIT) + +/* Compile time error code numbers. They are given names so that they can more +easily be tracked. When a new number is added, the tables called eint1 and +eint2 in pcre2posix.c may need to be updated, and a new error text must be +added to compile_error_texts in pcre2_error.c. Also, the error codes in +pcre2.h.in must be updated - their values are exactly 100 greater than these +values. */ + +enum { ERR0 = COMPILE_ERROR_BASE, + ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9, ERR10, + ERR11, ERR12, ERR13, ERR14, ERR15, ERR16, ERR17, ERR18, ERR19, ERR20, + ERR21, ERR22, ERR23, ERR24, ERR25, ERR26, ERR27, ERR28, ERR29, ERR30, + ERR31, ERR32, ERR33, ERR34, ERR35, ERR36, ERR37, ERR38, ERR39, ERR40, + ERR41, ERR42, ERR43, ERR44, ERR45, ERR46, ERR47, ERR48, ERR49, ERR50, + ERR51, ERR52, ERR53, ERR54, ERR55, ERR56, ERR57, ERR58, ERR59, ERR60, + ERR61, ERR62, ERR63, ERR64, ERR65, ERR66, ERR67, ERR68, ERR69, ERR70, + ERR71, ERR72, ERR73, ERR74, ERR75, ERR76, ERR77, ERR78, ERR79, ERR80, + ERR81, ERR82, ERR83, ERR84, ERR85, ERR86, ERR87, ERR88, ERR89, ERR90, + ERR91, ERR92, ERR93, ERR94, ERR95, ERR96, ERR97, ERR98, ERR99, ERR100, + ERR101 }; /* This is a table of start-of-pattern options such as (*UTF) and settings such as (*LIMIT_MATCH=nnnn) and (*CRLF). For completeness and backward @@ -685,18 +817,16 @@ compatibility, (*UTFn) is supported in the relevant libraries, but (*UTF) is generic and always supported. */ enum { PSO_OPT, /* Value is an option bit */ - PSO_XOPT, /* Value is an xoption bit */ PSO_FLG, /* Value is a flag bit */ PSO_NL, /* Value is a newline type */ PSO_BSR, /* Value is a \R type */ PSO_LIMH, /* Read integer value for heap limit */ PSO_LIMM, /* Read integer value for match limit */ - PSO_LIMD, /* Read integer value for depth limit */ - PSO_OPTMZ /* Value is an optimization bit */ + PSO_LIMD /* Read integer value for depth limit */ }; typedef struct pso { - const char *name; + const uint8_t *name; uint16_t length; uint16_t type; uint32_t value; @@ -705,29 +835,27 @@ typedef struct pso { /* NB: STRING_UTFn_RIGHTPAR contains the length as well */ static const pso pso_list[] = { - { STRING_UTFn_RIGHTPAR, PSO_OPT, PCRE2_UTF }, - { STRING_UTF_RIGHTPAR, 4, PSO_OPT, PCRE2_UTF }, - { STRING_UCP_RIGHTPAR, 4, PSO_OPT, PCRE2_UCP }, - { STRING_NOTEMPTY_RIGHTPAR, 9, PSO_FLG, PCRE2_NOTEMPTY_SET }, - { STRING_NOTEMPTY_ATSTART_RIGHTPAR, 17, PSO_FLG, PCRE2_NE_ATST_SET }, - { STRING_NO_AUTO_POSSESS_RIGHTPAR, 16, PSO_OPTMZ, PCRE2_OPTIM_AUTO_POSSESS }, - { STRING_NO_DOTSTAR_ANCHOR_RIGHTPAR, 18, PSO_OPTMZ, PCRE2_OPTIM_DOTSTAR_ANCHOR }, - { STRING_NO_JIT_RIGHTPAR, 7, PSO_FLG, PCRE2_NOJIT }, - { STRING_NO_START_OPT_RIGHTPAR, 13, PSO_OPTMZ, PCRE2_OPTIM_START_OPTIMIZE }, - { STRING_CASELESS_RESTRICT_RIGHTPAR, 18, PSO_XOPT, PCRE2_EXTRA_CASELESS_RESTRICT }, - { STRING_TURKISH_CASING_RIGHTPAR, 15, PSO_XOPT, PCRE2_EXTRA_TURKISH_CASING }, - { STRING_LIMIT_HEAP_EQ, 11, PSO_LIMH, 0 }, - { STRING_LIMIT_MATCH_EQ, 12, PSO_LIMM, 0 }, - { STRING_LIMIT_DEPTH_EQ, 12, PSO_LIMD, 0 }, - { STRING_LIMIT_RECURSION_EQ, 16, PSO_LIMD, 0 }, - { STRING_CR_RIGHTPAR, 3, PSO_NL, PCRE2_NEWLINE_CR }, - { STRING_LF_RIGHTPAR, 3, PSO_NL, PCRE2_NEWLINE_LF }, - { STRING_CRLF_RIGHTPAR, 5, PSO_NL, PCRE2_NEWLINE_CRLF }, - { STRING_ANY_RIGHTPAR, 4, PSO_NL, PCRE2_NEWLINE_ANY }, - { STRING_NUL_RIGHTPAR, 4, PSO_NL, PCRE2_NEWLINE_NUL }, - { STRING_ANYCRLF_RIGHTPAR, 8, PSO_NL, PCRE2_NEWLINE_ANYCRLF }, - { STRING_BSR_ANYCRLF_RIGHTPAR, 12, PSO_BSR, PCRE2_BSR_ANYCRLF }, - { STRING_BSR_UNICODE_RIGHTPAR, 12, PSO_BSR, PCRE2_BSR_UNICODE } + { (uint8_t *)STRING_UTFn_RIGHTPAR, PSO_OPT, PCRE2_UTF }, + { (uint8_t *)STRING_UTF_RIGHTPAR, 4, PSO_OPT, PCRE2_UTF }, + { (uint8_t *)STRING_UCP_RIGHTPAR, 4, PSO_OPT, PCRE2_UCP }, + { (uint8_t *)STRING_NOTEMPTY_RIGHTPAR, 9, PSO_FLG, PCRE2_NOTEMPTY_SET }, + { (uint8_t *)STRING_NOTEMPTY_ATSTART_RIGHTPAR, 17, PSO_FLG, PCRE2_NE_ATST_SET }, + { (uint8_t *)STRING_NO_AUTO_POSSESS_RIGHTPAR, 16, PSO_OPT, PCRE2_NO_AUTO_POSSESS }, + { (uint8_t *)STRING_NO_DOTSTAR_ANCHOR_RIGHTPAR, 18, PSO_OPT, PCRE2_NO_DOTSTAR_ANCHOR }, + { (uint8_t *)STRING_NO_JIT_RIGHTPAR, 7, PSO_FLG, PCRE2_NOJIT }, + { (uint8_t *)STRING_NO_START_OPT_RIGHTPAR, 13, PSO_OPT, PCRE2_NO_START_OPTIMIZE }, + { (uint8_t *)STRING_LIMIT_HEAP_EQ, 11, PSO_LIMH, 0 }, + { (uint8_t *)STRING_LIMIT_MATCH_EQ, 12, PSO_LIMM, 0 }, + { (uint8_t *)STRING_LIMIT_DEPTH_EQ, 12, PSO_LIMD, 0 }, + { (uint8_t *)STRING_LIMIT_RECURSION_EQ, 16, PSO_LIMD, 0 }, + { (uint8_t *)STRING_CR_RIGHTPAR, 3, PSO_NL, PCRE2_NEWLINE_CR }, + { (uint8_t *)STRING_LF_RIGHTPAR, 3, PSO_NL, PCRE2_NEWLINE_LF }, + { (uint8_t *)STRING_CRLF_RIGHTPAR, 5, PSO_NL, PCRE2_NEWLINE_CRLF }, + { (uint8_t *)STRING_ANY_RIGHTPAR, 4, PSO_NL, PCRE2_NEWLINE_ANY }, + { (uint8_t *)STRING_NUL_RIGHTPAR, 4, PSO_NL, PCRE2_NEWLINE_NUL }, + { (uint8_t *)STRING_ANYCRLF_RIGHTPAR, 8, PSO_NL, PCRE2_NEWLINE_ANYCRLF }, + { (uint8_t *)STRING_BSR_ANYCRLF_RIGHTPAR, 12, PSO_BSR, PCRE2_BSR_ANYCRLF }, + { (uint8_t *)STRING_BSR_UNICODE_RIGHTPAR, 12, PSO_BSR, PCRE2_BSR_UNICODE } }; /* This table is used when converting repeating opcodes into possessified @@ -782,15 +910,12 @@ static const uint8_t opcode_possessify[] = { OP_CRPOSRANGE, 0, /* CRRANGE, CRMINRANGE */ 0, 0, 0, 0, /* CRPOS{STAR,PLUS,QUERY,RANGE} */ - 0, 0, 0, 0, /* CLASS, NCLASS, XCLASS, ECLASS */ + 0, 0, 0, /* CLASS, NCLASS, XCLASS */ 0, 0, /* REF, REFI */ 0, 0, /* DNREF, DNREFI */ - 0, 0, /* RECURSE, CALLOUT */ + 0, 0 /* RECURSE, CALLOUT */ }; -/* Compile-time check that the table has the correct size. */ -STATIC_ASSERT(sizeof(opcode_possessify) == OP_CALLOUT+1, opcode_possessify); - #ifdef DEBUG_SHOW_PARSED /************************************************* @@ -852,7 +977,7 @@ for (;;) { uint32_t ptype = *pptr >> 16; uint32_t pvalue = *pptr++ & 0xffff; - fprintf(stderr, "META \\%c %d %d", (meta_arg == ESC_P)? CHAR_P:CHAR_p, + fprintf(stderr, "META \\%c %d %d", (meta_arg == ESC_P)? 'P':'p', ptype, pvalue); } else @@ -1027,24 +1152,6 @@ for (;;) fprintf(stderr, "%zd", offset); break; - case META_OFFSET: - fprintf(stderr, "META_OFFSET offset="); - GETOFFSET(offset, pptr); - fprintf(stderr, "%zd", offset); - break; - - case META_SCS: - fprintf(stderr, "META (*scan_substring:"); - break; - - case META_SCS_NAME: - fprintf(stderr, "META_SCS_NAME length=%d relative_offset=%d", *pptr++, (int)meta_arg); - break; - - case META_SCS_NUMBER: - fprintf(stderr, "META_SCS_NUMBER %d relative_offset=%d", *pptr++, (int)meta_arg); - break; - case META_MARK: fprintf(stderr, "META (*MARK:"); goto SHOWARG; @@ -1073,12 +1180,6 @@ for (;;) } fprintf(stderr, ") length=%u", length); break; - - case META_ECLASS_AND: fprintf(stderr, "META_ECLASS_AND"); break; - case META_ECLASS_OR: fprintf(stderr, "META_ECLASS_OR"); break; - case META_ECLASS_SUB: fprintf(stderr, "META_ECLASS_SUB"); break; - case META_ECLASS_XOR: fprintf(stderr, "META_ECLASS_XOR"); break; - case META_ECLASS_NOT: fprintf(stderr, "META_ECLASS_NOT"); break; } fprintf(stderr, "\n"); } @@ -1098,7 +1199,7 @@ associated JIT data. */ PCRE2_EXP_DEFN pcre2_code * PCRE2_CALL_CONVENTION pcre2_code_copy(const pcre2_code *code) { -PCRE2_SIZE *ref_count; +PCRE2_SIZE* ref_count; pcre2_code *newcode; if (code == NULL) return NULL; @@ -1210,10 +1311,7 @@ result must be greater than zero. ptrptr points to the character pointer variable ptrend points to the end of the input string allow_sign if < 0, sign not allowed; if >= 0, sign is relative to this - max_value the largest number allowed; - you must not pass a value for max_value larger than - INT_MAX/10 - 1 because this function relies on max_value to - avoid integer overflow + max_value the largest number allowed max_error the error to give for an over-large number intptr where to put the result errcodeptr where to put an error code @@ -1232,8 +1330,6 @@ uint32_t n = 0; PCRE2_SPTR ptr = *ptrptr; BOOL yield = FALSE; -PCRE2_ASSERT(max_value <= INT_MAX/10 - 1); - *errorcodeptr = 0; if (allow_sign >= 0 && ptr < ptrend) @@ -1254,11 +1350,10 @@ if (allow_sign >= 0 && ptr < ptrend) if (ptr >= ptrend || !IS_DIGIT(*ptr)) return FALSE; while (ptr < ptrend && IS_DIGIT(*ptr)) { - n = n * 10 + (*ptr++ - CHAR_0); + n = n * 10 + *ptr++ - CHAR_0; if (n > max_value) { *errorcodeptr = max_error; - while (ptr < ptrend && IS_DIGIT(*ptr)) ptr++; goto EXIT; } } @@ -1272,7 +1367,7 @@ if (allow_sign >= 0 && sign != 0) } if (sign > 0) n += allow_sign; - else if (n > (uint32_t)allow_sign) + else if ((int)n > allow_sign) { *errorcodeptr = ERR15; /* Non-existent subpattern */ goto EXIT; @@ -1359,7 +1454,7 @@ else if (pp >= ptrend || *pp != CHAR_RIGHT_CURLY_BRACKET) return FALSE; } -/* Now process the quantifier for real. We know it must be {n} or {n,} or {,m} +/* Now process the quantifier for real. We know it must be {n} or (n,} or {,m} or {n,m}. The only error that read_number() can return is for a number that is too big. If *errorcodeptr is returned as zero it means no number was found. */ @@ -1426,15 +1521,15 @@ return yield; /* This function is called when a \ has been encountered. It either returns a positive value for a simple escape such as \d, or 0 for a data character, which -is placed in chptr. A backreference to group n is returned as -(n+1). On +is placed in chptr. A backreference to group n is returned as negative n. On entry, ptr is pointing at the character after \. On exit, it points after the final code unit of the escape sequence. This function is also called from pcre2_substitute() to handle escape sequences in replacement strings. In this case, the cb argument is NULL, and in the case of escapes that have further processing, only sequences that define a data -character are recognised. The options argument is the final value of the -compiled pattern's options. +character are recognised. The isclass argument is not relevant; the options +argument is the final value of the compiled pattern's options. Arguments: ptrptr points to the input position pointer @@ -1443,8 +1538,7 @@ compiled pattern's options. errorcodeptr points to the errorcode variable (containing zero) options the current options bits xoptions the current extra options bits - bracount the number of capturing parentheses encountered so far - isclass TRUE if in a character class + isclass TRUE if inside a character class cb compile data block or NULL when called from pcre2_substitute() Returns: zero => a data character @@ -1455,8 +1549,8 @@ Returns: zero => a data character int PRIV(check_escape)(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, uint32_t *chptr, - int *errorcodeptr, uint32_t options, uint32_t xoptions, uint32_t bracount, - BOOL isclass, compile_block *cb) + int *errorcodeptr, uint32_t options, uint32_t xoptions, BOOL isclass, + compile_block *cb) { BOOL utf = (options & PCRE2_UTF) != 0; BOOL alt_bsux = @@ -1525,23 +1619,17 @@ else if ((i = escapes[c - ESCAPES_FIRST]) != 0) if (ptrend - p > 1 && *p == CHAR_U && p[1] == CHAR_PLUS) { -#ifndef EBCDIC +#ifdef EBCDIC + *errorcodeptr = ERR93; +#else if (utf) { ptr = p + 2; escape = 0; /* Not a fancy escape after all */ goto COME_FROM_NU; } + else *errorcodeptr = ERR93; #endif - *errorcodeptr = ERR93; - } - - /* Give an error in contexts where quantifiers are not allowed - (character classes; substitution strings). */ - - else if (isclass || cb == NULL) - { - *errorcodeptr = ERR37; } /* Give an error if what follows is not a quantifier, but don't override @@ -1572,8 +1660,7 @@ else if (cb == NULL) { - if (c < CHAR_0 || - (c > CHAR_9 && (c != CHAR_c && c != CHAR_o && c != CHAR_x && c != CHAR_g))) + if (c != CHAR_c && c != CHAR_o && c != CHAR_x) { *errorcodeptr = ERR3; return 0; @@ -1628,7 +1715,6 @@ else hptr >= ptrend || /* Hit end of input */ *hptr != CHAR_RIGHT_CURLY_BRACKET) /* No } terminator */ { - if (isclass) break; /* In a class, just treat as '\u' literal */ escape = ESC_ub; /* Special return */ ptr++; /* Skip { */ break; /* Hex escape not recognized */ @@ -1687,14 +1773,8 @@ else (possibly recursive) subroutine calls, _not_ backreferences. We return the ESC_g code. - Summary: Return a negative number for a numerical back reference (offset - by 1), ESC_k for a named back reference, and ESC_g for a named or - numbered subroutine call. - - The above describes the \g behaviour inside patterns. Inside replacement - strings (pcre2_substitute) we support only \g for Python - compatibility. Return ESG_g for the named case, and -(num+1) for the - numbered case. + Summary: Return a negative number for a numerical back reference, ESC_k for + a named back reference, and ESC_g for a named or numbered subroutine call. */ case CHAR_g: @@ -1706,40 +1786,6 @@ else break; } - if (cb == NULL) - { - PCRE2_SPTR p; - /* Substitution strings */ - if (*ptr != CHAR_LESS_THAN_SIGN) - { - *errorcodeptr = ERR57; - break; - } - - p = ptr + 1; - - if (!read_number(&p, ptrend, -1, MAX_GROUP_NUMBER, ERR61, &s, - errorcodeptr)) - { - if (*errorcodeptr == 0) escape = ESC_g; /* No number found */ - break; - } - - if (p >= ptrend || *p != CHAR_GREATER_THAN_SIGN) - { - /* not advancing ptr; report error at the \g character */ - *errorcodeptr = ERR57; - break; - } - - /* This is the reason that back references are returned as -(s+1) rather - than just -s. In a pattern, \0 is not a back reference, but \g<0> is - valid in a substitution string, so this must be representable. */ - ptr = p + 1; - escape = -(s+1); - break; - } - if (*ptr == CHAR_LESS_THAN_SIGN || *ptr == CHAR_APOSTROPHE) { escape = ESC_g; @@ -1754,7 +1800,7 @@ else PCRE2_SPTR p = ptr + 1; while (p < ptrend && (*p == CHAR_SPACE || *p == CHAR_HT)) p++; - if (!read_number(&p, ptrend, bracount, MAX_GROUP_NUMBER, ERR61, &s, + if (!read_number(&p, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61, &s, errorcodeptr)) { if (*errorcodeptr == 0) escape = ESC_k; /* No number found */ @@ -1764,7 +1810,6 @@ else if (p >= ptrend || *p != CHAR_RIGHT_CURLY_BRACKET) { - /* not advancing ptr; report error at the \g character */ *errorcodeptr = ERR57; break; } @@ -1775,7 +1820,7 @@ else else { - if (!read_number(&ptr, ptrend, bracount, MAX_GROUP_NUMBER, ERR61, &s, + if (!read_number(&ptr, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61, &s, errorcodeptr)) { if (*errorcodeptr == 0) *errorcodeptr = ERR57; /* No number found */ @@ -1789,7 +1834,7 @@ else break; } - escape = -(s+1); + escape = -s; break; /* The handling of escape sequences consisting of a string of digits @@ -1801,16 +1846,7 @@ else number is less than 10, or if there are that many previous extracting left brackets, it is a back reference. Otherwise, up to three octal digits are read to form an escaped character code. Thus \123 is likely to be octal 123 - (cf \0123, which is octal 012 followed by the literal 3). This is the "Perl - style" of handling ambiguous octal/backrefences such as \12. - - There is an alternative disambiguation strategy, selected by - PCRE2_EXTRA_PYTHON_OCTAL, which follows Python's behaviour. An octal must - have either a leading zero, or exactly three octal digits; otherwise it's - a backreference. The disambiguation is stable, and does not depend on how - many capture groups are defined (it's simply an invalid backreference if - there is no corresponding capture group). Additionally, octal values above - \377 (\xff) are rejected. + (cf \0123, which is octal 012 followed by the literal 3). Inside a character class, \ followed by a digit is always either a literal 8 or 9 or an octal number. */ @@ -1818,65 +1854,24 @@ else case CHAR_1: case CHAR_2: case CHAR_3: case CHAR_4: case CHAR_5: case CHAR_6: case CHAR_7: case CHAR_8: case CHAR_9: - if (isclass) - { - /* Fall through to octal handling; never a backreference inside a class. */ - } - else if ((xoptions & PCRE2_EXTRA_PYTHON_OCTAL) != 0) - { - /* Python-style disambiguation. */ - if (ptr[-1] <= CHAR_7 && ptr + 1 < ptrend && ptr[0] >= CHAR_0 && - ptr[0] <= CHAR_7 && ptr[1] >= CHAR_0 && ptr[1] <= CHAR_7) - { - /* We peeked a three-digit octal, so fall through */ - } - else - { - /* We are at a digit, so the only possible error from read_number() is - a number that is too large. */ - ptr--; /* Back to the digit */ - - if (!read_number(&ptr, ptrend, -1, MAX_GROUP_NUMBER, 0, &s, errorcodeptr)) - { - *errorcodeptr = ERR61; - break; - } - - escape = -(s+1); - break; - } - } - else + if (!isclass) { - /* Perl-style disambiguation. */ oldptr = ptr; ptr--; /* Back to the digit */ /* As we know we are at a digit, the only possible error from - read_number() is a number that is too large to be a group number. Because - that number might be still valid if read as an octal, errorcodeptr is not - set on failure and therefore a sentinel value of INT_MAX is used instead - of the original value, and will be used later to properly set the error, - if not falling through. */ - - if (!read_number(&ptr, ptrend, -1, MAX_GROUP_NUMBER, 0, &s, errorcodeptr)) - s = INT_MAX; + read_number() is a number that is too large to be a group number. In this + case we fall through handle this as not a group reference. If we have + read a small enough number, check for a back reference. - /* \1 to \9 are always back references. \8x and \9x are too; \1x to \7x + \1 to \9 are always back references. \8x and \9x are too; \1x to \7x are octal escapes if there are not that many previous captures. */ - if (s < 10 || c >= CHAR_8 || (unsigned)s <= bracount) + if (read_number(&ptr, ptrend, -1, INT_MAX/10 - 1, 0, &s, errorcodeptr) && + (s < 10 || oldptr[-1] >= CHAR_8 || s <= (int)cb->bracount)) { - /* s > MAX_GROUP_NUMBER should not be possible because of read_number(), - but we keep it just to be safe and because it will also catch the - sentinel value that was set on failure by that function. */ - - if ((unsigned)s > MAX_GROUP_NUMBER) - { - PCRE2_ASSERT(s == INT_MAX); - *errorcodeptr = ERR61; - } - else escape = -(s+1); /* Indicates a back reference */ + if (s > (int)MAX_GROUP_NUMBER) *errorcodeptr = ERR61; + else escape = -s; /* Indicates a back reference */ break; } @@ -1895,26 +1890,16 @@ else /* \0 always starts an octal number, but we may drop through to here with a larger first octal digit. The original code used just to take the least significant 8 bits of octal numbers (I think this is what early Perls used - to do). Nowadays we allow for larger numbers in UTF-8 mode and 16/32-bit mode, + to do). Nowadays we allow for larger numbers in UTF-8 mode and 16-bit mode, but no more than 3 octal digits. */ case CHAR_0: c -= CHAR_0; while(i++ < 2 && ptr < ptrend && *ptr >= CHAR_0 && *ptr <= CHAR_7) c = c * 8 + *ptr++ - CHAR_0; - if (c > 0xff) - { - if ((xoptions & PCRE2_EXTRA_PYTHON_OCTAL) != 0) *errorcodeptr = ERR102; #if PCRE2_CODE_UNIT_WIDTH == 8 - else if (!utf) *errorcodeptr = ERR51; + if (!utf && c > 0xff) *errorcodeptr = ERR51; #endif - } - - /* PCRE2_EXTRA_NO_BS0 disables the NUL escape '\0' but doesn't affect - two- or three-character octal escapes \00 and \000, nor \x00. */ - - if ((xoptions & PCRE2_EXTRA_NO_BS0) != 0 && c == 0 && i == 1) - *errorcodeptr = ERR98; break; /* \o is a relatively new Perl feature, supporting a more general way of @@ -1943,7 +1928,7 @@ else cc = *ptr++; if (c == 0 && cc == CHAR_0) continue; /* Leading zeroes */ #if PCRE2_CODE_UNIT_WIDTH == 32 - if (c >= 0x20000000u) { overflow = TRUE; break; } + if (c >= 0x20000000l) { overflow = TRUE; break; } #endif c = (c << 3) + (cc - CHAR_0); #if PCRE2_CODE_UNIT_WIDTH == 8 @@ -2069,29 +2054,10 @@ else else { - /* Perl has the surprising/broken behaviour that \x without following - hex digits is treated as an escape for NUL. Their source code laments - this but keeps it for backwards compatibility. A warning is printed - when "use warnings" is enabled. Because we don't have warnings, we - simply forbid it. */ - if (ptr >= ptrend || (cc = XDIGIT(*ptr)) == 0xff) - { - /* Not a hex digit */ - *errorcodeptr = ERR78; - break; - } + c = 0; + if (ptr >= ptrend || (cc = XDIGIT(*ptr)) == 0xff) break; /* Not a hex digit */ ptr++; c = cc; - - /* With "use re 'strict'" Perl actually requires exactly two digits (error - for \x, \xA and \xAAA). While \x was already rejected, this seems overly - strict, and there seems little incentive to align with that, given the - backwards-compatibility cost. - - For comparison, note that other engines disagree. For example: - - Java allows 1 or 2 hex digits. Error if 0 digits. No error if >2 digits - - .NET requires 2 hex digits. Error if 0, 1 digits. No error if >2 digits. - */ if (ptr >= ptrend || (cc = XDIGIT(*ptr)) == 0xff) break; /* Not a hex digit */ ptr++; c = (c << 4) | cc; @@ -2213,65 +2179,37 @@ c = *ptr++; *negptr = FALSE; /* \P or \p can be followed by a name in {}, optionally preceded by ^ for -negation. We must be handling Unicode encoding here, though we may be compiling -for UTF-8 input in an EBCDIC environment. (PCRE2 does not support both EBCDIC -input and Unicode input in the same build.) In accordance with Unicode's "loose -matching" rules, ASCII white space, hyphens, and underscores are ignored. We -don't use isspace() or tolower() because (a) code points may be greater than -255, and (b) they wouldn't work when compiling for Unicode in an EBCDIC -environment. */ +negation. */ if (c == CHAR_LEFT_CURLY_BRACKET) { if (ptr >= cb->end_pattern) goto ERROR_RETURN; - for (i = 0; i < (int)(sizeof(name) / sizeof(PCRE2_UCHAR)) - 1; i++) + if (*ptr == CHAR_CIRCUMFLEX_ACCENT) { - REDO: + *negptr = TRUE; + ptr++; + } + for (i = 0; i < (int)(sizeof(name) / sizeof(PCRE2_UCHAR)) - 1; i++) + { if (ptr >= cb->end_pattern) goto ERROR_RETURN; c = *ptr++; - - /* Skip ignorable Unicode characters. */ - - while (c == CHAR_UNDERSCORE || c == CHAR_MINUS || c == CHAR_SPACE || - (c >= CHAR_HT && c <= CHAR_CR)) +#if PCRE2_CODE_UNIT_WIDTH != 8 + while (c == '_' || c == '-' || (c <= 0xff && isspace(c))) +#else + while (c == '_' || c == '-' || isspace(c)) +#endif { if (ptr >= cb->end_pattern) goto ERROR_RETURN; c = *ptr++; } - - /* The first significant character being circumflex negates the meaning of - the item. */ - - if (i == 0 && !*negptr && c == CHAR_CIRCUMFLEX_ACCENT) - { - *negptr = TRUE; - goto REDO; - } - + if (c == CHAR_NUL) goto ERROR_RETURN; if (c == CHAR_RIGHT_CURLY_BRACKET) break; - - /* Names consist of ASCII letters and digits, but equals and colon may also - occur as a name/value separator. We must also allow for \p{L&}. A simple - check for a value between '&' and 'z' suffices because anything else in a - name or value will cause an "unknown property" error anyway. */ - - if (c < CHAR_AMPERSAND || c > CHAR_z) goto ERROR_RETURN; - - /* Lower case a capital letter or remember where the name/value separator - is. */ - - if (c >= CHAR_A && c <= CHAR_Z) c |= 0x20; - else if ((c == CHAR_COLON || c == CHAR_EQUALS_SIGN) && vptr == NULL) - vptr = name + i; - - name[i] = c; + name[i] = tolower(c); + if ((c == ':' || c == '=') && vptr == NULL) vptr = name + i; } - /* Error if the loop didn't end with '}' - either we hit the end of the - pattern or the name was longer than any legal property name. */ - if (c != CHAR_RIGHT_CURLY_BRACKET) goto ERROR_RETURN; name[i] = 0; } @@ -2279,19 +2217,14 @@ if (c == CHAR_LEFT_CURLY_BRACKET) /* If { doesn't follow \p or \P there is just one following character, which must be an ASCII letter. */ -else if (c >= CHAR_A && c <= CHAR_Z) - { - name[0] = c | 0x20; /* Lower case */ - name[1] = 0; - } -else if (c >= CHAR_a && c <= CHAR_z) +else if (MAX_255(c) && (cb->ctypes[c] & ctype_letter) != 0) { - name[0] = c; + name[0] = tolower(c); name[1] = 0; } else goto ERROR_RETURN; -*ptrptr = ptr; /* Update pattern pointer */ +*ptrptr = ptr; /* If the property contains ':' or '=' we have class name and value separately specified. The following are supported: @@ -2549,9 +2482,6 @@ if (ptr >= ptrend) /* No characters in name */ *nameptr = ptr; *offsetptr = (PCRE2_SIZE)(ptr - cb->start_pattern); -/* If this logic were ever to change, the matching function in pcre2_substitute.c -ought to be updated to match. */ - /* In UTF mode, a group name may contain letters and decimal digits as defined by Unicode properties, and underscores, but must not start with a digit. */ @@ -2770,60 +2700,6 @@ return parsed_pattern; -/************************************************* -* Maximum size of parsed_pattern for given input * -*************************************************/ - -/* This function is called from parse_regex() below, to determine the amount -of memory to allocate for parsed_pattern. It is also called to check whether -the amount of data written respects the amount of memory allocated. - -Arguments: - ptr points to the start of the pattern - ptrend points to the end of the pattern - utf TRUE in UTF mode - options the options bits - -Returns: the number of uint32_t units for parsed_pattern -*/ -static ptrdiff_t -max_parsed_pattern(PCRE2_SPTR ptr, PCRE2_SPTR ptrend, BOOL utf, - uint32_t options) -{ -PCRE2_SIZE big32count = 0; -ptrdiff_t parsed_size_needed; - -/* When PCRE2_AUTO_CALLOUT is not set, in all but one case the number of -unsigned 32-bit ints written out to the parsed pattern is bounded by the length -of the pattern. The exceptional case is when running in 32-bit, non-UTF mode, -when literal characters greater than META_END (0x80000000) have to be coded as -two units. In this case, therefore, we scan the pattern to check for such -values. */ - -#if PCRE2_CODE_UNIT_WIDTH == 32 -if (!utf) - { - PCRE2_SPTR p; - for (p = ptr; p < ptrend; p++) if (*p >= META_END) big32count++; - } -#else -(void)utf; /* Avoid compiler warning */ -#endif - -parsed_size_needed = (ptrend - ptr) + big32count; - -/* When PCRE2_AUTO_CALLOUT is set we have to assume a numerical callout (4 -elements) for each character. This is overkill, but memory is plentiful these -days. */ - -if ((options & PCRE2_AUTO_CALLOUT) != 0) - parsed_size_needed += (ptrend - ptr) * 4; - -return parsed_size_needed; -} - - - /************************************************* * Parse regex and identify named groups * *************************************************/ @@ -2875,33 +2751,7 @@ the main compiling phase. */ /* States used for analyzing ranges in character classes. The two OK values must be last. */ -enum { - RANGE_NO, /* State after '[' (initial), or '[a-z'; hyphen is literal */ - RANGE_STARTED, /* State after '[1-'; last-emitted code is META_RANGE_XYZ */ - RANGE_FORBID_NO, /* State after '[\d'; '-]' is allowed but not '-1]' */ - RANGE_FORBID_STARTED, /* State after '[\d-'*/ - RANGE_OK_ESCAPED, /* State after '[\1'; hyphen may be a range */ - RANGE_OK_LITERAL /* State after '[1'; hyphen may be a range */ -}; - -/* States used for analyzing operators and operands in extended character -classes. */ - -enum { - CLASS_OP_EMPTY, /* At start of an expression; empty previous contents */ - CLASS_OP_OPERAND, /* Have preceding operand; after "z" a "--" can follow */ - CLASS_OP_OPERATOR /* Have preceding operator; after "--" operand must follow */ -}; - -/* States used for determining the parse mode in character classes. The two -PERL_EXT values must be last. */ - -enum { - CLASS_MODE_NORMAL, /* Ordinary PCRE2 '[...]' class. */ - CLASS_MODE_ALT_EXT, /* UTS#18-style extended '[...]' class. */ - CLASS_MODE_PERL_EXT, /* Perl extended '(?[...])' class. */ - CLASS_MODE_PERL_EXT_LEAF /* Leaf within extended '(?[ [...] ])' class. */ -}; +enum { RANGE_NO, RANGE_STARTED, RANGE_OK_ESCAPED, RANGE_OK_LITERAL }; /* Only in 32-bit mode can there be literals > META_END. A macro encapsulates the storing of literal values in the main parsed pattern, where they can always @@ -2920,16 +2770,13 @@ be quantified. */ /* Here's the actual function. */ -static int parse_regex(PCRE2_SPTR ptr, uint32_t options, uint32_t xoptions, - BOOL *has_lookbehind, compile_block *cb) +static int parse_regex(PCRE2_SPTR ptr, uint32_t options, BOOL *has_lookbehind, + compile_block *cb) { uint32_t c; uint32_t delimiter; uint32_t namelen; uint32_t class_range_state; -uint32_t class_op_state; -uint32_t class_mode_state; -uint32_t *class_start; uint32_t *verblengthptr = NULL; /* Value avoids compiler warning */ uint32_t *verbstartptr = NULL; uint32_t *previous_callout = NULL; @@ -2939,9 +2786,8 @@ uint32_t *this_parsed_item = NULL; uint32_t *prev_parsed_item = NULL; uint32_t meta_quantifier = 0; uint32_t add_after_mark = 0; +uint32_t xoptions = cb->cx->extra_options; uint16_t nest_depth = 0; -int16_t class_depth_m1 = -1; /* The m1 means minus 1. */ -int16_t class_maxdepth_m1 = -1; int after_manual_callout = 0; int expect_cond_assert = 0; int errorcode = 0; @@ -2958,17 +2804,8 @@ PCRE2_SPTR thisptr; PCRE2_SPTR name; PCRE2_SPTR ptrend = cb->end_pattern; PCRE2_SPTR verbnamestart = NULL; /* Value avoids compiler warning */ -PCRE2_SPTR class_range_forbid_ptr = NULL; named_group *ng; nest_save *top_nest, *end_nests; -#ifdef PCRE2_DEBUG -uint32_t *parsed_pattern_check; -ptrdiff_t parsed_pattern_extra = 0; -ptrdiff_t parsed_pattern_extra_check = 0; -PCRE2_SPTR ptr_check; -#endif - -PCRE2_ASSERT(parsed_pattern != NULL); /* Insert leading items for word and line matching (features provided for the benefit of pcre2grep). */ @@ -2984,11 +2821,6 @@ else if ((xoptions & PCRE2_EXTRA_MATCH_WORD) != 0) *parsed_pattern++ = META_NOCAPTURE; } -#ifdef PCRE2_DEBUG -parsed_pattern_check = parsed_pattern; -ptr_check = ptr; -#endif - /* If the pattern is actually a literal string, process it separately to avoid cluttering up the main loop. */ @@ -2998,7 +2830,6 @@ if ((options & PCRE2_LITERAL) != 0) { if (parsed_pattern >= parsed_pattern_end) { - PCRE2_DEBUG_UNREACHABLE(); errorcode = ERR63; /* Internal error (parsed pattern overflow) */ goto FAILED; } @@ -3042,40 +2873,18 @@ while (ptr < ptrend) PCRE2_SPTR tempptr; PCRE2_SIZE offset; - if (nest_depth > cb->cx->parens_nest_limit) - { - errorcode = ERR19; - goto FAILED; /* Parentheses too deeply nested */ - } - - /* Check that we haven't emitted too much into parsed_pattern. We allocate - a suitably-sized buffer upfront, then do unchecked writes to it. If we only - write a little bit too much, everything will appear to be OK, because the - upfront size is an overestimate... but a malicious pattern could end up - forcing a write past the buffer end. We must catch this during - development. */ - -#ifdef PCRE2_DEBUG - /* Strong post-write check. Won't help in release builds - at this point - the write has already occurred so it's too late. However, should stop us - committing unsafe code. */ - PCRE2_ASSERT((parsed_pattern - parsed_pattern_check) + - (parsed_pattern_extra - parsed_pattern_extra_check) <= - max_parsed_pattern(ptr_check, ptr, utf, options)); - parsed_pattern_check = parsed_pattern; - parsed_pattern_extra_check = parsed_pattern_extra; - ptr_check = ptr; -#endif - if (parsed_pattern >= parsed_pattern_end) { - /* Weak pre-write check; only ensures parsed_pattern[0] is writeable - (but the code below can write many chars). Better than nothing. */ - PCRE2_DEBUG_UNREACHABLE(); errorcode = ERR63; /* Internal error (parsed pattern overflow) */ goto FAILED; } + if (nest_depth > cb->cx->parens_nest_limit) + { + errorcode = ERR19; + goto FAILED; /* Parentheses too deeply nested */ + } + /* If the last time round this loop something was added, parsed_pattern will no longer be equal to this_parsed_item. Remember where the previous item started and reset for the next item. Note that sometimes round the loop, @@ -3195,7 +3004,7 @@ while (ptr < ptrend) if ((options & PCRE2_ALT_VERBNAMES) != 0) { escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode, options, - xoptions, cb->bracount, FALSE, cb); + xoptions, FALSE, cb); if (errorcode != 0) goto FAILED; } else escape = 0; /* Treat all as literal */ @@ -3395,7 +3204,7 @@ while (ptr < ptrend) case CHAR_BACKSLASH: tempptr = ptr; escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode, options, - xoptions, cb->bracount, FALSE, cb); + xoptions, FALSE, cb); if (errorcode != 0) { ESCAPE_FAILED: @@ -3426,7 +3235,7 @@ while (ptr < ptrend) else if (escape < 0) { offset = (PCRE2_SIZE)(ptr - cb->start_pattern - 1); - escape = -escape - 1; + escape = -escape; *parsed_pattern++ = META_BACKREF | (uint32_t)escape; if (escape < 10) { @@ -3538,7 +3347,7 @@ while (ptr < ptrend) /* When \g is used with quotes or angle brackets as delimiters, it is a numerical or named subroutine call, and control comes here. When used - with brace delimiters it is a numerical back reference and does not come + with brace delimiters it is a numberical back reference and does not come here because check_escape() returns it directly as a reference. \k is always a named back reference. */ @@ -3649,7 +3458,7 @@ while (ptr < ptrend) if (!prev_okquantifier) { errorcode = ERR9; - goto FAILED_BACK; // TODO https://github.com/PCRE2Project/pcre2/issues/549 + goto FAILED_BACK; } /* Most (*VERB)s are not allowed to be quantified, but an ungreedy @@ -3665,11 +3474,6 @@ while (ptr < ptrend) *verbstartptr = META_NOCAPTURE; parsed_pattern[1] = META_KET; parsed_pattern += 2; - -#ifdef PCRE2_DEBUG - PCRE2_ASSERT(parsed_pattern_extra >= 2); - parsed_pattern_extra -= 2; -#endif } /* Now we can put the quantifier into the parsed pattern vector. At this @@ -3689,6 +3493,7 @@ while (ptr < ptrend) /* ---- Character class ---- */ case CHAR_LEFT_SQUARE_BRACKET: + okquantifier = TRUE; /* In another (POSIX) regex library, the ugly syntax [[:<:]] and [[:>:]] is used for "start of word" and "end of word". As these are otherwise illegal @@ -3726,7 +3531,6 @@ while (ptr < ptrend) } *parsed_pattern++ = META_KET; ptr += 6; - okquantifier = TRUE; break; } @@ -3741,14 +3545,46 @@ while (ptr < ptrend) goto FAILED; } - class_mode_state = ((options & PCRE2_ALT_EXTENDED_CLASS) != 0)? - CLASS_MODE_ALT_EXT : CLASS_MODE_NORMAL; + /* Process a regular character class. If the first character is '^', set + the negation flag. If the first few characters (either before or after ^) + are \Q\E or \E or space or tab in extended-more mode, we skip them too. + This makes for compatibility with Perl. */ + + negate_class = FALSE; + while (ptr < ptrend) + { + GETCHARINCTEST(c, ptr); + if (c == CHAR_BACKSLASH) + { + if (ptr < ptrend && *ptr == CHAR_E) ptr++; + else if (ptrend - ptr >= 3 && + PRIV(strncmp_c8)(ptr, STR_Q STR_BACKSLASH STR_E, 3) == 0) + ptr += 3; + else + break; + } + else if ((options & PCRE2_EXTENDED_MORE) != 0 && + (c == CHAR_SPACE || c == CHAR_HT)) /* Note: just these two */ + continue; + else if (!negate_class && c == CHAR_CIRCUMFLEX_ACCENT) + negate_class = TRUE; + else break; + } + + /* Now the real contents of the class; c has the first "real" character. + Empty classes are permitted only if the option is set. */ + + if (c == CHAR_RIGHT_SQUARE_BRACKET && + (cb->external_options & PCRE2_ALLOW_EMPTY_CLASS) != 0) + { + *parsed_pattern++ = negate_class? META_CLASS_EMPTY_NOT : META_CLASS_EMPTY; + break; /* End of class processing */ + } - /* Jump here from '(?[...])'. That jump must initialize class_mode_state, - set c to the '[' character, and ptr to just after the '['. */ + /* Process a non-empty class. */ - FROM_PERL_EXTENDED_CLASS: - okquantifier = TRUE; + *parsed_pattern++ = negate_class? META_CLASS_NOT : META_CLASS; + class_range_state = RANGE_NO; /* In an EBCDIC environment, Perl treats alphabetic ranges specially because there are holes in the encoding, and simply using the range A-Z @@ -3758,16 +3594,7 @@ while (ptr < ptrend) character values are literal or not, and a state variable for handling ranges. */ - /* Loop for the contents of the class. Classes may be nested, if - PCRE2_ALT_EXTENDED_CLASS is set, or the class is of the form (?[...]). */ - - /* c is still set to '[' so the loop will handle the start of the class. */ - - class_depth_m1 = -1; - class_maxdepth_m1 = -1; - class_range_state = RANGE_NO; - class_op_state = CLASS_OP_EMPTY; - class_start = NULL; + /* Loop for the contents of the class */ for (;;) { @@ -3783,26 +3610,13 @@ while (ptr < ptrend) ptr++; /* Skip the 'E' */ goto CLASS_CONTINUE; } - - /* Surprisingly, you cannot use \Q..\E to escape a character inside a - Perl extended class. However, empty \Q\E sequences are allowed, so here - were're only giving an error if the \Q..\E is non-empty. */ - - if (class_mode_state == CLASS_MODE_PERL_EXT) - { - errorcode = ERR116; - goto FAILED; - } - goto CLASS_LITERAL; } - /* Skip over space and tab (only) in extended-more mode, or anywhere - inside a Perl extended class (which implies /xx). */ + /* Skip over space and tab (only) in extended-more mode. */ - if ((c == CHAR_SPACE || c == CHAR_HT) && - ((options & PCRE2_EXTENDED_MORE) != 0 || - class_mode_state >= CLASS_MODE_PERL_EXT)) + if ((options & PCRE2_EXTENDED_MORE) != 0 && + (c == CHAR_SPACE || c == CHAR_HT)) goto CLASS_CONTINUE; /* Handle POSIX class names. Perl allows a negation extension of the @@ -3811,8 +3625,7 @@ while (ptr < ptrend) [.ch.] and [=ch=] ("collating elements") and fault them, as Perl 5.6 and 5.8 do. */ - if (class_depth_m1 >= 0 && - c == CHAR_LEFT_SQUARE_BRACKET && + if (c == CHAR_LEFT_SQUARE_BRACKET && ptrend - ptr >= 3 && (*ptr == CHAR_COLON || *ptr == CHAR_DOT || *ptr == CHAR_EQUALS_SIGN) && @@ -3828,41 +3641,14 @@ while (ptr < ptrend) if (class_range_state == RANGE_STARTED) { - ptr = tempptr + 2; - errorcode = ERR50; - goto FAILED; - } - - /* Perl treats a hyphen after a POSIX class as a literal, not the - start of a range. However, it gives a warning in its warning mode - unless the hyphen is the last character in the class. PCRE does not - have a warning mode, so we give an error, because this is likely an - error on the user's part. - - Roll back to the hyphen for the error position. */ - - if (class_range_state == RANGE_FORBID_STARTED) - { - ptr = class_range_forbid_ptr; errorcode = ERR50; goto FAILED; } - /* Disallow implicit union in Perl extended classes. */ - - if (class_op_state == CLASS_OP_OPERAND && - class_mode_state == CLASS_MODE_PERL_EXT) - { - ptr = tempptr + 2; - errorcode = ERR113; - goto FAILED; - } - if (*ptr != CHAR_COLON) { - ptr = tempptr + 2; errorcode = ERR13; - goto FAILED; + goto FAILED_BACK; } if (*(++ptr) == CHAR_CIRCUMFLEX_ACCENT) @@ -3872,19 +3658,33 @@ while (ptr < ptrend) } posix_class = check_posix_name(ptr, (int)(tempptr - ptr)); - ptr = tempptr + 2; if (posix_class < 0) { errorcode = ERR30; goto FAILED; } + ptr = tempptr + 2; + + /* Perl treats a hyphen after a POSIX class as a literal, not the + start of a range. However, it gives a warning in its warning mode + unless the hyphen is the last character in the class. PCRE does not + have a warning mode, so we give an error, because this is likely an + error on the user's part. */ + + if (ptr < ptrend - 1 && *ptr == CHAR_MINUS && + ptr[1] != CHAR_RIGHT_SQUARE_BRACKET) + { + errorcode = ERR50; + goto FAILED; + } - /* Set "a hyphen is forbidden to be the start of a range". For the '-]' - case, the hyphen is treated as a literal, but for '-1' it is disallowed - (because it would be interpreted as range). */ + /* Set "a hyphen is not the start of a range" for the -] case, and also + in case the POSIX class is followed by \E or \Q\E (possibly repeated - + fuzzers do that kind of thing) and *then* a hyphen. This causes that + hyphen to be treated as a literal. I don't think it's worth setting up + special apparatus to do otherwise. */ - class_range_state = RANGE_FORBID_NO; - class_op_state = CLASS_OP_OPERAND; + class_range_state = RANGE_NO; /* When PCRE2_UCP is set, unless PCRE2_EXTRA_ASCII_POSIX is set, some of the POSIX classes are converted to use Unicode properties \p or \P @@ -3927,344 +3727,56 @@ while (ptr < ptrend) *parsed_pattern++ = posix_class; } - /* Check for the start of the outermost class, or the start of a nested class. */ + /* Handle potential start of range */ - else if ((c == CHAR_LEFT_SQUARE_BRACKET && - (class_depth_m1 < 0 || class_mode_state == CLASS_MODE_ALT_EXT || - class_mode_state == CLASS_MODE_PERL_EXT)) || - (c == CHAR_LEFT_PARENTHESIS && - class_mode_state == CLASS_MODE_PERL_EXT)) + else if (c == CHAR_MINUS && class_range_state >= RANGE_OK_ESCAPED) { - uint32_t start_c = c; - uint32_t new_class_mode_state; - - /* Update the class mode, if moving into a 'leaf' inside a Perl extended - class. */ - - if (start_c == CHAR_LEFT_SQUARE_BRACKET && - class_mode_state == CLASS_MODE_PERL_EXT && class_depth_m1 >= 0) - new_class_mode_state = CLASS_MODE_PERL_EXT_LEAF; - else - new_class_mode_state = class_mode_state; + *parsed_pattern++ = (class_range_state == RANGE_OK_LITERAL)? + META_RANGE_LITERAL : META_RANGE_ESCAPED; + class_range_state = RANGE_STARTED; + } - /* Tidy up the other class before starting the nested class. */ - /* -[ beginning a nested class is a literal '-' */ + /* Handle a literal character */ + else if (c != CHAR_BACKSLASH) + { + CLASS_LITERAL: if (class_range_state == RANGE_STARTED) - parsed_pattern[-1] = CHAR_MINUS; - - /* Disallow implicit union in Perl extended classes. */ - - if (class_op_state == CLASS_OP_OPERAND && - class_mode_state == CLASS_MODE_PERL_EXT) - { - errorcode = ERR113; - goto FAILED; - } - - /* Validate nesting depth */ - if (class_depth_m1 >= ECLASS_NEST_LIMIT - 1) { - errorcode = ERR107; - goto FAILED; /* Classes too deeply nested */ - } - - /* Process the character class start. If the first character is '^', set - the negation flag. If the first few characters (either before or after ^) - are \Q\E or \E or space or tab in extended-more mode, we skip them too. - This makes for compatibility with Perl. */ - - negate_class = FALSE; - for (;;) - { - if (ptr >= ptrend) + if (c == parsed_pattern[-2]) /* Optimize one-char range */ + parsed_pattern--; + else if (parsed_pattern[-2] > c) /* Check range is in order */ { - if (start_c == CHAR_LEFT_PARENTHESIS) - errorcode = ERR14; /* Missing terminating ')' */ - else - errorcode = ERR6; /* Missing terminating ']' */ - goto FAILED; - } - - GETCHARINCTEST(c, ptr); - if (new_class_mode_state == CLASS_MODE_PERL_EXT) break; - else if (c == CHAR_BACKSLASH) - { - if (ptr < ptrend && *ptr == CHAR_E) ptr++; - else if (ptrend - ptr >= 3 && - PRIV(strncmp_c8)(ptr, STR_Q STR_BACKSLASH STR_E, 3) == 0) - ptr += 3; - else - break; - } - else if ((c == CHAR_SPACE || c == CHAR_HT) && /* Note: just these two */ - ((options & PCRE2_EXTENDED_MORE) != 0 || - new_class_mode_state >= CLASS_MODE_PERL_EXT)) - continue; - else if (!negate_class && c == CHAR_CIRCUMFLEX_ACCENT) - negate_class = TRUE; - else break; - } - - /* Now the real contents of the class; c has the first "real" character. - Empty classes are permitted only if the option is set, and if it's not - a Perl-extended class. */ - - if (c == CHAR_RIGHT_SQUARE_BRACKET && - (cb->external_options & PCRE2_ALLOW_EMPTY_CLASS) != 0 && - new_class_mode_state < CLASS_MODE_PERL_EXT) - { - PCRE2_ASSERT(start_c == CHAR_LEFT_SQUARE_BRACKET); - - if (class_start != NULL) - { - PCRE2_ASSERT(class_depth_m1 >= 0); - /* Represents that the class is an extended class. */ - *class_start |= CLASS_IS_ECLASS; - class_start = NULL; - } - - *parsed_pattern++ = negate_class? META_CLASS_EMPTY_NOT : META_CLASS_EMPTY; - - /* Leave nesting depth unchanged; but check for zero depth to handle the - very first (top-level) class being empty. */ - if (class_depth_m1 < 0) break; - - class_range_state = RANGE_NO; /* for processing the containing class */ - class_op_state = CLASS_OP_OPERAND; - goto CLASS_CONTINUE; - } - - /* Enter a non-empty class. */ - - if (class_start != NULL) - { - PCRE2_ASSERT(class_depth_m1 >= 0); - /* Represents that the class is an extended class. */ - *class_start |= CLASS_IS_ECLASS; - class_start = NULL; - } - - class_start = parsed_pattern; - *parsed_pattern++ = negate_class? META_CLASS_NOT : META_CLASS; - class_range_state = RANGE_NO; - class_op_state = CLASS_OP_EMPTY; - class_mode_state = new_class_mode_state; - ++class_depth_m1; - if (class_maxdepth_m1 < class_depth_m1) - class_maxdepth_m1 = class_depth_m1; - /* Reset; no op seen yet at new depth. */ - cb->class_op_used[class_depth_m1] = 0; - - /* Implement the special start-of-class literal meaning of ']'. */ - if (c == CHAR_RIGHT_SQUARE_BRACKET && - new_class_mode_state != CLASS_MODE_PERL_EXT) - { - class_range_state = RANGE_OK_LITERAL; - class_op_state = CLASS_OP_OPERAND; - PARSED_LITERAL(c, parsed_pattern); - goto CLASS_CONTINUE; - } - - continue; /* We have already loaded c with the next character */ - } - - /* Check for the end of the class. */ - - else if (c == CHAR_RIGHT_SQUARE_BRACKET || - (c == CHAR_RIGHT_PARENTHESIS && class_mode_state == CLASS_MODE_PERL_EXT)) - { - /* In Perl extended mode, the ']' can only be used to match the - opening '[', and ')' must match an opening parenthesis. */ - if (class_mode_state == CLASS_MODE_PERL_EXT) - { - if (c == CHAR_RIGHT_SQUARE_BRACKET && class_depth_m1 != 0) - { - errorcode = ERR14; + errorcode = ERR8; goto FAILED_BACK; } - if (c == CHAR_RIGHT_PARENTHESIS && class_depth_m1 < 1) - { - errorcode = ERR22; - goto FAILED; - } - } - - /* Check no trailing operator. */ - if (class_op_state == CLASS_OP_OPERATOR) - { - errorcode = ERR110; - goto FAILED; - } - - /* Check no empty expression for Perl extended expressions. */ - if (class_mode_state == CLASS_MODE_PERL_EXT && - class_op_state == CLASS_OP_EMPTY) - { - errorcode = ERR114; - goto FAILED; - } - - /* -] at the end of a class is a literal '-' */ - if (class_range_state == RANGE_STARTED) - parsed_pattern[-1] = CHAR_MINUS; - - *parsed_pattern++ = META_CLASS_END; - - if (--class_depth_m1 < 0) - { - /* Check for and consume ')' after '(?[...]'. */ - PCRE2_ASSERT(class_mode_state != CLASS_MODE_PERL_EXT_LEAF); - if (class_mode_state == CLASS_MODE_PERL_EXT) + else { - if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS) - { - errorcode = ERR115; - goto FAILED; - } - - ptr++; + if (!char_is_literal && parsed_pattern[-1] == META_RANGE_LITERAL) + parsed_pattern[-1] = META_RANGE_ESCAPED; + PARSED_LITERAL(c, parsed_pattern); } - - break; - } - - class_range_state = RANGE_NO; /* for processing the containing class */ - class_op_state = CLASS_OP_OPERAND; - if (class_mode_state == CLASS_MODE_PERL_EXT_LEAF) - class_mode_state = CLASS_MODE_PERL_EXT; - /* The extended class flag has already - been set for the parent class. */ - class_start = NULL; - } - - /* Handle a Perl set binary operator */ - - else if (class_mode_state == CLASS_MODE_PERL_EXT && - (c == CHAR_PLUS || c == CHAR_VERTICAL_LINE || c == CHAR_MINUS || - c == CHAR_AMPERSAND || c == CHAR_CIRCUMFLEX_ACCENT)) - { - /* Check that there was a preceding operand. */ - if (class_op_state != CLASS_OP_OPERAND) - { - errorcode = ERR109; - goto FAILED; - } - - if (class_start != NULL) - { - PCRE2_ASSERT(class_depth_m1 >= 0); - /* Represents that the class is an extended class. */ - *class_start |= CLASS_IS_ECLASS; - class_start = NULL; - } - - PCRE2_ASSERT(class_range_state != RANGE_STARTED && - class_range_state != RANGE_FORBID_STARTED); - - *parsed_pattern++ = c == CHAR_PLUS? META_ECLASS_OR : - c == CHAR_VERTICAL_LINE? META_ECLASS_OR : - c == CHAR_MINUS? META_ECLASS_SUB : - c == CHAR_AMPERSAND? META_ECLASS_AND : - META_ECLASS_XOR; - class_range_state = RANGE_NO; - class_op_state = CLASS_OP_OPERATOR; - } - - /* Handle a Perl set unary operator */ - - else if (class_mode_state == CLASS_MODE_PERL_EXT && - c == CHAR_EXCLAMATION_MARK) - { - /* Check that the "!" has not got a preceding operand (i.e. it's the - start of the class, or follows an operator). */ - if (class_op_state == CLASS_OP_OPERAND) - { - errorcode = ERR113; - goto FAILED; - } - - if (class_start != NULL) - { - PCRE2_ASSERT(class_depth_m1 >= 0); - /* Represents that the class is an extended class. */ - *class_start |= CLASS_IS_ECLASS; - class_start = NULL; - } - - PCRE2_ASSERT(class_range_state != RANGE_STARTED && - class_range_state != RANGE_FORBID_STARTED); - - *parsed_pattern++ = META_ECLASS_NOT; - class_range_state = RANGE_NO; - class_op_state = CLASS_OP_OPERATOR; - } - - /* Handle a UTS#18 set operator */ - - else if (class_mode_state == CLASS_MODE_ALT_EXT && - (c == CHAR_VERTICAL_LINE || c == CHAR_MINUS || - c == CHAR_AMPERSAND || c == CHAR_TILDE) && - ptr < ptrend && *ptr == c) - { - ++ptr; - - /* Check there isn't a triple-repetition. */ - if (ptr < ptrend && *ptr == c) - { - while (ptr < ptrend && *ptr == c) ++ptr; /* Improve error offset. */ - errorcode = ERR108; - goto FAILED; - } - - /* Check for a preceding operand. */ - if (class_op_state != CLASS_OP_OPERAND) - { - errorcode = ERR109; - goto FAILED; - } - - /* Check for mixed precedence. Forbid [A--B&&C]. */ - if (cb->class_op_used[class_depth_m1] != 0 && - cb->class_op_used[class_depth_m1] != (uint8_t)c) - { - errorcode = ERR111; - goto FAILED; + class_range_state = RANGE_NO; } - - if (class_start != NULL) + else /* Potential start of range */ { - PCRE2_ASSERT(class_depth_m1 >= 0); - /* Represents that the class is an extended class. */ - *class_start |= CLASS_IS_ECLASS; - class_start = NULL; + class_range_state = char_is_literal? + RANGE_OK_LITERAL : RANGE_OK_ESCAPED; + PARSED_LITERAL(c, parsed_pattern); } - - /* Dangling '-' before an operator is a literal */ - if (class_range_state == RANGE_STARTED) - parsed_pattern[-1] = CHAR_MINUS; - - *parsed_pattern++ = c == CHAR_VERTICAL_LINE? META_ECLASS_OR : - c == CHAR_MINUS? META_ECLASS_SUB : - c == CHAR_AMPERSAND? META_ECLASS_AND : - META_ECLASS_XOR; - class_range_state = RANGE_NO; - class_op_state = CLASS_OP_OPERATOR; - cb->class_op_used[class_depth_m1] = (uint8_t)c; } /* Handle escapes in a class */ - else if (c == CHAR_BACKSLASH) + else { tempptr = ptr; escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode, options, - xoptions, cb->bracount, TRUE, cb); + xoptions, TRUE, cb); if (errorcode != 0) { - if ((xoptions & PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL) == 0 || - class_mode_state >= CLASS_MODE_PERL_EXT) + if ((xoptions & PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL) == 0) goto FAILED; ptr = tempptr; if (ptr >= ptrend) c = CHAR_BACKSLASH; else @@ -4285,11 +3797,6 @@ while (ptr < ptrend) char_is_literal = FALSE; goto CLASS_LITERAL; - case ESC_k: - c = CHAR_k; /* \k is not special in a class, just like \g */ - char_is_literal = FALSE; - goto CLASS_LITERAL; - case ESC_Q: inescq = TRUE; /* Enter literal mode */ goto CLASS_CONTINUE; @@ -4301,10 +3808,29 @@ while (ptr < ptrend) case ESC_R: case ESC_X: errorcode = ERR7; - ptr--; // TODO https://github.com/PCRE2Project/pcre2/issues/549 + ptr--; goto FAILED; + } - case ESC_N: /* Not permitted by Perl either */ + /* The second part of a range can be a single-character escape + sequence (detected above), but not any of the other escapes. Perl + treats a hyphen as a literal in such circumstances. However, in Perl's + warning mode, a warning is given, so PCRE now faults it, as it is + almost certainly a mistake on the user's part. */ + + if (class_range_state == RANGE_STARTED) + { + errorcode = ERR50; + goto FAILED; /* Not CLASS_ESCAPE_FAILED; always an error */ + } + + /* Of the remaining escapes, only those that define characters are + allowed in a class. None may start a range. */ + + class_range_state = RANGE_NO; + switch(escape) + { + case ESC_N: errorcode = ERR71; goto FAILED; @@ -4338,18 +3864,6 @@ while (ptr < ptrend) uint16_t ptype = 0, pdata = 0; if (!get_ucp(&ptr, &negated, &ptype, &pdata, &errorcode, cb)) goto FAILED; - - /* In caseless matching, particular characteristics Lu, Ll, and Lt - get converted to the general characteristic L&. That is, upper, - lower, and title case letters are all conflated. */ - - if ((options & PCRE2_CASELESS) != 0 && ptype == PT_PC && - (pdata == ucp_Lu || pdata == ucp_Ll || pdata == ucp_Lt)) - { - ptype = PT_LAMP; - pdata = 0; - } - if (negated) escape = (escape == ESC_P)? ESC_p : ESC_P; *parsed_pattern++ = META_ESCAPE + escape; *parsed_pattern++ = (ptype << 16) | pdata; @@ -4360,134 +3874,21 @@ while (ptr < ptrend) #endif break; /* End \P and \p */ - /* All others are not allowed in a class */ - - default: - PCRE2_DEBUG_UNREACHABLE(); - /* Fall through */ - - case ESC_A: - case ESC_Z: - case ESC_z: - case ESC_G: - case ESC_K: - case ESC_C: + default: /* All others are not allowed in a class */ errorcode = ERR7; - ptr--; // TODO https://github.com/PCRE2Project/pcre2/issues/549 - goto FAILED; - } - - /* All the switch-cases above which end in "break" describe a set - of characters. None may start a range. */ - - /* The second part of a range can be a single-character escape - sequence (detected above), but not any of the other escapes. Perl - treats a hyphen as a literal in such circumstances. However, in Perl's - warning mode, a warning is given, so PCRE now faults it, as it is - almost certainly a mistake on the user's part. */ - - if (class_range_state == RANGE_STARTED) - { - errorcode = ERR50; - goto FAILED; - } - - /* Perl gives a warning unless the hyphen following a multi-character - escape is the last character in the class. PCRE throws an error. */ - - if (class_range_state == RANGE_FORBID_STARTED) - { - ptr = class_range_forbid_ptr; - errorcode = ERR50; - goto FAILED; - } - - /* Disallow implicit union in Perl extended classes. */ - - if (class_op_state == CLASS_OP_OPERAND && - class_mode_state == CLASS_MODE_PERL_EXT) - { - errorcode = ERR113; + ptr--; goto FAILED; } - class_range_state = RANGE_FORBID_NO; - class_op_state = CLASS_OP_OPERAND; - } + /* Perl gives a warning unless a following hyphen is the last character + in the class. PCRE throws an error. */ - /* Forbid unescaped literals, and the special meaning of '-', inside a - Perl extended class. */ - - else if (class_mode_state == CLASS_MODE_PERL_EXT) - { - errorcode = ERR116; - goto FAILED; - } - - /* Handle potential start of range */ - - else if (c == CHAR_MINUS && class_range_state >= RANGE_OK_ESCAPED) - { - *parsed_pattern++ = (class_range_state == RANGE_OK_LITERAL)? - META_RANGE_LITERAL : META_RANGE_ESCAPED; - class_range_state = RANGE_STARTED; - } - - /* Handle forbidden start of range */ - - else if (c == CHAR_MINUS && class_range_state == RANGE_FORBID_NO) - { - *parsed_pattern++ = CHAR_MINUS; - class_range_state = RANGE_FORBID_STARTED; - class_range_forbid_ptr = ptr; - } - - /* Handle a literal character */ - - else - { - CLASS_LITERAL: - - /* Disallow implicit union in Perl extended classes. */ - - if (class_op_state == CLASS_OP_OPERAND && - class_mode_state == CLASS_MODE_PERL_EXT) - { - errorcode = ERR113; - goto FAILED; - } - - if (class_range_state == RANGE_STARTED) - { - if (c == parsed_pattern[-2]) /* Optimize one-char range */ - parsed_pattern--; - else if (parsed_pattern[-2] > c) /* Check range is in order */ - { - errorcode = ERR8; - goto FAILED_BACK; // TODO https://github.com/PCRE2Project/pcre2/issues/549 - } - else - { - if (!char_is_literal && parsed_pattern[-1] == META_RANGE_LITERAL) - parsed_pattern[-1] = META_RANGE_ESCAPED; - PARSED_LITERAL(c, parsed_pattern); - } - class_range_state = RANGE_NO; - class_op_state = CLASS_OP_OPERAND; - } - else if (class_range_state == RANGE_FORBID_STARTED) + if (ptr < ptrend - 1 && *ptr == CHAR_MINUS && + ptr[1] != CHAR_RIGHT_SQUARE_BRACKET) { - ptr = class_range_forbid_ptr; errorcode = ERR50; goto FAILED; } - else /* Potential start of range */ - { - class_range_state = char_is_literal? - RANGE_OK_LITERAL : RANGE_OK_ESCAPED; - class_op_state = CLASS_OP_OPERAND; - PARSED_LITERAL(c, parsed_pattern); - } } /* Proceed to next thing in the class. */ @@ -4495,18 +3896,22 @@ while (ptr < ptrend) CLASS_CONTINUE: if (ptr >= ptrend) { - if (class_mode_state == CLASS_MODE_PERL_EXT && class_depth_m1 > 0) - errorcode = ERR14; /* Missing terminating ')' */ - if (class_mode_state == CLASS_MODE_ALT_EXT && - class_depth_m1 == 0 && class_maxdepth_m1 == 1) - errorcode = ERR112; /* Missing terminating ']', but we saw '[ [ ]...' */ - else - errorcode = ERR6; /* Missing terminating ']' */ + errorcode = ERR6; /* Missing terminating ']' */ goto FAILED; } GETCHARINCTEST(c, ptr); + if (c == CHAR_RIGHT_SQUARE_BRACKET && !inescq) break; } /* End of class-processing loop */ + /* -] at the end of a class is a literal '-' */ + + if (class_range_state == RANGE_STARTED) + { + parsed_pattern[-1] = CHAR_MINUS; + class_range_state = RANGE_NO; + } + + *parsed_pattern++ = META_CLASS_END; break; /* End of character class */ @@ -4589,7 +3994,8 @@ while (ptr < ptrend) if (prev_expect_cond_assert > 0 && (meta < META_LOOKAHEAD || meta > META_LOOKBEHINDNOT)) { - errorcode = ERR28; /* Atomic assertion expected */ + errorcode = (meta == META_LOOKAHEAD_NA || meta == META_LOOKBEHIND_NA)? + ERR98 : ERR28; /* (Atomic) assertion expected */ goto FAILED; } @@ -4599,7 +4005,6 @@ while (ptr < ptrend) switch(meta) { default: - PCRE2_DEBUG_UNREACHABLE(); errorcode = ERR89; /* Unknown code; should never occur because */ goto FAILED; /* the meta values come from a table above. */ @@ -4615,90 +4020,6 @@ while (ptr < ptrend) case META_LOOKAHEADNOT: goto NEGATIVE_LOOK_AHEAD; - case META_SCS: - if (++ptr >= ptrend) goto UNCLOSED_PARENTHESIS; - - if (*ptr != CHAR_LEFT_PARENTHESIS) - { - errorcode = ERR15; - goto FAILED; - } - - ptr++; - *parsed_pattern++ = META_SCS; - /* Temporary variable, zero in the first iteration. */ - offset = 0; - - for (;;) - { - PCRE2_SIZE next_offset = (PCRE2_SIZE)(ptr - cb->start_pattern); - - /* Handle (scan_substring:([+-]number)... */ - if (read_number(&ptr, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61, - &i, &errorcode)) - { - PCRE2_ASSERT(i >= 0); - if (i <= 0) - { - errorcode = ERR15; - goto FAILED; - } - meta = META_SCS_NUMBER; - namelen = (uint32_t)i; - } - else if (errorcode != 0) goto FAILED; /* Number too big */ - else - { - if (ptr >= ptrend) goto UNCLOSED_PARENTHESIS; - - /* Handle (*scan_substring:('name') or (*scan_substring:() */ - if (*ptr == CHAR_LESS_THAN_SIGN) - terminator = CHAR_GREATER_THAN_SIGN; - else if (*ptr == CHAR_APOSTROPHE) - terminator = CHAR_APOSTROPHE; - else - { - errorcode = ERR15; - goto FAILED; - } - - if (!read_name(&ptr, ptrend, utf, terminator, &next_offset, - &name, &namelen, &errorcode, cb)) goto FAILED; - - meta = META_SCS_NAME; - } - - PCRE2_ASSERT(next_offset > 0); - if (offset == 0 || (next_offset - offset) >= 0x10000) - { - *parsed_pattern++ = META_OFFSET; - PUTOFFSET(next_offset, parsed_pattern); - offset = next_offset; - } - - /* The offset is encoded as a relative offset, because for some - inputs such as ",2" in (*scs:(1,2,3)...), we only have space for - two uint32_t values, and an opcode and absolute offset may require - three uint32_t values. */ - *parsed_pattern++ = meta | (uint32_t)(next_offset - offset); - *parsed_pattern++ = namelen; - offset = next_offset; - - if (ptr >= ptrend) goto UNCLOSED_PARENTHESIS; - - if (*ptr == CHAR_RIGHT_PARENTHESIS) break; - - if (*ptr != CHAR_COMMA) - { - errorcode = ERR24; - goto FAILED; - } - - ptr++; - } - ptr++; - goto POST_ASSERTION; - case META_LOOKBEHIND: case META_LOOKBEHINDNOT: case META_LOOKBEHIND_NA: @@ -4730,12 +4051,6 @@ while (ptr < ptrend) top_nest->flags = NSF_ATOMICSR; top_nest->options = options & PARSE_TRACKED_OPTIONS; top_nest->xoptions = xoptions & PARSE_TRACKED_EXTRA_OPTIONS; - -#ifdef PCRE2_DEBUG - /* We'll write out two META_KETs for a single ")" in the input - pattern, so we reserve space for that in our bounds check. */ - parsed_pattern_extra++; -#endif } break; #else /* SUPPORT_UNICODE */ @@ -4795,11 +4110,6 @@ while (ptr < ptrend) verbstartptr = parsed_pattern; okquantifier = (verbs[i].meta == META_ACCEPT); -#ifdef PCRE2_DEBUG - /* Reserve space in our bounds check for optionally wrapping the (*ACCEPT) - with a non-capturing bracket, if there is a following quantifier. */ - if (okquantifier) parsed_pattern_extra += 2; -#endif /* It appears that Perl allows any characters whatsoever, other than a closing parenthesis, to appear in arguments ("names"), so we no longer @@ -5107,7 +4417,11 @@ while (ptr < ptrend) (IS_DIGIT(*ptr))? -1:(int)(cb->bracount), /* + and - are relative */ MAX_GROUP_NUMBER, ERR61, &i, &errorcode)) goto FAILED; - PCRE2_ASSERT(i >= 0); /* NB (?0) is permitted, represented by i=0 */ + if (i < 0) /* NB (?0) is permitted */ + { + errorcode = ERR15; /* Unknown group */ + goto FAILED_BACK; + } if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS) goto UNCLOSED_PARENTHESIS; @@ -5135,12 +4449,6 @@ while (ptr < ptrend) /* ---- Callout with numerical or string argument ---- */ case CHAR_C: - if ((xoptions & PCRE2_EXTRA_NEVER_CALLOUT) != 0) - { - errorcode = ERR103; - goto FAILED; - } - if (++ptr >= ptrend) goto UNCLOSED_PARENTHESIS; /* If the previous item was a condition starting (?(? an assertion, @@ -5228,7 +4536,7 @@ while (ptr < ptrend) parsed_pattern += 3; /* Skip pattern info */ while (ptr < ptrend && IS_DIGIT(*ptr)) { - n = n * 10 + (*ptr++ - CHAR_0); + n = n * 10 + *ptr++ - CHAR_0; if (n > 255) { errorcode = ERR38; @@ -5299,7 +4607,6 @@ while (ptr < ptrend) if (read_number(&ptr, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61, &i, &errorcode)) { - PCRE2_ASSERT(i >= 0); if (i <= 0) { errorcode = ERR15; @@ -5450,7 +4757,7 @@ while (ptr < ptrend) goto POST_ASSERTION; case CHAR_ASTERISK: - POSITIVE_NONATOMIC_LOOK_AHEAD: /* Come from (*napla: */ + POSITIVE_NONATOMIC_LOOK_AHEAD: /* Come from (?* */ *parsed_pattern++ = META_LOOKAHEAD_NA; ptr++; goto POST_ASSERTION; @@ -5615,18 +4922,6 @@ while (ptr < ptrend) cb->named_groups[cb->names_found].isdup = (uint16_t)isdupname; cb->names_found++; break; - - - /* ---- Perl extended character class ---- */ - - /* These are of the form '(?[...])'. We handle these via the same parser - that consumes ordinary '[...]' classes, but with a flag set to activate - the extended behaviour. */ - - case CHAR_LEFT_SQUARE_BRACKET: - class_mode_state = CLASS_MODE_PERL_EXT; - c = *ptr++; - goto FROM_PERL_EXTENDED_CLASS; } /* End of (? switch */ break; /* End of ( handling */ @@ -5665,11 +4960,6 @@ while (ptr < ptrend) if ((top_nest->flags & NSF_ATOMICSR) != 0) { *parsed_pattern++ = META_KET; - -#ifdef PCRE2_DEBUG - PCRE2_ASSERT(parsed_pattern_extra > 0); - parsed_pattern_extra--; -#endif } if (top_nest == (nest_save *)(cb->start_workspace)) top_nest = NULL; @@ -5678,7 +4968,7 @@ while (ptr < ptrend) if (nest_depth == 0) /* Unmatched closing parenthesis */ { errorcode = ERR22; - goto FAILED_BACK; // TODO https://github.com/PCRE2Project/pcre2/issues/549 + goto FAILED_BACK; } nest_depth--; *parsed_pattern++ = META_KET; @@ -5694,15 +4984,9 @@ if (inverbname && ptr >= ptrend) goto FAILED; } - -PARSED_END: - -PCRE2_ASSERT((parsed_pattern - parsed_pattern_check) + - (parsed_pattern_extra - parsed_pattern_extra_check) <= - max_parsed_pattern(ptr_check, ptr, utf, options)); - /* Manage callout for the final item */ +PARSED_END: parsed_pattern = manage_callouts(ptr, &previous_callout, auto_callout, parsed_pattern, cb); @@ -5725,7 +5009,6 @@ Otherwise we have unclosed parentheses. */ if (parsed_pattern >= parsed_pattern_end) { - PCRE2_DEBUG_UNREACHABLE(); errorcode = ERR63; /* Internal error (parsed pattern overflow) */ goto FAILED; } @@ -5831,12 +5114,419 @@ for (;;) code += code[1] + PRIV(OP_lengths)[*code]; break; - default: - return code; + default: + return code; + } + } +/* Control never reaches here */ +} + + + +#ifdef SUPPORT_UNICODE +/************************************************* +* Get othercase range * +*************************************************/ + +/* This function is passed the start and end of a class range in UCP mode. For +single characters the range may be just one character long. The function +searches up the characters, looking for ranges of characters in the "other" +case. Each call returns the next one, updating the start address. A character +with multiple other cases is returned on its own with a special return value. + +Arguments: + cptr points to starting character value; updated + d end value + ocptr where to put start of othercase range + odptr where to put end of othercase range + restricted TRUE if caseless restriction applies + +Yield: -1 when no more + 0 when a range is returned + >0 the CASESET offset for char with multiple other cases; + for this return, *ocptr contains the original +*/ + +static int +get_othercase_range(uint32_t *cptr, uint32_t d, uint32_t *ocptr, + uint32_t *odptr, BOOL restricted) +{ +uint32_t c, othercase, next; +unsigned int co; + +/* Find the first character that has an other case. If it has multiple other +cases, return its case offset value. When CASELESS_RESTRICT is set, ignore the +multi-case entries that begin with ASCII values. In 32-bit mode, a value +greater than the Unicode maximum ends the range. */ + +for (c = *cptr; c <= d; c++) + { +#if PCRE2_CODE_UNIT_WIDTH == 32 + if (c > MAX_UTF_CODE_POINT) return -1; +#endif + if ((co = UCD_CASESET(c)) != 0 && + (!restricted || PRIV(ucd_caseless_sets)[co] > 127)) + { + *ocptr = c++; /* Character that has the set */ + *cptr = c; /* Rest of input range */ + return (int)co; + } + + /* This is not a valid multiple-case character. Check that the single other + case is different to the original. We don't need to check "restricted" here + because the non-ASCII characters with multiple cases that include an ASCII + character don't have a different "othercase". */ + + if ((othercase = UCD_OTHERCASE(c)) != c) break; + } + +if (c > d) return -1; /* Reached end of range */ + +/* Found a character that has a single other case. Search for the end of the +range, which is either the end of the input range, or a character that has zero +or more than one other cases. */ + +*ocptr = othercase; +next = othercase + 1; + +for (++c; c <= d; c++) + { + if ((co = UCD_CASESET(c)) != 0 || UCD_OTHERCASE(c) != next) break; + next++; + } + +*odptr = next - 1; /* End of othercase range */ +*cptr = c; /* Rest of input range */ +return 0; +} +#endif /* SUPPORT_UNICODE */ + + + +/************************************************* +* Add a character or range to a class (internal) * +*************************************************/ + +/* This function packages up the logic of adding a character or range of +characters to a class. The character values in the arguments will be within the +valid values for the current mode (8-bit, 16-bit, UTF, etc). This function is +called only from within the "add to class" group of functions, some of which +are recursive and mutually recursive. The external entry point is +add_to_class(). + +Arguments: + classbits the bit map for characters < 256 + uchardptr points to the pointer for extra data + options the options bits + xoptions the extra options bits + cb compile data + start start of range character + end end of range character + +Returns: the number of < 256 characters added + the pointer to extra data is updated +*/ + +static unsigned int +add_to_class_internal(uint8_t *classbits, PCRE2_UCHAR **uchardptr, + uint32_t options, uint32_t xoptions, compile_block *cb, uint32_t start, + uint32_t end) +{ +uint32_t c; +uint32_t classbits_end = (end <= 0xff ? end : 0xff); +unsigned int n8 = 0; + +/* If caseless matching is required, scan the range and process alternate +cases. In Unicode, there are 8-bit characters that have alternate cases that +are greater than 255 and vice-versa (though these may be ignored if caseless +restriction is in force). Sometimes we can just extend the original range. */ + +if ((options & PCRE2_CASELESS) != 0) + { +#ifdef SUPPORT_UNICODE + if ((options & (PCRE2_UTF|PCRE2_UCP)) != 0) + { + int rc; + uint32_t oc, od; + + options &= ~PCRE2_CASELESS; /* Remove for recursive calls */ + c = start; + + while ((rc = get_othercase_range(&c, end, &oc, &od, + (xoptions & PCRE2_EXTRA_CASELESS_RESTRICT) != 0)) >= 0) + { + /* Handle a single character that has more than one other case. */ + + if (rc > 0) n8 += add_list_to_class_internal(classbits, uchardptr, + options, xoptions, cb, PRIV(ucd_caseless_sets) + rc, oc); + + /* Do nothing if the other case range is within the original range. */ + + else if (oc >= cb->class_range_start && od <= cb->class_range_end) + continue; + + /* Extend the original range if there is overlap, noting that if oc < c, + we can't have od > end because a subrange is always shorter than the + basic range. Otherwise, use a recursive call to add the additional range. + */ + + else if (oc < start && od >= start - 1) start = oc; /* Extend downwards */ + else if (od > end && oc <= end + 1) + { + end = od; /* Extend upwards */ + if (end > classbits_end) classbits_end = (end <= 0xff ? end : 0xff); + } + else n8 += add_to_class_internal(classbits, uchardptr, options, xoptions, + cb, oc, od); + } + } + else +#else + (void)xoptions; /* Avoid compiler warning */ +#endif /* SUPPORT_UNICODE */ + + /* Not UTF mode */ + + for (c = start; c <= classbits_end; c++) + { + SETBIT(classbits, cb->fcc[c]); + n8++; + } + } + +/* Now handle the originally supplied range. Adjust the final value according +to the bit length - this means that the same lists of (e.g.) horizontal spaces +can be used in all cases. */ + +if ((options & PCRE2_UTF) == 0 && end > MAX_NON_UTF_CHAR) + end = MAX_NON_UTF_CHAR; + +if (start > cb->class_range_start && end < cb->class_range_end) return n8; + +/* Use the bitmap for characters < 256. Otherwise use extra data.*/ + +for (c = start; c <= classbits_end; c++) + { + /* Regardless of start, c will always be <= 255. */ + SETBIT(classbits, c); + n8++; + } + +#ifdef SUPPORT_WIDE_CHARS +if (start <= 0xff) start = 0xff + 1; + +if (end >= start) + { + PCRE2_UCHAR *uchardata = *uchardptr; + +#ifdef SUPPORT_UNICODE + if ((options & PCRE2_UTF) != 0) + { + if (start < end) + { + *uchardata++ = XCL_RANGE; + uchardata += PRIV(ord2utf)(start, uchardata); + uchardata += PRIV(ord2utf)(end, uchardata); + } + else if (start == end) + { + *uchardata++ = XCL_SINGLE; + uchardata += PRIV(ord2utf)(start, uchardata); + } + } + else +#endif /* SUPPORT_UNICODE */ + + /* Without UTF support, character values are constrained by the bit length, + and can only be > 256 for 16-bit and 32-bit libraries. */ + +#if PCRE2_CODE_UNIT_WIDTH == 8 + {} +#else + if (start < end) + { + *uchardata++ = XCL_RANGE; + *uchardata++ = start; + *uchardata++ = end; + } + else if (start == end) + { + *uchardata++ = XCL_SINGLE; + *uchardata++ = start; + } +#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */ + *uchardptr = uchardata; /* Updata extra data pointer */ + } +#else /* SUPPORT_WIDE_CHARS */ + (void)uchardptr; /* Avoid compiler warning */ +#endif /* SUPPORT_WIDE_CHARS */ + +return n8; /* Number of 8-bit characters */ +} + + + +#ifdef SUPPORT_UNICODE +/************************************************* +* Add a list of characters to a class (internal) * +*************************************************/ + +/* This function is used for adding a list of case-equivalent characters to a +class when in UTF mode. This function is called only from within +add_to_class_internal(), with which it is mutually recursive. + +Arguments: + classbits the bit map for characters < 256 + uchardptr points to the pointer for extra data + options the options bits + xoptions the extra options bits + cb contains pointers to tables etc. + p points to row of 32-bit values, terminated by NOTACHAR + except character to omit; this is used when adding lists of + case-equivalent characters to avoid including the one we + already know about + +Returns: the number of < 256 characters added + the pointer to extra data is updated +*/ + +static unsigned int +add_list_to_class_internal(uint8_t *classbits, PCRE2_UCHAR **uchardptr, + uint32_t options, uint32_t xoptions, compile_block *cb, const uint32_t *p, + unsigned int except) +{ +unsigned int n8 = 0; +while (p[0] < NOTACHAR) + { + unsigned int n = 0; + if (p[0] != except) + { + while(p[n+1] == p[0] + n + 1) n++; + n8 += add_to_class_internal(classbits, uchardptr, options, xoptions, cb, + p[0], p[n]); + } + p += n + 1; + } +return n8; +} +#endif + + + +/************************************************* +* External entry point for add range to class * +*************************************************/ + +/* This function sets the overall range so that the internal functions can try +to avoid duplication when handling case-independence. + +Arguments: + classbits the bit map for characters < 256 + uchardptr points to the pointer for extra data + options the options bits + xoptions the extra options bits + cb compile data + start start of range character + end end of range character + +Returns: the number of < 256 characters added + the pointer to extra data is updated +*/ + +static unsigned int +add_to_class(uint8_t *classbits, PCRE2_UCHAR **uchardptr, uint32_t options, + uint32_t xoptions, compile_block *cb, uint32_t start, uint32_t end) +{ +cb->class_range_start = start; +cb->class_range_end = end; +return add_to_class_internal(classbits, uchardptr, options, xoptions, cb, + start, end); +} + + +/************************************************* +* External entry point for add list to class * +*************************************************/ + +/* This function is used for adding a list of horizontal or vertical whitespace +characters to a class. The list must be in order so that ranges of characters +can be detected and handled appropriately. This function sets the overall range +so that the internal functions can try to avoid duplication when handling +case-independence. + +Arguments: + classbits the bit map for characters < 256 + uchardptr points to the pointer for extra data + options the options bits + xoptions the extra options bits + cb contains pointers to tables etc. + p points to row of 32-bit values, terminated by NOTACHAR + except character to omit; this is used when adding lists of + case-equivalent characters to avoid including the one we + already know about + +Returns: the number of < 256 characters added + the pointer to extra data is updated +*/ + +static unsigned int +add_list_to_class(uint8_t *classbits, PCRE2_UCHAR **uchardptr, uint32_t options, + uint32_t xoptions, compile_block *cb, const uint32_t *p, unsigned int except) +{ +unsigned int n8 = 0; +while (p[0] < NOTACHAR) + { + unsigned int n = 0; + if (p[0] != except) + { + while(p[n+1] == p[0] + n + 1) n++; + cb->class_range_start = p[0]; + cb->class_range_end = p[n]; + n8 += add_to_class_internal(classbits, uchardptr, options, xoptions, cb, + p[0], p[n]); } + p += n + 1; } +return n8; +} + + -PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */ +/************************************************* +* Add characters not in a list to a class * +*************************************************/ + +/* This function is used for adding the complement of a list of horizontal or +vertical whitespace to a class. The list must be in order. + +Arguments: + classbits the bit map for characters < 256 + uchardptr points to the pointer for extra data + options the options bits + xoptions the extra options bits + cb contains pointers to tables etc. + p points to row of 32-bit values, terminated by NOTACHAR + +Returns: the number of < 256 characters added + the pointer to extra data is updated +*/ + +static unsigned int +add_not_list_to_class(uint8_t *classbits, PCRE2_UCHAR **uchardptr, + uint32_t options, uint32_t xoptions, compile_block *cb, const uint32_t *p) +{ +BOOL utf = (options & PCRE2_UTF) != 0; +unsigned int n8 = 0; +if (p[0] > 0) + n8 += add_to_class(classbits, uchardptr, options, xoptions, cb, 0, p[0] - 1); +while (p[0] < NOTACHAR) + { + while (p[1] == p[0] + 1) p++; + n8 += add_to_class(classbits, uchardptr, options, xoptions, cb, p[0] + 1, + (p[1] == NOTACHAR) ? (utf ? 0x10ffffu : 0xffffffffu) : p[1] - 1); + p++; + } +return n8; } @@ -5882,7 +5572,6 @@ have duplicate names. Give an internal error. */ if (i >= cb->names_found) { - PCRE2_DEBUG_UNREACHABLE(); *errorcodeptr = ERR53; cb->erroroffset = name - cb->start_pattern; return FALSE; @@ -5960,13 +5649,12 @@ uint32_t options = *optionsptr; /* May change dynamically */ uint32_t xoptions = *xoptionsptr; /* May change dynamically */ uint32_t firstcu, reqcu; uint32_t zeroreqcu, zerofirstcu; +uint32_t escape; uint32_t *pptr = *pptrptr; uint32_t meta, meta_arg; uint32_t firstcuflags, reqcuflags; uint32_t zeroreqcuflags, zerofirstcuflags; uint32_t req_caseopt, reqvary, tempreqvary; -/* Some opcodes, such as META_SCS_NUMBER or META_SCS_NAME, -depends on the previous value of offset. */ PCRE2_SIZE offset = 0; PCRE2_SIZE length_prevgroup = 0; PCRE2_UCHAR *code = *codeptr; @@ -5980,6 +5668,8 @@ BOOL had_accept = FALSE; BOOL matched_char = FALSE; BOOL previous_matched_char = FALSE; BOOL reset_caseful = FALSE; +const uint8_t *cbits = cb->cbits; +uint8_t classbits[32]; /* We can fish out the UTF setting once and for all into a BOOL, but we must not do this for other options (e.g. PCRE2_EXTENDED) that may change dynamically @@ -5992,6 +5682,17 @@ BOOL ucp = (options & PCRE2_UCP) != 0; BOOL utf = FALSE; #endif +/* Helper variables for OP_XCLASS opcode (for characters > 255). We define +class_uchardata always so that it can be passed to add_to_class() always, +though it will not be used in non-UTF 8-bit cases. This avoids having to supply +alternative calls for the different cases. */ + +PCRE2_UCHAR *class_uchardata; +#ifdef SUPPORT_WIDE_CHARS +BOOL xclass; +PCRE2_UCHAR *class_uchardata_base; +#endif + /* Set up the default and non-default settings for greediness */ greedy_default = ((options & PCRE2_UNGREEDY) != 0); @@ -6021,8 +5722,15 @@ req_caseopt = ((options & PCRE2_CASELESS) != 0)? REQ_CASELESS : 0; for (;; pptr++) { +#ifdef SUPPORT_WIDE_CHARS + BOOL xclass_has_prop; +#endif + BOOL negate_class; + BOOL should_flip_negation; + BOOL match_all_or_no_wide_chars; BOOL possessive_quantifier; BOOL note_group_empty; + int class_has_8bitchar; uint32_t mclength; uint32_t skipunits; uint32_t subreqcu, subfirstcu; @@ -6045,13 +5753,8 @@ for (;; pptr++) if (code > cb->start_workspace + cb->workspace_size - WORK_SIZE_SAFETY_MARGIN) /* Check for overrun */ { - if (code >= cb->start_workspace + cb->workspace_size) - { - PCRE2_DEBUG_UNREACHABLE(); - *errorcodeptr = ERR52; /* Over-ran workspace - internal error */ - } - else - *errorcodeptr = ERR86; + *errorcodeptr = (code >= cb->start_workspace + cb->workspace_size)? + ERR52 : ERR86; return 0; } @@ -6157,24 +5860,13 @@ for (;; pptr++) /* ===================================================================*/ /* Empty character classes are allowed if PCRE2_ALLOW_EMPTY_CLASS is set. Otherwise, an initial ']' is taken as a data character. When empty classes - are allowed, [] must generate an empty class - we have no dedicated opcode - to optimise the representation, but it's a rare case (the '(*FAIL)' - construct would be a clearer way for a pattern author to represent a - non-matching branch, but it does have different semantics to '[]' if both - are followed by a quantifier). The empty-negated [^] matches any character, - so is useful: generate OP_ALLANY for this. */ + are allowed, [] must always fail, so generate OP_FAIL, whereas [^] must + match any character, so generate OP_ALLANY. */ case META_CLASS_EMPTY: case META_CLASS_EMPTY_NOT: matched_char = TRUE; - if (meta == META_CLASS_EMPTY_NOT) *code++ = OP_ALLANY; - else - { - *code++ = OP_CLASS; - memset(code, 0, 32); - code += 32 / sizeof(PCRE2_UCHAR); - } - + *code++ = (meta == META_CLASS_EMPTY_NOT)? OP_ALLANY : OP_FAIL; if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE; zerofirstcu = firstcu; zerofirstcuflags = firstcuflags; @@ -6197,16 +5889,7 @@ for (;; pptr++) case META_CLASS_NOT: case META_CLASS: matched_char = TRUE; - - /* Check for complex extended classes and handle them separately. */ - - if ((*pptr & CLASS_IS_ECLASS) != 0) - { - if (!PRIV(compile_class_nested)(options, xoptions, &pptr, &code, - errorcodeptr, cb, lengthptr)) - return 0; - goto CLASS_END_PROCESSING; - } + negate_class = meta == META_CLASS_NOT; /* We can optimize the case of a single character in a class by generating OP_CHAR or OP_CHARI if it's positive, or OP_NOT or OP_NOTI if it's @@ -6219,6 +5902,9 @@ for (;; pptr++) if (pptr[1] < META_END && pptr[2] == META_CLASS_END) { +#ifdef SUPPORT_UNICODE + uint32_t d; +#endif uint32_t c = pptr[1]; pptr += 2; /* Move on to class end */ @@ -6228,123 +5914,573 @@ for (;; pptr++) goto NORMAL_CHAR_SET; } - /* Handle a negative one-character class */ + /* Handle a negative one-character class */ + + zeroreqcu = reqcu; + zeroreqcuflags = reqcuflags; + if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE; + zerofirstcu = firstcu; + zerofirstcuflags = firstcuflags; + + /* For caseless UTF or UCP mode, check whether this character has more + than one other case. If so, generate a special OP_NOTPROP item instead of + OP_NOTI. When restricted by PCRE2_EXTRA_CASELESS_RESTRICT, ignore any + caseless set that starts with an ASCII character. */ + +#ifdef SUPPORT_UNICODE + if ((utf||ucp) && (options & PCRE2_CASELESS) != 0 && + (d = UCD_CASESET(c)) != 0 && + ((xoptions & PCRE2_EXTRA_CASELESS_RESTRICT) == 0 || + PRIV(ucd_caseless_sets)[d] > 127)) + { + *code++ = OP_NOTPROP; + *code++ = PT_CLIST; + *code++ = d; + break; /* We are finished with this class */ + } +#endif + /* Char has only one other (usable) case, or UCP not available */ + + *code++ = ((options & PCRE2_CASELESS) != 0)? OP_NOTI: OP_NOT; + code += PUTCHAR(c, code); + break; /* We are finished with this class */ + } /* End of 1-char optimization */ + + /* Handle character classes that contain more than just one literal + character. If there are exactly two characters in a positive class, see if + they are case partners. This can be optimized to generate a caseless single + character match (which also sets first/required code units if relevant). + When casing restrictions apply, ignore a caseless set if both characters + are ASCII. */ + + if (meta == META_CLASS && pptr[1] < META_END && pptr[2] < META_END && + pptr[3] == META_CLASS_END) + { + uint32_t c = pptr[1]; + +#ifdef SUPPORT_UNICODE + if (UCD_CASESET(c) == 0 || + ((xoptions & PCRE2_EXTRA_CASELESS_RESTRICT) != 0 && + c < 128 && pptr[2] < 128)) +#endif + { + uint32_t d; + +#ifdef SUPPORT_UNICODE + if ((utf || ucp) && c > 127) d = UCD_OTHERCASE(c); else +#endif + { +#if PCRE2_CODE_UNIT_WIDTH != 8 + if (c > 255) d = c; else +#endif + d = TABLE_GET(c, cb->fcc, c); + } + + if (c != d && pptr[2] == d) + { + pptr += 3; /* Move on to class end */ + meta = c; + if ((options & PCRE2_CASELESS) == 0) + { + reset_caseful = TRUE; + options |= PCRE2_CASELESS; + req_caseopt = REQ_CASELESS; + } + goto CLASS_CASELESS_CHAR; + } + } + } + + /* If a non-extended class contains a negative special such as \S, we need + to flip the negation flag at the end, so that support for characters > 255 + works correctly (they are all included in the class). An extended class may + need to insert specific matching or non-matching code for wide characters. + */ + + should_flip_negation = match_all_or_no_wide_chars = FALSE; + + /* Extended class (xclass) will be used when characters > 255 + might match. */ + +#ifdef SUPPORT_WIDE_CHARS + xclass = FALSE; + class_uchardata = code + LINK_SIZE + 2; /* For XCLASS items */ + class_uchardata_base = class_uchardata; /* Save the start */ +#endif + + /* For optimization purposes, we track some properties of the class: + class_has_8bitchar will be non-zero if the class contains at least one + character with a code point less than 256; xclass_has_prop will be TRUE if + Unicode property checks are present in the class. */ + + class_has_8bitchar = 0; +#ifdef SUPPORT_WIDE_CHARS + xclass_has_prop = FALSE; +#endif + + /* Initialize the 256-bit (32-byte) bit map to all zeros. We build the map + in a temporary bit of memory, in case the class contains fewer than two + 8-bit characters because in that case the compiled code doesn't use the bit + map. */ + + memset(classbits, 0, 32 * sizeof(uint8_t)); + + /* Process items until META_CLASS_END is reached. */ + + while ((meta = *(++pptr)) != META_CLASS_END) + { + /* Handle POSIX classes such as [:alpha:] etc. */ + + if (meta == META_POSIX || meta == META_POSIX_NEG) + { + BOOL local_negate = (meta == META_POSIX_NEG); + int posix_class = *(++pptr); + int taboffset, tabopt; + uint8_t pbits[32]; + + should_flip_negation = local_negate; /* Note negative special */ + + /* If matching is caseless, upper and lower are converted to alpha. + This relies on the fact that the class table starts with alpha, + lower, upper as the first 3 entries. */ + + if ((options & PCRE2_CASELESS) != 0 && posix_class <= 2) + posix_class = 0; + + /* When PCRE2_UCP is set, some of the POSIX classes are converted to + different escape sequences that use Unicode properties \p or \P. + Others that are not available via \p or \P have to generate + XCL_PROP/XCL_NOTPROP directly, which is done here. */ + +#ifdef SUPPORT_UNICODE + if ((options & PCRE2_UCP) != 0 && + (xoptions & PCRE2_EXTRA_ASCII_POSIX) == 0) + { + switch(posix_class) + { + case PC_GRAPH: + case PC_PRINT: + case PC_PUNCT: + *class_uchardata++ = local_negate? XCL_NOTPROP : XCL_PROP; + *class_uchardata++ = (PCRE2_UCHAR) + ((posix_class == PC_GRAPH)? PT_PXGRAPH : + (posix_class == PC_PRINT)? PT_PXPRINT : PT_PXPUNCT); + *class_uchardata++ = 0; + xclass_has_prop = TRUE; + goto CONTINUE_CLASS; + + /* For the other POSIX classes (ex: ascii) we are going to + fall through to the non-UCP case and build a bit map for + characters with code points less than 256. However, if we are in + a negated POSIX class, characters with code points greater than + 255 must either all match or all not match, depending on whether + the whole class is not or is negated. For example, for + [[:^ascii:]... they must all match, whereas for [^[:^ascii:]... + they must not. + + In the special case where there are no xclass items, this is + automatically handled by the use of OP_CLASS or OP_NCLASS, but an + explicit range is needed for OP_XCLASS. Setting a flag here + causes the range to be generated later when it is known that + OP_XCLASS is required. In the 8-bit library this is relevant only in + utf mode, since no wide characters can exist otherwise. */ + + default: +#if PCRE2_CODE_UNIT_WIDTH == 8 + if (utf) +#endif + match_all_or_no_wide_chars |= local_negate; + break; + } + } +#endif /* SUPPORT_UNICODE */ + + /* In the non-UCP case, or when UCP makes no difference, we build the + bit map for the POSIX class in a chunk of local store because we may + be adding and subtracting from it, and we don't want to subtract bits + that may be in the main map already. At the end we or the result into + the bit map that is being built. */ + + posix_class *= 3; + + /* Copy in the first table (always present) */ + + memcpy(pbits, cbits + posix_class_maps[posix_class], + 32 * sizeof(uint8_t)); + + /* If there is a second table, add or remove it as required. */ + + taboffset = posix_class_maps[posix_class + 1]; + tabopt = posix_class_maps[posix_class + 2]; + + if (taboffset >= 0) + { + if (tabopt >= 0) + for (int i = 0; i < 32; i++) pbits[i] |= cbits[(int)i + taboffset]; + else + for (int i = 0; i < 32; i++) pbits[i] &= ~cbits[(int)i + taboffset]; + } + + /* Now see if we need to remove any special characters. An option + value of 1 removes vertical space and 2 removes underscore. */ + + if (tabopt < 0) tabopt = -tabopt; + if (tabopt == 1) pbits[1] &= ~0x3c; + else if (tabopt == 2) pbits[11] &= 0x7f; + + /* Add the POSIX table or its complement into the main table that is + being built and we are done. */ + + if (local_negate) + for (int i = 0; i < 32; i++) classbits[i] |= (uint8_t)(~pbits[i]); + else + for (int i = 0; i < 32; i++) classbits[i] |= pbits[i]; + + /* Every class contains at least one < 256 character. */ + + class_has_8bitchar = 1; + goto CONTINUE_CLASS; /* End of POSIX handling */ + } + + /* Other than POSIX classes, the only items we should encounter are + \d-type escapes and literal characters (possibly as ranges). */ + + if (meta == META_BIGVALUE) + { + meta = *(++pptr); + goto CLASS_LITERAL; + } + + /* Any other non-literal must be an escape */ + + if (meta >= META_END) + { + if (META_CODE(meta) != META_ESCAPE) + { +#ifdef DEBUG_SHOW_PARSED + fprintf(stderr, "** Unrecognized parsed pattern item 0x%.8x " + "in character class\n", meta); +#endif + *errorcodeptr = ERR89; /* Internal error - unrecognized. */ + return 0; + } + escape = META_DATA(meta); + + /* Every class contains at least one < 256 character. */ + + class_has_8bitchar++; + + switch(escape) + { + case ESC_d: + for (int i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_digit]; + break; + + case ESC_D: + should_flip_negation = TRUE; + for (int i = 0; i < 32; i++) + classbits[i] |= (uint8_t)(~cbits[i+cbit_digit]); + break; + + case ESC_w: + for (int i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_word]; + break; + + case ESC_W: + should_flip_negation = TRUE; + for (int i = 0; i < 32; i++) + classbits[i] |= (uint8_t)(~cbits[i+cbit_word]); + break; + + /* Perl 5.004 onwards omitted VT from \s, but restored it at Perl + 5.18. Before PCRE 8.34, we had to preserve the VT bit if it was + previously set by something earlier in the character class. + Luckily, the value of CHAR_VT is 0x0b in both ASCII and EBCDIC, so + we could just adjust the appropriate bit. From PCRE 8.34 we no + longer treat \s and \S specially. */ + + case ESC_s: + for (int i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_space]; + break; + + case ESC_S: + should_flip_negation = TRUE; + for (int i = 0; i < 32; i++) + classbits[i] |= (uint8_t)(~cbits[i+cbit_space]); + break; + + /* When adding the horizontal or vertical space lists to a class, or + their complements, disable PCRE2_CASELESS, because it justs wastes + time, and in the "not-x" UTF cases can create unwanted duplicates in + the XCLASS list (provoked by characters that have more than one other + case and by both cases being in the same "not-x" sublist). */ + + case ESC_h: + (void)add_list_to_class(classbits, &class_uchardata, + options & ~PCRE2_CASELESS, xoptions, cb, PRIV(hspace_list), + NOTACHAR); + break; + + case ESC_H: + (void)add_not_list_to_class(classbits, &class_uchardata, + options & ~PCRE2_CASELESS, xoptions, cb, PRIV(hspace_list)); + break; + + case ESC_v: + (void)add_list_to_class(classbits, &class_uchardata, + options & ~PCRE2_CASELESS, xoptions, cb, PRIV(vspace_list), + NOTACHAR); + break; + + case ESC_V: + (void)add_not_list_to_class(classbits, &class_uchardata, + options & ~PCRE2_CASELESS, xoptions, cb, PRIV(vspace_list)); + break; + + /* If Unicode is not supported, \P and \p are not allowed and are + faulted at parse time, so will never appear here. */ + +#ifdef SUPPORT_UNICODE + case ESC_p: + case ESC_P: + { + uint32_t ptype = *(++pptr) >> 16; + uint32_t pdata = *pptr & 0xffff; + *class_uchardata++ = (escape == ESC_p)? XCL_PROP : XCL_NOTPROP; + *class_uchardata++ = ptype; + *class_uchardata++ = pdata; + xclass_has_prop = TRUE; + class_has_8bitchar--; /* Undo! */ + } + break; +#endif + } + + goto CONTINUE_CLASS; + } /* End handling \d-type escapes */ + + /* A literal character may be followed by a range meta. At parse time + there are checks for out-of-order characters, for ranges where the two + characters are equal, and for hyphens that cannot indicate a range. At + this point, therefore, no checking is needed. */ + + else + { + uint32_t c, d; + + CLASS_LITERAL: + c = d = meta; + + /* Remember if \r or \n were explicitly used */ + + if (c == CHAR_CR || c == CHAR_NL) cb->external_flags |= PCRE2_HASCRORLF; + + /* Process a character range */ + + if (pptr[1] == META_RANGE_LITERAL || pptr[1] == META_RANGE_ESCAPED) + { +#ifdef EBCDIC + BOOL range_is_literal = (pptr[1] == META_RANGE_LITERAL); +#endif + pptr += 2; + d = *pptr; + if (d == META_BIGVALUE) d = *(++pptr); + + /* Remember an explicit \r or \n, and add the range to the class. */ + + if (d == CHAR_CR || d == CHAR_NL) cb->external_flags |= PCRE2_HASCRORLF; + + /* In an EBCDIC environment, Perl treats alphabetic ranges specially + because there are holes in the encoding, and simply using the range + A-Z (for example) would include the characters in the holes. This + applies only to literal ranges; [\xC1-\xE9] is different to [A-Z]. */ + +#ifdef EBCDIC + if (range_is_literal && + (cb->ctypes[c] & ctype_letter) != 0 && + (cb->ctypes[d] & ctype_letter) != 0 && + (c <= CHAR_z) == (d <= CHAR_z)) + { + uint32_t uc = (d <= CHAR_z)? 0 : 64; + uint32_t C = c - uc; + uint32_t D = d - uc; + + if (C <= CHAR_i) + { + class_has_8bitchar += + add_to_class(classbits, &class_uchardata, options, xoptions, + cb, C + uc, ((D < CHAR_i)? D : CHAR_i) + uc); + C = CHAR_j; + } + + if (C <= D && C <= CHAR_r) + { + class_has_8bitchar += + add_to_class(classbits, &class_uchardata, options, xoptions, + cb, C + uc, ((D < CHAR_r)? D : CHAR_r) + uc); + C = CHAR_s; + } + + if (C <= D) + { + class_has_8bitchar += + add_to_class(classbits, &class_uchardata, options, xoptions, + cb, C + uc, D + uc); + } + } + else +#endif + /* Not an EBCDIC special range */ + + class_has_8bitchar += add_to_class(classbits, &class_uchardata, + options, xoptions, cb, c, d); + goto CONTINUE_CLASS; /* Go get the next char in the class */ + } /* End of range handling */ - zeroreqcu = reqcu; - zeroreqcuflags = reqcuflags; - if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE; - zerofirstcu = firstcu; - zerofirstcuflags = firstcuflags; - /* For caseless UTF or UCP mode, check whether this character has more - than one other case. If so, generate a special OP_NOTPROP item instead of - OP_NOTI. When restricted by PCRE2_EXTRA_CASELESS_RESTRICT, ignore any - caseless set that starts with an ASCII character. If the character is - affected by the special Turkish rules, hardcode the not-matching - characters using a caseset. */ + /* Handle a single character. */ -#ifdef SUPPORT_UNICODE - if ((utf||ucp) && (options & PCRE2_CASELESS) != 0) - { - uint32_t caseset; + class_has_8bitchar += + add_to_class(classbits, &class_uchardata, options, xoptions, cb, + meta, meta); + } - if ((xoptions & (PCRE2_EXTRA_TURKISH_CASING|PCRE2_EXTRA_CASELESS_RESTRICT)) == - PCRE2_EXTRA_TURKISH_CASING && - UCD_ANY_I(c)) - { - caseset = PRIV(ucd_turkish_dotted_i_caseset) + (UCD_DOTTED_I(c)? 0 : 3); - } - else if ((caseset = UCD_CASESET(c)) != 0 && - (xoptions & PCRE2_EXTRA_CASELESS_RESTRICT) != 0 && - PRIV(ucd_caseless_sets)[caseset] < 128) - { - caseset = 0; /* Ignore the caseless set if it's restricted. */ - } + /* Continue to the next item in the class. */ - if (caseset != 0) + CONTINUE_CLASS: + +#ifdef SUPPORT_WIDE_CHARS + /* If any wide characters or Unicode properties have been encountered, + set xclass = TRUE. Then, in the pre-compile phase, accumulate the length + of the extra data and reset the pointer. This is so that very large + classes that contain a zillion wide characters or Unicode property tests + do not overwrite the workspace (which is on the stack). */ + + if (class_uchardata > class_uchardata_base) + { + xclass = TRUE; + if (lengthptr != NULL) { - *code++ = OP_NOTPROP; - *code++ = PT_CLIST; - *code++ = caseset; - break; /* We are finished with this class */ + *lengthptr += class_uchardata - class_uchardata_base; + class_uchardata = class_uchardata_base; } } #endif - /* Char has only one other (usable) case, or UCP not available */ - *code++ = ((options & PCRE2_CASELESS) != 0)? OP_NOTI: OP_NOT; - code += PUTCHAR(c, code); - break; /* We are finished with this class */ - } /* End of 1-char optimization */ + continue; /* Needed to avoid error when not supporting wide chars */ + } /* End of main class-processing loop */ - /* Handle character classes that contain more than just one literal - character. If there are exactly two characters in a positive class, see if - they are case partners. This can be optimized to generate a caseless single - character match (which also sets first/required code units if relevant). - When casing restrictions apply, ignore a caseless set if both characters - are ASCII. When Turkish casing applies, an 'i' does not match its normal - Unicode "othercase". */ + /* If this class is the first thing in the branch, there can be no first + char setting, whatever the repeat count. Any reqcu setting must remain + unchanged after any kind of repeat. */ - if (meta == META_CLASS && pptr[1] < META_END && pptr[2] < META_END && - pptr[3] == META_CLASS_END) - { - uint32_t c = pptr[1]; + if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE; + zerofirstcu = firstcu; + zerofirstcuflags = firstcuflags; + zeroreqcu = reqcu; + zeroreqcuflags = reqcuflags; + /* If there are characters with values > 255, or Unicode property settings + (\p or \P), we have to compile an extended class, with its own opcode, + unless there were no property settings and there was a negated special such + as \S in the class, and PCRE2_UCP is not set, because in that case all + characters > 255 are in or not in the class, so any that were explicitly + given as well can be ignored. + + In the UCP case, if certain negated POSIX classes (ex: [:^ascii:]) were + were present in a class, we either have to match or not match all wide + characters (depending on whether the whole class is or is not negated). + This requirement is indicated by match_all_or_no_wide_chars being true. + We do this by including an explicit range, which works in both cases. + This applies only in UTF and 16-bit and 32-bit non-UTF modes, since there + cannot be any wide characters in 8-bit non-UTF mode. + + When there *are* properties in a positive UTF-8 or any 16-bit or 32_bit + class where \S etc is present without PCRE2_UCP, causing an extended class + to be compiled, we make sure that all characters > 255 are included by + forcing match_all_or_no_wide_chars to be true. + + If, when generating an xclass, there are no characters < 256, we can omit + the bitmap in the actual compiled code. */ + +#ifdef SUPPORT_WIDE_CHARS /* Defined for 16/32 bits, or 8-bit with Unicode */ + if (xclass && ( #ifdef SUPPORT_UNICODE - if ((UCD_CASESET(c) == 0 || - ((xoptions & PCRE2_EXTRA_CASELESS_RESTRICT) != 0 && - c < 128 && pptr[2] < 128)) && - !((xoptions & (PCRE2_EXTRA_TURKISH_CASING|PCRE2_EXTRA_CASELESS_RESTRICT)) == - PCRE2_EXTRA_TURKISH_CASING && - UCD_ANY_I(c))) + (options & PCRE2_UCP) != 0 || #endif - { - uint32_t d; - -#ifdef SUPPORT_UNICODE - if ((utf || ucp) && c > 127) d = UCD_OTHERCASE(c); else + xclass_has_prop || !should_flip_negation)) + { + if (match_all_or_no_wide_chars || ( +#if PCRE2_CODE_UNIT_WIDTH == 8 + utf && #endif + should_flip_negation && !negate_class && (options & PCRE2_UCP) == 0)) + { + *class_uchardata++ = XCL_RANGE; + if (utf) /* Will always be utf in the 8-bit library */ { -#if PCRE2_CODE_UNIT_WIDTH != 8 - if (c > 255) d = c; else + class_uchardata += PRIV(ord2utf)(0x100, class_uchardata); + class_uchardata += PRIV(ord2utf)(MAX_UTF_CODE_POINT, class_uchardata); + } + else /* Can only happen for the 16-bit & 32-bit libraries */ + { +#if PCRE2_CODE_UNIT_WIDTH == 16 + *class_uchardata++ = 0x100; + *class_uchardata++ = 0xffffu; +#elif PCRE2_CODE_UNIT_WIDTH == 32 + *class_uchardata++ = 0x100; + *class_uchardata++ = 0xffffffffu; #endif - d = TABLE_GET(c, cb->fcc, c); } + } + *class_uchardata++ = XCL_END; /* Marks the end of extra data */ + *code++ = OP_XCLASS; + code += LINK_SIZE; + *code = negate_class? XCL_NOT:0; + if (xclass_has_prop) *code |= XCL_HASPROP; - if (c != d && pptr[2] == d) + /* If the map is required, move up the extra data to make room for it; + otherwise just move the code pointer to the end of the extra data. */ + + if (class_has_8bitchar > 0) + { + *code++ |= XCL_MAP; + (void)memmove(code + (32 / sizeof(PCRE2_UCHAR)), code, + CU2BYTES(class_uchardata - code)); + if (negate_class && !xclass_has_prop) { - pptr += 3; /* Move on to class end */ - meta = c; - if ((options & PCRE2_CASELESS) == 0) - { - reset_caseful = TRUE; - options |= PCRE2_CASELESS; - req_caseopt = REQ_CASELESS; - } - goto CLASS_CASELESS_CHAR; + /* Using 255 ^ instead of ~ avoids clang sanitize warning. */ + for (int i = 0; i < 32; i++) classbits[i] = 255 ^ classbits[i]; } + memcpy(code, classbits, 32); + code = class_uchardata + (32 / sizeof(PCRE2_UCHAR)); } - } + else code = class_uchardata; - /* Now emit the OP_CLASS/OP_NCLASS/OP_XCLASS/OP_ALLANY opcode. */ + /* Now fill in the complete length of the item */ - pptr = PRIV(compile_class_not_nested)(options, xoptions, pptr + 1, - &code, meta == META_CLASS_NOT, NULL, - errorcodeptr, cb, lengthptr); - if (pptr == NULL) return 0; - PCRE2_ASSERT(*pptr == META_CLASS_END); - - CLASS_END_PROCESSING: + PUT(previous, 1, (int)(code - previous)); + break; /* End of class handling */ + } +#endif /* SUPPORT_WIDE_CHARS */ - /* If this class is the first thing in the branch, there can be no first - char setting, whatever the repeat count. Any reqcu setting must remain - unchanged after any kind of repeat. */ + /* If there are no characters > 255, or they are all to be included or + excluded, set the opcode to OP_CLASS or OP_NCLASS, depending on whether the + whole class was negated and whether there were negative specials such as \S + (non-UCP) in the class. Then copy the 32-byte map into the code vector, + negating it if necessary. */ - if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE; - zerofirstcu = firstcu; - zerofirstcuflags = firstcuflags; - zeroreqcu = reqcu; - zeroreqcuflags = reqcuflags; + *code++ = (negate_class == should_flip_negation) ? OP_CLASS : OP_NCLASS; + if (lengthptr == NULL) /* Save time in the pre-compile phase */ + { + if (negate_class) + { + /* Using 255 ^ instead of ~ avoids clang sanitize warning. */ + for (int i = 0; i < 32; i++) classbits[i] = 255 ^ classbits[i]; + } + memcpy(code, classbits, 32); + } + code += 32 / sizeof(PCRE2_UCHAR); break; /* End of class processing */ @@ -6450,15 +6586,6 @@ for (;; pptr++) req_caseopt = ((options & PCRE2_CASELESS) != 0)? REQ_CASELESS : 0; break; - case META_OFFSET: - GETPLUSOFFSET(offset, pptr); - break; - - case META_SCS: - bravalue = OP_ASSERT_SCS; - cb->assert_depth += 1; - goto GROUP_PROCESS; - /* ===================================================================*/ /* Handle conditional subpatterns. The case of (?(Rdigits) is ambiguous @@ -6470,7 +6597,6 @@ for (;; pptr++) case META_COND_RNUMBER: /* (?(Rdigits) */ case META_COND_NAME: /* (?(name) or (?'name') or ?() */ case META_COND_RNAME: /* (?(R&name) - test for recursion */ - case META_SCS_NAME: /* Name of scan substring */ bravalue = OP_COND; { int count, index; @@ -6479,10 +6605,7 @@ for (;; pptr++) named_group *ng = cb->named_groups; uint32_t length = *(++pptr); - if (meta == META_SCS_NAME) - offset += meta_arg; - else - GETPLUSOFFSET(offset, pptr); + GETPLUSOFFSET(offset, pptr); name = cb->start_pattern + offset; /* In the first pass, the names generated in the pre-pass are available, @@ -6492,21 +6615,34 @@ for (;; pptr++) numerical group. */ for (i = 0; i < cb->names_found; i++, ng++) + { if (length == ng->length && - PRIV(strncmp)(name, ng->name, length) == 0) break; + PRIV(strncmp)(name, ng->name, length) == 0) + { + if (!ng->isdup) + { + code[1+LINK_SIZE] = (meta == META_COND_RNAME)? OP_RREF : OP_CREF; + PUT2(code, 2+LINK_SIZE, ng->number); + if (ng->number > cb->top_backref) cb->top_backref = ng->number; + skipunits = 1+IMM2_SIZE; + goto GROUP_PROCESS_NOTE_EMPTY; + } + break; /* Found a duplicated name */ + } + } + + /* If the name was not found we have a bad reference, unless we are + dealing with R, which is treated as a recursion test by number. + */ if (i >= cb->names_found) { - /* If the name was not found we have a bad reference, unless we are - dealing with R, which is treated as a recursion test by - number. */ - groupnumber = 0; if (meta == META_COND_RNUMBER) { for (i = 1; i < length; i++) { - groupnumber = groupnumber * 10 + (name[i] - CHAR_0); + groupnumber = groupnumber * 10 + name[i] - CHAR_0; if (groupnumber > MAX_GROUP_NUMBER) { *errorcodeptr = ERR61; @@ -6533,26 +6669,11 @@ for (;; pptr++) skipunits = 1+IMM2_SIZE; goto GROUP_PROCESS_NOTE_EMPTY; } - else if (!ng->isdup) - { - /* Otherwise found a duplicated name */ - if (ng->number > cb->top_backref) cb->top_backref = ng->number; - if (meta == META_SCS_NAME) - { - code[0] = OP_CREF; - PUT2(code, 1, ng->number); - code += 1+IMM2_SIZE; - break; - } + /* A duplicated name was found. Note that if an R name is found + (META_COND_RNUMBER), it is a reference test, not a recursion test. */ - code[1+LINK_SIZE] = (meta == META_COND_RNAME)? OP_RREF : OP_CREF; - PUT2(code, 2+LINK_SIZE, ng->number); - skipunits = 1+IMM2_SIZE; - if (meta != META_SCS_NAME) goto GROUP_PROCESS_NOTE_EMPTY; - cb->assert_depth += 1; - goto GROUP_PROCESS; - } + code[1+LINK_SIZE] = (meta == META_COND_RNAME)? OP_RREF : OP_CREF; /* We have a duplicated name. In the compile pass we have to search the main table in order to get the index and count values. */ @@ -6562,27 +6683,14 @@ for (;; pptr++) if (lengthptr == NULL && !find_dupname_details(name, length, &index, &count, errorcodeptr, cb)) return 0; - if (meta == META_SCS_NAME) - { - code[0] = OP_DNCREF; - PUT2(code, 1, index); - PUT2(code, 1+IMM2_SIZE, count); - code += 1+2*IMM2_SIZE; - break; - } - - /* A duplicated name was found. Note that if an R name is found - (META_COND_RNUMBER), it is a reference test, not a recursion test. */ - - code[1+LINK_SIZE] = (meta == META_COND_RNAME)? OP_DNRREF : OP_DNCREF; + /* Add one to the opcode to change CREF/RREF into DNCREF/DNRREF and + insert appropriate data values. */ - /* Insert appropriate data values. */ + code[1+LINK_SIZE]++; skipunits = 1+2*IMM2_SIZE; PUT2(code, 2+LINK_SIZE, index); PUT2(code, 2+LINK_SIZE+IMM2_SIZE, count); } - - PCRE2_ASSERT(meta != META_SCS_NAME); goto GROUP_PROCESS_NOTE_EMPTY; /* The DEFINE condition is always false. Its internal groups may never @@ -6599,13 +6707,8 @@ for (;; pptr++) /* Conditional test of a group's being set. */ case META_COND_NUMBER: - case META_SCS_NUMBER: bravalue = OP_COND; - if (meta == META_SCS_NUMBER) - offset += meta_arg; - else - GETPLUSOFFSET(offset, pptr); - + GETPLUSOFFSET(offset, pptr); groupnumber = *(++pptr); if (groupnumber > cb->bracount) { @@ -6614,17 +6717,7 @@ for (;; pptr++) return 0; } if (groupnumber > cb->top_backref) cb->top_backref = groupnumber; - - if (meta == META_SCS_NUMBER) - { - code[0] = OP_CREF; - PUT2(code, 1, groupnumber); - code += 1+IMM2_SIZE; - break; - } - - /* Point at initial ( for too many branches error */ - offset -= 2; + offset -= 2; /* Point at initial ( for too many branches error */ code[1+LINK_SIZE] = OP_CREF; skipunits = 1+IMM2_SIZE; PUT2(code, 2+LINK_SIZE, groupnumber); @@ -6762,7 +6855,7 @@ for (;; pptr++) /* If we've just compiled an assertion, pop the assert depth. */ - if (bravalue >= OP_ASSERT && bravalue <= OP_ASSERT_SCS) + if (bravalue >= OP_ASSERT && bravalue <= OP_ASSERTBACK_NA) cb->assert_depth -= 1; /* At the end of compiling, code is still pointing to the start of the @@ -7001,11 +7094,6 @@ for (;; pptr++) *code++ = ((options & PCRE2_CASELESS) != 0)? OP_DNREFI : OP_DNREF; PUT2INC(code, 0, index); PUT2INC(code, 0, count); - if ((options & PCRE2_CASELESS) != 0) - *code++ = (((xoptions & PCRE2_EXTRA_CASELESS_RESTRICT) != 0)? - REFI_FLAG_CASELESS_RESTRICT : 0) | - (((xoptions & PCRE2_EXTRA_TURKISH_CASING) != 0)? - REFI_FLAG_TURKISH_CASING : 0); } break; @@ -7125,6 +7213,7 @@ for (;; pptr++) single-char opcodes. */ reqvary = (repeat_min == repeat_max)? 0 : REQ_VARY; + op_type = 0; /* Adjust first and required code units for a zero repeat. */ @@ -7165,7 +7254,6 @@ for (;; pptr++) /* Save start of previous item, in case we have to move it up in order to insert something before it, and remember what it was. */ - PCRE2_ASSERT(previous != NULL); tempcode = previous; op_previous = *previous; @@ -7225,7 +7313,6 @@ for (;; pptr++) #ifdef SUPPORT_WIDE_CHARS case OP_XCLASS: - case OP_ECLASS: #endif case OP_CLASS: case OP_NCLASS: @@ -7256,6 +7343,14 @@ for (;; pptr++) } break; + /* If previous is OP_FAIL, it was generated by an empty class [] + (PCRE2_ALLOW_EMPTY_CLASS is set). The other ways in which OP_FAIL can be + generated, that is by (*FAIL) or (?!), disallow a quantifier at parse + time. We can just ignore this repeat. */ + + case OP_FAIL: + goto END_REPEAT; + /* Prior to 10.30, repeated recursions were wrapped in OP_ONCE brackets because pcre2_match() could not handle backtracking into recursively called groups. Now that this backtracking is available, we no longer need @@ -7339,7 +7434,6 @@ for (;; pptr++) case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: case OP_ASSERTBACK_NA: - case OP_ASSERT_SCS: case OP_ONCE: case OP_SCRIPT_RUN: case OP_BRA: @@ -7664,10 +7758,9 @@ for (;; pptr++) here because it just makes it horribly messy. */ default: - if (op_previous >= OP_EODN || op_previous <= OP_WORD_BOUNDARY) + if (op_previous >= OP_EODN) /* Not a character type - internal error */ { - PCRE2_DEBUG_UNREACHABLE(); - *errorcodeptr = ERR10; /* Not a character type - internal error */ + *errorcodeptr = ERR10; return 0; } else @@ -7687,8 +7780,7 @@ for (;; pptr++) } else { - /* Come here from just above with a character in mcbuffer/mclength. - You must also set op_type before the jump. */ + /* Come here from just above with a character in mcbuffer/mclength. */ OUTPUT_SINGLE_REPEAT: prop_type = prop_value = -1; } @@ -7871,7 +7963,6 @@ for (;; pptr++) #ifdef SUPPORT_WIDE_CHARS case OP_XCLASS: - case OP_ECLASS: tempcode += GET(tempcode, 1); break; #endif @@ -7956,11 +8047,6 @@ for (;; pptr++) if (firstcuflags == REQ_UNSET) zerofirstcuflags = firstcuflags = REQ_NONE; *code++ = ((options & PCRE2_CASELESS) != 0)? OP_REFI : OP_REF; PUT2INC(code, 0, meta_arg); - if ((options & PCRE2_CASELESS) != 0) - *code++ = (((xoptions & PCRE2_EXTRA_CASELESS_RESTRICT) != 0)? - REFI_FLAG_CASELESS_RESTRICT : 0) | - (((xoptions & PCRE2_EXTRA_TURKISH_CASING) != 0)? - REFI_FLAG_TURKISH_CASING : 0); /* Update the map of back references, and keep the highest one. We could do this in parse_regex() for numerical back references, but not @@ -8053,30 +8139,12 @@ for (;; pptr++) uint32_t ptype = *(++pptr) >> 16; uint32_t pdata = *pptr & 0xffff; - /* In caseless matching, particular characteristics Lu, Ll, and Lt get - converted to the general characteristic L&. That is, upper, lower, and - title case letters are all conflated. */ - - if ((options & PCRE2_CASELESS) != 0 && ptype == PT_PC && - (pdata == ucp_Lu || pdata == ucp_Ll || pdata == ucp_Lt)) - { - ptype = PT_LAMP; - pdata = 0; - } - - /* The special case of \p{Any} is compiled to OP_ALLANY and \P{Any} - is compiled to [] so as to benefit from the auto-anchoring code. */ + /* The special case of \p{Any} is compiled to OP_ALLANY so as to benefit + from the auto-anchoring code. */ - if (ptype == PT_ANY) + if (meta_arg == ESC_p && ptype == PT_ANY) { - if (meta_arg == ESC_P) - { - *code++ = OP_CLASS; - memset(code, 0, 32); - code += 32 / sizeof(PCRE2_UCHAR); - } - else - *code++ = OP_ALLANY; + *code++ = OP_ALLANY; } else { @@ -8145,7 +8213,9 @@ for (;; pptr++) default: if (meta >= META_END) { - PCRE2_DEBUG_UNREACHABLE(); +#ifdef DEBUG_SHOW_PARSED + fprintf(stderr, "** Unrecognized parsed pattern item 0x%.8x\n", *pptr); +#endif *errorcodeptr = ERR89; /* Internal error - unrecognized. */ return 0; } @@ -8161,28 +8231,15 @@ for (;; pptr++) /* For caseless UTF or UCP mode, check whether this character has more than one other case. If so, generate a special OP_PROP item instead of OP_CHARI. When casing restrictions apply, ignore caseless sets that start with an - ASCII character. If the character is affected by the special Turkish rules, - hardcode the matching characters using a caseset. */ + ASCII character. */ #ifdef SUPPORT_UNICODE if ((utf||ucp) && (options & PCRE2_CASELESS) != 0) { - uint32_t caseset; - - if ((xoptions & (PCRE2_EXTRA_TURKISH_CASING|PCRE2_EXTRA_CASELESS_RESTRICT)) == - PCRE2_EXTRA_TURKISH_CASING && - UCD_ANY_I(meta)) - { - caseset = PRIV(ucd_turkish_dotted_i_caseset) + (UCD_DOTTED_I(meta)? 0 : 3); - } - else if ((caseset = UCD_CASESET(meta)) != 0 && - (xoptions & PCRE2_EXTRA_CASELESS_RESTRICT) != 0 && - PRIV(ucd_caseless_sets)[caseset] < 128) - { - caseset = 0; /* Ignore the caseless set if it's restricted. */ - } - - if (caseset != 0) + uint32_t caseset = UCD_CASESET(meta); + if (caseset != 0 && + ((xoptions & PCRE2_EXTRA_CASELESS_RESTRICT) == 0 || + PRIV(ucd_caseless_sets)[caseset] > 127)) { *code++ = OP_PROP; *code++ = PT_CLIST; @@ -8280,8 +8337,7 @@ for (;; pptr++) } /* End of big switch */ } /* End of big loop */ -PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */ -return 0; /* Avoid compiler warnings */ +/* Control never reaches here. */ } @@ -8337,6 +8393,8 @@ uint32_t firstcu, reqcu; uint32_t lookbehindlength; uint32_t lookbehindminlength; uint32_t firstcuflags, reqcuflags; +uint32_t branchfirstcu, branchreqcu; +uint32_t branchfirstcuflags, branchreqcuflags; PCRE2_SIZE length; branch_chain bc; @@ -8405,11 +8463,9 @@ code += 1 + LINK_SIZE + skipunits; for (;;) { int branch_return; - uint32_t branchfirstcu = 0, branchreqcu = 0; - uint32_t branchfirstcuflags = REQ_UNSET, branchreqcuflags = REQ_UNSET; /* Insert OP_REVERSE or OP_VREVERSE if this is a lookbehind assertion. There - is only a single minimum length for the whole assertion. When the minimum + is only a single mimimum length for the whole assertion. When the mimimum length is LOOKBEHIND_MAX it means that all branches are of fixed length, though not necessarily the same length. In this case, the original OP_REVERSE can be used. It can also be used if a branch in a variable length lookbehind @@ -8521,10 +8577,10 @@ for (;;) { if (lengthptr == NULL) { - uint32_t branch_length = (uint32_t)(code - last_branch); + PCRE2_SIZE branch_length = code - last_branch; do { - uint32_t prev_length = GET(last_branch, 1); + PCRE2_SIZE prev_length = GET(last_branch, 1); PUT(last_branch, 1, branch_length); branch_length = prev_length; last_branch -= branch_length; @@ -8535,7 +8591,7 @@ for (;;) /* Fill in the ket */ *code = OP_KET; - PUT(code, 1, (uint32_t)(code - start_bracket)); + PUT(code, 1, (int)(code - start_bracket)); code += 1 + LINK_SIZE; /* Set values to pass back */ @@ -8586,9 +8642,7 @@ for (;;) lookbehindlength = META_DATA(*pptr); pptr++; } - -PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */ -return 0; /* Avoid compiler warnings */ +/* Control never reaches here */ } @@ -8631,14 +8685,13 @@ this prevents the number of characters it matches from being adjusted. cb points to the compile data block atomcount atomic group level inassert TRUE if in an assertion - dotstar_anchor TRUE if automatic anchoring optimization is enabled Returns: TRUE or FALSE */ static BOOL is_anchored(PCRE2_SPTR code, uint32_t bracket_map, compile_block *cb, - int atomcount, BOOL inassert, BOOL dotstar_anchor) + int atomcount, BOOL inassert) { do { PCRE2_SPTR scode = first_significant_code( @@ -8650,7 +8703,7 @@ do { if (op == OP_BRA || op == OP_BRAPOS || op == OP_SBRA || op == OP_SBRAPOS) { - if (!is_anchored(scode, bracket_map, cb, atomcount, inassert, dotstar_anchor)) + if (!is_anchored(scode, bracket_map, cb, atomcount, inassert)) return FALSE; } @@ -8661,14 +8714,14 @@ do { { int n = GET2(scode, 1+LINK_SIZE); uint32_t new_map = bracket_map | ((n < 32)? (1u << n) : 1); - if (!is_anchored(scode, new_map, cb, atomcount, inassert, dotstar_anchor)) return FALSE; + if (!is_anchored(scode, new_map, cb, atomcount, inassert)) return FALSE; } /* Positive forward assertion */ else if (op == OP_ASSERT || op == OP_ASSERT_NA) { - if (!is_anchored(scode, bracket_map, cb, atomcount, TRUE, dotstar_anchor)) return FALSE; + if (!is_anchored(scode, bracket_map, cb, atomcount, TRUE)) return FALSE; } /* Condition. If there is no second branch, it can't be anchored. */ @@ -8676,7 +8729,7 @@ do { else if (op == OP_COND || op == OP_SCOND) { if (scode[GET(scode,1)] != OP_ALT) return FALSE; - if (!is_anchored(scode, bracket_map, cb, atomcount, inassert, dotstar_anchor)) + if (!is_anchored(scode, bracket_map, cb, atomcount, inassert)) return FALSE; } @@ -8684,7 +8737,7 @@ do { else if (op == OP_ONCE) { - if (!is_anchored(scode, bracket_map, cb, atomcount + 1, inassert, dotstar_anchor)) + if (!is_anchored(scode, bracket_map, cb, atomcount + 1, inassert)) return FALSE; } @@ -8699,7 +8752,8 @@ do { op == OP_TYPEPOSSTAR)) { if (scode[1] != OP_ALLANY || (bracket_map & cb->backref_map) != 0 || - atomcount > 0 || cb->had_pruneorskip || inassert || !dotstar_anchor) + atomcount > 0 || cb->had_pruneorskip || inassert || + (cb->external_options & PCRE2_NO_DOTSTAR_ANCHOR) != 0) return FALSE; } @@ -8736,14 +8790,13 @@ or *SKIP does not count, because once again the assumption no longer holds. cb points to the compile data atomcount atomic group level inassert TRUE if in an assertion - dotstar_anchor TRUE if automatic anchoring optimization is enabled Returns: TRUE or FALSE */ static BOOL is_startline(PCRE2_SPTR code, unsigned int bracket_map, compile_block *cb, - int atomcount, BOOL inassert, BOOL dotstar_anchor) + int atomcount, BOOL inassert) { do { PCRE2_SPTR scode = first_significant_code( @@ -8774,8 +8827,7 @@ do { return FALSE; default: /* Assertion */ - if (!is_startline(scode, bracket_map, cb, atomcount, TRUE, dotstar_anchor)) - return FALSE; + if (!is_startline(scode, bracket_map, cb, atomcount, TRUE)) return FALSE; do scode += GET(scode, 1); while (*scode == OP_ALT); scode += 1 + LINK_SIZE; break; @@ -8789,7 +8841,7 @@ do { if (op == OP_BRA || op == OP_BRAPOS || op == OP_SBRA || op == OP_SBRAPOS) { - if (!is_startline(scode, bracket_map, cb, atomcount, inassert, dotstar_anchor)) + if (!is_startline(scode, bracket_map, cb, atomcount, inassert)) return FALSE; } @@ -8800,15 +8852,14 @@ do { { int n = GET2(scode, 1+LINK_SIZE); unsigned int new_map = bracket_map | ((n < 32)? (1u << n) : 1); - if (!is_startline(scode, new_map, cb, atomcount, inassert, dotstar_anchor)) - return FALSE; + if (!is_startline(scode, new_map, cb, atomcount, inassert)) return FALSE; } /* Positive forward assertions */ else if (op == OP_ASSERT || op == OP_ASSERT_NA) { - if (!is_startline(scode, bracket_map, cb, atomcount, TRUE, dotstar_anchor)) + if (!is_startline(scode, bracket_map, cb, atomcount, TRUE)) return FALSE; } @@ -8816,7 +8867,7 @@ do { else if (op == OP_ONCE) { - if (!is_startline(scode, bracket_map, cb, atomcount + 1, inassert, dotstar_anchor)) + if (!is_startline(scode, bracket_map, cb, atomcount + 1, inassert)) return FALSE; } @@ -8830,7 +8881,8 @@ do { else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR || op == OP_TYPEPOSSTAR) { if (scode[1] != OP_ANY || (bracket_map & cb->backref_map) != 0 || - atomcount > 0 || cb->had_pruneorskip || inassert || !dotstar_anchor) + atomcount > 0 || cb->had_pruneorskip || inassert || + (cb->external_options & PCRE2_NO_DOTSTAR_ANCHOR) != 0) return FALSE; } @@ -8864,8 +8916,8 @@ OP_RECURSE. Returns: pointer to the opcode for OP_RECURSE, or NULL if not found */ -static PCRE2_UCHAR * -find_recurse(PCRE2_UCHAR *code, BOOL utf) +static PCRE2_SPTR +find_recurse(PCRE2_SPTR code, BOOL utf) { for (;;) { @@ -8874,13 +8926,12 @@ for (;;) if (c == OP_RECURSE) return code; /* XCLASS is used for classes that cannot be represented just by a bit map. - This includes negated single high-valued characters. ECLASS is used for - classes that use set operations internally. CALLOUT_STR is used for - callouts with string arguments. In each case the length in the table is + This includes negated single high-valued characters. CALLOUT_STR is used for + callouts with string arguments. In both cases the length in the table is zero; the actual length is stored in the compiled code. */ - if (c == OP_XCLASS || c == OP_ECLASS) code += GET(code, 1); - else if (c == OP_CALLOUT_STR) code += GET(code, 1 + 2*LINK_SIZE); + if (c == OP_XCLASS) code += GET(code, 1); + else if (c == OP_CALLOUT_STR) code += GET(code, 1 + 2*LINK_SIZE); /* Otherwise, we can get the item's length from the table, except that for repeated character types, we have to test for \p and \P, which have an extra @@ -9210,12 +9261,9 @@ for (;; pptr++) if (meta < META_END) continue; /* Literal */ break; - case META_END: - - /* The parsed regex is malformed; we have reached the end and did - not find the end of the construct which we are skipping over. */ + /* This should never occur. */ - PCRE2_DEBUG_UNREACHABLE(); + case META_END: return NULL; /* The data for these items is variable in length. */ @@ -9224,9 +9272,19 @@ for (;; pptr++) if (META_DATA(*pptr) >= 10) pptr += SIZEOFFSET; break; - case META_ESCAPE: - if (*pptr - META_ESCAPE == ESC_P || *pptr - META_ESCAPE == ESC_p) - pptr += 1; /* Skip prop data */ + case META_ESCAPE: /* A few escapes are followed by data items. */ + switch (META_DATA(*pptr)) + { + case ESC_P: + case ESC_p: + pptr += 1; + break; + + case ESC_g: + case ESC_k: + pptr += 1 + SIZEOFFSET; + break; + } break; case META_MARK: /* Add the length of the name. */ @@ -9252,7 +9310,6 @@ for (;; pptr++) case META_COND_RNAME: case META_COND_RNUMBER: case META_COND_VERSION: - case META_SCS: case META_LOOKAHEAD: case META_LOOKAHEADNOT: case META_LOOKAHEAD_NA: @@ -9280,8 +9337,8 @@ for (;; pptr++) if (meta >= sizeof(meta_extra_lengths)) return NULL; pptr += meta_extra_lengths[meta]; } - -PCRE2_UNREACHABLE(); /* Control never reaches here */ +/* Control never reaches here */ +return pptr; } @@ -9412,10 +9469,10 @@ for (;; pptr++) parsed_recurse_check *r; uint32_t *gptr, *gptrend; uint32_t escape; - uint32_t min, max; uint32_t group = 0; uint32_t itemlength = 0; uint32_t itemminlength = 0; + uint32_t min, max; if (*pptr < META_END) { @@ -9514,7 +9571,6 @@ for (;; pptr++) case META_LOOKAHEAD: case META_LOOKAHEADNOT: case META_LOOKAHEAD_NA: - case META_SCS: *errcodeptr = check_lookbehinds(pptr + 1, &pptr, recurses, cb, lcptr); if (*errcodeptr != 0) return -1; @@ -9546,9 +9602,7 @@ for (;; pptr++) break; /* A nested lookbehind does not contribute any length to this lookbehind, - but must itself be checked and have its lengths set. Note that - set_lookbehind_lengths() updates pptr, leaving it pointing to the final ket - of the group, so no need to update it here. */ + but must itself be checked and have its lengths set. */ case META_LOOKBEHIND: case META_LOOKBEHINDNOT: @@ -9784,8 +9838,7 @@ for (;; pptr++) return branchlength; PARSED_SKIP_FAILED: -PCRE2_DEBUG_UNREACHABLE(); -*errcodeptr = ERR90; /* Unhandled META code - internal error */ +*errcodeptr = ERR90; return -1; } @@ -9869,7 +9922,7 @@ possibly different) length. */ if (variable) { gbptr[1] = minlength; - if ((PCRE2_SIZE)maxlength > cb->max_varlookbehind) + if ((uint32_t)maxlength > cb->max_varlookbehind) { *errcodeptr = ERR100; cb->erroroffset = offset; @@ -9878,6 +9931,8 @@ if (variable) } else gbptr[1] = LOOKBEHIND_MAX; + +gbptr[1] = variable? minlength : LOOKBEHIND_MAX; return TRUE; } @@ -9923,18 +9978,11 @@ for (; *pptr != META_END; pptr++) switch (META_CODE(*pptr)) { default: - - /* The following erroroffset is a bogus but safe value. This branch should - be avoided by providing a proper implementation for all supported cases - below. */ - - PCRE2_DEBUG_UNREACHABLE(); - cb->erroroffset = 0; return ERR70; /* Unrecognized meta code */ case META_ESCAPE: if (*pptr - META_ESCAPE == ESC_P || *pptr - META_ESCAPE == ESC_p) - pptr += 1; /* Skip prop data */ + pptr += 1; break; case META_KET: @@ -9948,7 +9996,6 @@ for (; *pptr != META_END; pptr++) case META_ATOMIC: case META_CAPTURE: case META_COND_ASSERT: - case META_SCS: case META_LOOKAHEAD: case META_LOOKAHEADNOT: case META_LOOKAHEAD_NA: @@ -9986,7 +10033,6 @@ for (; *pptr != META_END; pptr++) case META_THEN: break; - case META_OFFSET: case META_RECURSE: pptr += SIZEOFFSET; break; @@ -10021,8 +10067,6 @@ for (; *pptr != META_END; pptr++) case META_BIGVALUE: case META_POSIX: case META_POSIX_NEG: - case META_SCS_NAME: - case META_SCS_NUMBER: pptr += 1; break; @@ -10045,9 +10089,6 @@ for (; *pptr != META_END; pptr++) pptr += 1 + pptr[1]; break; - /* Note that set_lookbehind_lengths() updates pptr, leaving it pointing to - the final ket of the group, so no need to update it here. */ - case META_LOOKBEHIND: case META_LOOKBEHINDNOT: case META_LOOKBEHIND_NA: @@ -10094,19 +10135,19 @@ compile_block cb; /* "Static" compile-time data */ const uint8_t *tables; /* Char tables base pointer */ PCRE2_UCHAR *code; /* Current pointer in compiled code */ -PCRE2_UCHAR * codestart; /* Start of compiled code */ +PCRE2_SPTR codestart; /* Start of compiled code */ PCRE2_SPTR ptr; /* Current pointer in pattern */ uint32_t *pptr; /* Current pointer in parsed pattern */ PCRE2_SIZE length = 1; /* Allow for final END opcode */ PCRE2_SIZE usedlength; /* Actual length used */ PCRE2_SIZE re_blocksize; /* Size of memory block */ +PCRE2_SIZE big32count = 0; /* 32-bit literals >= 0x80000000 */ PCRE2_SIZE parsed_size_needed; /* Needed for parsed pattern */ uint32_t firstcuflags, reqcuflags; /* Type of first/req code unit */ uint32_t firstcu, reqcu; /* Value of first/req code unit */ uint32_t setflags = 0; /* NL and BSR set flags */ -uint32_t xoptions; /* Flags from context, modified */ uint32_t skipatstart; /* When checking (*UTF) etc */ uint32_t limit_heap = UINT32_MAX; @@ -10120,10 +10161,6 @@ int regexrc; /* Return from compile */ uint32_t i; /* Local loop counter */ -/* Enable all optimizations by default. */ -uint32_t optim_flags = ccontext != NULL ? ccontext->optimization_flags : - PCRE2_OPTIMIZATION_ALL; - /* Comments at the head of this file explain about these variables. */ uint32_t stack_groupinfo[GROUPINFO_DEFAULT_SIZE]; @@ -10187,7 +10224,6 @@ PCRE2_ZERO_TERMINATED. Check for an overlong pattern. */ if ((zero_terminated = (patlen == PCRE2_ZERO_TERMINATED))) patlen = PRIV(strlen)(pattern); -(void)zero_terminated; /* Silence compiler; only used if Valgrind enabled */ if (patlen > ccontext->max_pattern_length) { @@ -10195,18 +10231,6 @@ if (patlen > ccontext->max_pattern_length) return NULL; } -/* Optimization flags in 'options' can override those in the compile context. -This is because some options to disable optimizations were added before the -optimization flags word existed, and we need to continue supporting them -for backwards compatibility. */ - -if ((options & PCRE2_NO_AUTO_POSSESS) != 0) - optim_flags &= ~PCRE2_OPTIM_AUTO_POSSESS; -if ((options & PCRE2_NO_DOTSTAR_ANCHOR) != 0) - optim_flags &= ~PCRE2_OPTIM_DOTSTAR_ANCHOR; -if ((options & PCRE2_NO_START_OPTIMIZE) != 0) - optim_flags &= ~PCRE2_OPTIM_START_OPTIMIZE; - /* From here on, all returns from this function should end up going via the EXIT label. */ @@ -10245,11 +10269,6 @@ cb.start_code = cworkspace; cb.start_pattern = pattern; cb.start_workspace = cworkspace; cb.workspace_size = COMPILE_WORK_SIZE; -#ifdef SUPPORT_WIDE_CHARS -cb.cranges = NULL; -cb.next_cranges = NULL; -cb.char_lists_size = 0; -#endif /* Maximum back reference and backref bitmap. The bitmap records up to 31 back references to help in deciding whether (.*) can be treated as anchored or not. @@ -10283,7 +10302,6 @@ non-zero-terminated patterns. */ if (zero_terminated) VALGRIND_MAKE_MEM_NOACCESS(pattern + patlen, CU2BYTES(1)); #endif -xoptions = ccontext->extra_options; ptr = pattern; skipatstart = 0; @@ -10295,13 +10313,13 @@ if ((options & PCRE2_LITERAL) == 0) { for (i = 0; i < sizeof(pso_list)/sizeof(pso); i++) { + uint32_t c, pp; const pso *p = pso_list + i; if (patlen - skipatstart - 2 >= p->length && - PRIV(strncmp_c8)(ptr + skipatstart + 2, p->name, p->length) == 0) + PRIV(strncmp_c8)(ptr + skipatstart + 2, (char *)(p->name), + p->length) == 0) { - uint32_t c, pp; - skipatstart += p->length + 2; switch(p->type) { @@ -10309,10 +10327,6 @@ if ((options & PCRE2_LITERAL) == 0) cb.external_options |= p->value; break; - case PSO_XOPT: - xoptions |= p->value; - break; - case PSO_FLG: setflags |= p->value; break; @@ -10332,12 +10346,18 @@ if ((options & PCRE2_LITERAL) == 0) case PSO_LIMH: c = 0; pp = skipatstart; - while (pp < patlen && IS_DIGIT(ptr[pp])) + if (!IS_DIGIT(ptr[pp])) + { + errorcode = ERR60; + ptr += pp; + goto HAD_EARLY_ERROR; + } + while (IS_DIGIT(ptr[pp])) { if (c > UINT32_MAX / 10 - 1) break; /* Integer overflow */ c = c*10 + (ptr[pp++] - CHAR_0); } - if (pp >= patlen || pp == skipatstart || ptr[pp] != CHAR_RIGHT_PARENTHESIS) + if (ptr[pp++] != CHAR_RIGHT_PARENTHESIS) { errorcode = ERR60; ptr += pp; @@ -10346,45 +10366,14 @@ if ((options & PCRE2_LITERAL) == 0) if (p->type == PSO_LIMH) limit_heap = c; else if (p->type == PSO_LIMM) limit_match = c; else limit_depth = c; - skipatstart = ++pp; - break; - - case PSO_OPTMZ: - optim_flags &= ~(p->value); - - /* For backward compatibility the three original VERBs to disable - optimizations need to also update the corresponding bit in the - external options. */ - - switch(p->value) - { - case PCRE2_OPTIM_AUTO_POSSESS: - cb.external_options |= PCRE2_NO_AUTO_POSSESS; - break; - - case PCRE2_OPTIM_DOTSTAR_ANCHOR: - cb.external_options |= PCRE2_NO_DOTSTAR_ANCHOR; - break; - - case PCRE2_OPTIM_START_OPTIMIZE: - cb.external_options |= PCRE2_NO_START_OPTIMIZE; - break; - } - + skipatstart += pp - skipatstart; break; - - default: - /* All values in the enum need an explicit entry for this switch - but until a better way to prevent coding mistakes is invented keep - a catch all that triggers a debug build assert as a failsafe */ - PCRE2_DEBUG_UNREACHABLE(); } break; /* Out of the table scan loop */ } } if (i >= sizeof(pso_list)/sizeof(pso)) break; /* Out of pso loop */ } - PCRE2_ASSERT(skipatstart <= patlen); } /* End of pattern-start options; advance to start of real regex. */ @@ -10436,31 +10425,6 @@ if (ucp && (cb.external_options & PCRE2_NEVER_UCP) != 0) goto HAD_EARLY_ERROR; } -/* PCRE2_EXTRA_TURKISH_CASING checks */ - -if ((xoptions & PCRE2_EXTRA_TURKISH_CASING) != 0) - { - if (!utf && !ucp) - { - errorcode = ERR104; - goto HAD_EARLY_ERROR; - } - -#if PCRE2_CODE_UNIT_WIDTH == 8 - if (!utf) - { - errorcode = ERR105; - goto HAD_EARLY_ERROR; - } -#endif - - if ((xoptions & PCRE2_EXTRA_CASELESS_RESTRICT) != 0) - { - errorcode = ERR106; - goto HAD_EARLY_ERROR; - } - } - /* Process the BSR setting. */ if (bsr == 0) bsr = ccontext->bsr_convention; @@ -10501,7 +10465,6 @@ switch(newline) break; default: - PCRE2_DEBUG_UNREACHABLE(); errorcode = ERR56; goto HAD_EARLY_ERROR; } @@ -10510,31 +10473,42 @@ switch(newline) their numerical equivalents, so that this information is always available for the remaining processing. (2) At the same time, parse the pattern and put a processed version into the parsed_pattern vector. This has escapes interpreted -and comments removed (amongst other things). */ +and comments removed (amongst other things). -/* Ensure that the parsed pattern buffer is big enough. For many smaller -patterns the vector on the stack (which was set up above) can be used. */ +In all but one case, when PCRE2_AUTO_CALLOUT is not set, the number of unsigned +32-bit ints in the parsed pattern is bounded by the length of the pattern plus +one (for the terminator) plus four if PCRE2_EXTRA_WORD or PCRE2_EXTRA_LINE is +set. The exceptional case is when running in 32-bit, non-UTF mode, when literal +characters greater than META_END (0x80000000) have to be coded as two units. In +this case, therefore, we scan the pattern to check for such values. */ + +#if PCRE2_CODE_UNIT_WIDTH == 32 +if (!utf) + { + PCRE2_SPTR p; + for (p = ptr; p < cb.end_pattern; p++) if (*p >= META_END) big32count++; + } +#endif -parsed_size_needed = max_parsed_pattern(ptr, cb.end_pattern, utf, options); +/* Ensure that the parsed pattern buffer is big enough. When PCRE2_AUTO_CALLOUT +is set we have to assume a numerical callout (4 elements) for each character +plus one at the end. This is overkill, but memory is plentiful these days. For +many smaller patterns the vector on the stack (which was set up above) can be +used. */ -/* Allow for 2x uint32_t at the start and 2 at the end, for -PCRE2_EXTRA_MATCH_WORD or PCRE2_EXTRA_MATCH_LINE (which are exclusive). */ +parsed_size_needed = patlen - skipatstart + big32count; if ((ccontext->extra_options & (PCRE2_EXTRA_MATCH_WORD|PCRE2_EXTRA_MATCH_LINE)) != 0) parsed_size_needed += 4; -/* When PCRE2_AUTO_CALLOUT is set we allow for one callout at the end. */ - if ((options & PCRE2_AUTO_CALLOUT) != 0) - parsed_size_needed += 4; - -parsed_size_needed += 1; /* For the final META_END */ + parsed_size_needed = (parsed_size_needed + 1) * 5; -if (parsed_size_needed > PARSED_PATTERN_DEFAULT_SIZE) +if (parsed_size_needed >= PARSED_PATTERN_DEFAULT_SIZE) { uint32_t *heap_parsed_pattern = ccontext->memctl.malloc( - parsed_size_needed * sizeof(uint32_t), ccontext->memctl.memory_data); + (parsed_size_needed + 1) * sizeof(uint32_t), ccontext->memctl.memory_data); if (heap_parsed_pattern == NULL) { *errorptr = ERR21; @@ -10542,11 +10516,11 @@ if (parsed_size_needed > PARSED_PATTERN_DEFAULT_SIZE) } cb.parsed_pattern = heap_parsed_pattern; } -cb.parsed_pattern_end = cb.parsed_pattern + parsed_size_needed; +cb.parsed_pattern_end = cb.parsed_pattern + parsed_size_needed + 1; /* Do the parsing scan. */ -errorcode = parse_regex(ptr, cb.external_options, xoptions, &has_lookbehind, &cb); +errorcode = parse_regex(ptr, cb.external_options, &has_lookbehind, &cb); if (errorcode != 0) goto HAD_CB_ERROR; /* If there are any lookbehinds, scan the parsed pattern to figure out their @@ -10615,7 +10589,7 @@ pptr = cb.parsed_pattern; code = cworkspace; *code = OP_BRA; -(void)compile_regex(cb.external_options, xoptions, &code, &pptr, +(void)compile_regex(cb.external_options, ccontext->extra_options, &code, &pptr, &errorcode, 0, &firstcu, &firstcuflags, &reqcu, &reqcuflags, NULL, NULL, &cb, &length); @@ -10623,13 +10597,7 @@ if (errorcode != 0) goto HAD_CB_ERROR; /* Offset is in cb.erroroffset */ /* This should be caught in compile_regex(), but just in case... */ -#if defined SUPPORT_WIDE_CHARS -PCRE2_ASSERT((cb.char_lists_size & 0x3) == 0); -if (length > MAX_PATTERN_SIZE || - MAX_PATTERN_SIZE - length < (cb.char_lists_size / sizeof(PCRE2_UCHAR))) -#else if (length > MAX_PATTERN_SIZE) -#endif { errorcode = ERR20; goto HAD_CB_ERROR; @@ -10640,22 +10608,9 @@ block for storing the compiled pattern and names table. Integer overflow should no longer be possible because nowadays we limit the maximum value of cb.names_found and cb.name_entry_size. */ -re_blocksize = - CU2BYTES((PCRE2_SIZE)cb.names_found * (PCRE2_SIZE)cb.name_entry_size); - -#if defined SUPPORT_WIDE_CHARS -if (cb.char_lists_size != 0) - { -#if PCRE2_CODE_UNIT_WIDTH != 32 - /* Align to 32 bit first. This ensures the - allocated area will also be 32 bit aligned. */ - re_blocksize = (PCRE2_SIZE)CLIST_ALIGN_TO(re_blocksize, sizeof(uint32_t)); -#endif - re_blocksize += cb.char_lists_size; - } -#endif - -re_blocksize += CU2BYTES(length); +re_blocksize = sizeof(pcre2_real_code) + + CU2BYTES(length + + (PCRE2_SIZE)cb.names_found * (PCRE2_SIZE)cb.name_entry_size); if (re_blocksize > ccontext->max_pattern_compiled_length) { @@ -10663,7 +10618,6 @@ if (re_blocksize > ccontext->max_pattern_compiled_length) goto HAD_CB_ERROR; } -re_blocksize += sizeof(pcre2_real_code); re = (pcre2_real_code *) ccontext->memctl.malloc(re_blocksize, ccontext->memctl.memory_data); if (re == NULL) @@ -10684,11 +10638,10 @@ re->tables = tables; re->executable_jit = NULL; memset(re->start_bitmap, 0, 32 * sizeof(uint8_t)); re->blocksize = re_blocksize; -re->code_start = re_blocksize - CU2BYTES(length); re->magic_number = MAGIC_NUMBER; re->compile_options = options; re->overall_options = cb.external_options; -re->extra_options = xoptions; +re->extra_options = ccontext->extra_options; re->flags = PCRE2_CODE_UNIT_WIDTH/8 | cb.external_flags | setflags; re->limit_heap = limit_heap; re->limit_match = limit_match; @@ -10703,12 +10656,12 @@ re->top_bracket = 0; re->top_backref = 0; re->name_entry_size = cb.name_entry_size; re->name_count = cb.names_found; -re->optimization_flags = optim_flags; /* The basic block is immediately followed by the name table, and the compiled code follows after that. */ -codestart = (PCRE2_UCHAR *)((uint8_t *)re + re->code_start); +codestart = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code)) + + re->name_entry_size * re->name_count; /* Update the compile data block for the actual compile. The starting points of the name/number translation table and of the code are passed around in the @@ -10723,10 +10676,6 @@ cb.start_code = codestart; cb.req_varyopt = 0; cb.had_accept = FALSE; cb.had_pruneorskip = FALSE; -#ifdef SUPPORT_WIDE_CHARS -cb.char_lists_size = 0; -#endif - /* If any named groups were found, create the name/number table from the list created in the pre-pass. */ @@ -10745,7 +10694,7 @@ of the function here. */ pptr = cb.parsed_pattern; code = (PCRE2_UCHAR *)codestart; *code = OP_BRA; -regexrc = compile_regex(re->overall_options, re->extra_options, &code, +regexrc = compile_regex(re->overall_options, ccontext->extra_options, &code, &pptr, &errorcode, 0, &firstcu, &firstcuflags, &reqcu, &reqcuflags, NULL, NULL, &cb, NULL); if (regexrc < 0) re->flags |= PCRE2_MATCH_EMPTY; @@ -10767,12 +10716,7 @@ memory as unaddressable, so that any out-of-bound reads can be detected. */ *code++ = OP_END; usedlength = code - codestart; -if (usedlength > length) - { - PCRE2_DEBUG_UNREACHABLE(); - errorcode = ERR23; /* Overflow of code block - internal error */ - } -else +if (usedlength > length) errorcode = ERR23; else { re->blocksize -= CU2BYTES(length - usedlength); #ifdef SUPPORT_VALGRIND @@ -10794,9 +10738,9 @@ if (errorcode == 0 && cb.had_recurse) int start = RSCAN_CACHE_SIZE; recurse_cache rc[RSCAN_CACHE_SIZE]; - for (rcode = find_recurse(codestart, utf); + for (rcode = (PCRE2_UCHAR *)find_recurse(codestart, utf); rcode != NULL; - rcode = find_recurse(rcode + 1 + LINK_SIZE, utf)) + rcode = (PCRE2_UCHAR *)find_recurse(rcode + 1 + LINK_SIZE, utf)) { int p, groupnumber; @@ -10825,7 +10769,6 @@ if (errorcode == 0 && cb.had_recurse) rgroup = PRIV(find_bracket)(search_from, utf, groupnumber); if (rgroup == NULL) { - PCRE2_DEBUG_UNREACHABLE(); errorcode = ERR53; break; } @@ -10836,7 +10779,7 @@ if (errorcode == 0 && cb.had_recurse) } } - PUT(rcode, 1, (uint32_t)(rgroup - codestart)); + PUT(rcode, 1, rgroup - codestart); } } @@ -10855,14 +10798,10 @@ used in this code because at least one compiler gives a warning about loss of "const" attribute if the cast (PCRE2_UCHAR *)codestart is used directly in the function call. */ -if (errorcode == 0 && (optim_flags & PCRE2_OPTIM_AUTO_POSSESS) != 0) +if (errorcode == 0 && (re->overall_options & PCRE2_NO_AUTO_POSSESS) == 0) { PCRE2_UCHAR *temp = (PCRE2_UCHAR *)codestart; - if (PRIV(auto_possessify)(temp, &cb) != 0) - { - PCRE2_DEBUG_UNREACHABLE(); - errorcode = ERR80; - } + if (PRIV(auto_possessify)(temp, &cb) != 0) errorcode = ERR80; } /* Failed to compile, or error while post-processing. */ @@ -10875,21 +10814,18 @@ or anything else, such as starting with non-atomic .* when DOTALL is set and there are no occurrences of *PRUNE or *SKIP (though there is an option to disable this case). */ -if ((re->overall_options & PCRE2_ANCHORED) == 0) - { - BOOL dotstar_anchor = ((optim_flags & PCRE2_OPTIM_DOTSTAR_ANCHOR) != 0); - if (is_anchored(codestart, 0, &cb, 0, FALSE, dotstar_anchor)) - re->overall_options |= PCRE2_ANCHORED; - } +if ((re->overall_options & PCRE2_ANCHORED) == 0 && + is_anchored(codestart, 0, &cb, 0, FALSE)) + re->overall_options |= PCRE2_ANCHORED; /* Set up the first code unit or startline flag, the required code unit, and -then study the pattern. This code need not be obeyed if PCRE2_OPTIM_START_OPTIMIZE -is disabled, as the data it would create will not be used. Note that a first code +then study the pattern. This code need not be obeyed if PCRE2_NO_START_OPTIMIZE +is set, as the data it would create will not be used. Note that a first code unit (but not the startline flag) is useful for anchored patterns because it can still give a quick "no match" and also avoid searching for a last code unit. */ -if ((optim_flags & PCRE2_OPTIM_START_OPTIMIZE) != 0) +if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0) { int minminlength = 0; /* For minimal minlength from first/required CU */ @@ -10897,19 +10833,8 @@ if ((optim_flags & PCRE2_OPTIM_START_OPTIMIZE) != 0) (these are not saved during the compile because they can cause conflicts with actual literals that follow). */ - if (firstcuflags >= REQ_NONE) { - uint32_t assertedcuflags = 0; - uint32_t assertedcu = find_firstassertedcu(codestart, &assertedcuflags, 0); - /* It would be wrong to use the asserted first code unit as `firstcu` for - * regexes which are able to match a 1-character string (e.g. /(?=a)b?a/) - * For that example, if we set both firstcu and reqcu to 'a', it would mean - * the subject string needs to be at least 2 characters long, which is wrong. - * With more analysis, we would be able to set firstcu in more cases. */ - if (assertedcuflags < REQ_NONE && assertedcu != reqcu) { - firstcu = assertedcu; - firstcuflags = assertedcuflags; - } - } + if (firstcuflags >= REQ_NONE) + firstcu = find_firstassertedcu(codestart, &firstcuflags, 0); /* Save the data for a first code unit. The existence of one means the minimum length must be at least 1. */ @@ -10930,8 +10855,8 @@ if ((optim_flags & PCRE2_OPTIM_START_OPTIMIZE) != 0) } /* The first code unit is > 128 in UTF or UCP mode, or > 255 otherwise. - In 8-bit UTF mode, code units in the range 128-255 are introductory code - units and cannot have another case, but if UCP is set they may do. */ + In 8-bit UTF mode, codepoints in the range 128-255 are introductory code + points and cannot have another case, but if UCP is set they may do. */ #ifdef SUPPORT_UNICODE #if PCRE2_CODE_UNIT_WIDTH == 8 @@ -10952,12 +10877,9 @@ if ((optim_flags & PCRE2_OPTIM_START_OPTIMIZE) != 0) non-DOTALL matches when *PRUNE and SKIP are not present. (There is an option that disables this case.) */ - else if ((re->overall_options & PCRE2_ANCHORED) == 0) - { - BOOL dotstar_anchor = ((optim_flags & PCRE2_OPTIM_DOTSTAR_ANCHOR) != 0); - if (is_startline(codestart, 0, &cb, 0, FALSE, dotstar_anchor)) - re->flags |= PCRE2_STARTLINE; - } + else if ((re->overall_options & PCRE2_ANCHORED) == 0 && + is_startline(codestart, 0, &cb, 0, FALSE)) + re->flags |= PCRE2_STARTLINE; /* Handle the "required code unit", if one is set. In the UTF case we can increment the minimum minimum length only if we are sure this really is a @@ -11017,7 +10939,6 @@ if ((optim_flags & PCRE2_OPTIM_START_OPTIMIZE) != 0) if (PRIV(study)(re) != 0) { - PCRE2_DEBUG_UNREACHABLE(); errorcode = ERR31; goto HAD_CB_ERROR; } @@ -11040,10 +10961,6 @@ version of the pattern, free it before returning. Also free the list of named groups if a larger one had to be obtained, and likewise the group information vector. */ -#ifdef SUPPORT_UNICODE -PCRE2_ASSERT(cb.cranges == NULL); -#endif - EXIT: #ifdef SUPPORT_VALGRIND if (zero_terminated) VALGRIND_MAKE_MEM_DEFINED(pattern + patlen, CU2BYTES(1)); @@ -11054,7 +10971,6 @@ if (cb.named_group_list_size > NAMED_GROUP_LIST_SIZE) ccontext->memctl.free((void *)cb.named_groups, ccontext->memctl.memory_data); if (cb.groupinfo != stack_groupinfo) ccontext->memctl.free((void *)cb.groupinfo, ccontext->memctl.memory_data); - return re; /* Will be NULL after an error */ /* Errors discovered in parse_regex() set the offset value in the compile @@ -11067,28 +10983,12 @@ an offset is available in the parsed pattern. */ ptr = pattern + cb.erroroffset; HAD_EARLY_ERROR: -PCRE2_ASSERT(ptr >= pattern); /* Ensure we don't return invalid erroroffset */ -PCRE2_ASSERT(ptr <= (pattern + patlen)); *erroroffset = ptr - pattern; HAD_ERROR: *errorptr = errorcode; pcre2_code_free(re); re = NULL; - -#ifdef SUPPORT_WIDE_CHARS -if (cb.cranges != NULL) - { - class_ranges* cranges = cb.cranges; - do - { - class_ranges* next_cranges = cranges->next; - cb.cx->memctl.free(cranges, cb.cx->memctl.memory_data); - cranges = next_cranges; - } - while (cranges != NULL); - } -#endif goto EXIT; } diff --git a/ext/pcre/pcre2lib/pcre2_compile.h b/ext/pcre/pcre2lib/pcre2_compile.h deleted file mode 100644 index c8bf610bed547..0000000000000 --- a/ext/pcre/pcre2lib/pcre2_compile.h +++ /dev/null @@ -1,280 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE2 is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2024 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * 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. - - * Neither the name of the University of Cambridge 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 OWNER 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 PCRE2_COMPILE_H_IDEMPOTENT_GUARD -#define PCRE2_COMPILE_H_IDEMPOTENT_GUARD - -#include "pcre2_internal.h" - -/* Compile time error code numbers. They are given names so that they can more -easily be tracked. When a new number is added, the tables called eint1 and -eint2 in pcre2posix.c may need to be updated, and a new error text must be -added to compile_error_texts in pcre2_error.c. Also, the error codes in -pcre2.h.in must be updated - their values are exactly 100 greater than these -values. */ - -enum { ERR0 = COMPILE_ERROR_BASE, - ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9, ERR10, - ERR11, ERR12, ERR13, ERR14, ERR15, ERR16, ERR17, ERR18, ERR19, ERR20, - ERR21, ERR22, ERR23, ERR24, ERR25, ERR26, ERR27, ERR28, ERR29, ERR30, - ERR31, ERR32, ERR33, ERR34, ERR35, ERR36, ERR37, ERR38, ERR39, ERR40, - ERR41, ERR42, ERR43, ERR44, ERR45, ERR46, ERR47, ERR48, ERR49, ERR50, - ERR51, ERR52, ERR53, ERR54, ERR55, ERR56, ERR57, ERR58, ERR59, ERR60, - ERR61, ERR62, ERR63, ERR64, ERR65, ERR66, ERR67, ERR68, ERR69, ERR70, - ERR71, ERR72, ERR73, ERR74, ERR75, ERR76, ERR77, ERR78, ERR79, ERR80, - ERR81, ERR82, ERR83, ERR84, ERR85, ERR86, ERR87, ERR88, ERR89, ERR90, - ERR91, ERR92, ERR93, ERR94, ERR95, ERR96, ERR97, ERR98, ERR99, ERR100, - ERR101,ERR102,ERR103,ERR104,ERR105,ERR106,ERR107,ERR108,ERR109,ERR110, - ERR111,ERR112,ERR113,ERR114,ERR115,ERR116 }; - -/* Code values for parsed patterns, which are stored in a vector of 32-bit -unsigned ints. Values less than META_END are literal data values. The coding -for identifying the item is in the top 16-bits, leaving 16 bits for the -additional data that some of them need. The META_CODE, META_DATA, and META_DIFF -macros are used to manipulate parsed pattern elements. - -NOTE: When these definitions are changed, the table of extra lengths for each -code (meta_extra_lengths) must be updated to remain in step. */ - -#define META_END 0x80000000u /* End of pattern */ - -#define META_ALT 0x80010000u /* alternation */ -#define META_ATOMIC 0x80020000u /* atomic group */ -#define META_BACKREF 0x80030000u /* Back ref */ -#define META_BACKREF_BYNAME 0x80040000u /* \k'name' */ -#define META_BIGVALUE 0x80050000u /* Next is a literal > META_END */ -#define META_CALLOUT_NUMBER 0x80060000u /* (?C with numerical argument */ -#define META_CALLOUT_STRING 0x80070000u /* (?C with string argument */ -#define META_CAPTURE 0x80080000u /* Capturing parenthesis */ -#define META_CIRCUMFLEX 0x80090000u /* ^ metacharacter */ -#define META_CLASS 0x800a0000u /* start non-empty class */ -#define META_CLASS_EMPTY 0x800b0000u /* empty class */ -#define META_CLASS_EMPTY_NOT 0x800c0000u /* negative empty class */ -#define META_CLASS_END 0x800d0000u /* end of non-empty class */ -#define META_CLASS_NOT 0x800e0000u /* start non-empty negative class */ -#define META_COND_ASSERT 0x800f0000u /* (?(?assertion)... */ -#define META_COND_DEFINE 0x80100000u /* (?(DEFINE)... */ -#define META_COND_NAME 0x80110000u /* (?()... */ -#define META_COND_NUMBER 0x80120000u /* (?(digits)... */ -#define META_COND_RNAME 0x80130000u /* (?(R&name)... */ -#define META_COND_RNUMBER 0x80140000u /* (?(Rdigits)... */ -#define META_COND_VERSION 0x80150000u /* (?(VERSIONx.y)... */ -#define META_OFFSET 0x80160000u /* Setting offset for various - META codes (e.g. META_SCS_NAME) */ -#define META_SCS 0x80170000u /* (*scan_substring:... */ -#define META_SCS_NAME 0x80180000u /* Next of scan_substring */ -#define META_SCS_NUMBER 0x80190000u /* Next digits of scan_substring */ -#define META_DOLLAR 0x801a0000u /* $ metacharacter */ -#define META_DOT 0x801b0000u /* . metacharacter */ -#define META_ESCAPE 0x801c0000u /* \d and friends */ -#define META_KET 0x801d0000u /* closing parenthesis */ -#define META_NOCAPTURE 0x801e0000u /* no capture parens */ -#define META_OPTIONS 0x801f0000u /* (?i) and friends */ -#define META_POSIX 0x80200000u /* POSIX class item */ -#define META_POSIX_NEG 0x80210000u /* negative POSIX class item */ -#define META_RANGE_ESCAPED 0x80220000u /* range with at least one escape */ -#define META_RANGE_LITERAL 0x80230000u /* range defined literally */ -#define META_RECURSE 0x80240000u /* Recursion */ -#define META_RECURSE_BYNAME 0x80250000u /* (?&name) */ -#define META_SCRIPT_RUN 0x80260000u /* (*script_run:...) */ - -/* These must be kept together to make it easy to check that an assertion -is present where expected in a conditional group. */ - -#define META_LOOKAHEAD 0x80270000u /* (?= */ -#define META_LOOKAHEADNOT 0x80280000u /* (?! */ -#define META_LOOKBEHIND 0x80290000u /* (?<= */ -#define META_LOOKBEHINDNOT 0x802a0000u /* (?>16) - -/* Extended class management flags. */ - -#define CLASS_IS_ECLASS 0x1 - -/* Macro for the highest character value. */ - -#if PCRE2_CODE_UNIT_WIDTH == 8 -#define MAX_UCHAR_VALUE 0xffu -#elif PCRE2_CODE_UNIT_WIDTH == 16 -#define MAX_UCHAR_VALUE 0xffffu -#else -#define MAX_UCHAR_VALUE 0xffffffffu -#endif - -#define GET_MAX_CHAR_VALUE(utf) \ - ((utf) ? MAX_UTF_CODE_POINT : MAX_UCHAR_VALUE) - -/* Macro for setting individual bits in class bitmaps. */ - -#define SETBIT(a,b) a[(b) >> 3] |= (uint8_t)(1u << ((b) & 0x7)) - -/* Macro for 8 bit specific checks. */ -#if PCRE2_CODE_UNIT_WIDTH == 8 -#define SELECT_VALUE8(value8, value) (value8) -#else -#define SELECT_VALUE8(value8, value) (value) -#endif - -/* Macro for aligning data. */ -#define CLIST_ALIGN_TO(base, align) \ - ((base + ((size_t)(align) - 1)) & ~((size_t)(align) - 1)) - -/* Structure for holding information about an OP_ECLASS internal operand. -An "operand" here could be just a single OP_[X]CLASS, or it could be some -complex expression; but it's some sequence of ECL_* codes which pushes one -value to the stack. */ -typedef struct { - /* The position of the operand - or NULL if (lengthptr != NULL). */ - PCRE2_UCHAR *code_start; - PCRE2_SIZE length; - /* The operand's type if it is a single code (ECL_XCLASS, ECL_ANY, ECL_NONE); - otherwise zero if the operand is not atomic. */ - uint8_t op_single_type; - /* Regardless of whether it's a single code or not, we fully constant-fold - the bitmap for code points < 256. */ - class_bits_storage bits; -} eclass_op_info; - -/* Macros for the definitions below, to prevent name collisions. */ - -#define _pcre2_posix_class_maps PCRE2_SUFFIX(_pcre2_posix_class_maps) -#define _pcre2_update_classbits PCRE2_SUFFIX(_pcre2_update_classbits_) -#define _pcre2_compile_class_nested PCRE2_SUFFIX(_pcre2_compile_class_nested_) -#define _pcre2_compile_class_not_nested PCRE2_SUFFIX(_pcre2_compile_class_not_nested_) - - -/* Indices of the POSIX classes in posix_names, posix_name_lengths, -posix_class_maps, and posix_substitutes. They must be kept in sync. */ - -#define PC_DIGIT 7 -#define PC_GRAPH 8 -#define PC_PRINT 9 -#define PC_PUNCT 10 -#define PC_XDIGIT 13 - -extern const int PRIV(posix_class_maps)[]; - - -/* Set bits in classbits according to the property type */ - -void PRIV(update_classbits)(uint32_t ptype, uint32_t pdata, BOOL negated, - uint8_t *classbits); - -/* Compile the META codes from start_ptr...end_ptr, writing a single OP_CLASS -OP_CLASS, OP_NCLASS, OP_XCLASS, or OP_ALLANY into pcode. */ - -uint32_t *PRIV(compile_class_not_nested)(uint32_t options, uint32_t xoptions, - uint32_t *start_ptr, PCRE2_UCHAR **pcode, BOOL negate_class, BOOL* has_bitmap, - int *errorcodeptr, compile_block *cb, PCRE2_SIZE *lengthptr); - -/* Compile the META codes in pptr into opcodes written to pcode. The pptr must -start at a META_CLASS or META_CLASS_NOT. - -The pptr will be left pointing at the matching META_CLASS_END. */ - -BOOL PRIV(compile_class_nested)(uint32_t options, uint32_t xoptions, - uint32_t **pptr, PCRE2_UCHAR **pcode, int *errorcodeptr, - compile_block *cb, PCRE2_SIZE *lengthptr); - -#endif /* PCRE2_COMPILE_H_IDEMPOTENT_GUARD */ - -/* End of pcre2_compile.h */ diff --git a/ext/pcre/pcre2lib/pcre2_compile_class.c b/ext/pcre/pcre2lib/pcre2_compile_class.c deleted file mode 100644 index 6a73bb9a71b9e..0000000000000 --- a/ext/pcre/pcre2lib/pcre2_compile_class.c +++ /dev/null @@ -1,2737 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2024 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * 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. - - * Neither the name of the University of Cambridge 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 OWNER 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. ------------------------------------------------------------------------------ -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "pcre2_compile.h" - -typedef struct { - /* Option bits for eclass. */ - uint32_t options; - uint32_t xoptions; - /* Rarely used members. */ - int *errorcodeptr; - compile_block *cb; - /* Bitmap is needed. */ - BOOL needs_bitmap; -} eclass_context; - -/* Checks the allowed tokens at the end of a class structure in debug mode. -When a new token is not processed by all loops, and the token is equals to -a) one of the cases here: - the compiler will complain about a duplicated case value. -b) none of the cases here: - the loop without the handler will stop with an assertion failure. */ - -#ifdef PCRE2_DEBUG -#define CLASS_END_CASES(meta) \ - default: \ - PCRE2_ASSERT((meta) <= META_END); \ - /* Fall through */ \ - case META_CLASS: \ - case META_CLASS_NOT: \ - case META_CLASS_EMPTY: \ - case META_CLASS_EMPTY_NOT: \ - case META_CLASS_END: \ - case META_ECLASS_AND: \ - case META_ECLASS_OR: \ - case META_ECLASS_SUB: \ - case META_ECLASS_XOR: \ - case META_ECLASS_NOT: -#else -#define CLASS_END_CASES(meta) \ - default: -#endif - -#ifdef SUPPORT_WIDE_CHARS - -/* Heapsort algorithm. */ - -static void do_heapify(uint32_t *buffer, size_t size, size_t i) -{ -size_t max; -size_t left; -size_t right; -uint32_t tmp1, tmp2; - -while (TRUE) - { - max = i; - left = (i << 1) + 2; - right = left + 2; - - if (left < size && buffer[left] > buffer[max]) max = left; - if (right < size && buffer[right] > buffer[max]) max = right; - if (i == max) return; - - /* Swap items. */ - tmp1 = buffer[i]; - tmp2 = buffer[i + 1]; - buffer[i] = buffer[max]; - buffer[i + 1] = buffer[max + 1]; - buffer[max] = tmp1; - buffer[max + 1] = tmp2; - i = max; - } -} - -#ifdef SUPPORT_UNICODE - -#define PARSE_CLASS_UTF 0x1 -#define PARSE_CLASS_CASELESS_UTF 0x2 -#define PARSE_CLASS_RESTRICTED_UTF 0x4 -#define PARSE_CLASS_TURKISH_UTF 0x8 - -/* Get the range of nocase characters which includes the -'c' character passed as argument, or directly follows 'c'. */ - -static const uint32_t* -get_nocase_range(uint32_t c) -{ -uint32_t left = 0; -uint32_t right = PRIV(ucd_nocase_ranges_size); -uint32_t middle; - -if (c > MAX_UTF_CODE_POINT) return PRIV(ucd_nocase_ranges) + right; - -while (TRUE) - { - /* Range end of the middle element. */ - middle = ((left + right) >> 1) | 0x1; - - if (PRIV(ucd_nocase_ranges)[middle] <= c) - left = middle + 1; - else if (middle > 1 && PRIV(ucd_nocase_ranges)[middle - 2] > c) - right = middle - 1; - else - return PRIV(ucd_nocase_ranges) + (middle - 1); - } -} - -/* Get the list of othercase characters, which belongs to the passed range. -Create ranges from these characters, and append them to the buffer argument. */ - -static size_t -utf_caseless_extend(uint32_t start, uint32_t end, uint32_t options, - uint32_t *buffer) -{ -uint32_t new_start = start; -uint32_t new_end = end; -uint32_t c = start; -const uint32_t *list; -uint32_t tmp[3]; -size_t result = 2; -const uint32_t *skip_range = get_nocase_range(c); -uint32_t skip_start = skip_range[0]; - -#if PCRE2_CODE_UNIT_WIDTH == 8 -PCRE2_ASSERT(options & PARSE_CLASS_UTF); -#endif - -#if PCRE2_CODE_UNIT_WIDTH == 32 -if (end > MAX_UTF_CODE_POINT) end = MAX_UTF_CODE_POINT; -#endif - -while (c <= end) - { - uint32_t co; - - if (c > skip_start) - { - c = skip_range[1]; - skip_range += 2; - skip_start = skip_range[0]; - continue; - } - - /* Compute caseless set. */ - - if ((options & (PARSE_CLASS_TURKISH_UTF|PARSE_CLASS_RESTRICTED_UTF)) == - PARSE_CLASS_TURKISH_UTF && - UCD_ANY_I(c)) - { - co = PRIV(ucd_turkish_dotted_i_caseset) + (UCD_DOTTED_I(c)? 0 : 3); - } - else if ((co = UCD_CASESET(c)) != 0 && - (options & PARSE_CLASS_RESTRICTED_UTF) != 0 && - PRIV(ucd_caseless_sets)[co] < 128) - { - co = 0; /* Ignore the caseless set if it's restricted. */ - } - - if (co != 0) - list = PRIV(ucd_caseless_sets) + co; - else - { - co = UCD_OTHERCASE(c); - list = tmp; - tmp[0] = c; - tmp[1] = NOTACHAR; - - if (co != c) - { - tmp[1] = co; - tmp[2] = NOTACHAR; - } - } - c++; - - /* Add characters. */ - do - { -#if PCRE2_CODE_UNIT_WIDTH == 16 - if (!(options & PARSE_CLASS_UTF) && *list > 0xffff) continue; -#endif - - if (*list < new_start) - { - if (*list + 1 == new_start) - { - new_start--; - continue; - } - } - else if (*list > new_end) - { - if (*list - 1 == new_end) - { - new_end++; - continue; - } - } - else continue; - - result += 2; - if (buffer != NULL) - { - buffer[0] = *list; - buffer[1] = *list; - buffer += 2; - } - } - while (*(++list) != NOTACHAR); - } - - if (buffer != NULL) - { - buffer[0] = new_start; - buffer[1] = new_end; - buffer += 2; - (void)buffer; - } - return result; -} - -#endif - -/* Add a character list to a buffer. */ - -static size_t -append_char_list(const uint32_t *p, uint32_t *buffer) -{ -const uint32_t *n; -size_t result = 0; - -while (*p != NOTACHAR) - { - n = p; - while (n[0] == n[1] - 1) n++; - - PCRE2_ASSERT(*p < 0xffff); - - if (buffer != NULL) - { - buffer[0] = *p; - buffer[1] = *n; - buffer += 2; - } - - result += 2; - p = n + 1; - } - - return result; -} - -static uint32_t -get_highest_char(uint32_t options) -{ -(void)options; /* Avoid compiler warning. */ - -#if PCRE2_CODE_UNIT_WIDTH == 8 -return MAX_UTF_CODE_POINT; -#else -#ifdef SUPPORT_UNICODE -return GET_MAX_CHAR_VALUE((options & PARSE_CLASS_UTF) != 0); -#else -return MAX_UCHAR_VALUE; -#endif -#endif -} - -/* Add a negated character list to a buffer. */ -static size_t -append_negated_char_list(const uint32_t *p, uint32_t options, uint32_t *buffer) -{ -const uint32_t *n; -uint32_t start = 0; -size_t result = 2; - -PCRE2_ASSERT(*p > 0); - -while (*p != NOTACHAR) - { - n = p; - while (n[0] == n[1] - 1) n++; - - PCRE2_ASSERT(*p < 0xffff); - - if (buffer != NULL) - { - buffer[0] = start; - buffer[1] = *p - 1; - buffer += 2; - } - - result += 2; - start = *n + 1; - p = n + 1; - } - - if (buffer != NULL) - { - buffer[0] = start; - buffer[1] = get_highest_char(options); - buffer += 2; - (void)buffer; - } - - return result; -} - -static uint32_t * -append_non_ascii_range(uint32_t options, uint32_t *buffer) -{ - if (buffer == NULL) return NULL; - - buffer[0] = 0x100; - buffer[1] = get_highest_char(options); - return buffer + 2; -} - -static size_t -parse_class(uint32_t *ptr, uint32_t options, uint32_t *buffer) -{ -size_t total_size = 0; -size_t size; -uint32_t meta_arg; -uint32_t start_char; - -while (TRUE) - { - switch (META_CODE(*ptr)) - { - case META_ESCAPE: - meta_arg = META_DATA(*ptr); - switch (meta_arg) - { - case ESC_D: - case ESC_W: - case ESC_S: - buffer = append_non_ascii_range(options, buffer); - total_size += 2; - break; - - case ESC_h: - size = append_char_list(PRIV(hspace_list), buffer); - total_size += size; - if (buffer != NULL) buffer += size; - break; - - case ESC_H: - size = append_negated_char_list(PRIV(hspace_list), options, buffer); - total_size += size; - if (buffer != NULL) buffer += size; - break; - - case ESC_v: - size = append_char_list(PRIV(vspace_list), buffer); - total_size += size; - if (buffer != NULL) buffer += size; - break; - - case ESC_V: - size = append_negated_char_list(PRIV(vspace_list), options, buffer); - total_size += size; - if (buffer != NULL) buffer += size; - break; - - case ESC_p: - case ESC_P: - ptr++; - if (meta_arg == ESC_p && (*ptr >> 16) == PT_ANY) - { - if (buffer != NULL) - { - buffer[0] = 0; - buffer[1] = get_highest_char(options); - buffer += 2; - } - total_size += 2; - } - break; - } - ptr++; - continue; - case META_POSIX_NEG: - buffer = append_non_ascii_range(options, buffer); - total_size += 2; - ptr += 2; - continue; - case META_POSIX: - ptr += 2; - continue; - case META_BIGVALUE: - /* Character literal */ - ptr++; - break; - CLASS_END_CASES(*ptr) - if (*ptr >= META_END) return total_size; - break; - } - - start_char = *ptr; - - if (ptr[1] == META_RANGE_LITERAL || ptr[1] == META_RANGE_ESCAPED) - { - ptr += 2; - PCRE2_ASSERT(*ptr < META_END || *ptr == META_BIGVALUE); - - if (*ptr == META_BIGVALUE) ptr++; - -#ifdef EBCDIC -#error "Missing EBCDIC support" -#endif - } - -#ifdef SUPPORT_UNICODE - if (options & PARSE_CLASS_CASELESS_UTF) - { - size = utf_caseless_extend(start_char, *ptr++, options, buffer); - if (buffer != NULL) buffer += size; - total_size += size; - continue; - } -#endif - - if (buffer != NULL) - { - buffer[0] = start_char; - buffer[1] = *ptr; - buffer += 2; - } - - ptr++; - total_size += 2; - } - - return total_size; -} - -/* Extra uint32_t values for storing the lengths of range lists in -the worst case. Two uint32_t lengths and a range end for a range -starting before 255 */ -#define CHAR_LIST_EXTRA_SIZE 3 - -/* Starting character values for each character list. */ - -static const uint32_t char_list_starts[] = { -#if PCRE2_CODE_UNIT_WIDTH == 32 - XCL_CHAR_LIST_HIGH_32_START, -#endif -#if PCRE2_CODE_UNIT_WIDTH == 32 || defined SUPPORT_UNICODE - XCL_CHAR_LIST_LOW_32_START, -#endif - XCL_CHAR_LIST_HIGH_16_START, - /* Must be terminated by XCL_CHAR_LIST_LOW_16_START, - which also represents the end of the bitset. */ - XCL_CHAR_LIST_LOW_16_START, -}; - -static class_ranges * -compile_optimize_class(uint32_t *start_ptr, uint32_t options, - uint32_t xoptions, compile_block *cb) -{ -class_ranges* cranges; -uint32_t *ptr; -uint32_t *buffer; -uint32_t *dst; -uint32_t class_options = 0; -size_t range_list_size = 0, total_size, i; -uint32_t tmp1, tmp2; -const uint32_t *char_list_next; -uint16_t *next_char; -uint32_t char_list_start, char_list_end; -uint32_t range_start, range_end; - -#ifdef SUPPORT_UNICODE -if (options & PCRE2_UTF) - class_options |= PARSE_CLASS_UTF; - -if ((options & PCRE2_CASELESS) && (options & (PCRE2_UTF|PCRE2_UCP))) - class_options |= PARSE_CLASS_CASELESS_UTF; - -if (xoptions & PCRE2_EXTRA_CASELESS_RESTRICT) - class_options |= PARSE_CLASS_RESTRICTED_UTF; - -if (xoptions & PCRE2_EXTRA_TURKISH_CASING) - class_options |= PARSE_CLASS_TURKISH_UTF; -#endif - -/* Compute required space for the range. */ - -range_list_size = parse_class(start_ptr, class_options, NULL); -PCRE2_ASSERT((range_list_size & 0x1) == 0); - -/* Allocate buffer. The total_size also represents the end of the buffer. */ - -total_size = range_list_size + - ((range_list_size >= 2) ? CHAR_LIST_EXTRA_SIZE : 0); - -cranges = cb->cx->memctl.malloc( - sizeof(class_ranges) + total_size * sizeof(uint32_t), - cb->cx->memctl.memory_data); - -if (cranges == NULL) return NULL; - -cranges->next = NULL; -cranges->range_list_size = (uint16_t)range_list_size; -cranges->char_lists_types = 0; -cranges->char_lists_size = 0; -cranges->char_lists_start = 0; - -if (range_list_size == 0) return cranges; - -buffer = (uint32_t*)(cranges + 1); -parse_class(start_ptr, class_options, buffer); - -/* Using <= instead of == to help static analysis. */ -if (range_list_size <= 2) return cranges; - -/* In-place sorting of ranges. */ - -i = (((range_list_size >> 2) - 1) << 1); -while (TRUE) - { - do_heapify(buffer, range_list_size, i); - if (i == 0) break; - i -= 2; - } - -i = range_list_size - 2; -while (TRUE) - { - tmp1 = buffer[i]; - tmp2 = buffer[i + 1]; - buffer[i] = buffer[0]; - buffer[i + 1] = buffer[1]; - buffer[0] = tmp1; - buffer[1] = tmp2; - - do_heapify(buffer, i, 0); - if (i == 0) break; - i -= 2; - } - -/* Merge ranges whenever possible. */ -dst = buffer; -ptr = buffer + 2; -range_list_size -= 2; - -/* The second condition is a very rare corner case, where the end of the last -range is the maximum character. This range cannot be extended further. */ - -while (range_list_size > 0 && dst[1] != ~(uint32_t)0) - { - if (dst[1] + 1 < ptr[0]) - { - dst += 2; - dst[0] = ptr[0]; - dst[1] = ptr[1]; - } - else if (dst[1] < ptr[1]) dst[1] = ptr[1]; - - ptr += 2; - range_list_size -= 2; - } - -PCRE2_ASSERT(dst[1] <= get_highest_char(class_options)); - -/* When the number of ranges are less than six, -they are not converted to range lists. */ - -ptr = buffer; -while (ptr < dst && ptr[1] < 0x100) ptr += 2; -if (dst - ptr < (2 * (6 - 1))) - { - cranges->range_list_size = (uint16_t)(dst + 2 - buffer); - return cranges; - } - -/* Compute character lists structures. */ - -char_list_next = char_list_starts; -char_list_start = *char_list_next++; -#if PCRE2_CODE_UNIT_WIDTH == 32 -char_list_end = XCL_CHAR_LIST_HIGH_32_END; -#elif defined SUPPORT_UNICODE -char_list_end = XCL_CHAR_LIST_LOW_32_END; -#else -char_list_end = XCL_CHAR_LIST_HIGH_16_END; -#endif -next_char = (uint16_t*)(buffer + total_size); - -tmp1 = 0; -tmp2 = ((sizeof(char_list_starts) / sizeof(uint32_t)) - 1) * XCL_TYPE_BIT_LEN; -PCRE2_ASSERT(tmp2 <= 3 * XCL_TYPE_BIT_LEN && tmp2 >= XCL_TYPE_BIT_LEN); -range_start = dst[0]; -range_end = dst[1]; - -while (TRUE) - { - if (range_start >= char_list_start) - { - if (range_start == range_end || range_end < char_list_end) - { - tmp1++; - next_char--; - - if (char_list_start < XCL_CHAR_LIST_LOW_32_START) - *next_char = (uint16_t)((range_end << XCL_CHAR_SHIFT) | XCL_CHAR_END); - else - *(uint32_t*)(--next_char) = - (range_end << XCL_CHAR_SHIFT) | XCL_CHAR_END; - } - - if (range_start < range_end) - { - if (range_start > char_list_start) - { - tmp1++; - next_char--; - - if (char_list_start < XCL_CHAR_LIST_LOW_32_START) - *next_char = (uint16_t)(range_start << XCL_CHAR_SHIFT); - else - *(uint32_t*)(--next_char) = (range_start << XCL_CHAR_SHIFT); - } - else - cranges->char_lists_types |= XCL_BEGIN_WITH_RANGE << tmp2; - } - - PCRE2_ASSERT((uint32_t*)next_char >= dst + 2); - - if (dst > buffer) - { - dst -= 2; - range_start = dst[0]; - range_end = dst[1]; - continue; - } - - range_start = 0; - range_end = 0; - } - - if (range_end >= char_list_start) - { - PCRE2_ASSERT(range_start < char_list_start); - - if (range_end < char_list_end) - { - tmp1++; - next_char--; - - if (char_list_start < XCL_CHAR_LIST_LOW_32_START) - *next_char = (uint16_t)((range_end << XCL_CHAR_SHIFT) | XCL_CHAR_END); - else - *(uint32_t*)(--next_char) = - (range_end << XCL_CHAR_SHIFT) | XCL_CHAR_END; - - PCRE2_ASSERT((uint32_t*)next_char >= dst + 2); - } - - cranges->char_lists_types |= XCL_BEGIN_WITH_RANGE << tmp2; - } - - if (tmp1 >= XCL_ITEM_COUNT_MASK) - { - cranges->char_lists_types |= XCL_ITEM_COUNT_MASK << tmp2; - next_char--; - - if (char_list_start < XCL_CHAR_LIST_LOW_32_START) - *next_char = (uint16_t)tmp1; - else - *(uint32_t*)(--next_char) = tmp1; - } - else - cranges->char_lists_types |= tmp1 << tmp2; - - if (range_start < XCL_CHAR_LIST_LOW_16_START) break; - - PCRE2_ASSERT(tmp2 >= XCL_TYPE_BIT_LEN); - char_list_end = char_list_start - 1; - char_list_start = *char_list_next++; - tmp1 = 0; - tmp2 -= XCL_TYPE_BIT_LEN; - } - -if (dst[0] < XCL_CHAR_LIST_LOW_16_START) dst += 2; -PCRE2_ASSERT((uint16_t*)dst <= next_char); - -cranges->char_lists_size = - (size_t)((uint8_t*)(buffer + total_size) - (uint8_t*)next_char); -cranges->char_lists_start = (size_t)((uint8_t*)next_char - (uint8_t*)buffer); -cranges->range_list_size = (uint16_t)(dst - buffer); -return cranges; -} - -#endif /* SUPPORT_WIDE_CHARS */ - -#ifdef SUPPORT_UNICODE - -void PRIV(update_classbits)(uint32_t ptype, uint32_t pdata, BOOL negated, - uint8_t *classbits) -{ -/* Update PRIV(xclass) when this function is changed. */ -int c, chartype; -const ucd_record *prop; -uint32_t gentype; -BOOL set_bit; - -if (ptype == PT_ANY) - { - if (!negated) memset(classbits, 0xff, 32); - return; - } - -for (c = 0; c < 256; c++) - { - prop = GET_UCD(c); - set_bit = FALSE; - (void)set_bit; - - switch (ptype) - { - case PT_LAMP: - chartype = prop->chartype; - set_bit = (chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt); - break; - - case PT_GC: - set_bit = (PRIV(ucp_gentype)[prop->chartype] == pdata); - break; - - case PT_PC: - set_bit = (prop->chartype == pdata); - break; - - case PT_SC: - set_bit = (prop->script == pdata); - break; - - case PT_SCX: - set_bit = (prop->script == pdata || - MAPBIT(PRIV(ucd_script_sets) + UCD_SCRIPTX_PROP(prop), pdata) != 0); - break; - - case PT_ALNUM: - gentype = PRIV(ucp_gentype)[prop->chartype]; - set_bit = (gentype == ucp_L || gentype == ucp_N); - break; - - case PT_SPACE: /* Perl space */ - case PT_PXSPACE: /* POSIX space */ - switch(c) - { - HSPACE_BYTE_CASES: - VSPACE_BYTE_CASES: - set_bit = TRUE; - break; - - default: - set_bit = (PRIV(ucp_gentype)[prop->chartype] == ucp_Z); - break; - } - break; - - case PT_WORD: - chartype = prop->chartype; - gentype = PRIV(ucp_gentype)[chartype]; - set_bit = (gentype == ucp_L || gentype == ucp_N || - chartype == ucp_Mn || chartype == ucp_Pc); - break; - - case PT_UCNC: - set_bit = (c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT || - c == CHAR_GRAVE_ACCENT || c >= 0xa0); - break; - - case PT_BIDICL: - set_bit = (UCD_BIDICLASS_PROP(prop) == pdata); - break; - - case PT_BOOL: - set_bit = MAPBIT(PRIV(ucd_boolprop_sets) + - UCD_BPROPS_PROP(prop), pdata) != 0; - break; - - case PT_PXGRAPH: - chartype = prop->chartype; - gentype = PRIV(ucp_gentype)[chartype]; - set_bit = (gentype != ucp_Z && (gentype != ucp_C || chartype == ucp_Cf)); - break; - - case PT_PXPRINT: - chartype = prop->chartype; - set_bit = (chartype != ucp_Zl && chartype != ucp_Zp && - (PRIV(ucp_gentype)[chartype] != ucp_C || chartype == ucp_Cf)); - break; - - case PT_PXPUNCT: - gentype = PRIV(ucp_gentype)[prop->chartype]; - set_bit = (gentype == ucp_P || (c < 128 && gentype == ucp_S)); - break; - - default: - PCRE2_ASSERT(ptype == PT_PXXDIGIT); - set_bit = (c >= CHAR_0 && c <= CHAR_9) || - (c >= CHAR_A && c <= CHAR_F) || - (c >= CHAR_a && c <= CHAR_f); - break; - } - - if (negated) set_bit = !set_bit; - if (set_bit) *classbits |= (uint8_t)(1 << (c & 0x7)); - if ((c & 0x7) == 0x7) classbits++; - } -} - -#endif /* SUPPORT_UNICODE */ - - - -#ifdef SUPPORT_WIDE_CHARS - -/************************************************* -* XClass related properties * -*************************************************/ - -/* XClass needs to be generated. */ -#define XCLASS_REQUIRED 0x1 -/* XClass has 8 bit character. */ -#define XCLASS_HAS_8BIT_CHARS 0x2 -/* XClass has properties. */ -#define XCLASS_HAS_PROPS 0x4 -/* XClass has character lists. */ -#define XCLASS_HAS_CHAR_LISTS 0x8 -/* XClass matches to all >= 256 characters. */ -#define XCLASS_HIGH_ANY 0x10 - -#endif - - -/************************************************* -* Internal entry point for add range to class * -*************************************************/ - -/* This function sets the overall range for characters < 256. -It also handles non-utf case folding. - -Arguments: - options the options bits - xoptions the extra options bits - cb compile data - start start of range character - end end of range character - -Returns: cb->classbits is updated -*/ - -static void -add_to_class(uint32_t options, uint32_t xoptions, compile_block *cb, - uint32_t start, uint32_t end) -{ -uint8_t *classbits = cb->classbits.classbits; -uint32_t c, byte_start, byte_end; -uint32_t classbits_end = (end <= 0xff ? end : 0xff); - -/* If caseless matching is required, scan the range and process alternate -cases. In Unicode, there are 8-bit characters that have alternate cases that -are greater than 255 and vice-versa (though these may be ignored if caseless -restriction is in force). Sometimes we can just extend the original range. */ - -if ((options & PCRE2_CASELESS) != 0) - { -#ifdef SUPPORT_UNICODE - /* UTF mode. This branch is taken if we don't support wide characters (e.g. - 8-bit library, without UTF), but we do treat those characters as Unicode - (if UCP flag is set). In this case, we only need to expand the character class - set to include the case pairs which are in the 0-255 codepoint range. */ - if ((options & (PCRE2_UTF|PCRE2_UCP)) != 0) - { - BOOL turkish_i = (xoptions & (PCRE2_EXTRA_TURKISH_CASING|PCRE2_EXTRA_CASELESS_RESTRICT)) == - PCRE2_EXTRA_TURKISH_CASING; - if (start < 128) - { - uint32_t lo_end = (classbits_end < 127 ? classbits_end : 127); - for (c = start; c <= lo_end; c++) - { - if (turkish_i && UCD_ANY_I(c)) continue; - SETBIT(classbits, cb->fcc[c]); - } - } - if (classbits_end >= 128) - { - uint32_t hi_start = (start > 128 ? start : 128); - for (c = hi_start; c <= classbits_end; c++) - { - uint32_t co = UCD_OTHERCASE(c); - if (co <= 0xff) SETBIT(classbits, co); - } - } - } - - else -#endif /* SUPPORT_UNICODE */ - - /* Not UTF mode */ - { - for (c = start; c <= classbits_end; c++) - SETBIT(classbits, cb->fcc[c]); - } - } - -/* Use the bitmap for characters < 256. Otherwise use extra data. */ - -byte_start = (start + 7) >> 3; -byte_end = (classbits_end + 1) >> 3; - -if (byte_start >= byte_end) - { - for (c = start; c <= classbits_end; c++) - /* Regardless of start, c will always be <= 255. */ - SETBIT(classbits, c); - return; - } - -for (c = byte_start; c < byte_end; c++) - classbits[c] = 0xff; - -byte_start <<= 3; -byte_end <<= 3; - -for (c = start; c < byte_start; c++) - SETBIT(classbits, c); - -for (c = byte_end; c <= classbits_end; c++) - SETBIT(classbits, c); -} - - -#if PCRE2_CODE_UNIT_WIDTH == 8 -/************************************************* -* Internal entry point for add list to class * -*************************************************/ - -/* This function is used for adding a list of horizontal or vertical whitespace -characters to a class. The list must be in order so that ranges of characters -can be detected and handled appropriately. This function sets the overall range -so that the internal functions can try to avoid duplication when handling -case-independence. - -Arguments: - options the options bits - xoptions the extra options bits - cb contains pointers to tables etc. - p points to row of 32-bit values, terminated by NOTACHAR - -Returns: cb->classbits is updated -*/ - -static void -add_list_to_class(uint32_t options, uint32_t xoptions, compile_block *cb, - const uint32_t *p) -{ -while (p[0] < 256) - { - unsigned int n = 0; - - while(p[n+1] == p[0] + n + 1) n++; - add_to_class(options, xoptions, cb, p[0], p[n]); - - p += n + 1; - } -} - - - -/************************************************* -* Add characters not in a list to a class * -*************************************************/ - -/* This function is used for adding the complement of a list of horizontal or -vertical whitespace to a class. The list must be in order. - -Arguments: - options the options bits - xoptions the extra options bits - cb contains pointers to tables etc. - p points to row of 32-bit values, terminated by NOTACHAR - -Returns: cb->classbits is updated -*/ - -static void -add_not_list_to_class(uint32_t options, uint32_t xoptions, compile_block *cb, - const uint32_t *p) -{ -if (p[0] > 0) - add_to_class(options, xoptions, cb, 0, p[0] - 1); -while (p[0] < 256) - { - while (p[1] == p[0] + 1) p++; - add_to_class(options, xoptions, cb, p[0] + 1, (p[1] > 255) ? 255 : p[1] - 1); - p++; - } -} -#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */ - - - -/************************************************* -* Main entry-point to compile a character class * -*************************************************/ - -/* This function consumes a "leaf", which is a set of characters that will -become a single OP_CLASS OP_NCLASS, OP_XCLASS, or OP_ALLANY. */ - -uint32_t * -PRIV(compile_class_not_nested)(uint32_t options, uint32_t xoptions, - uint32_t *start_ptr, PCRE2_UCHAR **pcode, BOOL negate_class, BOOL* has_bitmap, - int *errorcodeptr, compile_block *cb, PCRE2_SIZE *lengthptr) -{ -uint32_t *pptr = start_ptr; -PCRE2_UCHAR *code = *pcode; -BOOL should_flip_negation; -const uint8_t *cbits = cb->cbits; -/* Some functions such as add_to_class() or eclass processing -expects that the bitset is stored in cb->classbits.classbits. */ -uint8_t *const classbits = cb->classbits.classbits; - -#ifdef SUPPORT_UNICODE -BOOL utf = (options & PCRE2_UTF) != 0; -#else /* No Unicode support */ -BOOL utf = FALSE; -#endif - -/* Helper variables for OP_XCLASS opcode (for characters > 255). */ - -#ifdef SUPPORT_WIDE_CHARS -uint32_t xclass_props; -PCRE2_UCHAR *class_uchardata; -class_ranges* cranges; -#endif - -/* If an XClass contains a negative special such as \S, we need to flip the -negation flag at the end, so that support for characters > 255 works correctly -(they are all included in the class). An XClass may need to insert specific -matching or non-matching code for wide characters. -*/ - -should_flip_negation = FALSE; - -/* XClass will be used when characters > 255 might match. */ - -#ifdef SUPPORT_WIDE_CHARS -xclass_props = 0; - -#if PCRE2_CODE_UNIT_WIDTH == 8 -cranges = NULL; - -if (utf) -#endif - { - if (lengthptr != NULL) - { - cranges = compile_optimize_class(pptr, options, xoptions, cb); - - if (cranges == NULL) - { - *errorcodeptr = ERR21; - return NULL; - } - - /* Caching the pre-processed character ranges. */ - if (cb->next_cranges != NULL) - cb->next_cranges->next = cranges; - else - cb->cranges = cranges; - - cb->next_cranges = cranges; - } - else - { - /* Reuse the pre-processed character ranges. */ - cranges = cb->cranges; - PCRE2_ASSERT(cranges != NULL); - cb->cranges = cranges->next; - } - - if (cranges->range_list_size > 0) - { - const uint32_t *ranges = (const uint32_t*)(cranges + 1); - - if (ranges[0] <= 255) - xclass_props |= XCLASS_HAS_8BIT_CHARS; - - if (ranges[cranges->range_list_size - 1] == GET_MAX_CHAR_VALUE(utf) && - ranges[cranges->range_list_size - 2] <= 256) - xclass_props |= XCLASS_HIGH_ANY; - } - } - -class_uchardata = code + LINK_SIZE + 2; /* For XCLASS items */ -#endif /* SUPPORT_WIDE_CHARS */ - -/* Initialize the 256-bit (32-byte) bit map to all zeros. We build the map -in a temporary bit of memory, in case the class contains fewer than two -8-bit characters because in that case the compiled code doesn't use the bit -map. */ - -memset(classbits, 0, 32); - -/* Process items until end_ptr is reached. */ - -while (TRUE) - { - uint32_t meta = *(pptr++); - BOOL local_negate; - int posix_class; - int taboffset, tabopt; - class_bits_storage pbits; - uint32_t escape, c; - - /* Handle POSIX classes such as [:alpha:] etc. */ - switch (META_CODE(meta)) - { - case META_POSIX: - case META_POSIX_NEG: - - local_negate = (meta == META_POSIX_NEG); - posix_class = *(pptr++); - - if (local_negate) should_flip_negation = TRUE; /* Note negative special */ - - /* If matching is caseless, upper and lower are converted to alpha. - This relies on the fact that the class table starts with alpha, - lower, upper as the first 3 entries. */ - - if ((options & PCRE2_CASELESS) != 0 && posix_class <= 2) - posix_class = 0; - - /* When PCRE2_UCP is set, some of the POSIX classes are converted to - different escape sequences that use Unicode properties \p or \P. - Others that are not available via \p or \P have to generate - XCL_PROP/XCL_NOTPROP directly, which is done here. */ - -#ifdef SUPPORT_UNICODE - /* TODO This entire block of code here appears to be unreachable!? I simply - can't see how it can be hit, given that the frontend parser doesn't emit - META_POSIX for GRAPH/PRINT/PUNCT when UCP is set. */ - if ((options & PCRE2_UCP) != 0 && - (xoptions & PCRE2_EXTRA_ASCII_POSIX) == 0) - { - uint32_t ptype; - - switch(posix_class) - { - case PC_GRAPH: - case PC_PRINT: - case PC_PUNCT: - ptype = (posix_class == PC_GRAPH)? PT_PXGRAPH : - (posix_class == PC_PRINT)? PT_PXPRINT : PT_PXPUNCT; - - PRIV(update_classbits)(ptype, 0, local_negate, classbits); - - if ((xclass_props & XCLASS_HIGH_ANY) == 0) - { - if (lengthptr != NULL) - *lengthptr += 3; - else - { - *class_uchardata++ = local_negate? XCL_NOTPROP : XCL_PROP; - *class_uchardata++ = (PCRE2_UCHAR)ptype; - *class_uchardata++ = 0; - } - xclass_props |= XCLASS_REQUIRED | XCLASS_HAS_PROPS; - } - continue; - - /* For the other POSIX classes (ex: ascii) we are going to - fall through to the non-UCP case and build a bit map for - characters with code points less than 256. However, if we are in - a negated POSIX class, characters with code points greater than - 255 must either all match or all not match, depending on whether - the whole class is not or is negated. For example, for - [[:^ascii:]... they must all match, whereas for [^[:^ascii:]... - they must not. - - In the special case where there are no xclass items, this is - automatically handled by the use of OP_CLASS or OP_NCLASS, but an - explicit range is needed for OP_XCLASS. Setting a flag here - causes the range to be generated later when it is known that - OP_XCLASS is required. In the 8-bit library this is relevant only in - utf mode, since no wide characters can exist otherwise. */ - - default: - break; - } - } -#endif /* SUPPORT_UNICODE */ - - /* In the non-UCP case, or when UCP makes no difference, we build the - bit map for the POSIX class in a chunk of local store because we may - be adding and subtracting from it, and we don't want to subtract bits - that may be in the main map already. At the end we or the result into - the bit map that is being built. */ - - posix_class *= 3; - - /* Copy in the first table (always present) */ - - memcpy(pbits.classbits, cbits + PRIV(posix_class_maps)[posix_class], 32); - - /* If there is a second table, add or remove it as required. */ - - taboffset = PRIV(posix_class_maps)[posix_class + 1]; - tabopt = PRIV(posix_class_maps)[posix_class + 2]; - - if (taboffset >= 0) - { - if (tabopt >= 0) - for (int i = 0; i < 32; i++) - pbits.classbits[i] |= cbits[i + taboffset]; - else - for (int i = 0; i < 32; i++) - pbits.classbits[i] &= (uint8_t)(~cbits[i + taboffset]); - } - - /* Now see if we need to remove any special characters. An option - value of 1 removes vertical space and 2 removes underscore. */ - - if (tabopt < 0) tabopt = -tabopt; - if (tabopt == 1) pbits.classbits[1] &= ~0x3c; - else if (tabopt == 2) pbits.classbits[11] &= 0x7f; - - /* Add the POSIX table or its complement into the main table that is - being built and we are done. */ - - { - uint32_t *classwords = cb->classbits.classwords; - - if (local_negate) - for (int i = 0; i < 8; i++) - classwords[i] |= (uint32_t)(~pbits.classwords[i]); - else - for (int i = 0; i < 8; i++) - classwords[i] |= pbits.classwords[i]; - } - -#ifdef SUPPORT_WIDE_CHARS - /* Every class contains at least one < 256 character. */ - xclass_props |= XCLASS_HAS_8BIT_CHARS; -#endif - continue; /* End of POSIX handling */ - - /* Other than POSIX classes, the only items we should encounter are - \d-type escapes and literal characters (possibly as ranges). */ - case META_BIGVALUE: - meta = *(pptr++); - break; - - case META_ESCAPE: - escape = META_DATA(meta); - - switch(escape) - { - case ESC_d: - for (int i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_digit]; - break; - - case ESC_D: - should_flip_negation = TRUE; - for (int i = 0; i < 32; i++) - classbits[i] |= (uint8_t)(~cbits[i+cbit_digit]); - break; - - case ESC_w: - for (int i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_word]; - break; - - case ESC_W: - should_flip_negation = TRUE; - for (int i = 0; i < 32; i++) - classbits[i] |= (uint8_t)(~cbits[i+cbit_word]); - break; - - /* Perl 5.004 onwards omitted VT from \s, but restored it at Perl - 5.18. Before PCRE 8.34, we had to preserve the VT bit if it was - previously set by something earlier in the character class. - Luckily, the value of CHAR_VT is 0x0b in both ASCII and EBCDIC, so - we could just adjust the appropriate bit. From PCRE 8.34 we no - longer treat \s and \S specially. */ - - case ESC_s: - for (int i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_space]; - break; - - case ESC_S: - should_flip_negation = TRUE; - for (int i = 0; i < 32; i++) - classbits[i] |= (uint8_t)(~cbits[i+cbit_space]); - break; - - /* When adding the horizontal or vertical space lists to a class, or - their complements, disable PCRE2_CASELESS, because it justs wastes - time, and in the "not-x" UTF cases can create unwanted duplicates in - the XCLASS list (provoked by characters that have more than one other - case and by both cases being in the same "not-x" sublist). */ - - case ESC_h: -#if PCRE2_CODE_UNIT_WIDTH == 8 -#ifdef SUPPORT_UNICODE - if (cranges != NULL) break; -#endif - add_list_to_class(options & ~PCRE2_CASELESS, xoptions, - cb, PRIV(hspace_list)); -#else - PCRE2_ASSERT(cranges != NULL); -#endif - break; - - case ESC_H: -#if PCRE2_CODE_UNIT_WIDTH == 8 -#ifdef SUPPORT_UNICODE - if (cranges != NULL) break; -#endif - add_not_list_to_class(options & ~PCRE2_CASELESS, xoptions, - cb, PRIV(hspace_list)); -#else - PCRE2_ASSERT(cranges != NULL); -#endif - break; - - case ESC_v: -#if PCRE2_CODE_UNIT_WIDTH == 8 -#ifdef SUPPORT_UNICODE - if (cranges != NULL) break; -#endif - add_list_to_class(options & ~PCRE2_CASELESS, xoptions, - cb, PRIV(vspace_list)); -#else - PCRE2_ASSERT(cranges != NULL); -#endif - break; - - case ESC_V: -#if PCRE2_CODE_UNIT_WIDTH == 8 -#ifdef SUPPORT_UNICODE - if (cranges != NULL) break; -#endif - add_not_list_to_class(options & ~PCRE2_CASELESS, xoptions, - cb, PRIV(vspace_list)); -#else - PCRE2_ASSERT(cranges != NULL); -#endif - break; - - /* If Unicode is not supported, \P and \p are not allowed and are - faulted at parse time, so will never appear here. */ - -#ifdef SUPPORT_UNICODE - case ESC_p: - case ESC_P: - { - uint32_t ptype = *pptr >> 16; - uint32_t pdata = *(pptr++) & 0xffff; - - /* The "Any" is processed by PRIV(update_classbits)(). */ - if (ptype == PT_ANY) - { -#if PCRE2_CODE_UNIT_WIDTH == 8 - if (!utf && escape == ESC_p) memset(classbits, 0xff, 32); -#endif - continue; - } - - PRIV(update_classbits)(ptype, pdata, (escape == ESC_P), classbits); - - if ((xclass_props & XCLASS_HIGH_ANY) == 0) - { - if (lengthptr != NULL) - *lengthptr += 3; - else - { - *class_uchardata++ = (escape == ESC_p)? XCL_PROP : XCL_NOTPROP; - *class_uchardata++ = ptype; - *class_uchardata++ = pdata; - } - xclass_props |= XCLASS_REQUIRED | XCLASS_HAS_PROPS; - } - } - continue; -#endif - } - -#ifdef SUPPORT_WIDE_CHARS - /* Every non-property class contains at least one < 256 character. */ - xclass_props |= XCLASS_HAS_8BIT_CHARS; -#endif - /* End handling \d-type escapes */ - continue; - - CLASS_END_CASES(meta) - /* Literals. */ - if (meta < META_END) break; - /* Non-literals: end of class contents. */ - goto END_PROCESSING; - } - - /* A literal character may be followed by a range meta. At parse time - there are checks for out-of-order characters, for ranges where the two - characters are equal, and for hyphens that cannot indicate a range. At - this point, therefore, no checking is needed. */ - - c = meta; - - /* Remember if \r or \n were explicitly used */ - - if (c == CHAR_CR || c == CHAR_NL) cb->external_flags |= PCRE2_HASCRORLF; - - /* Process a character range */ - - if (*pptr == META_RANGE_LITERAL || *pptr == META_RANGE_ESCAPED) - { - uint32_t d; - -#ifdef EBCDIC - BOOL range_is_literal = (*pptr == META_RANGE_LITERAL); -#endif - ++pptr; - d = *(pptr++); - if (d == META_BIGVALUE) d = *(pptr++); - - /* Remember an explicit \r or \n, and add the range to the class. */ - - if (d == CHAR_CR || d == CHAR_NL) cb->external_flags |= PCRE2_HASCRORLF; - -#if PCRE2_CODE_UNIT_WIDTH == 8 -#ifdef SUPPORT_UNICODE - if (cranges != NULL) continue; - xclass_props |= XCLASS_HAS_8BIT_CHARS; -#endif - - /* In an EBCDIC environment, Perl treats alphabetic ranges specially - because there are holes in the encoding, and simply using the range - A-Z (for example) would include the characters in the holes. This - applies only to literal ranges; [\xC1-\xE9] is different to [A-Z]. */ - -#ifdef EBCDIC - if (range_is_literal && - (cb->ctypes[c] & ctype_letter) != 0 && - (cb->ctypes[d] & ctype_letter) != 0 && - (c <= CHAR_z) == (d <= CHAR_z)) - { - uint32_t uc = (d <= CHAR_z)? 0 : 64; - uint32_t C = c - uc; - uint32_t D = d - uc; - - if (C <= CHAR_i) - { - add_to_class(options, xoptions, cb, C + uc, - ((D < CHAR_i)? D : CHAR_i) + uc); - C = CHAR_j; - } - - if (C <= D && C <= CHAR_r) - { - add_to_class(options, xoptions, cb, C + uc, - ((D < CHAR_r)? D : CHAR_r) + uc); - C = CHAR_s; - } - - if (C <= D) - add_to_class(options, xoptions, cb, C + uc, D + uc); - } - else -#endif - /* Not an EBCDIC special range */ - - add_to_class(options, xoptions, cb, c, d); -#else - PCRE2_ASSERT(cranges != NULL); -#endif - continue; - } /* End of range handling */ - - /* Character ranges are ignored when class_ranges is present. */ -#if PCRE2_CODE_UNIT_WIDTH == 8 -#ifdef SUPPORT_UNICODE - if (cranges != NULL) continue; - xclass_props |= XCLASS_HAS_8BIT_CHARS; -#endif - /* Handle a single character. */ - - add_to_class(options, xoptions, cb, meta, meta); -#else - PCRE2_ASSERT(cranges != NULL); -#endif - } /* End of main class-processing loop */ - -END_PROCESSING: - -#ifdef SUPPORT_WIDE_CHARS -PCRE2_ASSERT((xclass_props & XCLASS_HAS_PROPS) == 0 || - (xclass_props & XCLASS_HIGH_ANY) == 0); - -if (cranges != NULL) - { - uint32_t *range = (uint32_t*)(cranges + 1); - uint32_t *end = range + cranges->range_list_size; - - while (range < end && range[0] < 256) - { - PCRE2_ASSERT((xclass_props & XCLASS_HAS_8BIT_CHARS) != 0); - /* Add range to bitset. If we are in UTF or UCP mode, then clear the - caseless bit, because the cranges handle caselessness (only) in this - condition; see the condition for PARSE_CLASS_CASELESS_UTF in - compile_optimize_class(). */ - add_to_class(((options & (PCRE2_UTF|PCRE2_UCP)) != 0)? - (options & ~PCRE2_CASELESS) : options, xoptions, cb, range[0], range[1]); - - if (range[1] > 255) break; - range += 2; - } - - if (cranges->char_lists_size > 0) - { - /* The cranges structure is still used and freed later. */ - PCRE2_ASSERT((xclass_props & XCLASS_HIGH_ANY) == 0); - xclass_props |= XCLASS_REQUIRED | XCLASS_HAS_CHAR_LISTS; - } - else - { - if ((xclass_props & XCLASS_HIGH_ANY) != 0) - { - PCRE2_ASSERT(range + 2 == end && range[0] <= 256 && - range[1] >= GET_MAX_CHAR_VALUE(utf)); - should_flip_negation = TRUE; - range = end; - } - - while (range < end) - { - uint32_t range_start = range[0]; - uint32_t range_end = range[1]; - - range += 2; - xclass_props |= XCLASS_REQUIRED; - - if (range_start < 256) range_start = 256; - - if (lengthptr != NULL) - { -#ifdef SUPPORT_UNICODE - if (utf) - { - *lengthptr += 1; - - if (range_start < range_end) - *lengthptr += PRIV(ord2utf)(range_start, class_uchardata); - - *lengthptr += PRIV(ord2utf)(range_end, class_uchardata); - continue; - } -#endif /* SUPPORT_UNICODE */ - - *lengthptr += range_start < range_end ? 3 : 2; - continue; - } - -#ifdef SUPPORT_UNICODE - if (utf) - { - if (range_start < range_end) - { - *class_uchardata++ = XCL_RANGE; - class_uchardata += PRIV(ord2utf)(range_start, class_uchardata); - } - else - *class_uchardata++ = XCL_SINGLE; - - class_uchardata += PRIV(ord2utf)(range_end, class_uchardata); - continue; - } -#endif /* SUPPORT_UNICODE */ - - /* Without UTF support, character values are constrained - by the bit length, and can only be > 256 for 16-bit and - 32-bit libraries. */ -#if PCRE2_CODE_UNIT_WIDTH != 8 - if (range_start < range_end) - { - *class_uchardata++ = XCL_RANGE; - *class_uchardata++ = range_start; - } - else - *class_uchardata++ = XCL_SINGLE; - - *class_uchardata++ = range_end; -#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */ - } - - if (lengthptr == NULL) - cb->cx->memctl.free(cranges, cb->cx->memctl.memory_data); - } - } -#endif /* SUPPORT_WIDE_CHARS */ - -/* If there are characters with values > 255, or Unicode property settings -(\p or \P), we have to compile an extended class, with its own opcode, -unless there were no property settings and there was a negated special such -as \S in the class, and PCRE2_UCP is not set, because in that case all -characters > 255 are in or not in the class, so any that were explicitly -given as well can be ignored. - -In the UCP case, if certain negated POSIX classes (ex: [:^ascii:]) were -were present in a class, we either have to match or not match all wide -characters (depending on whether the whole class is or is not negated). -This requirement is indicated by match_all_or_no_wide_chars being true. -We do this by including an explicit range, which works in both cases. -This applies only in UTF and 16-bit and 32-bit non-UTF modes, since there -cannot be any wide characters in 8-bit non-UTF mode. - -When there *are* properties in a positive UTF-8 or any 16-bit or 32_bit -class where \S etc is present without PCRE2_UCP, causing an extended class -to be compiled, we make sure that all characters > 255 are included by -forcing match_all_or_no_wide_chars to be true. - -If, when generating an xclass, there are no characters < 256, we can omit -the bitmap in the actual compiled code. */ - -#ifdef SUPPORT_WIDE_CHARS /* Defined for 16/32 bits, or 8-bit with Unicode */ -if ((xclass_props & XCLASS_REQUIRED) != 0) - { - PCRE2_UCHAR *previous = code; - - if ((xclass_props & XCLASS_HAS_CHAR_LISTS) == 0) - *class_uchardata++ = XCL_END; /* Marks the end of extra data */ - *code++ = OP_XCLASS; - code += LINK_SIZE; - *code = negate_class? XCL_NOT:0; - if ((xclass_props & XCLASS_HAS_PROPS) != 0) *code |= XCL_HASPROP; - - /* If the map is required, move up the extra data to make room for it; - otherwise just move the code pointer to the end of the extra data. */ - - if ((xclass_props & XCLASS_HAS_8BIT_CHARS) != 0 || has_bitmap != NULL) - { - if (negate_class) - { - uint32_t *classwords = cb->classbits.classwords; - for (int i = 0; i < 8; i++) classwords[i] = ~classwords[i]; - } - - if (has_bitmap == NULL) - { - *code++ |= XCL_MAP; - (void)memmove(code + (32 / sizeof(PCRE2_UCHAR)), code, - CU2BYTES(class_uchardata - code)); - memcpy(code, classbits, 32); - code = class_uchardata + (32 / sizeof(PCRE2_UCHAR)); - } - else - { - code = class_uchardata; - if ((xclass_props & XCLASS_HAS_8BIT_CHARS) != 0) - *has_bitmap = TRUE; - } - } - else code = class_uchardata; - - if ((xclass_props & XCLASS_HAS_CHAR_LISTS) != 0) - { - /* Char lists size is an even number, because all items are 16 or 32 - bit values. The character list data is always aligned to 32 bits. */ - size_t char_lists_size = cranges->char_lists_size; - PCRE2_ASSERT((char_lists_size & 0x1) == 0 && - (cb->char_lists_size & 0x3) == 0); - - if (lengthptr != NULL) - { - char_lists_size = CLIST_ALIGN_TO(char_lists_size, sizeof(uint32_t)); - -#if PCRE2_CODE_UNIT_WIDTH == 8 - *lengthptr += 2 + LINK_SIZE; -#else - *lengthptr += 1 + LINK_SIZE; -#endif - - cb->char_lists_size += char_lists_size; - - char_lists_size /= sizeof(PCRE2_UCHAR); - - /* Storage space for character lists is included - in the maximum pattern size. */ - if (*lengthptr > MAX_PATTERN_SIZE || - MAX_PATTERN_SIZE - *lengthptr < char_lists_size) - { - *errorcodeptr = ERR20; /* Pattern is too large */ - return NULL; - } - } - else - { - uint8_t *data; - - PCRE2_ASSERT(cranges->char_lists_types <= XCL_TYPE_MASK); -#if PCRE2_CODE_UNIT_WIDTH == 8 - /* Encode as high / low bytes. */ - code[0] = (uint8_t)(XCL_LIST | - (cranges->char_lists_types >> 8)); - code[1] = (uint8_t)cranges->char_lists_types; - code += 2; -#else - *code++ = (PCRE2_UCHAR)(XCL_LIST | cranges->char_lists_types); -#endif - - /* Character lists are stored in backwards direction from - byte code start. The non-dfa/dfa matchers can access these - lists using the byte code start stored in match blocks. - Each list is aligned to 32 bit with an optional unused - 16 bit value at the beginning of the character list. */ - - cb->char_lists_size += char_lists_size; - data = (uint8_t*)cb->start_code - cb->char_lists_size; - - memcpy(data, (uint8_t*)(cranges + 1) + cranges->char_lists_start, - char_lists_size); - - /* Since character lists total size is less than MAX_PATTERN_SIZE, - their starting offset fits into a value which size is LINK_SIZE. */ - - char_lists_size = cb->char_lists_size; - PUT(code, 0, (uint32_t)(char_lists_size >> 1)); - code += LINK_SIZE; - -#if defined PCRE2_DEBUG || defined SUPPORT_VALGRIND - if ((char_lists_size & 0x2) != 0) - { - /* In debug the unused 16 bit value is set - to a fixed value and marked unused. */ - ((uint16_t*)data)[-1] = 0x5555; -#ifdef SUPPORT_VALGRIND - VALGRIND_MAKE_MEM_NOACCESS(data - 2, 2); -#endif - } -#endif - - cb->char_lists_size = - CLIST_ALIGN_TO(char_lists_size, sizeof(uint32_t)); - - cb->cx->memctl.free(cranges, cb->cx->memctl.memory_data); - } - } - - /* Now fill in the complete length of the item */ - - PUT(previous, 1, (int)(code - previous)); - goto DONE; /* End of class handling */ - } -#endif /* SUPPORT_WIDE_CHARS */ - -/* If there are no characters > 255, or they are all to be included or -excluded, set the opcode to OP_CLASS or OP_NCLASS, depending on whether the -whole class was negated and whether there were negative specials such as \S -(non-UCP) in the class. Then copy the 32-byte map into the code vector, -negating it if necessary. */ - -if (negate_class) - { - uint32_t *classwords = cb->classbits.classwords; - - for (int i = 0; i < 8; i++) classwords[i] = ~classwords[i]; - } - -if ((SELECT_VALUE8(!utf, 0) || negate_class != should_flip_negation) && - cb->classbits.classwords[0] == ~(uint32_t)0) - { - const uint32_t *classwords = cb->classbits.classwords; - int i; - - for (i = 0; i < 8; i++) - if (classwords[i] != ~(uint32_t)0) break; - - if (i == 8) - { - *code++ = OP_ALLANY; - goto DONE; /* End of class handling */ - } - } - -*code++ = (negate_class == should_flip_negation) ? OP_CLASS : OP_NCLASS; -memcpy(code, classbits, 32); -code += 32 / sizeof(PCRE2_UCHAR); - -DONE: -*pcode = code; -return pptr - 1; -} - - - -/* ===================================================================*/ -/* Here follows a block of ECLASS-compiling functions. You may well want to -read them from top to bottom; they are ordered from leafmost (at the top) to -outermost parser (at the bottom of the file). */ - -/* This function folds one operand using the negation operator. -The new, combined chunk of stack code is written out to *pop_info. */ - -static void -fold_negation(eclass_op_info *pop_info, PCRE2_SIZE *lengthptr, - BOOL preserve_classbits) -{ -/* If the chunk of stack code is already composed of multiple ops, we won't -descend in and try and propagate the negation down the tree. (That would lead -to O(n^2) compile-time, which could be exploitable with a malicious regex - -although maybe that's not really too much of a worry in a library that offers -an exponential-time matching function!) */ - -if (pop_info->op_single_type == 0) - { - if (lengthptr != NULL) - *lengthptr += 1; - else - pop_info->code_start[pop_info->length] = ECL_NOT; - pop_info->length += 1; - } - -/* Otherwise, it's a nice single-op item, so we can easily fold in the negation -without needing to produce an ECL_NOT. */ - -else if (pop_info->op_single_type == ECL_ANY || - pop_info->op_single_type == ECL_NONE) - { - pop_info->op_single_type = (pop_info->op_single_type == ECL_NONE)? - ECL_ANY : ECL_NONE; - if (lengthptr == NULL) - *(pop_info->code_start) = pop_info->op_single_type; - } -else - { - PCRE2_ASSERT(pop_info->op_single_type == ECL_XCLASS && - pop_info->length >= 1 + LINK_SIZE + 1); - if (lengthptr == NULL) - pop_info->code_start[1 + LINK_SIZE] ^= XCL_NOT; - } - -if (!preserve_classbits) - { - for (int i = 0; i < 8; i++) - pop_info->bits.classwords[i] = ~pop_info->bits.classwords[i]; - } -} - - - -/* This function folds together two operands using a binary operator. -The new, combined chunk of stack code is written out to *lhs_op_info. */ - -static void -fold_binary(int op, eclass_op_info *lhs_op_info, eclass_op_info *rhs_op_info, - PCRE2_SIZE *lengthptr) -{ -switch (op) - { - /* ECL_AND truth table: - - LHS RHS RESULT - ---------------- - ANY * RHS - * ANY LHS - NONE * NONE - * NONE NONE - X Y X & Y - */ - - case ECL_AND: - if (rhs_op_info->op_single_type == ECL_ANY) - { - /* no-op: drop the RHS */ - } - else if (lhs_op_info->op_single_type == ECL_ANY) - { - /* no-op: drop the LHS, and memmove the RHS into its place */ - if (lengthptr == NULL) - memmove(lhs_op_info->code_start, rhs_op_info->code_start, - CU2BYTES(rhs_op_info->length)); - lhs_op_info->length = rhs_op_info->length; - lhs_op_info->op_single_type = rhs_op_info->op_single_type; - } - else if (rhs_op_info->op_single_type == ECL_NONE) - { - /* the result is ECL_NONE: write into the LHS */ - if (lengthptr == NULL) - lhs_op_info->code_start[0] = ECL_NONE; - lhs_op_info->length = 1; - lhs_op_info->op_single_type = ECL_NONE; - } - else if (lhs_op_info->op_single_type == ECL_NONE) - { - /* the result is ECL_NONE: drop the RHS */ - } - else - { - /* Both of LHS & RHS are either ECL_XCLASS, or compound operations. */ - if (lengthptr != NULL) - *lengthptr += 1; - else - { - PCRE2_ASSERT(rhs_op_info->code_start == - lhs_op_info->code_start + lhs_op_info->length); - rhs_op_info->code_start[rhs_op_info->length] = ECL_AND; - } - lhs_op_info->length += rhs_op_info->length + 1; - lhs_op_info->op_single_type = 0; - } - - for (int i = 0; i < 8; i++) - lhs_op_info->bits.classwords[i] &= rhs_op_info->bits.classwords[i]; - break; - - /* ECL_OR truth table: - - LHS RHS RESULT - ---------------- - ANY * ANY - * ANY ANY - NONE * RHS - * NONE LHS - X Y X | Y - */ - - case ECL_OR: - if (rhs_op_info->op_single_type == ECL_NONE) - { - /* no-op: drop the RHS */ - } - else if (lhs_op_info->op_single_type == ECL_NONE) - { - /* no-op: drop the LHS, and memmove the RHS into its place */ - if (lengthptr == NULL) - memmove(lhs_op_info->code_start, rhs_op_info->code_start, - CU2BYTES(rhs_op_info->length)); - lhs_op_info->length = rhs_op_info->length; - lhs_op_info->op_single_type = rhs_op_info->op_single_type; - } - else if (rhs_op_info->op_single_type == ECL_ANY) - { - /* the result is ECL_ANY: write into the LHS */ - if (lengthptr == NULL) - lhs_op_info->code_start[0] = ECL_ANY; - lhs_op_info->length = 1; - lhs_op_info->op_single_type = ECL_ANY; - } - else if (lhs_op_info->op_single_type == ECL_ANY) - { - /* the result is ECL_ANY: drop the RHS */ - } - else - { - /* Both of LHS & RHS are either ECL_XCLASS, or compound operations. */ - if (lengthptr != NULL) - *lengthptr += 1; - else - { - PCRE2_ASSERT(rhs_op_info->code_start == - lhs_op_info->code_start + lhs_op_info->length); - rhs_op_info->code_start[rhs_op_info->length] = ECL_OR; - } - lhs_op_info->length += rhs_op_info->length + 1; - lhs_op_info->op_single_type = 0; - } - - for (int i = 0; i < 8; i++) - lhs_op_info->bits.classwords[i] |= rhs_op_info->bits.classwords[i]; - break; - - /* ECL_XOR truth table: - - LHS RHS RESULT - ---------------- - ANY * !RHS - * ANY !LHS - NONE * RHS - * NONE LHS - X Y X ^ Y - */ - - case ECL_XOR: - if (rhs_op_info->op_single_type == ECL_NONE) - { - /* no-op: drop the RHS */ - } - else if (lhs_op_info->op_single_type == ECL_NONE) - { - /* no-op: drop the LHS, and memmove the RHS into its place */ - if (lengthptr == NULL) - memmove(lhs_op_info->code_start, rhs_op_info->code_start, - CU2BYTES(rhs_op_info->length)); - lhs_op_info->length = rhs_op_info->length; - lhs_op_info->op_single_type = rhs_op_info->op_single_type; - } - else if (rhs_op_info->op_single_type == ECL_ANY) - { - /* the result is !LHS: fold in the negation, and drop the RHS */ - /* Preserve the classbits, because we promise to deal with them later. */ - fold_negation(lhs_op_info, lengthptr, TRUE); - } - else if (lhs_op_info->op_single_type == ECL_ANY) - { - /* the result is !RHS: drop the LHS, memmove the RHS into its place, and - fold in the negation */ - if (lengthptr == NULL) - memmove(lhs_op_info->code_start, rhs_op_info->code_start, - CU2BYTES(rhs_op_info->length)); - lhs_op_info->length = rhs_op_info->length; - lhs_op_info->op_single_type = rhs_op_info->op_single_type; - - /* Preserve the classbits, because we promise to deal with them later. */ - fold_negation(lhs_op_info, lengthptr, TRUE); - } - else - { - /* Both of LHS & RHS are either ECL_XCLASS, or compound operations. */ - if (lengthptr != NULL) - *lengthptr += 1; - else - { - PCRE2_ASSERT(rhs_op_info->code_start == - lhs_op_info->code_start + lhs_op_info->length); - rhs_op_info->code_start[rhs_op_info->length] = ECL_XOR; - } - lhs_op_info->length += rhs_op_info->length + 1; - lhs_op_info->op_single_type = 0; - } - - for (int i = 0; i < 8; i++) - lhs_op_info->bits.classwords[i] ^= rhs_op_info->bits.classwords[i]; - break; - - default: - PCRE2_DEBUG_UNREACHABLE(); - break; - } -} - - - -static BOOL -compile_eclass_nested(eclass_context *context, BOOL negated, - uint32_t **pptr, PCRE2_UCHAR **pcode, - eclass_op_info *pop_info, PCRE2_SIZE *lengthptr); - -/* This function consumes a group of implicitly-unioned class elements. -These can be characters, ranges, properties, or nested classes, as long -as they are all joined by being placed adjacently. */ - -static BOOL -compile_class_operand(eclass_context *context, BOOL negated, - uint32_t **pptr, PCRE2_UCHAR **pcode, eclass_op_info *pop_info, - PCRE2_SIZE *lengthptr) -{ -uint32_t *ptr = *pptr; -uint32_t *prev_ptr; -PCRE2_UCHAR *code = *pcode; -PCRE2_UCHAR *code_start = code; -PCRE2_SIZE prev_length = (lengthptr != NULL)? *lengthptr : 0; -PCRE2_SIZE extra_length; -uint32_t meta = META_CODE(*ptr); - -switch (meta) - { - case META_CLASS_EMPTY_NOT: - case META_CLASS_EMPTY: - ++ptr; - pop_info->length = 1; - if ((meta == META_CLASS_EMPTY) == negated) - { - *code++ = pop_info->op_single_type = ECL_ANY; - memset(pop_info->bits.classbits, 0xff, 32); - } - else - { - *code++ = pop_info->op_single_type = ECL_NONE; - memset(pop_info->bits.classbits, 0, 32); - } - break; - - case META_CLASS: - case META_CLASS_NOT: - if ((*ptr & CLASS_IS_ECLASS) != 0) - { - if (!compile_eclass_nested(context, negated, &ptr, &code, - pop_info, lengthptr)) - return FALSE; - - PCRE2_ASSERT(*ptr == META_CLASS_END); - ptr++; - goto DONE; - } - - ptr++; - /* Fall through */ - - default: - /* Scan forward characters, ranges, and properties. - For example: inside [a-z_ -- m] we don't have brackets around "a-z_" but - we still need to collect that fragment up into a "leaf" OP_CLASS. */ - - prev_ptr = ptr; - ptr = PRIV(compile_class_not_nested)( - context->options, context->xoptions, ptr, &code, - (meta != META_CLASS_NOT) == negated, &context->needs_bitmap, - context->errorcodeptr, context->cb, lengthptr); - if (ptr == NULL) return FALSE; - - /* We must have a 100% guarantee that ptr increases when - compile_class_operand() returns, even on Release builds, so that we can - statically prove our loops terminate. */ - if (ptr <= prev_ptr) - { - PCRE2_DEBUG_UNREACHABLE(); - return FALSE; - } - - /* If we fell through above, consume the closing ']'. */ - if (meta == META_CLASS || meta == META_CLASS_NOT) - { - PCRE2_ASSERT(*ptr == META_CLASS_END); - ptr++; - } - - /* Regardless of whether (lengthptr == NULL), some data will still be written - out to *pcode, which we need: we have to peek at it, to transform the opcode - into the ECLASS version (since we need to hoist up the bitmaps). */ - PCRE2_ASSERT(code > code_start); - extra_length = (lengthptr != NULL)? *lengthptr - prev_length : 0; - - /* Easiest case: convert OP_ALLANY to ECL_ANY */ - - if (*code_start == OP_ALLANY) - { - PCRE2_ASSERT(code - code_start == 1 && extra_length == 0); - pop_info->length = 1; - *code_start = pop_info->op_single_type = ECL_ANY; - memset(pop_info->bits.classbits, 0xff, 32); - } - - /* For OP_CLASS and OP_NCLASS, we hoist out the bitmap and convert to - ECL_NONE / ECL_ANY respectively. */ - - else if (*code_start == OP_CLASS || *code_start == OP_NCLASS) - { - PCRE2_ASSERT(code - code_start == 1 + 32 / sizeof(PCRE2_UCHAR) && - extra_length == 0); - pop_info->length = 1; - *code_start = pop_info->op_single_type = - (*code_start == OP_CLASS)? ECL_NONE : ECL_ANY; - memcpy(pop_info->bits.classbits, code_start + 1, 32); - /* Rewind the code pointer, but make sure we adjust *lengthptr, because we - do need to reserve that space (even though we only use it temporarily). */ - if (lengthptr != NULL) - *lengthptr += code - (code_start + 1); - code = code_start + 1; - - if (!context->needs_bitmap && *code_start == ECL_NONE) - { - uint32_t *classwords = pop_info->bits.classwords; - - for (int i = 0; i < 8; i++) - if (classwords[i] != 0) - { - context->needs_bitmap = TRUE; - break; - } - } - else - context->needs_bitmap = TRUE; - } - - /* Finally, for OP_XCLASS we hoist out the bitmap (if any), and convert to - ECL_XCLASS. */ - - else - { - PCRE2_ASSERT(*code_start == OP_XCLASS); - *code_start = pop_info->op_single_type = ECL_XCLASS; - - PCRE2_ASSERT(code - code_start >= 1 + LINK_SIZE + 1); - - memcpy(pop_info->bits.classbits, context->cb->classbits.classbits, 32); - pop_info->length = (code - code_start) + extra_length; - } - - break; - } /* End of switch(meta) */ - -pop_info->code_start = (lengthptr == NULL)? code_start : NULL; - -if (lengthptr != NULL) - { - *lengthptr += code - code_start; - code = code_start; - } - -DONE: -PCRE2_ASSERT(lengthptr == NULL || (code == code_start)); - -*pptr = ptr; -*pcode = code; -return TRUE; -} - - - -/* This function consumes a group of implicitly-unioned class elements. -These can be characters, ranges, properties, or nested classes, as long -as they are all joined by being placed adjacently. */ - -static BOOL -compile_class_juxtaposition(eclass_context *context, BOOL negated, - uint32_t **pptr, PCRE2_UCHAR **pcode, eclass_op_info *pop_info, - PCRE2_SIZE *lengthptr) -{ -uint32_t *ptr = *pptr; -PCRE2_UCHAR *code = *pcode; -#ifdef PCRE2_DEBUG -PCRE2_UCHAR *start_code = *pcode; -#endif - -/* See compile_class_binary_loose() for comments on compile-time folding of -the "negated" flag. */ - -/* Because it's a non-empty class, there must be an operand at the start. */ -if (!compile_class_operand(context, negated, &ptr, &code, pop_info, lengthptr)) - return FALSE; - -while (*ptr != META_CLASS_END && - !(*ptr >= META_ECLASS_AND && *ptr <= META_ECLASS_NOT)) - { - uint32_t op; - BOOL rhs_negated; - eclass_op_info rhs_op_info; - - if (negated) - { - /* !(A juxtapose B) -> !A && !B */ - op = ECL_AND; - rhs_negated = TRUE; - } - else - { - /* A juxtapose B -> A || B */ - op = ECL_OR; - rhs_negated = FALSE; - } - - /* An operand must follow the operator. */ - if (!compile_class_operand(context, rhs_negated, &ptr, &code, - &rhs_op_info, lengthptr)) - return FALSE; - - /* Convert infix to postfix (RPN). */ - fold_binary(op, pop_info, &rhs_op_info, lengthptr); - if (lengthptr == NULL) - code = pop_info->code_start + pop_info->length; - } - -PCRE2_ASSERT(lengthptr == NULL || code == start_code); - -*pptr = ptr; -*pcode = code; -return TRUE; -} - - - -/* This function consumes unary prefix operators. */ - -static BOOL -compile_class_unary(eclass_context *context, BOOL negated, - uint32_t **pptr, PCRE2_UCHAR **pcode, eclass_op_info *pop_info, - PCRE2_SIZE *lengthptr) -{ -uint32_t *ptr = *pptr; -#ifdef PCRE2_DEBUG -PCRE2_UCHAR *start_code = *pcode; -#endif - -while (*ptr == META_ECLASS_NOT) - { - ++ptr; - negated = !negated; - } - -*pptr = ptr; -/* Because it's a non-empty class, there must be an operand. */ -if (!compile_class_juxtaposition(context, negated, pptr, pcode, - pop_info, lengthptr)) - return FALSE; - -PCRE2_ASSERT(lengthptr == NULL || *pcode == start_code); -return TRUE; -} - - - -/* This function consumes tightly-binding binary operators. */ - -static BOOL -compile_class_binary_tight(eclass_context *context, BOOL negated, - uint32_t **pptr, PCRE2_UCHAR **pcode, eclass_op_info *pop_info, - PCRE2_SIZE *lengthptr) -{ -uint32_t *ptr = *pptr; -PCRE2_UCHAR *code = *pcode; -#ifdef PCRE2_DEBUG -PCRE2_UCHAR *start_code = *pcode; -#endif - -/* See compile_class_binary_loose() for comments on compile-time folding of -the "negated" flag. */ - -/* Because it's a non-empty class, there must be an operand at the start. */ -if (!compile_class_unary(context, negated, &ptr, &code, pop_info, lengthptr)) - return FALSE; - -while (*ptr == META_ECLASS_AND) - { - uint32_t op; - BOOL rhs_negated; - eclass_op_info rhs_op_info; - - if (negated) - { - /* !(A && B) -> !A || !B */ - op = ECL_OR; - rhs_negated = TRUE; - } - else - { - /* A && B -> A && B */ - op = ECL_AND; - rhs_negated = FALSE; - } - - ++ptr; - - /* An operand must follow the operator. */ - if (!compile_class_unary(context, rhs_negated, &ptr, &code, - &rhs_op_info, lengthptr)) - return FALSE; - - /* Convert infix to postfix (RPN). */ - fold_binary(op, pop_info, &rhs_op_info, lengthptr); - if (lengthptr == NULL) - code = pop_info->code_start + pop_info->length; - } - -PCRE2_ASSERT(lengthptr == NULL || code == start_code); - -*pptr = ptr; -*pcode = code; -return TRUE; -} - - - -/* This function consumes loosely-binding binary operators. */ - -static BOOL -compile_class_binary_loose(eclass_context *context, BOOL negated, - uint32_t **pptr, PCRE2_UCHAR **pcode, eclass_op_info *pop_info, - PCRE2_SIZE *lengthptr) -{ -uint32_t *ptr = *pptr; -PCRE2_UCHAR *code = *pcode; -#ifdef PCRE2_DEBUG -PCRE2_UCHAR *start_code = *pcode; -#endif - -/* We really want to fold the negation operator, if at all possible, so that -simple cases can be reduced down. In particular, in 8-bit no-UTF mode, we want -to produce a fully-folded expression, so that we can guarantee not to emit any -OP_ECLASS codes (in the same way that we never emit OP_XCLASS in this mode). - -This has the consequence that with a little ingenuity, we can in fact avoid -emitting (nearly...) all cases of the "NOT" operator. Imagine that we have: - !(A ... -We have parsed the preceding "!", and we are about to parse the "A" operand. We -don't know yet whether there will even be a following binary operand! Both of -these are possibilities for what follows: - !(A && B) - !(A) -However, we can still fold the "!" into the "A" operand, because no matter what -the following binary operator will be, we can produce an expression which is -equivalent. */ - -/* Because it's a non-empty class, there must be an operand at the start. */ -if (!compile_class_binary_tight(context, negated, &ptr, &code, - pop_info, lengthptr)) - return FALSE; - -while (*ptr >= META_ECLASS_OR && *ptr <= META_ECLASS_XOR) - { - uint32_t op; - BOOL op_neg; - BOOL rhs_negated; - eclass_op_info rhs_op_info; - - if (negated) - { - /* The whole expression is being negated; we respond by unconditionally - negating the LHS A, before seeing what follows. And hooray! We can recover, - no matter what follows. */ - /* !(A || B) -> !A && !B */ - /* !(A -- B) -> !(A && !B) -> !A || B */ - /* !(A XOR B) -> !(!A XOR !B) -> !A XNOR !B */ - op = (*ptr == META_ECLASS_OR )? ECL_AND : - (*ptr == META_ECLASS_SUB)? ECL_OR : - /*ptr == META_ECLASS_XOR*/ ECL_XOR; - op_neg = (*ptr == META_ECLASS_XOR); - rhs_negated = *ptr != META_ECLASS_SUB; - } - else - { - /* A || B -> A || B */ - /* A -- B -> A && !B */ - /* A XOR B -> A XOR B */ - op = (*ptr == META_ECLASS_OR )? ECL_OR : - (*ptr == META_ECLASS_SUB)? ECL_AND : - /*ptr == META_ECLASS_XOR*/ ECL_XOR; - op_neg = FALSE; - rhs_negated = *ptr == META_ECLASS_SUB; - } - - ++ptr; - - /* An operand must follow the operator. */ - if (!compile_class_binary_tight(context, rhs_negated, &ptr, &code, - &rhs_op_info, lengthptr)) - return FALSE; - - /* Convert infix to postfix (RPN). */ - fold_binary(op, pop_info, &rhs_op_info, lengthptr); - if (op_neg) fold_negation(pop_info, lengthptr, FALSE); - if (lengthptr == NULL) - code = pop_info->code_start + pop_info->length; - } - -PCRE2_ASSERT(lengthptr == NULL || code == start_code); - -*pptr = ptr; -*pcode = code; -return TRUE; -} - - - -/* This function converts the META codes in pptr into opcodes written to -pcode. The pptr must start at a META_CLASS or META_CLASS_NOT. - -The class is compiled as a left-associative sequence of operator -applications. - -The pptr will be left pointing at the matching META_CLASS_END. */ - -static BOOL -compile_eclass_nested(eclass_context *context, BOOL negated, - uint32_t **pptr, PCRE2_UCHAR **pcode, - eclass_op_info *pop_info, PCRE2_SIZE *lengthptr) -{ -uint32_t *ptr = *pptr; -#ifdef PCRE2_DEBUG -PCRE2_UCHAR *start_code = *pcode; -#endif - -/* The CLASS_IS_ECLASS bit must be set since it is a nested class. */ -PCRE2_ASSERT(*ptr == (META_CLASS | CLASS_IS_ECLASS) || - *ptr == (META_CLASS_NOT | CLASS_IS_ECLASS)); - -if (*ptr++ == (META_CLASS_NOT | CLASS_IS_ECLASS)) - negated = !negated; - -(*pptr)++; - -/* Because it's a non-empty class, there must be an operand at the start. */ -if (!compile_class_binary_loose(context, negated, pptr, pcode, - pop_info, lengthptr)) - return FALSE; - -PCRE2_ASSERT(**pptr == META_CLASS_END); -PCRE2_ASSERT(lengthptr == NULL || *pcode == start_code); -return TRUE; -} - -BOOL -PRIV(compile_class_nested)(uint32_t options, uint32_t xoptions, - uint32_t **pptr, PCRE2_UCHAR **pcode, int *errorcodeptr, - compile_block *cb, PCRE2_SIZE *lengthptr) -{ -eclass_context context; -eclass_op_info op_info; -PCRE2_SIZE previous_length = (lengthptr != NULL)? *lengthptr : 0; -PCRE2_UCHAR *code = *pcode; -PCRE2_UCHAR *previous; -BOOL allbitsone = TRUE; - -context.needs_bitmap = FALSE; -context.options = options; -context.xoptions = xoptions; -context.errorcodeptr = errorcodeptr; -context.cb = cb; - -previous = code; -*code++ = OP_ECLASS; -code += LINK_SIZE; -*code++ = 0; /* Flags, currently zero. */ -if (!compile_eclass_nested(&context, FALSE, pptr, &code, &op_info, lengthptr)) - return FALSE; - -if (lengthptr != NULL) - { - *lengthptr += code - previous; - code = previous; - /* (*lengthptr - previous_length) now holds the amount of buffer that - we require to make the call to compile_class_nested() with - lengthptr = NULL, and including the (1+LINK_SIZE+1) that we write out - before that call. */ - } - -/* Do some useful counting of what's in the bitmap. */ -for (int i = 0; i < 8; i++) - if (op_info.bits.classwords[i] != 0xffffffff) - { - allbitsone = FALSE; - break; - } - -/* After constant-folding the extended class syntax, it may turn out to be -a simple class after all. In that case, we can unwrap it from the -OP_ECLASS container - and in fact, we must do so, because in 8-bit -no-Unicode mode the matcher is compiled without support for OP_ECLASS. */ - -#ifndef SUPPORT_WIDE_CHARS -PCRE2_ASSERT(op_info.op_single_type != 0); -#else -if (op_info.op_single_type != 0) -#endif - { - /* Rewind back over the OP_ECLASS. */ - code = previous; - - /* If the bits are all ones, and the "high characters" are all matched - too, we use a special-cased encoding of OP_ALLANY. */ - - if (op_info.op_single_type == ECL_ANY && allbitsone) - { - /* Advancing code means rewinding lengthptr, at this point. */ - if (lengthptr != NULL) *lengthptr -= 1; - *code++ = OP_ALLANY; - } - - /* If the high bits are all matched / all not-matched, then we emit an - OP_NCLASS/OP_CLASS respectively. */ - - else if (op_info.op_single_type == ECL_ANY || - op_info.op_single_type == ECL_NONE) - { - PCRE2_SIZE required_len = 1 + (32 / sizeof(PCRE2_UCHAR)); - - if (lengthptr != NULL) - { - if (required_len > (*lengthptr - previous_length)) - *lengthptr = previous_length + required_len; - } - - /* Advancing code means rewinding lengthptr, at this point. */ - if (lengthptr != NULL) *lengthptr -= required_len; - *code++ = (op_info.op_single_type == ECL_ANY)? OP_NCLASS : OP_CLASS; - memcpy(code, op_info.bits.classbits, 32); - code += 32 / sizeof(PCRE2_UCHAR); - } - - /* Otherwise, we have an ECL_XCLASS, so we have the OP_XCLASS data - there, but, we pulled out its bitmap into op_info, so now we have to - put that back into the OP_XCLASS. */ - - else - { -#ifndef SUPPORT_WIDE_CHARS - PCRE2_DEBUG_UNREACHABLE(); -#else - BOOL need_map = context.needs_bitmap; - PCRE2_SIZE required_len; - - PCRE2_ASSERT(op_info.op_single_type == ECL_XCLASS); - required_len = op_info.length + (need_map? 32/sizeof(PCRE2_UCHAR) : 0); - - if (lengthptr != NULL) - { - /* Don't unconditionally request all the space we need - we may - already have asked for more during processing of the ECLASS. */ - if (required_len > (*lengthptr - previous_length)) - *lengthptr = previous_length + required_len; - - /* The code we write out here won't be ignored, even during the - (lengthptr != NULL) phase, because if there's a following quantifier - it will peek backwards. So we do have to write out a (truncated) - OP_XCLASS, even on this branch. */ - *lengthptr -= 1 + LINK_SIZE + 1; - *code++ = OP_XCLASS; - PUT(code, 0, 1 + LINK_SIZE + 1); - code += LINK_SIZE; - *code++ = 0; - } - else - { - PCRE2_UCHAR *rest; - PCRE2_SIZE rest_len; - PCRE2_UCHAR flags; - - /* 1 unit: OP_XCLASS | LINK_SIZE units | 1 unit: flags | ...rest */ - PCRE2_ASSERT(op_info.length >= 1 + LINK_SIZE + 1); - rest = op_info.code_start + 1 + LINK_SIZE + 1; - rest_len = (op_info.code_start + op_info.length) - rest; - - /* First read any data we use, before memmove splats it. */ - flags = op_info.code_start[1 + LINK_SIZE]; - PCRE2_ASSERT((flags & XCL_MAP) == 0); - - /* Next do the memmove before any writes. */ - memmove(code + 1 + LINK_SIZE + 1 + (need_map? 32/sizeof(PCRE2_UCHAR) : 0), - rest, CU2BYTES(rest_len)); - - /* Finally write the header data. */ - *code++ = OP_XCLASS; - PUT(code, 0, (int)required_len); - code += LINK_SIZE; - *code++ = flags | (need_map? XCL_MAP : 0); - if (need_map) - { - memcpy(code, op_info.bits.classbits, 32); - code += 32 / sizeof(PCRE2_UCHAR); - } - code += rest_len; - } -#endif /* SUPPORT_WIDE_CHARS */ - } - } - -/* Otherwise, we're going to keep the OP_ECLASS. However, again we need -to do some adjustment to insert the bitmap if we have one. */ - -#ifdef SUPPORT_WIDE_CHARS -else - { - BOOL need_map = context.needs_bitmap; - PCRE2_SIZE required_len = - 1 + LINK_SIZE + 1 + (need_map? 32/sizeof(PCRE2_UCHAR) : 0) + op_info.length; - - if (lengthptr != NULL) - { - if (required_len > (*lengthptr - previous_length)) - *lengthptr = previous_length + required_len; - - /* As for the XCLASS branch above, we do have to write out a dummy - OP_ECLASS, because of the backwards peek by the quantifier code. Write - out a (truncated) OP_ECLASS, even on this branch. */ - *lengthptr -= 1 + LINK_SIZE + 1; - *code++ = OP_ECLASS; - PUT(code, 0, 1 + LINK_SIZE + 1); - code += LINK_SIZE; - *code++ = 0; - } - else - { - if (need_map) - { - PCRE2_UCHAR *map_start = previous + 1 + LINK_SIZE + 1; - previous[1 + LINK_SIZE] |= ECL_MAP; - memmove(map_start + 32/sizeof(PCRE2_UCHAR), map_start, - CU2BYTES(code - map_start)); - memcpy(map_start, op_info.bits.classbits, 32); - code += 32 / sizeof(PCRE2_UCHAR); - } - PUT(previous, 1, (int)(code - previous)); - } - } -#endif /* SUPPORT_WIDE_CHARS */ - -*pcode = code; -return TRUE; -} - -/* End of pcre2_compile_class.c */ diff --git a/ext/pcre/pcre2lib/pcre2_config.c b/ext/pcre/pcre2lib/pcre2_config.c index 031981b09bfea..5ef103caf7925 100644 --- a/ext/pcre/pcre2lib/pcre2_config.c +++ b/ext/pcre/pcre2lib/pcre2_config.c @@ -224,8 +224,8 @@ switch (what) XSTRING when PCRE2_PRERELEASE is not empty, an unwanted space is inserted. There are problems using an "obvious" approach like this: - XSTRING(PCRE2_MAJOR) "." XSTRING(PCRE2_MINOR) - XSTRING(PCRE2_PRERELEASE) " " XSTRING(PCRE2_DATE) + XSTRING(PCRE2_MAJOR) "." XSTRING(PCRE_MINOR) + XSTRING(PCRE2_PRERELEASE) " " XSTRING(PCRE_DATE) because, when PCRE2_PRERELEASE is empty, this leads to an attempted expansion of STRING(). The C standard states: "If (before argument substitution) any diff --git a/ext/pcre/pcre2lib/pcre2_context.c b/ext/pcre/pcre2lib/pcre2_context.c index 2345145d3f55c..9edbd1b2ae865 100644 --- a/ext/pcre/pcre2lib/pcre2_context.c +++ b/ext/pcre/pcre2lib/pcre2_context.c @@ -130,7 +130,7 @@ return gcontext; /* A default compile context is set up to save having to initialize at run time when no context is supplied to the compile function. */ -pcre2_compile_context PRIV(default_compile_context) = { +const pcre2_compile_context PRIV(default_compile_context) = { { default_malloc, default_free, NULL }, /* Default memory handling */ NULL, /* Stack guard */ NULL, /* Stack guard data */ @@ -141,8 +141,7 @@ pcre2_compile_context PRIV(default_compile_context) = { NEWLINE_DEFAULT, /* Newline convention */ PARENS_NEST_LIMIT, /* As it says */ 0, /* Extra options */ - MAX_VARLOOKBEHIND, /* As it says */ - PCRE2_OPTIMIZATION_ALL /* All optimizations enabled */ + MAX_VARLOOKBEHIND /* As it says */ }; /* The create function copies the default into the new memory, but must @@ -164,7 +163,7 @@ return ccontext; /* A default match context is set up to save having to initialize at run time when no context is supplied to a match function. */ -pcre2_match_context PRIV(default_match_context) = { +const pcre2_match_context PRIV(default_match_context) = { { default_malloc, default_free, NULL }, #ifdef SUPPORT_JIT NULL, /* JIT callback */ @@ -174,8 +173,6 @@ pcre2_match_context PRIV(default_match_context) = { NULL, /* Callout data */ NULL, /* Substitute callout function */ NULL, /* Substitute callout data */ - NULL, /* Substitute case callout function */ - NULL, /* Substitute case callout data */ PCRE2_UNSET, /* Offset limit */ HEAP_LIMIT, MATCH_LIMIT, @@ -200,7 +197,7 @@ return mcontext; /* A default convert context is set up to save having to initialize at run time when no context is supplied to the convert function. */ -pcre2_convert_context PRIV(default_convert_context) = { +const pcre2_convert_context PRIV(default_convert_context) = { { default_malloc, default_free, NULL }, /* Default memory handling */ #ifdef _WIN32 CHAR_BACKSLASH, /* Default path separator */ @@ -412,38 +409,6 @@ ccontext->stack_guard_data = user_data; return 0; } -PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION -pcre2_set_optimize(pcre2_compile_context *ccontext, uint32_t directive) -{ -if (ccontext == NULL) - return PCRE2_ERROR_NULL; - -switch (directive) - { - case PCRE2_OPTIMIZATION_NONE: - ccontext->optimization_flags = 0; - break; - - case PCRE2_OPTIMIZATION_FULL: - ccontext->optimization_flags = PCRE2_OPTIMIZATION_ALL; - break; - - default: - if (directive >= PCRE2_AUTO_POSSESS && directive <= PCRE2_START_OPTIMIZE_OFF) - { - /* Even directive numbers starting from 64 switch a bit on; - * Odd directive numbers starting from 65 switch a bit off */ - if ((directive & 1) != 0) - ccontext->optimization_flags &= ~(1u << ((directive >> 1) - 32)); - else - ccontext->optimization_flags |= 1u << ((directive >> 1) - 32); - return 0; - } - return PCRE2_ERROR_BADOPTION; - } - -return 0; -} /* ------------ Match context ------------ */ @@ -459,24 +424,13 @@ return 0; PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION pcre2_set_substitute_callout(pcre2_match_context *mcontext, int (*substitute_callout)(pcre2_substitute_callout_block *, void *), - void *substitute_callout_data) + void *substitute_callout_data) { mcontext->substitute_callout = substitute_callout; mcontext->substitute_callout_data = substitute_callout_data; return 0; } -PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION -pcre2_set_substitute_case_callout(pcre2_match_context *mcontext, - PCRE2_SIZE (*substitute_case_callout)(PCRE2_SPTR, PCRE2_SIZE, PCRE2_UCHAR *, - PCRE2_SIZE, int, void *), - void *substitute_case_callout_data) -{ -mcontext->substitute_case_callout = substitute_case_callout; -mcontext->substitute_case_callout_data = substitute_case_callout_data; -return 0; -} - PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION pcre2_set_heap_limit(pcre2_match_context *mcontext, uint32_t limit) { diff --git a/ext/pcre/pcre2lib/pcre2_convert.c b/ext/pcre/pcre2lib/pcre2_convert.c index d2b238ca4afb4..fe396ae4f9c58 100644 --- a/ext/pcre/pcre2lib/pcre2_convert.c +++ b/ext/pcre/pcre2lib/pcre2_convert.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2024 University of Cambridge + New API code Copyright (c) 2016-2022 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -74,7 +74,7 @@ enum { POSIX_START_REGEX, POSIX_ANCHORED, POSIX_NOT_BRACKET, #define PUTCHARS(string) \ { \ - for (const char *s = string; *s != 0; s++) \ + for (s = (char *)(string); *s != 0; s++) \ { \ if (p >= endp) return PCRE2_ERROR_NOMEMORY; \ *p++ = *s; \ @@ -125,6 +125,7 @@ convert_posix(uint32_t pattype, PCRE2_SPTR pattern, PCRE2_SIZE plength, BOOL utf, PCRE2_UCHAR *use_buffer, PCRE2_SIZE use_length, PCRE2_SIZE *bufflenptr, BOOL dummyrun, pcre2_convert_context *ccontext) { +char *s; PCRE2_SPTR posix = pattern; PCRE2_UCHAR *p = use_buffer; PCRE2_UCHAR *pp = p; @@ -1064,7 +1065,7 @@ pcre2_pattern_convert(PCRE2_SPTR pattern, PCRE2_SIZE plength, uint32_t options, PCRE2_UCHAR **buffptr, PCRE2_SIZE *bufflenptr, pcre2_convert_context *ccontext) { -int rc; +int i, rc; PCRE2_UCHAR dummy_buffer[DUMMY_BUFFER_SIZE]; PCRE2_UCHAR *use_buffer = dummy_buffer; PCRE2_SIZE use_length = DUMMY_BUFFER_SIZE; @@ -1118,7 +1119,7 @@ if (buffptr != NULL && *buffptr != NULL) /* Call an individual converter, either just once (if a buffer was provided or just the length is needed), or twice (if a memory allocation is required). */ -for (int i = 0; i < 2; i++) +for (i = 0; i < 2; i++) { PCRE2_UCHAR *allocated; BOOL dummyrun = buffptr == NULL || *buffptr == NULL; @@ -1137,7 +1138,8 @@ for (int i = 0; i < 2; i++) break; default: - goto EXIT; + *bufflenptr = 0; /* Error offset */ + return PCRE2_ERROR_INTERNAL; } if (rc != 0 || /* Error */ @@ -1157,12 +1159,8 @@ for (int i = 0; i < 2; i++) use_length = *bufflenptr + 1; } -/* Something went terribly wrong. Trigger an assert and return an error */ -PCRE2_DEBUG_UNREACHABLE(); +/* Control should never get here. */ -EXIT: - -*bufflenptr = 0; /* Error offset */ return PCRE2_ERROR_INTERNAL; } diff --git a/ext/pcre/pcre2lib/pcre2_dfa_match.c b/ext/pcre/pcre2lib/pcre2_dfa_match.c index ebf31d284d27e..caae65248ff7c 100644 --- a/ext/pcre/pcre2lib/pcre2_dfa_match.c +++ b/ext/pcre/pcre2lib/pcre2_dfa_match.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2024 University of Cambridge + New API code Copyright (c) 2016-2023 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -156,7 +156,6 @@ static const uint8_t coptable[] = { 0, /* CLASS */ 0, /* NCLASS */ 0, /* XCLASS - variable length */ - 0, /* ECLASS - variable length */ 0, /* REF */ 0, /* REFI */ 0, /* DNREF */ @@ -176,7 +175,6 @@ static const uint8_t coptable[] = { 0, /* Assert behind not */ 0, /* NA assert */ 0, /* NA assert behind */ - 0, /* Assert scan substring */ 0, /* ONCE */ 0, /* SCRIPT_RUN */ 0, 0, 0, 0, 0, /* BRA, BRAPOS, CBRA, CBRAPOS, COND */ @@ -190,7 +188,7 @@ static const uint8_t coptable[] = { 0, 0, /* COMMIT, COMMIT_ARG */ 0, 0, 0, /* FAIL, ACCEPT, ASSERT_ACCEPT */ 0, 0, 0, /* CLOSE, SKIPZERO, DEFINE */ - 0, 0, /* \B and \b in UCP mode */ + 0, 0 /* \B and \b in UCP mode */ }; /* This table identifies those opcodes that inspect a character. It is used to @@ -236,7 +234,6 @@ static const uint8_t poptable[] = { 1, /* CLASS */ 1, /* NCLASS */ 1, /* XCLASS - variable length */ - 1, /* ECLASS - variable length */ 0, /* REF */ 0, /* REFI */ 0, /* DNREF */ @@ -256,7 +253,6 @@ static const uint8_t poptable[] = { 0, /* Assert behind not */ 0, /* NA assert */ 0, /* NA assert behind */ - 0, /* Assert scan substring */ 0, /* ONCE */ 0, /* SCRIPT_RUN */ 0, 0, 0, 0, 0, /* BRA, BRAPOS, CBRA, CBRAPOS, COND */ @@ -270,13 +266,9 @@ static const uint8_t poptable[] = { 0, 0, /* COMMIT, COMMIT_ARG */ 0, 0, 0, /* FAIL, ACCEPT, ASSERT_ACCEPT */ 0, 0, 0, /* CLOSE, SKIPZERO, DEFINE */ - 1, 1, /* \B and \b in UCP mode */ + 1, 1 /* \B and \b in UCP mode */ }; -/* Compile-time check that these tables have the correct size. */ -STATIC_ASSERT(sizeof(coptable) == OP_TABLE_LENGTH, coptable); -STATIC_ASSERT(sizeof(poptable) == OP_TABLE_LENGTH, poptable); - /* These 2 tables allow for compact code for testing for \D, \d, \S, \s, \W, and \w */ @@ -703,6 +695,7 @@ for (;;) int i, j; int clen, dlen; uint32_t c, d; + int forced_fail = 0; BOOL partial_newline = FALSE; BOOL could_continue = reset_could_continue; reset_could_continue = FALSE; @@ -848,6 +841,19 @@ for (;;) switch (codevalue) { +/* ========================================================================== */ + /* These cases are never obeyed. This is a fudge that causes a compile- + time error if the vectors coptable or poptable, which are indexed by + opcode, are not the correct length. It seems to be the only way to do + such a check at compile time, as the sizeof() operator does not work + in the C preprocessor. */ + + case OP_TABLE_LENGTH: + case OP_TABLE_LENGTH + + ((sizeof(coptable) == OP_TABLE_LENGTH) && + (sizeof(poptable) == OP_TABLE_LENGTH)): + return 0; + /* ========================================================================== */ /* Reached a closing bracket. If not at the end of the pattern, carry on with the next opcode. For repeating opcodes, also add the repeat @@ -1173,6 +1179,10 @@ for (;;) const ucd_record * prop = GET_UCD(c); switch(code[1]) { + case PT_ANY: + OK = TRUE; + break; + case PT_LAMP: chartype = prop->chartype; OK = chartype == ucp_Lu || chartype == ucp_Ll || @@ -1452,6 +1462,10 @@ for (;;) const ucd_record * prop = GET_UCD(c); switch(code[2]) { + case PT_ANY: + OK = TRUE; + break; + case PT_LAMP: chartype = prop->chartype; OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt; @@ -1713,6 +1727,10 @@ for (;;) const ucd_record * prop = GET_UCD(c); switch(code[2]) { + case PT_ANY: + OK = TRUE; + break; + case PT_LAMP: chartype = prop->chartype; OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt; @@ -1999,6 +2017,10 @@ for (;;) const ucd_record * prop = GET_UCD(c); switch(code[1 + IMM2_SIZE + 1]) { + case PT_ANY: + OK = TRUE; + break; + case PT_LAMP: chartype = prop->chartype; OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt; @@ -2641,54 +2663,35 @@ for (;;) case OP_CLASS: case OP_NCLASS: -#ifdef SUPPORT_WIDE_CHARS case OP_XCLASS: - case OP_ECLASS: -#endif { BOOL isinclass = FALSE; int next_state_offset; PCRE2_SPTR ecode; -#ifdef SUPPORT_WIDE_CHARS - /* An extended class may have a table or a list of single characters, - ranges, or both, and it may be positive or negative. There's a - function that sorts all this out. */ - - if (codevalue == OP_XCLASS) - { - ecode = code + GET(code, 1); - if (clen > 0) - isinclass = PRIV(xclass)(c, code + 1 + LINK_SIZE, - (const uint8_t*)mb->start_code, utf); - } - - /* A nested set-based class has internal opcodes for performing - set operations. */ - - else if (codevalue == OP_ECLASS) - { - ecode = code + GET(code, 1); - if (clen > 0) - isinclass = PRIV(eclass)(c, code + 1 + LINK_SIZE, ecode, - (const uint8_t*)mb->start_code, utf); - } - - else -#endif /* SUPPORT_WIDE_CHARS */ - /* For a simple class, there is always just a 32-byte table, and we can set isinclass from it. */ + if (codevalue != OP_XCLASS) { ecode = code + 1 + (32 / sizeof(PCRE2_UCHAR)); if (clen > 0) { isinclass = (c > 255)? (codevalue == OP_NCLASS) : - ((((const uint8_t *)(code + 1))[c/8] & (1u << (c&7))) != 0); + ((((uint8_t *)(code + 1))[c/8] & (1u << (c&7))) != 0); } } + /* An extended class may have a table or a list of single characters, + ranges, or both, and it may be positive or negative. There's a + function that sorts all this out. */ + + else + { + ecode = code + GET(code, 1); + if (clen > 0) isinclass = PRIV(xclass)(c, code + 1 + LINK_SIZE, utf); + } + /* At this point, isinclass is set for all kinds of class, and ecode points to the byte after the end of the class. If there is a quantifier, this is where it will be. */ @@ -2781,6 +2784,7 @@ for (;;) though the other "backtracking verbs" are not supported. */ case OP_FAIL: + forced_fail++; /* Count FAILs for multiple states */ break; case OP_ASSERT: @@ -3054,7 +3058,7 @@ for (;;) if (codevalue == OP_BRAPOSZERO) { allow_zero = TRUE; - ++code; /* The following opcode will be one of the above BRAs */ + codevalue = *(++code); /* Codevalue will be one of above BRAs */ } else allow_zero = FALSE; @@ -3267,12 +3271,18 @@ for (;;) matches that we are going to find. If partial matching has been requested, check for appropriate conditions. + The "forced_ fail" variable counts the number of (*F) encountered for the + character. If it is equal to the original active_count (saved in + workspace[1]) it means that (*F) was found on every active state. In this + case we don't want to give a partial match. + The "could_continue" variable is true if a state could have continued but for the fact that the end of the subject was reached. */ if (new_count <= 0) { if (could_continue && /* Some could go on, and */ + forced_fail != workspace[1] && /* Not all forced fail & */ ( /* either... */ (mb->moptions & PCRE2_PARTIAL_HARD) != 0 /* Hard partial */ || /* or... */ @@ -3428,7 +3438,7 @@ if ((re->flags & PCRE2_MODE_MASK) != PCRE2_CODE_UNIT_WIDTH/8) /* PCRE2_NOTEMPTY and PCRE2_NOTEMPTY_ATSTART are match-time flags in the options variable for this function. Users of PCRE2 who are not calling the function directly would like to have a way of setting these flags, in the same -way that they can set pcre2_compile() flags like PCRE2_NO_AUTO_POSSESS with +way that they can set pcre2_compile() flags like PCRE2_NO_AUTOPOSSESS with constructions like (*NO_AUTOPOSSESS). To enable this, (*NOTEMPTY) and (*NOTEMPTY_ATSTART) set bits in the pattern's "flag" function which can now be transferred to the options for this function. The bits are guaranteed to be @@ -3518,7 +3528,8 @@ if (mb->match_limit_depth > re->limit_depth) if (mb->heap_limit > re->limit_heap) mb->heap_limit = re->limit_heap; -mb->start_code = (PCRE2_SPTR)((const uint8_t *)re + re->code_start); +mb->start_code = (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code)) + + re->name_count * re->name_entry_size; mb->tables = re->tables; mb->start_subject = subject; mb->end_subject = end_subject; @@ -3565,9 +3576,7 @@ switch(re->newline_convention) mb->nltype = NLTYPE_ANYCRLF; break; - default: - PCRE2_DEBUG_UNREACHABLE(); - return PCRE2_ERROR_INTERNAL; + default: return PCRE2_ERROR_INTERNAL; } /* Check a UTF string for validity if required. For 8-bit and 16-bit strings, @@ -3696,7 +3705,7 @@ for (;;) these, for testing and for ensuring that all callouts do actually occur. The optimizations must also be avoided when restarting a DFA match. */ - if ((re->optimization_flags & PCRE2_OPTIM_START_OPTIMIZE) != 0 && + if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0 && (options & PCRE2_DFA_RESTART) == 0) { /* If firstline is TRUE, the start of the match is constrained to the first diff --git a/ext/pcre/pcre2lib/pcre2_error.c b/ext/pcre/pcre2lib/pcre2_error.c index 8b7423c6c6404..7fa997aa9510b 100644 --- a/ext/pcre/pcre2lib/pcre2_error.c +++ b/ext/pcre/pcre2lib/pcre2_error.c @@ -96,7 +96,7 @@ static const unsigned char compile_error_texts[] = "length of lookbehind assertion is not limited\0" "a relative value of zero is not allowed\0" "conditional subpattern contains more than two branches\0" - "atomic assertion expected after (?( or (?(?C)\0" + "assertion expected after (?( or (?(?C)\0" "digit expected after (?+ or (?-\0" /* 30 */ "unknown POSIX class name\0" @@ -161,7 +161,7 @@ static const unsigned char compile_error_texts[] = "using UCP is disabled by the application\0" "name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN)\0" "character code point value in \\u.... sequence is too large\0" - "digits missing after \\x or in \\x{} or \\o{} or \\N{U+}\0" + "digits missing in \\x{} or \\o{} or \\N{U+}\0" "syntax error or number too big in (?(VERSION condition\0" /* 80 */ "internal error: unknown opcode in auto_possessify()\0" @@ -185,29 +185,11 @@ static const unsigned char compile_error_texts[] = "(*alpha_assertion) not recognized\0" "script runs require Unicode support, which this version of PCRE2 does not have\0" "too many capturing groups (maximum 65535)\0" - "octal digit missing after \\0 (PCRE2_EXTRA_NO_BS0 is set)\0" + "atomic assertion expected after (?( or (?(?C)\0" "\\K is not allowed in lookarounds (but see PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK)\0" /* 100 */ "branch too long in variable-length lookbehind assertion\0" "compiled pattern would be longer than the limit set by the application\0" - "octal value given by \\ddd is greater than \\377 (forbidden by PCRE2_EXTRA_PYTHON_OCTAL)\0" - "using callouts is disabled by the application\0" - "PCRE2_EXTRA_TURKISH_CASING require Unicode (UTF or UCP) mode\0" - /* 105 */ - "PCRE2_EXTRA_TURKISH_CASING requires UTF in 8-bit mode\0" - "PCRE2_EXTRA_TURKISH_CASING and PCRE2_EXTRA_CASELESS_RESTRICT are not compatible\0" - "extended character class nesting is too deep\0" - "invalid operator in extended character class\0" - "unexpected operator in extended character class (no preceding operand)\0" - /* 110 */ - "expected operand after operator in extended character class\0" - "square brackets needed to clarify operator precedence in extended character class\0" - "missing terminating ] for extended character class (note '[' must be escaped under PCRE2_ALT_EXTENDED_CLASS)\0" - "unexpected expression in extended character class (no preceding operator)\0" - "empty expression in extended character class\0" - /* 115 */ - "terminating ] with no following closing parenthesis in (?[...]\0" - "unexpected character in (?[...]) extended character class\0" ; /* Match-time and UTF error texts are in the same format. */ @@ -294,10 +276,6 @@ static const unsigned char match_error_texts[] = "internal error - duplicate substitution match\0" "PCRE2_MATCH_INVALID_UTF is not supported for DFA matching\0" "INTERNAL ERROR: invalid substring offset\0" - "feature is not supported by the JIT compiler\0" - "error performing replacement case transformation\0" - /* 70 */ - "replacement too large (longer than PCRE2_SIZE)\0" ; @@ -340,7 +318,7 @@ else if (enumber < 0) /* Match or UTF error */ } else /* Invalid error number */ { - message = (const unsigned char *)"\0"; /* Empty message list */ + message = (unsigned char *)"\0"; /* Empty message list */ n = 1; } diff --git a/ext/pcre/pcre2lib/pcre2_extuni.c b/ext/pcre/pcre2lib/pcre2_extuni.c index 91d839e2970c4..4ed9f00c55a1c 100644 --- a/ext/pcre/pcre2lib/pcre2_extuni.c +++ b/ext/pcre/pcre2lib/pcre2_extuni.c @@ -40,7 +40,7 @@ POSSIBILITY OF SUCH DAMAGE. /* This module contains an internal function that is used to match a Unicode extended grapheme sequence. It is used by both pcre2_match() and -pcre2_dfa_match(). However, it is called only when Unicode support is being +pcre2_def_match(). However, it is called only when Unicode support is being compiled. Nevertheless, we provide a dummy function when there is no Unicode support, because some compilers do not like functionless source files. */ diff --git a/ext/pcre/pcre2lib/pcre2_find_bracket.c b/ext/pcre/pcre2lib/pcre2_find_bracket.c index 486f4539d89e3..1290c5e9de11b 100644 --- a/ext/pcre/pcre2lib/pcre2_find_bracket.c +++ b/ext/pcre/pcre2lib/pcre2_find_bracket.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2024 University of Cambridge + New API code Copyright (c) 2016-2023 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -76,19 +76,18 @@ for (;;) if (c == OP_END) return NULL; /* XCLASS is used for classes that cannot be represented just by a bit map. - This includes negated single high-valued characters. ECLASS is used for - classes that use set operations internally. CALLOUT_STR is used for - callouts with string arguments. In each case the length in the table is + This includes negated single high-valued characters. CALLOUT_STR is used for + callouts with string arguments. In both cases the length in the table is zero; the actual length is stored in the compiled code. */ - if (c == OP_XCLASS || c == OP_ECLASS) code += GET(code, 1); - else if (c == OP_CALLOUT_STR) code += GET(code, 1 + 2*LINK_SIZE); + if (c == OP_XCLASS) code += GET(code, 1); + else if (c == OP_CALLOUT_STR) code += GET(code, 1 + 2*LINK_SIZE); /* Handle lookbehind */ else if (c == OP_REVERSE || c == OP_VREVERSE) { - if (number < 0) return code; + if (number < 0) return (PCRE2_UCHAR *)code; code += PRIV(OP_lengths)[c]; } @@ -98,7 +97,7 @@ for (;;) c == OP_CBRAPOS || c == OP_SCBRAPOS) { int n = (int)GET2(code, 1+LINK_SIZE); - if (n == number) return code; + if (n == number) return (PCRE2_UCHAR *)code; code += PRIV(OP_lengths)[c]; } diff --git a/ext/pcre/pcre2lib/pcre2_internal.h b/ext/pcre/pcre2lib/pcre2_internal.h index 6e0a5e05d03f5..e5808182e676c 100644 --- a/ext/pcre/pcre2lib/pcre2_internal.h +++ b/ext/pcre/pcre2lib/pcre2_internal.h @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2024 University of Cambridge + New API code Copyright (c) 2016-2023 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -88,12 +88,6 @@ typedef int BOOL; #define TRUE 1 #endif -/* Helper macro for static (compile-time) assertions. Can be used inside -functions, or at the top-level of a file. */ -#define STATIC_ASSERT_JOIN(a,b) a ## b -#define STATIC_ASSERT(cond, msg) \ - typedef int STATIC_ASSERT_JOIN(static_assertion_,msg)[(cond)?1:-1] - /* Valgrind (memcheck) support */ #ifdef SUPPORT_VALGRIND @@ -529,29 +523,29 @@ start/end of string field names are. */ three must not be changed, because whichever is set is actually the number of bytes in a code unit in that mode. */ -#define PCRE2_MODE8 0x00000001u /* compiled in 8 bit mode */ -#define PCRE2_MODE16 0x00000002u /* compiled in 16 bit mode */ -#define PCRE2_MODE32 0x00000004u /* compiled in 32 bit mode */ -#define PCRE2_FIRSTSET 0x00000010u /* first_code unit is set */ -#define PCRE2_FIRSTCASELESS 0x00000020u /* caseless first code unit */ -#define PCRE2_FIRSTMAPSET 0x00000040u /* bitmap of first code units is set */ -#define PCRE2_LASTSET 0x00000080u /* last code unit is set */ -#define PCRE2_LASTCASELESS 0x00000100u /* caseless last code unit */ -#define PCRE2_STARTLINE 0x00000200u /* start after \n for multiline */ -#define PCRE2_JCHANGED 0x00000400u /* j option used in pattern */ -#define PCRE2_HASCRORLF 0x00000800u /* explicit \r or \n in pattern */ -#define PCRE2_HASTHEN 0x00001000u /* pattern contains (*THEN) */ -#define PCRE2_MATCH_EMPTY 0x00002000u /* pattern can match empty string */ -#define PCRE2_BSR_SET 0x00004000u /* BSR was set in the pattern */ -#define PCRE2_NL_SET 0x00008000u /* newline was set in the pattern */ -#define PCRE2_NOTEMPTY_SET 0x00010000u /* (*NOTEMPTY) used ) keep */ -#define PCRE2_NE_ATST_SET 0x00020000u /* (*NOTEMPTY_ATSTART) used) together */ -#define PCRE2_DEREF_TABLES 0x00040000u /* release character tables */ -#define PCRE2_NOJIT 0x00080000u /* (*NOJIT) used */ -#define PCRE2_HASBKPORX 0x00100000u /* contains \P, \p, or \X */ -#define PCRE2_DUPCAPUSED 0x00200000u /* contains (?| */ -#define PCRE2_HASBKC 0x00400000u /* contains \C */ -#define PCRE2_HASACCEPT 0x00800000u /* contains (*ACCEPT) */ +#define PCRE2_MODE8 0x00000001 /* compiled in 8 bit mode */ +#define PCRE2_MODE16 0x00000002 /* compiled in 16 bit mode */ +#define PCRE2_MODE32 0x00000004 /* compiled in 32 bit mode */ +#define PCRE2_FIRSTSET 0x00000010 /* first_code unit is set */ +#define PCRE2_FIRSTCASELESS 0x00000020 /* caseless first code unit */ +#define PCRE2_FIRSTMAPSET 0x00000040 /* bitmap of first code units is set */ +#define PCRE2_LASTSET 0x00000080 /* last code unit is set */ +#define PCRE2_LASTCASELESS 0x00000100 /* caseless last code unit */ +#define PCRE2_STARTLINE 0x00000200 /* start after \n for multiline */ +#define PCRE2_JCHANGED 0x00000400 /* j option used in pattern */ +#define PCRE2_HASCRORLF 0x00000800 /* explicit \r or \n in pattern */ +#define PCRE2_HASTHEN 0x00001000 /* pattern contains (*THEN) */ +#define PCRE2_MATCH_EMPTY 0x00002000 /* pattern can match empty string */ +#define PCRE2_BSR_SET 0x00004000 /* BSR was set in the pattern */ +#define PCRE2_NL_SET 0x00008000 /* newline was set in the pattern */ +#define PCRE2_NOTEMPTY_SET 0x00010000 /* (*NOTEMPTY) used ) keep */ +#define PCRE2_NE_ATST_SET 0x00020000 /* (*NOTEMPTY_ATSTART) used) together */ +#define PCRE2_DEREF_TABLES 0x00040000 /* release character tables */ +#define PCRE2_NOJIT 0x00080000 /* (*NOJIT) used */ +#define PCRE2_HASBKPORX 0x00100000 /* contains \P, \p, or \X */ +#define PCRE2_DUPCAPUSED 0x00200000 /* contains (?| */ +#define PCRE2_HASBKC 0x00400000 /* contains \C */ +#define PCRE2_HASACCEPT 0x00800000 /* contains (*ACCEPT) */ #define PCRE2_MODE_MASK (PCRE2_MODE8 | PCRE2_MODE16 | PCRE2_MODE32) @@ -580,16 +574,6 @@ modes. */ #define REQ_CU_MAX 2000 #endif -/* The maximum nesting depth for Unicode character class sets. -Currently fixed. Warning: the interpreter relies on this so it can encode -the operand stack in a uint32_t. A nesting limit of 15 implies (15*2+1)=31 -stack operands required, due to the fact that we have two (and only two) -levels of operator precedence. In the UTS#18 syntax, you can write 'x&&y[z]' -and in Perl syntax you can write '(?[ x - y & (z) ])', both of which imply -pushing the match results for x & y to the stack. */ - -#define ECLASS_NEST_LIMIT 15 - /* Offsets for the bitmap tables in the cbits set of tables. Each table contains a set of bits for a class map. Some classes are built by combining these tables. */ @@ -625,13 +609,6 @@ total length of the tables. */ #define ctypes_offset (cbits_offset + cbit_length) /* Character types */ #define TABLES_LENGTH (ctypes_offset + 256) -/* Private flags used in compile_context.optimization_flags */ - -#define PCRE2_OPTIM_AUTO_POSSESS 0x00000001u -#define PCRE2_OPTIM_DOTSTAR_ANCHOR 0x00000002u -#define PCRE2_OPTIM_START_OPTIMIZE 0x00000004u - -#define PCRE2_OPTIMIZATION_ALL 0x00000007u /* -------------------- Character and string names ------------------------ */ @@ -938,7 +915,6 @@ a positive value. */ #define STRING_naplb0 "naplb\0" #define STRING_nla0 "nla\0" #define STRING_nlb0 "nlb\0" -#define STRING_scs0 "scs\0" #define STRING_sr0 "sr\0" #define STRING_asr0 "asr\0" #define STRING_positive_lookahead0 "positive_lookahead\0" @@ -949,7 +925,6 @@ a positive value. */ #define STRING_negative_lookbehind0 "negative_lookbehind\0" #define STRING_script_run0 "script_run\0" #define STRING_atomic_script_run "atomic_script_run" -#define STRING_scan_substring0 "scan_substring\0" #define STRING_alpha0 "alpha\0" #define STRING_lower0 "lower\0" @@ -990,8 +965,6 @@ a positive value. */ #define STRING_NO_START_OPT_RIGHTPAR "NO_START_OPT)" #define STRING_NOTEMPTY_RIGHTPAR "NOTEMPTY)" #define STRING_NOTEMPTY_ATSTART_RIGHTPAR "NOTEMPTY_ATSTART)" -#define STRING_CASELESS_RESTRICT_RIGHTPAR "CASELESS_RESTRICT)" -#define STRING_TURKISH_CASING_RIGHTPAR "TURKISH_CASING)" #define STRING_LIMIT_HEAP_EQ "LIMIT_HEAP=" #define STRING_LIMIT_MATCH_EQ "LIMIT_MATCH=" #define STRING_LIMIT_DEPTH_EQ "LIMIT_DEPTH=" @@ -1243,7 +1216,6 @@ only. */ #define STRING_naplb0 STR_n STR_a STR_p STR_l STR_b "\0" #define STRING_nla0 STR_n STR_l STR_a "\0" #define STRING_nlb0 STR_n STR_l STR_b "\0" -#define STRING_scs0 STR_s STR_c STR_s "\0" #define STRING_sr0 STR_s STR_r "\0" #define STRING_asr0 STR_a STR_s STR_r "\0" #define STRING_positive_lookahead0 STR_p STR_o STR_s STR_i STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_a STR_h STR_e STR_a STR_d "\0" @@ -1254,7 +1226,6 @@ only. */ #define STRING_negative_lookbehind0 STR_n STR_e STR_g STR_a STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_b STR_e STR_h STR_i STR_n STR_d "\0" #define STRING_script_run0 STR_s STR_c STR_r STR_i STR_p STR_t STR_UNDERSCORE STR_r STR_u STR_n "\0" #define STRING_atomic_script_run STR_a STR_t STR_o STR_m STR_i STR_c STR_UNDERSCORE STR_s STR_c STR_r STR_i STR_p STR_t STR_UNDERSCORE STR_r STR_u STR_n -#define STRING_scan_substring0 STR_s STR_c STR_a STR_n STR_UNDERSCORE STR_s STR_u STR_b STR_s STR_t STR_r STR_i STR_n STR_g "\0" #define STRING_alpha0 STR_a STR_l STR_p STR_h STR_a "\0" #define STRING_lower0 STR_l STR_o STR_w STR_e STR_r "\0" @@ -1295,8 +1266,6 @@ only. */ #define STRING_NO_START_OPT_RIGHTPAR STR_N STR_O STR_UNDERSCORE STR_S STR_T STR_A STR_R STR_T STR_UNDERSCORE STR_O STR_P STR_T STR_RIGHT_PARENTHESIS #define STRING_NOTEMPTY_RIGHTPAR STR_N STR_O STR_T STR_E STR_M STR_P STR_T STR_Y STR_RIGHT_PARENTHESIS #define STRING_NOTEMPTY_ATSTART_RIGHTPAR STR_N STR_O STR_T STR_E STR_M STR_P STR_T STR_Y STR_UNDERSCORE STR_A STR_T STR_S STR_T STR_A STR_R STR_T STR_RIGHT_PARENTHESIS -#define STRING_CASELESS_RESTRICT_RIGHTPAR STR_C STR_A STR_S STR_E STR_L STR_E STR_S STR_S STR_UNDERSCORE STR_R STR_E STR_S STR_T STR_R STR_I STR_C STR_T STR_RIGHT_PARENTHESIS -#define STRING_TURKISH_CASING_RIGHTPAR STR_T STR_U STR_R STR_K STR_I STR_S STR_H STR_UNDERSCORE STR_C STR_A STR_S STR_I STR_N STR_G STR_RIGHT_PARENTHESIS #define STRING_LIMIT_HEAP_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_H STR_E STR_A STR_P STR_EQUALS_SIGN #define STRING_LIMIT_MATCH_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_M STR_A STR_T STR_C STR_H STR_EQUALS_SIGN #define STRING_LIMIT_DEPTH_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_D STR_E STR_P STR_T STR_H STR_EQUALS_SIGN @@ -1321,22 +1290,21 @@ only. */ changed, the autopossessifying table in pcre2_auto_possess.c must be updated to match. */ -#define PT_LAMP 0 /* L& - the union of Lu, Ll, Lt */ -#define PT_GC 1 /* Specified general characteristic (e.g. L) */ -#define PT_PC 2 /* Specified particular characteristic (e.g. Lu) */ -#define PT_SC 3 /* Script only (e.g. Han) */ -#define PT_SCX 4 /* Script extensions (includes SC) */ -#define PT_ALNUM 5 /* Alphanumeric - the union of L and N */ -#define PT_SPACE 6 /* Perl space - general category Z plus 9,10,12,13 */ -#define PT_PXSPACE 7 /* POSIX space - Z plus 9,10,11,12,13 */ -#define PT_WORD 8 /* Word - L, N, Mn, or Pc */ -#define PT_CLIST 9 /* Pseudo-property: match character list */ -#define PT_UCNC 10 /* Universal Character nameable character */ -#define PT_BIDICL 11 /* Specified bidi class */ -#define PT_BOOL 12 /* Boolean property */ -#define PT_ANY 13 /* Must be the last entry! - Any property - matches all chars */ -#define PT_TABSIZE PT_ANY /* Size of square table for autopossessify tests */ +#define PT_ANY 0 /* Any property - matches all chars */ +#define PT_LAMP 1 /* L& - the union of Lu, Ll, Lt */ +#define PT_GC 2 /* Specified general characteristic (e.g. L) */ +#define PT_PC 3 /* Specified particular characteristic (e.g. Lu) */ +#define PT_SC 4 /* Script only (e.g. Han) */ +#define PT_SCX 5 /* Script extensions (includes SC) */ +#define PT_ALNUM 6 /* Alphanumeric - the union of L and N */ +#define PT_SPACE 7 /* Perl space - general category Z plus 9,10,12,13 */ +#define PT_PXSPACE 8 /* POSIX space - Z plus 9,10,11,12,13 */ +#define PT_WORD 9 /* Word - L, N, Mn, or Pc */ +#define PT_CLIST 10 /* Pseudo-property: match character list */ +#define PT_UCNC 11 /* Universal Character nameable character */ +#define PT_BIDICL 12 /* Specified bidi class */ +#define PT_BOOL 13 /* Boolean property */ +#define PT_TABSIZE 14 /* Size of square table for autopossessify tests */ /* The following special properties are used only in XCLASS items, when POSIX classes are specified and PCRE2_UCP is set - in other words, for Unicode @@ -1366,94 +1334,6 @@ contain characters with values greater than 255. */ #define XCL_RANGE 2 /* A range (two multibyte chars) follows */ #define XCL_PROP 3 /* Unicode property (2-byte property code follows) */ #define XCL_NOTPROP 4 /* Unicode inverted property (ditto) */ -/* This value represents the beginning of character lists. The value -is 16 bit long, and stored as a high and low byte pair in 8 bit mode. -The lower 12 bit contains information about character lists (see later). */ -#define XCL_LIST (sizeof(PCRE2_UCHAR) == 1 ? 0x10 : 0x1000) - -/* When a character class contains many characters/ranges, -they are stored in character lists. There are four character -lists which contain characters/ranges within a given range. - -The name, character range and item size for each list: -Low16 [0x100 - 0x7fff] 16 bit items -High16 [0x8000 - 0xffff] 16 bit items -Low32 [0x10000 - 0x7fffffff] 32 bit items -High32 [0x80000000 - 0xffffffff] 32 bit items - -The Low32 character list is used only when utf encoding or 32 bit -character width is enabled, and the High32 character is used only -when 32 bit character width is enabled. - -Each character list contain items. The lowest bit represents that -an item is the beginning of a range (bit is cleared), or not (bit -is set). The other bits represent the character shifted left by -one, so its highest bit is discarded. Due to the layout of character -lists, the highest bit of a character is always known: - -Low16 and Low32: the highest bit is always zero -High16 and High32: the highest bit is always one - -The items are ordered in increasing order, so binary search can be -used to find the lower bound of an input character. The lower bound -is the highest item, which value is less or equal than the input -character. If the lower bit of the item is cleard, or the character -stored in the item equals to the input character, the input -character is in the character list. */ - -/* Character list constants. */ -#define XCL_CHAR_LIST_LOW_16_START 0x100 -#define XCL_CHAR_LIST_LOW_16_END 0x7fff -#define XCL_CHAR_LIST_LOW_16_ADD 0x0 - -#define XCL_CHAR_LIST_HIGH_16_START 0x8000 -#define XCL_CHAR_LIST_HIGH_16_END 0xffff -#define XCL_CHAR_LIST_HIGH_16_ADD 0x8000 - -#define XCL_CHAR_LIST_LOW_32_START 0x10000 -#define XCL_CHAR_LIST_LOW_32_END 0x7fffffff -#define XCL_CHAR_LIST_LOW_32_ADD 0x0 - -#define XCL_CHAR_LIST_HIGH_32_START 0x80000000 -#define XCL_CHAR_LIST_HIGH_32_END 0xffffffff -#define XCL_CHAR_LIST_HIGH_32_ADD 0x80000000 - -/* Mask for getting the descriptors of character list ranges. -Each descriptor has XCL_TYPE_BIT_LEN bits, and can be processed -by XCL_BEGIN_WITH_RANGE and XCL_ITEM_COUNT_MASK macros. */ -#define XCL_TYPE_MASK 0xfff -#define XCL_TYPE_BIT_LEN 3 -/* If this bit is set, the first item of the character list is the -end of a range, which started before the starting character of the -character list. */ -#define XCL_BEGIN_WITH_RANGE 0x4 -/* Number of items in the character list: 0, 1, or 2. The value 3 -represents that the item count is stored at the begining of the -character list. The item count has the same width as the items -in the character list (e.g. 16 bit for Low16 and High16 lists). */ -#define XCL_ITEM_COUNT_MASK 0x3 -/* Shift and flag for constructing character list items. The XCL_CHAR_END -is set, when the item is not the beginning of a range. The XCL_CHAR_SHIFT -can be used to encode / decode the character value stored in an item. */ -#define XCL_CHAR_END 0x1 -#define XCL_CHAR_SHIFT 1 - -/* Flag bits for an extended class (OP_ECLASS), which is used for complex -character matches such as [\p{Greek} && \p{Ll}]. */ - -#define ECL_MAP 0x01 /* Flag: a 32-byte map is present */ - -/* Type tags for the items stored in an extended class (OP_ECLASS). These items -follow the OP_ECLASS's flag char and bitmap, and represent a Reverse Polish -Notation list of operands and operators manipulating a stack of bits. */ - -#define ECL_AND 1 /* Pop two from the stack, AND, and push result. */ -#define ECL_OR 2 /* Pop two from the stack, OR, and push result. */ -#define ECL_XOR 3 /* Pop two from the stack, XOR, and push result. */ -#define ECL_NOT 4 /* Pop one from the stack, NOT, and push result. */ -#define ECL_XCLASS 5 /* XCLASS nested within ECLASS; match and push result. */ -#define ECL_ANY 6 /* Temporary, only used during compilation. */ -#define ECL_NONE 7 /* Temporary, only used during compilation. */ /* These are escaped items that aren't just an encoding of a particular data value such as \n. They must have non-zero values, as check_escape() returns 0 @@ -1675,105 +1555,102 @@ enum { character > 255 is encountered. */ OP_XCLASS, /* 112 Extended class for handling > 255 chars within the class. This does both positive and negative. */ - OP_ECLASS, /* 113 Really-extended class, for handling logical - expressions computed over characters. */ - OP_REF, /* 114 Match a back reference, casefully */ - OP_REFI, /* 115 Match a back reference, caselessly */ - OP_DNREF, /* 116 Match a duplicate name backref, casefully */ - OP_DNREFI, /* 117 Match a duplicate name backref, caselessly */ - OP_RECURSE, /* 118 Match a numbered subpattern (possibly recursive) */ - OP_CALLOUT, /* 119 Call out to external function if provided */ - OP_CALLOUT_STR, /* 120 Call out with string argument */ - - OP_ALT, /* 121 Start of alternation */ - OP_KET, /* 122 End of group that doesn't have an unbounded repeat */ - OP_KETRMAX, /* 123 These two must remain together and in this */ - OP_KETRMIN, /* 124 order. They are for groups the repeat for ever. */ - OP_KETRPOS, /* 125 Possessive unlimited repeat. */ + OP_REF, /* 113 Match a back reference, casefully */ + OP_REFI, /* 114 Match a back reference, caselessly */ + OP_DNREF, /* 115 Match a duplicate name backref, casefully */ + OP_DNREFI, /* 116 Match a duplicate name backref, caselessly */ + OP_RECURSE, /* 117 Match a numbered subpattern (possibly recursive) */ + OP_CALLOUT, /* 118 Call out to external function if provided */ + OP_CALLOUT_STR, /* 119 Call out with string argument */ + + OP_ALT, /* 120 Start of alternation */ + OP_KET, /* 121 End of group that doesn't have an unbounded repeat */ + OP_KETRMAX, /* 122 These two must remain together and in this */ + OP_KETRMIN, /* 123 order. They are for groups the repeat for ever. */ + OP_KETRPOS, /* 124 Possessive unlimited repeat. */ /* The assertions must come before BRA, CBRA, ONCE, and COND. */ - OP_REVERSE, /* 126 Move pointer back - used in lookbehind assertions */ - OP_VREVERSE, /* 127 Move pointer back - variable */ - OP_ASSERT, /* 128 Positive lookahead */ - OP_ASSERT_NOT, /* 129 Negative lookahead */ - OP_ASSERTBACK, /* 130 Positive lookbehind */ - OP_ASSERTBACK_NOT, /* 131 Negative lookbehind */ - OP_ASSERT_NA, /* 132 Positive non-atomic lookahead */ - OP_ASSERTBACK_NA, /* 133 Positive non-atomic lookbehind */ - OP_ASSERT_SCS, /* 134 Scan substring */ + OP_REVERSE, /* 125 Move pointer back - used in lookbehind assertions */ + OP_VREVERSE, /* 126 Move pointer back - variable */ + OP_ASSERT, /* 127 Positive lookahead */ + OP_ASSERT_NOT, /* 128 Negative lookahead */ + OP_ASSERTBACK, /* 129 Positive lookbehind */ + OP_ASSERTBACK_NOT, /* 130 Negative lookbehind */ + OP_ASSERT_NA, /* 131 Positive non-atomic lookahead */ + OP_ASSERTBACK_NA, /* 132 Positive non-atomic lookbehind */ /* ONCE, SCRIPT_RUN, BRA, BRAPOS, CBRA, CBRAPOS, and COND must come immediately after the assertions, with ONCE first, as there's a test for >= ONCE for a subpattern that isn't an assertion. The POS versions must immediately follow the non-POS versions in each case. */ - OP_ONCE, /* 135 Atomic group, contains captures */ - OP_SCRIPT_RUN, /* 136 Non-capture, but check characters' scripts */ - OP_BRA, /* 137 Start of non-capturing bracket */ - OP_BRAPOS, /* 138 Ditto, with unlimited, possessive repeat */ - OP_CBRA, /* 139 Start of capturing bracket */ - OP_CBRAPOS, /* 140 Ditto, with unlimited, possessive repeat */ - OP_COND, /* 141 Conditional group */ + OP_ONCE, /* 133 Atomic group, contains captures */ + OP_SCRIPT_RUN, /* 134 Non-capture, but check characters' scripts */ + OP_BRA, /* 135 Start of non-capturing bracket */ + OP_BRAPOS, /* 136 Ditto, with unlimited, possessive repeat */ + OP_CBRA, /* 137 Start of capturing bracket */ + OP_CBRAPOS, /* 138 Ditto, with unlimited, possessive repeat */ + OP_COND, /* 139 Conditional group */ /* These five must follow the previous five, in the same order. There's a check for >= SBRA to distinguish the two sets. */ - OP_SBRA, /* 142 Start of non-capturing bracket, check empty */ - OP_SBRAPOS, /* 143 Ditto, with unlimited, possessive repeat */ - OP_SCBRA, /* 144 Start of capturing bracket, check empty */ - OP_SCBRAPOS, /* 145 Ditto, with unlimited, possessive repeat */ - OP_SCOND, /* 146 Conditional group, check empty */ + OP_SBRA, /* 140 Start of non-capturing bracket, check empty */ + OP_SBRAPOS, /* 141 Ditto, with unlimited, possessive repeat */ + OP_SCBRA, /* 142 Start of capturing bracket, check empty */ + OP_SCBRAPOS, /* 143 Ditto, with unlimited, possessive repeat */ + OP_SCOND, /* 144 Conditional group, check empty */ /* The next two pairs must (respectively) be kept together. */ - OP_CREF, /* 147 Used to hold a capture number as condition */ - OP_DNCREF, /* 148 Used to point to duplicate names as a condition */ - OP_RREF, /* 149 Used to hold a recursion number as condition */ - OP_DNRREF, /* 150 Used to point to duplicate names as a condition */ - OP_FALSE, /* 151 Always false (used by DEFINE and VERSION) */ - OP_TRUE, /* 152 Always true (used by VERSION) */ + OP_CREF, /* 145 Used to hold a capture number as condition */ + OP_DNCREF, /* 146 Used to point to duplicate names as a condition */ + OP_RREF, /* 147 Used to hold a recursion number as condition */ + OP_DNRREF, /* 148 Used to point to duplicate names as a condition */ + OP_FALSE, /* 149 Always false (used by DEFINE and VERSION) */ + OP_TRUE, /* 150 Always true (used by VERSION) */ - OP_BRAZERO, /* 153 These two must remain together and in this */ - OP_BRAMINZERO, /* 154 order. */ - OP_BRAPOSZERO, /* 155 */ + OP_BRAZERO, /* 151 These two must remain together and in this */ + OP_BRAMINZERO, /* 152 order. */ + OP_BRAPOSZERO, /* 153 */ /* These are backtracking control verbs */ - OP_MARK, /* 156 always has an argument */ - OP_PRUNE, /* 157 */ - OP_PRUNE_ARG, /* 158 same, but with argument */ - OP_SKIP, /* 159 */ - OP_SKIP_ARG, /* 160 same, but with argument */ - OP_THEN, /* 161 */ - OP_THEN_ARG, /* 162 same, but with argument */ - OP_COMMIT, /* 163 */ - OP_COMMIT_ARG, /* 164 same, but with argument */ + OP_MARK, /* 154 always has an argument */ + OP_PRUNE, /* 155 */ + OP_PRUNE_ARG, /* 156 same, but with argument */ + OP_SKIP, /* 157 */ + OP_SKIP_ARG, /* 158 same, but with argument */ + OP_THEN, /* 159 */ + OP_THEN_ARG, /* 160 same, but with argument */ + OP_COMMIT, /* 161 */ + OP_COMMIT_ARG, /* 162 same, but with argument */ /* These are forced failure and success verbs. FAIL and ACCEPT do accept an argument, but these cases can be compiled as, for example, (*MARK:X)(*FAIL) without the need for a special opcode. */ - OP_FAIL, /* 165 */ - OP_ACCEPT, /* 166 */ - OP_ASSERT_ACCEPT, /* 167 Used inside assertions */ - OP_CLOSE, /* 168 Used before OP_ACCEPT to close open captures */ + OP_FAIL, /* 163 */ + OP_ACCEPT, /* 164 */ + OP_ASSERT_ACCEPT, /* 165 Used inside assertions */ + OP_CLOSE, /* 166 Used before OP_ACCEPT to close open captures */ /* This is used to skip a subpattern with a {0} quantifier */ - OP_SKIPZERO, /* 169 */ + OP_SKIPZERO, /* 167 */ /* This is used to identify a DEFINE group during compilation so that it can be checked for having only one branch. It is changed to OP_FALSE before compilation finishes. */ - OP_DEFINE, /* 170 */ + OP_DEFINE, /* 168 */ /* These opcodes replace their normal counterparts in UCP mode when PCRE2_EXTRA_ASCII_BSW is not set. */ - OP_NOT_UCP_WORD_BOUNDARY, /* 171 */ - OP_UCP_WORD_BOUNDARY, /* 172 */ + OP_NOT_UCP_WORD_BOUNDARY, /* 169 */ + OP_UCP_WORD_BOUNDARY, /* 170 */ /* This is not an opcode, but is used to check that tables indexed by opcode are the correct length, in order to catch updating errors - there have been @@ -1816,21 +1693,19 @@ some cases doesn't actually use these names at all). */ "*+","++", "?+", "{", \ "*", "*?", "+", "+?", "?", "??", "{", "{", \ "*+","++", "?+", "{", \ - "class", "nclass", "xclass", "eclass", \ - "Ref", "Refi", "DnRef", "DnRefi", \ + "class", "nclass", "xclass", "Ref", "Refi", "DnRef", "DnRefi", \ "Recurse", "Callout", "CalloutStr", \ "Alt", "Ket", "KetRmax", "KetRmin", "KetRpos", \ "Reverse", "VReverse", "Assert", "Assert not", \ "Assert back", "Assert back not", \ "Non-atomic assert", "Non-atomic assert back", \ - "Scan substring", \ "Once", \ "Script run", \ "Bra", "BraPos", "CBra", "CBraPos", \ "Cond", \ "SBra", "SBraPos", "SCBra", "SCBraPos", \ "SCond", \ - "Capture ref", "Capture dnref", "Cond rec", "Cond dnrec", \ + "Cond ref", "Cond dnref", "Cond rec", "Cond dnrec", \ "Cond false", "Cond true", \ "Brazero", "Braminzero", "Braposzero", \ "*MARK", "*PRUNE", "*PRUNE", "*SKIP", "*SKIP", \ @@ -1891,11 +1766,10 @@ in UTF-8 mode. The code that uses this table must know about such things. */ 1+(32/sizeof(PCRE2_UCHAR)), /* CLASS */ \ 1+(32/sizeof(PCRE2_UCHAR)), /* NCLASS */ \ 0, /* XCLASS - variable length */ \ - 0, /* ECLASS - variable length */ \ 1+IMM2_SIZE, /* REF */ \ - 1+IMM2_SIZE+1, /* REFI */ \ + 1+IMM2_SIZE, /* REFI */ \ 1+2*IMM2_SIZE, /* DNREF */ \ - 1+2*IMM2_SIZE+1, /* DNREFI */ \ + 1+2*IMM2_SIZE, /* DNREFI */ \ 1+LINK_SIZE, /* RECURSE */ \ 1+2*LINK_SIZE+1, /* CALLOUT */ \ 0, /* CALLOUT_STR - variable length */ \ @@ -1912,7 +1786,6 @@ in UTF-8 mode. The code that uses this table must know about such things. */ 1+LINK_SIZE, /* Assert behind not */ \ 1+LINK_SIZE, /* NA Assert */ \ 1+LINK_SIZE, /* NA Assert behind */ \ - 1+LINK_SIZE, /* Scan substring */ \ 1+LINK_SIZE, /* ONCE */ \ 1+LINK_SIZE, /* SCRIPT_RUN */ \ 1+LINK_SIZE, /* BRA */ \ @@ -1942,11 +1815,6 @@ in UTF-8 mode. The code that uses this table must know about such things. */ #define RREF_ANY 0xffff -/* Constants used by OP_REFI and OP_DNREFI to control matching behaviour. */ - -#define REFI_FLAG_CASELESS_RESTRICT 0x1 -#define REFI_FLAG_TURKISH_CASING 0x2 - /* ---------- Private structures that are mode-independent. ---------- */ @@ -2022,14 +1890,6 @@ typedef struct { #define UCD_SCRIPTX(ch) UCD_SCRIPTX_PROP(GET_UCD(ch)) #define UCD_BPROPS(ch) UCD_BPROPS_PROP(GET_UCD(ch)) #define UCD_BIDICLASS(ch) UCD_BIDICLASS_PROP(GET_UCD(ch)) -#define UCD_ANY_I(ch) \ - /* match any of the four characters 'i', 'I', U+0130, U+0131 */ \ - (((uint32_t)(ch) | 0x20u) == 0x69u || ((uint32_t)(ch) | 1u) == 0x0131u) -#define UCD_DOTTED_I(ch) \ - ((uint32_t)(ch) == 0x69u || (uint32_t)(ch) == 0x0130u) -#define UCD_FOLD_I_TURKISH(ch) \ - ((uint32_t)(ch) == 0x0130u ? 0x69u : \ - (uint32_t)(ch) == 0x49u ? 0x0131u : (uint32_t)(ch)) /* The "scriptx" and bprops fields contain offsets into vectors of 32-bit words that form a bitmap representing a list of scripts or boolean properties. These @@ -2095,9 +1955,6 @@ extern const uint8_t PRIV(utf8_table4)[]; #define _pcre2_vspace_list PCRE2_SUFFIX(_pcre2_vspace_list_) #define _pcre2_ucd_boolprop_sets PCRE2_SUFFIX(_pcre2_ucd_boolprop_sets_) #define _pcre2_ucd_caseless_sets PCRE2_SUFFIX(_pcre2_ucd_caseless_sets_) -#define _pcre2_ucd_turkish_dotted_i_caseset PCRE2_SUFFIX(_pcre2_ucd_turkish_dotted_i_caseset_) -#define _pcre2_ucd_nocase_ranges PCRE2_SUFFIX(_pcre2_ucd_nocase_ranges_) -#define _pcre2_ucd_nocase_ranges_size PCRE2_SUFFIX(_pcre2_ucd_nocase_ranges_size_) #define _pcre2_ucd_digit_sets PCRE2_SUFFIX(_pcre2_ucd_digit_sets_) #define _pcre2_ucd_script_sets PCRE2_SUFFIX(_pcre2_ucd_script_sets_) #define _pcre2_ucd_records PCRE2_SUFFIX(_pcre2_ucd_records_) @@ -2114,17 +1971,14 @@ extern const uint8_t PRIV(utf8_table4)[]; extern const uint8_t PRIV(OP_lengths)[]; extern const uint32_t PRIV(callout_end_delims)[]; extern const uint32_t PRIV(callout_start_delims)[]; -extern pcre2_compile_context PRIV(default_compile_context); -extern pcre2_convert_context PRIV(default_convert_context); -extern pcre2_match_context PRIV(default_match_context); +extern const pcre2_compile_context PRIV(default_compile_context); +extern const pcre2_convert_context PRIV(default_convert_context); +extern const pcre2_match_context PRIV(default_match_context); extern const uint8_t PRIV(default_tables)[]; extern const uint32_t PRIV(hspace_list)[]; extern const uint32_t PRIV(vspace_list)[]; extern const uint32_t PRIV(ucd_boolprop_sets)[]; extern const uint32_t PRIV(ucd_caseless_sets)[]; -extern const uint32_t PRIV(ucd_turkish_dotted_i_caseset); -extern const uint32_t PRIV(ucd_nocase_ranges)[]; -extern const uint32_t PRIV(ucd_nocase_ranges_size); extern const uint32_t PRIV(ucd_digit_sets)[]; extern const uint32_t PRIV(ucd_script_sets)[]; extern const ucd_record PRIV(ucd_records)[]; @@ -2185,12 +2039,11 @@ is available. */ #define _pcre2_valid_utf PCRE2_SUFFIX(_pcre2_valid_utf_) #define _pcre2_was_newline PCRE2_SUFFIX(_pcre2_was_newline_) #define _pcre2_xclass PCRE2_SUFFIX(_pcre2_xclass_) -#define _pcre2_eclass PCRE2_SUFFIX(_pcre2_eclass_) extern int _pcre2_auto_possessify(PCRE2_UCHAR *, const compile_block *); extern int _pcre2_check_escape(PCRE2_SPTR *, PCRE2_SPTR, uint32_t *, - int *, uint32_t, uint32_t, uint32_t, BOOL, compile_block *); + int *, uint32_t, uint32_t, BOOL, compile_block *); extern PCRE2_SPTR _pcre2_extuni(uint32_t, PCRE2_SPTR, PCRE2_SPTR, PCRE2_SPTR, BOOL, int *); extern PCRE2_SPTR _pcre2_find_bracket(PCRE2_SPTR, BOOL, int); @@ -2213,9 +2066,7 @@ extern int _pcre2_study(pcre2_real_code *); extern int _pcre2_valid_utf(PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE *); extern BOOL _pcre2_was_newline(PCRE2_SPTR, uint32_t, PCRE2_SPTR, uint32_t *, BOOL); -extern BOOL _pcre2_xclass(uint32_t, PCRE2_SPTR, const uint8_t *, BOOL); -extern BOOL _pcre2_eclass(uint32_t, PCRE2_SPTR, PCRE2_SPTR, - const uint8_t *, BOOL); +extern BOOL _pcre2_xclass(uint32_t, PCRE2_SPTR, BOOL); /* This function is needed only when memmove() is not available. */ @@ -2228,8 +2079,6 @@ extern void * _pcre2_memmove(void *, const void *, size_t); extern BOOL PRIV(ckd_smul)(PCRE2_SIZE *, int, int); -#include "pcre2_util.h" - #endif /* PCRE2_INTERNAL_H_IDEMPOTENT_GUARD */ /* End of pcre2_internal.h */ diff --git a/ext/pcre/pcre2lib/pcre2_intmodedep.h b/ext/pcre/pcre2lib/pcre2_intmodedep.h index 6b858139f577c..9bd9e694a496e 100644 --- a/ext/pcre/pcre2lib/pcre2_intmodedep.h +++ b/ext/pcre/pcre2lib/pcre2_intmodedep.h @@ -47,7 +47,7 @@ to have access to the hidden structures at all supported widths. Some of the mode-dependent macros are required at different widths for different parts of the pcre2test code (in particular, the included -pcre2_printint.c file). We undefine them here so that they can be re-defined for +pcre_printint.c file). We undefine them here so that they can be re-defined for multiple inclusions. Not all of these are used in pcre2test, but it's easier just to undefine them all. */ @@ -435,7 +435,7 @@ UTF-16 mode. */ c = *eptr; \ if ((c & 0xfc00u) == 0xd800u) GETUTF16LEN(c, eptr, len); -/* Get the next UTF-16 character, testing for UTF-16 mode, not advancing the +/* Get the next UTF-816character, testing for UTF-16 mode, not advancing the pointer, incrementing length if there is a low surrogate. This is called when we do not know if we are in UTF-16 mode. */ @@ -556,11 +556,6 @@ code that uses them is simpler because it assumes this. */ /* The real general context structure. At present it holds only data for custom memory control. */ -/* WARNING: if this is ever changed, code in pcre2_substitute.c will have to be -changed because it builds a general context "by hand" in order to avoid the -malloc() call in pcre2_general_context)_create(). There is also code in -pcre2_match.c that makes the same assumption. */ - typedef struct pcre2_real_general_context { pcre2_memctl memctl; } pcre2_real_general_context; @@ -579,7 +574,6 @@ typedef struct pcre2_real_compile_context { uint32_t parens_nest_limit; uint32_t extra_options; uint32_t max_varlookbehind; - uint32_t optimization_flags; } pcre2_real_compile_context; /* The real match context structure. */ @@ -590,13 +584,10 @@ typedef struct pcre2_real_match_context { pcre2_jit_callback jit_callback; void *jit_callback_data; #endif - int (*callout)(pcre2_callout_block *, void *); - void *callout_data; - int (*substitute_callout)(pcre2_substitute_callout_block *, void *); - void *substitute_callout_data; - PCRE2_SIZE (*substitute_case_callout)(PCRE2_SPTR, PCRE2_SIZE, PCRE2_UCHAR *, - PCRE2_SIZE, int, void *); - void *substitute_case_callout_data; + int (*callout)(pcre2_callout_block *, void *); + void *callout_data; + int (*substitute_callout)(pcre2_substitute_callout_block *, void *); + void *substitute_callout_data; PCRE2_SIZE offset_limit; uint32_t heap_limit; uint32_t match_limit; @@ -632,7 +623,6 @@ typedef struct pcre2_real_code { void *executable_jit; /* Pointer to JIT code */ uint8_t start_bitmap[32]; /* Bitmap for starting code unit < 256 */ CODE_BLOCKSIZE_TYPE blocksize; /* Total (bytes) that was malloc-ed */ - CODE_BLOCKSIZE_TYPE code_start; /* Byte code start offset */ uint32_t magic_number; /* Paranoid and endianness check */ uint32_t compile_options; /* Options passed to pcre2_compile() */ uint32_t overall_options; /* Options after processing the pattern */ @@ -651,7 +641,6 @@ typedef struct pcre2_real_code { uint16_t top_backref; /* Highest numbered back reference */ uint16_t name_entry_size; /* Size (code units) of table entries */ uint16_t name_count; /* Number of name entries in the table */ - uint32_t optimization_flags; /* Optimizations enabled at compile time */ } pcre2_real_code; /* The real match data structure. Define ovector as large as it can ever @@ -727,23 +716,6 @@ typedef struct named_group { uint16_t isdup; /* TRUE if a duplicate */ } named_group; -/* Structure for caching sorted ranges. This improves the performance -of translating META code to byte code. */ - -typedef struct class_ranges { - struct class_ranges *next; /* Next class ranges */ - size_t char_lists_size; /* Total size of encoded char lists */ - size_t char_lists_start; /* Start offset of encoded char lists */ - uint16_t range_list_size; /* Size of ranges array */ - uint16_t char_lists_types; /* The XCL_LIST header of char lists */ - /* Followed by the list of ranges (start/end pairs) */ -} class_ranges; - -typedef union class_bits_storage { - uint8_t classbits[32]; - uint32_t classwords[8]; -} class_bits_storage; - /* Structure for passing "static" information around between the functions doing the compiling, so that they are thread-safe. */ @@ -753,15 +725,14 @@ typedef struct compile_block { const uint8_t *fcc; /* Points to case-flipping table */ const uint8_t *cbits; /* Points to character type table */ const uint8_t *ctypes; /* Points to table of type maps */ - PCRE2_UCHAR *start_workspace; /* The start of working space */ - PCRE2_UCHAR *start_code; /* The start of the compiled code */ + PCRE2_SPTR start_workspace; /* The start of working space */ + PCRE2_SPTR start_code; /* The start of the compiled code */ PCRE2_SPTR start_pattern; /* The start of the pattern */ PCRE2_SPTR end_pattern; /* The end of the pattern */ PCRE2_UCHAR *name_table; /* The name/number table */ PCRE2_SIZE workspace_size; /* Size of workspace */ PCRE2_SIZE small_ref_offset[10]; /* Offsets for \1 to \9 */ PCRE2_SIZE erroroffset; /* Offset of error in pattern */ - class_bits_storage classbits; /* Temporary store for classbits */ uint16_t names_found; /* Number of entries so far */ uint16_t name_entry_size; /* Size of each entry */ uint16_t parens_depth; /* Depth of nested parentheses */ @@ -779,9 +750,9 @@ typedef struct compile_block { uint32_t backref_map; /* Bitmap of low back refs */ uint32_t nltype; /* Newline type */ uint32_t nllen; /* Newline string length */ + uint32_t class_range_start; /* Overall class range start */ + uint32_t class_range_end; /* Overall class range end */ PCRE2_UCHAR nl[4]; /* Newline string when fixed length */ - uint8_t class_op_used[ECLASS_NEST_LIMIT]; /* Operation used for - extended classes */ uint32_t req_varyopt; /* "After variable item" flag for reqbyte */ uint32_t max_varlookbehind; /* Limit for variable lookbehinds */ int max_lookbehind; /* Maximum lookbehind encountered (characters) */ @@ -789,11 +760,6 @@ typedef struct compile_block { BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */ BOOL had_recurse; /* Had a pattern recursion or subroutine call */ BOOL dupnames; /* Duplicate names exist */ -#ifdef SUPPORT_WIDE_CHARS - class_ranges *cranges; /* First class range. */ - class_ranges *next_cranges; /* Next class range. */ - size_t char_lists_size; /* Current size of character lists */ -#endif } compile_block; /* Structure for keeping the properties of the in-memory stack used @@ -827,7 +793,7 @@ typedef struct heapframe { to RRMATCH(), but which do not need to be copied to new frames. */ PCRE2_SPTR ecode; /* The current position in the pattern */ - PCRE2_SPTR temp_sptr[2]; /* Used for short-term PCRE2_SPTR values */ + PCRE2_SPTR temp_sptr[2]; /* Used for short-term PCRE_SPTR values */ PCRE2_SIZE length; /* Used for character, string, or code lengths */ PCRE2_SIZE back_frame; /* Amount to subtract on RRETURN */ PCRE2_SIZE temp_size; /* Used for short-term PCRE2_SIZE values */ @@ -875,10 +841,11 @@ typedef struct heapframe { PCRE2_SIZE ovector[131072]; /* Must be last in the structure */ } heapframe; -/* Assert that the size of the heapframe structure is a multiple of PCRE2_SIZE. -See various comments above. */ +/* This typedef is a check that the size of the heapframe structure is a +multiple of PCRE2_SIZE. See various comments above. */ -STATIC_ASSERT((sizeof(heapframe) % sizeof(PCRE2_SIZE)) == 0, heapframe_size); +typedef char check_heapframe_size[ + ((sizeof(heapframe) % sizeof(PCRE2_SIZE)) == 0)? (+1):(-1)]; /* Structure for computing the alignment of heapframe. */ diff --git a/ext/pcre/pcre2lib/pcre2_jit_char_inc.h b/ext/pcre/pcre2lib/pcre2_jit_char_inc.h deleted file mode 100644 index 69fe938fc5bc0..0000000000000 --- a/ext/pcre/pcre2lib/pcre2_jit_char_inc.h +++ /dev/null @@ -1,2280 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - This module by Zoltan Herczeg - Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2024 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * 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. - - * Neither the name of the University of Cambridge 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 OWNER 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. ------------------------------------------------------------------------------ -*/ - -/* XClass matching code. */ - -#ifdef SUPPORT_WIDE_CHARS - -#define ECLASS_CHAR_DATA STACK_TOP -#define ECLASS_STACK_DATA STACK_LIMIT - -#define SET_CHAR_OFFSET(value) \ - if ((value) != charoffset) \ - { \ - if ((value) < charoffset) \ - OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(charoffset - (value))); \ - else \ - OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)((value) - charoffset)); \ - } \ - charoffset = (value); - -#define READ_FROM_CHAR_LIST(destination) \ - if (list_ind <= 1) \ - { \ - destination = *(const uint16_t*)next_char; \ - next_char += 2; \ - } \ - else \ - { \ - destination = *(const uint32_t*)next_char; \ - next_char += 4; \ - } - -#define XCLASS_LOCAL_RANGES_SIZE 32 -#define XCLASS_LOCAL_RANGES_LOG2_SIZE 5 - -typedef struct xclass_stack_item { - sljit_u32 first_item; - sljit_u32 last_item; - struct sljit_jump *jump; -} xclass_stack_item; - -typedef struct xclass_ranges { - size_t range_count; - /* Pointer to ranges. A stack area is provided when a small buffer is enough. */ - uint32_t *ranges; - uint32_t local_ranges[XCLASS_LOCAL_RANGES_SIZE * 2]; - /* Stack size must be log2(ranges / 2). */ - xclass_stack_item *stack; - xclass_stack_item local_stack[XCLASS_LOCAL_RANGES_LOG2_SIZE]; -} xclass_ranges; - -static void xclass_compute_ranges(compiler_common *common, PCRE2_SPTR cc, xclass_ranges *ranges) -{ -DEFINE_COMPILER; -size_t range_count = 0, est_range_count; -size_t est_stack_size, tmp; -uint32_t type, list_ind; -uint32_t est_type; -uint32_t char_list_add, range_start, range_end; -const uint8_t *next_char; -const uint8_t *est_next_char; -#if defined SUPPORT_UNICODE && (PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16) -BOOL utf = common->utf; -#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == [8|16] */ - -if (*cc == XCL_SINGLE || *cc == XCL_RANGE) - { - /* Only a few ranges are present. */ - do - { - type = *cc++; - SLJIT_ASSERT(type == XCL_SINGLE || type == XCL_RANGE); - GETCHARINCTEST(range_end, cc); - ranges->ranges[range_count] = range_end; - - if (type == XCL_RANGE) - { - GETCHARINCTEST(range_end, cc); - } - - ranges->ranges[range_count + 1] = range_end; - range_count += 2; - } - while (*cc != XCL_END); - - SLJIT_ASSERT(range_count <= XCLASS_LOCAL_RANGES_SIZE); - ranges->range_count = range_count; - return; - } - -SLJIT_ASSERT(cc[0] >= XCL_LIST); -#if PCRE2_CODE_UNIT_WIDTH == 8 -type = (uint32_t)(cc[0] << 8) | cc[1]; -cc += 2; -#else -type = cc[0]; -cc++; -#endif /* CODE_UNIT_WIDTH */ - -/* Align characters. */ -next_char = (const uint8_t*)common->start - (GET(cc, 0) << 1); -type &= XCL_TYPE_MASK; - -/* Estimate size. */ -est_next_char = next_char; -est_type = type; -est_range_count = 0; -list_ind = 0; - -while (est_type > 0) - { - uint32_t item_count = est_type & XCL_ITEM_COUNT_MASK; - - if (item_count == XCL_ITEM_COUNT_MASK) - { - if (list_ind <= 1) - { - item_count = *(const uint16_t*)est_next_char; - est_next_char += 2; - } - else - { - item_count = *(const uint32_t*)est_next_char; - est_next_char += 4; - } - } - - est_type >>= XCL_TYPE_BIT_LEN; - est_next_char += (size_t)item_count << (list_ind <= 1 ? 1 : 2); - list_ind++; - est_range_count += item_count + 1; - } - -if (est_range_count > XCLASS_LOCAL_RANGES_SIZE) - { - est_stack_size = 0; - tmp = est_range_count - 1; - - /* Compute log2(est_range_count) */ - while (tmp > 0) - { - est_stack_size++; - tmp >>= 1; - } - - ranges->stack = (xclass_stack_item*)SLJIT_MALLOC((sizeof(xclass_stack_item) * est_stack_size) - + ((sizeof(uint32_t) << 1) * (size_t)est_range_count), compiler->allocator_data); - - if (ranges->stack == NULL) - { - sljit_set_compiler_memory_error(compiler); - ranges->ranges = NULL; - return; - } - - ranges->ranges = (uint32_t*)(ranges->stack + est_stack_size); - } - -char_list_add = XCL_CHAR_LIST_LOW_16_ADD; -range_start = ~(uint32_t)0; -list_ind = 0; - -if ((type & XCL_BEGIN_WITH_RANGE) != 0) - range_start = XCL_CHAR_LIST_LOW_16_START; - -while (type > 0) - { - uint32_t item_count = type & XCL_ITEM_COUNT_MASK; - - if (item_count == XCL_ITEM_COUNT_MASK) - { - READ_FROM_CHAR_LIST(item_count); - SLJIT_ASSERT(item_count >= XCL_ITEM_COUNT_MASK); - } - - while (item_count > 0) - { - READ_FROM_CHAR_LIST(range_end); - - if ((range_end & XCL_CHAR_END) != 0) - { - range_end = char_list_add + (range_end >> XCL_CHAR_SHIFT); - - if (range_start == ~(uint32_t)0) - range_start = range_end; - - ranges->ranges[range_count] = range_start; - ranges->ranges[range_count + 1] = range_end; - range_count += 2; - range_start = ~(uint32_t)0; - } - else - range_start = char_list_add + (range_end >> XCL_CHAR_SHIFT); - - item_count--; - } - - list_ind++; - type >>= XCL_TYPE_BIT_LEN; - - if (range_start == ~(uint32_t)0) - { - if ((type & XCL_BEGIN_WITH_RANGE) != 0) - { - if (list_ind == 1) range_start = XCL_CHAR_LIST_HIGH_16_START; -#if PCRE2_CODE_UNIT_WIDTH == 32 - else if (list_ind == 2) range_start = XCL_CHAR_LIST_LOW_32_START; - else range_start = XCL_CHAR_LIST_HIGH_32_START; -#else - else range_start = XCL_CHAR_LIST_LOW_32_START; -#endif - } - } - else if ((type & XCL_BEGIN_WITH_RANGE) == 0) - { - if (list_ind == 1) range_end = XCL_CHAR_LIST_LOW_16_END; - else if (list_ind == 2) range_end = XCL_CHAR_LIST_HIGH_16_END; -#if PCRE2_CODE_UNIT_WIDTH == 32 - else if (list_ind == 3) range_end = XCL_CHAR_LIST_LOW_32_END; - else range_end = XCL_CHAR_LIST_HIGH_32_END; -#else - else range_end = XCL_CHAR_LIST_LOW_32_END; -#endif - - ranges->ranges[range_count] = range_start; - ranges->ranges[range_count + 1] = range_end; - range_count += 2; - range_start = ~(uint32_t)0; - } - - if (list_ind == 1) char_list_add = XCL_CHAR_LIST_HIGH_16_ADD; -#if PCRE2_CODE_UNIT_WIDTH == 32 - else if (list_ind == 2) char_list_add = XCL_CHAR_LIST_LOW_32_ADD; - else char_list_add = XCL_CHAR_LIST_HIGH_32_ADD; -#else - else char_list_add = XCL_CHAR_LIST_LOW_32_ADD; -#endif - } - -SLJIT_ASSERT(range_count > 0 && range_count <= (est_range_count << 1)); -SLJIT_ASSERT(next_char <= (const uint8_t*)common->start); -ranges->range_count = range_count; -} - -static void xclass_check_bitset(compiler_common *common, const sljit_u8 *bitset, jump_list **found, jump_list **backtracks) -{ -DEFINE_COMPILER; -struct sljit_jump *jump; - -jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); -if (!optimize_class(common, bitset, (bitset[31] & 0x80) != 0, TRUE, found)) - { - OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); - OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); - OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)bitset); - OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); - OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, TMP2, 0); - add_jump(compiler, found, JUMP(SLJIT_NOT_ZERO)); - } - -add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); -JUMPHERE(jump); -} - -#if defined SUPPORT_UNICODE && (PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16) - -static void xclass_update_min_max(compiler_common *common, PCRE2_SPTR cc, sljit_u32 *min_ptr, sljit_u32 *max_ptr) -{ -uint32_t type, list_ind, c; -sljit_u32 min = *min_ptr; -sljit_u32 max = *max_ptr; -uint32_t char_list_add; -const uint8_t *next_char; -BOOL utf = TRUE; - -/* This function is pointless without utf 8/16. */ -SLJIT_ASSERT(common->utf); -if (*cc == XCL_SINGLE || *cc == XCL_RANGE) - { - /* Only a few ranges are present. */ - do - { - type = *cc++; - SLJIT_ASSERT(type == XCL_SINGLE || type == XCL_RANGE); - GETCHARINCTEST(c, cc); - - if (c < min) - min = c; - - if (type == XCL_RANGE) - { - GETCHARINCTEST(c, cc); - } - - if (c > max) - max = c; - } - while (*cc != XCL_END); - - SLJIT_ASSERT(min <= MAX_UTF_CODE_POINT && max <= MAX_UTF_CODE_POINT && min <= max); - *min_ptr = min; - *max_ptr = max; - return; - } - -SLJIT_ASSERT(cc[0] >= XCL_LIST); -#if PCRE2_CODE_UNIT_WIDTH == 8 -type = (uint32_t)(cc[0] << 8) | cc[1]; -cc += 2; -#else -type = cc[0]; -cc++; -#endif /* CODE_UNIT_WIDTH */ - -/* Align characters. */ -next_char = (const uint8_t*)common->start - (GET(cc, 0) << 1); -type &= XCL_TYPE_MASK; - -SLJIT_ASSERT(type != 0); - -/* Detect minimum. */ - -/* Skip unused ranges. */ -list_ind = 0; -while ((type & (XCL_BEGIN_WITH_RANGE | XCL_ITEM_COUNT_MASK)) == 0) - { - type >>= XCL_TYPE_BIT_LEN; - list_ind++; - } - -SLJIT_ASSERT(list_ind <= 2); -switch (list_ind) - { - case 0: - char_list_add = XCL_CHAR_LIST_LOW_16_ADD; - c = XCL_CHAR_LIST_LOW_16_START; - break; - - case 1: - char_list_add = XCL_CHAR_LIST_HIGH_16_ADD; - c = XCL_CHAR_LIST_HIGH_16_START; - break; - - default: - char_list_add = XCL_CHAR_LIST_LOW_32_ADD; - c = XCL_CHAR_LIST_LOW_32_START; - break; - } - -if ((type & XCL_BEGIN_WITH_RANGE) != 0) - { - if (c < min) - min = c; - } -else - { - if ((type & XCL_ITEM_COUNT_MASK) == XCL_ITEM_COUNT_MASK) - { - if (list_ind <= 1) - c = *(const uint16_t*)(next_char + 2); - else - c = *(const uint32_t*)(next_char + 4); - } - else - { - if (list_ind <= 1) - c = *(const uint16_t*)next_char; - else - c = *(const uint32_t*)next_char; - } - - c = char_list_add + (c >> XCL_CHAR_SHIFT); - if (c < min) - min = c; - } - -/* Detect maximum. */ - -/* Skip intermediate ranges. */ -while (TRUE) - { - if ((type & XCL_ITEM_COUNT_MASK) == XCL_ITEM_COUNT_MASK) - { - if (list_ind <= 1) - { - c = *(const uint16_t*)next_char; - next_char += (c + 1) << 1; - } - else - { - c = *(const uint32_t*)next_char; - next_char += (c + 1) << 2; - } - } - else - next_char += (type & XCL_ITEM_COUNT_MASK) << (list_ind <= 1 ? 1 : 2); - - if ((type >> XCL_TYPE_BIT_LEN) == 0) - break; - - list_ind++; - type >>= XCL_TYPE_BIT_LEN; - } - -SLJIT_ASSERT(list_ind <= 2 && type != 0); -switch (list_ind) - { - case 0: - char_list_add = XCL_CHAR_LIST_LOW_16_ADD; - c = XCL_CHAR_LIST_LOW_16_END; - break; - - case 1: - char_list_add = XCL_CHAR_LIST_HIGH_16_ADD; - c = XCL_CHAR_LIST_HIGH_16_END; - break; - - default: - char_list_add = XCL_CHAR_LIST_LOW_32_ADD; - c = XCL_CHAR_LIST_LOW_32_END; - break; - } - -if ((type & XCL_ITEM_COUNT_MASK) != 0) - { - /* Type is reused as temporary. */ - if (list_ind <= 1) - type = *(const uint16_t*)(next_char - 2); - else - type = *(const uint32_t*)(next_char - 4); - - if (type & XCL_CHAR_END) - c = char_list_add + (type >> XCL_CHAR_SHIFT); - } - -if (c > max) - max = c; - -SLJIT_ASSERT(min <= MAX_UTF_CODE_POINT && max <= MAX_UTF_CODE_POINT && min <= max); -*min_ptr = min; -*max_ptr = max; -} - -#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == [8|16] */ - -#define XCLASS_IS_ECLASS 0x001 -#ifdef SUPPORT_UNICODE -#define XCLASS_SAVE_CHAR 0x002 -#define XCLASS_HAS_TYPE 0x004 -#define XCLASS_HAS_SCRIPT 0x008 -#define XCLASS_HAS_SCRIPT_EXTENSION 0x010 -#define XCLASS_HAS_BOOL 0x020 -#define XCLASS_HAS_BIDICL 0x040 -#define XCLASS_NEEDS_UCD (XCLASS_HAS_TYPE | XCLASS_HAS_SCRIPT | XCLASS_HAS_SCRIPT_EXTENSION | XCLASS_HAS_BOOL | XCLASS_HAS_BIDICL) -#define XCLASS_SCRIPT_EXTENSION_NOTPROP 0x080 -#define XCLASS_SCRIPT_EXTENSION_RESTORE_RETURN_ADDR 0x100 -#define XCLASS_SCRIPT_EXTENSION_RESTORE_LOCAL0 0x200 -#endif /* SUPPORT_UNICODE */ - -static PCRE2_SPTR compile_char1_matchingpath(compiler_common *common, PCRE2_UCHAR type, PCRE2_SPTR cc, jump_list **backtracks, BOOL check_str_ptr); - -/* TMP3 must be preserved because it is used by compile_iterator_matchingpath. */ -static void compile_xclass_matchingpath(compiler_common *common, PCRE2_SPTR cc, jump_list **backtracks, sljit_u32 status) -{ -DEFINE_COMPILER; -jump_list *found = NULL; -jump_list *check_result = NULL; -jump_list **list = (cc[0] & XCL_NOT) == 0 ? &found : backtracks; -sljit_uw c, charoffset; -sljit_u32 max = READ_CHAR_MAX, min = 0; -struct sljit_jump *jump = NULL; -PCRE2_UCHAR flags; -PCRE2_SPTR ccbegin; -sljit_u32 compares, invertcmp, depth; -sljit_u32 first_item, last_item, mid_item; -sljit_u32 range_start, range_end; -xclass_ranges ranges; -BOOL has_cmov, last_range_set; - -#ifdef SUPPORT_UNICODE -sljit_u32 category_list = 0; -sljit_u32 items; -int typereg = TMP1; -#endif /* SUPPORT_UNICODE */ - -SLJIT_ASSERT(common->locals_size >= SSIZE_OF(sw)); -/* Scanning the necessary info. */ -flags = *cc++; -ccbegin = cc; -compares = 0; - -if (flags & XCL_MAP) - cc += 32 / sizeof(PCRE2_UCHAR); - -#ifdef SUPPORT_UNICODE -while (*cc == XCL_PROP || *cc == XCL_NOTPROP) - { - compares++; - cc++; - - items = 0; - - switch(*cc) - { - case PT_LAMP: - items = UCPCAT3(ucp_Lu, ucp_Ll, ucp_Lt); - break; - - case PT_GC: - items = UCPCAT_RANGE(PRIV(ucp_typerange)[(int)cc[1] * 2], PRIV(ucp_typerange)[(int)cc[1] * 2 + 1]); - break; - - case PT_PC: - items = UCPCAT(cc[1]); - break; - - case PT_WORD: - items = UCPCAT2(ucp_Mn, ucp_Pc) | UCPCAT_L | UCPCAT_N; - break; - - case PT_ALNUM: - items = UCPCAT_L | UCPCAT_N; - break; - - case PT_SCX: - status |= XCLASS_HAS_SCRIPT_EXTENSION; - if (cc[-1] == XCL_NOTPROP) - { - status |= XCLASS_SCRIPT_EXTENSION_NOTPROP; - break; - } - compares++; - /* Fall through */ - - case PT_SC: - status |= XCLASS_HAS_SCRIPT; - break; - - case PT_SPACE: - case PT_PXSPACE: - case PT_PXGRAPH: - case PT_PXPRINT: - case PT_PXPUNCT: - status |= XCLASS_SAVE_CHAR | XCLASS_HAS_TYPE; - break; - - case PT_UCNC: - case PT_PXXDIGIT: - status |= XCLASS_SAVE_CHAR; - break; - - case PT_BOOL: - status |= XCLASS_HAS_BOOL; - break; - - case PT_BIDICL: - status |= XCLASS_HAS_BIDICL; - break; - - default: - SLJIT_UNREACHABLE(); - break; - } - - if (items > 0) - { - if (cc[-1] == XCL_NOTPROP) - items ^= UCPCAT_ALL; - category_list |= items; - status |= XCLASS_HAS_TYPE; - compares--; - } - - cc += 2; - } - -if (category_list == UCPCAT_ALL) - { - /* All or no characters are accepted, same as dotall. */ - if (status & XCLASS_IS_ECLASS) - { - if (list != backtracks) - OP2(SLJIT_OR, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, 1); - return; - } - - compile_char1_matchingpath(common, OP_ALLANY, cc, backtracks, FALSE); - if (list == backtracks) - add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); - return; - } - -if (category_list != 0) - compares++; -#endif - -if (*cc != XCL_END) - { -#if defined SUPPORT_UNICODE && (PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16) - if (common->utf && compares == 0 && !(status & XCLASS_IS_ECLASS)) - { - SLJIT_ASSERT(category_list == 0); - max = 0; - min = (flags & XCL_MAP) != 0 ? 0 : READ_CHAR_MAX; - xclass_update_min_max(common, cc, &min, &max); - } -#endif - compares++; -#ifdef SUPPORT_UNICODE - status |= XCLASS_SAVE_CHAR; -#endif /* SUPPORT_UNICODE */ - } - -#ifdef SUPPORT_UNICODE -SLJIT_ASSERT(compares > 0 || category_list != 0); -#else /* !SUPPORT_UNICODE */ -SLJIT_ASSERT(compares > 0); -#endif /* SUPPORT_UNICODE */ - -/* We are not necessary in utf mode even in 8 bit mode. */ -cc = ccbegin; -if (!(status & XCLASS_IS_ECLASS)) - { - if ((flags & XCL_NOT) != 0) - read_char(common, min, max, backtracks, READ_CHAR_UPDATE_STR_PTR); - else - { -#ifdef SUPPORT_UNICODE - read_char(common, min, max, (status & XCLASS_NEEDS_UCD) ? backtracks : NULL, 0); -#else /* !SUPPORT_UNICODE */ - read_char(common, min, max, NULL, 0); -#endif /* SUPPORT_UNICODE */ - } - } - -if ((flags & XCL_MAP) != 0) - { - SLJIT_ASSERT(!(status & XCLASS_IS_ECLASS)); - xclass_check_bitset(common, (const sljit_u8 *)cc, &found, backtracks); - cc += 32 / sizeof(PCRE2_UCHAR); - } - -#ifdef SUPPORT_UNICODE -if (status & XCLASS_NEEDS_UCD) - { - if ((status & (XCLASS_SAVE_CHAR | XCLASS_IS_ECLASS)) == XCLASS_SAVE_CHAR) - OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0); - -#if PCRE2_CODE_UNIT_WIDTH == 32 - if (!common->utf) - { - OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, MAX_UTF_CODE_POINT + 1); - SELECT(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, UNASSIGNED_UTF_CHAR, TMP1); - } -#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */ - - OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); - OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); - OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1)); - OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK); - OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); - OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2)); - OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1); - OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 3); - OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2); - OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0); - - ccbegin = cc; - - if (status & XCLASS_HAS_BIDICL) - { - OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, scriptx_bidiclass)); - OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BIDICLASS_SHIFT); - - while (*cc == XCL_PROP || *cc == XCL_NOTPROP) - { - cc++; - - if (*cc == PT_BIDICL) - { - compares--; - invertcmp = (compares == 0 && list != backtracks); - if (cc[-1] == XCL_NOTPROP) - invertcmp ^= 0x1; - jump = CMP(SLJIT_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (int)cc[1]); - add_jump(compiler, compares > 0 ? list : backtracks, jump); - } - cc += 2; - } - - cc = ccbegin; - } - - if (status & XCLASS_HAS_BOOL) - { - OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, bprops)); - OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BPROPS_MASK); - OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 2); - - while (*cc == XCL_PROP || *cc == XCL_NOTPROP) - { - cc++; - if (*cc == PT_BOOL) - { - compares--; - invertcmp = (compares == 0 && list != backtracks); - if (cc[-1] == XCL_NOTPROP) - invertcmp ^= 0x1; - - OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP1), (sljit_sw)(PRIV(ucd_boolprop_sets) + (cc[1] >> 5)), SLJIT_IMM, (sljit_sw)(1u << (cc[1] & 0x1f))); - add_jump(compiler, compares > 0 ? list : backtracks, JUMP(SLJIT_NOT_ZERO ^ invertcmp)); - } - cc += 2; - } - - cc = ccbegin; - } - - if (status & XCLASS_HAS_SCRIPT) - { - OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script)); - - while (*cc == XCL_PROP || *cc == XCL_NOTPROP) - { - cc++; - - switch (*cc) - { - case PT_SCX: - if (cc[-1] == XCL_NOTPROP) - break; - /* Fall through */ - - case PT_SC: - compares--; - invertcmp = (compares == 0 && list != backtracks); - if (cc[-1] == XCL_NOTPROP) - invertcmp ^= 0x1; - - add_jump(compiler, compares > 0 ? list : backtracks, CMP(SLJIT_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (int)cc[1])); - } - cc += 2; - } - - cc = ccbegin; - } - - if (status & XCLASS_HAS_SCRIPT_EXTENSION) - { - OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, scriptx_bidiclass)); - OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_SCRIPTX_MASK); - OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 2); - - if (status & XCLASS_SCRIPT_EXTENSION_NOTPROP) - { - if (status & XCLASS_HAS_TYPE) - { - if ((status & (XCLASS_SAVE_CHAR | XCLASS_IS_ECLASS)) == XCLASS_SAVE_CHAR) - { - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL0, TMP2, 0); - status |= XCLASS_SCRIPT_EXTENSION_RESTORE_LOCAL0; - } - else - { - OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP2, 0); - status |= XCLASS_SCRIPT_EXTENSION_RESTORE_RETURN_ADDR; - } - } - OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script)); - } - - while (*cc == XCL_PROP || *cc == XCL_NOTPROP) - { - cc++; - - if (*cc == PT_SCX) - { - compares--; - invertcmp = (compares == 0 && list != backtracks); - - jump = NULL; - if (cc[-1] == XCL_NOTPROP) - { - jump = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, (int)cc[1]); - if (invertcmp) - { - add_jump(compiler, backtracks, jump); - jump = NULL; - } - invertcmp ^= 0x1; - } - - OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP1), (sljit_sw)(PRIV(ucd_script_sets) + (cc[1] >> 5)), SLJIT_IMM, (sljit_sw)(1u << (cc[1] & 0x1f))); - add_jump(compiler, compares > 0 ? list : backtracks, JUMP(SLJIT_NOT_ZERO ^ invertcmp)); - - if (jump != NULL) - JUMPHERE(jump); - } - cc += 2; - } - - if (status & XCLASS_SCRIPT_EXTENSION_RESTORE_LOCAL0) - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0); - else if (status & XCLASS_SCRIPT_EXTENSION_RESTORE_RETURN_ADDR) - OP1(SLJIT_MOV, TMP2, 0, RETURN_ADDR, 0); - cc = ccbegin; - } - - if (status & XCLASS_SAVE_CHAR) - OP1(SLJIT_MOV, TMP1, 0, (status & XCLASS_IS_ECLASS) ? ECLASS_CHAR_DATA : RETURN_ADDR, 0); - - if (status & XCLASS_HAS_TYPE) - { - if (status & XCLASS_SAVE_CHAR) - typereg = RETURN_ADDR; - - OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype)); - OP2(SLJIT_SHL, typereg, 0, SLJIT_IMM, 1, TMP2, 0); - - if (category_list > 0) - { - compares--; - invertcmp = (compares == 0 && list != backtracks); - OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, category_list); - add_jump(compiler, compares > 0 ? list : backtracks, JUMP(SLJIT_NOT_ZERO ^ invertcmp)); - } - } - } -#endif /* SUPPORT_UNICODE */ - -/* Generating code. */ -charoffset = 0; - -#ifdef SUPPORT_UNICODE -while (*cc == XCL_PROP || *cc == XCL_NOTPROP) - { - compares--; - invertcmp = (compares == 0 && list != backtracks); - jump = NULL; - - if (*cc == XCL_NOTPROP) - invertcmp ^= 0x1; - cc++; - switch(*cc) - { - case PT_LAMP: - case PT_GC: - case PT_PC: - case PT_SC: - case PT_SCX: - case PT_BOOL: - case PT_BIDICL: - case PT_WORD: - case PT_ALNUM: - compares++; - /* Already handled. */ - break; - - case PT_SPACE: - case PT_PXSPACE: - SET_CHAR_OFFSET(9); - OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0xd - 0x9); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); - - OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x85 - 0x9); - OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); - - OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x180e - 0x9); - OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); - - OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, UCPCAT_RANGE(ucp_Zl, ucp_Zs)); - OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_NOT_ZERO); - jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); - break; - - case PT_UCNC: - OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_DOLLAR_SIGN - charoffset)); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); - OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_COMMERCIAL_AT - charoffset)); - OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); - OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_GRAVE_ACCENT - charoffset)); - OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); - - SET_CHAR_OFFSET(0xa0); - OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, (sljit_sw)(0xd7ff - charoffset)); - OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); - SET_CHAR_OFFSET(0); - OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xe000 - 0); - OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_GREATER_EQUAL); - jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); - break; - - case PT_PXGRAPH: - OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, UCPCAT_RANGE(ucp_Cc, ucp_Cs) | UCPCAT_RANGE(ucp_Zl, ucp_Zs)); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_NOT_ZERO); - - OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, UCPCAT(ucp_Cf)); - jump = JUMP(SLJIT_ZERO); - - c = charoffset; - /* In case of ucp_Cf, we overwrite the result. */ - SET_CHAR_OFFSET(0x2066); - OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); - - OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066); - OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); - - OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x180e - 0x2066); - OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); - - /* Restore charoffset. */ - SET_CHAR_OFFSET(c); - - JUMPHERE(jump); - jump = CMP(SLJIT_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0); - break; - - case PT_PXPRINT: - OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, UCPCAT_RANGE(ucp_Cc, ucp_Cs) | UCPCAT2(ucp_Zl, ucp_Zp)); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_NOT_ZERO); - - OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, UCPCAT(ucp_Cf)); - jump = JUMP(SLJIT_ZERO); - - c = charoffset; - /* In case of ucp_Cf, we overwrite the result. */ - SET_CHAR_OFFSET(0x2066); - OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); - - OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066); - OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); - - /* Restore charoffset. */ - SET_CHAR_OFFSET(c); - - JUMPHERE(jump); - jump = CMP(SLJIT_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0); - break; - - case PT_PXPUNCT: - OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, UCPCAT_RANGE(ucp_Sc, ucp_So)); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_NOT_ZERO); - - SET_CHAR_OFFSET(0); - OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x7f); - OP_FLAGS(SLJIT_AND, TMP2, 0, SLJIT_LESS_EQUAL); - - OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, UCPCAT_RANGE(ucp_Pc, ucp_Ps)); - OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_NOT_ZERO); - jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); - break; - - case PT_PXXDIGIT: - SET_CHAR_OFFSET(CHAR_A); - OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, ~0x20); - OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP2, 0, SLJIT_IMM, CHAR_F - CHAR_A); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); - - SET_CHAR_OFFSET(CHAR_0); - OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_9 - CHAR_0); - OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); - - SET_CHAR_OFFSET(0xff10); - jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 0xff46 - 0xff10); - - OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0xff19 - 0xff10); - OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); - - SET_CHAR_OFFSET(0xff21); - OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0xff26 - 0xff21); - OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); - - SET_CHAR_OFFSET(0xff41); - OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0xff46 - 0xff41); - OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); - - SET_CHAR_OFFSET(0xff10); - - JUMPHERE(jump); - OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, 0); - jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); - break; - - default: - SLJIT_UNREACHABLE(); - break; - } - - cc += 2; - - if (jump != NULL) - add_jump(compiler, compares > 0 ? list : backtracks, jump); - } - -if (compares == 0) - { - if (found != NULL) - set_jumps(found, LABEL()); - - if (status & XCLASS_IS_ECLASS) - OP2(SLJIT_OR, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, 1); - return; - } -#endif /* SUPPORT_UNICODE */ - -SLJIT_ASSERT(compares == 1); -ranges.range_count = 0; -ranges.ranges = ranges.local_ranges; -ranges.stack = ranges.local_stack; - -xclass_compute_ranges(common, cc, &ranges); - -/* Memory error is set for the compiler. */ -if (ranges.stack == NULL) - return; - -#if (defined SLJIT_DEBUG && SLJIT_DEBUG) && \ - defined SUPPORT_UNICODE && (PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16) -if (common->utf) - { - min = READ_CHAR_MAX; - max = 0; - xclass_update_min_max(common, cc, &min, &max); - SLJIT_ASSERT(ranges.ranges[0] == min && ranges.ranges[ranges.range_count - 1] == max); - } -#endif /* SLJIT_DEBUG && SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == [8|16] */ - -invertcmp = (list != backtracks); - -if (ranges.range_count == 2) - { - range_start = ranges.ranges[0]; - range_end = ranges.ranges[1]; - - if (range_start < range_end) - { - SET_CHAR_OFFSET(range_start); - jump = CMP(SLJIT_LESS_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(range_end - range_start)); - } - else - jump = CMP(SLJIT_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(range_start - charoffset)); - - add_jump(compiler, backtracks, jump); - - SLJIT_ASSERT(ranges.stack == ranges.local_stack); - if (found != NULL) - set_jumps(found, LABEL()); - - if (status & XCLASS_IS_ECLASS) - OP2(SLJIT_OR, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, 1); - return; - } - -range_start = ranges.ranges[0]; -SET_CHAR_OFFSET(range_start); -if (ranges.range_count >= 6) - { - /* Early fail. */ - range_end = ranges.ranges[ranges.range_count - 1]; - add_jump(compiler, (flags & XCL_NOT) == 0 ? backtracks : &found, - CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, (sljit_sw)(range_end - range_start))); - } - -depth = 0; -first_item = 0; -last_item = ranges.range_count - 2; -has_cmov = sljit_has_cpu_feature(SLJIT_HAS_CMOV) != 0; - -while (TRUE) - { - /* At least two items are present. */ - SLJIT_ASSERT(first_item < last_item && charoffset == ranges.ranges[0]); - last_range_set = FALSE; - - if (first_item + 6 <= last_item) - { - mid_item = ((first_item + last_item) >> 1) & ~(sljit_u32)1; - SLJIT_ASSERT(last_item >= mid_item + 4); - - range_end = ranges.ranges[mid_item + 1]; - if (first_item + 6 > mid_item && ranges.ranges[mid_item] == range_end) - { - OP2U(SLJIT_SUB | SLJIT_SET_GREATER | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(range_end - charoffset)); - ranges.stack[depth].jump = JUMP(SLJIT_GREATER); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); - last_range_set = TRUE; - } - else - ranges.stack[depth].jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, (sljit_sw)(range_end - charoffset)); - - ranges.stack[depth].first_item = (sljit_u32)(mid_item + 2); - ranges.stack[depth].last_item = (sljit_u32)last_item; - - depth++; - SLJIT_ASSERT(ranges.stack == ranges.local_stack ? - depth <= XCLASS_LOCAL_RANGES_LOG2_SIZE : (ranges.stack + depth) <= (xclass_stack_item*)ranges.ranges); - - last_item = mid_item; - if (!last_range_set) - continue; - - last_item -= 2; - } - - if (!last_range_set) - { - range_start = ranges.ranges[first_item]; - range_end = ranges.ranges[first_item + 1]; - - if (range_start < range_end) - { - SET_CHAR_OFFSET(range_start); - OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, (sljit_sw)(range_end - range_start)); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); - } - else - { - OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(range_start - charoffset)); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); - } - first_item += 2; - } - - SLJIT_ASSERT(first_item <= last_item); - - do - { - range_start = ranges.ranges[first_item]; - range_end = ranges.ranges[first_item + 1]; - - if (range_start < range_end) - { - SET_CHAR_OFFSET(range_start); - OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, (sljit_sw)(range_end - range_start)); - - if (has_cmov) - SELECT(SLJIT_LESS_EQUAL, TMP2, STR_END, 0, TMP2); - else - OP_FLAGS(SLJIT_OR | ((first_item == last_item) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_LESS_EQUAL); - } - else - { - OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(range_start - charoffset)); - - if (has_cmov) - SELECT(SLJIT_EQUAL, TMP2, STR_END, 0, TMP2); - else - OP_FLAGS(SLJIT_OR | ((first_item == last_item) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_EQUAL); - } - - first_item += 2; - } - while (first_item <= last_item); - - if (depth == 0) break; - - add_jump(compiler, &check_result, JUMP(SLJIT_JUMP)); - - /* The charoffset resets after the end of a branch is reached. */ - charoffset = ranges.ranges[0]; - depth--; - first_item = ranges.stack[depth].first_item; - last_item = ranges.stack[depth].last_item; - JUMPHERE(ranges.stack[depth].jump); - } - -if (check_result != NULL) - set_jumps(check_result, LABEL()); - -if (has_cmov) - jump = CMP(SLJIT_NOT_EQUAL ^ invertcmp, TMP2, 0, SLJIT_IMM, 0); -else - { - sljit_set_current_flags(compiler, SLJIT_SET_Z); - jump = JUMP(SLJIT_NOT_EQUAL ^ invertcmp); - } - -add_jump(compiler, backtracks, jump); - -if (found != NULL) - set_jumps(found, LABEL()); - -if (status & XCLASS_IS_ECLASS) - OP2(SLJIT_OR, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, 1); - -if (ranges.stack != ranges.local_stack) - SLJIT_FREE(ranges.stack, compiler->allocator_data); -} - -static PCRE2_SPTR compile_eclass_matchingpath(compiler_common *common, PCRE2_SPTR cc, jump_list **backtracks) -{ -DEFINE_COMPILER; -PCRE2_SPTR end = cc + GET(cc, 0) - 1; -PCRE2_SPTR begin; -jump_list *not_found; -jump_list *found = NULL; - -cc += LINK_SIZE; - -/* Should be optimized later. */ -read_char(common, 0, READ_CHAR_MAX, backtracks, 0); - -if (((*cc++) & ECL_MAP) != 0) - { - xclass_check_bitset(common, (const sljit_u8 *)cc, &found, backtracks); - cc += 32 / sizeof(PCRE2_UCHAR); - } - -begin = cc; - -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL0, ECLASS_CHAR_DATA, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL1, ECLASS_STACK_DATA, 0); -OP1(SLJIT_MOV, ECLASS_STACK_DATA, 0, SLJIT_IMM, 0); -OP1(SLJIT_MOV, ECLASS_CHAR_DATA, 0, TMP1, 0); - -/* All eclass must start with an xclass. */ -SLJIT_ASSERT(*cc == ECL_XCLASS); - -while (cc < end) - { - switch (*cc) - { - case ECL_AND: - ++cc; - OP2(SLJIT_OR, TMP2, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, ~(sljit_sw)1); - OP2(SLJIT_LSHR, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, 1); - OP2(SLJIT_AND, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, TMP2, 0); - break; - - case ECL_OR: - ++cc; - OP2(SLJIT_AND, TMP2, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, 1); - OP2(SLJIT_LSHR, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, 1); - OP2(SLJIT_OR, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, TMP2, 0); - break; - - case ECL_XOR: - ++cc; - OP2(SLJIT_AND, TMP2, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, 1); - OP2(SLJIT_LSHR, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, 1); - OP2(SLJIT_XOR, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, TMP2, 0); - break; - - case ECL_NOT: - ++cc; - OP2(SLJIT_XOR, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, 1); - break; - - default: - SLJIT_ASSERT(*cc == ECL_XCLASS); - if (cc != begin) - { - OP1(SLJIT_MOV, TMP1, 0, ECLASS_CHAR_DATA, 0); - OP2(SLJIT_SHL, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, 1); - } - - not_found = NULL; - compile_xclass_matchingpath(common, cc + 1 + LINK_SIZE, ¬_found, XCLASS_IS_ECLASS); - set_jumps(not_found, LABEL()); - - cc += GET(cc, 1); - break; - } - } - -OP2U(SLJIT_SUB | SLJIT_SET_Z, ECLASS_STACK_DATA, 0, SLJIT_IMM, 0); -OP1(SLJIT_MOV, ECLASS_CHAR_DATA, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0); -OP1(SLJIT_MOV, ECLASS_STACK_DATA, 0, SLJIT_MEM1(SLJIT_SP), LOCAL1); -add_jump(compiler, backtracks, JUMP(SLJIT_EQUAL)); -set_jumps(found, LABEL()); -return end; -} - -/* Generic character matching code. */ - -#undef SET_CHAR_OFFSET -#undef READ_FROM_CHAR_LIST -#undef XCLASS_LOCAL_RANGES_SIZE -#undef XCLASS_LOCAL_RANGES_LOG2_SIZE - -#endif /* SUPPORT_WIDE_CHARS */ - -static PCRE2_SPTR byte_sequence_compare(compiler_common *common, BOOL caseless, PCRE2_SPTR cc, - compare_context *context, jump_list **backtracks) -{ -DEFINE_COMPILER; -unsigned int othercasebit = 0; -PCRE2_SPTR othercasechar = NULL; -#ifdef SUPPORT_UNICODE -int utflength; -#endif - -if (caseless && char_has_othercase(common, cc)) - { - othercasebit = char_get_othercase_bit(common, cc); - SLJIT_ASSERT(othercasebit); - /* Extracting bit difference info. */ -#if PCRE2_CODE_UNIT_WIDTH == 8 - othercasechar = cc + (othercasebit >> 8); - othercasebit &= 0xff; -#elif PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32 - /* Note that this code only handles characters in the BMP. If there - ever are characters outside the BMP whose othercase differs in only one - bit from itself (there currently are none), this code will need to be - revised for PCRE2_CODE_UNIT_WIDTH == 32. */ - othercasechar = cc + (othercasebit >> 9); - if ((othercasebit & 0x100) != 0) - othercasebit = (othercasebit & 0xff) << 8; - else - othercasebit &= 0xff; -#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */ - } - -if (context->sourcereg == -1) - { -#if PCRE2_CODE_UNIT_WIDTH == 8 -#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED - if (context->length >= 4) - OP1(SLJIT_MOV_S32, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); - else if (context->length >= 2) - OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); - else -#endif - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); -#elif PCRE2_CODE_UNIT_WIDTH == 16 -#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED - if (context->length >= 4) - OP1(SLJIT_MOV_S32, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); - else -#endif - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); -#elif PCRE2_CODE_UNIT_WIDTH == 32 - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); -#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */ - context->sourcereg = TMP2; - } - -#ifdef SUPPORT_UNICODE -utflength = 1; -if (common->utf && HAS_EXTRALEN(*cc)) - utflength += GET_EXTRALEN(*cc); - -do - { -#endif - - context->length -= IN_UCHARS(1); -#if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED) && (PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16) - - /* Unaligned read is supported. */ - if (othercasebit != 0 && othercasechar == cc) - { - context->c.asuchars[context->ucharptr] = *cc | othercasebit; - context->oc.asuchars[context->ucharptr] = othercasebit; - } - else - { - context->c.asuchars[context->ucharptr] = *cc; - context->oc.asuchars[context->ucharptr] = 0; - } - context->ucharptr++; - -#if PCRE2_CODE_UNIT_WIDTH == 8 - if (context->ucharptr >= 4 || context->length == 0 || (context->ucharptr == 2 && context->length == 1)) -#else - if (context->ucharptr >= 2 || context->length == 0) -#endif - { - if (context->length >= 4) - OP1(SLJIT_MOV_S32, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); - else if (context->length >= 2) - OP1(SLJIT_MOV_U16, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); -#if PCRE2_CODE_UNIT_WIDTH == 8 - else if (context->length >= 1) - OP1(SLJIT_MOV_U8, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); -#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */ - context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1; - - switch(context->ucharptr) - { - case 4 / sizeof(PCRE2_UCHAR): - if (context->oc.asint != 0) - OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint); - add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint)); - break; - - case 2 / sizeof(PCRE2_UCHAR): - if (context->oc.asushort != 0) - OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asushort); - add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asushort | context->oc.asushort)); - break; - -#if PCRE2_CODE_UNIT_WIDTH == 8 - case 1: - if (context->oc.asbyte != 0) - OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte); - add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte)); - break; -#endif - - default: - SLJIT_UNREACHABLE(); - break; - } - context->ucharptr = 0; - } - -#else - - /* Unaligned read is unsupported or in 32 bit mode. */ - if (context->length >= 1) - OP1(MOV_UCHAR, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); - - context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1; - - if (othercasebit != 0 && othercasechar == cc) - { - OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit); - add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit)); - } - else - add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc)); - -#endif - - cc++; -#ifdef SUPPORT_UNICODE - utflength--; - } -while (utflength > 0); -#endif - -return cc; -} - -#ifdef SUPPORT_UNICODE - -#if PCRE2_CODE_UNIT_WIDTH != 32 - -/* The code in this function copies the logic of the interpreter function that -is defined in the pcre2_extuni.c source. If that code is updated, this -function, and those below it, must be kept in step (note by PH, June 2024). */ - -static PCRE2_SPTR SLJIT_FUNC do_extuni_utf(jit_arguments *args, PCRE2_SPTR cc) -{ -PCRE2_SPTR start_subject = args->begin; -PCRE2_SPTR end_subject = args->end; -int lgb, rgb, ricount; -PCRE2_SPTR prevcc, endcc, bptr; -BOOL first = TRUE; -BOOL was_ep_ZWJ = FALSE; -uint32_t c; - -prevcc = cc; -endcc = NULL; -do - { - GETCHARINC(c, cc); - rgb = UCD_GRAPHBREAK(c); - - if (first) - { - lgb = rgb; - endcc = cc; - first = FALSE; - continue; - } - - if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) - break; - - /* ZWJ followed by Extended Pictographic is allowed only if the ZWJ was - preceded by Extended Pictographic. */ - - if (lgb == ucp_gbZWJ && rgb == ucp_gbExtended_Pictographic && !was_ep_ZWJ) - break; - - /* Not breaking between Regional Indicators is allowed only if there - are an even number of preceding RIs. */ - - if (lgb == ucp_gbRegional_Indicator && rgb == ucp_gbRegional_Indicator) - { - ricount = 0; - bptr = prevcc; - - /* bptr is pointing to the left-hand character */ - while (bptr > start_subject) - { - bptr--; - BACKCHAR(bptr); - GETCHAR(c, bptr); - - if (UCD_GRAPHBREAK(c) != ucp_gbRegional_Indicator) - break; - - ricount++; - } - - if ((ricount & 1) != 0) break; /* Grapheme break required */ - } - - /* Set a flag when ZWJ follows Extended Pictographic (with optional Extend in - between; see next statement). */ - - was_ep_ZWJ = (lgb == ucp_gbExtended_Pictographic && rgb == ucp_gbZWJ); - - /* If Extend follows Extended_Pictographic, do not update lgb; this allows - any number of them before a following ZWJ. */ - - if (rgb != ucp_gbExtend || lgb != ucp_gbExtended_Pictographic) - lgb = rgb; - - prevcc = endcc; - endcc = cc; - } -while (cc < end_subject); - -return endcc; -} - -#endif /* PCRE2_CODE_UNIT_WIDTH != 32 */ - -/* The code in this function copies the logic of the interpreter function that -is defined in the pcre2_extuni.c source. If that code is updated, this -function, and the one below it, must be kept in step (note by PH, June 2024). */ - -static PCRE2_SPTR SLJIT_FUNC do_extuni_utf_invalid(jit_arguments *args, PCRE2_SPTR cc) -{ -PCRE2_SPTR start_subject = args->begin; -PCRE2_SPTR end_subject = args->end; -int lgb, rgb, ricount; -PCRE2_SPTR prevcc, endcc, bptr; -BOOL first = TRUE; -BOOL was_ep_ZWJ = FALSE; -uint32_t c; - -prevcc = cc; -endcc = NULL; -do - { - GETCHARINC_INVALID(c, cc, end_subject, break); - rgb = UCD_GRAPHBREAK(c); - - if (first) - { - lgb = rgb; - endcc = cc; - first = FALSE; - continue; - } - - if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) - break; - - /* ZWJ followed by Extended Pictographic is allowed only if the ZWJ was - preceded by Extended Pictographic. */ - - if (lgb == ucp_gbZWJ && rgb == ucp_gbExtended_Pictographic && !was_ep_ZWJ) - break; - - /* Not breaking between Regional Indicators is allowed only if there - are an even number of preceding RIs. */ - - if (lgb == ucp_gbRegional_Indicator && rgb == ucp_gbRegional_Indicator) - { - ricount = 0; - bptr = prevcc; - - /* bptr is pointing to the left-hand character */ - while (bptr > start_subject) - { - GETCHARBACK_INVALID(c, bptr, start_subject, break); - - if (UCD_GRAPHBREAK(c) != ucp_gbRegional_Indicator) - break; - - ricount++; - } - - if ((ricount & 1) != 0) - break; /* Grapheme break required */ - } - - /* Set a flag when ZWJ follows Extended Pictographic (with optional Extend in - between; see next statement). */ - - was_ep_ZWJ = (lgb == ucp_gbExtended_Pictographic && rgb == ucp_gbZWJ); - - /* If Extend follows Extended_Pictographic, do not update lgb; this allows - any number of them before a following ZWJ. */ - - if (rgb != ucp_gbExtend || lgb != ucp_gbExtended_Pictographic) - lgb = rgb; - - prevcc = endcc; - endcc = cc; - } -while (cc < end_subject); - -return endcc; -} - -/* The code in this function copies the logic of the interpreter function that -is defined in the pcre2_extuni.c source. If that code is updated, this -function must be kept in step (note by PH, June 2024). */ - -static PCRE2_SPTR SLJIT_FUNC do_extuni_no_utf(jit_arguments *args, PCRE2_SPTR cc) -{ -PCRE2_SPTR start_subject = args->begin; -PCRE2_SPTR end_subject = args->end; -int lgb, rgb, ricount; -PCRE2_SPTR bptr; -uint32_t c; -BOOL was_ep_ZWJ = FALSE; - -/* Patch by PH */ -/* GETCHARINC(c, cc); */ -c = *cc++; - -#if PCRE2_CODE_UNIT_WIDTH == 32 -if (c >= 0x110000) - return cc; -#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */ -lgb = UCD_GRAPHBREAK(c); - -while (cc < end_subject) - { - c = *cc; -#if PCRE2_CODE_UNIT_WIDTH == 32 - if (c >= 0x110000) - break; -#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */ - rgb = UCD_GRAPHBREAK(c); - - if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) - break; - - /* ZWJ followed by Extended Pictographic is allowed only if the ZWJ was - preceded by Extended Pictographic. */ - - if (lgb == ucp_gbZWJ && rgb == ucp_gbExtended_Pictographic && !was_ep_ZWJ) - break; - - /* Not breaking between Regional Indicators is allowed only if there - are an even number of preceding RIs. */ - - if (lgb == ucp_gbRegional_Indicator && rgb == ucp_gbRegional_Indicator) - { - ricount = 0; - bptr = cc - 1; - - /* bptr is pointing to the left-hand character */ - while (bptr > start_subject) - { - bptr--; - c = *bptr; -#if PCRE2_CODE_UNIT_WIDTH == 32 - if (c >= 0x110000) - break; -#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */ - - if (UCD_GRAPHBREAK(c) != ucp_gbRegional_Indicator) break; - - ricount++; - } - - if ((ricount & 1) != 0) - break; /* Grapheme break required */ - } - - /* Set a flag when ZWJ follows Extended Pictographic (with optional Extend in - between; see next statement). */ - - was_ep_ZWJ = (lgb == ucp_gbExtended_Pictographic && rgb == ucp_gbZWJ); - - /* If Extend follows Extended_Pictographic, do not update lgb; this allows - any number of them before a following ZWJ. */ - - if (rgb != ucp_gbExtend || lgb != ucp_gbExtended_Pictographic) - lgb = rgb; - - cc++; - } - -return cc; -} - -static void compile_clist(compiler_common *common, PCRE2_SPTR cc, jump_list **backtracks) -{ -DEFINE_COMPILER; -const sljit_u32 *other_cases; -struct sljit_jump *jump; -sljit_u32 min = 0, max = READ_CHAR_MAX; -BOOL has_cmov = sljit_has_cpu_feature(SLJIT_HAS_CMOV) != 0; - -SLJIT_ASSERT(cc[1] == PT_CLIST); - -if (cc[0] == OP_PROP) - { - other_cases = PRIV(ucd_caseless_sets) + cc[2]; - - min = *other_cases++; - max = min; - - while (*other_cases != NOTACHAR) - { - if (*other_cases > max) max = *other_cases; - if (*other_cases < min) min = *other_cases; - other_cases++; - } - } - -other_cases = PRIV(ucd_caseless_sets) + cc[2]; -SLJIT_ASSERT(other_cases[0] != NOTACHAR && other_cases[1] != NOTACHAR); -/* The NOTACHAR is higher than any character. */ -SLJIT_ASSERT(other_cases[0] < other_cases[1] && other_cases[1] < other_cases[2]); - -read_char(common, min, max, backtracks, READ_CHAR_UPDATE_STR_PTR); - -/* At least two characters are required. - Otherwise this case would be handled by the normal code path. */ -/* NOTACHAR is the unsigned maximum. */ - -/* Optimizing character pairs, if their difference is power of 2. */ -if (is_powerof2(other_cases[1] ^ other_cases[0])) - { - OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(other_cases[1] ^ other_cases[0])); - OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, other_cases[1]); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); - other_cases += 2; - } -else if (is_powerof2(other_cases[2] ^ other_cases[1])) - { - SLJIT_ASSERT(other_cases[2] != NOTACHAR); - - OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(other_cases[2] ^ other_cases[1])); - OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, other_cases[2]); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); - - OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)other_cases[0]); - - if (has_cmov) - SELECT(SLJIT_EQUAL, TMP2, STR_END, 0, TMP2); - else - OP_FLAGS(SLJIT_OR | ((other_cases[3] == NOTACHAR) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_EQUAL); - - other_cases += 3; - } -else - { - OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++)); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); - } - -while (*other_cases != NOTACHAR) - { - OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++)); - - if (has_cmov) - SELECT(SLJIT_EQUAL, TMP2, STR_END, 0, TMP2); - else - OP_FLAGS(SLJIT_OR | ((*other_cases == NOTACHAR) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_EQUAL); - } - -if (has_cmov) - jump = CMP(cc[0] == OP_PROP ? SLJIT_EQUAL : SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0); -else - jump = JUMP(cc[0] == OP_PROP ? SLJIT_ZERO : SLJIT_NOT_ZERO); - -add_jump(compiler, backtracks, jump); -} - -#endif /* SUPPORT_UNICODE */ - -static PCRE2_SPTR compile_char1_matchingpath(compiler_common *common, PCRE2_UCHAR type, PCRE2_SPTR cc, jump_list **backtracks, BOOL check_str_ptr) -{ -DEFINE_COMPILER; -int length; -unsigned int c, oc, bit; -compare_context context; -struct sljit_jump *jump[3]; -jump_list *end_list; -#ifdef SUPPORT_UNICODE -PCRE2_UCHAR propdata[5]; -#endif /* SUPPORT_UNICODE */ - -switch(type) - { - case OP_NOT_DIGIT: - case OP_DIGIT: - /* Digits are usually 0-9, so it is worth to optimize them. */ - if (check_str_ptr) - detect_partial_match(common, backtracks); -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 - if (common->utf && is_char7_bitset((const sljit_u8*)common->ctypes - cbit_length + cbit_digit, FALSE)) - read_char7_type(common, backtracks, type == OP_NOT_DIGIT); - else -#endif - read_char8_type(common, backtracks, type == OP_NOT_DIGIT); - /* Flip the starting bit in the negative case. */ - OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, ctype_digit); - add_jump(compiler, backtracks, JUMP(type == OP_DIGIT ? SLJIT_ZERO : SLJIT_NOT_ZERO)); - return cc; - - case OP_NOT_WHITESPACE: - case OP_WHITESPACE: - if (check_str_ptr) - detect_partial_match(common, backtracks); -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 - if (common->utf && is_char7_bitset((const sljit_u8*)common->ctypes - cbit_length + cbit_space, FALSE)) - read_char7_type(common, backtracks, type == OP_NOT_WHITESPACE); - else -#endif - read_char8_type(common, backtracks, type == OP_NOT_WHITESPACE); - OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, ctype_space); - add_jump(compiler, backtracks, JUMP(type == OP_WHITESPACE ? SLJIT_ZERO : SLJIT_NOT_ZERO)); - return cc; - - case OP_NOT_WORDCHAR: - case OP_WORDCHAR: - if (check_str_ptr) - detect_partial_match(common, backtracks); -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 - if (common->utf && is_char7_bitset((const sljit_u8*)common->ctypes - cbit_length + cbit_word, FALSE)) - read_char7_type(common, backtracks, type == OP_NOT_WORDCHAR); - else -#endif - read_char8_type(common, backtracks, type == OP_NOT_WORDCHAR); - OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, ctype_word); - add_jump(compiler, backtracks, JUMP(type == OP_WORDCHAR ? SLJIT_ZERO : SLJIT_NOT_ZERO)); - return cc; - - case OP_ANY: - if (check_str_ptr) - detect_partial_match(common, backtracks); - read_char(common, common->nlmin, common->nlmax, backtracks, READ_CHAR_UPDATE_STR_PTR); - if (common->nltype == NLTYPE_FIXED && common->newline > 255) - { - jump[0] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); - end_list = NULL; - if (common->mode != PCRE2_JIT_PARTIAL_HARD) - add_jump(compiler, &end_list, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); - else - check_str_end(common, &end_list); - - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); - add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff)); - set_jumps(end_list, LABEL()); - JUMPHERE(jump[0]); - } - else - check_newlinechar(common, common->nltype, backtracks, TRUE); - return cc; - - case OP_ALLANY: - if (check_str_ptr) - detect_partial_match(common, backtracks); -#ifdef SUPPORT_UNICODE - if (common->utf && common->invalid_utf) - { - read_char(common, 0, READ_CHAR_MAX, backtracks, READ_CHAR_UPDATE_STR_PTR); - return cc; - } -#endif /* SUPPORT_UNICODE */ - - skip_valid_char(common); - return cc; - - case OP_ANYBYTE: - if (check_str_ptr) - detect_partial_match(common, backtracks); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - return cc; - -#ifdef SUPPORT_UNICODE - case OP_NOTPROP: - case OP_PROP: - if (check_str_ptr) - detect_partial_match(common, backtracks); - if (cc[0] == PT_CLIST) - { - compile_clist(common, cc - 1, backtracks); - return cc + 2; - } - - propdata[0] = 0; - propdata[1] = type == OP_NOTPROP ? XCL_NOTPROP : XCL_PROP; - propdata[2] = cc[0]; - propdata[3] = cc[1]; - propdata[4] = XCL_END; - compile_xclass_matchingpath(common, propdata, backtracks, 0); - return cc + 2; -#endif - - case OP_ANYNL: - if (check_str_ptr) - detect_partial_match(common, backtracks); - read_char(common, common->bsr_nlmin, common->bsr_nlmax, NULL, 0); - jump[0] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); - /* We don't need to handle soft partial matching case. */ - end_list = NULL; - if (common->mode != PCRE2_JIT_PARTIAL_HARD) - add_jump(compiler, &end_list, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); - else - check_str_end(common, &end_list); - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); - OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_NL); - OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL); -#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32 - OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT); -#endif - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); - jump[1] = JUMP(SLJIT_JUMP); - JUMPHERE(jump[0]); - check_newlinechar(common, common->bsr_nltype, backtracks, FALSE); - set_jumps(end_list, LABEL()); - JUMPHERE(jump[1]); - return cc; - - case OP_NOT_HSPACE: - case OP_HSPACE: - if (check_str_ptr) - detect_partial_match(common, backtracks); - - if (type == OP_NOT_HSPACE) - read_char(common, 0x9, 0x3000, backtracks, READ_CHAR_UPDATE_STR_PTR); - else - read_char(common, 0x9, 0x3000, NULL, 0); - - add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL)); - sljit_set_current_flags(compiler, SLJIT_SET_Z); - add_jump(compiler, backtracks, JUMP(type == OP_NOT_HSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO)); - return cc; - - case OP_NOT_VSPACE: - case OP_VSPACE: - if (check_str_ptr) - detect_partial_match(common, backtracks); - - if (type == OP_NOT_VSPACE) - read_char(common, 0xa, 0x2029, backtracks, READ_CHAR_UPDATE_STR_PTR); - else - read_char(common, 0xa, 0x2029, NULL, 0); - - add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL)); - sljit_set_current_flags(compiler, SLJIT_SET_Z); - add_jump(compiler, backtracks, JUMP(type == OP_NOT_VSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO)); - return cc; - -#ifdef SUPPORT_UNICODE - case OP_EXTUNI: - if (check_str_ptr) - detect_partial_match(common, backtracks); - - SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1); - OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0); - -#if PCRE2_CODE_UNIT_WIDTH != 32 - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM, - common->utf ? (common->invalid_utf ? SLJIT_FUNC_ADDR(do_extuni_utf_invalid) : SLJIT_FUNC_ADDR(do_extuni_utf)) : SLJIT_FUNC_ADDR(do_extuni_no_utf)); - if (common->invalid_utf) - add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0)); -#else - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM, - common->invalid_utf ? SLJIT_FUNC_ADDR(do_extuni_utf_invalid) : SLJIT_FUNC_ADDR(do_extuni_no_utf)); - if (common->invalid_utf) - add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0)); -#endif - - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0); - - if (common->mode == PCRE2_JIT_PARTIAL_HARD) - { - jump[0] = CMP(SLJIT_LESS, SLJIT_RETURN_REG, 0, STR_END, 0); - /* Since we successfully read a char above, partial matching must occur. */ - check_partial(common, TRUE); - JUMPHERE(jump[0]); - } - return cc; -#endif - - case OP_CHAR: - case OP_CHARI: - length = 1; -#ifdef SUPPORT_UNICODE - if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc); -#endif - - if (check_str_ptr && common->mode != PCRE2_JIT_COMPLETE) - detect_partial_match(common, backtracks); - - if (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0) - { - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); - if (length > 1 || (check_str_ptr && common->mode == PCRE2_JIT_COMPLETE)) - add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0)); - - context.length = IN_UCHARS(length); - context.sourcereg = -1; -#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED - context.ucharptr = 0; -#endif - return byte_sequence_compare(common, type == OP_CHARI, cc, &context, backtracks); - } - -#ifdef SUPPORT_UNICODE - if (common->utf) - { - GETCHAR(c, cc); - } - else -#endif - c = *cc; - - SLJIT_ASSERT(type == OP_CHARI && char_has_othercase(common, cc)); - - if (check_str_ptr && common->mode == PCRE2_JIT_COMPLETE) - add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); - - oc = char_othercase(common, c); - read_char(common, c < oc ? c : oc, c > oc ? c : oc, NULL, 0); - - SLJIT_ASSERT(!is_powerof2(c ^ oc)); - - if (sljit_has_cpu_feature(SLJIT_HAS_CMOV)) - { - OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, oc); - SELECT(SLJIT_EQUAL, TMP1, SLJIT_IMM, c, TMP1); - add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c)); - } - else - { - jump[0] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c); - add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, oc)); - JUMPHERE(jump[0]); - } - return cc + length; - - case OP_NOT: - case OP_NOTI: - if (check_str_ptr) - detect_partial_match(common, backtracks); - - length = 1; -#ifdef SUPPORT_UNICODE - if (common->utf) - { -#if PCRE2_CODE_UNIT_WIDTH == 8 - c = *cc; - if (c < 128 && !common->invalid_utf) - { - OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); - if (type == OP_NOT || !char_has_othercase(common, cc)) - add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c)); - else - { - /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */ - OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x20); - add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, c | 0x20)); - } - /* Skip the variable-length character. */ - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0); - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); - JUMPHERE(jump[0]); - return cc + 1; - } - else -#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */ - { - GETCHARLEN(c, cc, length); - } - } - else -#endif /* SUPPORT_UNICODE */ - c = *cc; - - if (type == OP_NOT || !char_has_othercase(common, cc)) - { - read_char(common, c, c, backtracks, READ_CHAR_UPDATE_STR_PTR); - add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c)); - } - else - { - oc = char_othercase(common, c); - read_char(common, c < oc ? c : oc, c > oc ? c : oc, backtracks, READ_CHAR_UPDATE_STR_PTR); - bit = c ^ oc; - if (is_powerof2(bit)) - { - OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit); - add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit)); - } - else - { - add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c)); - add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, oc)); - } - } - return cc + length; - - case OP_CLASS: - case OP_NCLASS: - if (check_str_ptr) - detect_partial_match(common, backtracks); - -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 - bit = (common->utf && is_char7_bitset((const sljit_u8 *)cc, type == OP_NCLASS)) ? 127 : 255; - if (type == OP_NCLASS) - read_char(common, 0, bit, backtracks, READ_CHAR_UPDATE_STR_PTR); - else - read_char(common, 0, bit, NULL, 0); -#else - if (type == OP_NCLASS) - read_char(common, 0, 255, backtracks, READ_CHAR_UPDATE_STR_PTR); - else - read_char(common, 0, 255, NULL, 0); -#endif - - if (optimize_class(common, (const sljit_u8 *)cc, type == OP_NCLASS, FALSE, backtracks)) - return cc + 32 / sizeof(PCRE2_UCHAR); - -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 - jump[0] = NULL; - if (common->utf) - { - jump[0] = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, bit); - if (type == OP_CLASS) - { - add_jump(compiler, backtracks, jump[0]); - jump[0] = NULL; - } - } -#elif PCRE2_CODE_UNIT_WIDTH != 8 - jump[0] = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); - if (type == OP_CLASS) - { - add_jump(compiler, backtracks, jump[0]); - jump[0] = NULL; - } -#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 */ - - OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); - OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); - OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc); - OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); - OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, TMP2, 0); - add_jump(compiler, backtracks, JUMP(SLJIT_ZERO)); - -#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8 - if (jump[0] != NULL) - JUMPHERE(jump[0]); -#endif - return cc + 32 / sizeof(PCRE2_UCHAR); - -#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32 - case OP_XCLASS: - if (check_str_ptr) - detect_partial_match(common, backtracks); - compile_xclass_matchingpath(common, cc + LINK_SIZE, backtracks, 0); - return cc + GET(cc, 0) - 1; - - case OP_ECLASS: - if (check_str_ptr) - detect_partial_match(common, backtracks); - return compile_eclass_matchingpath(common, cc, backtracks); -#endif - } -SLJIT_UNREACHABLE(); -return cc; -} - -static SLJIT_INLINE PCRE2_SPTR compile_charn_matchingpath(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, jump_list **backtracks) -{ -/* This function consumes at least one input character. */ -/* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */ -DEFINE_COMPILER; -PCRE2_SPTR ccbegin = cc; -compare_context context; -int size; - -context.length = 0; -do - { - if (cc >= ccend) - break; - - if (*cc == OP_CHAR) - { - size = 1; -#ifdef SUPPORT_UNICODE - if (common->utf && HAS_EXTRALEN(cc[1])) - size += GET_EXTRALEN(cc[1]); -#endif - } - else if (*cc == OP_CHARI) - { - size = 1; -#ifdef SUPPORT_UNICODE - if (common->utf) - { - if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0) - size = 0; - else if (HAS_EXTRALEN(cc[1])) - size += GET_EXTRALEN(cc[1]); - } - else -#endif - if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0) - size = 0; - } - else - size = 0; - - cc += 1 + size; - context.length += IN_UCHARS(size); - } -while (size > 0 && context.length <= 128); - -cc = ccbegin; -if (context.length > 0) - { - /* We have a fixed-length byte sequence. */ - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, context.length); - add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0)); - - context.sourcereg = -1; -#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED - context.ucharptr = 0; -#endif - do cc = byte_sequence_compare(common, *cc == OP_CHARI, cc + 1, &context, backtracks); while (context.length > 0); - return cc; - } - -/* A non-fixed length character will be checked if length == 0. */ -return compile_char1_matchingpath(common, *cc, cc + 1, backtracks, TRUE); -} - - diff --git a/ext/pcre/pcre2lib/pcre2_jit_compile.c b/ext/pcre/pcre2lib/pcre2_jit_compile.c index 7fd10d5eaf390..92f4fb858b108 100644 --- a/ext/pcre/pcre2lib/pcre2_jit_compile.c +++ b/ext/pcre/pcre2lib/pcre2_jit_compile.c @@ -282,14 +282,14 @@ typedef struct bracket_backtrack { struct sljit_label *zero_matchingpath; /* Contains the branches of a failed condition. */ union { - /* Both for OP_COND, OP_SCOND, OP_ASSERT_SCS. */ - jump_list *no_capture; + /* Both for OP_COND, OP_SCOND. */ + jump_list *condfailed; assert_backtrack *assert; /* For OP_ONCE. Less than 0 if not needed. */ int framesize; + /* For brackets with >3 alternatives. */ + struct sljit_jump *matching_mov_addr; } u; - /* For brackets with >3 alternatives. */ - struct sljit_jump *matching_mov_addr; /* Points to our private memory word on the stack. */ int private_data_ptr; } bracket_backtrack; @@ -313,12 +313,14 @@ typedef struct char_iterator_backtrack { backtrack_common common; /* Next iteration. */ struct sljit_label *matchingpath; - /* Creating a range based on the next character. */ - struct { - unsigned int othercasebit; - PCRE2_UCHAR chr; - BOOL charpos_enabled; - } charpos; + union { + jump_list *backtracks; + struct { + unsigned int othercasebit; + PCRE2_UCHAR chr; + BOOL enabled; + } charpos; + } u; } char_iterator_backtrack; typedef struct ref_iterator_backtrack { @@ -406,10 +408,6 @@ typedef struct compiler_common { then_trap_backtrack *then_trap; /* Starting offset of private data for capturing brackets. */ sljit_s32 cbra_ptr; -#if defined SLJIT_DEBUG && SLJIT_DEBUG - /* End offset of locals for assertions. */ - sljit_s32 locals_size; -#endif /* Output vector starting point. Must be divisible by 2. */ sljit_s32 ovector_start; /* Points to the starting character of the current match. */ @@ -431,11 +429,6 @@ typedef struct compiler_common { Each item must have a previous offset and type (see control_types) values. See do_search_mark. */ sljit_s32 control_head_ptr; - /* The offset of the saved STR_END in the outermost - scan substring block. Since scan substring restores - STR_END after a match, it is enough to restore - STR_END inside a scan substring block. */ - sljit_s32 restore_end_ptr; /* Points to the last matched capture block index. */ sljit_s32 capture_last_ptr; /* Fast forward skipping byte code pointer. */ @@ -520,6 +513,7 @@ typedef struct compiler_common { BOOL invalid_utf; BOOL ucp; /* Points to saving area for iref. */ + sljit_s32 iref_ptr; jump_list *getucd; jump_list *getucdtype; #if PCRE2_CODE_UNIT_WIDTH == 8 @@ -609,14 +603,14 @@ typedef struct compare_context { #endif /* Local space layout. */ +/* These two locals can be used by the current opcode. */ +#define LOCALS0 (0 * sizeof(sljit_sw)) +#define LOCALS1 (1 * sizeof(sljit_sw)) +/* Two local variables for possessive quantifiers (char1 cannot use them). */ +#define POSSESSIVE0 (2 * sizeof(sljit_sw)) +#define POSSESSIVE1 (3 * sizeof(sljit_sw)) /* Max limit of recursions. */ -#define LIMIT_MATCH (0 * sizeof(sljit_sw)) -/* Local variables. Their number is computed by check_opcode_types. */ -#define LOCAL0 (1 * sizeof(sljit_sw)) -#define LOCAL1 (2 * sizeof(sljit_sw)) -#define LOCAL2 (3 * sizeof(sljit_sw)) -#define LOCAL3 (4 * sizeof(sljit_sw)) -#define LOCAL4 (5 * sizeof(sljit_sw)) +#define LIMIT_MATCH (4 * sizeof(sljit_sw)) /* The output vector is stored on the stack, and contains pointers to characters. The vector data is divided into two groups: the first group contains the start / end character pointers, and the second is @@ -673,7 +667,7 @@ the start pointers when the end of the capturing group has not yet reached. */ #define GET_LOCAL_BASE(dst, dstw, offset) \ sljit_get_local_base(compiler, (dst), (dstw), (offset)) -#define READ_CHAR_MAX ((sljit_u32)0xffffffff) +#define READ_CHAR_MAX 0x7fffffff #define INVALID_UTF_CHAR -1 #define UNASSIGNED_UTF_CHAR 888 @@ -868,7 +862,7 @@ the start pointers when the end of the capturing group has not yet reached. */ static PCRE2_SPTR bracketend(PCRE2_SPTR cc) { -SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERT_SCS) || (*cc >= OP_ONCE && *cc <= OP_SCOND)); +SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NA) || (*cc >= OP_ONCE && *cc <= OP_SCOND)); do cc += GET(cc, 1); while (*cc == OP_ALT); SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS); cc += 1 + LINK_SIZE; @@ -878,7 +872,7 @@ return cc; static int no_alternatives(PCRE2_SPTR cc) { int count = 0; -SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERT_SCS) || (*cc >= OP_ONCE && *cc <= OP_SCOND)); +SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NA) || (*cc >= OP_ONCE && *cc <= OP_SCOND)); do { cc += GET(cc, 1); @@ -981,7 +975,6 @@ switch(*cc) case OP_ASSERTBACK_NOT: case OP_ASSERT_NA: case OP_ASSERTBACK_NA: - case OP_ASSERT_SCS: case OP_ONCE: case OP_SCRIPT_RUN: case OP_BRA: @@ -1104,9 +1097,7 @@ switch(*cc) return cc + GET(cc, 1 + 2*LINK_SIZE); #if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8 - case OP_ECLASS: case OP_XCLASS: - SLJIT_COMPILE_ASSERT(OP_XCLASS + 1 == OP_ECLASS && OP_CLASS + 1 == OP_NCLASS && OP_NCLASS < OP_XCLASS, class_byte_code_order); return cc + GET(cc, 1); #endif @@ -1123,36 +1114,12 @@ switch(*cc) } } -static sljit_s32 ref_update_local_size(compiler_common *common, PCRE2_SPTR cc, sljit_s32 current_locals_size) -{ -/* Depends on do_casefulcmp(), do_caselesscmp(), and compile_ref_matchingpath() */ -int locals_size = 2 * SSIZE_OF(sw); -SLJIT_UNUSED_ARG(common); - -#ifdef SUPPORT_UNICODE -if ((*cc == OP_REFI || *cc == OP_DNREFI) && (common->utf || common->ucp)) - locals_size = 3 * SSIZE_OF(sw); -#endif - -cc += PRIV(OP_lengths)[*cc]; -/* Although do_casefulcmp() uses only one local, the allocate_stack() -calls during the repeat destroys LOCAL1 variables. */ -if (*cc >= OP_CRSTAR && *cc <= OP_CRPOSRANGE) - locals_size += 2 * SSIZE_OF(sw); - -return (current_locals_size >= locals_size) ? current_locals_size : locals_size; -} - static BOOL check_opcode_types(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend) { int count; PCRE2_SPTR slot; PCRE2_SPTR assert_back_end = cc - 1; PCRE2_SPTR assert_na_end = cc - 1; -sljit_s32 locals_size = 2 * SSIZE_OF(sw); -BOOL set_recursive_head = FALSE; -BOOL set_capture_last = FALSE; -BOOL set_mark = FALSE; /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */ while (cc < ccend) @@ -1165,41 +1132,22 @@ while (cc < ccend) cc += 1; break; - case OP_TYPEUPTO: - case OP_TYPEEXACT: - if (cc[1 + IMM2_SIZE] == OP_EXTUNI && locals_size <= 3 * SSIZE_OF(sw)) - locals_size = 3 * SSIZE_OF(sw); - cc += (2 + IMM2_SIZE) - 1; - break; - - case OP_TYPEPOSSTAR: - case OP_TYPEPOSPLUS: - case OP_TYPEPOSQUERY: - if (cc[1] == OP_EXTUNI && locals_size <= 3 * SSIZE_OF(sw)) - locals_size = 3 * SSIZE_OF(sw); - cc += 2 - 1; - break; - - case OP_TYPEPOSUPTO: -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 - if (common->utf && locals_size <= 3 * SSIZE_OF(sw)) - locals_size = 3 * SSIZE_OF(sw); -#endif - if (cc[1 + IMM2_SIZE] == OP_EXTUNI && locals_size <= 3 * SSIZE_OF(sw)) - locals_size = 3 * SSIZE_OF(sw); - cc += (2 + IMM2_SIZE) - 1; - break; - case OP_REFI: +#ifdef SUPPORT_UNICODE + if (common->iref_ptr == 0) + { + common->iref_ptr = common->ovector_start; + common->ovector_start += 3 * sizeof(sljit_sw); + } +#endif /* SUPPORT_UNICODE */ + /* Fall through. */ case OP_REF: - locals_size = ref_update_local_size(common, cc, locals_size); common->optimized_cbracket[GET2(cc, 1)] = 0; - cc += PRIV(OP_lengths)[*cc]; + cc += 1 + IMM2_SIZE; break; case OP_ASSERT_NA: case OP_ASSERTBACK_NA: - case OP_ASSERT_SCS: slot = bracketend(cc); if (slot > assert_na_end) assert_na_end = slot; @@ -1226,10 +1174,8 @@ while (cc < ccend) cc += 1 + IMM2_SIZE; break; - case OP_DNREFI: case OP_DNREF: - locals_size = ref_update_local_size(common, cc, locals_size); - /* Fall through */ + case OP_DNREFI: case OP_DNCREF: count = GET2(cc, 1 + IMM2_SIZE); slot = common->name_table + GET2(cc, 1) * common->name_entry_size; @@ -1238,18 +1184,26 @@ while (cc < ccend) common->optimized_cbracket[GET2(slot, 0)] = 0; slot += common->name_entry_size; } - cc += PRIV(OP_lengths)[*cc]; + cc += 1 + 2 * IMM2_SIZE; break; case OP_RECURSE: /* Set its value only once. */ - set_recursive_head = TRUE; + if (common->recursive_head_ptr == 0) + { + common->recursive_head_ptr = common->ovector_start; + common->ovector_start += sizeof(sljit_sw); + } cc += 1 + LINK_SIZE; break; case OP_CALLOUT: case OP_CALLOUT_STR: - set_capture_last = TRUE; + if (common->capture_last_ptr == 0) + { + common->capture_last_ptr = common->ovector_start; + common->ovector_start += sizeof(sljit_sw); + } cc += (*cc == OP_CALLOUT) ? PRIV(OP_lengths)[OP_CALLOUT] : GET(cc, 1 + 2*LINK_SIZE); break; @@ -1267,8 +1221,15 @@ while (cc < ccend) case OP_COMMIT_ARG: case OP_PRUNE_ARG: + if (cc < assert_na_end) + return FALSE; + /* Fall through */ case OP_MARK: - set_mark = TRUE; + if (common->mark_ptr == 0) + { + common->mark_ptr = common->ovector_start; + common->ovector_start += sizeof(sljit_sw); + } cc += 1 + 2 + cc[1]; break; @@ -1281,6 +1242,8 @@ while (cc < ccend) case OP_SKIP: if (cc < assert_back_end) common->has_skip_in_assert_back = TRUE; + if (cc < assert_na_end) + return FALSE; cc += 1; break; @@ -1289,31 +1252,19 @@ while (cc < ccend) common->has_skip_arg = TRUE; if (cc < assert_back_end) common->has_skip_in_assert_back = TRUE; + if (cc < assert_na_end) + return FALSE; cc += 1 + 2 + cc[1]; break; + case OP_PRUNE: + case OP_COMMIT: case OP_ASSERT_ACCEPT: if (cc < assert_na_end) return FALSE; cc++; break; -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 - case OP_CRPOSRANGE: - /* The second value can be 0 for infinite repeats. */ - if (common->utf && GET2(cc, 1) != GET2(cc, 1 + IMM2_SIZE) && locals_size <= 3 * SSIZE_OF(sw)) - locals_size = 3 * SSIZE_OF(sw); - cc += 1 + 2 * IMM2_SIZE; - break; - - case OP_POSUPTO: - case OP_POSUPTOI: - case OP_NOTPOSUPTO: - case OP_NOTPOSUPTOI: - if (common->utf && locals_size <= 3 * SSIZE_OF(sw)) - locals_size = 3 * SSIZE_OF(sw); -#endif - /* Fall through */ default: cc = next_opcode(common, cc); if (cc == NULL) @@ -1321,36 +1272,6 @@ while (cc < ccend) break; } } - -SLJIT_ASSERT((locals_size & (SSIZE_OF(sw) - 1)) == 0); -#if defined SLJIT_DEBUG && SLJIT_DEBUG -common->locals_size = locals_size; -#endif - -if (locals_size > 0) - common->ovector_start += locals_size; - -if (set_mark) - { - SLJIT_ASSERT(common->mark_ptr == 0); - common->mark_ptr = common->ovector_start; - common->ovector_start += sizeof(sljit_sw); - } - -if (set_recursive_head) - { - SLJIT_ASSERT(common->recursive_head_ptr == 0); - common->recursive_head_ptr = common->ovector_start; - common->ovector_start += sizeof(sljit_sw); - } - -if (set_capture_last) - { - SLJIT_ASSERT(common->capture_last_ptr == 0); - common->capture_last_ptr = common->ovector_start; - common->ovector_start += sizeof(sljit_sw); - } - return TRUE; } @@ -1591,9 +1512,8 @@ do case OP_NCLASS: #if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8 case OP_XCLASS: - case OP_ECLASS: accelerated_start = cc; - cc += (*cc >= OP_XCLASS) ? GET(cc, 1) : (unsigned int)(1 + (32 / sizeof(PCRE2_UCHAR))); + cc += ((*cc == OP_XCLASS) ? GET(cc, 1) : (unsigned int)(1 + (32 / sizeof(PCRE2_UCHAR)))); #else accelerated_start = cc; cc += (1 + (32 / sizeof(PCRE2_UCHAR))); @@ -1767,7 +1687,7 @@ switch(*cc) if (max == 0) return (*cc == OP_CRRANGE) ? 2 : 1; max -= min; - if (max > (sljit_u32)(*cc == OP_CRRANGE ? 0 : 1)) + if (max > 2) max = 2; return max; @@ -1985,12 +1905,6 @@ while (cc < ccend) bracketlen = 1 + LINK_SIZE; break; - case OP_ASSERT_SCS: - common->private_data_ptrs[cc - common->start] = private_data_ptr; - private_data_ptr += 2 * sizeof(sljit_sw); - bracketlen = 1 + LINK_SIZE; - break; - case OP_CBRAPOS: case OP_SCBRAPOS: common->private_data_ptrs[cc - common->start] = private_data_ptr; @@ -2048,13 +1962,13 @@ while (cc < ccend) CASE_ITERATOR_TYPE_PRIVATE_DATA_2A size = 1; - if (cc[1] != OP_EXTUNI) + if (cc[1] != OP_ANYNL && cc[1] != OP_EXTUNI) space = 2; break; case OP_TYPEUPTO: size = 1 + IMM2_SIZE; - if (cc[1 + IMM2_SIZE] != OP_EXTUNI) + if (cc[1 + IMM2_SIZE] != OP_ANYNL && cc[1 + IMM2_SIZE] != OP_EXTUNI) space = 2; break; @@ -2071,7 +1985,6 @@ while (cc < ccend) #if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8 case OP_XCLASS: - case OP_ECLASS: size = GET(cc, 1); space = get_class_iterator_size(cc + size); break; @@ -2287,7 +2200,6 @@ while (cc < ccend) case OP_CLASS: case OP_NCLASS: case OP_XCLASS: - case OP_ECLASS: case OP_CALLOUT: case OP_CALLOUT_STR: @@ -2330,7 +2242,6 @@ if (ccend == NULL) cc = next_opcode(common, cc); } -/* The data is restored by do_revertframes(). */ SLJIT_ASSERT(cc != NULL); while (cc < ccend) switch(*cc) @@ -2605,13 +2516,6 @@ while (cc < ccend) cc += 1 + LINK_SIZE; break; - case OP_ASSERT_SCS: - SLJIT_ASSERT(PRIVATE_DATA(cc) != 0); - if (recurse_check_bit(common, PRIVATE_DATA(cc))) - length += 2; - cc += 1 + LINK_SIZE; - break; - case OP_CBRA: case OP_SCBRA: offset = GET2(cc, 1 + LINK_SIZE); @@ -2719,8 +2623,7 @@ while (cc < ccend) case OP_NCLASS: #if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8 case OP_XCLASS: - case OP_ECLASS: - size = (*cc >= OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(PCRE2_UCHAR); + size = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(PCRE2_UCHAR); #else size = 1 + 32 / (int)sizeof(PCRE2_UCHAR); #endif @@ -2962,14 +2865,6 @@ while (cc < ccend) cc += 1 + LINK_SIZE; break; - case OP_ASSERT_SCS: - private_srcw[0] = PRIVATE_DATA(cc); - private_srcw[1] = private_srcw[0] + sizeof(sljit_sw); - if (recurse_check_bit(common, private_srcw[0])) - private_count = 2; - cc += 1 + LINK_SIZE; - break; - case OP_CBRA: case OP_SCBRA: offset = GET2(cc, 1 + LINK_SIZE); @@ -3110,8 +3005,7 @@ while (cc < ccend) case OP_NCLASS: #if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8 case OP_XCLASS: - case OP_ECLASS: - i = (*cc >= OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(PCRE2_UCHAR); + i = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(PCRE2_UCHAR); #else i = 1 + 32 / (int)sizeof(PCRE2_UCHAR); #endif @@ -3246,66 +3140,50 @@ static SLJIT_INLINE PCRE2_SPTR set_then_offsets(compiler_common *common, PCRE2_S PCRE2_SPTR end = bracketend(cc); BOOL has_alternatives = cc[GET(cc, 1)] == OP_ALT; -/* Assert captures *THEN verb even if it has no alternatives. */ -if (*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) +/* Assert captures then. */ +if (*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NA) current_offset = NULL; -else if (*cc >= OP_ASSERT_NA && *cc <= OP_ASSERT_SCS) - has_alternatives = TRUE; -/* Conditional block does never capture. */ -else if (*cc == OP_COND || *cc == OP_SCOND) +/* Conditional block does not. */ +if (*cc == OP_COND || *cc == OP_SCOND) has_alternatives = FALSE; cc = next_opcode(common, cc); if (has_alternatives) { - switch (*cc) - { - case OP_REVERSE: - case OP_CREF: - cc += 1 + IMM2_SIZE; - break; - case OP_VREVERSE: - case OP_DNCREF: - cc += 1 + 2 * IMM2_SIZE; - break; - } + if (*cc == OP_REVERSE) + cc += 1 + IMM2_SIZE; + else if (*cc == OP_VREVERSE) + cc += 1 + 2 * IMM2_SIZE; current_offset = common->then_offsets + (cc - common->start); } while (cc < end) { - if (*cc >= OP_ASSERT && *cc <= OP_SCOND) - { + if ((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NA) || (*cc >= OP_ONCE && *cc <= OP_SCOND)) cc = set_then_offsets(common, cc, current_offset); - continue; - } - - if (*cc == OP_ALT && has_alternatives) + else { - cc += 1 + LINK_SIZE; + if (*cc == OP_ALT && has_alternatives) + { + cc += 1 + LINK_SIZE; - if (*cc == OP_REVERSE) - cc += 1 + IMM2_SIZE; - else if (*cc == OP_VREVERSE) - cc += 1 + 2 * IMM2_SIZE; + if (*cc == OP_REVERSE) + cc += 1 + IMM2_SIZE; + else if (*cc == OP_VREVERSE) + cc += 1 + 2 * IMM2_SIZE; - current_offset = common->then_offsets + (cc - common->start); - continue; - } + current_offset = common->then_offsets + (cc - common->start); + continue; + } - if (*cc >= OP_THEN && *cc <= OP_THEN_ARG && current_offset != NULL) - *current_offset = 1; - cc = next_opcode(common, cc); + if (*cc >= OP_THEN && *cc <= OP_THEN_ARG && current_offset != NULL) + *current_offset = 1; + cc = next_opcode(common, cc); + } } -cc = end - 1 - LINK_SIZE; - -/* Ignore repeats. */ -if (*cc == OP_KET && PRIVATE_DATA(cc) != 0) - end += PRIVATE_DATA(cc + 1); - return end; } @@ -3391,12 +3269,8 @@ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * SSIZE_OF(sw)); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345); OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0); -#if defined SLJIT_DEBUG && SLJIT_DEBUG -SLJIT_ASSERT(common->locals_size >= 2 * SSIZE_OF(sw)); -/* These two are also used by the stackalloc calls. */ -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL0, TMP1, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL1, TMP1, 0); -#endif +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, TMP1, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP1, 0); #endif add_stub(common, CMP(SLJIT_LESS, STACK_TOP, 0, STACK_LIMIT, 0)); } @@ -5715,38 +5589,11 @@ if (last) chars->last_count++; } -/* Value can be increased if needed. Patterns -such as /(a|){33}b/ can exhaust the stack. - -Note: /(a|){29}b/ already stops scan_prefix() -because it reaches the maximum step_count. */ -#define SCAN_PREFIX_STACK_END 32 - -/* -Scan prefix stores the prefix string in the chars array. -The elements of the chars array is either small character -sets or "any" (count is set to 255). - -Examples (the chars array is represented by a simple regex): - -/(abc|xbyd)/ prefix: /[ax]b[cy]/ (length: 3) -/a[a-z]b+c/ prefix: a.b (length: 3) -/ab?cd/ prefix: a[bc][cd] (length: 3) -/(ab|cd)|(ef|gh)/ prefix: [aceg][bdfh] (length: 2) - -The length is returned by scan_prefix(). The length is -less than or equal than the minimum length of the pattern. -*/ - -static int scan_prefix(compiler_common *common, PCRE2_SPTR cc, fast_forward_char_data *chars) +static int scan_prefix(compiler_common *common, PCRE2_SPTR cc, fast_forward_char_data *chars, int max_chars, sljit_u32 *rec_count) { -fast_forward_char_data *chars_start = chars; -fast_forward_char_data *chars_end = chars + MAX_N_CHARS; -PCRE2_SPTR cc_stack[SCAN_PREFIX_STACK_END]; -fast_forward_char_data *chars_stack[SCAN_PREFIX_STACK_END]; -sljit_u8 next_alternative_stack[SCAN_PREFIX_STACK_END]; +/* Recursive function, which scans prefix literals. */ BOOL last, any, class, caseless; -int stack_ptr, step_count, repeat, len, len_save; +int len, repeat, len_save, consumed = 0; sljit_u32 chr; /* Any unicode character. */ sljit_u8 *bytes, *bytes_end, byte; PCRE2_SPTR alternative, cc_save, oc; @@ -5759,44 +5606,11 @@ PCRE2_UCHAR othercase[1]; #endif repeat = 1; -stack_ptr = 0; -step_count = 10000; while (TRUE) { - if (--step_count == 0) + if (*rec_count == 0) return 0; - - SLJIT_ASSERT(chars <= chars_start + MAX_N_CHARS); - - if (chars >= chars_end) - { - if (stack_ptr == 0) - return (int)(chars_end - chars_start); - - --stack_ptr; - cc = cc_stack[stack_ptr]; - chars = chars_stack[stack_ptr]; - - if (chars >= chars_end) - continue; - - if (next_alternative_stack[stack_ptr] != 0) - { - /* When an alternative is processed, the - next alternative is pushed onto the stack. */ - SLJIT_ASSERT(*cc == OP_ALT); - alternative = cc + GET(cc, 1); - if (*alternative == OP_ALT) - { - SLJIT_ASSERT(stack_ptr < SCAN_PREFIX_STACK_END); - SLJIT_ASSERT(chars_stack[stack_ptr] == chars); - SLJIT_ASSERT(next_alternative_stack[stack_ptr] == 1); - cc_stack[stack_ptr] = alternative; - stack_ptr++; - } - cc += 1 + LINK_SIZE; - } - } + (*rec_count)--; last = TRUE; any = FALSE; @@ -5836,7 +5650,6 @@ while (TRUE) case OP_ASSERTBACK_NOT: case OP_ASSERT_NA: case OP_ASSERTBACK_NA: - case OP_ASSERT_SCS: cc = bracketend(cc); continue; @@ -5873,17 +5686,9 @@ while (TRUE) #ifdef SUPPORT_UNICODE if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc); #endif - if (stack_ptr >= SCAN_PREFIX_STACK_END) - { - chars_end = chars; - continue; - } - - cc_stack[stack_ptr] = cc + len; - chars_stack[stack_ptr] = chars; - next_alternative_stack[stack_ptr] = 0; - stack_ptr++; - + max_chars = scan_prefix(common, cc + len, chars, max_chars, rec_count); + if (max_chars == 0) + return consumed; last = FALSE; break; @@ -5901,18 +5706,12 @@ while (TRUE) case OP_CBRA: case OP_CBRAPOS: alternative = cc + GET(cc, 1); - if (*alternative == OP_ALT) + while (*alternative == OP_ALT) { - if (stack_ptr >= SCAN_PREFIX_STACK_END) - { - chars_end = chars; - continue; - } - - cc_stack[stack_ptr] = alternative; - chars_stack[stack_ptr] = chars; - next_alternative_stack[stack_ptr] = 1; - stack_ptr++; + max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, max_chars, rec_count); + if (max_chars == 0) + return consumed; + alternative += GET(alternative, 1); } if (*cc == OP_CBRA || *cc == OP_CBRAPOS) @@ -5923,34 +5722,22 @@ while (TRUE) case OP_CLASS: #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 if (common->utf && !is_char7_bitset((const sljit_u8 *)(cc + 1), FALSE)) - { - chars_end = chars; - continue; - } + return consumed; #endif class = TRUE; break; case OP_NCLASS: #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 - if (common->utf) - { - chars_end = chars; - continue; - } + if (common->utf) return consumed; #endif class = TRUE; break; #if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8 case OP_XCLASS: - case OP_ECLASS: #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 - if (common->utf) - { - chars_end = chars; - continue; - } + if (common->utf) return consumed; #endif any = TRUE; cc += GET(cc, 1); @@ -5960,10 +5747,7 @@ while (TRUE) case OP_DIGIT: #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_digit, FALSE)) - { - chars_end = chars; - continue; - } + return consumed; #endif any = TRUE; cc++; @@ -5972,10 +5756,7 @@ while (TRUE) case OP_WHITESPACE: #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_space, FALSE)) - { - chars_end = chars; - continue; - } + return consumed; #endif any = TRUE; cc++; @@ -5984,10 +5765,7 @@ while (TRUE) case OP_WORDCHAR: #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_word, FALSE)) - { - chars_end = chars; - continue; - } + return consumed; #endif any = TRUE; cc++; @@ -6003,11 +5781,7 @@ while (TRUE) case OP_ANY: case OP_ALLANY: #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 - if (common->utf) - { - chars_end = chars; - continue; - } + if (common->utf) return consumed; #endif any = TRUE; cc++; @@ -6017,11 +5791,7 @@ while (TRUE) case OP_NOTPROP: case OP_PROP: #if PCRE2_CODE_UNIT_WIDTH != 32 - if (common->utf) - { - chars_end = chars; - continue; - } + if (common->utf) return consumed; #endif any = TRUE; cc += 1 + 2; @@ -6036,11 +5806,7 @@ while (TRUE) case OP_NOTEXACT: case OP_NOTEXACTI: #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 - if (common->utf) - { - chars_end = chars; - continue; - } + if (common->utf) return consumed; #endif any = TRUE; repeat = GET2(cc, 1); @@ -6048,20 +5814,21 @@ while (TRUE) break; default: - chars_end = chars; - continue; + return consumed; } - SLJIT_ASSERT(chars < chars_end); - if (any) { do { chars->count = 255; + + consumed++; + if (--max_chars == 0) + return consumed; chars++; } - while (--repeat > 0 && chars < chars_end); + while (--repeat > 0); repeat = 1; continue; @@ -6072,27 +5839,17 @@ while (TRUE) bytes = (sljit_u8*) (cc + 1); cc += 1 + 32 / sizeof(PCRE2_UCHAR); - SLJIT_ASSERT(last == TRUE && repeat == 1); switch (*cc) { - case OP_CRQUERY: - case OP_CRMINQUERY: - case OP_CRPOSQUERY: - last = FALSE; - /* Fall through */ case OP_CRSTAR: case OP_CRMINSTAR: case OP_CRPOSSTAR: - if (stack_ptr >= SCAN_PREFIX_STACK_END) - { - chars_end = chars; - continue; - } - - cc_stack[stack_ptr] = ++cc; - chars_stack[stack_ptr] = chars; - next_alternative_stack[stack_ptr] = 0; - stack_ptr++; + case OP_CRQUERY: + case OP_CRMINQUERY: + case OP_CRPOSQUERY: + max_chars = scan_prefix(common, cc + 1, chars, max_chars, rec_count); + if (max_chars == 0) + return consumed; break; default: @@ -6106,13 +5863,7 @@ while (TRUE) case OP_CRPOSRANGE: repeat = GET2(cc, 1); if (repeat <= 0) - { - chars_end = chars; - continue; - } - - last = (repeat != (int)GET2(cc, 1 + IMM2_SIZE)); - cc += 1 + 2 * IMM2_SIZE; + return consumed; break; } @@ -6147,13 +5898,36 @@ while (TRUE) bytes = bytes_end - 32; } + consumed++; + if (--max_chars == 0) + return consumed; chars++; } - while (--repeat > 0 && chars < chars_end); + while (--repeat > 0); + + switch (*cc) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRPOSSTAR: + return consumed; + + case OP_CRQUERY: + case OP_CRMINQUERY: + case OP_CRPOSQUERY: + cc++; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + case OP_CRPOSRANGE: + if (GET2(cc, 1) != GET2(cc, 1 + IMM2_SIZE)) + return consumed; + cc += 1 + 2 * IMM2_SIZE; + break; + } repeat = 1; - if (last) - chars_end = chars; continue; } @@ -6169,10 +5943,7 @@ while (TRUE) { GETCHAR(chr, cc); if ((int)PRIV(ord2utf)(char_othercase(common, chr), othercase) != len) - { - chars_end = chars; - continue; - } + return consumed; } else #endif @@ -6203,6 +5974,7 @@ while (TRUE) do { len--; + consumed++; chr = *cc; add_prefix_char(*cc, chars, len == 0); @@ -6210,13 +5982,15 @@ while (TRUE) if (caseless) add_prefix_char(*oc, chars, len == 0); + if (--max_chars == 0) + return consumed; chars++; cc++; oc++; } - while (len > 0 && chars < chars_end); + while (len > 0); - if (--repeat == 0 || chars >= chars_end) + if (--repeat == 0) break; len = len_save; @@ -6225,7 +5999,7 @@ while (TRUE) repeat = 1; if (last) - chars_end = chars; + return consumed; } } @@ -6395,6 +6169,7 @@ int i, max, from; int range_right = -1, range_len; sljit_u8 *update_table = NULL; BOOL in_range; +sljit_u32 rec_count; for (i = 0; i < MAX_N_CHARS; i++) { @@ -6402,7 +6177,8 @@ for (i = 0; i < MAX_N_CHARS; i++) chars[i].last_count = 0; } -max = scan_prefix(common, common->start, chars); +rec_count = 10000; +max = scan_prefix(common, common->start, chars, MAX_N_CHARS, &rec_count); if (max < 1) return FALSE; @@ -6992,7 +6768,8 @@ jump = JUMP(SLJIT_NOT_ZERO /* SIG_LESS */); OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); JUMPHERE(jump); -OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, TMP2, 0); +OP2(SLJIT_SUB, TMP2, 0, SLJIT_IMM, 0, TMP2, 0); +OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0); if (HAS_VIRTUAL_REGISTERS) { OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -(2 * SSIZE_OF(sw))); @@ -7034,8 +6811,7 @@ struct sljit_jump *jump; SLJIT_UNUSED_ARG(ucp); SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16); -SLJIT_ASSERT(common->locals_size >= 2 * SSIZE_OF(sw)); -sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_SP), LOCAL0); +sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_SP), LOCALS0); /* Get type of the previous char, and put it to TMP3. */ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); @@ -7104,7 +6880,7 @@ JUMPHERE(skipread); OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); check_str_end(common, &skipread_list); -peek_char(common, READ_CHAR_MAX, SLJIT_MEM1(SLJIT_SP), LOCAL1, &invalid_utf2); +peek_char(common, READ_CHAR_MAX, SLJIT_MEM1(SLJIT_SP), LOCALS1, &invalid_utf2); /* Testing char type. This is a code duplication. */ #ifdef SUPPORT_UNICODE @@ -7143,7 +6919,7 @@ else } set_jumps(skipread_list, LABEL()); -OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0); +OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); OP2(SLJIT_XOR | SLJIT_SET_Z, TMP2, 0, TMP2, 0, TMP3, 0); OP_SRC(SLJIT_FAST_RETURN, TMP1, 0); @@ -7152,15 +6928,15 @@ if (common->invalid_utf) { set_jumps(invalid_utf1, LABEL()); - peek_char(common, READ_CHAR_MAX, SLJIT_MEM1(SLJIT_SP), LOCAL1, NULL); + peek_char(common, READ_CHAR_MAX, SLJIT_MEM1(SLJIT_SP), LOCALS1, NULL); CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR, valid_utf); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, -1); OP_SRC(SLJIT_FAST_RETURN, TMP1, 0); set_jumps(invalid_utf2, LABEL()); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); OP1(SLJIT_MOV, TMP2, 0, TMP3, 0); OP_SRC(SLJIT_FAST_RETURN, TMP1, 0); } @@ -7541,9 +7317,7 @@ else char2_reg = RETURN_ADDR; } -/* Update ref_update_local_size() when this changes. */ -SLJIT_ASSERT(common->locals_size >= SSIZE_OF(sw)); -sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_SP), LOCAL0); +sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_SP), LOCALS0); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); if (char1_reg == STR_END) @@ -7562,7 +7336,7 @@ if (sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, JUMPTO(SLJIT_NOT_ZERO, label); JUMPHERE(jump); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); } else if (sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS) { @@ -7577,7 +7351,7 @@ else if (sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_ JUMPTO(SLJIT_NOT_ZERO, label); JUMPHERE(jump); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); } else @@ -7592,7 +7366,7 @@ else JUMPTO(SLJIT_NOT_ZERO, label); JUMPHERE(jump); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); } if (char1_reg == STR_END) @@ -7630,12 +7404,10 @@ if (sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, else if (sljit_emit_mem_update(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS) opt_type = 2; -/* Update ref_update_local_size() when this changes. */ -SLJIT_ASSERT(common->locals_size >= 2 * SSIZE_OF(sw)); -sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_SP), LOCAL0); +sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_SP), LOCALS0); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL1, char1_reg, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, char1_reg, 0); if (char2_reg == STACK_TOP) { @@ -7689,7 +7461,7 @@ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); JUMPTO(SLJIT_NOT_ZERO, label); JUMPHERE(jump); -OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0); +OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); if (opt_type == 2) OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); @@ -7700,253 +7472,1929 @@ if (char2_reg == STACK_TOP) OP1(SLJIT_MOV, lcc_table, 0, RETURN_ADDR, 0); } -OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCAL1); +OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); OP_SRC(SLJIT_FAST_RETURN, TMP1, 0); } -#include "pcre2_jit_char_inc.h" - -static PCRE2_SPTR compile_simple_assertion_matchingpath(compiler_common *common, PCRE2_UCHAR type, PCRE2_SPTR cc, jump_list **backtracks) +static PCRE2_SPTR byte_sequence_compare(compiler_common *common, BOOL caseless, PCRE2_SPTR cc, + compare_context *context, jump_list **backtracks) { DEFINE_COMPILER; -struct sljit_jump *jump[4]; +unsigned int othercasebit = 0; +PCRE2_SPTR othercasechar = NULL; +#ifdef SUPPORT_UNICODE +int utflength; +#endif -switch(type) +if (caseless && char_has_othercase(common, cc)) { - case OP_SOD: - if (HAS_VIRTUAL_REGISTERS) - { - OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); - } + othercasebit = char_get_othercase_bit(common, cc); + SLJIT_ASSERT(othercasebit); + /* Extracting bit difference info. */ +#if PCRE2_CODE_UNIT_WIDTH == 8 + othercasechar = cc + (othercasebit >> 8); + othercasebit &= 0xff; +#elif PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32 + /* Note that this code only handles characters in the BMP. If there + ever are characters outside the BMP whose othercase differs in only one + bit from itself (there currently are none), this code will need to be + revised for PCRE2_CODE_UNIT_WIDTH == 32. */ + othercasechar = cc + (othercasebit >> 9); + if ((othercasebit & 0x100) != 0) + othercasebit = (othercasebit & 0xff) << 8; else - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin)); - add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, TMP1, 0)); - return cc; + othercasebit &= 0xff; +#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */ + } - case OP_SOM: - if (HAS_VIRTUAL_REGISTERS) +if (context->sourcereg == -1) + { +#if PCRE2_CODE_UNIT_WIDTH == 8 +#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED + if (context->length >= 4) + OP1(SLJIT_MOV_S32, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); + else if (context->length >= 2) + OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); + else +#endif + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); +#elif PCRE2_CODE_UNIT_WIDTH == 16 +#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED + if (context->length >= 4) + OP1(SLJIT_MOV_S32, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); + else +#endif + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); +#elif PCRE2_CODE_UNIT_WIDTH == 32 + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); +#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */ + context->sourcereg = TMP2; + } + +#ifdef SUPPORT_UNICODE +utflength = 1; +if (common->utf && HAS_EXTRALEN(*cc)) + utflength += GET_EXTRALEN(*cc); + +do + { +#endif + + context->length -= IN_UCHARS(1); +#if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED) && (PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16) + + /* Unaligned read is supported. */ + if (othercasebit != 0 && othercasechar == cc) + { + context->c.asuchars[context->ucharptr] = *cc | othercasebit; + context->oc.asuchars[context->ucharptr] = othercasebit; + } + else + { + context->c.asuchars[context->ucharptr] = *cc; + context->oc.asuchars[context->ucharptr] = 0; + } + context->ucharptr++; + +#if PCRE2_CODE_UNIT_WIDTH == 8 + if (context->ucharptr >= 4 || context->length == 0 || (context->ucharptr == 2 && context->length == 1)) +#else + if (context->ucharptr >= 2 || context->length == 0) +#endif + { + if (context->length >= 4) + OP1(SLJIT_MOV_S32, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); + else if (context->length >= 2) + OP1(SLJIT_MOV_U16, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); +#if PCRE2_CODE_UNIT_WIDTH == 8 + else if (context->length >= 1) + OP1(SLJIT_MOV_U8, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); +#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */ + context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1; + + switch(context->ucharptr) + { + case 4 / sizeof(PCRE2_UCHAR): + if (context->oc.asint != 0) + OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint)); + break; + + case 2 / sizeof(PCRE2_UCHAR): + if (context->oc.asushort != 0) + OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asushort); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asushort | context->oc.asushort)); + break; + +#if PCRE2_CODE_UNIT_WIDTH == 8 + case 1: + if (context->oc.asbyte != 0) + OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte)); + break; +#endif + + default: + SLJIT_UNREACHABLE(); + break; + } + context->ucharptr = 0; + } + +#else + + /* Unaligned read is unsupported or in 32 bit mode. */ + if (context->length >= 1) + OP1(MOV_UCHAR, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); + + context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1; + + if (othercasebit != 0 && othercasechar == cc) + { + OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit)); + } + else + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc)); + +#endif + + cc++; +#ifdef SUPPORT_UNICODE + utflength--; + } +while (utflength > 0); +#endif + +return cc; +} + +#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8 + +#define SET_CHAR_OFFSET(value) \ + if ((value) != charoffset) \ + { \ + if ((value) < charoffset) \ + OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(charoffset - (value))); \ + else \ + OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)((value) - charoffset)); \ + } \ + charoffset = (value); + +static PCRE2_SPTR compile_char1_matchingpath(compiler_common *common, PCRE2_UCHAR type, PCRE2_SPTR cc, jump_list **backtracks, BOOL check_str_ptr); + +#ifdef SUPPORT_UNICODE +#define XCLASS_SAVE_CHAR 0x001 +#define XCLASS_CHAR_SAVED 0x002 +#define XCLASS_HAS_TYPE 0x004 +#define XCLASS_HAS_SCRIPT 0x008 +#define XCLASS_HAS_SCRIPT_EXTENSION 0x010 +#define XCLASS_HAS_BOOL 0x020 +#define XCLASS_HAS_BIDICL 0x040 +#define XCLASS_NEEDS_UCD (XCLASS_HAS_TYPE | XCLASS_HAS_SCRIPT | XCLASS_HAS_SCRIPT_EXTENSION | XCLASS_HAS_BOOL | XCLASS_HAS_BIDICL) +#define XCLASS_SCRIPT_EXTENSION_NOTPROP 0x080 +#define XCLASS_SCRIPT_EXTENSION_RESTORE_RETURN_ADDR 0x100 +#define XCLASS_SCRIPT_EXTENSION_RESTORE_LOCALS0 0x200 +#endif /* SUPPORT_UNICODE */ + +static void compile_xclass_matchingpath(compiler_common *common, PCRE2_SPTR cc, jump_list **backtracks) +{ +DEFINE_COMPILER; +jump_list *found = NULL; +jump_list **list = (cc[0] & XCL_NOT) == 0 ? &found : backtracks; +sljit_uw c, charoffset, max = 256, min = READ_CHAR_MAX; +struct sljit_jump *jump = NULL; +PCRE2_SPTR ccbegin; +int compares, invertcmp, numberofcmps; +#if defined SUPPORT_UNICODE && (PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16) +BOOL utf = common->utf; +#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == [8|16] */ + +#ifdef SUPPORT_UNICODE +sljit_u32 unicode_status = 0; +sljit_u32 category_list = 0; +sljit_u32 items; +int typereg = TMP1; +const sljit_u32 *other_cases; +#endif /* SUPPORT_UNICODE */ + +/* Scanning the necessary info. */ +cc++; +ccbegin = cc; +compares = 0; + +if (cc[-1] & XCL_MAP) + { + min = 0; + cc += 32 / sizeof(PCRE2_UCHAR); + } + +while (*cc != XCL_END) + { + compares++; + + if (*cc == XCL_SINGLE) + { + cc ++; + GETCHARINCTEST(c, cc); + if (c > max) max = c; + if (c < min) min = c; +#ifdef SUPPORT_UNICODE + unicode_status |= XCLASS_SAVE_CHAR; +#endif /* SUPPORT_UNICODE */ + } + else if (*cc == XCL_RANGE) + { + cc ++; + GETCHARINCTEST(c, cc); + if (c < min) min = c; + GETCHARINCTEST(c, cc); + if (c > max) max = c; +#ifdef SUPPORT_UNICODE + unicode_status |= XCLASS_SAVE_CHAR; +#endif /* SUPPORT_UNICODE */ + } +#ifdef SUPPORT_UNICODE + else + { + SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP); + cc++; + + if (*cc == PT_CLIST && cc[-1] == XCL_PROP) + { + other_cases = PRIV(ucd_caseless_sets) + cc[1]; + while (*other_cases != NOTACHAR) + { + if (*other_cases > max) max = *other_cases; + if (*other_cases < min) min = *other_cases; + other_cases++; + } + } + else + { + max = READ_CHAR_MAX; + min = 0; + } + + items = 0; + + switch(*cc) + { + case PT_ANY: + /* Any either accepts everything or ignored. */ + if (cc[-1] == XCL_PROP) + items = UCPCAT_ALL; + else + compares--; + break; + + case PT_LAMP: + items = UCPCAT3(ucp_Lu, ucp_Ll, ucp_Lt); + break; + + case PT_GC: + items = UCPCAT_RANGE(PRIV(ucp_typerange)[(int)cc[1] * 2], PRIV(ucp_typerange)[(int)cc[1] * 2 + 1]); + break; + + case PT_PC: + items = UCPCAT(cc[1]); + break; + + case PT_WORD: + items = UCPCAT2(ucp_Mn, ucp_Pc) | UCPCAT_L | UCPCAT_N; + break; + + case PT_ALNUM: + items = UCPCAT_L | UCPCAT_N; + break; + + case PT_SCX: + unicode_status |= XCLASS_HAS_SCRIPT_EXTENSION; + if (cc[-1] == XCL_NOTPROP) + { + unicode_status |= XCLASS_SCRIPT_EXTENSION_NOTPROP; + break; + } + compares++; + /* Fall through */ + + case PT_SC: + unicode_status |= XCLASS_HAS_SCRIPT; + break; + + case PT_SPACE: + case PT_PXSPACE: + case PT_PXGRAPH: + case PT_PXPRINT: + case PT_PXPUNCT: + unicode_status |= XCLASS_SAVE_CHAR | XCLASS_HAS_TYPE; + break; + + case PT_CLIST: + case PT_UCNC: + case PT_PXXDIGIT: + unicode_status |= XCLASS_SAVE_CHAR; + break; + + case PT_BOOL: + unicode_status |= XCLASS_HAS_BOOL; + break; + + case PT_BIDICL: + unicode_status |= XCLASS_HAS_BIDICL; + break; + + default: + SLJIT_UNREACHABLE(); + break; + } + + if (items > 0) + { + if (cc[-1] == XCL_NOTPROP) + items ^= UCPCAT_ALL; + category_list |= items; + unicode_status |= XCLASS_HAS_TYPE; + compares--; + } + + cc += 2; + } +#endif /* SUPPORT_UNICODE */ + } + +#ifdef SUPPORT_UNICODE +if (category_list == UCPCAT_ALL) + { + /* All characters are accepted, same as dotall. */ + compile_char1_matchingpath(common, OP_ALLANY, cc, backtracks, FALSE); + if (list == backtracks) + add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); + return; + } + +if (compares == 0 && category_list == 0) + { + /* No characters are accepted, same as (*F) or dotall. */ + compile_char1_matchingpath(common, OP_ALLANY, cc, backtracks, FALSE); + if (list != backtracks) + add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); + return; + } +#else /* !SUPPORT_UNICODE */ +SLJIT_ASSERT(compares > 0); +#endif /* SUPPORT_UNICODE */ + +/* We are not necessary in utf mode even in 8 bit mode. */ +cc = ccbegin; +if ((cc[-1] & XCL_NOT) != 0) + read_char(common, min, max, backtracks, READ_CHAR_UPDATE_STR_PTR); +else + { +#ifdef SUPPORT_UNICODE + read_char(common, min, max, (unicode_status & XCLASS_NEEDS_UCD) ? backtracks : NULL, 0); +#else /* !SUPPORT_UNICODE */ + read_char(common, min, max, NULL, 0); +#endif /* SUPPORT_UNICODE */ + } + +if ((cc[-1] & XCL_HASPROP) == 0) + { + if ((cc[-1] & XCL_MAP) != 0) + { + jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); + if (!optimize_class(common, (const sljit_u8 *)cc, (((const sljit_u8 *)cc)[31] & 0x80) != 0, TRUE, &found)) + { + OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); + OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc); + OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); + OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, TMP2, 0); + add_jump(compiler, &found, JUMP(SLJIT_NOT_ZERO)); + } + + add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); + JUMPHERE(jump); + + cc += 32 / sizeof(PCRE2_UCHAR); + } + else + { + OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, min); + add_jump(compiler, (cc[-1] & XCL_NOT) == 0 ? backtracks : &found, CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, max - min)); + } + } +else if ((cc[-1] & XCL_MAP) != 0) + { + OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0); +#ifdef SUPPORT_UNICODE + unicode_status |= XCLASS_CHAR_SAVED; +#endif /* SUPPORT_UNICODE */ + if (!optimize_class(common, (const sljit_u8 *)cc, FALSE, TRUE, list)) + { +#if PCRE2_CODE_UNIT_WIDTH == 8 + jump = NULL; + if (common->utf) +#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */ + jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); + + OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); + OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc); + OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); + OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, TMP2, 0); + add_jump(compiler, list, JUMP(SLJIT_NOT_ZERO)); + +#if PCRE2_CODE_UNIT_WIDTH == 8 + if (common->utf) +#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */ + JUMPHERE(jump); + } + + OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0); + cc += 32 / sizeof(PCRE2_UCHAR); + } + +#ifdef SUPPORT_UNICODE +if (unicode_status & XCLASS_NEEDS_UCD) + { + if ((unicode_status & (XCLASS_SAVE_CHAR | XCLASS_CHAR_SAVED)) == XCLASS_SAVE_CHAR) + OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0); + +#if PCRE2_CODE_UNIT_WIDTH == 32 + if (!common->utf) + { + jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, MAX_UTF_CODE_POINT + 1); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, UNASSIGNED_UTF_CHAR); + JUMPHERE(jump); + } +#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */ + + OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); + OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); + OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1)); + OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK); + OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); + OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2)); + OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1); + OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 3); + OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2); + OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0); + + ccbegin = cc; + + if (category_list != 0) + compares++; + + if (unicode_status & XCLASS_HAS_BIDICL) + { + OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, scriptx_bidiclass)); + OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BIDICLASS_SHIFT); + + while (*cc != XCL_END) + { + if (*cc == XCL_SINGLE) + { + cc ++; + GETCHARINCTEST(c, cc); + } + else if (*cc == XCL_RANGE) + { + cc ++; + GETCHARINCTEST(c, cc); + GETCHARINCTEST(c, cc); + } + else + { + SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP); + cc++; + if (*cc == PT_BIDICL) + { + compares--; + invertcmp = (compares == 0 && list != backtracks); + if (cc[-1] == XCL_NOTPROP) + invertcmp ^= 0x1; + jump = CMP(SLJIT_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (int)cc[1]); + add_jump(compiler, compares > 0 ? list : backtracks, jump); + } + cc += 2; + } + } + + cc = ccbegin; + } + + if (unicode_status & XCLASS_HAS_BOOL) + { + OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, bprops)); + OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BPROPS_MASK); + OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 2); + + while (*cc != XCL_END) + { + if (*cc == XCL_SINGLE) + { + cc ++; + GETCHARINCTEST(c, cc); + } + else if (*cc == XCL_RANGE) + { + cc ++; + GETCHARINCTEST(c, cc); + GETCHARINCTEST(c, cc); + } + else + { + SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP); + cc++; + if (*cc == PT_BOOL) + { + compares--; + invertcmp = (compares == 0 && list != backtracks); + if (cc[-1] == XCL_NOTPROP) + invertcmp ^= 0x1; + + OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP1), (sljit_sw)(PRIV(ucd_boolprop_sets) + (cc[1] >> 5)), SLJIT_IMM, (sljit_sw)(1u << (cc[1] & 0x1f))); + add_jump(compiler, compares > 0 ? list : backtracks, JUMP(SLJIT_NOT_ZERO ^ invertcmp)); + } + cc += 2; + } + } + + cc = ccbegin; + } + + if (unicode_status & XCLASS_HAS_SCRIPT) + { + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script)); + + while (*cc != XCL_END) + { + if (*cc == XCL_SINGLE) + { + cc ++; + GETCHARINCTEST(c, cc); + } + else if (*cc == XCL_RANGE) + { + cc ++; + GETCHARINCTEST(c, cc); + GETCHARINCTEST(c, cc); + } + else + { + SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP); + cc++; + switch (*cc) + { + case PT_SCX: + if (cc[-1] == XCL_NOTPROP) + break; + /* Fall through */ + + case PT_SC: + compares--; + invertcmp = (compares == 0 && list != backtracks); + if (cc[-1] == XCL_NOTPROP) + invertcmp ^= 0x1; + + add_jump(compiler, compares > 0 ? list : backtracks, CMP(SLJIT_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (int)cc[1])); + } + cc += 2; + } + } + + cc = ccbegin; + } + + if (unicode_status & XCLASS_HAS_SCRIPT_EXTENSION) + { + OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, scriptx_bidiclass)); + OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_SCRIPTX_MASK); + OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 2); + + if (unicode_status & XCLASS_SCRIPT_EXTENSION_NOTPROP) + { + if (unicode_status & XCLASS_HAS_TYPE) + { + if (unicode_status & XCLASS_SAVE_CHAR) + { + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, TMP2, 0); + unicode_status |= XCLASS_SCRIPT_EXTENSION_RESTORE_LOCALS0; + } + else + { + OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP2, 0); + unicode_status |= XCLASS_SCRIPT_EXTENSION_RESTORE_RETURN_ADDR; + } + } + OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script)); + } + + while (*cc != XCL_END) + { + if (*cc == XCL_SINGLE) + { + cc ++; + GETCHARINCTEST(c, cc); + } + else if (*cc == XCL_RANGE) + { + cc ++; + GETCHARINCTEST(c, cc); + GETCHARINCTEST(c, cc); + } + else + { + SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP); + cc++; + if (*cc == PT_SCX) + { + compares--; + invertcmp = (compares == 0 && list != backtracks); + + jump = NULL; + if (cc[-1] == XCL_NOTPROP) + { + jump = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, (int)cc[1]); + if (invertcmp) + { + add_jump(compiler, backtracks, jump); + jump = NULL; + } + invertcmp ^= 0x1; + } + + OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP1), (sljit_sw)(PRIV(ucd_script_sets) + (cc[1] >> 5)), SLJIT_IMM, (sljit_sw)(1u << (cc[1] & 0x1f))); + add_jump(compiler, compares > 0 ? list : backtracks, JUMP(SLJIT_NOT_ZERO ^ invertcmp)); + + if (jump != NULL) + JUMPHERE(jump); + } + cc += 2; + } + } + + if (unicode_status & XCLASS_SCRIPT_EXTENSION_RESTORE_LOCALS0) + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); + else if (unicode_status & XCLASS_SCRIPT_EXTENSION_RESTORE_RETURN_ADDR) + OP1(SLJIT_MOV, TMP2, 0, RETURN_ADDR, 0); + cc = ccbegin; + } + + if (unicode_status & XCLASS_SAVE_CHAR) + OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0); + + if (unicode_status & XCLASS_HAS_TYPE) + { + if (unicode_status & XCLASS_SAVE_CHAR) + typereg = RETURN_ADDR; + + OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype)); + OP2(SLJIT_SHL, typereg, 0, SLJIT_IMM, 1, TMP2, 0); + + if (category_list > 0) + { + compares--; + invertcmp = (compares == 0 && list != backtracks); + OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, category_list); + add_jump(compiler, compares > 0 ? list : backtracks, JUMP(SLJIT_NOT_ZERO ^ invertcmp)); + } + } + } +#endif /* SUPPORT_UNICODE */ + +/* Generating code. */ +charoffset = 0; +numberofcmps = 0; + +while (*cc != XCL_END) + { + compares--; + invertcmp = (compares == 0 && list != backtracks); + jump = NULL; + + if (*cc == XCL_SINGLE) + { + cc ++; + GETCHARINCTEST(c, cc); + + if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE)) + { + OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); + OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_EQUAL); + numberofcmps++; + } + else if (numberofcmps > 0) + { + OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); + OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL); + jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); + numberofcmps = 0; + } + else + { + jump = CMP(SLJIT_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); + numberofcmps = 0; + } + } + else if (*cc == XCL_RANGE) + { + cc ++; + GETCHARINCTEST(c, cc); + SET_CHAR_OFFSET(c); + GETCHARINCTEST(c, cc); + + if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE)) + { + OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); + OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); + numberofcmps++; + } + else if (numberofcmps > 0) + { + OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); + OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL); + jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); + numberofcmps = 0; + } + else + { + jump = CMP(SLJIT_LESS_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); + numberofcmps = 0; + } + } +#ifdef SUPPORT_UNICODE + else + { + SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP); + if (*cc == XCL_NOTPROP) + invertcmp ^= 0x1; + cc++; + switch(*cc) + { + case PT_ANY: + case PT_LAMP: + case PT_GC: + case PT_PC: + case PT_SC: + case PT_SCX: + case PT_BOOL: + case PT_BIDICL: + case PT_WORD: + case PT_ALNUM: + compares++; + /* Already handled. */ + break; + + case PT_SPACE: + case PT_PXSPACE: + SET_CHAR_OFFSET(9); + OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0xd - 0x9); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); + + OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x85 - 0x9); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); + + OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x180e - 0x9); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); + + OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, UCPCAT_RANGE(ucp_Zl, ucp_Zs)); + OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_NOT_ZERO); + jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); + break; + + case PT_CLIST: + other_cases = PRIV(ucd_caseless_sets) + cc[1]; + + /* At least three characters are required. + Otherwise this case would be handled by the normal code path. */ + SLJIT_ASSERT(other_cases[0] != NOTACHAR && other_cases[1] != NOTACHAR && other_cases[2] != NOTACHAR); + SLJIT_ASSERT(other_cases[0] < other_cases[1] && other_cases[1] < other_cases[2]); + + /* Optimizing character pairs, if their difference is power of 2. */ + if (is_powerof2(other_cases[1] ^ other_cases[0])) + { + if (charoffset == 0) + OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]); + else + { + OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)charoffset); + OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]); + } + OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, other_cases[1]); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); + other_cases += 2; + } + else if (is_powerof2(other_cases[2] ^ other_cases[1])) + { + if (charoffset == 0) + OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, other_cases[2] ^ other_cases[1]); + else + { + OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)charoffset); + OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]); + } + OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, other_cases[2]); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); + + OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(other_cases[0] - charoffset)); + OP_FLAGS(SLJIT_OR | ((other_cases[3] == NOTACHAR) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_EQUAL); + + other_cases += 3; + } + else + { + OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset)); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); + } + + while (*other_cases != NOTACHAR) + { + OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset)); + OP_FLAGS(SLJIT_OR | ((*other_cases == NOTACHAR) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_EQUAL); + } + jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); + break; + + case PT_UCNC: + OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_DOLLAR_SIGN - charoffset)); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); + OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_COMMERCIAL_AT - charoffset)); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); + OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_GRAVE_ACCENT - charoffset)); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); + + SET_CHAR_OFFSET(0xa0); + OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, (sljit_sw)(0xd7ff - charoffset)); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); + SET_CHAR_OFFSET(0); + OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xe000 - 0); + OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_GREATER_EQUAL); + jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); + break; + + case PT_PXGRAPH: + OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, UCPCAT_RANGE(ucp_Cc, ucp_Cs) | UCPCAT_RANGE(ucp_Zl, ucp_Zs)); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_NOT_ZERO); + + OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, UCPCAT(ucp_Cf)); + jump = JUMP(SLJIT_ZERO); + + c = charoffset; + /* In case of ucp_Cf, we overwrite the result. */ + SET_CHAR_OFFSET(0x2066); + OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); + + OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); + + OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x180e - 0x2066); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); + + /* Restore charoffset. */ + SET_CHAR_OFFSET(c); + + JUMPHERE(jump); + jump = CMP(SLJIT_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0); + break; + + case PT_PXPRINT: + OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, UCPCAT_RANGE(ucp_Cc, ucp_Cs) | UCPCAT2(ucp_Zl, ucp_Zp)); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_NOT_ZERO); + + OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, UCPCAT(ucp_Cf)); + jump = JUMP(SLJIT_ZERO); + + c = charoffset; + /* In case of ucp_Cf, we overwrite the result. */ + SET_CHAR_OFFSET(0x2066); + OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); + + OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); + + /* Restore charoffset. */ + SET_CHAR_OFFSET(c); + + JUMPHERE(jump); + jump = CMP(SLJIT_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0); + break; + + case PT_PXPUNCT: + OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, UCPCAT_RANGE(ucp_Sc, ucp_So)); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_NOT_ZERO); + + SET_CHAR_OFFSET(0); + OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x7f); + OP_FLAGS(SLJIT_AND, TMP2, 0, SLJIT_LESS_EQUAL); + + OP2U(SLJIT_AND | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, UCPCAT_RANGE(ucp_Pc, ucp_Ps)); + OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_NOT_ZERO); + jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); + break; + + case PT_PXXDIGIT: + SET_CHAR_OFFSET(CHAR_A); + OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, ~0x20); + OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP2, 0, SLJIT_IMM, CHAR_F - CHAR_A); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); + + SET_CHAR_OFFSET(CHAR_0); + OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_9 - CHAR_0); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); + + SET_CHAR_OFFSET(0xff10); + jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 0xff46 - 0xff10); + + OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0xff19 - 0xff10); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); + + SET_CHAR_OFFSET(0xff21); + OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0xff26 - 0xff21); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); + + SET_CHAR_OFFSET(0xff41); + OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0xff46 - 0xff41); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); + + SET_CHAR_OFFSET(0xff10); + + JUMPHERE(jump); + OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, 0); + jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); + break; + + default: + SLJIT_UNREACHABLE(); + break; + } + cc += 2; + } +#endif /* SUPPORT_UNICODE */ + + if (jump != NULL) + add_jump(compiler, compares > 0 ? list : backtracks, jump); + } + +SLJIT_ASSERT(compares == 0); +if (found != NULL) + set_jumps(found, LABEL()); +} + +#undef SET_TYPE_OFFSET +#undef SET_CHAR_OFFSET + +#endif + +static PCRE2_SPTR compile_simple_assertion_matchingpath(compiler_common *common, PCRE2_UCHAR type, PCRE2_SPTR cc, jump_list **backtracks) +{ +DEFINE_COMPILER; +struct sljit_jump *jump[4]; + +switch(type) + { + case OP_SOD: + if (HAS_VIRTUAL_REGISTERS) + { + OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); + } + else + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, TMP1, 0)); + return cc; + + case OP_SOM: + if (HAS_VIRTUAL_REGISTERS) + { + OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); + } + else + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, TMP1, 0)); + return cc; + + case OP_NOT_WORD_BOUNDARY: + case OP_WORD_BOUNDARY: + case OP_NOT_UCP_WORD_BOUNDARY: + case OP_UCP_WORD_BOUNDARY: + add_jump(compiler, (type == OP_NOT_WORD_BOUNDARY || type == OP_WORD_BOUNDARY) ? &common->wordboundary : &common->ucp_wordboundary, JUMP(SLJIT_FAST_CALL)); +#ifdef SUPPORT_UNICODE + if (common->invalid_utf) + { + add_jump(compiler, backtracks, CMP((type == OP_NOT_WORD_BOUNDARY || type == OP_NOT_UCP_WORD_BOUNDARY) ? SLJIT_NOT_EQUAL : SLJIT_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, 0)); + return cc; + } +#endif /* SUPPORT_UNICODE */ + sljit_set_current_flags(compiler, SLJIT_SET_Z); + add_jump(compiler, backtracks, JUMP((type == OP_NOT_WORD_BOUNDARY || type == OP_NOT_UCP_WORD_BOUNDARY) ? SLJIT_NOT_ZERO : SLJIT_ZERO)); + return cc; + + case OP_EODN: + /* Requires rather complex checks. */ + jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + if (common->nltype == NLTYPE_FIXED && common->newline > 255) + { + OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); + if (common->mode == PCRE2_JIT_COMPLETE) + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_END, 0)); + else + { + jump[1] = CMP(SLJIT_EQUAL, TMP2, 0, STR_END, 0); + OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP2, 0, STR_END, 0); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS); + OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); + OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_NOT_EQUAL); + add_jump(compiler, backtracks, JUMP(SLJIT_NOT_EQUAL)); + check_partial(common, TRUE); + add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); + JUMPHERE(jump[1]); + } + OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); + } + else if (common->nltype == NLTYPE_FIXED) + { + OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_END, 0)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline)); + } + else + { + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); + jump[1] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); + OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); + OP2U(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_GREATER, TMP2, 0, STR_END, 0); + jump[2] = JUMP(SLJIT_GREATER); + add_jump(compiler, backtracks, JUMP(SLJIT_NOT_EQUAL) /* LESS */); + /* Equal. */ + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); + jump[3] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); + add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); + + JUMPHERE(jump[1]); + if (common->nltype == NLTYPE_ANYCRLF) + { + OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, STR_END, 0)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL)); + } + else + { + OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0); + read_char(common, common->nlmin, common->nlmax, backtracks, READ_CHAR_UPDATE_STR_PTR); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, STR_END, 0)); + add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); + sljit_set_current_flags(compiler, SLJIT_SET_Z); + add_jump(compiler, backtracks, JUMP(SLJIT_ZERO)); + OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0); + } + JUMPHERE(jump[2]); + JUMPHERE(jump[3]); + } + JUMPHERE(jump[0]); + if (common->mode != PCRE2_JIT_COMPLETE) + check_partial(common, TRUE); + return cc; + + case OP_EOD: + add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0)); + if (common->mode != PCRE2_JIT_COMPLETE) + check_partial(common, TRUE); + return cc; + + case OP_DOLL: + if (HAS_VIRTUAL_REGISTERS) + { + OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); + OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL); + } + else + OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL); + add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO)); + + if (!common->endonly) + compile_simple_assertion_matchingpath(common, OP_EODN, cc, backtracks); + else + { + add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0)); + check_partial(common, FALSE); + } + return cc; + + case OP_DOLLM: + jump[1] = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0); + if (HAS_VIRTUAL_REGISTERS) + { + OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); + OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL); + } + else + OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL); + add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO)); + check_partial(common, FALSE); + jump[0] = JUMP(SLJIT_JUMP); + JUMPHERE(jump[1]); + + if (common->nltype == NLTYPE_FIXED && common->newline > 255) + { + OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); + if (common->mode == PCRE2_JIT_COMPLETE) + add_jump(compiler, backtracks, CMP(SLJIT_GREATER, TMP2, 0, STR_END, 0)); + else + { + jump[1] = CMP(SLJIT_LESS_EQUAL, TMP2, 0, STR_END, 0); + /* STR_PTR = STR_END - IN_UCHARS(1) */ + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); + check_partial(common, TRUE); + add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); + JUMPHERE(jump[1]); + } + + OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); + } + else + { + peek_char(common, common->nlmax, TMP3, 0, NULL); + check_newlinechar(common, common->nltype, backtracks, FALSE); + } + JUMPHERE(jump[0]); + return cc; + + case OP_CIRC: + if (HAS_VIRTUAL_REGISTERS) + { + OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin)); + add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0)); + OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL); + add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO)); + } + else + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin)); + add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0)); + OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL); + add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO)); + } + return cc; + + case OP_CIRCM: + /* TMP2 might be used by peek_char_back. */ + if (HAS_VIRTUAL_REGISTERS) + { + OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); + jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP2, 0); + OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL); + } + else + { + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin)); + jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP2, 0); + OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL); + } + add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO)); + jump[0] = JUMP(SLJIT_JUMP); + JUMPHERE(jump[1]); + + if (!common->alt_circumflex) + add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); + + if (common->nltype == NLTYPE_FIXED && common->newline > 255) + { + OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); + add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, TMP2, 0)); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); + OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); + } + else + { + peek_char_back(common, common->nlmax, backtracks); + check_newlinechar(common, common->nltype, backtracks, FALSE); + } + JUMPHERE(jump[0]); + return cc; + } +SLJIT_UNREACHABLE(); +return cc; +} + +#ifdef SUPPORT_UNICODE + +#if PCRE2_CODE_UNIT_WIDTH != 32 + +/* The code in this function copies the logic of the interpreter function that +is defined in the pcre2_extuni.c source. If that code is updated, this +function, and those below it, must be kept in step (note by PH, June 2024). */ + +static PCRE2_SPTR SLJIT_FUNC do_extuni_utf(jit_arguments *args, PCRE2_SPTR cc) +{ +PCRE2_SPTR start_subject = args->begin; +PCRE2_SPTR end_subject = args->end; +int lgb, rgb, ricount; +PCRE2_SPTR prevcc, endcc, bptr; +BOOL first = TRUE; +BOOL was_ep_ZWJ = FALSE; +uint32_t c; + +prevcc = cc; +endcc = NULL; +do + { + GETCHARINC(c, cc); + rgb = UCD_GRAPHBREAK(c); + + if (first) + { + lgb = rgb; + endcc = cc; + first = FALSE; + continue; + } + + if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) + break; + + /* ZWJ followed by Extended Pictographic is allowed only if the ZWJ was + preceded by Extended Pictographic. */ + + if (lgb == ucp_gbZWJ && rgb == ucp_gbExtended_Pictographic && !was_ep_ZWJ) + break; + + /* Not breaking between Regional Indicators is allowed only if there + are an even number of preceding RIs. */ + + if (lgb == ucp_gbRegional_Indicator && rgb == ucp_gbRegional_Indicator) + { + ricount = 0; + bptr = prevcc; + + /* bptr is pointing to the left-hand character */ + while (bptr > start_subject) + { + bptr--; + BACKCHAR(bptr); + GETCHAR(c, bptr); + + if (UCD_GRAPHBREAK(c) != ucp_gbRegional_Indicator) + break; + + ricount++; + } + + if ((ricount & 1) != 0) break; /* Grapheme break required */ + } + + /* Set a flag when ZWJ follows Extended Pictographic (with optional Extend in + between; see next statement). */ + + was_ep_ZWJ = (lgb == ucp_gbExtended_Pictographic && rgb == ucp_gbZWJ); + + /* If Extend follows Extended_Pictographic, do not update lgb; this allows + any number of them before a following ZWJ. */ + + if (rgb != ucp_gbExtend || lgb != ucp_gbExtended_Pictographic) + lgb = rgb; + + prevcc = endcc; + endcc = cc; + } +while (cc < end_subject); + +return endcc; +} + +#endif /* PCRE2_CODE_UNIT_WIDTH != 32 */ + +/* The code in this function copies the logic of the interpreter function that +is defined in the pcre2_extuni.c source. If that code is updated, this +function, and the one below it, must be kept in step (note by PH, June 2024). */ + +static PCRE2_SPTR SLJIT_FUNC do_extuni_utf_invalid(jit_arguments *args, PCRE2_SPTR cc) +{ +PCRE2_SPTR start_subject = args->begin; +PCRE2_SPTR end_subject = args->end; +int lgb, rgb, ricount; +PCRE2_SPTR prevcc, endcc, bptr; +BOOL first = TRUE; +BOOL was_ep_ZWJ = FALSE; +uint32_t c; + +prevcc = cc; +endcc = NULL; +do + { + GETCHARINC_INVALID(c, cc, end_subject, break); + rgb = UCD_GRAPHBREAK(c); + + if (first) + { + lgb = rgb; + endcc = cc; + first = FALSE; + continue; + } + + if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) + break; + + /* ZWJ followed by Extended Pictographic is allowed only if the ZWJ was + preceded by Extended Pictographic. */ + + if (lgb == ucp_gbZWJ && rgb == ucp_gbExtended_Pictographic && !was_ep_ZWJ) + break; + + /* Not breaking between Regional Indicators is allowed only if there + are an even number of preceding RIs. */ + + if (lgb == ucp_gbRegional_Indicator && rgb == ucp_gbRegional_Indicator) + { + ricount = 0; + bptr = prevcc; + + /* bptr is pointing to the left-hand character */ + while (bptr > start_subject) + { + GETCHARBACK_INVALID(c, bptr, start_subject, break); + + if (UCD_GRAPHBREAK(c) != ucp_gbRegional_Indicator) + break; + + ricount++; + } + + if ((ricount & 1) != 0) + break; /* Grapheme break required */ + } + + /* Set a flag when ZWJ follows Extended Pictographic (with optional Extend in + between; see next statement). */ + + was_ep_ZWJ = (lgb == ucp_gbExtended_Pictographic && rgb == ucp_gbZWJ); + + /* If Extend follows Extended_Pictographic, do not update lgb; this allows + any number of them before a following ZWJ. */ + + if (rgb != ucp_gbExtend || lgb != ucp_gbExtended_Pictographic) + lgb = rgb; + + prevcc = endcc; + endcc = cc; + } +while (cc < end_subject); + +return endcc; +} + +/* The code in this function copies the logic of the interpreter function that +is defined in the pcre2_extuni.c source. If that code is updated, this +function must be kept in step (note by PH, June 2024). */ + +static PCRE2_SPTR SLJIT_FUNC do_extuni_no_utf(jit_arguments *args, PCRE2_SPTR cc) +{ +PCRE2_SPTR start_subject = args->begin; +PCRE2_SPTR end_subject = args->end; +int lgb, rgb, ricount; +PCRE2_SPTR bptr; +uint32_t c; +BOOL was_ep_ZWJ = FALSE; + +/* Patch by PH */ +/* GETCHARINC(c, cc); */ +c = *cc++; + +#if PCRE2_CODE_UNIT_WIDTH == 32 +if (c >= 0x110000) + return cc; +#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */ +lgb = UCD_GRAPHBREAK(c); + +while (cc < end_subject) + { + c = *cc; +#if PCRE2_CODE_UNIT_WIDTH == 32 + if (c >= 0x110000) + break; +#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */ + rgb = UCD_GRAPHBREAK(c); + + if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) + break; + + /* ZWJ followed by Extended Pictographic is allowed only if the ZWJ was + preceded by Extended Pictographic. */ + + if (lgb == ucp_gbZWJ && rgb == ucp_gbExtended_Pictographic && !was_ep_ZWJ) + break; + + /* Not breaking between Regional Indicators is allowed only if there + are an even number of preceding RIs. */ + + if (lgb == ucp_gbRegional_Indicator && rgb == ucp_gbRegional_Indicator) + { + ricount = 0; + bptr = cc - 1; + + /* bptr is pointing to the left-hand character */ + while (bptr > start_subject) + { + bptr--; + c = *bptr; +#if PCRE2_CODE_UNIT_WIDTH == 32 + if (c >= 0x110000) + break; +#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */ + + if (UCD_GRAPHBREAK(c) != ucp_gbRegional_Indicator) break; + + ricount++; + } + + if ((ricount & 1) != 0) + break; /* Grapheme break required */ + } + + /* Set a flag when ZWJ follows Extended Pictographic (with optional Extend in + between; see next statement). */ + + was_ep_ZWJ = (lgb == ucp_gbExtended_Pictographic && rgb == ucp_gbZWJ); + + /* If Extend follows Extended_Pictographic, do not update lgb; this allows + any number of them before a following ZWJ. */ + + if (rgb != ucp_gbExtend || lgb != ucp_gbExtended_Pictographic) + lgb = rgb; + + cc++; + } + +return cc; +} + +#endif /* SUPPORT_UNICODE */ + +static PCRE2_SPTR compile_char1_matchingpath(compiler_common *common, PCRE2_UCHAR type, PCRE2_SPTR cc, jump_list **backtracks, BOOL check_str_ptr) +{ +DEFINE_COMPILER; +int length; +unsigned int c, oc, bit; +compare_context context; +struct sljit_jump *jump[3]; +jump_list *end_list; +#ifdef SUPPORT_UNICODE +PCRE2_UCHAR propdata[5]; +#endif /* SUPPORT_UNICODE */ + +switch(type) + { + case OP_NOT_DIGIT: + case OP_DIGIT: + /* Digits are usually 0-9, so it is worth to optimize them. */ + if (check_str_ptr) + detect_partial_match(common, backtracks); +#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 + if (common->utf && is_char7_bitset((const sljit_u8*)common->ctypes - cbit_length + cbit_digit, FALSE)) + read_char7_type(common, backtracks, type == OP_NOT_DIGIT); + else +#endif + read_char8_type(common, backtracks, type == OP_NOT_DIGIT); + /* Flip the starting bit in the negative case. */ + OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, ctype_digit); + add_jump(compiler, backtracks, JUMP(type == OP_DIGIT ? SLJIT_ZERO : SLJIT_NOT_ZERO)); + return cc; + + case OP_NOT_WHITESPACE: + case OP_WHITESPACE: + if (check_str_ptr) + detect_partial_match(common, backtracks); +#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 + if (common->utf && is_char7_bitset((const sljit_u8*)common->ctypes - cbit_length + cbit_space, FALSE)) + read_char7_type(common, backtracks, type == OP_NOT_WHITESPACE); + else +#endif + read_char8_type(common, backtracks, type == OP_NOT_WHITESPACE); + OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, ctype_space); + add_jump(compiler, backtracks, JUMP(type == OP_WHITESPACE ? SLJIT_ZERO : SLJIT_NOT_ZERO)); + return cc; + + case OP_NOT_WORDCHAR: + case OP_WORDCHAR: + if (check_str_ptr) + detect_partial_match(common, backtracks); +#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 + if (common->utf && is_char7_bitset((const sljit_u8*)common->ctypes - cbit_length + cbit_word, FALSE)) + read_char7_type(common, backtracks, type == OP_NOT_WORDCHAR); + else +#endif + read_char8_type(common, backtracks, type == OP_NOT_WORDCHAR); + OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, ctype_word); + add_jump(compiler, backtracks, JUMP(type == OP_WORDCHAR ? SLJIT_ZERO : SLJIT_NOT_ZERO)); + return cc; + + case OP_ANY: + if (check_str_ptr) + detect_partial_match(common, backtracks); + read_char(common, common->nlmin, common->nlmax, backtracks, READ_CHAR_UPDATE_STR_PTR); + if (common->nltype == NLTYPE_FIXED && common->newline > 255) { - OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); + jump[0] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); + end_list = NULL; + if (common->mode != PCRE2_JIT_PARTIAL_HARD) + add_jump(compiler, &end_list, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); + else + check_str_end(common, &end_list); + + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff)); + set_jumps(end_list, LABEL()); + JUMPHERE(jump[0]); } else - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str)); - add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, TMP1, 0)); + check_newlinechar(common, common->nltype, backtracks, TRUE); return cc; - case OP_NOT_WORD_BOUNDARY: - case OP_WORD_BOUNDARY: - case OP_NOT_UCP_WORD_BOUNDARY: - case OP_UCP_WORD_BOUNDARY: - add_jump(compiler, (type == OP_NOT_WORD_BOUNDARY || type == OP_WORD_BOUNDARY) ? &common->wordboundary : &common->ucp_wordboundary, JUMP(SLJIT_FAST_CALL)); + case OP_ALLANY: + if (check_str_ptr) + detect_partial_match(common, backtracks); #ifdef SUPPORT_UNICODE - if (common->invalid_utf) + if (common->utf && common->invalid_utf) { - add_jump(compiler, backtracks, CMP((type == OP_NOT_WORD_BOUNDARY || type == OP_NOT_UCP_WORD_BOUNDARY) ? SLJIT_NOT_EQUAL : SLJIT_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, 0)); + read_char(common, 0, READ_CHAR_MAX, backtracks, READ_CHAR_UPDATE_STR_PTR); return cc; } #endif /* SUPPORT_UNICODE */ + + skip_valid_char(common); + return cc; + + case OP_ANYBYTE: + if (check_str_ptr) + detect_partial_match(common, backtracks); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + return cc; + +#ifdef SUPPORT_UNICODE + case OP_NOTPROP: + case OP_PROP: + propdata[0] = XCL_HASPROP; + propdata[1] = type == OP_NOTPROP ? XCL_NOTPROP : XCL_PROP; + propdata[2] = cc[0]; + propdata[3] = cc[1]; + propdata[4] = XCL_END; + if (check_str_ptr) + detect_partial_match(common, backtracks); + compile_xclass_matchingpath(common, propdata, backtracks); + return cc + 2; +#endif + + case OP_ANYNL: + if (check_str_ptr) + detect_partial_match(common, backtracks); + read_char(common, common->bsr_nlmin, common->bsr_nlmax, NULL, 0); + jump[0] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); + /* We don't need to handle soft partial matching case. */ + end_list = NULL; + if (common->mode != PCRE2_JIT_PARTIAL_HARD) + add_jump(compiler, &end_list, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); + else + check_str_end(common, &end_list); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); + jump[1] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + jump[2] = JUMP(SLJIT_JUMP); + JUMPHERE(jump[0]); + check_newlinechar(common, common->bsr_nltype, backtracks, FALSE); + set_jumps(end_list, LABEL()); + JUMPHERE(jump[1]); + JUMPHERE(jump[2]); + return cc; + + case OP_NOT_HSPACE: + case OP_HSPACE: + if (check_str_ptr) + detect_partial_match(common, backtracks); + + if (type == OP_NOT_HSPACE) + read_char(common, 0x9, 0x3000, backtracks, READ_CHAR_UPDATE_STR_PTR); + else + read_char(common, 0x9, 0x3000, NULL, 0); + + add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL)); sljit_set_current_flags(compiler, SLJIT_SET_Z); - add_jump(compiler, backtracks, JUMP((type == OP_NOT_WORD_BOUNDARY || type == OP_NOT_UCP_WORD_BOUNDARY) ? SLJIT_NOT_ZERO : SLJIT_ZERO)); + add_jump(compiler, backtracks, JUMP(type == OP_NOT_HSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO)); return cc; - case OP_EODN: - /* Requires rather complex checks. */ - jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); - if (common->nltype == NLTYPE_FIXED && common->newline > 255) - { - OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); - if (common->mode == PCRE2_JIT_COMPLETE) - add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_END, 0)); - else - { - jump[1] = CMP(SLJIT_EQUAL, TMP2, 0, STR_END, 0); - OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP2, 0, STR_END, 0); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS); - OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); - OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_NOT_EQUAL); - add_jump(compiler, backtracks, JUMP(SLJIT_NOT_EQUAL)); - check_partial(common, TRUE); - add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); - JUMPHERE(jump[1]); - } - OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); - add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); - add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); - } - else if (common->nltype == NLTYPE_FIXED) - { - OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); - add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_END, 0)); - add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline)); - } + case OP_NOT_VSPACE: + case OP_VSPACE: + if (check_str_ptr) + detect_partial_match(common, backtracks); + + if (type == OP_NOT_VSPACE) + read_char(common, 0xa, 0x2029, backtracks, READ_CHAR_UPDATE_STR_PTR); else - { - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); - jump[1] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); - OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); - OP2U(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_GREATER, TMP2, 0, STR_END, 0); - jump[2] = JUMP(SLJIT_GREATER); - add_jump(compiler, backtracks, JUMP(SLJIT_NOT_EQUAL) /* LESS */); - /* Equal. */ - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); - jump[3] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); - add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); + read_char(common, 0xa, 0x2029, NULL, 0); - JUMPHERE(jump[1]); - if (common->nltype == NLTYPE_ANYCRLF) - { - OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, STR_END, 0)); - add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL)); - } - else - { - OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0); - read_char(common, common->nlmin, common->nlmax, backtracks, READ_CHAR_UPDATE_STR_PTR); - add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, STR_END, 0)); - add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); - sljit_set_current_flags(compiler, SLJIT_SET_Z); - add_jump(compiler, backtracks, JUMP(SLJIT_ZERO)); - OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0); - } - JUMPHERE(jump[2]); - JUMPHERE(jump[3]); - } - JUMPHERE(jump[0]); - if (common->mode != PCRE2_JIT_COMPLETE) - check_partial(common, TRUE); + add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL)); + sljit_set_current_flags(compiler, SLJIT_SET_Z); + add_jump(compiler, backtracks, JUMP(type == OP_NOT_VSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO)); return cc; - case OP_EOD: - add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0)); - if (common->mode != PCRE2_JIT_COMPLETE) +#ifdef SUPPORT_UNICODE + case OP_EXTUNI: + if (check_str_ptr) + detect_partial_match(common, backtracks); + + SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1); + OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0); + +#if PCRE2_CODE_UNIT_WIDTH != 32 + sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM, + common->utf ? (common->invalid_utf ? SLJIT_FUNC_ADDR(do_extuni_utf_invalid) : SLJIT_FUNC_ADDR(do_extuni_utf)) : SLJIT_FUNC_ADDR(do_extuni_no_utf)); + if (common->invalid_utf) + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0)); +#else + sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM, + common->invalid_utf ? SLJIT_FUNC_ADDR(do_extuni_utf_invalid) : SLJIT_FUNC_ADDR(do_extuni_no_utf)); + if (common->invalid_utf) + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0)); +#endif + + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0); + + if (common->mode == PCRE2_JIT_PARTIAL_HARD) + { + jump[0] = CMP(SLJIT_LESS, SLJIT_RETURN_REG, 0, STR_END, 0); + /* Since we successfully read a char above, partial matching must occure. */ check_partial(common, TRUE); + JUMPHERE(jump[0]); + } return cc; +#endif - case OP_DOLL: - if (HAS_VIRTUAL_REGISTERS) + case OP_CHAR: + case OP_CHARI: + length = 1; +#ifdef SUPPORT_UNICODE + if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc); +#endif + + if (check_str_ptr && common->mode != PCRE2_JIT_COMPLETE) + detect_partial_match(common, backtracks); + + if (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0) { - OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); - OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); + if (length > 1 || (check_str_ptr && common->mode == PCRE2_JIT_COMPLETE)) + add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0)); + + context.length = IN_UCHARS(length); + context.sourcereg = -1; +#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED + context.ucharptr = 0; +#endif + return byte_sequence_compare(common, type == OP_CHARI, cc, &context, backtracks); } - else - OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL); - add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO)); - if (!common->endonly) - compile_simple_assertion_matchingpath(common, OP_EODN, cc, backtracks); - else +#ifdef SUPPORT_UNICODE + if (common->utf) { - add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0)); - check_partial(common, FALSE); + GETCHAR(c, cc); } - return cc; + else +#endif + c = *cc; - case OP_DOLLM: - jump[1] = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0); - if (HAS_VIRTUAL_REGISTERS) + SLJIT_ASSERT(type == OP_CHARI && char_has_othercase(common, cc)); + + if (check_str_ptr && common->mode == PCRE2_JIT_COMPLETE) + add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); + + oc = char_othercase(common, c); + read_char(common, c < oc ? c : oc, c > oc ? c : oc, NULL, 0); + + SLJIT_ASSERT(!is_powerof2(c ^ oc)); + + if (sljit_has_cpu_feature(SLJIT_HAS_CMOV)) { - OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); - OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL); + OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, oc); + SELECT(SLJIT_EQUAL, TMP1, SLJIT_IMM, c, TMP1); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c)); } else - OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL); - add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO)); - check_partial(common, FALSE); - jump[0] = JUMP(SLJIT_JUMP); - JUMPHERE(jump[1]); + { + jump[0] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c); + add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, oc)); + JUMPHERE(jump[0]); + } + return cc + length; - if (common->nltype == NLTYPE_FIXED && common->newline > 255) + case OP_NOT: + case OP_NOTI: + if (check_str_ptr) + detect_partial_match(common, backtracks); + + length = 1; +#ifdef SUPPORT_UNICODE + if (common->utf) { - OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); - if (common->mode == PCRE2_JIT_COMPLETE) - add_jump(compiler, backtracks, CMP(SLJIT_GREATER, TMP2, 0, STR_END, 0)); - else +#if PCRE2_CODE_UNIT_WIDTH == 8 + c = *cc; + if (c < 128 && !common->invalid_utf) { - jump[1] = CMP(SLJIT_LESS_EQUAL, TMP2, 0, STR_END, 0); - /* STR_PTR = STR_END - IN_UCHARS(1) */ - add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); - check_partial(common, TRUE); - add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); - JUMPHERE(jump[1]); + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); + if (type == OP_NOT || !char_has_othercase(common, cc)) + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c)); + else + { + /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */ + OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x20); + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, c | 0x20)); + } + /* Skip the variable-length character. */ + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); + JUMPHERE(jump[0]); + return cc + 1; + } + else +#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */ + { + GETCHARLEN(c, cc, length); } - - OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); - add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); - add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); - } - else - { - peek_char(common, common->nlmax, TMP3, 0, NULL); - check_newlinechar(common, common->nltype, backtracks, FALSE); } - JUMPHERE(jump[0]); - return cc; + else +#endif /* SUPPORT_UNICODE */ + c = *cc; - case OP_CIRC: - if (HAS_VIRTUAL_REGISTERS) + if (type == OP_NOT || !char_has_othercase(common, cc)) { - OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin)); - add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0)); - OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL); - add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO)); + read_char(common, c, c, backtracks, READ_CHAR_UPDATE_STR_PTR); + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c)); } else { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin)); - add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0)); - OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL); - add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO)); + oc = char_othercase(common, c); + read_char(common, c < oc ? c : oc, c > oc ? c : oc, backtracks, READ_CHAR_UPDATE_STR_PTR); + bit = c ^ oc; + if (is_powerof2(bit)) + { + OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit); + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit)); + } + else + { + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c)); + add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, oc)); + } } - return cc; + return cc + length; - case OP_CIRCM: - /* TMP2 might be used by peek_char_back. */ - if (HAS_VIRTUAL_REGISTERS) + case OP_CLASS: + case OP_NCLASS: + if (check_str_ptr) + detect_partial_match(common, backtracks); + +#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 + bit = (common->utf && is_char7_bitset((const sljit_u8 *)cc, type == OP_NCLASS)) ? 127 : 255; + if (type == OP_NCLASS) + read_char(common, 0, bit, backtracks, READ_CHAR_UPDATE_STR_PTR); + else + read_char(common, 0, bit, NULL, 0); +#else + if (type == OP_NCLASS) + read_char(common, 0, 255, backtracks, READ_CHAR_UPDATE_STR_PTR); + else + read_char(common, 0, 255, NULL, 0); +#endif + + if (optimize_class(common, (const sljit_u8 *)cc, type == OP_NCLASS, FALSE, backtracks)) + return cc + 32 / sizeof(PCRE2_UCHAR); + +#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 + jump[0] = NULL; + if (common->utf) { - OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); - jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP2, 0); - OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL); + jump[0] = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, bit); + if (type == OP_CLASS) + { + add_jump(compiler, backtracks, jump[0]); + jump[0] = NULL; + } } - else +#elif PCRE2_CODE_UNIT_WIDTH != 8 + jump[0] = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); + if (type == OP_CLASS) { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin)); - jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP2, 0); - OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL); + add_jump(compiler, backtracks, jump[0]); + jump[0] = NULL; } - add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO)); - jump[0] = JUMP(SLJIT_JUMP); - JUMPHERE(jump[1]); +#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 */ - if (!common->alt_circumflex) - add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); + OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); + OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc); + OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); + OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, TMP2, 0); + add_jump(compiler, backtracks, JUMP(SLJIT_ZERO)); - if (common->nltype == NLTYPE_FIXED && common->newline > 255) +#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8 + if (jump[0] != NULL) + JUMPHERE(jump[0]); +#endif + return cc + 32 / sizeof(PCRE2_UCHAR); + +#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32 + case OP_XCLASS: + if (check_str_ptr) + detect_partial_match(common, backtracks); + compile_xclass_matchingpath(common, cc + LINK_SIZE, backtracks); + return cc + GET(cc, 0) - 1; +#endif + } +SLJIT_UNREACHABLE(); +return cc; +} + +static SLJIT_INLINE PCRE2_SPTR compile_charn_matchingpath(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, jump_list **backtracks) +{ +/* This function consumes at least one input character. */ +/* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */ +DEFINE_COMPILER; +PCRE2_SPTR ccbegin = cc; +compare_context context; +int size; + +context.length = 0; +do + { + if (cc >= ccend) + break; + + if (*cc == OP_CHAR) { - OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); - add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, TMP2, 0)); - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); - OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); - add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); - add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); + size = 1; +#ifdef SUPPORT_UNICODE + if (common->utf && HAS_EXTRALEN(cc[1])) + size += GET_EXTRALEN(cc[1]); +#endif } - else + else if (*cc == OP_CHARI) { - peek_char_back(common, common->nlmax, backtracks); - check_newlinechar(common, common->nltype, backtracks, FALSE); + size = 1; +#ifdef SUPPORT_UNICODE + if (common->utf) + { + if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0) + size = 0; + else if (HAS_EXTRALEN(cc[1])) + size += GET_EXTRALEN(cc[1]); + } + else +#endif + if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0) + size = 0; } - JUMPHERE(jump[0]); + else + size = 0; + + cc += 1 + size; + context.length += IN_UCHARS(size); + } +while (size > 0 && context.length <= 128); + +cc = ccbegin; +if (context.length > 0) + { + /* We have a fixed-length byte sequence. */ + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, context.length); + add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0)); + + context.sourcereg = -1; +#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED + context.ucharptr = 0; +#endif + do cc = byte_sequence_compare(common, *cc == OP_CHARI, cc + 1, &context, backtracks); while (context.length > 0); return cc; } -SLJIT_UNREACHABLE(); -return cc; + +/* A non-fixed length character will be checked if length == 0. */ +return compile_char1_matchingpath(common, *cc, cc + 1, backtracks, TRUE); } /* Forward definitions. */ @@ -8022,16 +9470,10 @@ struct sljit_jump *nopartial; #if defined SUPPORT_UNICODE struct sljit_label *loop; struct sljit_label *caseless_loop; -struct sljit_jump *turkish_ascii_i = NULL; -struct sljit_jump *turkish_non_ascii_i = NULL; jump_list *no_match = NULL; int source_reg = COUNT_MATCH; int source_end_reg = ARGUMENTS; int char1_reg = STACK_LIMIT; -PCRE2_UCHAR refi_flag = 0; - -if (*cc == OP_REFI || *cc == OP_DNREFI) - refi_flag = cc[PRIV(OP_lengths)[*cc] - 1]; #endif /* SUPPORT_UNICODE */ if (ref) @@ -8046,10 +9488,9 @@ else OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0); #if defined SUPPORT_UNICODE -if ((common->utf || common->ucp) && (*cc == OP_REFI || *cc == OP_DNREFI)) +if (common->utf && *cc == OP_REFI) { - /* Update ref_update_local_size() when this changes. */ - SLJIT_ASSERT(common->locals_size >= 3 * SSIZE_OF(sw)); + SLJIT_ASSERT(common->iref_ptr != 0); if (ref) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); @@ -8059,9 +9500,9 @@ if ((common->utf || common->ucp) && (*cc == OP_REFI || *cc == OP_DNREFI)) if (withchecks && emptyfail) add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, TMP2, 0)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL0, source_reg, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL1, source_end_reg, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL2, char1_reg, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->iref_ptr, source_reg, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw), source_end_reg, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw) * 2, char1_reg, 0); OP1(SLJIT_MOV, source_reg, 0, TMP1, 0); OP1(SLJIT_MOV, source_end_reg, 0, TMP2, 0); @@ -8085,16 +9526,6 @@ if ((common->utf || common->ucp) && (*cc == OP_REFI || *cc == OP_DNREFI)) CMPTO(SLJIT_EQUAL, TMP1, 0, char1_reg, 0, loop); - if ((refi_flag & (REFI_FLAG_TURKISH_CASING|REFI_FLAG_CASELESS_RESTRICT)) == - REFI_FLAG_TURKISH_CASING) - { - OP2(SLJIT_OR, SLJIT_TMP_DEST_REG, 0, char1_reg, 0, SLJIT_IMM, 0x20); - turkish_ascii_i = CMP(SLJIT_EQUAL, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 0x69); - - OP2(SLJIT_OR, SLJIT_TMP_DEST_REG, 0, char1_reg, 0, SLJIT_IMM, 0x1); - turkish_non_ascii_i = CMP(SLJIT_EQUAL, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 0x131); - } - OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); @@ -8114,9 +9545,6 @@ if ((common->utf || common->ucp) && (*cc == OP_REFI || *cc == OP_DNREFI)) OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2); OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_caseless_sets)); - if (refi_flag & REFI_FLAG_CASELESS_RESTRICT) - add_jump(compiler, &no_match, CMP(SLJIT_LESS | SLJIT_32, SLJIT_MEM1(TMP2), 0, SLJIT_IMM, 128)); - caseless_loop = LABEL(); OP1(SLJIT_MOV_U32, TMP1, 0, SLJIT_MEM1(TMP2), 0); OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, sizeof(uint32_t)); @@ -8124,52 +9552,30 @@ if ((common->utf || common->ucp) && (*cc == OP_REFI || *cc == OP_DNREFI)) JUMPTO(SLJIT_EQUAL, loop); JUMPTO(SLJIT_LESS, caseless_loop); - if ((refi_flag & (REFI_FLAG_TURKISH_CASING|REFI_FLAG_CASELESS_RESTRICT)) == - REFI_FLAG_TURKISH_CASING) - { - add_jump(compiler, &no_match, JUMP(SLJIT_JUMP)); - JUMPHERE(turkish_ascii_i); - - OP2(SLJIT_LSHR, char1_reg, 0, char1_reg, 0, SLJIT_IMM, 5); - OP2(SLJIT_AND, char1_reg, 0, char1_reg, 0, SLJIT_IMM, 1); - OP2(SLJIT_XOR, char1_reg, 0, char1_reg, 0, SLJIT_IMM, 1); - OP2(SLJIT_ADD, char1_reg, 0, char1_reg, 0, SLJIT_IMM, 0x130); - CMPTO(SLJIT_EQUAL, TMP1, 0, char1_reg, 0, loop); - - add_jump(compiler, &no_match, JUMP(SLJIT_JUMP)); - JUMPHERE(turkish_non_ascii_i); - - OP2(SLJIT_AND, char1_reg, 0, char1_reg, 0, SLJIT_IMM, 1); - OP2(SLJIT_XOR, char1_reg, 0, char1_reg, 0, SLJIT_IMM, 1); - OP2(SLJIT_SHL, char1_reg, 0, char1_reg, 0, SLJIT_IMM, 5); - OP2(SLJIT_ADD, char1_reg, 0, char1_reg, 0, SLJIT_IMM, 0x49); - CMPTO(SLJIT_EQUAL, TMP1, 0, char1_reg, 0, loop); - } - set_jumps(no_match, LABEL()); if (common->mode == PCRE2_JIT_COMPLETE) JUMPHERE(partial); - OP1(SLJIT_MOV, source_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0); - OP1(SLJIT_MOV, source_end_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCAL1); - OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCAL2); + OP1(SLJIT_MOV, source_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr); + OP1(SLJIT_MOV, source_end_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw)); + OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw) * 2); add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); if (common->mode != PCRE2_JIT_COMPLETE) { JUMPHERE(partial); - OP1(SLJIT_MOV, source_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0); - OP1(SLJIT_MOV, source_end_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCAL1); - OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCAL2); + OP1(SLJIT_MOV, source_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr); + OP1(SLJIT_MOV, source_end_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw)); + OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw) * 2); check_partial(common, FALSE); add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); } JUMPHERE(jump); - OP1(SLJIT_MOV, source_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0); - OP1(SLJIT_MOV, source_end_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCAL1); - OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCAL2); + OP1(SLJIT_MOV, source_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr); + OP1(SLJIT_MOV, source_end_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw)); + OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw) * 2); return; } else @@ -8188,7 +9594,7 @@ else if (common->mode == PCRE2_JIT_COMPLETE) add_jump(compiler, backtracks, partial); - add_jump(compiler, (*cc == OP_REF || *cc == OP_DNREF) ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL)); + add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL)); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); if (common->mode != PCRE2_JIT_COMPLETE) @@ -8200,7 +9606,7 @@ else OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, STR_END, 0); partial = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0); OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0); - add_jump(compiler, (*cc == OP_REF || *cc == OP_DNREF) ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL)); + add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL)); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); JUMPHERE(partial); check_partial(common, FALSE); @@ -8224,7 +9630,6 @@ DEFINE_COMPILER; BOOL ref = (*cc == OP_REF || *cc == OP_REFI); backtrack_common *backtrack; PCRE2_UCHAR type; -int local_start = LOCAL2; int offset = 0; struct sljit_label *label; struct sljit_jump *zerolength; @@ -8239,21 +9644,9 @@ if (ref) offset = GET2(cc, 1) << 1; else cc += IMM2_SIZE; - -if (*ccbegin == OP_REFI || *ccbegin == OP_DNREFI) - { - cc += 1; -#ifdef SUPPORT_UNICODE - if (common->utf || common->ucp) - local_start = LOCAL3; -#endif - } - type = cc[1 + IMM2_SIZE]; SLJIT_COMPILE_ASSERT((OP_CRSTAR & 0x1) == 0, crstar_opcode_must_be_even); -/* Update ref_update_local_size() when this changes. */ -SLJIT_ASSERT(local_start + 2 * SSIZE_OF(sw) <= (int)LOCAL0 + common->locals_size); minimize = (type & 0x1) != 0; switch(type) { @@ -8305,7 +9698,7 @@ if (!minimize) { compile_dnref_search(common, ccbegin, NULL); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), local_start + SSIZE_OF(sw), TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, TMP2, 0); zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); } /* Restore if not zero length. */ @@ -8328,24 +9721,24 @@ if (!minimize) { compile_dnref_search(common, ccbegin, &backtrack->own_backtracks); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), local_start + SSIZE_OF(sw), TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, TMP2, 0); zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); } } if (min > 1 || max > 1) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), local_start, SLJIT_IMM, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, SLJIT_IMM, 0); label = LABEL(); if (!ref) - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), local_start + SSIZE_OF(sw)); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1); compile_ref_matchingpath(common, ccbegin, &backtrack->own_backtracks, FALSE, FALSE); if (min > 1 || max > 1) { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), local_start); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0); OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), local_start, TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, TMP1, 0); if (min > 1) CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, min, label); if (max > 1) @@ -8613,13 +10006,12 @@ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(mark), (common->mark_pt SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1); /* Needed to save important temporary registers. */ -SLJIT_ASSERT(common->locals_size >= SSIZE_OF(sw)); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL0, STR_PTR, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0); /* SLJIT_R0 = arguments */ OP1(SLJIT_MOV, SLJIT_R1, 0, STACK_TOP, 0); GET_LOCAL_BASE(SLJIT_R2, 0, OVECTOR_START); sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(32, W, W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(do_callout_jit)); -OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0); +OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); free_stack(common, callout_arg_size); /* Check return value. */ @@ -8787,7 +10179,6 @@ jump_list **found; /* Saving previous accept variables. */ BOOL save_local_quit_available = common->local_quit_available; BOOL save_in_positive_assertion = common->in_positive_assertion; -sljit_s32 save_restore_end_ptr = common->restore_end_ptr; then_trap_backtrack *save_then_trap = common->then_trap; struct sljit_label *save_quit_label = common->quit_label; struct sljit_label *save_accept_label = common->accept_label; @@ -8895,7 +10286,6 @@ if (conditional || (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)) { /* Control verbs cannot escape from these asserts. */ local_quit_available = TRUE; - common->restore_end_ptr = 0; common->local_quit_available = TRUE; common->quit_label = NULL; common->quit = NULL; @@ -8931,7 +10321,6 @@ while (1) common->quit = save_quit; } common->in_positive_assertion = save_in_positive_assertion; - common->restore_end_ptr = save_restore_end_ptr; common->then_trap = save_then_trap; common->accept_label = save_accept_label; common->positive_assertion_quit = save_positive_assertion_quit; @@ -9029,7 +10418,6 @@ while (1) common->quit = save_quit; } common->in_positive_assertion = save_in_positive_assertion; - common->restore_end_ptr = save_restore_end_ptr; common->then_trap = save_then_trap; common->accept_label = save_accept_label; common->positive_assertion_quit = save_positive_assertion_quit; @@ -9169,8 +10557,7 @@ if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) { JUMPTO(SLJIT_JUMP, backtrack->matchingpath); JUMPHERE(brajump); - SLJIT_ASSERT(framesize != 0); - if (framesize > 0) + if (framesize >= 0) { OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); @@ -9235,9 +10622,7 @@ if (local_quit_available) common->quit_label = save_quit_label; common->quit = save_quit; } - common->in_positive_assertion = save_in_positive_assertion; -common->restore_end_ptr = save_restore_end_ptr; common->then_trap = save_then_trap; common->accept_label = save_accept_label; common->positive_assertion_quit = save_positive_assertion_quit; @@ -9428,7 +10813,6 @@ BOOL needs_control_head = FALSE; BOOL has_vreverse = FALSE; struct sljit_jump *jump; struct sljit_jump *skip; -jump_list *jumplist; struct sljit_label *rmax_label = NULL; struct sljit_jump *braminzero = NULL; @@ -9491,8 +10875,7 @@ if (opcode == OP_CBRA || opcode == OP_SCBRA) BACKTRACK_AS(bracket_backtrack)->private_data_ptr = private_data_ptr; matchingpath += IMM2_SIZE; } -else if (opcode == OP_ASSERT_NA || opcode == OP_ASSERTBACK_NA || opcode == OP_ONCE - || opcode == OP_ASSERT_SCS || opcode == OP_SCRIPT_RUN || opcode == OP_SBRA || opcode == OP_SCOND) +else if (opcode == OP_ASSERT_NA || opcode == OP_ASSERTBACK_NA || opcode == OP_ONCE || opcode == OP_SCRIPT_RUN || opcode == OP_SBRA || opcode == OP_SCOND) { /* Other brackets simply allocate the next entry. */ private_data_ptr = PRIVATE_DATA(ccbegin); @@ -9703,88 +11086,6 @@ else if (opcode == OP_ASSERT_NA || opcode == OP_ASSERTBACK_NA || opcode == OP_SC if (*matchingpath == OP_REVERSE) matchingpath = compile_reverse_matchingpath(common, matchingpath, backtrack); } -else if (opcode == OP_ASSERT_SCS) - { - /* Nested scs blocks will not update this variable. */ - if (common->restore_end_ptr == 0) - common->restore_end_ptr = private_data_ptr + sizeof(sljit_sw); - - if (*matchingpath == OP_CREF && (matchingpath[1 + IMM2_SIZE] != OP_CREF && matchingpath[1 + IMM2_SIZE] != OP_DNCREF)) - { - /* Optimized case for a single capture reference. */ - i = OVECTOR(GET2(matchingpath, 1) << 1); - - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), i); - - add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.no_capture), CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1))); - matchingpath += 1 + IMM2_SIZE; - - allocate_stack(common, has_alternatives ? 3 : 2); - - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); - OP1(SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw), STR_END, 0); - OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), i + sizeof(sljit_sw)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0); - OP1(SLJIT_MOV, STR_PTR, 0, TMP2, 0); - } - else - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)); - jumplist = NULL; - - while (TRUE) - { - if (*matchingpath == OP_CREF) - { - sljit_get_local_base(compiler, TMP2, 0, OVECTOR(GET2(matchingpath, 1) << 1)); - matchingpath += 1 + IMM2_SIZE; - } - else - { - SLJIT_ASSERT(*matchingpath == OP_DNCREF); - - i = GET2(matchingpath, 1 + IMM2_SIZE); - slot = common->name_table + GET2(matchingpath, 1) * common->name_entry_size; - - while (i-- > 1) - { - sljit_get_local_base(compiler, TMP2, 0, OVECTOR(GET2(slot, 0) << 1)); - add_jump(compiler, &jumplist, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(TMP2), 0, TMP1, 0)); - slot += common->name_entry_size; - } - - sljit_get_local_base(compiler, TMP2, 0, OVECTOR(GET2(slot, 0) << 1)); - matchingpath += 1 + 2 * IMM2_SIZE; - } - - if (*matchingpath != OP_CREF && *matchingpath != OP_DNCREF) - break; - - add_jump(compiler, &jumplist, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(TMP2), 0, TMP1, 0)); - } - - add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.no_capture), - CMP(SLJIT_EQUAL, SLJIT_MEM1(TMP2), 0, TMP1, 0)); - - set_jumps(jumplist, LABEL()); - - allocate_stack(common, has_alternatives ? 3 : 2); - - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); - OP1(SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP2), 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw), STR_END, 0); - OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); - } - - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_TMP_DEST_REG, 0); - - if (has_alternatives) - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), STR_PTR, 0); - } else if (has_alternatives) { /* Pushing the starting string pointer. */ @@ -9798,7 +11099,7 @@ if (opcode == OP_COND || opcode == OP_SCOND) if (*matchingpath == OP_CREF) { SLJIT_ASSERT(has_alternatives); - add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.no_capture), + add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(matchingpath, 1) << 1), SLJIT_MEM1(SLJIT_SP), OVECTOR(1))); matchingpath += 1 + IMM2_SIZE; } @@ -9820,13 +11121,13 @@ if (opcode == OP_COND || opcode == OP_SCOND) slot += common->name_entry_size; } OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0); - add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.no_capture), JUMP(SLJIT_ZERO)); + add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), JUMP(SLJIT_ZERO)); matchingpath += 1 + 2 * IMM2_SIZE; } else if ((*matchingpath >= OP_RREF && *matchingpath <= OP_TRUE) || *matchingpath == OP_FAIL) { /* Never has other case. */ - BACKTRACK_AS(bracket_backtrack)->u.no_capture = NULL; + BACKTRACK_AS(bracket_backtrack)->u.condfailed = NULL; SLJIT_ASSERT(!has_alternatives); if (*matchingpath == OP_TRUE) @@ -9915,6 +11216,9 @@ switch (opcode) if (PRIVATE_DATA(ccbegin + 1)) OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw)); break; + case OP_ASSERT_NA: + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); + break; case OP_ONCE: match_once_common(common, ket, BACKTRACK_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head); break; @@ -9980,7 +11284,7 @@ if (has_alternatives) if (i <= 3) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); else - BACKTRACK_AS(bracket_backtrack)->matching_mov_addr = sljit_emit_mov_addr(compiler, SLJIT_MEM1(STACK_TOP), STACK(stacksize)); + BACKTRACK_AS(bracket_backtrack)->u.matching_mov_addr = sljit_emit_mov_addr(compiler, SLJIT_MEM1(STACK_TOP), STACK(stacksize)); } if (ket != OP_KETRMAX) BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL(); @@ -9992,22 +11296,6 @@ if (offset != 0 && common->optimized_cbracket[offset >> 1] != 0) SLJIT_ASSERT(private_data_ptr == OVECTOR(offset + 0)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0); } -else switch (opcode) - { - case OP_ASSERT_NA: - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); - break; - case OP_ASSERT_SCS: - OP1(SLJIT_MOV, TMP1, 0, STR_END, 0); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); - OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw), TMP1, 0); - - /* Nested scs blocks will not update this variable. */ - if (common->restore_end_ptr == private_data_ptr + SSIZE_OF(sw)) - common->restore_end_ptr = 0; - break; - } if (ket == OP_KETRMAX) { @@ -10071,19 +11359,13 @@ if (bra == OP_BRAMINZERO) /* We need to release the end pointer to perform the backtrack for the zero-length iteration. When framesize is < 0, OP_ONCE will do the release itself. */ - if (opcode == OP_ONCE) + if (opcode == OP_ONCE && BACKTRACK_AS(bracket_backtrack)->u.framesize >= 0) { - int framesize = BACKTRACK_AS(bracket_backtrack)->u.framesize; - - SLJIT_ASSERT(framesize != 0); - if (framesize > 0) - { - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); - add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize - 1) * sizeof(sljit_sw)); - } + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); + add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); + OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (BACKTRACK_AS(bracket_backtrack)->u.framesize - 1) * sizeof(sljit_sw)); } - else if (ket == OP_KETRMIN) + else if (ket == OP_KETRMIN && opcode != OP_ONCE) free_stack(common, 1); } /* Continue to the normal backtrack. */ @@ -10331,7 +11613,12 @@ while (*cc != OP_KETRPOS) add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0)); if (!zero) - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); + { + if (framesize < 0) + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0); + else + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); + } } JUMPTO(SLJIT_JUMP, loop); @@ -10425,11 +11712,11 @@ else if (*opcode >= OP_TYPESTAR && *opcode <= OP_TYPEPOSUPTO) } else { - SLJIT_ASSERT(*opcode == OP_CLASS || *opcode == OP_NCLASS || *opcode == OP_XCLASS || *opcode == OP_ECLASS); + SLJIT_ASSERT(*opcode == OP_CLASS || *opcode == OP_NCLASS || *opcode == OP_XCLASS); *type = *opcode; - class_len = (*type < OP_XCLASS) ? (int)(1 + (32 / sizeof(PCRE2_UCHAR))) : GET(cc, 1); - *opcode = cc[class_len]; cc++; + class_len = (*type < OP_XCLASS) ? (int)(1 + (32 / sizeof(PCRE2_UCHAR))) : GET(cc, 0); + *opcode = cc[class_len - 1]; if (*opcode >= OP_CRSTAR && *opcode <= OP_CRMINQUERY) { @@ -10441,10 +11728,8 @@ else *exact = 1; *opcode -= OP_PLUS - OP_STAR; } - return cc; } - - if (*opcode >= OP_CRPOSSTAR && *opcode <= OP_CRPOSQUERY) + else if (*opcode >= OP_CRPOSSTAR && *opcode <= OP_CRPOSQUERY) { *opcode -= OP_CRPOSSTAR - OP_POSSTAR; *end = cc + class_len; @@ -10454,40 +11739,41 @@ else *exact = 1; *opcode = OP_POSSTAR; } - return cc; - } - - SLJIT_ASSERT(*opcode == OP_CRRANGE || *opcode == OP_CRMINRANGE || *opcode == OP_CRPOSRANGE); - *max = GET2(cc, (class_len + IMM2_SIZE)); - *exact = GET2(cc, class_len); - *end = cc + class_len + 2 * IMM2_SIZE; - - if (*max == 0) - { - SLJIT_ASSERT(*exact > 1); - if (*opcode == OP_CRRANGE) - *opcode = OP_UPTO; - else if (*opcode == OP_CRPOSRANGE) - *opcode = OP_POSUPTO; - else - *opcode = OP_MINSTAR; - return cc; } - - *max -= *exact; - if (*max == 0) - *opcode = OP_EXACT; else { - SLJIT_ASSERT(*exact > 0 || *max > 1); - if (*opcode == OP_CRRANGE) - *opcode = OP_UPTO; - else if (*opcode == OP_CRPOSRANGE) - *opcode = OP_POSUPTO; - else if (*max == 1) - *opcode = OP_MINQUERY; + SLJIT_ASSERT(*opcode == OP_CRRANGE || *opcode == OP_CRMINRANGE || *opcode == OP_CRPOSRANGE); + *max = GET2(cc, (class_len + IMM2_SIZE)); + *exact = GET2(cc, class_len); + + if (*max == 0) + { + if (*opcode == OP_CRPOSRANGE) + *opcode = OP_POSSTAR; + else + *opcode -= OP_CRRANGE - OP_STAR; + } else - *opcode = OP_MINUPTO; + { + *max -= *exact; + if (*max == 0) + *opcode = OP_EXACT; + else if (*max == 1) + { + if (*opcode == OP_CRPOSRANGE) + *opcode = OP_POSQUERY; + else + *opcode -= OP_CRRANGE - OP_QUERY; + } + else + { + if (*opcode == OP_CRPOSRANGE) + *opcode = OP_POSUPTO; + else + *opcode -= OP_CRRANGE - OP_UPTO; + } + } + *end = cc + class_len + 2 * IMM2_SIZE; } return cc; } @@ -10533,17 +11819,16 @@ if (common->utf && HAS_EXTRALEN(*cc)) *end += GET_EXTRALEN(*cc); return cc; } -static PCRE2_SPTR compile_iterator_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent, jump_list **prev_backtracks) +static PCRE2_SPTR compile_iterator_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent) { DEFINE_COMPILER; -backtrack_common *backtrack = NULL; -PCRE2_SPTR begin = cc; +backtrack_common *backtrack; PCRE2_UCHAR opcode; PCRE2_UCHAR type; sljit_u32 max = 0, exact; sljit_s32 early_fail_ptr = PRIVATE_DATA(cc + 1); sljit_s32 early_fail_type; -BOOL charpos_enabled, use_tmp; +BOOL charpos_enabled; PCRE2_UCHAR charpos_char; unsigned int charpos_othercasebit; PCRE2_SPTR end; @@ -10556,6 +11841,11 @@ int base = (private_data_ptr == 0) ? SLJIT_MEM1(STACK_TOP) : SLJIT_MEM1(SLJIT_SP int offset0 = (private_data_ptr == 0) ? STACK(0) : private_data_ptr; int offset1 = (private_data_ptr == 0) ? STACK(1) : private_data_ptr + SSIZE_OF(sw); int tmp_base, tmp_offset; +#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 +BOOL use_tmp; +#endif + +PUSH_BACKTRACK(sizeof(char_iterator_backtrack), cc, NULL); early_fail_type = (early_fail_ptr & 0x7); early_fail_ptr >>= 3; @@ -10571,7 +11861,7 @@ SLJIT_ASSERT(common->fast_forward_bc_ptr != NULL || early_fail_ptr == 0 || (early_fail_ptr >= common->early_fail_start_ptr && early_fail_ptr <= common->early_fail_end_ptr)); if (early_fail_type == type_fail) - add_jump(compiler, prev_backtracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), early_fail_ptr)); + add_jump(compiler, &backtrack->own_backtracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), early_fail_ptr)); cc = get_iterator_parameters(common, cc, &opcode, &type, &max, &exact, &end); @@ -10583,47 +11873,39 @@ if (type != OP_EXTUNI) else { tmp_base = SLJIT_MEM1(SLJIT_SP); - tmp_offset = LOCAL2; + tmp_offset = POSSESSIVE0; } -if (opcode == OP_EXACT) +/* Handle fixed part first. */ +if (exact > 1) { - SLJIT_ASSERT(early_fail_ptr == 0 && exact >= 2); + SLJIT_ASSERT(early_fail_ptr == 0); if (common->mode == PCRE2_JIT_COMPLETE -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 +#ifdef SUPPORT_UNICODE && !common->utf #endif && type != OP_ANYNL && type != OP_EXTUNI) { - OP2(SLJIT_SUB, TMP1, 0, STR_END, 0, STR_PTR, 0); - add_jump(compiler, prev_backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, IN_UCHARS(exact))); - -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 32 - if (type == OP_ALLANY && !common->invalid_utf) -#else - if (type == OP_ALLANY) -#endif - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(exact)); - else - { - OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, exact); - label = LABEL(); - compile_char1_matchingpath(common, type, cc, prev_backtracks, FALSE); - OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); - JUMPTO(SLJIT_NOT_ZERO, label); - } + OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(exact)); + add_jump(compiler, &backtrack->own_backtracks, CMP(SLJIT_GREATER, TMP1, 0, STR_END, 0)); + OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, exact); + label = LABEL(); + compile_char1_matchingpath(common, type, cc, &backtrack->own_backtracks, FALSE); + OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + JUMPTO(SLJIT_NOT_ZERO, label); } else { - SLJIT_ASSERT(tmp_base == TMP3 || common->locals_size >= 3 * SSIZE_OF(sw)); OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, exact); label = LABEL(); - compile_char1_matchingpath(common, type, cc, prev_backtracks, TRUE); + compile_char1_matchingpath(common, type, cc, &backtrack->own_backtracks, TRUE); OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, label); } } +else if (exact == 1) + compile_char1_matchingpath(common, type, cc, &backtrack->own_backtracks, TRUE); if (early_fail_type == type_fail_range) { @@ -10632,57 +11914,38 @@ if (early_fail_type == type_fail_range) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), early_fail_ptr + SSIZE_OF(sw)); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, TMP2, 0); OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, TMP2, 0); - add_jump(compiler, prev_backtracks, CMP(SLJIT_LESS_EQUAL, TMP2, 0, TMP1, 0)); + add_jump(compiler, &backtrack->own_backtracks, CMP(SLJIT_LESS_EQUAL, TMP2, 0, TMP1, 0)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr + SSIZE_OF(sw), STR_PTR, 0); } -if (opcode < OP_EXACT) - PUSH_BACKTRACK(sizeof(char_iterator_backtrack), begin, NULL); - switch(opcode) { case OP_STAR: case OP_UPTO: - SLJIT_ASSERT(backtrack != NULL && (early_fail_ptr == 0 || opcode == OP_STAR)); - max += exact; - - if (type == OP_EXTUNI) - { - SLJIT_ASSERT(private_data_ptr == 0); - SLJIT_ASSERT(early_fail_ptr == 0); + SLJIT_ASSERT(early_fail_ptr == 0 || opcode == OP_STAR); - if (exact == 1) - { - SLJIT_ASSERT(opcode == OP_STAR); - allocate_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); - } - else - { - /* If OP_EXTUNI is present, it has a separate EXACT opcode. */ - SLJIT_ASSERT(exact == 0); + if (type == OP_ANYNL || type == OP_EXTUNI) + { + SLJIT_ASSERT(private_data_ptr == 0); + SLJIT_ASSERT(early_fail_ptr == 0); - allocate_stack(common, 2); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0); - } + allocate_stack(common, 2); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0); if (opcode == OP_UPTO) - { - SLJIT_ASSERT(common->locals_size >= 3 * SSIZE_OF(sw)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL2, SLJIT_IMM, max); - } + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, SLJIT_IMM, max); label = LABEL(); - compile_char1_matchingpath(common, type, cc, &backtrack->own_backtracks, TRUE); + compile_char1_matchingpath(common, type, cc, &BACKTRACK_AS(char_iterator_backtrack)->u.backtracks, TRUE); if (opcode == OP_UPTO) { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCAL2); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0); OP2(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); jump = JUMP(SLJIT_ZERO); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL2, TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, TMP1, 0); } /* We cannot use TMP3 because of allocate_stack. */ @@ -10702,9 +11965,6 @@ switch(opcode) { if (opcode == OP_STAR) { - if (exact == 1) - detect_partial_match(common, prev_backtracks); - if (private_data_ptr == 0) allocate_stack(common, 2); @@ -10725,9 +11985,6 @@ switch(opcode) else #endif { - /* If OP_ALLANY is present, it has a separate EXACT opcode. */ - SLJIT_ASSERT(exact == 0); - if (private_data_ptr == 0) allocate_stack(common, 2); @@ -10759,7 +12016,6 @@ switch(opcode) charpos_char = 0; charpos_othercasebit = 0; - SLJIT_ASSERT(tmp_base == TMP3); if ((type != OP_CHAR && type != OP_CHARI) && (*end == OP_CHAR || *end == OP_CHARI)) { #ifdef SUPPORT_UNICODE @@ -10789,320 +12045,176 @@ switch(opcode) if (charpos_othercasebit != 0) charpos_char |= charpos_othercasebit; - BACKTRACK_AS(char_iterator_backtrack)->charpos.charpos_enabled = TRUE; - BACKTRACK_AS(char_iterator_backtrack)->charpos.chr = charpos_char; - BACKTRACK_AS(char_iterator_backtrack)->charpos.othercasebit = charpos_othercasebit; - - if (private_data_ptr == 0) - allocate_stack(common, 2); - - use_tmp = (opcode == OP_STAR); - - if (use_tmp) - { - OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0); - OP1(SLJIT_MOV, base, offset0, TMP3, 0); - } - else - { - OP1(SLJIT_MOV, base, offset1, COUNT_MATCH, 0); - OP1(SLJIT_MOV, COUNT_MATCH, 0, SLJIT_IMM, 0); - OP1(SLJIT_MOV, base, offset0, COUNT_MATCH, 0); - OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, exact == max ? 0 : (max + 1)); - } - - /* Search the first instance of charpos_char. */ - if (exact > 0) - detect_partial_match(common, &no_match); - else - jump = JUMP(SLJIT_JUMP); - - label = LABEL(); - - if (opcode == OP_UPTO) - { - if (exact == max) - OP2(SLJIT_ADD, TMP3, 0, TMP3, 0, SLJIT_IMM, 1); - else - { - OP2(SLJIT_SUB | SLJIT_SET_Z, TMP3, 0, TMP3, 0, SLJIT_IMM, 1); - add_jump(compiler, &no_match, JUMP(SLJIT_ZERO)); - } - } - - compile_char1_matchingpath(common, type, cc, &no_match, FALSE); - - if (early_fail_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0); - - if (exact == 0) - JUMPHERE(jump); - - detect_partial_match(common, &no_match); - - if (opcode == OP_UPTO && exact > 0) - { - if (exact == max) - CMPTO(SLJIT_LESS, TMP3, 0, SLJIT_IMM, exact, label); - else - CMPTO(SLJIT_GREATER, TMP3, 0, SLJIT_IMM, (max + 1) - exact, label); - } - - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); - if (charpos_othercasebit != 0) - OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, charpos_othercasebit); - CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char, label); - - OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); - if (use_tmp) - { - OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP3, 0, SLJIT_IMM, 0); - SELECT(SLJIT_EQUAL, TMP3, STR_PTR, 0, TMP3); - } - else - { - OP2U(SLJIT_SUB | SLJIT_SET_Z, COUNT_MATCH, 0, SLJIT_IMM, 0); - SELECT(SLJIT_EQUAL, COUNT_MATCH, STR_PTR, 0, COUNT_MATCH); - } - JUMPTO(SLJIT_JUMP, label); - - set_jumps(no_match, LABEL()); - OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); - if (use_tmp) - OP1(SLJIT_MOV, base, offset1, TMP3, 0); - else - { - OP1(SLJIT_MOV, TMP1, 0, base, offset1); - OP1(SLJIT_MOV, base, offset1, COUNT_MATCH, 0); - OP1(SLJIT_MOV, COUNT_MATCH, 0, TMP1, 0); - } - - add_jump(compiler, &backtrack->own_backtracks, CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0)); - - BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL(); - OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - break; + BACKTRACK_AS(char_iterator_backtrack)->u.charpos.enabled = TRUE; + BACKTRACK_AS(char_iterator_backtrack)->u.charpos.chr = charpos_char; + BACKTRACK_AS(char_iterator_backtrack)->u.charpos.othercasebit = charpos_othercasebit; } } - if (private_data_ptr == 0) - allocate_stack(common, 2); + if (charpos_enabled) + { + if (opcode == OP_UPTO) + OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max + 1); -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 - use_tmp = (opcode == OP_STAR); + /* Search the first instance of charpos_char. */ + jump = JUMP(SLJIT_JUMP); + label = LABEL(); + if (opcode == OP_UPTO) + { + OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + add_jump(compiler, &backtrack->own_backtracks, JUMP(SLJIT_ZERO)); + } + compile_char1_matchingpath(common, type, cc, &backtrack->own_backtracks, FALSE); + if (early_fail_ptr != 0) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0); + JUMPHERE(jump); - if (common->utf) - { - if (!use_tmp) - OP1(SLJIT_MOV, base, offset0, COUNT_MATCH, 0); + detect_partial_match(common, &backtrack->own_backtracks); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); + if (charpos_othercasebit != 0) + OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, charpos_othercasebit); + CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char, label); - OP1(SLJIT_MOV, use_tmp ? TMP3 : COUNT_MATCH, 0, STR_PTR, 0); - } -#endif + if (private_data_ptr == 0) + allocate_stack(common, 2); + OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); + OP1(SLJIT_MOV, base, offset1, STR_PTR, 0); - if (opcode == OP_UPTO) - OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, exact == max ? -(sljit_sw)exact : (sljit_sw)max); + if (opcode == OP_UPTO) + { + OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + add_jump(compiler, &no_match, JUMP(SLJIT_ZERO)); + } - if (opcode == OP_UPTO && exact > 0) - { + /* Search the last instance of charpos_char. */ label = LABEL(); + compile_char1_matchingpath(common, type, cc, &no_match, FALSE); + if (early_fail_ptr != 0) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0); detect_partial_match(common, &no_match); - compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE); -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 - if (common->utf) - OP1(SLJIT_MOV, use_tmp ? TMP3 : COUNT_MATCH, 0, STR_PTR, 0); -#endif + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); + if (charpos_othercasebit != 0) + OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, charpos_othercasebit); - if (exact == max) + if (opcode == OP_STAR) { - OP2(SLJIT_ADD | SLJIT_SET_Z, TMP3, 0, TMP3, 0, SLJIT_IMM, 1); - JUMPTO(SLJIT_NOT_ZERO, label); + CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char, label); + OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); + JUMPTO(SLJIT_JUMP, label); } else { - OP2(SLJIT_SUB | SLJIT_SET_Z, TMP3, 0, TMP3, 0, SLJIT_IMM, 1); - add_jump(compiler, &no_match, JUMP(SLJIT_ZERO)); - CMPTO(SLJIT_NOT_EQUAL, TMP3, 0, SLJIT_IMM, max - exact, label); + jump = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char); + OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); + JUMPHERE(jump); + OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + JUMPTO(SLJIT_NOT_ZERO, label); } - OP1(SLJIT_MOV, base, offset1, STR_PTR, 0); - JUMPTO(SLJIT_JUMP, label); + set_jumps(no_match, LABEL()); + OP2(SLJIT_ADD, STR_PTR, 0, base, offset0, SLJIT_IMM, IN_UCHARS(1)); + OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); } else { + if (private_data_ptr == 0) + allocate_stack(common, 2); + OP1(SLJIT_MOV, base, offset1, STR_PTR, 0); +#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 + use_tmp = (!HAS_VIRTUAL_REGISTERS && opcode == OP_STAR); + SLJIT_ASSERT(!use_tmp || tmp_base == TMP3); + + if (common->utf) + OP1(SLJIT_MOV, use_tmp ? TMP3 : base, use_tmp ? 0 : offset0, STR_PTR, 0); +#endif + if (opcode == OP_UPTO) + OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max); detect_partial_match(common, &no_match); label = LABEL(); compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE); #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 if (common->utf) - OP1(SLJIT_MOV, use_tmp ? TMP3 : COUNT_MATCH, 0, STR_PTR, 0); + OP1(SLJIT_MOV, use_tmp ? TMP3 : base, use_tmp ? 0 : offset0, STR_PTR, 0); #endif if (opcode == OP_UPTO) { - OP2(SLJIT_SUB | SLJIT_SET_Z, TMP3, 0, TMP3, 0, SLJIT_IMM, 1); + OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); add_jump(compiler, &no_match, JUMP(SLJIT_ZERO)); } detect_partial_match_to(common, label); - } + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 - if (common->utf) - { set_jumps(no_char1_match, LABEL()); - set_jumps(no_match, LABEL()); - if (use_tmp) +#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 + if (common->utf) { - OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0); - OP1(SLJIT_MOV, base, offset0, TMP3, 0); + set_jumps(no_match, LABEL()); + if (use_tmp) + { + OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0); + OP1(SLJIT_MOV, base, offset0, TMP3, 0); + } + else + OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); } else +#endif { - OP1(SLJIT_MOV, STR_PTR, 0, COUNT_MATCH, 0); - OP1(SLJIT_MOV, COUNT_MATCH, 0, base, offset0); + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + set_jumps(no_match, LABEL()); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); } - } - else -#endif - { - if (opcode != OP_UPTO || exact == 0) - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - set_jumps(no_char1_match, LABEL()); - - OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - set_jumps(no_match, LABEL()); - OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); - } - if (opcode == OP_UPTO) - { - if (exact > 0) - { - if (max == exact) - jump = CMP(SLJIT_GREATER_EQUAL, TMP3, 0, SLJIT_IMM, -(sljit_sw)exact); - else - jump = CMP(SLJIT_GREATER, TMP3, 0, SLJIT_IMM, max - exact); - - add_jump(compiler, &backtrack->own_backtracks, jump); - } + if (early_fail_ptr != 0) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0); } - else if (exact == 1) - add_jump(compiler, &backtrack->own_backtracks, CMP(SLJIT_EQUAL, base, offset1, STR_PTR, 0)); - - if (early_fail_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0); BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL(); break; - case OP_QUERY: - SLJIT_ASSERT(backtrack != NULL && early_fail_ptr == 0); + case OP_MINSTAR: if (private_data_ptr == 0) allocate_stack(common, 1); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); - compile_char1_matchingpath(common, type, cc, &backtrack->own_backtracks, TRUE); BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL(); - break; - - case OP_MINSTAR: - case OP_MINQUERY: - SLJIT_ASSERT(backtrack != NULL && (opcode == OP_MINSTAR || early_fail_ptr == 0)); - if (private_data_ptr == 0) - allocate_stack(common, 1); - - if (exact >= 1) - { - if (exact >= 2) - { - /* Extuni has a separate exact opcode. */ - SLJIT_ASSERT(tmp_base == TMP3 && early_fail_ptr == 0); - OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, exact); - } - - if (opcode == OP_MINQUERY) - OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, -1); - - label = LABEL(); - BACKTRACK_AS(char_iterator_backtrack)->matchingpath = label; - - compile_char1_matchingpath(common, type, cc, &backtrack->own_backtracks, TRUE); - - if (exact >= 2) - { - OP2(SLJIT_SUB | SLJIT_SET_Z, TMP3, 0, TMP3, 0, SLJIT_IMM, 1); - JUMPTO(SLJIT_NOT_ZERO, label); - } - - if (opcode == OP_MINQUERY) - OP2(SLJIT_AND, base, offset0, base, offset0, STR_PTR, 0); - else - OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); - } - else - { - OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); - BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL(); - } - if (early_fail_ptr != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0); break; case OP_MINUPTO: - SLJIT_ASSERT(backtrack != NULL && early_fail_ptr == 0); + SLJIT_ASSERT(early_fail_ptr == 0); if (private_data_ptr == 0) allocate_stack(common, 2); - + OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); OP1(SLJIT_MOV, base, offset1, SLJIT_IMM, max + 1); + BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL(); + break; - if (exact == 0) - { - OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); - BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL(); - break; - } - - if (exact >= 2) - { - /* Extuni has a separate exact opcode. */ - SLJIT_ASSERT(tmp_base == TMP3); - OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, exact); - } - - label = LABEL(); - BACKTRACK_AS(char_iterator_backtrack)->matchingpath = label; - - compile_char1_matchingpath(common, type, cc, &backtrack->own_backtracks, TRUE); - - if (exact >= 2) - { - OP2(SLJIT_SUB | SLJIT_SET_Z, TMP3, 0, TMP3, 0, SLJIT_IMM, 1); - JUMPTO(SLJIT_NOT_ZERO, label); - } - + case OP_QUERY: + case OP_MINQUERY: + SLJIT_ASSERT(early_fail_ptr == 0); + if (private_data_ptr == 0) + allocate_stack(common, 1); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); + if (opcode == OP_QUERY) + compile_char1_matchingpath(common, type, cc, &BACKTRACK_AS(char_iterator_backtrack)->u.backtracks, TRUE); + BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL(); break; case OP_EXACT: - SLJIT_ASSERT(backtrack == NULL); break; case OP_POSSTAR: - SLJIT_ASSERT(backtrack == NULL); #if defined SUPPORT_UNICODE if (type == OP_ALLANY && !common->invalid_utf) #else if (type == OP_ALLANY) #endif { - if (exact == 1) - detect_partial_match(common, prev_backtracks); - OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0); process_partial_match(common); if (early_fail_ptr != 0) @@ -11111,150 +12223,98 @@ switch(opcode) } #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 - if (common->utf) + if (type == OP_EXTUNI || common->utf) { - SLJIT_ASSERT(tmp_base == TMP3 || common->locals_size >= 3 * SSIZE_OF(sw)); - - if (tmp_base != TMP3) - { - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL2, COUNT_MATCH, 0); - tmp_base = COUNT_MATCH; - } - - OP1(SLJIT_MOV, tmp_base, 0, exact == 1 ? SLJIT_IMM : STR_PTR, 0); + OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); detect_partial_match(common, &no_match); label = LABEL(); compile_char1_matchingpath(common, type, cc, &no_match, FALSE); - OP1(SLJIT_MOV, tmp_base, 0, STR_PTR, 0); + OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); detect_partial_match_to(common, label); set_jumps(no_match, LABEL()); - OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, 0); - - if (tmp_base != TMP3) - OP1(SLJIT_MOV, COUNT_MATCH, 0, SLJIT_MEM1(SLJIT_SP), LOCAL2); - - if (exact == 1) - add_jump(compiler, prev_backtracks, CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0)); - + OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset); if (early_fail_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0); + { + if (!HAS_VIRTUAL_REGISTERS && tmp_base == TMP3) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, TMP3, 0); + else + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0); + } break; } #endif - if (exact == 1) - OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); - detect_partial_match(common, &no_match); label = LABEL(); - /* Extuni never fails, so no_char1_match is not used in that case. - Anynl optionally reads an extra character on success. */ compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE); detect_partial_match_to(common, label); - if (type != OP_EXTUNI) - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); set_jumps(no_char1_match, LABEL()); - if (type != OP_EXTUNI) - OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); set_jumps(no_match, LABEL()); - - if (exact == 1) - add_jump(compiler, prev_backtracks, CMP(SLJIT_EQUAL, tmp_base, tmp_offset, STR_PTR, 0)); - if (early_fail_ptr != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0); break; case OP_POSUPTO: - SLJIT_ASSERT(backtrack == NULL && early_fail_ptr == 0); - max += exact; - + SLJIT_ASSERT(early_fail_ptr == 0); #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 - if (type == OP_EXTUNI || common->utf) -#else - if (type == OP_EXTUNI) -#endif + if (common->utf) { - SLJIT_ASSERT(common->locals_size >= 3 * SSIZE_OF(sw)); - - /* Count match is not modified by compile_char1_matchingpath. */ - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL2, COUNT_MATCH, 0); - OP1(SLJIT_MOV, COUNT_MATCH, 0, SLJIT_IMM, exact == max ? 0 : max); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, STR_PTR, 0); + OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max); + detect_partial_match(common, &no_match); label = LABEL(); - /* Extuni only modifies TMP3 on successful match. */ - OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0); - compile_char1_matchingpath(common, type, cc, &no_match, TRUE); + compile_char1_matchingpath(common, type, cc, &no_match, FALSE); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, STR_PTR, 0); + OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + add_jump(compiler, &no_match, JUMP(SLJIT_ZERO)); + detect_partial_match_to(common, label); + + set_jumps(no_match, LABEL()); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1); + break; + } +#endif - if (exact == max) + if (type == OP_ALLANY) + { + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(max)); + + if (common->mode == PCRE2_JIT_COMPLETE) { - OP2(SLJIT_ADD, COUNT_MATCH, 0, COUNT_MATCH, 0, SLJIT_IMM, 1); - JUMPTO(SLJIT_JUMP, label); + OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_PTR, 0, STR_END, 0); + SELECT(SLJIT_GREATER, STR_PTR, STR_END, 0, STR_PTR); } else { - OP2(SLJIT_SUB | SLJIT_SET_Z, COUNT_MATCH, 0, COUNT_MATCH, 0, SLJIT_IMM, 1); - JUMPTO(SLJIT_NOT_ZERO, label); - OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0); - } - - set_jumps(no_match, LABEL()); - - if (exact > 0) - { - if (exact == max) - OP2U(SLJIT_SUB | SLJIT_SET_LESS, COUNT_MATCH, 0, SLJIT_IMM, exact); - else - OP2U(SLJIT_SUB | SLJIT_SET_GREATER, COUNT_MATCH, 0, SLJIT_IMM, max - exact); + jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, STR_END, 0); + process_partial_match(common); + JUMPHERE(jump); } - - OP1(SLJIT_MOV, COUNT_MATCH, 0, SLJIT_MEM1(SLJIT_SP), LOCAL2); - - if (exact > 0) - add_jump(compiler, prev_backtracks, JUMP(exact == max ? SLJIT_LESS : SLJIT_GREATER)); - OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0); break; } - SLJIT_ASSERT(tmp_base == TMP3); - - OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, exact == max ? 0 : max); + OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max); detect_partial_match(common, &no_match); label = LABEL(); compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE); - - if (exact == max) - OP2(SLJIT_ADD, TMP3, 0, TMP3, 0, SLJIT_IMM, 1); - else - { - OP2(SLJIT_SUB | SLJIT_SET_Z, TMP3, 0, TMP3, 0, SLJIT_IMM, 1); - add_jump(compiler, &no_match, JUMP(SLJIT_ZERO)); - } + OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + add_jump(compiler, &no_match, JUMP(SLJIT_ZERO)); detect_partial_match_to(common, label); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); set_jumps(no_char1_match, LABEL()); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); set_jumps(no_match, LABEL()); - - if (exact > 0) - { - if (exact == max) - jump = CMP(SLJIT_LESS, TMP3, 0, SLJIT_IMM, exact); - else - jump = CMP(SLJIT_GREATER, TMP3, 0, SLJIT_IMM, max - exact); - - add_jump(compiler, prev_backtracks, jump); - } break; case OP_POSQUERY: - SLJIT_ASSERT(backtrack == NULL && early_fail_ptr == 0); - SLJIT_ASSERT(tmp_base == TMP3 || common->locals_size >= 3 * SSIZE_OF(sw)); + SLJIT_ASSERT(early_fail_ptr == 0); OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); compile_char1_matchingpath(common, type, cc, &no_match, TRUE); OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); @@ -11417,7 +12477,6 @@ DEFINE_COMPILER; backtrack_common *backtrack; BOOL has_then_trap = FALSE; then_trap_backtrack *save_then_trap = NULL; -size_t op_len; SLJIT_ASSERT(*ccend == OP_END || (*ccend >= OP_ALT && *ccend <= OP_KETRPOS)); @@ -11553,23 +12612,21 @@ while (cc < ccend) case OP_TYPEPOSPLUS: case OP_TYPEPOSQUERY: case OP_TYPEPOSUPTO: - cc = compile_iterator_matchingpath(common, cc, parent, parent->top != NULL ? &parent->top->simple_backtracks : &parent->own_backtracks); + cc = compile_iterator_matchingpath(common, cc, parent); break; case OP_CLASS: case OP_NCLASS: if (cc[1 + (32 / sizeof(PCRE2_UCHAR))] >= OP_CRSTAR && cc[1 + (32 / sizeof(PCRE2_UCHAR))] <= OP_CRPOSRANGE) - cc = compile_iterator_matchingpath(common, cc, parent, parent->top != NULL ? &parent->top->simple_backtracks : &parent->own_backtracks); + cc = compile_iterator_matchingpath(common, cc, parent); else cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->simple_backtracks : &parent->own_backtracks, TRUE); break; #if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32 case OP_XCLASS: - case OP_ECLASS: - op_len = GET(cc, 1); - if (cc[op_len] >= OP_CRSTAR && cc[op_len] <= OP_CRPOSRANGE) - cc = compile_iterator_matchingpath(common, cc, parent, parent->top != NULL ? &parent->top->simple_backtracks : &parent->own_backtracks); + if (*(cc + GET(cc, 1)) >= OP_CRSTAR && *(cc + GET(cc, 1)) <= OP_CRPOSRANGE) + cc = compile_iterator_matchingpath(common, cc, parent); else cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->simple_backtracks : &parent->own_backtracks, TRUE); break; @@ -11577,26 +12634,24 @@ while (cc < ccend) case OP_REF: case OP_REFI: - op_len = PRIV(OP_lengths)[*cc]; - if (cc[op_len] >= OP_CRSTAR && cc[op_len] <= OP_CRPOSRANGE) + if (cc[1 + IMM2_SIZE] >= OP_CRSTAR && cc[1 + IMM2_SIZE] <= OP_CRPOSRANGE) cc = compile_ref_iterator_matchingpath(common, cc, parent); else { compile_ref_matchingpath(common, cc, parent->top != NULL ? &parent->top->simple_backtracks : &parent->own_backtracks, TRUE, FALSE); - cc += op_len; + cc += 1 + IMM2_SIZE; } break; case OP_DNREF: case OP_DNREFI: - op_len = PRIV(OP_lengths)[*cc]; - if (cc[op_len] >= OP_CRSTAR && cc[op_len] <= OP_CRPOSRANGE) + if (cc[1 + 2 * IMM2_SIZE] >= OP_CRSTAR && cc[1 + 2 * IMM2_SIZE] <= OP_CRPOSRANGE) cc = compile_ref_iterator_matchingpath(common, cc, parent); else { compile_dnref_search(common, cc, parent->top != NULL ? &parent->top->simple_backtracks : &parent->own_backtracks); compile_ref_matchingpath(common, cc, parent->top != NULL ? &parent->top->simple_backtracks : &parent->own_backtracks, TRUE, FALSE); - cc += op_len; + cc += 1 + 2 * IMM2_SIZE; } break; @@ -11637,7 +12692,6 @@ while (cc < ccend) case OP_ASSERT_NA: case OP_ASSERTBACK_NA: - case OP_ASSERT_SCS: case OP_ONCE: case OP_SCRIPT_RUN: case OP_BRA: @@ -11749,28 +12803,6 @@ SLJIT_ASSERT(cc == ccend); #define CURRENT_AS(type) ((type *)current) -static void compile_newline_move_back(compiler_common *common) -{ -DEFINE_COMPILER; -struct sljit_jump *jump; - -OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -jump = CMP(SLJIT_LESS_EQUAL, TMP1, 0, TMP2, 0); -/* All newlines are single byte, or their last byte -is not equal to CHAR_NL/CHAR_CR even if UTF is enabled. */ -OP1(MOV_UCHAR, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); -OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); -OP2(SLJIT_SHL, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 8); -OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_TMP_DEST_REG, 0); -OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_CR << 8 | CHAR_NL); -OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL); -#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32 -OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT); -#endif -OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0); -JUMPHERE(jump); -} - static void compile_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current) { DEFINE_COMPILER; @@ -11793,104 +12825,52 @@ switch(opcode) { case OP_STAR: case OP_UPTO: - if (type == OP_EXTUNI) + if (type == OP_ANYNL || type == OP_EXTUNI) { SLJIT_ASSERT(private_data_ptr == 0); - set_jumps(current->own_backtracks, LABEL()); + set_jumps(CURRENT_AS(char_iterator_backtrack)->u.backtracks, LABEL()); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(char_iterator_backtrack)->matchingpath); } else { - if (CURRENT_AS(char_iterator_backtrack)->charpos.charpos_enabled) + if (CURRENT_AS(char_iterator_backtrack)->u.charpos.enabled) { OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); OP1(SLJIT_MOV, TMP2, 0, base, offset1); + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0); label = LABEL(); - if (type == OP_ANYNL) - compile_newline_move_back(common); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); + OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); + if (CURRENT_AS(char_iterator_backtrack)->u.charpos.othercasebit != 0) + OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, CURRENT_AS(char_iterator_backtrack)->u.charpos.othercasebit); + CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CURRENT_AS(char_iterator_backtrack)->u.charpos.chr, CURRENT_AS(char_iterator_backtrack)->matchingpath); move_back(common, NULL, TRUE); - - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); - if (CURRENT_AS(char_iterator_backtrack)->charpos.othercasebit != 0) - OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, CURRENT_AS(char_iterator_backtrack)->charpos.othercasebit); - CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CURRENT_AS(char_iterator_backtrack)->charpos.chr, CURRENT_AS(char_iterator_backtrack)->matchingpath); - /* The range beginning must match, no need to compare. */ - JUMPTO(SLJIT_JUMP, label); - - set_jumps(current->own_backtracks, LABEL()); - current->own_backtracks = NULL; + CMPTO(SLJIT_GREATER, STR_PTR, 0, TMP2, 0, label); } else { OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); - - if (opcode == OP_STAR && exact == 1) - { - if (type == OP_ANYNL) - { - OP1(SLJIT_MOV, TMP2, 0, base, offset1); - compile_newline_move_back(common); - } - - move_back(common, NULL, TRUE); - jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, base, offset1); - } - else - { - if (type == OP_ANYNL) - { - OP1(SLJIT_MOV, TMP2, 0, base, offset1); - jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0); - compile_newline_move_back(common); - } - else - jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, base, offset1); - - move_back(common, NULL, TRUE); - } - + jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, base, offset1); + move_back(common, NULL, TRUE); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath); - - set_jumps(current->own_backtracks, LABEL()); } - JUMPHERE(jump); if (private_data_ptr == 0) free_stack(common, 2); } break; - case OP_QUERY: - OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); - OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0); - CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(char_iterator_backtrack)->matchingpath); - jump = JUMP(SLJIT_JUMP); - set_jumps(current->own_backtracks, LABEL()); - OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); - OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0); - JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath); - JUMPHERE(jump); - if (private_data_ptr == 0) - free_stack(common, 1); - break; - case OP_MINSTAR: OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); - if (exact == 0) - { - compile_char1_matchingpath(common, type, cc, &jumplist, TRUE); - OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); - } - else if (exact > 1) - OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1); - + compile_char1_matchingpath(common, type, cc, &jumplist, TRUE); + OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath); - set_jumps(exact > 0 ? current->own_backtracks : jumplist, LABEL()); + set_jumps(jumplist, LABEL()); if (private_data_ptr == 0) free_stack(common, 1); break; @@ -11899,60 +12879,56 @@ switch(opcode) OP1(SLJIT_MOV, TMP1, 0, base, offset1); OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); OP2(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); + add_jump(compiler, &jumplist, JUMP(SLJIT_ZERO)); - if (exact == 0) - { - add_jump(compiler, &jumplist, JUMP(SLJIT_ZERO)); - - OP1(SLJIT_MOV, base, offset1, TMP1, 0); - compile_char1_matchingpath(common, type, cc, &jumplist, TRUE); - OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); - JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath); - - set_jumps(jumplist, LABEL()); - } - else - { - if (exact > 1) - OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1); - OP1(SLJIT_MOV, base, offset1, TMP1, 0); - JUMPTO(SLJIT_NOT_ZERO, CURRENT_AS(char_iterator_backtrack)->matchingpath); - - set_jumps(current->own_backtracks, LABEL()); - } + OP1(SLJIT_MOV, base, offset1, TMP1, 0); + compile_char1_matchingpath(common, type, cc, &jumplist, TRUE); + OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); + JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath); + set_jumps(jumplist, LABEL()); if (private_data_ptr == 0) free_stack(common, 2); break; - case OP_MINQUERY: + case OP_QUERY: OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0); + CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(char_iterator_backtrack)->matchingpath); + jump = JUMP(SLJIT_JUMP); + set_jumps(CURRENT_AS(char_iterator_backtrack)->u.backtracks, LABEL()); + OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); + OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0); + JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath); + JUMPHERE(jump); + if (private_data_ptr == 0) + free_stack(common, 1); + break; - if (exact >= 1) - { - if (exact >= 2) - OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1); - CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(char_iterator_backtrack)->matchingpath); - set_jumps(current->own_backtracks, LABEL()); - } - else - { - jump = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); - compile_char1_matchingpath(common, type, cc, &jumplist, TRUE); - JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath); - set_jumps(jumplist, LABEL()); - JUMPHERE(jump); - } - + case OP_MINQUERY: + OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); + OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0); + jump = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); + compile_char1_matchingpath(common, type, cc, &jumplist, TRUE); + JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath); + set_jumps(jumplist, LABEL()); + JUMPHERE(jump); if (private_data_ptr == 0) free_stack(common, 1); break; + case OP_EXACT: + case OP_POSSTAR: + case OP_POSQUERY: + case OP_POSUPTO: + break; + default: SLJIT_UNREACHABLE(); break; } + +set_jumps(current->own_backtracks, LABEL()); } static SLJIT_INLINE void compile_ref_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current) @@ -11962,7 +12938,7 @@ PCRE2_SPTR cc = current->cc; BOOL ref = (*cc == OP_REF || *cc == OP_REFI); PCRE2_UCHAR type; -type = cc[PRIV(OP_lengths)[*cc]]; +type = cc[ref ? 1 + IMM2_SIZE : 1 + 2 * IMM2_SIZE]; if ((type & 0x1) == 0) { @@ -12081,7 +13057,7 @@ PCRE2_SPTR ccbegin; PCRE2_SPTR ccprev; PCRE2_UCHAR bra = OP_BRA; PCRE2_UCHAR ket; -const assert_backtrack *assert; +assert_backtrack *assert; BOOL has_alternatives; BOOL needs_control_head = FALSE; BOOL has_vreverse; @@ -12117,7 +13093,7 @@ ccbegin = cc; cc += GET(cc, 1); has_alternatives = *cc == OP_ALT; if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) - has_alternatives = (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT) || CURRENT_AS(bracket_backtrack)->u.no_capture != NULL; + has_alternatives = (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT) || CURRENT_AS(bracket_backtrack)->u.condfailed != NULL; if (opcode == OP_CBRA || opcode == OP_SCBRA) offset = (GET2(ccbegin, 1 + LINK_SIZE)) << 1; if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN)) @@ -12220,27 +13196,14 @@ if (offset != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP2, 0); } } -else if (SLJIT_UNLIKELY(opcode == OP_ASSERT_SCS)) - { - OP1(SLJIT_MOV, TMP1, 0, STR_END, 0); - OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw), TMP1, 0); - - /* Nested scs blocks will not update this variable. */ - if (common->restore_end_ptr == 0) - common->restore_end_ptr = private_data_ptr + sizeof(sljit_sw); - } if (SLJIT_UNLIKELY(opcode == OP_ONCE)) { - int framesize = CURRENT_AS(bracket_backtrack)->u.framesize; - - SLJIT_ASSERT(framesize != 0); - if (framesize > 0) + if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0) { OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize - 1) * sizeof(sljit_sw)); + OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (CURRENT_AS(bracket_backtrack)->u.framesize - 1) * sizeof(sljit_sw)); } once = JUMP(SLJIT_JUMP); } @@ -12265,8 +13228,8 @@ else if (has_alternatives) { sljit_emit_ijump(compiler, SLJIT_JUMP, TMP1, 0); - SLJIT_ASSERT(CURRENT_AS(bracket_backtrack)->matching_mov_addr != NULL); - sljit_set_label(CURRENT_AS(bracket_backtrack)->matching_mov_addr, LABEL()); + SLJIT_ASSERT(CURRENT_AS(bracket_backtrack)->u.matching_mov_addr); + sljit_set_label(CURRENT_AS(bracket_backtrack)->u.matching_mov_addr, LABEL()); sljit_emit_op0(compiler, SLJIT_ENDBR); } else @@ -12284,8 +13247,7 @@ if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) { SLJIT_ASSERT(has_alternatives); assert = CURRENT_AS(bracket_backtrack)->u.assert; - SLJIT_ASSERT(assert->framesize != 0); - if (assert->framesize > 0 && (ccbegin[1 + LINK_SIZE] == OP_ASSERT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK)) + if (assert->framesize >= 0 && (ccbegin[1 + LINK_SIZE] == OP_ASSERT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK)) { OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); @@ -12296,11 +13258,11 @@ if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) cond = JUMP(SLJIT_JUMP); set_jumps(CURRENT_AS(bracket_backtrack)->u.assert->condfailed, LABEL()); } - else if (CURRENT_AS(bracket_backtrack)->u.no_capture != NULL) + else if (CURRENT_AS(bracket_backtrack)->u.condfailed != NULL) { SLJIT_ASSERT(has_alternatives); cond = JUMP(SLJIT_JUMP); - set_jumps(CURRENT_AS(bracket_backtrack)->u.no_capture, LABEL()); + set_jumps(CURRENT_AS(bracket_backtrack)->u.condfailed, LABEL()); } else SLJIT_ASSERT(!has_alternatives); @@ -12321,33 +13283,26 @@ if (has_alternatives) cc += GET(cc, 1); has_vreverse = FALSE; - - switch (opcode) + if (opcode == OP_ASSERTBACK || opcode == OP_ASSERTBACK_NA) { - case OP_ASSERTBACK: - case OP_ASSERTBACK_NA: - SLJIT_ASSERT(private_data_ptr != 0); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); + SLJIT_ASSERT(private_data_ptr != 0); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); - has_vreverse = (*ccprev == OP_VREVERSE); - if (*ccprev == OP_REVERSE || has_vreverse) - ccprev = compile_reverse_matchingpath(common, ccprev, current); - break; - case OP_ASSERT_SCS: - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(2)); - break; - case OP_ONCE: - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(needs_control_head ? 1 : 0)); - break; - case OP_COND: - case OP_SCOND: - break; - default: + has_vreverse = (*ccprev == OP_VREVERSE); + if (*ccprev == OP_REVERSE || has_vreverse) + ccprev = compile_reverse_matchingpath(common, ccprev, current); + } + else if (opcode != OP_COND && opcode != OP_SCOND) + { + if (opcode != OP_ONCE) + { if (private_data_ptr != 0) OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); else OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - break; + } + else + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(needs_control_head ? 1 : 0)); } compile_matchingpath(common, ccprev, cc, current); @@ -12468,18 +13423,14 @@ if (has_alternatives) if (cond != NULL) { SLJIT_ASSERT(opcode == OP_COND || opcode == OP_SCOND); - if (ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT) + assert = CURRENT_AS(bracket_backtrack)->u.assert; + if ((ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT) && assert->framesize >= 0) { - assert = CURRENT_AS(bracket_backtrack)->u.assert; - SLJIT_ASSERT(assert->framesize != 0); - if (assert->framesize > 0) - { - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr); - add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-2)); - OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (assert->framesize - 1) * sizeof(sljit_sw)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, TMP1, 0); - } + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr); + add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-2)); + OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (assert->framesize - 1) * sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, TMP1, 0); } JUMPHERE(cond); } @@ -12521,21 +13472,6 @@ else if (opcode == OP_ASSERT_NA || opcode == OP_ASSERTBACK_NA || opcode == OP_SC OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); } -else if (opcode == OP_ASSERT_SCS) - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); - OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw), TMP2, 0); - free_stack(common, has_alternatives ? 3 : 2); - - set_jumps(CURRENT_AS(bracket_backtrack)->u.no_capture, LABEL()); - - /* Nested scs blocks will not update this variable. */ - if (common->restore_end_ptr == private_data_ptr + SSIZE_OF(sw)) - common->restore_end_ptr = 0; - } else if (opcode == OP_ONCE) { cc = ccbegin + GET(ccbegin, 1); @@ -12716,9 +13652,6 @@ if (opcode == OP_THEN || opcode == OP_THEN_ARG) } } -if (common->restore_end_ptr != 0 && opcode != OP_SKIP_ARG) - OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->restore_end_ptr); - if (common->local_quit_available) { /* Abort match with a fail. */ @@ -12736,18 +13669,8 @@ if (opcode == OP_SKIP_ARG) OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(current->cc + 2)); sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(do_search_mark)); - if (common->restore_end_ptr == 0) - { - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_R0, 0); - add_jump(compiler, &common->reset_match, CMP(SLJIT_NOT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0)); - return; - } - - jump = CMP(SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_R0, 0); - OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->restore_end_ptr); - add_jump(compiler, &common->reset_match, JUMP(SLJIT_JUMP)); - JUMPHERE(jump); + add_jump(compiler, &common->reset_match, CMP(SLJIT_NOT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0)); return; } @@ -12779,7 +13702,6 @@ static SLJIT_INLINE void compile_then_trap_backtrackingpath(compiler_common *com { DEFINE_COMPILER; struct sljit_jump *jump; -int framesize; int size; if (CURRENT_AS(then_trap_backtrack)->then_trap) @@ -12796,15 +13718,11 @@ free_stack(common, size); jump = JUMP(SLJIT_JUMP); set_jumps(CURRENT_AS(then_trap_backtrack)->quit, LABEL()); - -framesize = CURRENT_AS(then_trap_backtrack)->framesize; -SLJIT_ASSERT(framesize != 0); - /* STACK_TOP is set by THEN. */ -if (framesize > 0) +if (CURRENT_AS(then_trap_backtrack)->framesize >= 0) { add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize - 1) * sizeof(sljit_sw)); + OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (CURRENT_AS(then_trap_backtrack)->framesize - 1) * sizeof(sljit_sw)); } OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 3); @@ -12895,13 +13813,10 @@ while (current) case OP_TYPEPOSPLUS: case OP_TYPEPOSQUERY: case OP_TYPEPOSUPTO: - /* Since classes has no backtracking path, this - backtrackingpath was pushed by an iterator. */ case OP_CLASS: case OP_NCLASS: #if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8 case OP_XCLASS: - case OP_ECLASS: #endif compile_iterator_backtrackingpath(common, current); break; @@ -12926,7 +13841,6 @@ while (current) case OP_ASSERT_NA: case OP_ASSERTBACK_NA: - case OP_ASSERT_SCS: case OP_ONCE: case OP_SCRIPT_RUN: case OP_BRA: @@ -12978,12 +13892,8 @@ while (current) case OP_COMMIT: case OP_COMMIT_ARG: - if (common->restore_end_ptr != 0) - OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->restore_end_ptr); - if (!common->local_quit_available) OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH); - if (common->quit_label == NULL) add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP)); else @@ -13244,7 +14154,8 @@ int private_data_size; PCRE2_SPTR ccend; executable_functions *functions; void *executable_func; -sljit_uw executable_size, private_data_length, total_length; +sljit_uw executable_size; +sljit_uw total_length; struct sljit_label *mainloop_label = NULL; struct sljit_label *continue_match_label; struct sljit_label *empty_match_found_label = NULL; @@ -13271,7 +14182,7 @@ memset(&rootbacktrack, 0, sizeof(backtrack_common)); memset(common, 0, sizeof(compiler_common)); common->re = re; common->name_table = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code)); -rootbacktrack.cc = (PCRE2_SPTR)((uint8_t *)re + re->code_start); +rootbacktrack.cc = common->name_table + re->name_count * re->name_entry_size; #ifdef SUPPORT_UNICODE common->invalid_utf = (mode & PCRE2_JIT_INVALID_UTF) != 0; @@ -13319,7 +14230,7 @@ common->name_entry_size = re->name_entry_size; common->unset_backref = (re->overall_options & PCRE2_MATCH_UNSET_BACKREF) != 0; common->alt_circumflex = (re->overall_options & PCRE2_ALT_CIRCUMFLEX) != 0; #ifdef SUPPORT_UNICODE -/* PCRE2_UTF[16|32] have the same value as PCRE2_UTF8. */ +/* PCRE_UTF[16|32] have the same value as PCRE_UTF8. */ common->utf = (re->overall_options & PCRE2_UTF) != 0; common->ucp = (re->overall_options & PCRE2_UCP) != 0; if (common->utf) @@ -13351,26 +14262,10 @@ else ccend = bracketend(common->start); /* Calculate the local space size on the stack. */ -common->ovector_start = LOCAL0; -/* Allocate space for temporary data structures. */ -private_data_length = ccend - common->start; -/* The chance of overflow is very low, but might happen on 32 bit. */ -if (private_data_length > ~(sljit_uw)0 / sizeof(sljit_s32)) +common->ovector_start = LIMIT_MATCH + sizeof(sljit_sw); +common->optimized_cbracket = (sljit_u8 *)SLJIT_MALLOC(re->top_bracket + 1, allocator_data); +if (!common->optimized_cbracket) return PCRE2_ERROR_NOMEMORY; - -private_data_length *= sizeof(sljit_s32); -/* Align to 32 bit. */ -total_length = ((re->top_bracket + 1) + (sljit_uw)(sizeof(sljit_s32) - 1)) & ~(sljit_uw)(sizeof(sljit_s32) - 1); -if (~(sljit_uw)0 - private_data_length < total_length) - return PCRE2_ERROR_NOMEMORY; - -total_length += private_data_length; -common->private_data_ptrs = (sljit_s32*)SLJIT_MALLOC(total_length, allocator_data); -if (!common->private_data_ptrs) - return PCRE2_ERROR_NOMEMORY; - -memset(common->private_data_ptrs, 0, private_data_length); -common->optimized_cbracket = ((sljit_u8 *)common->private_data_ptrs) + private_data_length; #if defined DEBUG_FORCE_UNOPTIMIZED_CBRAS && DEBUG_FORCE_UNOPTIMIZED_CBRAS == 1 memset(common->optimized_cbracket, 0, re->top_bracket + 1); #else @@ -13384,19 +14279,16 @@ common->ovector_start += sizeof(sljit_sw); #endif if (!check_opcode_types(common, common->start, ccend)) { - SLJIT_FREE(common->private_data_ptrs, allocator_data); - return PCRE2_ERROR_JIT_UNSUPPORTED; + SLJIT_FREE(common->optimized_cbracket, allocator_data); + return PCRE2_ERROR_NOMEMORY; } /* Checking flags and updating ovector_start. */ -if (mode == PCRE2_JIT_COMPLETE && - (re->flags & PCRE2_LASTSET) != 0 && - (re->optimization_flags & PCRE2_OPTIM_START_OPTIMIZE) != 0) +if (mode == PCRE2_JIT_COMPLETE && (re->flags & PCRE2_LASTSET) != 0 && (re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0) { common->req_char_ptr = common->ovector_start; common->ovector_start += sizeof(sljit_sw); } - if (mode != PCRE2_JIT_COMPLETE) { common->start_used_ptr = common->ovector_start; @@ -13407,23 +14299,19 @@ if (mode != PCRE2_JIT_COMPLETE) common->ovector_start += sizeof(sljit_sw); } } - if ((re->overall_options & (PCRE2_FIRSTLINE | PCRE2_USE_OFFSET_LIMIT)) != 0) { common->match_end_ptr = common->ovector_start; common->ovector_start += sizeof(sljit_sw); } - #if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD common->control_head_ptr = 1; #endif - if (common->control_head_ptr != 0) { common->control_head_ptr = common->ovector_start; common->ovector_start += sizeof(sljit_sw); } - if (common->has_set_som) { /* Saving the real start pointer is necessary. */ @@ -13444,11 +14332,19 @@ if (common->capture_last_ptr != 0) SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0)); common->cbra_ptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_sw); + +total_length = ccend - common->start; +common->private_data_ptrs = (sljit_s32*)SLJIT_MALLOC(total_length * (sizeof(sljit_s32) + (common->has_then ? 1 : 0)), allocator_data); +if (!common->private_data_ptrs) + { + SLJIT_FREE(common->optimized_cbracket, allocator_data); + return PCRE2_ERROR_NOMEMORY; + } +memset(common->private_data_ptrs, 0, total_length * sizeof(sljit_s32)); + private_data_size = common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw); -if ((re->overall_options & PCRE2_ANCHORED) == 0 && - (re->optimization_flags & PCRE2_OPTIM_START_OPTIMIZE) != 0 && - !common->has_skip_in_assert_back) +if ((re->overall_options & PCRE2_ANCHORED) == 0 && (re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0 && !common->has_skip_in_assert_back) detect_early_fail(common, common->start, &private_data_size, 0, 0); set_private_data_ptrs(common, &private_data_size, ccend); @@ -13458,18 +14354,13 @@ SLJIT_ASSERT(common->early_fail_start_ptr <= common->early_fail_end_ptr); if (private_data_size > 65536) { SLJIT_FREE(common->private_data_ptrs, allocator_data); - return PCRE2_ERROR_JIT_UNSUPPORTED; + SLJIT_FREE(common->optimized_cbracket, allocator_data); + return PCRE2_ERROR_NOMEMORY; } if (common->has_then) { - total_length = ccend - common->start; - common->then_offsets = (sljit_u8 *)SLJIT_MALLOC(total_length, allocator_data); - if (!common->then_offsets) - { - SLJIT_FREE(common->private_data_ptrs, allocator_data); - return PCRE2_ERROR_NOMEMORY; - } + common->then_offsets = (sljit_u8 *)(common->private_data_ptrs + total_length); memset(common->then_offsets, 0, total_length); set_then_offsets(common, common->start, NULL); } @@ -13477,16 +14368,15 @@ if (common->has_then) compiler = sljit_create_compiler(allocator_data); if (!compiler) { + SLJIT_FREE(common->optimized_cbracket, allocator_data); SLJIT_FREE(common->private_data_ptrs, allocator_data); - if (common->has_then) - SLJIT_FREE(common->then_offsets, allocator_data); return PCRE2_ERROR_NOMEMORY; } common->compiler = compiler; /* Main pcre2_jit_exec entry. */ SLJIT_ASSERT((private_data_size & (sizeof(sljit_sw) - 1)) == 0); -sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, W), 5 | SLJIT_ENTER_VECTOR(SLJIT_NUMBER_OF_SCRATCH_VECTOR_REGISTERS), 5, private_data_size); +sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, W), 5, 5, SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS, 0, private_data_size); /* Register init. */ reset_ovector(common, (re->top_bracket + 1) * 2); @@ -13520,7 +14410,7 @@ if ((re->overall_options & PCRE2_ANCHORED) == 0) mainloop_label = mainloop_entry(common); continue_match_label = LABEL(); /* Forward search if possible. */ - if ((re->optimization_flags & PCRE2_OPTIM_START_OPTIMIZE) != 0) + if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0) { if (mode == PCRE2_JIT_COMPLETE && fast_forward_first_n_chars(common)) ; @@ -13535,8 +14425,7 @@ if ((re->overall_options & PCRE2_ANCHORED) == 0) else continue_match_label = LABEL(); -if (mode == PCRE2_JIT_COMPLETE && re->minlength > 0 && - (re->optimization_flags & PCRE2_OPTIM_START_OPTIMIZE) != 0) +if (mode == PCRE2_JIT_COMPLETE && re->minlength > 0 && (re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0) { OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH); OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(re->minlength)); @@ -13571,9 +14460,8 @@ compile_matchingpath(common, common->start, ccend, &rootbacktrack); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) { sljit_free_compiler(compiler); + SLJIT_FREE(common->optimized_cbracket, allocator_data); SLJIT_FREE(common->private_data_ptrs, allocator_data); - if (common->has_then) - SLJIT_FREE(common->then_offsets, allocator_data); PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data); return PCRE2_ERROR_NOMEMORY; } @@ -13628,9 +14516,8 @@ compile_backtrackingpath(common, rootbacktrack.top); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) { sljit_free_compiler(compiler); + SLJIT_FREE(common->optimized_cbracket, allocator_data); SLJIT_FREE(common->private_data_ptrs, allocator_data); - if (common->has_then) - SLJIT_FREE(common->then_offsets, allocator_data); PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data); return PCRE2_ERROR_NOMEMORY; } @@ -13711,8 +14598,6 @@ common->early_fail_end_ptr = 0; common->currententry = common->entries; common->local_quit_available = TRUE; quit_label = common->quit_label; -SLJIT_ASSERT(common->restore_end_ptr == 0); - if (common->currententry != NULL) { /* A free bit for each private data. */ @@ -13742,28 +14627,24 @@ if (common->currententry != NULL) SLJIT_ASSERT(sljit_get_compiler_error(compiler) || common->recurse_bitset == NULL); sljit_free_compiler(compiler); + SLJIT_FREE(common->optimized_cbracket, allocator_data); SLJIT_FREE(common->private_data_ptrs, allocator_data); - if (common->has_then) - SLJIT_FREE(common->then_offsets, allocator_data); PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data); return PCRE2_ERROR_NOMEMORY; } } - common->local_quit_available = FALSE; common->quit_label = quit_label; -SLJIT_ASSERT(common->restore_end_ptr == 0); -/* Allocating stack, returns with PCRE2_ERROR_JIT_STACKLIMIT if fails. */ +/* Allocating stack, returns with PCRE_ERROR_JIT_STACKLIMIT if fails. */ /* This is a (really) rare case. */ set_jumps(common->stackalloc, LABEL()); /* RETURN_ADDR is not a saved register. */ -SLJIT_ASSERT(common->locals_size >= 2 * SSIZE_OF(sw)); -sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_SP), LOCAL0); +sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_SP), LOCALS0); SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL1, STR_PTR, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0); OP2(SLJIT_SUB, SLJIT_R1, 0, STACK_LIMIT, 0, SLJIT_IMM, STACK_GROWTH_RATE); OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, stack)); @@ -13774,8 +14655,8 @@ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM, SLJIT_FU jump = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); OP1(SLJIT_MOV, TMP2, 0, STACK_LIMIT, 0); OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_RETURN_REG, 0); -OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0); -OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCAL1); +OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); +OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); OP_SRC(SLJIT_FAST_RETURN, TMP1, 0); /* Allocation failed. */ @@ -13896,9 +14777,8 @@ if (common->getucdtype != NULL) } #endif /* SUPPORT_UNICODE */ +SLJIT_FREE(common->optimized_cbracket, allocator_data); SLJIT_FREE(common->private_data_ptrs, allocator_data); -if (common->has_then) - SLJIT_FREE(common->then_offsets, allocator_data); executable_func = sljit_generate_code(compiler, 0, NULL); executable_size = sljit_get_generated_code_size(compiler); @@ -13968,36 +14848,9 @@ pcre2_jit_compile(pcre2_code *code, uint32_t options) { pcre2_real_code *re = (pcre2_real_code *)code; #ifdef SUPPORT_JIT -void *exec_memory; executable_functions *functions; static int executable_allocator_is_working = -1; - -if (executable_allocator_is_working == -1) - { - /* Checks whether the executable allocator is working. This check - might run multiple times in multi-threaded environments, but the - result should not be affected by it. */ - exec_memory = SLJIT_MALLOC_EXEC(32, NULL); - if (exec_memory != NULL) - { - SLJIT_FREE_EXEC(((sljit_u8*)(exec_memory)) + SLJIT_EXEC_OFFSET(exec_memory), NULL); - executable_allocator_is_working = 1; - } - else executable_allocator_is_working = 0; - } -#endif - -if (options & PCRE2_JIT_TEST_ALLOC) - { - if (options != PCRE2_JIT_TEST_ALLOC) - return PCRE2_ERROR_JIT_BADOPTION; - -#ifdef SUPPORT_JIT - return executable_allocator_is_working ? 0 : PCRE2_ERROR_NOMEMORY; -#else - return PCRE2_ERROR_JIT_UNSUPPORTED; #endif - } if (code == NULL) return PCRE2_ERROR_NULL; @@ -14059,6 +14912,20 @@ return PCRE2_ERROR_JIT_BADOPTION; if ((re->flags & PCRE2_NOJIT) != 0) return 0; +if (executable_allocator_is_working == -1) + { + /* Checks whether the executable allocator is working. This check + might run multiple times in multi-threaded environments, but the + result should not be affected by it. */ + void *ptr = SLJIT_MALLOC_EXEC(32, NULL); + if (ptr != NULL) + { + SLJIT_FREE_EXEC(((sljit_u8*)(ptr)) + SLJIT_EXEC_OFFSET(ptr), NULL); + executable_allocator_is_working = 1; + } + else executable_allocator_is_working = 0; + } + if (!executable_allocator_is_working) return PCRE2_ERROR_NOMEMORY; diff --git a/ext/pcre/pcre2lib/pcre2_jit_match.c b/ext/pcre/pcre2lib/pcre2_jit_match.c index 8867f768df15c..ae5903e202b57 100644 --- a/ext/pcre/pcre2lib/pcre2_jit_match.c +++ b/ext/pcre/pcre2lib/pcre2_jit_match.c @@ -83,7 +83,7 @@ return executable_func(arguments); Returns: > 0 => success; value is the number of ovector pairs filled = 0 => success, but ovector is not big enough - -1 => failed to match (PCRE2_ERROR_NOMATCH) + -1 => failed to match (PCRE_ERROR_NOMATCH) < -1 => some kind of unexpected problem */ diff --git a/ext/pcre/pcre2lib/pcre2_jit_neon_inc.h b/ext/pcre/pcre2lib/pcre2_jit_neon_inc.h index 1389a16573d56..4a718b67b7eba 100644 --- a/ext/pcre/pcre2lib/pcre2_jit_neon_inc.h +++ b/ext/pcre/pcre2lib/pcre2_jit_neon_inc.h @@ -82,7 +82,7 @@ POSSIBILITY OF SUCH DAMAGE. # endif # endif -#if (defined(__GNUC__) && defined(__SANITIZE_ADDRESS__) && __SANITIZE_ADDRESS__ ) \ +#if (defined(__GNUC__) && __SANITIZE_ADDRESS__) \ || (defined(__clang__) \ && ((__clang_major__ == 3 && __clang_minor__ >= 3) || (__clang_major__ > 3))) __attribute__((no_sanitize_address)) @@ -198,14 +198,14 @@ vect_t data = VLD1Q(*str_ptr); #if PCRE2_CODE_UNIT_WIDTH != 8 data = VANDQ(data, char_mask); #endif - + #if defined(FFCS) vect_t eq = VCEQQ(data, vc1); #elif defined(FFCS_2) vect_t eq1 = VCEQQ(data, vc1); vect_t eq2 = VCEQQ(data, vc2); -vect_t eq = VORRQ(eq1, eq2); +vect_t eq = VORRQ(eq1, eq2); #elif defined(FFCS_MASK) vect_t eq = VORRQ(data, vmask); @@ -226,7 +226,7 @@ if (p1 < *str_ptr) } else data2 = shift_left_n_lanes(data, offs1 - offs2); - + if (compare1_type == compare_match1) data = VCEQQ(data, cmp1a); else @@ -281,7 +281,7 @@ while (*str_ptr < str_end) #elif defined(FFCS_2) eq1 = VCEQQ(data, vc1); eq2 = VCEQQ(data, vc2); - eq = VORRQ(eq1, eq2); + eq = VORRQ(eq1, eq2); #elif defined(FFCS_MASK) eq = VORRQ(data, vmask); diff --git a/ext/pcre/pcre2lib/pcre2_jit_simd_inc.h b/ext/pcre/pcre2lib/pcre2_jit_simd_inc.h index 66e93cd5996fd..502977fc32045 100644 --- a/ext/pcre/pcre2lib/pcre2_jit_simd_inc.h +++ b/ext/pcre/pcre2lib/pcre2_jit_simd_inc.h @@ -246,10 +246,10 @@ struct sljit_jump *quit; struct sljit_jump *partial_quit[2]; vector_compare_type compare_type = vector_compare_match1; sljit_s32 tmp1_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, TMP1); -sljit_s32 data_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR0); -sljit_s32 cmp1_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR1); -sljit_s32 cmp2_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR2); -sljit_s32 tmp_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR3); +sljit_s32 data_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0); +sljit_s32 cmp1_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR1); +sljit_s32 cmp2_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR2); +sljit_s32 tmp_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR3); sljit_u32 bit = 0; int i; @@ -273,17 +273,17 @@ if (common->mode == PCRE2_JIT_COMPLETE) /* First part (unaligned start) */ value = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_LANE_ZERO; -sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR1, 0, SLJIT_IMM, character_to_int32(char1 | bit)); +sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR1, 0, SLJIT_IMM, character_to_int32(char1 | bit)); if (char1 != char2) - sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR2, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2)); + sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR2, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2)); OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0); -sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR1, SLJIT_VR1, 0); +sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR1, SLJIT_FR1, 0); if (char1 != char2) - sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR2, SLJIT_VR2, 0); + sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR2, SLJIT_FR2, 0); #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 restart = LABEL(); @@ -294,12 +294,12 @@ OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~value); OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, value); value = (reg_type == SLJIT_SIMD_REG_256) ? SLJIT_SIMD_MEM_ALIGNED_256 : SLJIT_SIMD_MEM_ALIGNED_128; -sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_VR0, SLJIT_MEM1(STR_PTR), 0); +sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_FR0, SLJIT_MEM1(STR_PTR), 0); for (i = 0; i < 4; i++) fast_forward_char_pair_sse2_compare(compiler, compare_type, reg_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind); -sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_VR0, TMP1, 0); +sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_FR0, TMP1, 0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0); @@ -318,11 +318,11 @@ if (common->mode == PCRE2_JIT_COMPLETE) add_jump(compiler, &common->failed_match, partial_quit[1]); value = (reg_type == SLJIT_SIMD_REG_256) ? SLJIT_SIMD_MEM_ALIGNED_256 : SLJIT_SIMD_MEM_ALIGNED_128; -sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_VR0, SLJIT_MEM1(STR_PTR), 0); +sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_FR0, SLJIT_MEM1(STR_PTR), 0); for (i = 0; i < 4; i++) fast_forward_char_pair_sse2_compare(compiler, compare_type, reg_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind); -sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_VR0, TMP1, 0); +sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_FR0, TMP1, 0); CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start); JUMPHERE(quit); @@ -380,10 +380,10 @@ struct sljit_jump *quit; jump_list *not_found = NULL; vector_compare_type compare_type = vector_compare_match1; sljit_s32 tmp1_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, TMP1); -sljit_s32 data_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR0); -sljit_s32 cmp1_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR1); -sljit_s32 cmp2_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR2); -sljit_s32 tmp_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR3); +sljit_s32 data_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0); +sljit_s32 cmp1_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR1); +sljit_s32 cmp2_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR2); +sljit_s32 tmp_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR3); sljit_u32 bit = 0; int i; @@ -406,29 +406,29 @@ OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0); /* First part (unaligned start) */ value = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_LANE_ZERO; -sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR1, 0, SLJIT_IMM, character_to_int32(char1 | bit)); +sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR1, 0, SLJIT_IMM, character_to_int32(char1 | bit)); if (char1 != char2) - sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR2, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2)); + sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR2, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2)); OP1(SLJIT_MOV, STR_PTR, 0, TMP2, 0); -sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR1, SLJIT_VR1, 0); +sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR1, SLJIT_FR1, 0); if (char1 != char2) - sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR2, SLJIT_VR2, 0); + sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR2, SLJIT_FR2, 0); value = (reg_type == SLJIT_SIMD_REG_256) ? 0x1f : 0xf; OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~value); OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, value); value = (reg_type == SLJIT_SIMD_REG_256) ? SLJIT_SIMD_MEM_ALIGNED_256 : SLJIT_SIMD_MEM_ALIGNED_128; -sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_VR0, SLJIT_MEM1(STR_PTR), 0); +sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_FR0, SLJIT_MEM1(STR_PTR), 0); for (i = 0; i < 4; i++) fast_forward_char_pair_sse2_compare(compiler, compare_type, reg_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind); -sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_VR0, TMP1, 0); +sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_FR0, TMP1, 0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0); @@ -445,12 +445,12 @@ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, value); add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); value = (reg_type == SLJIT_SIMD_REG_256) ? SLJIT_SIMD_MEM_ALIGNED_256 : SLJIT_SIMD_MEM_ALIGNED_128; -sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_VR0, SLJIT_MEM1(STR_PTR), 0); +sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_FR0, SLJIT_MEM1(STR_PTR), 0); for (i = 0; i < 4; i++) fast_forward_char_pair_sse2_compare(compiler, compare_type, reg_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind); -sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_VR0, TMP1, 0); +sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_FR0, TMP1, 0); CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start); JUMPHERE(quit); @@ -488,14 +488,14 @@ sljit_u32 bit1 = 0; sljit_u32 bit2 = 0; sljit_u32 diff = IN_UCHARS(offs1 - offs2); sljit_s32 tmp1_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, TMP1); -sljit_s32 data1_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR0); -sljit_s32 data2_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR1); -sljit_s32 cmp1a_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR2); -sljit_s32 cmp2a_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR3); -sljit_s32 cmp1b_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR4); -sljit_s32 cmp2b_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR5); -sljit_s32 tmp1_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR6); -sljit_s32 tmp2_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_TMP_DEST_VREG); +sljit_s32 data1_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0); +sljit_s32 data2_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR1); +sljit_s32 cmp1a_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR2); +sljit_s32 cmp2a_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR3); +sljit_s32 cmp1b_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR4); +sljit_s32 cmp2b_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR5); +sljit_s32 tmp1_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR6); +sljit_s32 tmp2_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_TMP_FR0); struct sljit_label *start; #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 struct sljit_label *restart; @@ -541,10 +541,10 @@ else } value = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_LANE_ZERO; -sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR2, 0, TMP1, 0); +sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR2, 0, TMP1, 0); if (char1a != char1b) - sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR4, 0, TMP2, 0); + sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR4, 0, TMP2, 0); if (char2a == char2b) OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a)); @@ -566,18 +566,18 @@ else } } -sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR3, 0, TMP1, 0); +sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR3, 0, TMP1, 0); if (char2a != char2b) - sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR5, 0, TMP2, 0); + sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR5, 0, TMP2, 0); -sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR2, SLJIT_VR2, 0); +sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR2, SLJIT_FR2, 0); if (char1a != char1b) - sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR4, SLJIT_VR4, 0); + sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR4, SLJIT_FR4, 0); -sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR3, SLJIT_VR3, 0); +sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR3, SLJIT_FR3, 0); if (char2a != char2b) - sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR5, SLJIT_VR5, 0); + sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR5, SLJIT_FR5, 0); #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 restart = LABEL(); @@ -589,11 +589,11 @@ value = (reg_type == SLJIT_SIMD_REG_256) ? ~0x1f : ~0xf; OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, value); value = (reg_type == SLJIT_SIMD_REG_256) ? SLJIT_SIMD_MEM_ALIGNED_256 : SLJIT_SIMD_MEM_ALIGNED_128; -sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_VR0, SLJIT_MEM1(STR_PTR), 0); +sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_FR0, SLJIT_MEM1(STR_PTR), 0); jump[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_PTR, 0); -sljit_emit_simd_mov(compiler, reg_type, SLJIT_VR1, SLJIT_MEM1(STR_PTR), -(sljit_sw)diff); +sljit_emit_simd_mov(compiler, reg_type, SLJIT_FR1, SLJIT_MEM1(STR_PTR), -(sljit_sw)diff); jump[1] = JUMP(SLJIT_JUMP); JUMPHERE(jump[0]); @@ -668,8 +668,8 @@ for (i = 0; i < 4; i++) fast_forward_char_pair_sse2_compare(compiler, compare1_type, reg_type, i, data1_ind, cmp1a_ind, cmp1b_ind, tmp1_ind); } -sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | reg_type, SLJIT_VR0, SLJIT_VR0, SLJIT_VR1, 0); -sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_VR0, TMP1, 0); +sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | reg_type, SLJIT_FR0, SLJIT_FR0, SLJIT_FR1); +sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_FR0, TMP1, 0); /* Ignore matches before the first STR_PTR. */ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); @@ -687,8 +687,8 @@ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, value); add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); value = (reg_type == SLJIT_SIMD_REG_256) ? SLJIT_SIMD_MEM_ALIGNED_256 : SLJIT_SIMD_MEM_ALIGNED_128; -sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_VR0, SLJIT_MEM1(STR_PTR), 0); -sljit_emit_simd_mov(compiler, reg_type, SLJIT_VR1, SLJIT_MEM1(STR_PTR), -(sljit_sw)diff); +sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_FR0, SLJIT_MEM1(STR_PTR), 0); +sljit_emit_simd_mov(compiler, reg_type, SLJIT_FR1, SLJIT_MEM1(STR_PTR), -(sljit_sw)diff); for (i = 0; i < 4; i++) { @@ -696,8 +696,8 @@ for (i = 0; i < 4; i++) fast_forward_char_pair_sse2_compare(compiler, compare2_type, reg_type, i, data2_ind, cmp2a_ind, cmp2b_ind, tmp1_ind); } -sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | reg_type, SLJIT_VR0, SLJIT_VR0, SLJIT_VR1, 0); -sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_VR0, TMP1, 0); +sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | reg_type, SLJIT_FR0, SLJIT_FR0, SLJIT_FR1); +sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_FR0, TMP1, 0); CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start); @@ -843,13 +843,12 @@ DEFINE_COMPILER; int_char ic; struct sljit_jump *partial_quit, *quit; /* Save temporary registers. */ -SLJIT_ASSERT(common->locals_size >= 2 * (int)sizeof(sljit_sw)); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL0, STR_PTR, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL1, TMP3, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP3, 0); /* Prepare function arguments */ OP1(SLJIT_MOV, SLJIT_R0, 0, STR_END, 0); -GET_LOCAL_BASE(SLJIT_R1, 0, LOCAL0); +GET_LOCAL_BASE(SLJIT_R1, 0, LOCALS0); OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, offset); if (char1 == char2) @@ -911,8 +910,8 @@ else } } /* Restore registers. */ -OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0); -OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(SLJIT_SP), LOCAL1); +OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); +OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); /* Check return value. */ partial_quit = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); @@ -1039,7 +1038,7 @@ SLJIT_ASSERT(diff <= IN_UCHARS(max_fast_forward_char_pair_offset())); SLJIT_ASSERT(compiler->scratches == 5); /* Save temporary register STR_PTR. */ -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL0, STR_PTR, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0); /* Prepare arguments for the function call. */ if (common->match_end_ptr == 0) @@ -1053,7 +1052,7 @@ else SELECT(SLJIT_LESS, SLJIT_R0, STR_END, 0, SLJIT_R0); } -GET_LOCAL_BASE(SLJIT_R1, 0, LOCAL0); +GET_LOCAL_BASE(SLJIT_R1, 0, LOCALS0); OP1(SLJIT_MOV_S32, SLJIT_R2, 0, SLJIT_IMM, offs1); OP1(SLJIT_MOV_S32, SLJIT_R3, 0, SLJIT_IMM, offs2); ic.c.c1 = char1a; @@ -1094,7 +1093,7 @@ if (diff == 1) { } /* Restore STR_PTR register. */ -OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0); +OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); /* Check return value. */ partial_quit = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); diff --git a/ext/pcre/pcre2lib/pcre2_maketables.c b/ext/pcre/pcre2lib/pcre2_maketables.c index 0474cc7dbb41c..ac8b63b8097fb 100644 --- a/ext/pcre/pcre2lib/pcre2_maketables.c +++ b/ext/pcre/pcre2lib/pcre2_maketables.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2024 University of Cambridge + New API code Copyright (c) 2016-2020 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -155,10 +155,10 @@ return yield; PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION pcre2_maketables_free(pcre2_general_context *gcontext, const uint8_t *tables) { -if (gcontext != NULL) - gcontext->memctl.free((void *)tables, gcontext->memctl.memory_data); -else - free((void *)tables); + if (gcontext) + gcontext->memctl.free((void *)tables, gcontext->memctl.memory_data); + else + free((void *)tables); } #endif diff --git a/ext/pcre/pcre2lib/pcre2_match.c b/ext/pcre/pcre2lib/pcre2_match.c index 5adc03480522f..6c422c2e5ef9e 100644 --- a/ext/pcre/pcre2lib/pcre2_match.c +++ b/ext/pcre/pcre2lib/pcre2_match.c @@ -155,17 +155,17 @@ changed, the code at RETURN_SWITCH below must be updated in sync. */ enum { RM1=1, RM2, RM3, RM4, RM5, RM6, RM7, RM8, RM9, RM10, RM11, RM12, RM13, RM14, RM15, RM16, RM17, RM18, RM19, RM20, RM21, RM22, RM23, RM24, RM25, RM26, RM27, RM28, RM29, RM30, - RM31, RM32, RM33, RM34, RM35, RM36, RM37, RM38, RM39 }; + RM31, RM32, RM33, RM34, RM35, RM36, RM37 }; #ifdef SUPPORT_WIDE_CHARS -enum { RM100=100, RM101, RM102, RM103 }; +enum { RM100=100, RM101 }; #endif #ifdef SUPPORT_UNICODE enum { RM200=200, RM201, RM202, RM203, RM204, RM205, RM206, RM207, RM208, RM209, RM210, RM211, RM212, RM213, RM214, RM215, RM216, RM217, RM218, RM219, RM220, RM221, RM222, RM223, - RM224 }; + RM224, RM225 }; #endif /* Define short names for general fields in the current backtrack frame, which @@ -348,7 +348,6 @@ seems unlikely.) Arguments: offset index into the offset vector caseless TRUE if caseless - caseopts bitmask of REFI_FLAG_XYZ values F the current backtracking frame pointer mb points to match block lengthptr pointer for returning the length matched @@ -359,8 +358,8 @@ Returns: = 0 sucessful match; number of code units matched is set */ static int -match_ref(PCRE2_SIZE offset, BOOL caseless, int caseopts, heapframe *F, - match_block *mb, PCRE2_SIZE *lengthptr) +match_ref(PCRE2_SIZE offset, BOOL caseless, heapframe *F, match_block *mb, + PCRE2_SIZE *lengthptr) { PCRE2_SPTR p; PCRE2_SIZE length; @@ -390,8 +389,6 @@ if (caseless) { #if defined SUPPORT_UNICODE BOOL utf = (mb->poptions & PCRE2_UTF) != 0; - BOOL caseless_restrict = (caseopts & REFI_FLAG_CASELESS_RESTRICT) != 0; - BOOL turkish_casing = !caseless_restrict && (caseopts & REFI_FLAG_TURKISH_CASING) != 0; if (utf || (mb->poptions & PCRE2_UCP) != 0) { @@ -423,20 +420,10 @@ if (caseless) d = *p++; } - if (turkish_casing && UCD_ANY_I(d)) - { - c = UCD_FOLD_I_TURKISH(c); - d = UCD_FOLD_I_TURKISH(d); - if (c != d) return -1; /* No match */ - } - else if (c != d && c != (uint32_t)((int)d + (ur = GET_UCD(d))->other_case)) + ur = GET_UCD(d); + if (c != d && c != (uint32_t)((int)d + ur->other_case)) { const uint32_t *pp = PRIV(ucd_caseless_sets) + ur->caseset; - - /* When PCRE2_EXTRA_CASELESS_RESTRICT is set, ignore any caseless sets - that start with an ASCII character. */ - if (caseless_restrict && *pp < 128) return -1; /* No match */ - for (;;) { if (c < *pp) return -1; /* No match */ @@ -541,46 +528,38 @@ For hard partial matching, we immediately return a partial match. Otherwise, carrying on means that a complete match on the current subject will be sought. A partial match is returned only if no complete match can be found. */ -#define CHECK_PARTIAL() \ - do { \ - if (Feptr >= mb->end_subject) \ - { \ - SCHECK_PARTIAL(); \ - } \ - } \ - while (0) - -#define SCHECK_PARTIAL() \ - do { \ - if (mb->partial != 0 && \ - (Feptr > mb->start_used_ptr || mb->allowemptypartial)) \ - { \ - mb->hitend = TRUE; \ - if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; \ - } \ - } \ - while (0) +#define CHECK_PARTIAL()\ + if (Feptr >= mb->end_subject) \ + { \ + SCHECK_PARTIAL(); \ + } + +#define SCHECK_PARTIAL()\ + if (mb->partial != 0 && \ + (Feptr > mb->start_used_ptr || mb->allowemptypartial)) \ + { \ + mb->hitend = TRUE; \ + if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; \ + } /* These macros are used to implement backtracking. They simulate a recursive call to the match() function by means of a local vector of frames which remember the backtracking points. */ -#define RMATCH(ra,rb) \ - do { \ - start_ecode = ra; \ - Freturn_id = rb; \ - goto MATCH_RECURSE; \ - L_##rb:; \ - } \ - while (0) +#define RMATCH(ra,rb)\ + {\ + start_ecode = ra;\ + Freturn_id = rb;\ + goto MATCH_RECURSE;\ + L_##rb:;\ + } -#define RRETURN(ra) \ - do { \ - rrc = ra; \ - goto RETURN_SWITCH; \ - } \ - while (0) +#define RRETURN(ra)\ + {\ + rrc = ra;\ + goto RETURN_SWITCH;\ + } @@ -834,10 +813,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, offset = Flast_group_offset; for(;;) { - /* Corrupted heapframes?. Trigger an assert and return an error */ - PCRE2_ASSERT(offset != PCRE2_UNSET); if (offset == PCRE2_UNSET) return PCRE2_ERROR_INTERNAL; - N = (heapframe *)((char *)match_data->heapframes + offset); P = (heapframe *)((char *)N - frame_size); if (N->group_frame_type == (GF_CAPTURE | number)) break; @@ -876,10 +852,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, offset = Flast_group_offset; for(;;) { - /* Corrupted heapframes?. Trigger an assert and return an error */ - PCRE2_ASSERT(offset != PCRE2_UNSET); if (offset == PCRE2_UNSET) return PCRE2_ERROR_INTERNAL; - N = (heapframe *)((char *)match_data->heapframes + offset); P = (heapframe *)((char *)N - frame_size); if (GF_IDMASK(N->group_frame_type) == GF_RECURSE) break; @@ -1356,7 +1329,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, RRETURN(MATCH_NOMATCH); } } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never gets here */ } else /* Maximize */ @@ -1457,7 +1430,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, if (Lc != cc && Loc != cc) RRETURN(MATCH_NOMATCH); Feptr++; } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never gets here */ } else /* Maximize */ @@ -1515,7 +1488,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, } if (Lc != UCHAR21INCTEST(Feptr)) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never gets here */ } else /* Maximize */ { @@ -1733,7 +1706,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, Feptr++; } } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never gets here */ } /* Maximize case */ @@ -1871,7 +1844,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, if (Lc == *Feptr++) RRETURN(MATCH_NOMATCH); } } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never gets here */ } /* Maximize case */ @@ -1955,7 +1928,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, #define Lmax F->temp_32[1] #define Lstart_eptr F->temp_sptr[0] #define Lbyte_map_address F->temp_sptr[1] -#define Lbyte_map ((const unsigned char *)Lbyte_map_address) +#define Lbyte_map ((unsigned char *)Lbyte_map_address) case OP_NCLASS: case OP_CLASS: @@ -2098,7 +2071,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, if ((Lbyte_map[fc/8] & (1u << (fc&7))) == 0) RRETURN(MATCH_NOMATCH); } } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never gets here */ } /* If maximizing, find the longest possible run, then work backwards. */ @@ -2178,8 +2151,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, RRETURN(MATCH_NOMATCH); } } - - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never gets here */ #undef Lbyte_map_address #undef Lbyte_map @@ -2247,9 +2219,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(fc, Feptr); - if (!PRIV(xclass)(fc, Lxclass_data, - (const uint8_t*)mb->start_code, utf)) - RRETURN(MATCH_NOMATCH); + if (!PRIV(xclass)(fc, Lxclass_data, utf)) RRETURN(MATCH_NOMATCH); } /* If Lmax == Lmin we can just continue with the main loop. */ @@ -2272,11 +2242,9 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(fc, Feptr); - if (!PRIV(xclass)(fc, Lxclass_data, - (const uint8_t*)mb->start_code, utf)) - RRETURN(MATCH_NOMATCH); + if (!PRIV(xclass)(fc, Lxclass_data, utf)) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never gets here */ } /* If maximizing, find the longest possible run, then work backwards. */ @@ -2297,8 +2265,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, #else fc = *Feptr; #endif - if (!PRIV(xclass)(fc, Lxclass_data, - (const uint8_t*)mb->start_code, utf)) break; + if (!PRIV(xclass)(fc, Lxclass_data, utf)) break; Feptr += len; } @@ -2320,7 +2287,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never gets here */ } #endif /* SUPPORT_WIDE_CHARS: end of XCLASS */ @@ -2330,151 +2297,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, #undef Lmax - /* ===================================================================== */ - /* Match a complex, set-based character class. This opcodes are used when - there is complex nesting or logical operations within the character - class. */ - -#define Lstart_eptr F->temp_sptr[0] -#define Leclass_data F->temp_sptr[1] -#define Leclass_len F->temp_size -#define Lmin F->temp_32[0] -#define Lmax F->temp_32[1] - -#ifdef SUPPORT_WIDE_CHARS - case OP_ECLASS: - { - Leclass_data = Fecode + 1 + LINK_SIZE; /* Save for matching */ - Fecode += GET(Fecode, 1); /* Advance past the item */ - Leclass_len = (PCRE2_SIZE)(Fecode - Leclass_data); - - switch (*Fecode) - { - case OP_CRSTAR: - case OP_CRMINSTAR: - case OP_CRPLUS: - case OP_CRMINPLUS: - case OP_CRQUERY: - case OP_CRMINQUERY: - case OP_CRPOSSTAR: - case OP_CRPOSPLUS: - case OP_CRPOSQUERY: - fc = *Fecode++ - OP_CRSTAR; - Lmin = rep_min[fc]; - Lmax = rep_max[fc]; - reptype = rep_typ[fc]; - break; - - case OP_CRRANGE: - case OP_CRMINRANGE: - case OP_CRPOSRANGE: - Lmin = GET2(Fecode, 1); - Lmax = GET2(Fecode, 1 + IMM2_SIZE); - if (Lmax == 0) Lmax = UINT32_MAX; /* Max 0 => infinity */ - reptype = rep_typ[*Fecode - OP_CRSTAR]; - Fecode += 1 + 2 * IMM2_SIZE; - break; - - default: /* No repeat follows */ - Lmin = Lmax = 1; - break; - } - - /* First, ensure the minimum number of matches are present. */ - - for (i = 1; i <= Lmin; i++) - { - if (Feptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(fc, Feptr); - if (!PRIV(eclass)(fc, Leclass_data, Leclass_data + Leclass_len, - (const uint8_t*)mb->start_code, utf)) - RRETURN(MATCH_NOMATCH); - } - - /* If Lmax == Lmin we can just continue with the main loop. */ - - if (Lmin == Lmax) continue; - - /* If minimizing, keep testing the rest of the expression and advancing - the pointer while it matches the class. */ - - if (reptype == REPTYPE_MIN) - { - for (;;) - { - RMATCH(Fecode, RM102); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); - if (Feptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(fc, Feptr); - if (!PRIV(eclass)(fc, Leclass_data, Leclass_data + Leclass_len, - (const uint8_t*)mb->start_code, utf)) - RRETURN(MATCH_NOMATCH); - } - PCRE2_UNREACHABLE(); /* Control never reaches here */ - } - - /* If maximizing, find the longest possible run, then work backwards. */ - - else - { - Lstart_eptr = Feptr; - for (i = Lmin; i < Lmax; i++) - { - int len = 1; - if (Feptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - break; - } -#ifdef SUPPORT_UNICODE - GETCHARLENTEST(fc, Feptr, len); -#else - fc = *Feptr; -#endif - if (!PRIV(eclass)(fc, Leclass_data, Leclass_data + Leclass_len, - (const uint8_t*)mb->start_code, utf)) - break; - Feptr += len; - } - - if (reptype == REPTYPE_POS) continue; /* No backtracking */ - - /* After \C in UTF mode, Lstart_eptr might be in the middle of a - Unicode character. Use <= Lstart_eptr to ensure backtracking doesn't - go too far. */ - - for(;;) - { - RMATCH(Fecode, RM103); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (Feptr-- <= Lstart_eptr) break; /* Tried at original position */ -#ifdef SUPPORT_UNICODE - if (utf) BACKCHAR(Feptr); -#endif - } - RRETURN(MATCH_NOMATCH); - } - - PCRE2_UNREACHABLE(); /* Control never reaches here */ - } -#endif /* SUPPORT_WIDE_CHARS: end of ECLASS */ - -#undef Lstart_eptr -#undef Leclass_data -#undef Leclass_len -#undef Lmin -#undef Lmax - - /* ===================================================================== */ /* Match various character types when PCRE2_UCP is not set. These opcodes are not generated when PCRE2_UCP is set - instead appropriate property @@ -2670,6 +2492,10 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, switch(Fecode[1]) { + case PT_ANY: + if (notmatch) RRETURN(MATCH_NOMATCH); + break; + case PT_LAMP: chartype = prop->chartype; if ((chartype == ucp_Lu || @@ -2780,7 +2606,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, /* This should never occur */ default: - PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } @@ -2903,6 +2728,19 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, BOOL notmatch = Lctype == OP_NOTPROP; switch(proptype) { + case PT_ANY: + if (notmatch) RRETURN(MATCH_NOMATCH); + for (i = 1; i <= Lmin; i++) + { + if (Feptr >= mb->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(fc, Feptr); + } + break; + case PT_LAMP: for (i = 1; i <= Lmin; i++) { @@ -3131,7 +2969,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, /* This should not occur */ default: - PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } } @@ -3407,7 +3244,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, break; default: - PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } /* End switch(Lctype) */ @@ -3660,7 +3496,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, break; default: - PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } } @@ -3681,11 +3516,27 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, { switch(proptype) { + case PT_ANY: + for (;;) + { + RMATCH(Fecode, RM208); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(fc, Feptr); + if (Lctype == OP_NOTPROP) RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + case PT_LAMP: for (;;) { int chartype; - RMATCH(Fecode, RM208); + RMATCH(Fecode, RM209); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject) @@ -3700,12 +3551,12 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, chartype == ucp_Lt) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never gets here */ case PT_GC: for (;;) { - RMATCH(Fecode, RM209); + RMATCH(Fecode, RM210); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject) @@ -3717,12 +3568,12 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, if ((UCD_CATEGORY(fc) == Lpropvalue) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never gets here */ case PT_PC: for (;;) { - RMATCH(Fecode, RM210); + RMATCH(Fecode, RM211); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject) @@ -3734,12 +3585,12 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, if ((UCD_CHARTYPE(fc) == Lpropvalue) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never gets here */ case PT_SC: for (;;) { - RMATCH(Fecode, RM211); + RMATCH(Fecode, RM212); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject) @@ -3751,14 +3602,14 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, if ((UCD_SCRIPT(fc) == Lpropvalue) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never gets here */ case PT_SCX: for (;;) { BOOL ok; const ucd_record *prop; - RMATCH(Fecode, RM224); + RMATCH(Fecode, RM225); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject) @@ -3773,13 +3624,13 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, if (ok == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never gets here */ case PT_ALNUM: for (;;) { int category; - RMATCH(Fecode, RM212); + RMATCH(Fecode, RM213); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject) @@ -3792,7 +3643,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, if ((category == ucp_L || category == ucp_N) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never gets here */ /* Perl space used to exclude VT, but from Perl 5.18 it is included, which means that Perl space and POSIX space are now identical. PCRE @@ -3802,7 +3653,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, case PT_PXSPACE: /* POSIX space */ for (;;) { - RMATCH(Fecode, RM213); + RMATCH(Fecode, RM214); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject) @@ -3824,13 +3675,13 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, break; } } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never gets here */ case PT_WORD: for (;;) { int chartype, category; - RMATCH(Fecode, RM214); + RMATCH(Fecode, RM215); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject) @@ -3847,13 +3698,13 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, chartype == ucp_Pc) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never gets here */ case PT_CLIST: for (;;) { const uint32_t *cp; - RMATCH(Fecode, RM215); + RMATCH(Fecode, RM216); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject) @@ -3884,12 +3735,12 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, } } } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never gets here */ case PT_UCNC: for (;;) { - RMATCH(Fecode, RM216); + RMATCH(Fecode, RM217); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject) @@ -3903,12 +3754,12 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, fc >= 0xe000) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never gets here */ case PT_BIDICL: for (;;) { - RMATCH(Fecode, RM223); + RMATCH(Fecode, RM224); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject) @@ -3920,14 +3771,14 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, if ((UCD_BIDICLASS(fc) == Lpropvalue) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never gets here */ case PT_BOOL: for (;;) { BOOL ok; const ucd_record *prop; - RMATCH(Fecode, RM222); + RMATCH(Fecode, RM223); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject) @@ -3942,11 +3793,10 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, if (ok == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never gets here */ /* This should never occur */ default: - PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } } @@ -3958,7 +3808,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, { for (;;) { - RMATCH(Fecode, RM217); + RMATCH(Fecode, RM218); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject) @@ -3985,7 +3835,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, { for (;;) { - RMATCH(Fecode, RM218); + RMATCH(Fecode, RM219); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject) @@ -4101,7 +3951,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, break; default: - PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } } @@ -4246,13 +4095,11 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, break; default: - PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } } } - - PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */ + /* Control never gets here */ } /* If maximizing, it is worth using inline code for speed, doing the type @@ -4270,6 +4117,21 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, BOOL notmatch = Lctype == OP_NOTPROP; switch(proptype) { + case PT_ANY: + for (i = Lmin; i < Lmax; i++) + { + int len = 1; + if (Feptr >= mb->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLENTEST(fc, Feptr, len); + if (notmatch) break; + Feptr+= len; + } + break; + case PT_LAMP: for (i = Lmin; i < Lmax; i++) { @@ -4515,7 +4377,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, break; default: - PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } @@ -4530,7 +4391,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, for(;;) { if (Feptr <= Lstart_eptr) break; - RMATCH(Fecode, RM221); + RMATCH(Fecode, RM222); if (rrc != MATCH_NOMATCH) RRETURN(rrc); Feptr--; if (utf) BACKCHAR(Feptr); @@ -4573,7 +4434,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, PCRE2_SPTR fptr; if (Feptr <= Lstart_eptr) break; /* At start of char run */ - RMATCH(Fecode, RM219); + RMATCH(Fecode, RM220); if (rrc != MATCH_NOMATCH) RRETURN(rrc); /* Backtracking over an extended grapheme cluster involves inspecting @@ -4834,7 +4695,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, break; default: - PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } @@ -4847,7 +4707,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, for(;;) { if (Feptr <= Lstart_eptr) break; - RMATCH(Fecode, RM220); + RMATCH(Fecode, RM221); if (rrc != MATCH_NOMATCH) RRETURN(rrc); Feptr--; BACKCHAR(Feptr); @@ -5092,7 +4952,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, break; default: - PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } @@ -5129,18 +4988,16 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, #define Lmin F->temp_32[0] #define Lmax F->temp_32[1] #define Lcaseless F->temp_32[2] -#define Lcaseopts F->temp_32[3] #define Lstart F->temp_sptr[0] #define Loffset F->temp_size case OP_DNREF: case OP_DNREFI: Lcaseless = (Fop == OP_DNREFI); - Lcaseopts = (Fop == OP_DNREFI)? Fecode[1 + 2*IMM2_SIZE] : 0; { int count = GET2(Fecode, 1+IMM2_SIZE); PCRE2_SPTR slot = mb->name_table + GET2(Fecode, 1) * mb->name_entry_size; - Fecode += 1 + 2*IMM2_SIZE + (Fop == OP_DNREFI? 1 : 0); + Fecode += 1 + 2*IMM2_SIZE; while (count-- > 0) { @@ -5154,9 +5011,8 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, case OP_REF: case OP_REFI: Lcaseless = (Fop == OP_REFI); - Lcaseopts = (Fop == OP_REFI)? Fecode[1 + IMM2_SIZE] : 0; Loffset = (GET2(Fecode, 1) << 1) - 2; - Fecode += 1 + IMM2_SIZE + (Fop == OP_REFI? 1 : 0); + Fecode += 1 + IMM2_SIZE; /* Set up for repetition, or handle the non-repeated case. The maximum and minimum must be in the heap frame, but as they are short-term values, we @@ -5188,7 +5044,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, default: /* No repeat follows */ { - rrc = match_ref(Loffset, Lcaseless, Lcaseopts, F, mb, &length); + rrc = match_ref(Loffset, Lcaseless, F, mb, &length); if (rrc != 0) { if (rrc > 0) Feptr = mb->end_subject; /* Partial match */ @@ -5222,7 +5078,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, for (i = 1; i <= Lmin; i++) { PCRE2_SIZE slength; - rrc = match_ref(Loffset, Lcaseless, Lcaseopts, F, mb, &slength); + rrc = match_ref(Loffset, Lcaseless, F, mb, &slength); if (rrc != 0) { if (rrc > 0) Feptr = mb->end_subject; /* Partial match */ @@ -5246,7 +5102,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, RMATCH(Fecode, RM20); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); - rrc = match_ref(Loffset, Lcaseless, Lcaseopts, F, mb, &slength); + rrc = match_ref(Loffset, Lcaseless, F, mb, &slength); if (rrc != 0) { if (rrc > 0) Feptr = mb->end_subject; /* Partial match */ @@ -5255,8 +5111,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, } Feptr += slength; } - - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never gets here */ } /* If maximizing, find the longest string and work backwards, as long as @@ -5271,7 +5126,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, for (i = Lmin; i < Lmax; i++) { PCRE2_SIZE slength; - rrc = match_ref(Loffset, Lcaseless, Lcaseopts, F, mb, &slength); + rrc = match_ref(Loffset, Lcaseless, F, mb, &slength); if (rrc != 0) { /* Can't use CHECK_PARTIAL because we don't want to update Feptr in @@ -5322,7 +5177,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, for (i = Lmin; i < Lmax; i++) { PCRE2_SIZE slength; - (void)match_ref(Loffset, Lcaseless, Lcaseopts, F, mb, &slength); + (void)match_ref(Loffset, Lcaseless, F, mb, &slength); Feptr += slength; } } @@ -5330,8 +5185,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, RRETURN(MATCH_NOMATCH); } - - PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */ + /* Control never gets here */ #undef Lcaseless #undef Lmin @@ -5555,7 +5409,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, Fecode += GET(Fecode, 1); if (*Fecode != OP_ALT) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never reaches here. */ #undef Lframe_type @@ -5640,7 +5494,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, Lstart_branch = next_ecode; if (*Lstart_branch != OP_ALT) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never reaches here. */ #undef Lframe_type #undef Lstart_branch @@ -5731,132 +5585,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, #undef Lframe_type - /* ===================================================================== */ - /* Handle scan substring operation. */ - -#define Lframe_type F->temp_32[0] -#define Lextra_size F->temp_32[1] -#define Lsaved_moptions F->temp_32[2] -#define Lsaved_end_subject F->temp_sptr[0] -#define Lsaved_eptr F->temp_sptr[1] -#define Ltrue_end_extra F->temp_size - - case OP_ASSERT_SCS: - { - PCRE2_SPTR ecode = Fecode + 1 + LINK_SIZE; - uint32_t extra_size = 0; - int count; - PCRE2_SPTR slot; - - /* Disable compiler warning. */ - offset = 0; - (void)offset; - - for (;;) - { - if (*ecode == OP_CREF) - { - extra_size += 1+IMM2_SIZE; - offset = (GET2(ecode, 1) << 1) - 2; - ecode += 1+IMM2_SIZE; - if (offset < Foffset_top && Fovector[offset] != PCRE2_UNSET) - goto SCS_OFFSET_FOUND; - continue; - } - - if (*ecode != OP_DNCREF) RRETURN(MATCH_NOMATCH); - - count = GET2(ecode, 1 + IMM2_SIZE); - slot = mb->name_table + GET2(ecode, 1) * mb->name_entry_size; - extra_size += 1+2*IMM2_SIZE; - ecode += 1+2*IMM2_SIZE; - - while (count > 0) - { - offset = (GET2(slot, 0) << 1) - 2; - if (offset < Foffset_top && Fovector[offset] != PCRE2_UNSET) - goto SCS_OFFSET_FOUND; - slot += mb->name_entry_size; - count--; - } - } - - SCS_OFFSET_FOUND: - - /* Skip remaining options. */ - for (;;) - { - if (*ecode == OP_CREF) - { - extra_size += 1+IMM2_SIZE; - ecode += 1+IMM2_SIZE; - } - else if (*ecode == OP_DNCREF) - { - extra_size += 1+2*IMM2_SIZE; - ecode += 1+2*IMM2_SIZE; - } - else break; - } - - Lextra_size = extra_size; - } - - Lsaved_end_subject = mb->end_subject; - Ltrue_end_extra = mb->true_end_subject - mb->end_subject; - Lsaved_eptr = Feptr; - Lsaved_moptions = mb->moptions; - - Feptr = mb->start_subject + Fovector[offset]; - mb->true_end_subject = mb->end_subject = - mb->start_subject + Fovector[offset + 1]; - mb->moptions &= ~PCRE2_NOTEOL; - - Lframe_type = GF_NOCAPTURE | Fop; - for (;;) - { - group_frame_type = Lframe_type; - RMATCH(Fecode + 1 + LINK_SIZE + Lextra_size, RM38); - if (rrc == MATCH_ACCEPT) - { - memcpy(Fovector, - (char *)assert_accept_frame + offsetof(heapframe, ovector), - assert_accept_frame->offset_top * sizeof(PCRE2_SIZE)); - Foffset_top = assert_accept_frame->offset_top; - Fmark = assert_accept_frame->mark; - break; - } - - if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) - { - mb->end_subject = Lsaved_end_subject; - mb->true_end_subject = mb->end_subject + Ltrue_end_extra; - mb->moptions = Lsaved_moptions; - RRETURN(rrc); - } - - Fecode += GET(Fecode, 1); - if (*Fecode != OP_ALT) - { - mb->end_subject = Lsaved_end_subject; - mb->true_end_subject = mb->end_subject + Ltrue_end_extra; - mb->moptions = Lsaved_moptions; - RRETURN(MATCH_NOMATCH); - } - Lextra_size = 0; - } - - do Fecode += GET(Fecode, 1); while (*Fecode == OP_ALT); - Fecode += 1 + LINK_SIZE; - Feptr = Lsaved_eptr; - break; - -#undef Lframe_type -#undef Lextra_size -#undef Lsaved_end_subject -#undef Lsaved_eptr -#undef Ltrue_end_extra -#undef Lsave_moptions /* ===================================================================== */ /* The callout item calls an external function, if one is provided, passing @@ -6067,11 +5795,8 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, #ifdef SUPPORT_UNICODE if (utf) { - /* We used to do a simpler `while (number-- > 0)` but that triggers - clang's unsigned integer overflow sanitizer. */ - while (number > 0) + while (number-- > 0) { - --number; if (Feptr <= mb->check_subject) RRETURN(MATCH_NOMATCH); Feptr--; BACKCHAR(Feptr); @@ -6144,7 +5869,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, } /* Now try matching, moving forward one character on failure, until we - reach the minimum back length. */ + reach the mimimum back length. */ for (;;) { @@ -6156,7 +5881,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, if (utf) { FORWARDCHARTEST(Feptr, mb->end_subject); } #endif } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + /* Control never reaches here */ #undef Lmin #undef Lmax @@ -6206,20 +5931,14 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, (char *)P->eptr - (char *)mb->start_subject); #endif - /* If we are at the end of an assertion that is a condition, first check - to see if we are at the end of a variable-length branch in a lookbehind. - If this is the case and we have not landed on the current character, - return no match. Compare code below for non-condition lookbehinds. In - other cases, return a match, discarding any intermediate backtracking - points. Copy back the mark setting and the captures into the frame before - N so that they are set on return. Doing this for all assertions, both - positive and negative, seems to match what Perl does. */ + /* If we are at the end of an assertion that is a condition, return a + match, discarding any intermediate backtracking points. Copy back the + mark setting and the captures into the frame before N so that they are + set on return. Doing this for all assertions, both positive and negative, + seems to match what Perl does. */ if (GF_IDMASK(N->group_frame_type) == GF_CONDASSERT) { - if ((*bracode == OP_ASSERTBACK || *bracode == OP_ASSERTBACK_NOT) && - branch_start[1 + LINK_SIZE] == OP_VREVERSE && Feptr != P->eptr) - RRETURN(MATCH_NOMATCH); memcpy((char *)P + offsetof(heapframe, ovector), Fovector, Foffset_top * sizeof(PCRE2_SIZE)); P->offset_top = Foffset_top; @@ -6248,11 +5967,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, /* It is the end of whole-pattern recursion. */ offset = Flast_group_offset; - - /* Corrupted heapframes?. Trigger an assert and return an error */ - PCRE2_ASSERT(offset != PCRE2_UNSET); if (offset == PCRE2_UNSET) return PCRE2_ERROR_INTERNAL; - N = (heapframe *)((char *)match_data->heapframes + offset); P = (heapframe *)((char *)N - frame_size); Flast_group_offset = P->last_group_offset; @@ -6327,23 +6042,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, case OP_ASSERT_NOT: RRETURN(MATCH_MATCH); - /* A scan substring group must preserve the current end_subject, - and restore it before the backtracking is performed into its sub - pattern. */ - - case OP_ASSERT_SCS: - F->temp_sptr[0] = mb->end_subject; - mb->end_subject = P->temp_sptr[0]; - mb->true_end_subject = mb->end_subject + P->temp_size; - Feptr = P->temp_sptr[1]; - - RMATCH(Fecode + 1 + LINK_SIZE, RM39); - - mb->end_subject = F->temp_sptr[0]; - mb->true_end_subject = mb->end_subject; - RRETURN(rrc); - break; - /* At the end of a script run, apply the script-checking rules. This code will never by exercised if Unicode support it not compiled, because in that environment script runs cause an error at compile time. */ @@ -6467,8 +6165,8 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, case OP_EODN: ASSERT_NL_OR_EOS: - if (Feptr < mb->true_end_subject && - (!IS_NEWLINE(Feptr) || Feptr != mb->true_end_subject - mb->nllen)) + if (Feptr < mb->end_subject && + (!IS_NEWLINE(Feptr) || Feptr != mb->end_subject - mb->nllen)) { if (mb->partial != 0 && Feptr + 1 >= mb->end_subject && @@ -6749,7 +6447,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, something seriously wrong in the code above or the OP_xxx definitions. */ default: - PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } @@ -6758,8 +6455,8 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, loop. */ } /* End of main loop */ +/* Control never reaches here */ -PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */ /* ========================================================================= */ /* The RRETURN() macro jumps here. The number that is saved in Freturn_id @@ -6785,21 +6482,20 @@ switch (Freturn_id) LBL( 9) LBL(10) LBL(11) LBL(12) LBL(13) LBL(14) LBL(15) LBL(16) LBL(17) LBL(18) LBL(19) LBL(20) LBL(21) LBL(22) LBL(23) LBL(24) LBL(25) LBL(26) LBL(27) LBL(28) LBL(29) LBL(30) LBL(31) LBL(32) - LBL(33) LBL(34) LBL(35) LBL(36) LBL(37) LBL(38) LBL(39) + LBL(33) LBL(34) LBL(35) LBL(36) LBL(37) #ifdef SUPPORT_WIDE_CHARS - LBL(100) LBL(101) LBL(102) LBL(103) + LBL(100) LBL(101) #endif #ifdef SUPPORT_UNICODE LBL(200) LBL(201) LBL(202) LBL(203) LBL(204) LBL(205) LBL(206) LBL(207) LBL(208) LBL(209) LBL(210) LBL(211) LBL(212) LBL(213) LBL(214) LBL(215) LBL(216) LBL(217) LBL(218) LBL(219) LBL(220) - LBL(221) LBL(222) LBL(223) LBL(224) + LBL(221) LBL(222) LBL(223) LBL(224) LBL(225) #endif default: - PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } #undef LBL @@ -6925,7 +6621,7 @@ if ((re->flags & PCRE2_MODE_MASK) != PCRE2_CODE_UNIT_WIDTH/8) /* PCRE2_NOTEMPTY and PCRE2_NOTEMPTY_ATSTART are match-time flags in the options variable for this function. Users of PCRE2 who are not calling the function directly would like to have a way of setting these flags, in the same -way that they can set pcre2_compile() flags like PCRE2_NO_AUTO_POSSESS with +way that they can set pcre2_compile() flags like PCRE2_NO_AUTOPOSSESS with constructions like (*NO_AUTOPOSSESS). To enable this, (*NOTEMPTY) and (*NOTEMPTY_ATSTART) set bits in the pattern's "flag" function which we now transfer to the options for this function. The bits are guaranteed to be @@ -7007,6 +6703,9 @@ if (use_jit) #ifdef SUPPORT_UNICODE if (utf && (options & PCRE2_NO_UTF_CHECK) == 0 && !allow_invalid) { +#if PCRE2_CODE_UNIT_WIDTH != 32 + unsigned int i; +#endif /* For 8-bit and 16-bit UTF, check that the first code unit is a valid character start. */ @@ -7027,7 +6726,7 @@ if (use_jit) start of matching. */ #if PCRE2_CODE_UNIT_WIDTH != 32 - for (unsigned int i = re->max_lookbehind; i > 0 && start_match > subject; i--) + for (i = re->max_lookbehind; i > 0 && start_match > subject; i--) { start_match--; while (start_match > subject && @@ -7274,10 +6973,10 @@ mb->mark = mb->nomatch_mark = NULL; /* In case never set */ /* The name table is needed for finding all the numbers associated with a given name, for condition testing. The code follows the name table. */ -mb->name_table = (PCRE2_SPTR)((const uint8_t *)re + sizeof(pcre2_real_code)); +mb->name_table = (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code)); mb->name_count = re->name_count; mb->name_entry_size = re->name_entry_size; -mb->start_code = (PCRE2_SPTR)((const uint8_t *)re + re->code_start); +mb->start_code = mb->name_table + re->name_count * re->name_entry_size; /* Process the \R and newline settings. */ @@ -7314,9 +7013,7 @@ switch(re->newline_convention) mb->nltype = NLTYPE_ANYCRLF; break; - default: - PCRE2_DEBUG_UNREACHABLE(); - return PCRE2_ERROR_INTERNAL; + default: return PCRE2_ERROR_INTERNAL; } /* The backtracking frames have fixed data at the front, and a PCRE2_SIZE @@ -7462,7 +7159,7 @@ for(;;) However, there is an option (settable at compile time) that disables these, for testing and for ensuring that all callouts do actually occur. */ - if ((re->optimization_flags & PCRE2_OPTIM_START_OPTIMIZE) != 0) + if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0) { /* If firstline is TRUE, the start of the match is constrained to the first line of a multiline string. That is, the match must be before or at the diff --git a/ext/pcre/pcre2lib/pcre2_match_data.c b/ext/pcre/pcre2lib/pcre2_match_data.c index 100e7c9d944cf..757dab9df51d3 100644 --- a/ext/pcre/pcre2lib/pcre2_match_data.c +++ b/ext/pcre/pcre2lib/pcre2_match_data.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2024 University of Cambridge + New API code Copyright (c) 2016-2022 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -77,16 +77,14 @@ return yield; * Create a match data block using pattern data * *************************************************/ -/* If no context is supplied, use the memory allocator from the code. This code -assumes that a general context contains nothing other than a memory allocator. -If that ever changes, this code will need fixing. */ +/* If no context is supplied, use the memory allocator from the code. */ PCRE2_EXP_DEFN pcre2_match_data * PCRE2_CALL_CONVENTION pcre2_match_data_create_from_pattern(const pcre2_code *code, pcre2_general_context *gcontext) { if (gcontext == NULL) gcontext = (pcre2_general_context *)code; -return pcre2_match_data_create(((const pcre2_real_code *)code)->top_bracket + 1, +return pcre2_match_data_create(((pcre2_real_code *)code)->top_bracket + 1, gcontext); } diff --git a/ext/pcre/pcre2lib/pcre2_ord2utf.c b/ext/pcre/pcre2lib/pcre2_ord2utf.c index a1e9e08803bc0..1403730996d6b 100644 --- a/ext/pcre/pcre2lib/pcre2_ord2utf.c +++ b/ext/pcre/pcre2lib/pcre2_ord2utf.c @@ -117,4 +117,4 @@ return 1; } #endif /* SUPPORT_UNICODE */ -/* End of pcre2_ord2utf.c */ +/* End of pcre_ord2utf.c */ diff --git a/ext/pcre/pcre2lib/pcre2_pattern_info.c b/ext/pcre/pcre2lib/pcre2_pattern_info.c index fe4d3c661a01c..a29f5eff673be 100644 --- a/ext/pcre/pcre2lib/pcre2_pattern_info.c +++ b/ext/pcre/pcre2lib/pcre2_pattern_info.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2024 University of Cambridge + New API code Copyright (c) 2016-2018 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -64,7 +64,7 @@ Returns: 0 when data returned PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION pcre2_pattern_info(const pcre2_code *code, uint32_t what, void *where) { -const pcre2_real_code *re = (const pcre2_real_code *)code; +const pcre2_real_code *re = (pcre2_real_code *)code; if (where == NULL) /* Requests field length */ { @@ -230,8 +230,7 @@ switch(what) break; case PCRE2_INFO_NAMETABLE: - *((PCRE2_SPTR *)where) = (PCRE2_SPTR)((const char *)re + - sizeof(pcre2_real_code)); + *((PCRE2_SPTR *)where) = (PCRE2_SPTR)((char *)re + sizeof(pcre2_real_code)); break; case PCRE2_INFO_NEWLINE: @@ -269,7 +268,7 @@ PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION pcre2_callout_enumerate(const pcre2_code *code, int (*callback)(pcre2_callout_enumerate_block *, void *), void *callout_data) { -const pcre2_real_code *re = (const pcre2_real_code *)code; +pcre2_real_code *re = (pcre2_real_code *)code; pcre2_callout_enumerate_block cb; PCRE2_SPTR cc; #ifdef SUPPORT_UNICODE @@ -292,7 +291,7 @@ if (re->magic_number != MAGIC_NUMBER) return PCRE2_ERROR_BADMAGIC; if ((re->flags & (PCRE2_CODE_UNIT_WIDTH/8)) == 0) return PCRE2_ERROR_BADMODE; cb.version = 0; -cc = (PCRE2_SPTR)((const uint8_t *)re + sizeof(pcre2_real_code)) +cc = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code)) + re->name_count * re->name_entry_size; while (TRUE) @@ -384,9 +383,8 @@ while (TRUE) #endif break; -#ifdef SUPPORT_WIDE_CHARS +#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8 case OP_XCLASS: - case OP_ECLASS: cc += GET(cc, 1); break; #endif diff --git a/ext/pcre/pcre2lib/pcre2_printint.c b/ext/pcre/pcre2lib/pcre2_printint.c index 84f84f82f733c..870e283b74565 100644 --- a/ext/pcre/pcre2lib/pcre2_printint.c +++ b/ext/pcre/pcre2lib/pcre2_printint.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2024 University of Cambridge + New API code Copyright (c) 2016-2023 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -53,7 +53,6 @@ pcre2_internal.h, which is #included by pcre2test before this file. */ #ifndef OP_LISTS_DEFINED static const char *OP_names[] = { OP_NAME_LIST }; -STATIC_ASSERT(sizeof(OP_names)/sizeof(*OP_names) == OP_TABLE_LENGTH, OP_names); #define OP_LISTS_DEFINED #endif @@ -66,17 +65,13 @@ STATIC_ASSERT(sizeof(OP_names)/sizeof(*OP_names) == OP_TABLE_LENGTH, OP_names); #define print_custring PCRE2_SUFFIX(print_custring_) #define print_custring_bylen PCRE2_SUFFIX(print_custring_bylen_) #define print_prop PCRE2_SUFFIX(print_prop_) -#define print_char_list PCRE2_SUFFIX(print_char_list_) -#define print_map PCRE2_SUFFIX(print_map_) -#define print_class PCRE2_SUFFIX(print_class_) /* Table of sizes for the fixed-length opcodes. It's defined in a macro so that the definition is next to the definition of the opcodes in pcre2_internal.h. The contents of the table are, however, mode-dependent. */ static const uint8_t OP_lengths[] = { OP_LENGTHS }; -STATIC_ASSERT(sizeof(OP_lengths)/sizeof(*OP_lengths) == OP_TABLE_LENGTH, - PCRE2_SUFFIX(OP_lengths_)); + /************************************************* @@ -250,7 +245,7 @@ const char *yield = "??"; size_t len = 0; unsigned int ptypex = (ptype == PT_SC)? PT_SCX : ptype; -for (ptrdiff_t i = PRIV(utt_size) - 1; i >= 0; i--) +for (int i = PRIV(utt_size) - 1; i >= 0; i--) { const ucp_type_table *u = PRIV(utt) + i; @@ -323,298 +318,6 @@ else -/************************************************* -* Print character list * -*************************************************/ - -/* Prints the characters and character ranges in a character list. - -Arguments: - f file to write to - code pointer in the compiled code -*/ - -static PCRE2_SPTR -print_char_list(FILE *f, PCRE2_SPTR code, const uint8_t *char_lists_end) -{ -uint32_t type, list_ind; -uint32_t char_list_add = XCL_CHAR_LIST_LOW_16_ADD; -uint32_t range_start = ~(uint32_t)0, range_end = 0; -const uint8_t *next_char; - -#if PCRE2_CODE_UNIT_WIDTH == 8 -type = (uint32_t)(code[0] << 8) | code[1]; -code += 2; -#else -type = code[0]; -code++; -#endif /* CODE_UNIT_WIDTH */ - -/* Align characters. */ -next_char = char_lists_end - (GET(code, 0) << 1); -type &= XCL_TYPE_MASK; -list_ind = 0; - -if ((type & XCL_BEGIN_WITH_RANGE) != 0) - range_start = XCL_CHAR_LIST_LOW_16_START; - -while (type > 0) - { - uint32_t item_count = type & XCL_ITEM_COUNT_MASK; - - if (item_count == XCL_ITEM_COUNT_MASK) - { - if (list_ind <= 1) - { - item_count = *(const uint16_t*)next_char; - next_char += 2; - } - else - { - item_count = *(const uint32_t*)next_char; - next_char += 4; - } - } - - while (item_count > 0) - { - if (list_ind <= 1) - { - range_end = *(const uint16_t*)next_char; - next_char += 2; - } - else - { - range_end = *(const uint32_t*)next_char; - next_char += 4; - } - - if ((range_end & XCL_CHAR_END) != 0) - { - range_end = char_list_add + (range_end >> XCL_CHAR_SHIFT); - - if (range_start < range_end) - fprintf(f, "\\x{%x}-", range_start); - - fprintf(f, "\\x{%x}", range_end); - range_start = ~(uint32_t)0; - } - else - range_start = char_list_add + (range_end >> XCL_CHAR_SHIFT); - - item_count--; - } - - list_ind++; - type >>= XCL_TYPE_BIT_LEN; - - /* The following code could be optimized to 8/16/32 bit, - but it is not worth it for a debugging function. */ - - if (range_start == ~(uint32_t)0) - { - if ((type & XCL_BEGIN_WITH_RANGE) != 0) - { - if (list_ind == 1) range_start = XCL_CHAR_LIST_HIGH_16_START; - else if (list_ind == 2) range_start = XCL_CHAR_LIST_LOW_32_START; - else range_start = XCL_CHAR_LIST_HIGH_32_START; - } - } - else if ((type & XCL_BEGIN_WITH_RANGE) == 0) - { - fprintf(f, "\\x{%x}-", range_start); - - if (list_ind == 1) range_end = XCL_CHAR_LIST_LOW_16_END; - else if (list_ind == 2) range_end = XCL_CHAR_LIST_HIGH_16_END; - else if (list_ind == 3) range_end = XCL_CHAR_LIST_LOW_32_END; - else range_end = XCL_CHAR_LIST_HIGH_32_END; - - fprintf(f, "\\x{%x}", range_end); - range_start = ~(uint32_t)0; - } - - if (list_ind == 1) char_list_add = XCL_CHAR_LIST_HIGH_16_ADD; - else if (list_ind == 2) char_list_add = XCL_CHAR_LIST_LOW_32_ADD; - else char_list_add = XCL_CHAR_LIST_HIGH_32_ADD; - } - -return code + LINK_SIZE; -} - - - -/************************************************* -* Print a character bitmap * -*************************************************/ - -/* Prints a 32-byte bitmap, which occurs within a character class opcode. - -Arguments: - f file to write to - map pointer to the bitmap - negated TRUE if the bitmap will be printed as negated - -Returns: nothing -*/ - -static void -print_map(FILE *f, const uint8_t *map, BOOL negated) -{ -BOOL first = TRUE; -uint8_t inverted_map[32]; -int i; - -if (negated) - { - /* Using 255 ^ instead of ~ avoids clang sanitize warning. */ - for (i = 0; i < 32; i++) inverted_map[i] = 255 ^ map[i]; - map = inverted_map; - } - -for (i = 0; i < 256; i++) - { - if ((map[i/8] & (1u << (i&7))) != 0) - { - int j; - for (j = i+1; j < 256; j++) - if ((map[j/8] & (1u << (j&7))) == 0) break; - if (i == '-' || i == '\\' || i == ']' || (first && i == '^')) - fprintf(f, "\\"); - if (PRINTABLE(i)) fprintf(f, "%c", i); - else fprintf(f, "\\x%02x", i); - first = FALSE; - if (--j > i) - { - if (j != i + 1) fprintf(f, "-"); - if (j == '-' || j == '\\' || j == ']') fprintf(f, "\\"); - if (PRINTABLE(j)) fprintf(f, "%c", j); - else fprintf(f, "\\x%02x", j); - } - i = j; - } - } -} - - - -/************************************************* -* Print character class * -*************************************************/ - -/* Prints a character class, which must be either an OP_CLASS, OP_NCLASS, or -OP_XCLASS. - -Arguments: - f file to write to - type OP_CLASS, OP_NCLASS, or OP_XCLASS - code pointer in the compiled code (after the OP tag) - utf TRUE if re is UTF (will be FALSE if UTF is not supported) - before text to print before - after text to print after - -Returns: nothing -*/ - -static void -print_class(FILE *f, int type, PCRE2_SPTR code, const uint8_t *char_lists_end, - BOOL utf, const char *before, const char *after) -{ -BOOL printmap, negated; -PCRE2_SPTR ccode; - -/* Negative XCLASS and NCLASS both have a bitmap indicating which characters -are accepted. For clarity we print this inverted and prefixed by "^". */ -if (type == OP_XCLASS) - { - ccode = code + LINK_SIZE; - printmap = (*ccode & XCL_MAP) != 0; - negated = (*ccode & XCL_NOT) != 0; - ccode++; - } -else /* CLASS or NCLASS */ - { - printmap = TRUE; - negated = type == OP_NCLASS; - ccode = code; - } - -fprintf(f, "%s[%s", before, negated? "^" : ""); - -/* Print a bit map */ -if (printmap) - { - print_map(f, (const uint8_t *)ccode, negated); - ccode += 32 / sizeof(PCRE2_UCHAR); - } - -/* For an XCLASS there is always some additional data */ -if (type == OP_XCLASS) - { - PCRE2_UCHAR ch; - - while ((ch = *ccode++) != XCL_END) - { - const char *notch = ""; - - if (ch >= XCL_LIST) - { - ccode = print_char_list(f, ccode - 1, char_lists_end); - break; - } - - switch(ch) - { - case XCL_NOTPROP: - notch = "^"; - /* Fall through */ - case XCL_PROP: - { - unsigned int ptype = *ccode++; - unsigned int pvalue = *ccode++; - const char *s; - switch(ptype) - { - case PT_PXGRAPH: - fprintf(f, "[:%sgraph:]", notch); - break; - case PT_PXPRINT: - fprintf(f, "[:%sprint:]", notch); - break; - case PT_PXPUNCT: - fprintf(f, "[:%spunct:]", notch); - break; - case PT_PXXDIGIT: - fprintf(f, "[:%sxdigit:]", notch); - break; - default: - s = get_ucpname(ptype, pvalue); - fprintf(f, "\\%c{%c%s}", ((notch[0] == '^')? 'P':'p'), - toupper(s[0]), s+1); - break; - } - } - break; - - default: - ccode += 1 + print_char(f, ccode, utf); - if (ch == XCL_RANGE) - { - fprintf(f, "-"); - ccode += 1 + print_char(f, ccode, utf); - } - break; - } - } - - PCRE2_ASSERT(ccode == code + (GET(code, 0) - 1)); - } - -/* Indicate a non-UTF class which was created by negation */ -fprintf(f, "]%s", after); -} - - - /************************************************* * Print compiled pattern * *************************************************/ @@ -639,7 +342,7 @@ uint32_t nesize = re->name_entry_size; BOOL utf = (re->overall_options & PCRE2_UTF) != 0; nametable = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code)); -code = codestart = (PCRE2_SPTR)((uint8_t *)re + re->code_start); +code = codestart = nametable + re->name_count * re->name_entry_size; for(;;) { @@ -656,6 +359,20 @@ for(;;) switch(*code) { +/* ========================================================================== */ + /* These cases are never obeyed. This is a fudge that causes a compile- + time error if the vectors OP_names or OP_lengths, which are indexed + by opcode, are not the correct length. It seems to be the only way to do + such a check at compile time, as the sizeof() operator does not work in + the C preprocessor. */ + + case OP_TABLE_LENGTH: + case OP_TABLE_LENGTH + + ((sizeof(OP_names)/sizeof(const char *) == OP_TABLE_LENGTH) && + (sizeof(OP_lengths) == OP_TABLE_LENGTH)): + return; +/* ========================================================================== */ + case OP_END: fprintf(f, " %s\n", OP_names[*code]); fprintf(f, "------------------------------------------------------------------\n"); @@ -707,7 +424,6 @@ for(;;) case OP_ASSERTBACK_NOT: case OP_ASSERT_NA: case OP_ASSERTBACK_NA: - case OP_ASSERT_SCS: case OP_ONCE: case OP_SCRIPT_RUN: case OP_COND: @@ -741,7 +457,7 @@ for(;;) case OP_DNCREF: { PCRE2_SPTR entry = nametable + (GET2(code, 1) * nesize) + IMM2_SIZE; - fprintf(f, " %s Capture ref <", flag); + fprintf(f, " %s Cond ref <", flag); print_custring(f, entry); fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE)); } @@ -858,7 +574,7 @@ for(;;) case OP_NOT: fprintf(f, " %s [^", flag); extra = print_char(f, code + 1, utf); - fprintf(f, "] (not)"); + fprintf(f, "]"); break; case OP_NOTSTARI: @@ -884,7 +600,7 @@ for(;;) case OP_NOTPOSQUERY: fprintf(f, " %s [^", flag); extra = print_char(f, code + 1, utf); - fprintf(f, "]%s (not)", OP_names[*code]); + fprintf(f, "]%s", OP_names[*code]); break; case OP_NOTEXACTI: @@ -906,7 +622,6 @@ for(;;) if (*code == OP_NOTMINUPTO || *code == OP_NOTMINUPTOI) fprintf(f, "?"); else if (*code == OP_NOTPOSUPTO || *code == OP_NOTPOSUPTOI) fprintf(f, "+"); - fprintf(f, " (not)"); break; case OP_RECURSE: @@ -917,17 +632,14 @@ for(;;) case OP_REFI: flag = "/i"; - extra = code[1 + IMM2_SIZE]; /* Fall through */ case OP_REF: fprintf(f, " %s \\%d", flag, GET2(code,1)); - if (extra != 0) fprintf(f, " 0x%02x", extra); ccode = code + OP_lengths[*code]; goto CLASS_REF_REPEAT; case OP_DNREFI: flag = "/i"; - extra = code[1 + 2*IMM2_SIZE]; /* Fall through */ case OP_DNREF: { @@ -935,7 +647,6 @@ for(;;) fprintf(f, " %s \\k<", flag); print_custring(f, entry); fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE)); - if (extra != 0) fprintf(f, " 0x%02x", extra); } ccode = code + OP_lengths[*code]; goto CLASS_REF_REPEAT; @@ -965,77 +676,141 @@ for(;;) print_prop(f, code, " ", ""); break; -#ifdef SUPPORT_WIDE_CHARS - case OP_ECLASS: - extra = GET(code, 1); - fprintf(f, " eclass[\n"); - /* We print the opcodes contained inside as well. */ - ccode = code + 1 + LINK_SIZE + 1; - if ((ccode[-1] & ECL_MAP) != 0) - { - const uint8_t *map = (const uint8_t *)ccode; - /* The first 6 ASCII characters (SOH...ACK) are totally, utterly useless. - If they're set in the bitmap, then it's clearly been formed by negation.*/ - BOOL print_negated = (map[0] & 0x7e) == 0x7e; - - fprintf(f, " bitmap: [%s", print_negated? "^" : ""); - print_map(f, map, print_negated); - fprintf(f, "]\n"); - ccode += 32 / sizeof(PCRE2_UCHAR); - } - else - fprintf(f, " no bitmap\n"); - while (ccode < code + extra) + /* OP_XCLASS cannot occur in 8-bit, non-UTF mode. However, there's no harm + in having this code always here, and it makes it less messy without all + those #ifdefs. */ + + case OP_CLASS: + case OP_NCLASS: + case OP_XCLASS: { - if (print_lengths) - fprintf(f, "%3d ", (int)(ccode - codestart)); - else - fprintf(f, " "); + BOOL printmap, invertmap; - switch (*ccode) + fprintf(f, " ["); + + /* Negative XCLASS has an inverted map whereas the original opcodes have + already done the inversion. */ + + invertmap = FALSE; + if (*code == OP_XCLASS) { - case ECL_AND: - fprintf(f, " AND\n"); - ccode += 1; - break; - case ECL_OR: - fprintf(f, " OR\n"); - ccode += 1; - break; - case ECL_XOR: - fprintf(f, " XOR\n"); - ccode += 1; - break; - case ECL_NOT: - fprintf(f, " NOT\n"); - ccode += 1; - break; + extra = GET(code, 1); + ccode = code + LINK_SIZE + 1; + printmap = (*ccode & XCL_MAP) != 0; + if ((*ccode & XCL_NOT) != 0) + { + invertmap = (*ccode & XCL_HASPROP) == 0; + fprintf(f, "^"); + } + ccode++; + } + else /* CLASS or NCLASS */ + { + printmap = TRUE; + ccode = code + 1; + } - case ECL_XCLASS: - print_class(f, OP_XCLASS, ccode+1, (uint8_t*)codestart, utf, - " xclass: ", "\n"); - ccode += GET(ccode, 1); - break; + /* Print a bit map */ - default: - fprintf(f, " UNEXPECTED\n"); - ccode += 1; - break; + if (printmap) + { + uint8_t inverted_map[32]; + uint8_t *map = (uint8_t *)ccode; + + if (invertmap) + { + /* Using 255 ^ instead of ~ avoids clang sanitize warning. */ + for (i = 0; i < 32; i++) inverted_map[i] = 255 ^ map[i]; + map = inverted_map; + } + + for (i = 0; i < 256; i++) + { + if ((map[i/8] & (1u << (i&7))) != 0) + { + int j; + for (j = i+1; j < 256; j++) + if ((map[j/8] & (1u << (j&7))) == 0) break; + if (i == '-' || i == ']') fprintf(f, "\\"); + if (PRINTABLE(i)) fprintf(f, "%c", i); + else fprintf(f, "\\x%02x", i); + if (--j > i) + { + if (j != i + 1) fprintf(f, "-"); + if (j == '-' || j == ']') fprintf(f, "\\"); + if (PRINTABLE(j)) fprintf(f, "%c", j); + else fprintf(f, "\\x%02x", j); + } + i = j; + } + } + ccode += 32 / sizeof(PCRE2_UCHAR); } } - fprintf(f, " ]"); - goto CLASS_REF_REPEAT; -#endif /* SUPPORT_WIDE_CHARS */ - case OP_CLASS: - case OP_NCLASS: -#ifdef SUPPORT_WIDE_CHARS - case OP_XCLASS: + /* For an XCLASS there is always some additional data */ + if (*code == OP_XCLASS) - extra = GET(code, 1); -#endif - print_class(f, *code, code+1, (uint8_t*)codestart, utf, " ", ""); - ccode = code + OP_lengths[*code] + extra; + { + PCRE2_UCHAR ch; + while ((ch = *ccode++) != XCL_END) + { + const char *notch = ""; + + switch(ch) + { + case XCL_NOTPROP: + notch = "^"; + /* Fall through */ + + case XCL_PROP: + { + unsigned int ptype = *ccode++; + unsigned int pvalue = *ccode++; + const char *s; + + switch(ptype) + { + case PT_PXGRAPH: + fprintf(f, "[:%sgraph:]", notch); + break; + + case PT_PXPRINT: + fprintf(f, "[:%sprint:]", notch); + break; + + case PT_PXPUNCT: + fprintf(f, "[:%spunct:]", notch); + break; + + case PT_PXXDIGIT: + fprintf(f, "[:%sxdigit:]", notch); + break; + + default: + s = get_ucpname(ptype, pvalue); + fprintf(f, "\\%c{%c%s}", ((notch[0] == '^')? 'P':'p'), + toupper(s[0]), s+1); + break; + } + } + break; + + default: + ccode += 1 + print_char(f, ccode, utf); + if (ch == XCL_RANGE) + { + fprintf(f, "-"); + ccode += 1 + print_char(f, ccode, utf); + } + break; + } + } + } + + /* Indicate a non-UTF class which was created by negation */ + + fprintf(f, "]%s", (*code == OP_NCLASS)? " (neg)" : ""); /* Handle repeats after a class or a back reference */ diff --git a/ext/pcre/pcre2lib/pcre2_serialize.c b/ext/pcre/pcre2lib/pcre2_serialize.c index a10e3020bbe9d..ba17a26d2eeb2 100644 --- a/ext/pcre/pcre2lib/pcre2_serialize.c +++ b/ext/pcre/pcre2lib/pcre2_serialize.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2024 University of Cambridge + New API code Copyright (c) 2016-2020 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -127,25 +127,25 @@ dst_bytes += TABLES_LENGTH; for (i = 0; i < number_of_codes; i++) { re = (const pcre2_real_code *)(codes[i]); - (void)memcpy(dst_bytes, (const char *)re, re->blocksize); - - /* Certain fields in the compiled code block are re-set during - deserialization. In order to ensure that the serialized data stream is always - the same for the same pattern, set them to zero here. We can't assume the - copy of the pattern is correctly aligned for accessing the fields as part of + (void)memcpy(dst_bytes, (char *)re, re->blocksize); + + /* Certain fields in the compiled code block are re-set during + deserialization. In order to ensure that the serialized data stream is always + the same for the same pattern, set them to zero here. We can't assume the + copy of the pattern is correctly aligned for accessing the fields as part of a structure. Note the use of sizeof(void *) in the second of these, to - specify the size of a pointer. If sizeof(uint8_t *) is used (tables is a - pointer to uint8_t), gcc gives a warning because the first argument is also a - pointer to uint8_t. Casting the first argument to (void *) can stop this, but + specify the size of a pointer. If sizeof(uint8_t *) is used (tables is a + pointer to uint8_t), gcc gives a warning because the first argument is also a + pointer to uint8_t. Casting the first argument to (void *) can stop this, but it didn't stop Coverity giving the same complaint. */ - - (void)memset(dst_bytes + offsetof(pcre2_real_code, memctl), 0, + + (void)memset(dst_bytes + offsetof(pcre2_real_code, memctl), 0, sizeof(pcre2_memctl)); - (void)memset(dst_bytes + offsetof(pcre2_real_code, tables), 0, + (void)memset(dst_bytes + offsetof(pcre2_real_code, tables), 0, sizeof(void *)); (void)memset(dst_bytes + offsetof(pcre2_real_code, executable_jit), 0, - sizeof(void *)); - + sizeof(void *)); + dst_bytes += re->blocksize; } @@ -232,10 +232,10 @@ for (i = 0; i < number_of_codes; i++) if (dst_re->magic_number != MAGIC_NUMBER || dst_re->name_entry_size > MAX_NAME_SIZE + IMM2_SIZE + 1 || dst_re->name_count > MAX_NAME_COUNT) - { - memctl->free(dst_re, memctl->memory_data); + { + memctl->free(dst_re, memctl->memory_data); return PCRE2_ERROR_BADSERIALIZEDDATA; - } + } /* At the moment only one table is supported. */ diff --git a/ext/pcre/pcre2lib/pcre2_study.c b/ext/pcre/pcre2lib/pcre2_study.c index 85764cea56533..792e696dad74b 100644 --- a/ext/pcre/pcre2lib/pcre2_study.c +++ b/ext/pcre/pcre2lib/pcre2_study.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2024 University of Cambridge + New API code Copyright (c) 2016-2023 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -114,7 +114,7 @@ uint32_t once_fudge = 0; BOOL had_recurse = FALSE; BOOL dupcapused = (re->flags & PCRE2_DUPCAPUSED) != 0; PCRE2_SPTR nextbranch = code + GET(code, 1); -PCRE2_SPTR cc = code + 1 + LINK_SIZE; +PCRE2_UCHAR *cc = (PCRE2_UCHAR *)code + 1 + LINK_SIZE; recurse_check this_recurse; /* If this is a "could be empty" group, its minimum length is 0. */ @@ -136,13 +136,12 @@ passes 16-bits, reset to that value and skip the rest of the branch. */ for (;;) { int d, min, recno; - PCRE2_UCHAR op; - PCRE2_SPTR cs, ce; + PCRE2_UCHAR op, *cs, *ce; if (branchlength >= UINT16_MAX) { branchlength = UINT16_MAX; - cc = nextbranch; + cc = (PCRE2_UCHAR *)nextbranch; } op = *cc; @@ -250,7 +249,6 @@ for (;;) case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: case OP_ASSERT_NA: - case OP_ASSERT_SCS: case OP_ASSERTBACK_NA: do cc += GET(cc, 1); while (*cc == OP_ALT); /* Fall through */ @@ -419,14 +417,15 @@ for (;;) case OP_NCLASS: #ifdef SUPPORT_WIDE_CHARS case OP_XCLASS: - case OP_ECLASS: /* The original code caused an unsigned overflow in 64 bit systems, so now we use a conditional statement. */ - if (op == OP_XCLASS || op == OP_ECLASS) + if (op == OP_XCLASS) cc += GET(cc, 1); else -#endif cc += PRIV(OP_lengths)[OP_CLASS]; +#else + cc += PRIV(OP_lengths)[OP_CLASS]; +#endif switch (*cc) { @@ -480,8 +479,8 @@ for (;;) if (!dupcapused && (re->overall_options & PCRE2_MATCH_UNSET_BACKREF) == 0) { int count = GET2(cc, 1+IMM2_SIZE); - PCRE2_SPTR slot = - (PCRE2_SPTR)((const uint8_t *)re + sizeof(pcre2_real_code)) + + PCRE2_UCHAR *slot = + (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code)) + GET2(cc, 1) * re->name_entry_size; d = INT_MAX; @@ -497,12 +496,13 @@ for (;;) dd = backref_cache[recno]; else { - ce = cs = PRIV(find_bracket)(startcode, utf, recno); + ce = cs = (PCRE2_UCHAR *)PRIV(find_bracket)(startcode, utf, recno); if (cs == NULL) return -2; do ce += GET(ce, 1); while (*ce == OP_ALT); dd = 0; - if (!dupcapused || PRIV(find_bracket)(ce, utf, recno) == NULL) + if (!dupcapused || + (PCRE2_UCHAR *)PRIV(find_bracket)(ce, utf, recno) == NULL) { if (cc > cs && cc < ce) /* Simple recursion */ { @@ -539,7 +539,7 @@ for (;;) } } else d = 0; - cc += PRIV(OP_lengths)[*cc]; + cc += 1 + 2*IMM2_SIZE; goto REPEAT_BACK_REFERENCE; /* Single back reference by number. References by name are converted to by @@ -557,11 +557,12 @@ for (;;) if ((re->overall_options & PCRE2_MATCH_UNSET_BACKREF) == 0) { - ce = cs = PRIV(find_bracket)(startcode, utf, recno); + ce = cs = (PCRE2_UCHAR *)PRIV(find_bracket)(startcode, utf, recno); if (cs == NULL) return -2; do ce += GET(ce, 1); while (*ce == OP_ALT); - if (!dupcapused || PRIV(find_bracket)(ce, utf, recno) == NULL) + if (!dupcapused || + (PCRE2_UCHAR *)PRIV(find_bracket)(ce, utf, recno) == NULL) { if (cc > cs && cc < ce) /* Simple recursion */ { @@ -592,7 +593,7 @@ for (;;) backref_cache[0] = recno; } - cc += PRIV(OP_lengths)[*cc]; + cc += 1 + IMM2_SIZE; /* Handle repeated back references */ @@ -642,7 +643,7 @@ for (;;) pattern contains multiple subpatterns with the same number. */ case OP_RECURSE: - cs = ce = startcode + GET(cc, 1); + cs = ce = (PCRE2_UCHAR *)startcode + GET(cc, 1); recno = GET2(cs, 1+LINK_SIZE); if (recno == prev_recurse_recno) { @@ -754,13 +755,10 @@ for (;;) new ones get added they are properly considered. */ default: - PCRE2_DEBUG_UNREACHABLE(); return -3; } } - -PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */ -return -3; /* Avoid compiler warnings */ +/* Control never gets here */ } @@ -921,138 +919,6 @@ if (table_limit != 32) for (c = 24; c < 32; c++) re->start_bitmap[c] = 0xff; -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 -/************************************************* -* Set starting bits for a character list. * -*************************************************/ - -/* This function sets starting bits for a character list. It enumerates -all characters and character ranges in the character list, and sets -the starting bits accordingly. - -Arguments: - code pointer to the code - start_bitmap pointer to the starting bitmap - -Returns: nothing -*/ -static void -study_char_list(PCRE2_SPTR code, uint8_t *start_bitmap, - const uint8_t *char_lists_end) -{ -uint32_t type, list_ind; -uint32_t char_list_add = XCL_CHAR_LIST_LOW_16_ADD; -uint32_t range_start = ~(uint32_t)0, range_end = 0; -const uint8_t *next_char; -PCRE2_UCHAR start_buffer[6], end_buffer[6]; -PCRE2_UCHAR start, end; - -/* Only needed in 8-bit mode at the moment. */ -type = (uint32_t)(code[0] << 8) | code[1]; -code += 2; - -/* Align characters. */ -next_char = char_lists_end - (GET(code, 0) << 1); -type &= XCL_TYPE_MASK; -list_ind = 0; - -if ((type & XCL_BEGIN_WITH_RANGE) != 0) - range_start = XCL_CHAR_LIST_LOW_16_START; - -while (type > 0) - { - uint32_t item_count = type & XCL_ITEM_COUNT_MASK; - - if (item_count == XCL_ITEM_COUNT_MASK) - { - if (list_ind <= 1) - { - item_count = *(const uint16_t*)next_char; - next_char += 2; - } - else - { - item_count = *(const uint32_t*)next_char; - next_char += 4; - } - } - - while (item_count > 0) - { - if (list_ind <= 1) - { - range_end = *(const uint16_t*)next_char; - next_char += 2; - } - else - { - range_end = *(const uint32_t*)next_char; - next_char += 4; - } - - if ((range_end & XCL_CHAR_END) != 0) - { - range_end = char_list_add + (range_end >> XCL_CHAR_SHIFT); - - PRIV(ord2utf)(range_end, end_buffer); - end = end_buffer[0]; - - if (range_start < range_end) - { - PRIV(ord2utf)(range_start, start_buffer); - for (start = start_buffer[0]; start <= end; start++) - start_bitmap[start / 8] |= (1u << (start & 7)); - } - else - start_bitmap[end / 8] |= (1u << (end & 7)); - - range_start = ~(uint32_t)0; - } - else - range_start = char_list_add + (range_end >> XCL_CHAR_SHIFT); - - item_count--; - } - - list_ind++; - type >>= XCL_TYPE_BIT_LEN; - - if (range_start == ~(uint32_t)0) - { - if ((type & XCL_BEGIN_WITH_RANGE) != 0) - { - /* In 8 bit mode XCL_CHAR_LIST_HIGH_32_START is not possible. */ - if (list_ind == 1) range_start = XCL_CHAR_LIST_HIGH_16_START; - else range_start = XCL_CHAR_LIST_LOW_32_START; - } - } - else if ((type & XCL_BEGIN_WITH_RANGE) == 0) - { - PRIV(ord2utf)(range_start, start_buffer); - - /* In 8 bit mode XCL_CHAR_LIST_LOW_32_END and - XCL_CHAR_LIST_HIGH_32_END are not possible. */ - if (list_ind == 1) range_end = XCL_CHAR_LIST_LOW_16_END; - else range_end = XCL_CHAR_LIST_HIGH_16_END; - - PRIV(ord2utf)(range_end, end_buffer); - end = end_buffer[0]; - - for (start = start_buffer[0]; start <= end; start++) - start_bitmap[start / 8] |= (1u << (start & 7)); - - range_start = ~(uint32_t)0; - } - - /* In 8 bit mode XCL_CHAR_LIST_HIGH_32_ADD is not possible. */ - if (list_ind == 1) char_list_add = XCL_CHAR_LIST_HIGH_16_ADD; - else char_list_add = XCL_CHAR_LIST_LOW_32_ADD; - } -} -#endif - - - /************************************************* * Create bitmap of starting code units * *************************************************/ @@ -1114,7 +980,7 @@ do { int rc; PCRE2_SPTR ncode; - const uint8_t *classmap = NULL; + uint8_t *classmap = NULL; #ifdef SUPPORT_WIDE_CHARS PCRE2_UCHAR xclassflags; #endif @@ -1268,7 +1134,6 @@ do case OP_ASSERTBACK_NOT: case OP_ASSERT_NA: case OP_ASSERTBACK_NA: - case OP_ASSERT_SCS: ncode += GET(ncode, 1); while (*ncode == OP_ALT) ncode += GET(ncode, 1); ncode += 1 + LINK_SIZE; @@ -1387,14 +1252,12 @@ do tcode += GET(tcode, 1 + 2*LINK_SIZE); break; - /* Skip over lookbehind, negative lookahead, and scan substring - assertions */ + /* Skip over lookbehind and negative lookahead assertions */ case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: case OP_ASSERTBACK_NA: - case OP_ASSERT_SCS: do tcode += GET(tcode, 1); while (*tcode == OP_ALT); tcode += 1 + LINK_SIZE; break; @@ -1715,13 +1578,6 @@ do tcode += 2; break; - /* Set-based ECLASS: treat it the same as a "complex" XCLASS; give up. */ - -#ifdef SUPPORT_WIDE_CHARS - case OP_ECLASS: - return SSB_FAIL; -#endif - /* Extended class: if there are any property checks, or if this is a negative XCLASS without a map, give up. If there are no property checks, there must be wide characters on the XCLASS list, because otherwise an @@ -1740,7 +1596,7 @@ do map pointer if there is one, and fall through. */ classmap = ((xclassflags & XCL_MAP) == 0)? NULL : - (const uint8_t *)(tcode + 1 + LINK_SIZE + 1); + (uint8_t *)(tcode + 1 + LINK_SIZE + 1); /* In UTF-8 mode, scan the character list and set bits for leading bytes, then jump to handle the map. */ @@ -1752,13 +1608,6 @@ do PCRE2_SPTR p = tcode + 1 + LINK_SIZE + 1 + ((classmap == NULL)? 0:32); tcode += GET(tcode, 1); - if (*p >= XCL_LIST) - { - study_char_list(p, re->start_bitmap, - ((const uint8_t *)re + re->code_start)); - goto HANDLE_CLASSMAP; - } - for (;;) switch (*p++) { case XCL_SINGLE: @@ -1780,7 +1629,6 @@ do goto HANDLE_CLASSMAP; default: - PCRE2_DEBUG_UNREACHABLE(); return SSB_UNKNOWN; /* Internal error, should not occur */ } } @@ -1817,7 +1665,7 @@ do case OP_CLASS: if (*tcode == OP_XCLASS) tcode += GET(tcode, 1); else { - classmap = (const uint8_t *)(++tcode); + classmap = (uint8_t *)(++tcode); tcode += 32 / sizeof(PCRE2_UCHAR); } @@ -1920,7 +1768,8 @@ BOOL ucp = (re->overall_options & PCRE2_UCP) != 0; /* Find start of compiled code */ -code = (PCRE2_UCHAR *)((uint8_t *)re + re->code_start); +code = (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code)) + + re->name_entry_size * re->name_count; /* For a pattern that has a first code unit, or a multiline pattern that matches only at "line start", there is no point in seeking a list of starting @@ -1930,11 +1779,7 @@ if ((re->flags & (PCRE2_FIRSTSET|PCRE2_STARTLINE)) == 0) { int depth = 0; int rc = set_start_bits(re, code, utf, ucp, &depth); - if (rc == SSB_UNKNOWN) - { - PCRE2_DEBUG_UNREACHABLE(); - return 1; - } + if (rc == SSB_UNKNOWN) return 1; /* If a list of starting code units was set up, scan the list to see if only one or two were listed. Having only one listed is rare because usually a @@ -2007,22 +1852,25 @@ if ((re->flags & (PCRE2_FIRSTSET|PCRE2_STARTLINE)) == 0) } } - /* Replace the start code unit bits with a first code unit. If it is the - same as a required later code unit, then clear the required later code - unit. This is because a search for a required code unit starts after an - explicit first code unit, but at a code unit found from the bitmap. - Patterns such as /a*a/ don't work if both the start unit and required - unit are the same. */ - - if (a >= 0) { - if ((re->flags & PCRE2_LASTSET) && (re->last_codeunit == (uint32_t)a || (b >= 0 && re->last_codeunit == (uint32_t)b))) { - re->flags &= ~(PCRE2_LASTSET | PCRE2_LASTCASELESS); - re->last_codeunit = 0; - } + /* Replace the start code unit bits with a first code unit, but only if it + is not the same as a required later code unit. This is because a search for + a required code unit starts after an explicit first code unit, but at a + code unit found from the bitmap. Patterns such as /a*a/ don't work + if both the start unit and required unit are the same. */ + + if (a >= 0 && + ( + (re->flags & PCRE2_LASTSET) == 0 || + ( + re->last_codeunit != (uint32_t)a && + (b < 0 || re->last_codeunit != (uint32_t)b) + ) + )) + { re->first_codeunit = a; flags = PCRE2_FIRSTSET; if (b >= 0) flags |= PCRE2_FIRSTCASELESS; - } + } DONE: re->flags |= flags; @@ -2050,11 +1898,9 @@ if ((re->flags & (PCRE2_MATCH_EMPTY|PCRE2_HASACCEPT)) == 0 && break; /* Leave minlength unchanged (will be zero) */ case -2: - PCRE2_DEBUG_UNREACHABLE(); return 2; /* missing capturing bracket */ case -3: - PCRE2_DEBUG_UNREACHABLE(); return 3; /* unrecognized opcode */ default: diff --git a/ext/pcre/pcre2lib/pcre2_substitute.c b/ext/pcre/pcre2lib/pcre2_substitute.c index 17040ce5fd4c9..edbb78c6d7867 100644 --- a/ext/pcre/pcre2lib/pcre2_substitute.c +++ b/ext/pcre/pcre2lib/pcre2_substitute.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2024 University of Cambridge + New API code Copyright (c) 2016-2022 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -130,21 +130,17 @@ for (; ptr < ptrend; ptr++) ptr += 1; /* Must point after \ */ erc = PRIV(check_escape)(&ptr, ptrend, &ch, &errorcode, - code->overall_options, code->extra_options, code->top_bracket, FALSE, NULL); + code->overall_options, code->extra_options, FALSE, NULL); ptr -= 1; /* Back to last code unit of escape */ if (errorcode != 0) { - /* errorcode from check_escape is positive, so must not be returned by - pcre2_substitute(). */ - rc = PCRE2_ERROR_BADREPESCAPE; + rc = errorcode; goto EXIT; } switch(erc) { case 0: /* Data character */ - case ESC_b: /* Data character */ - case ESC_v: /* Data character */ case ESC_E: /* Isolated \E is ignored */ break; @@ -152,18 +148,7 @@ for (; ptr < ptrend; ptr++) literal = TRUE; break; - case ESC_g: - /* The \g form (\g already handled by check_escape) - - Don't worry about finding the matching ">". We are super, super lenient - about validating ${} replacements inside find_text_end(), so we certainly - don't need to worry about other syntax. Importantly, a \g<..> or $<...> - sequence can't contain a '}' character. */ - break; - default: - if (erc < 0) - break; /* capture group reference */ rc = PCRE2_ERROR_BADREPESCAPE; goto EXIT; } @@ -178,426 +163,6 @@ return rc; } -/************************************************* -* Validate group name * -*************************************************/ - -/* This function scans for a capture group name, validating it -consists of legal characters, is not empty, and does not exceed -MAX_NAME_SIZE. - -Arguments: - ptrptr points to the pointer to the start of the text (updated) - ptrend end of the whole string - utf true if the input is UTF-encoded - ctypes pointer to the character types table - -Returns: TRUE if a name was read - FALSE otherwise -*/ - -static BOOL -read_name_subst(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, BOOL utf, - const uint8_t* ctypes) -{ -PCRE2_SPTR ptr = *ptrptr; -PCRE2_SPTR nameptr = ptr; - -if (ptr >= ptrend) /* No characters in name */ - goto FAILED; - -/* We do not need to check whether the name starts with a non-digit. -We are simply referencing names here, not defining them. */ - -/* See read_name in the pcre2_compile.c for the corresponding logic -restricting group names inside the pattern itself. */ - -#ifdef SUPPORT_UNICODE -if (utf) - { - uint32_t c, type; - - while (ptr < ptrend) - { - GETCHAR(c, ptr); - type = UCD_CHARTYPE(c); - if (type != ucp_Nd && PRIV(ucp_gentype)[type] != ucp_L && - c != CHAR_UNDERSCORE) break; - ptr++; - FORWARDCHARTEST(ptr, ptrend); - } - } -else -#else -(void)utf; /* Avoid compiler warning */ -#endif /* SUPPORT_UNICODE */ - -/* Handle group names in non-UTF modes. */ - - { - while (ptr < ptrend && MAX_255(*ptr) && (ctypes[*ptr] & ctype_word) != 0) - { - ptr++; - } - } - -/* Check name length */ - -if (ptr - nameptr > MAX_NAME_SIZE) - goto FAILED; - -/* Subpattern names must not be empty */ -if (ptr == nameptr) - goto FAILED; - -*ptrptr = ptr; -return TRUE; - -FAILED: -*ptrptr = ptr; -return FALSE; -} - - -/************************************************* -* Case transformations * -*************************************************/ - -#define PCRE2_SUBSTITUTE_CASE_NONE 0 -// 1, 2, 3 are PCRE2_SUBSTITUTE_CASE_LOWER, UPPER, TITLE_FIRST. -#define PCRE2_SUBSTITUTE_CASE_REVERSE_TITLE_FIRST 4 - -typedef struct { - int to_case; /* One of PCRE2_SUBSTITUTE_CASE_xyz */ - BOOL single_char; -} case_state; - -/* Helper to guess how much a string is likely to increase in size when -case-transformed. Usually, strings don't change size at all, but some rare -characters do grow. Estimate +10%, plus another few characters. - -Performing this estimation is unfortunate, but inevitable, since we can't call -the callout if we ran out of buffer space to prepare its input. - -Because this estimate is inexact (and in pathological cases, underestimates the -required buffer size) we must document that when you have a -substitute_case_callout, and you are using PCRE2_SUBSTITUTE_OVERFLOW_LENGTH, you -may need more than two calls to determine the final buffer size. */ - -static PCRE2_SIZE -pessimistic_case_inflation(PCRE2_SIZE len) -{ -return (len >> 3u) + 10; -} - -/* Case transformation behaviour if no callout is passed. */ - -static PCRE2_SIZE -default_substitute_case_callout( - PCRE2_SPTR input, PCRE2_SIZE input_len, - PCRE2_UCHAR *output, PCRE2_SIZE output_cap, - case_state *state, const pcre2_code *code) -{ -PCRE2_SPTR input_end = input + input_len; -#ifdef SUPPORT_UNICODE -BOOL utf; -BOOL ucp; -#endif -PCRE2_UCHAR temp[6]; -BOOL next_to_upper; -BOOL rest_to_upper; -BOOL single_char; -BOOL overflow = FALSE; -PCRE2_SIZE written = 0; - -/* Helpful simplifying invariant: input and output are disjoint buffers. -I believe that this code is technically undefined behaviour, because the two -pointers input/output are "unrelated" pointers and hence not comparable. Casting -via char* bypasses some but not all of those technical rules. It is not included -in release builds, in any case. */ -PCRE2_ASSERT((char *)(input + input_len) <= (char *)output || - (char *)(output + output_cap) <= (char *)input); - -#ifdef SUPPORT_UNICODE -utf = (code->overall_options & PCRE2_UTF) != 0; -ucp = (code->overall_options & PCRE2_UCP) != 0; -#endif - -if (input_len == 0) return 0; - -switch (state->to_case) - { - default: - PCRE2_DEBUG_UNREACHABLE(); - return 0; - - case PCRE2_SUBSTITUTE_CASE_LOWER: // Can be single_char TRUE or FALSE - case PCRE2_SUBSTITUTE_CASE_UPPER: // Can only be single_char FALSE - next_to_upper = rest_to_upper = (state->to_case == PCRE2_SUBSTITUTE_CASE_UPPER); - break; - - case PCRE2_SUBSTITUTE_CASE_TITLE_FIRST: // Can be single_char TRUE or FALSE - next_to_upper = TRUE; - rest_to_upper = FALSE; - state->to_case = PCRE2_SUBSTITUTE_CASE_LOWER; - break; - - case PCRE2_SUBSTITUTE_CASE_REVERSE_TITLE_FIRST: // Can only be single_char FALSE - next_to_upper = FALSE; - rest_to_upper = TRUE; - state->to_case = PCRE2_SUBSTITUTE_CASE_UPPER; - break; - } - -single_char = state->single_char; -if (single_char) - state->to_case = PCRE2_SUBSTITUTE_CASE_NONE; - -while (input < input_end) - { - uint32_t ch; - unsigned int chlen; - - GETCHARINCTEST(ch, input); - -#ifdef SUPPORT_UNICODE - if ((utf || ucp) && ch >= 128) - { - uint32_t type = UCD_CHARTYPE(ch); - if (PRIV(ucp_gentype)[type] == ucp_L && - type != (next_to_upper? ucp_Lu : ucp_Ll)) - ch = UCD_OTHERCASE(ch); - - /* TODO This is far from correct... it doesn't support the SpecialCasing.txt - mappings, but worse, it's not even correct for all the ordinary case - mappings. We should add support for those (at least), and then add the - SpecialCasing.txt mappings for Esszet and ligatures, and finally use the - Turkish casing flag on the match context. */ - } - else -#endif - if (MAX_255(ch)) - { - if (((code->tables + cbits_offset + - (next_to_upper? cbit_upper:cbit_lower) - )[ch/8] & (1u << (ch%8))) == 0) - ch = (code->tables + fcc_offset)[ch]; - } - -#ifdef SUPPORT_UNICODE - if (utf) chlen = PRIV(ord2utf)(ch, temp); else -#endif - { - temp[0] = ch; - chlen = 1; - } - - if (!overflow && chlen <= output_cap) - { - memcpy(output, temp, CU2BYTES(chlen)); - output += chlen; - output_cap -= chlen; - } - else - { - overflow = TRUE; - } - - if (chlen > ~(PCRE2_SIZE)0 - written) /* Integer overflow */ - return ~(PCRE2_SIZE)0; - written += chlen; - - next_to_upper = rest_to_upper; - - /* memcpy the remainder, if only transforming a single character. */ - - if (single_char) - { - PCRE2_SIZE rest_len = input_end - input; - - if (!overflow && rest_len <= output_cap) - memcpy(output, input, CU2BYTES(rest_len)); - - if (rest_len > ~(PCRE2_SIZE)0 - written) /* Integer overflow */ - return ~(PCRE2_SIZE)0; - written += rest_len; - - return written; - } - } - -return written; -} - -/* Helper to perform the call to the substitute_case_callout. We wrap the -user-provided callout because our internal arguments are slightly extended. We -don't want the user callout to handle the case of "\l" (first character only to -lowercase) or "\l\U" (first character to lowercase, rest to uppercase) because -those are not operations defined by Unicode. Instead the user callout simply -needs to provide the three Unicode primitives: lower, upper, titlecase. */ - -static PCRE2_SIZE -do_case_copy( - PCRE2_UCHAR *input_output, PCRE2_SIZE input_len, PCRE2_SIZE output_cap, - case_state *state, BOOL utf, - PCRE2_SIZE (*substitute_case_callout)(PCRE2_SPTR, PCRE2_SIZE, PCRE2_UCHAR *, - PCRE2_SIZE, int, void *), - void *substitute_case_callout_data) -{ -PCRE2_SPTR input = input_output; -PCRE2_UCHAR *output = input_output; -PCRE2_SIZE rc; -PCRE2_SIZE rc2; -int ch1_to_case; -int rest_to_case; -PCRE2_UCHAR ch1[6]; -PCRE2_SIZE ch1_len; -PCRE2_SPTR rest; -PCRE2_SIZE rest_len; -BOOL ch1_overflow = FALSE; -BOOL rest_overflow = FALSE; - -#if PCRE2_CODE_UNIT_WIDTH == 32 || !defined(SUPPORT_UNICODE) -(void)utf; /* Avoid compiler warning. */ -#endif - -PCRE2_ASSERT(input_len != 0); - -switch (state->to_case) - { - default: - PCRE2_DEBUG_UNREACHABLE(); - return 0; - - case PCRE2_SUBSTITUTE_CASE_LOWER: // Can be single_char TRUE or FALSE - case PCRE2_SUBSTITUTE_CASE_UPPER: // Can only be single_char FALSE - case PCRE2_SUBSTITUTE_CASE_TITLE_FIRST: // Can be single_char TRUE or FALSE - - /* The easy case, where our internal casing operations align with those of - the callout. */ - - if (state->single_char == FALSE) - { - rc = substitute_case_callout(input, input_len, output, output_cap, - state->to_case, substitute_case_callout_data); - - if (state->to_case == PCRE2_SUBSTITUTE_CASE_TITLE_FIRST) - state->to_case = PCRE2_SUBSTITUTE_CASE_LOWER; - - return rc; - } - - ch1_to_case = state->to_case; - rest_to_case = PCRE2_SUBSTITUTE_CASE_NONE; - break; - - case PCRE2_SUBSTITUTE_CASE_REVERSE_TITLE_FIRST: // Can only be single_char FALSE - ch1_to_case = PCRE2_SUBSTITUTE_CASE_LOWER; - rest_to_case = PCRE2_SUBSTITUTE_CASE_UPPER; - break; - } - -/* Identify the leading character. Take copy, because its storage overlaps with -`output`, and hence may be scrambled by the callout. */ - - { - PCRE2_SPTR ch_end = input; - uint32_t ch; - - GETCHARINCTEST(ch, ch_end); - (void) ch; - PCRE2_ASSERT(ch_end <= input + input_len && ch_end - input <= 6); - ch1_len = ch_end - input; - memcpy(ch1, input, CU2BYTES(ch1_len)); - } - -rest = input + ch1_len; -rest_len = input_len - ch1_len; - -/* Transform just ch1. The buffers are always in-place (input == output). With a -custom callout, we need a loop to discover its required buffer size. The loop -wouldn't be required if the callout were well-behaved, but it might be naughty -and return "5" the first time, then "10" the next time we call it using the -exact same input! */ - - { - PCRE2_SIZE ch1_cap; - PCRE2_SIZE max_ch1_cap; - - ch1_cap = ch1_len; /* First attempt uses the space vacated by ch1. */ - PCRE2_ASSERT(output_cap >= input_len && input_len >= rest_len); - max_ch1_cap = output_cap - rest_len; - - while (TRUE) - { - rc = substitute_case_callout(ch1, ch1_len, output, ch1_cap, ch1_to_case, - substitute_case_callout_data); - if (rc == ~(PCRE2_SIZE)0) return rc; - - if (rc <= ch1_cap) break; - - if (rc > max_ch1_cap) - { - ch1_overflow = TRUE; - break; - } - - /* Move the rest to the right, to make room for expanding ch1. */ - - memmove(input_output + rc, rest, CU2BYTES(rest_len)); - rest = input + rc; - - ch1_cap = rc; - - /* Proof of loop termination: `ch1_cap` is growing on each iteration, but - the loop ends if `rc` reaches the (unchanging) upper bound of output_cap. */ - } - } - -if (rest_to_case == PCRE2_SUBSTITUTE_CASE_NONE) - { - if (!ch1_overflow) - { - PCRE2_ASSERT(rest_len <= output_cap - rc); - memmove(output + rc, rest, CU2BYTES(rest_len)); - } - rc2 = rest_len; - - state->to_case = PCRE2_SUBSTITUTE_CASE_NONE; - } -else - { - PCRE2_UCHAR dummy[1]; - - rc2 = substitute_case_callout(rest, rest_len, - ch1_overflow? dummy : output + rc, - ch1_overflow? 0u : output_cap - rc, - rest_to_case, substitute_case_callout_data); - if (rc2 == ~(PCRE2_SIZE)0) return rc2; - - if (!ch1_overflow && rc2 > output_cap - rc) rest_overflow = TRUE; - - /* If ch1 grows so that `xform(ch1)+rest` can't fit in the buffer, but then - `rest` shrinks, it's actually possible for the total calculated length of - `xform(ch1)+xform(rest)` to come out at less than output_cap. But we can't - report that, because it would make it seem that the operation succeeded. - If either of xform(ch1) or xform(rest) won't fit in the buffer, our final - result must be > output_cap. */ - if (ch1_overflow && rc2 < rest_len) - rc2 = rest_len; - - state->to_case = PCRE2_SUBSTITUTE_CASE_UPPER; - } - -if (rc2 > ~(PCRE2_SIZE)0 - rc) /* Integer overflow */ - return ~(PCRE2_SIZE)0; - -PCRE2_ASSERT(!(ch1_overflow || rest_overflow) || rc + rc2 > output_cap); -(void)rest_overflow; - -return rc + rc2; -} - /************************************************* * Match and substitute * @@ -629,107 +194,25 @@ Returns: >= 0 number of substitutions made overflow, either give an error immediately, or keep on, accumulating the length. */ -#define CHECKMEMCPY(from, length_) \ - do { \ - PCRE2_SIZE chkmc_length = length_; \ - if (overflowed) \ - { \ - if (chkmc_length > ~(PCRE2_SIZE)0 - extra_needed) /* Integer overflow */ \ - goto TOOLARGEREPLACE; \ - extra_needed += chkmc_length; \ - } \ - else if (lengthleft < chkmc_length) \ - { \ - if ((suboptions & PCRE2_SUBSTITUTE_OVERFLOW_LENGTH) == 0) goto NOROOM; \ - overflowed = TRUE; \ - extra_needed = chkmc_length - lengthleft; \ - } \ - else \ - { \ - memcpy(buffer + buff_offset, from, CU2BYTES(chkmc_length)); \ - buff_offset += chkmc_length; \ - lengthleft -= chkmc_length; \ - } \ - } \ - while (0) - -/* This macro checks for space and copies characters with casing modifications. -On overflow, it behaves as for CHECKMEMCPY(). - -When substitute_case_callout is NULL, the source and destination buffers must -not overlap, because our default handler does not support this. */ - -#define CHECKCASECPY_BASE(length_, do_call) \ - do { \ - PCRE2_SIZE chkcc_length = (PCRE2_SIZE)(length_); \ - PCRE2_SIZE chkcc_rc; \ - do_call \ - if (lengthleft < chkcc_rc) \ - { \ - if ((suboptions & PCRE2_SUBSTITUTE_OVERFLOW_LENGTH) == 0) goto NOROOM; \ - overflowed = TRUE; \ - extra_needed = chkcc_rc - lengthleft; \ - } \ - else \ - { \ - buff_offset += chkcc_rc; \ - lengthleft -= chkcc_rc; \ - } \ - } \ - while (0) - -#define CHECKCASECPY_DEFAULT(from, length_) \ - CHECKCASECPY_BASE(length_, { \ - chkcc_rc = default_substitute_case_callout(from, chkcc_length, \ - buffer + buff_offset, \ - overflowed? 0 : lengthleft, \ - &forcecase, code); \ - if (overflowed) \ - { \ - if (chkcc_rc > ~(PCRE2_SIZE)0 - extra_needed) /* Integer overflow */ \ - goto TOOLARGEREPLACE; \ - extra_needed += chkcc_rc; \ - break; \ - } \ - }) - -#define CHECKCASECPY_CALLOUT(length_) \ - CHECKCASECPY_BASE(length_, { \ - chkcc_rc = do_case_copy(buffer + buff_offset, chkcc_length, \ - lengthleft, &forcecase, utf, \ - substitute_case_callout, \ - substitute_case_callout_data); \ - if (chkcc_rc == ~(PCRE2_SIZE)0) goto CASEERROR; \ - }) - -/* This macro does a delayed case transformation, for the situation when we have -a case-forcing callout. */ - -#define DELAYEDFORCECASE() \ - do { \ - PCRE2_SIZE chars_outstanding = (buff_offset - casestart_offset) + \ - (extra_needed - casestart_extra_needed); \ - if (chars_outstanding > 0) \ - { \ - if (overflowed) \ - { \ - PCRE2_SIZE guess = pessimistic_case_inflation(chars_outstanding); \ - if (guess > ~(PCRE2_SIZE)0 - extra_needed) /* Integer overflow */ \ - goto TOOLARGEREPLACE; \ - extra_needed += guess; \ - } \ - else \ - { \ - /* Rewind the buffer */ \ - lengthleft += (buff_offset - casestart_offset); \ - buff_offset = casestart_offset; \ - /* Care! In-place case transformation */ \ - CHECKCASECPY_CALLOUT(chars_outstanding); \ - } \ - } \ - } \ - while (0) - +#define CHECKMEMCPY(from,length) \ + { \ + if (!overflowed && lengthleft < length) \ + { \ + if ((suboptions & PCRE2_SUBSTITUTE_OVERFLOW_LENGTH) == 0) goto NOROOM; \ + overflowed = TRUE; \ + extra_needed = length - lengthleft; \ + } \ + else if (overflowed) \ + { \ + extra_needed += length; \ + } \ + else \ + { \ + memcpy(buffer + buff_offset, from, CU2BYTES(length)); \ + buff_offset += length; \ + lengthleft -= length; \ + } \ + } /* Here's the function */ @@ -741,6 +224,8 @@ pcre2_substitute(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length, { int rc; int subs; +int forcecase = 0; +int forcecasereset = 0; uint32_t ovector_count; uint32_t goptions = 0; uint32_t suboptions; @@ -749,19 +234,18 @@ BOOL escaped_literal = FALSE; BOOL overflowed = FALSE; BOOL use_existing_match; BOOL replacement_only; +#ifdef SUPPORT_UNICODE BOOL utf = (code->overall_options & PCRE2_UTF) != 0; +BOOL ucp = (code->overall_options & PCRE2_UCP) != 0; +#endif PCRE2_UCHAR temp[6]; PCRE2_SPTR ptr; -PCRE2_SPTR repend = NULL; +PCRE2_SPTR repend; PCRE2_SIZE extra_needed = 0; PCRE2_SIZE buff_offset, buff_length, lengthleft, fraglength; PCRE2_SIZE *ovector; PCRE2_SIZE ovecsave[3]; pcre2_substitute_callout_block scb; -PCRE2_SIZE sub_start_extra_needed; -PCRE2_SIZE (*substitute_case_callout)(PCRE2_SPTR, PCRE2_SIZE, PCRE2_UCHAR *, - PCRE2_SIZE, int, void *) = NULL; -void *substitute_case_callout_data = NULL; /* General initialization */ @@ -770,12 +254,6 @@ lengthleft = buff_length = *blength; *blength = PCRE2_UNSET; ovecsave[0] = ovecsave[1] = ovecsave[2] = PCRE2_UNSET; -if (mcontext != NULL) - { - substitute_case_callout = mcontext->substitute_case_callout; - substitute_case_callout_data = mcontext->substitute_case_callout_data; - } - /* Partial matching is not valid. This must come after setting *blength to PCRE2_UNSET, so as not to imply an offset in the replacement. */ @@ -808,34 +286,27 @@ case, we copy the existing match into the internal block, except for any cached heap frame size and pointer. This ensures that no changes are made to the external match data block. */ -/* WARNING: In both cases below a general context is constructed "by hand" -because calling pcre2_general_context_create() involves a memory allocation. If -the contents of a general context control block are ever changed there will -have to be changes below. */ - if (match_data == NULL) { - pcre2_general_context gcontext; + pcre2_general_context *gcontext; if (use_existing_match) return PCRE2_ERROR_NULL; - gcontext.memctl = (mcontext == NULL)? - ((const pcre2_real_code *)code)->memctl : - ((pcre2_real_match_context *)mcontext)->memctl; + gcontext = (mcontext == NULL)? + (pcre2_general_context *)code : + (pcre2_general_context *)mcontext; match_data = internal_match_data = - pcre2_match_data_create_from_pattern(code, &gcontext); + pcre2_match_data_create_from_pattern(code, gcontext); if (internal_match_data == NULL) return PCRE2_ERROR_NOMEMORY; } else if (use_existing_match) { - int pairs; - pcre2_general_context gcontext; - gcontext.memctl = (mcontext == NULL)? - ((const pcre2_real_code *)code)->memctl : - ((pcre2_real_match_context *)mcontext)->memctl; - pairs = (code->top_bracket + 1 < match_data->oveccount)? + pcre2_general_context *gcontext = (mcontext == NULL)? + (pcre2_general_context *)code : + (pcre2_general_context *)mcontext; + int pairs = (code->top_bracket + 1 < match_data->oveccount)? code->top_bracket + 1 : match_data->oveccount; internal_match_data = pcre2_match_data_create(match_data->oveccount, - &gcontext); + gcontext); if (internal_match_data == NULL) return PCRE2_ERROR_NOMEMORY; memcpy(internal_match_data, match_data, offsetof(pcre2_match_data, ovector) + 2*pairs*sizeof(PCRE2_SIZE)); @@ -909,9 +380,6 @@ do { PCRE2_SPTR ptrstack[PTR_STACK_SIZE]; uint32_t ptrstackptr = 0; - case_state forcecase = { PCRE2_SUBSTITUTE_CASE_NONE, FALSE }; - PCRE2_SIZE casestart_offset = 0; - PCRE2_SIZE casestart_extra_needed = 0; if (use_existing_match) { @@ -944,9 +412,8 @@ do save_start = start_offset++; if (subject[start_offset-1] == CHAR_CR && - (code->newline_convention == PCRE2_NEWLINE_CRLF || - code->newline_convention == PCRE2_NEWLINE_ANY || - code->newline_convention == PCRE2_NEWLINE_ANYCRLF) && + code->newline_convention != PCRE2_NEWLINE_CR && + code->newline_convention != PCRE2_NEWLINE_LF && start_offset < length && subject[start_offset] == CHAR_LF) start_offset++; @@ -1013,16 +480,14 @@ do } subs++; - /* Copy the text leading up to the match (unless not required); remember - where the insert begins and how many ovector pairs are set; and remember how - much space we have requested in extra_needed. */ + /* Copy the text leading up to the match (unless not required), and remember + where the insert begins and how many ovector pairs are set. */ if (rc == 0) rc = ovector_count; fraglength = ovector[0] - start_offset; if (!replacement_only) CHECKMEMCPY(subject + start_offset, fraglength); scb.output_offsets[0] = buff_offset; scb.oveccount = rc; - sub_start_extra_needed = extra_needed; /* Process the replacement string. If the entire replacement is literal, just copy it with length check. */ @@ -1042,13 +507,6 @@ do { uint32_t ch; unsigned int chlen; - int group; - uint32_t special; - PCRE2_SPTR text1_start = NULL; - PCRE2_SPTR text1_end = NULL; - PCRE2_SPTR text2_start = NULL; - PCRE2_SPTR text2_end = NULL; - PCRE2_UCHAR name[MAX_NAME_SIZE + 1]; /* If at the end of a nested substring, pop the stack. */ @@ -1077,62 +535,25 @@ do if (*ptr == CHAR_DOLLAR_SIGN) { + int group, n; + uint32_t special = 0; BOOL inparens; - BOOL inangle; BOOL star; PCRE2_SIZE sublength; + PCRE2_SPTR text1_start = NULL; + PCRE2_SPTR text1_end = NULL; + PCRE2_SPTR text2_start = NULL; + PCRE2_SPTR text2_end = NULL; PCRE2_UCHAR next; - PCRE2_SPTR subptr, subptrend; + PCRE2_UCHAR name[33]; if (++ptr >= repend) goto BAD; if ((next = *ptr) == CHAR_DOLLAR_SIGN) goto LOADLITERAL; - special = 0; - text1_start = NULL; - text1_end = NULL; - text2_start = NULL; - text2_end = NULL; group = -1; + n = 0; inparens = FALSE; - inangle = FALSE; star = FALSE; - subptr = NULL; - subptrend = NULL; - - /* Special $ sequences, as supported by Perl, JavaScript, .NET and others. */ - if (next == CHAR_AMPERSAND) - { - ++ptr; - group = 0; - goto GROUP_SUBSTITUTE; - } - if (next == CHAR_GRAVE_ACCENT || next == CHAR_APOSTROPHE) - { - ++ptr; - rc = pcre2_substring_length_bynumber(match_data, 0, &sublength); - if (rc < 0) goto PTREXIT; /* (Sanity-check ovector before reading from it.) */ - - if (next == CHAR_GRAVE_ACCENT) - { - subptr = subject; - subptrend = subject + ovector[0]; - } - else - { - subptr = subject + ovector[1]; - subptrend = subject + length; - } - - goto SUBPTR_SUBSTITUTE; - } - if (next == CHAR_UNDERSCORE) - { - /* Java, .NET support $_ for "entire input string". */ - ++ptr; - subptr = subject; - subptrend = subject + length; - goto SUBPTR_SUBSTITUTE; - } if (next == CHAR_LEFT_CURLY_BRACKET) { @@ -1140,31 +561,22 @@ do next = *ptr; inparens = TRUE; } - else if (next == CHAR_LESS_THAN_SIGN) - { - /* JavaScript compatibility syntax, $. Processes only named - groups (not numbered) and does not support extensions such as star - (you can do ${name} and ${*name}, but not $<*name>). */ - if (++ptr >= repend) goto BAD; - next = *ptr; - inangle = TRUE; - } - if (!inangle && next == CHAR_ASTERISK) + if (next == CHAR_ASTERISK) { if (++ptr >= repend) goto BAD; next = *ptr; star = TRUE; } - if (!star && !inangle && next >= CHAR_0 && next <= CHAR_9) + if (!star && next >= CHAR_0 && next <= CHAR_9) { group = next - CHAR_0; while (++ptr < repend) { next = *ptr; if (next < CHAR_0 || next > CHAR_9) break; - group = group * 10 + (next - CHAR_0); + group = group * 10 + next - CHAR_0; /* A check for a number greater than the hightest captured group is sufficient here; no need for a separate overflow check. If unknown @@ -1188,25 +600,25 @@ do } else { - PCRE2_SIZE name_len; - PCRE2_SPTR name_start = ptr; - if (!read_name_subst(&ptr, repend, utf, code->tables + ctypes_offset)) - goto BAD; - name_len = ptr - name_start; - memcpy(name, name_start, CU2BYTES(name_len)); - name[name_len] = 0; + const uint8_t *ctypes = code->tables + ctypes_offset; + while (MAX_255(next) && (ctypes[next] & ctype_word) != 0) + { + name[n++] = next; + if (n > 32) goto BAD; + if (++ptr >= repend) break; + next = *ptr; + } + if (n == 0) goto BAD; + name[n] = 0; } - next = 0; /* not used or updated after this point */ - (void)next; - /* In extended mode we recognize ${name:+set text:unset text} and ${name:-default text}. */ if (inparens) { if ((suboptions & PCRE2_SUBSTITUTE_EXTENDED) != 0 && - !star && ptr < repend - 2 && *ptr == CHAR_COLON) + !star && ptr < repend - 2 && next == CHAR_COLON) { special = *(++ptr); if (special != CHAR_PLUS && special != CHAR_MINUS) @@ -1241,13 +653,6 @@ do ptr++; } - if (inangle) - { - if (ptr >= repend || *ptr != CHAR_GREATER_THAN_SIGN) - goto BAD; - ptr++; - } - /* Have found a syntactically correct group number or name, or *name. Only *MARK is currently recognized. */ @@ -1258,14 +663,10 @@ do PCRE2_SPTR mark = pcre2_get_mark(match_data); if (mark != NULL) { - /* Peek backwards one code unit to obtain the length of the mark. - It can (theoretically) contain an embedded NUL. */ - fraglength = mark[-1]; - if (forcecase.to_case != PCRE2_SUBSTITUTE_CASE_NONE && - substitute_case_callout == NULL) - CHECKCASECPY_DEFAULT(mark, fraglength); - else - CHECKMEMCPY(mark, fraglength); + PCRE2_SPTR mark_start = mark; + while (*mark != 0) mark++; + fraglength = mark - mark_start; + CHECKMEMCPY(mark_start, fraglength); } } else goto BAD; @@ -1276,7 +677,8 @@ do else { - GROUP_SUBSTITUTE: + PCRE2_SPTR subptr, subptrend; + /* Find a number for a named group. In case there are duplicate names, search for the first one that is set. If the name is not found when PCRE2_SUBSTITUTE_UNKNOWN_EMPTY is set, set the group number to a @@ -1373,14 +775,41 @@ do /* Substitute a literal string, possibly forcing alphabetic case. */ - SUBPTR_SUBSTITUTE: - if (forcecase.to_case != PCRE2_SUBSTITUTE_CASE_NONE && - substitute_case_callout == NULL) - CHECKCASECPY_DEFAULT(subptr, subptrend - subptr); - else - CHECKMEMCPY(subptr, subptrend - subptr); + while (subptr < subptrend) + { + GETCHARINCTEST(ch, subptr); + if (forcecase != 0) + { +#ifdef SUPPORT_UNICODE + if (utf || ucp) + { + uint32_t type = UCD_CHARTYPE(ch); + if (PRIV(ucp_gentype)[type] == ucp_L && + type != ((forcecase > 0)? ucp_Lu : ucp_Ll)) + ch = UCD_OTHERCASE(ch); + } + else +#endif + { + if (((code->tables + cbits_offset + + ((forcecase > 0)? cbit_upper:cbit_lower) + )[ch/8] & (1u << (ch%8))) == 0) + ch = (code->tables + fcc_offset)[ch]; + } + forcecase = forcecasereset; + } + +#ifdef SUPPORT_UNICODE + if (utf) chlen = PRIV(ord2utf)(ch, temp); else +#endif + { + temp[0] = ch; + chlen = 1; + } + CHECKMEMCPY(temp, chlen); + } } - } /* End of $ processing */ + } /* Handle an escape sequence in extended mode. We can use check_escape() to process \Q, \E, \c, \o, \x and \ followed by non-alphanumerics, but @@ -1391,239 +820,123 @@ do *ptr == CHAR_BACKSLASH) { int errorcode; - case_state new_forcecase = { PCRE2_SUBSTITUTE_CASE_NONE, FALSE }; if (ptr < repend - 1) switch (ptr[1]) { case CHAR_L: - new_forcecase.to_case = PCRE2_SUBSTITUTE_CASE_LOWER; - new_forcecase.single_char = FALSE; + forcecase = forcecasereset = -1; ptr += 2; - break; + continue; case CHAR_l: - new_forcecase.to_case = PCRE2_SUBSTITUTE_CASE_LOWER; - new_forcecase.single_char = TRUE; + forcecase = -1; + forcecasereset = 0; ptr += 2; - if (ptr + 2 < repend && ptr[0] == CHAR_BACKSLASH && ptr[1] == CHAR_U) - { - /* Perl reverse-title-casing feature for \l\U */ - new_forcecase.to_case = PCRE2_SUBSTITUTE_CASE_REVERSE_TITLE_FIRST; - new_forcecase.single_char = FALSE; - ptr += 2; - } - break; + continue; case CHAR_U: - new_forcecase.to_case = PCRE2_SUBSTITUTE_CASE_UPPER; - new_forcecase.single_char = FALSE; + forcecase = forcecasereset = 1; ptr += 2; - break; + continue; case CHAR_u: - new_forcecase.to_case = PCRE2_SUBSTITUTE_CASE_TITLE_FIRST; - new_forcecase.single_char = TRUE; + forcecase = 1; + forcecasereset = 0; ptr += 2; - if (ptr + 2 < repend && ptr[0] == CHAR_BACKSLASH && ptr[1] == CHAR_L) - { - /* Perl title-casing feature for \u\L */ - new_forcecase.to_case = PCRE2_SUBSTITUTE_CASE_TITLE_FIRST; - new_forcecase.single_char = FALSE; - ptr += 2; - } - break; + continue; default: break; } - if (new_forcecase.to_case != PCRE2_SUBSTITUTE_CASE_NONE) - { - SETFORCECASE: - - /* If the substitute_case_callout is unset, our case-forcing is done - immediately. If there is a callout however, then its action is delayed - until all the characters have been collected. - - Apply the callout now, before we set the new casing mode. */ - - if (substitute_case_callout != NULL && - forcecase.to_case != PCRE2_SUBSTITUTE_CASE_NONE) - DELAYEDFORCECASE(); - - forcecase = new_forcecase; - casestart_offset = buff_offset; - casestart_extra_needed = extra_needed; - continue; - } - ptr++; /* Point after \ */ rc = PRIV(check_escape)(&ptr, repend, &ch, &errorcode, - code->overall_options, code->extra_options, code->top_bracket, FALSE, NULL); + code->overall_options, code->extra_options, FALSE, NULL); if (errorcode != 0) goto BADESCAPE; switch(rc) { case ESC_E: - goto SETFORCECASE; + forcecase = forcecasereset = 0; + continue; case ESC_Q: escaped_literal = TRUE; continue; case 0: /* Data character */ - case ESC_b: /* \b is backspace in a substitution */ - case ESC_v: /* \v is vertical tab in a substitution */ - - if (rc == ESC_b) ch = CHAR_BS; - if (rc == ESC_v) ch = CHAR_VT; - -#ifdef SUPPORT_UNICODE - if (utf) chlen = PRIV(ord2utf)(ch, temp); else -#endif - { - temp[0] = ch; - chlen = 1; - } - - if (forcecase.to_case != PCRE2_SUBSTITUTE_CASE_NONE && - substitute_case_callout == NULL) - CHECKCASECPY_DEFAULT(temp, chlen); - else - CHECKMEMCPY(temp, chlen); - continue; - - case ESC_g: - { - PCRE2_SIZE name_len; - PCRE2_SPTR name_start; - - /* Parse the \g form (\g already handled by check_escape) */ - if (ptr >= repend || *ptr != CHAR_LESS_THAN_SIGN) - goto BADESCAPE; - ++ptr; - - name_start = ptr; - if (!read_name_subst(&ptr, repend, utf, code->tables + ctypes_offset)) - goto BADESCAPE; - name_len = ptr - name_start; - - if (ptr >= repend || *ptr != CHAR_GREATER_THAN_SIGN) - goto BADESCAPE; - ++ptr; - - special = 0; - group = -1; - memcpy(name, name_start, CU2BYTES(name_len)); - name[name_len] = 0; - goto GROUP_SUBSTITUTE; - } + goto LITERAL; default: - if (rc < 0) - { - special = 0; - group = -rc - 1; - goto GROUP_SUBSTITUTE; - } goto BADESCAPE; } - } /* End of backslash processing */ + } /* Handle a literal code unit */ else { - PCRE2_SPTR ch_start; - LOADLITERAL: - ch_start = ptr; GETCHARINCTEST(ch, ptr); /* Get character value, increment pointer */ - (void) ch; - if (forcecase.to_case != PCRE2_SUBSTITUTE_CASE_NONE && - substitute_case_callout == NULL) - CHECKCASECPY_DEFAULT(ch_start, ptr - ch_start); - else - CHECKMEMCPY(ch_start, ptr - ch_start); + LITERAL: + if (forcecase != 0) + { +#ifdef SUPPORT_UNICODE + if (utf || ucp) + { + uint32_t type = UCD_CHARTYPE(ch); + if (PRIV(ucp_gentype)[type] == ucp_L && + type != ((forcecase > 0)? ucp_Lu : ucp_Ll)) + ch = UCD_OTHERCASE(ch); + } + else +#endif + { + if (((code->tables + cbits_offset + + ((forcecase > 0)? cbit_upper:cbit_lower) + )[ch/8] & (1u << (ch%8))) == 0) + ch = (code->tables + fcc_offset)[ch]; + } + forcecase = forcecasereset; + } + +#ifdef SUPPORT_UNICODE + if (utf) chlen = PRIV(ord2utf)(ch, temp); else +#endif + { + temp[0] = ch; + chlen = 1; + } + CHECKMEMCPY(temp, chlen); } /* End handling a literal code unit */ } /* End of loop for scanning the replacement. */ - /* If the substitute_case_callout is unset, our case-forcing is done - immediately. If there is a callout however, then its action is delayed - until all the characters have been collected. - - We now clean up any trailing section of the replacement for which we deferred - the case-forcing. */ - - if (substitute_case_callout != NULL && - forcecase.to_case != PCRE2_SUBSTITUTE_CASE_NONE) - DELAYEDFORCECASE(); - /* The replacement has been copied to the output, or its size has been - remembered. Handle the callout if there is one. */ + remembered. Do the callout if there is one and we have done an actual + replacement. */ - if (mcontext != NULL && mcontext->substitute_callout != NULL) + if (!overflowed && mcontext != NULL && mcontext->substitute_callout != NULL) { - /* If we an actual (non-simulated) replacement, do the callout. */ + scb.subscount = subs; + scb.output_offsets[1] = buff_offset; + rc = mcontext->substitute_callout(&scb, mcontext->substitute_callout_data); - if (!overflowed) - { - scb.subscount = subs; - scb.output_offsets[1] = buff_offset; - rc = mcontext->substitute_callout(&scb, - mcontext->substitute_callout_data); + /* A non-zero return means cancel this substitution. Instead, copy the + matched string fragment. */ - /* A non-zero return means cancel this substitution. Instead, copy the - matched string fragment. */ - - if (rc != 0) - { - PCRE2_SIZE newlength = scb.output_offsets[1] - scb.output_offsets[0]; - PCRE2_SIZE oldlength = ovector[1] - ovector[0]; - - buff_offset -= newlength; - lengthleft += newlength; - if (!replacement_only) CHECKMEMCPY(subject + ovector[0], oldlength); - - /* A negative return means do not do any more. */ - - if (rc < 0) suboptions &= (~PCRE2_SUBSTITUTE_GLOBAL); - } - } - - /* In this interesting case, we cannot do the callout, so it's hard to - estimate the required buffer size. What callers want is to be able to make - two calls to pcre2_substitute(), once with PCRE2_SUBSTITUTE_OVERFLOW_LENGTH - to discover the buffer size, and then a second and final call. Older - versions of PCRE2 violated this assumption, by proceding as if the callout - had returned zero - but on the second call to pcre2_substitute() it could - return non-zero and then overflow the buffer again. Callers probably don't - want to keep on looping to incrementally discover the buffer size. */ - - else + if (rc != 0) { - PCRE2_SIZE newlength_buf = buff_offset - scb.output_offsets[0]; - PCRE2_SIZE newlength_extra = extra_needed - sub_start_extra_needed; - PCRE2_SIZE newlength = - (newlength_extra > ~(PCRE2_SIZE)0 - newlength_buf)? /* Integer overflow */ - ~(PCRE2_SIZE)0 : newlength_buf + newlength_extra; /* Cap the addition */ + PCRE2_SIZE newlength = scb.output_offsets[1] - scb.output_offsets[0]; PCRE2_SIZE oldlength = ovector[1] - ovector[0]; - /* Be pessimistic: request whichever buffer size is larger out of - accepting or rejecting the substitution. */ + buff_offset -= newlength; + lengthleft += newlength; + if (!replacement_only) CHECKMEMCPY(subject + ovector[0], oldlength); - if (oldlength > newlength) - { - PCRE2_SIZE additional = oldlength - newlength; - if (additional > ~(PCRE2_SIZE)0 - extra_needed) /* Integer overflow */ - goto TOOLARGEREPLACE; - extra_needed += additional; - } + /* A negative return means do not do any more. */ - /* Proceed as if the callout did not return a negative. A negative - effectively rejects all future substitutions, but we want to examine them - pessimistically. */ + if (rc < 0) suboptions &= (~PCRE2_SUBSTITUTE_GLOBAL); } } @@ -1660,9 +973,6 @@ needed. Otherwise, an overflow generates an immediate error return. */ if (overflowed) { rc = PCRE2_ERROR_NOMEMORY; - - if (extra_needed > ~(PCRE2_SIZE)0 - buff_length) /* Integer overflow */ - goto TOOLARGEREPLACE; *blength = buff_length + extra_needed; } @@ -1684,14 +994,6 @@ return rc; rc = PCRE2_ERROR_NOMEMORY; goto EXIT; -CASEERROR: -rc = PCRE2_ERROR_REPLACECASE; -goto EXIT; - -TOOLARGEREPLACE: -rc = PCRE2_ERROR_TOOLARGEREPLACE; -goto EXIT; - BAD: rc = PCRE2_ERROR_BADREPLACEMENT; goto PTREXIT; diff --git a/ext/pcre/pcre2lib/pcre2_substring.c b/ext/pcre/pcre2lib/pcre2_substring.c index 88afd2348bb3f..14e919dce9308 100644 --- a/ext/pcre/pcre2lib/pcre2_substring.c +++ b/ext/pcre/pcre2lib/pcre2_substring.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2024 University of Cambridge + New API code Copyright (c) 2016-2023 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -486,7 +486,7 @@ pcre2_substring_nametable_scan(const pcre2_code *code, PCRE2_SPTR stringname, uint16_t bot = 0; uint16_t top = code->name_count; uint16_t entrysize = code->name_entry_size; -PCRE2_SPTR nametable = (PCRE2_SPTR)((const char *)code + sizeof(pcre2_real_code)); +PCRE2_SPTR nametable = (PCRE2_SPTR)((char *)code + sizeof(pcre2_real_code)); while (top > bot) { diff --git a/ext/pcre/pcre2lib/pcre2_ucd.c b/ext/pcre/pcre2lib/pcre2_ucd.c index 4c5e5163b3a9a..97dbc8b26f36a 100644 --- a/ext/pcre/pcre2lib/pcre2_ucd.c +++ b/ext/pcre/pcre2lib/pcre2_ucd.c @@ -72,13 +72,11 @@ const ucd_record PRIV(ucd_records)[] = {{0,0,0,0,0,0,0}}; const uint16_t PRIV(ucd_stage1)[] = {0}; const uint16_t PRIV(ucd_stage2)[] = {0}; const uint32_t PRIV(ucd_caseless_sets)[] = {0}; -const uint32_t PRIV(ucd_nocase_ranges)[] = {0}; -const uint32_t PRIV(ucd_nocase_ranges_size) = 0; #else -/* Total size: 116564 bytes, block size: 128. */ +/* Total size: 112564 bytes, block size: 128. */ -const char *PRIV(unicode_version) = "16.0.0"; +const char *PRIV(unicode_version) = "15.0.0"; /* When recompiling tables with a new Unicode version, please check the types in this structure definition with those in pcre2_internal.h (the actual field @@ -142,87 +140,28 @@ const uint32_t PRIV(ucd_caseless_sets)[] = { 0x004b, 0x006b, 0x212a, NOTACHAR, 0x00c5, 0x00e5, 0x212b, NOTACHAR, 0x1c88, 0xa64a, 0xa64b, NOTACHAR, - 0x0069, 0x0130, NOTACHAR, - 0x0049, 0x0131, NOTACHAR, }; -/* This is the index, within ucd_caseless_sets, of the additional -Turkish case-equivalences. The dotted I ones are this offset; the -dotless I are +3 from here. */ - -const uint32_t PRIV(ucd_turkish_dotted_i_caseset) = 112; - /* When #included in pcre2test, we don't need the table of digit sets, nor the the large main UCD tables. */ #ifndef PCRE2_PCRE2TEST -/* This table contains character ranges, where the characters in the range have -no other case. Both start and end values are excluded from the range. */ - -const uint32_t PRIV(ucd_nocase_ranges)[] = { - 0x0000, 0x0041, /* 64 */ - 0x007a, 0x00b5, /* 58 */ - 0x00b5, 0x00c0, /* 10 */ - 0x0292, 0x029d, /* 10 */ - 0x029e, 0x0345, /* 166 */ - 0x0345, 0x0370, /* 42 */ - 0x0481, 0x048a, /* 8 */ - 0x0556, 0x0561, /* 10 */ - 0x0586, 0x10a0, /* 2841 */ - 0x10ff, 0x13a0, /* 672 */ - 0x13fd, 0x1c80, /* 2178 */ - 0x1cbf, 0x1d79, /* 185 */ - 0x1d7d, 0x1d8e, /* 16 */ - 0x1d8e, 0x1e00, /* 113 */ - 0x1ffc, 0x2126, /* 297 */ - 0x2132, 0x214e, /* 27 */ - 0x214e, 0x2160, /* 17 */ - 0x2184, 0x24b6, /* 817 */ - 0x24e9, 0x2c00, /* 1814 */ - 0x2cf3, 0x2d00, /* 12 */ - 0x2d2d, 0xa640, /* 30994 */ - 0xa66d, 0xa680, /* 18 */ - 0xa69b, 0xa722, /* 134 */ - 0xa76f, 0xa779, /* 9 */ - 0xa7dc, 0xa7f5, /* 24 */ - 0xa7f6, 0xab53, /* 860 */ - 0xab53, 0xab70, /* 28 */ - 0xabbf, 0xfb05, /* 20293 */ - 0xfb06, 0xff21, /* 1050 */ - 0xff5a, 0x10400, /* 1189 */ - 0x1044f, 0x104b0, /* 96 */ - 0x104fb, 0x10570, /* 116 */ - 0x105bc, 0x10c80, /* 1731 */ - 0x10cb2, 0x10cc0, /* 13 */ - 0x10cf2, 0x10d50, /* 93 */ - 0x10d65, 0x10d70, /* 10 */ - 0x10d85, 0x118a0, /* 2842 */ - 0x118df, 0x16e40, /* 21856 */ - 0x16e7f, 0x1e900, /* 31360 */ - 0x1e943, 0x110000, /* 988860 */ - 0xffffffff, 0xffffffff /* terminator */ -}; - -/* Total: 1110933 characters. */ -const uint32_t PRIV(ucd_nocase_ranges_size) = 80; - /* This table lists the code points for the '9' characters in each set of decimal digits. It is used to ensure that all the digits in a script run come from the same set. */ const uint32_t PRIV(ucd_digit_sets)[] = { - 76, /* Number of subsequent values */ + 68, /* Number of subsequent values */ 0x00039, 0x00669, 0x006f9, 0x007c9, 0x0096f, 0x009ef, 0x00a6f, 0x00aef, 0x00b6f, 0x00bef, 0x00c6f, 0x00cef, 0x00d6f, 0x00def, 0x00e59, 0x00ed9, 0x00f29, 0x01049, 0x01099, 0x017e9, 0x01819, 0x0194f, 0x019d9, 0x01a89, 0x01a99, 0x01b59, 0x01bb9, 0x01c49, 0x01c59, 0x0a629, 0x0a8d9, 0x0a909, - 0x0a9d9, 0x0a9f9, 0x0aa59, 0x0abf9, 0x0ff19, 0x104a9, 0x10d39, 0x10d49, - 0x1106f, 0x110f9, 0x1113f, 0x111d9, 0x112f9, 0x11459, 0x114d9, 0x11659, - 0x116c9, 0x116d9, 0x116e3, 0x11739, 0x118e9, 0x11959, 0x11bf9, 0x11c59, - 0x11d59, 0x11da9, 0x11f59, 0x16139, 0x16a69, 0x16ac9, 0x16b59, 0x16d79, - 0x1ccf9, 0x1d7d7, 0x1d7e1, 0x1d7eb, 0x1d7f5, 0x1d7ff, 0x1e149, 0x1e2f9, - 0x1e4f9, 0x1e5fa, 0x1e959, 0x1fbf9, + 0x0a9d9, 0x0a9f9, 0x0aa59, 0x0abf9, 0x0ff19, 0x104a9, 0x10d39, 0x1106f, + 0x110f9, 0x1113f, 0x111d9, 0x112f9, 0x11459, 0x114d9, 0x11659, 0x116c9, + 0x11739, 0x118e9, 0x11959, 0x11c59, 0x11d59, 0x11da9, 0x11f59, 0x16a69, + 0x16ac9, 0x16b59, 0x1d7d7, 0x1d7e1, 0x1d7eb, 0x1d7f5, 0x1d7ff, 0x1e149, + 0x1e2f9, 0x1e4f9, 0x1e959, 0x1fbf9, }; /* This vector is a list of script bitsets for the Script Extension property. @@ -230,117 +169,69 @@ The number of 32-bit words in each bitset is #defined in pcre2_ucp.h as ucd_script_sets_item_size. */ const uint32_t PRIV(ucd_script_sets)[] = { - 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x40200003u, 0x00381901u, 0x00100246u, 0x00000000u, - 0x00040305u, 0x00800000u, 0x08000000u, 0x00000000u, - 0x20000001u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x00000001u, 0x00800000u, 0x00000000u, 0x00000000u, - 0x00040001u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x01000007u, 0x00000840u, 0x80000200u, 0x00000000u, - 0x01000007u, 0x00000040u, 0x80010000u, 0x00000001u, - 0x01000005u, 0x00002000u, 0x00000000u, 0x00000000u, - 0x00040041u, 0x00001000u, 0x80000000u, 0x00000000u, - 0x01000047u, 0x00002801u, 0x00010001u, 0x00000001u, - 0x10000001u, 0x00001801u, 0x00000004u, 0x00000000u, - 0x00000007u, 0x00000000u, 0x00000200u, 0x00000000u, - 0x00000051u, 0x00002840u, 0x00000202u, 0x00000001u, - 0x0000005fu, 0x00000041u, 0x00000202u, 0x00000000u, - 0x00000001u, 0x00002000u, 0x00000000u, 0x00000000u, - 0x00000041u, 0x00000000u, 0x00000002u, 0x00000000u, - 0x01000005u, 0x00000000u, 0x00010000u, 0x00000000u, - 0x01000001u, 0x00000040u, 0x00000000u, 0x00000000u, - 0x00000001u, 0x00000000u, 0x80000000u, 0x00000000u, - 0x00800001u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x00000005u, 0x00000000u, 0x00000000u, 0x00000001u, - 0x00000003u, 0x00000000u, 0x00000200u, 0x00000001u, - 0x00000041u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x11000041u, 0x00000000u, 0x00000002u, 0x00000000u, - 0x01000041u, 0x00000000u, 0x00000002u, 0x00000000u, - 0x00000041u, 0x00000000u, 0x80000000u, 0x00000000u, - 0x01000041u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x01040001u, 0x00000001u, 0x80000001u, 0x00000000u, - 0x00000002u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x00000001u, 0x00000000u, 0x00010000u, 0x00000000u, - 0x00000001u, 0x00000000u, 0x00000001u, 0x00000001u, - 0x00000001u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x00000002u, 0x00000800u, 0x00000000u, 0x00000000u, - 0x00000004u, 0x00000000u, 0x00000200u, 0x00000000u, - 0x00000004u, 0x00001000u, 0x00000000u, 0x00000000u, - 0x00000005u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x00200008u, 0x00001000u, 0x00000000u, 0x00000000u, - 0x000000e0u, 0x00010000u, 0x11200000u, 0x00000000u, - 0x000000e0u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x000000e0u, 0x00010000u, 0x11208000u, 0x00000000u, - 0x00000060u, 0x08000000u, 0x04608480u, 0x00000000u, - 0x00000060u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x000000a0u, 0x00000000u, 0x01000000u, 0x00000000u, - 0x00000020u, 0x00000000u, 0x00200000u, 0x00000000u, - 0x0001ff01u, 0x40000000u, 0x00001008u, 0x00000000u, - 0x0001ff01u, 0x00000000u, 0x00001008u, 0x00000000u, - 0x0003ff00u, 0x80004000u, 0x409c1848u, 0x00000000u, - 0x0003ff00u, 0x80004020u, 0x609c1848u, 0x00000000u, - 0x00000100u, 0x04000000u, 0x00080040u, 0x00000000u, - 0x00000200u, 0x10004000u, 0x00000000u, 0x00000000u, - 0x00000400u, 0x00000000u, 0x00002000u, 0x00000000u, - 0x00000800u, 0x00000000u, 0x00000010u, 0x00000000u, - 0x00002000u, 0x00000000u, 0x00000008u, 0x00000000u, - 0x00008000u, 0x00000000u, 0x00800000u, 0x00000002u, - 0x00100000u, 0x10000040u, 0x00000000u, 0x00000000u, - 0x00200001u, 0x00001000u, 0x00000000u, 0x00000000u, - 0x02000000u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x00000000u, 0x0000001eu, 0x00000000u, 0x00000000u, - 0x04000000u, 0x00008000u, 0x00000000u, 0x00000000u, - 0x00008300u, 0x00000000u, 0x00000008u, 0x00000000u, - 0x00000100u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x00008100u, 0x00000000u, 0x00000008u, 0x00000000u, - 0x00000300u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x00000100u, 0x40000000u, 0x00000000u, 0x00000000u, - 0x0001f100u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x00000100u, 0x00000000u, 0x00800000u, 0x00000000u, - 0x0003d300u, 0x00000000u, 0x00801008u, 0x00000002u, - 0x00000100u, 0x00000000u, 0x00000008u, 0x00000000u, - 0x00008100u, 0x00000000u, 0x00000008u, 0x00000002u, - 0x00000200u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x00000000u, 0x00000000u, 0x00800000u, 0x00000000u, - 0x00000045u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x00000040u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x04000001u, 0x00008000u, 0x00000000u, 0x00000000u, - 0x00000020u, 0x00000000u, 0x00008000u, 0x00000000u, - 0x00200000u, 0x020c1000u, 0x00004000u, 0x00000000u, - 0x00000002u, 0x20080000u, 0x00004000u, 0x00000000u, - 0x00000101u, 0x00000000u, 0x00000008u, 0x00000000u, - 0x00000001u, 0x00000800u, 0x00000000u, 0x00000000u, - 0x00000000u, 0x02200000u, 0x00000000u, 0x00000000u, - 0x00200000u, 0x04780000u, 0x00004000u, 0x00000000u, - 0x00000000u, 0x00000000u, 0x00000002u, 0x00000000u, - 0x00000020u, 0x00000000u, 0x0000c000u, 0x00000000u, - 0x40000000u, 0x00000000u, 0x00020000u, 0x00000000u, - 0xfc400000u, 0x00000000u, 0x00000000u, 0x00000000u, - 0xfc400000u, 0x00008000u, 0x00000000u, 0x00000000u, - 0x78400000u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x40000000u, 0x00000000u, 0x00000000u, 0x00000000u, - 0xfc480000u, 0x00000000u, 0x00000000u, 0x00000000u, - 0xfc480000u, 0x00800000u, 0x00000000u, 0x00000000u, - 0xf8400000u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x60000000u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x18000000u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x58000000u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x40000001u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x00018d00u, 0xc4000000u, 0x00881950u, 0x00000002u, - 0x00008d00u, 0xc4000000u, 0x00881950u, 0x00000002u, - 0x00000d00u, 0x84000000u, 0x00081950u, 0x00000000u, - 0x00000d00u, 0xc4000000u, 0x00081950u, 0x00000000u, - 0x00000300u, 0x00000000u, 0x00000000u, 0x00000002u, - 0x00002100u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x00100001u, 0x00020000u, 0x00000000u, 0x00000000u, - 0x00000000u, 0x01000400u, 0x00000000u, 0x00000000u, - 0x00000020u, 0x00010000u, 0x00000000u, 0x00000000u, - 0x000000a0u, 0x00000000u, 0x00000000u, 0x00000000u, - 0x00000000u, 0x00000280u, 0x02000000u, 0x00000000u, - 0x00000000u, 0x00000280u, 0x00000000u, 0x00000000u, - 0x00000000u, 0x00000280u, 0x00000020u, 0x00000000u, - 0x00000020u, 0x00000800u, 0x00000000u, 0x00000000u, - 0x00000000u, 0x00000000u, 0x04000080u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, + 0x00000080u, 0x00000000u, 0x00000000u, + 0x00000040u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00004000u, 0x00000000u, + 0x00000002u, 0x00000000u, 0x00000000u, + 0x00800000u, 0x00000000u, 0x00000000u, + 0x00000001u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000001u, + 0x00000010u, 0x00000000u, 0x00000000u, + 0x00000008u, 0x00000004u, 0x00000000u, + 0x00000008u, 0x40000000u, 0x00000000u, + 0x00000008u, 0x00000040u, 0x00000000u, + 0x00000018u, 0x00000000u, 0x00000000u, + 0x00000028u, 0x00000000u, 0x00000000u, + 0x000000c0u, 0x00000000u, 0x00000000u, + 0x00c00000u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00000102u, 0x00000000u, + 0x80000000u, 0x00000001u, 0x00000000u, + 0x00000004u, 0x00000008u, 0x00000000u, + 0x00000005u, 0x00000000u, 0x00000000u, + 0x00000004u, 0x00200000u, 0x00000000u, + 0x00000014u, 0x00000000u, 0x00000000u, + 0x00000040u, 0x00008000u, 0x00000000u, + 0x00000040u, 0x00000000u, 0x00000001u, + 0x00000040u, 0x00001000u, 0x00000000u, + 0x00000840u, 0x00000000u, 0x00000000u, + 0x00020001u, 0x00000000u, 0x00000000u, + 0x00000800u, 0x00008000u, 0x00000000u, + 0x00000200u, 0x00010000u, 0x00000000u, + 0x00000100u, 0x02000000u, 0x00000000u, + 0x00800001u, 0x00000000u, 0x00000000u, + 0x00300000u, 0x00000000u, 0x00000000u, + 0x00002000u, 0x00000000u, 0x00000001u, + 0x00080001u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00080000u, 0x00000008u, + 0x00080000u, 0x00000020u, 0x00000000u, + 0x00000038u, 0x00000000u, 0x00000000u, + 0x00000028u, 0x00000000u, 0x00000002u, + 0x00000080u, 0x00000810u, 0x00000000u, + 0x40010000u, 0x00000800u, 0x00000000u, + 0x80000000u, 0x00000001u, 0x00000004u, + 0x80000000u, 0x00020001u, 0x00000000u, + 0x00002040u, 0x00008000u, 0x00000000u, + 0x00000041u, 0x00008000u, 0x00000000u, + 0x00b00000u, 0x00000000u, 0x00000000u, + 0x00010001u, 0x00000080u, 0x00000000u, + 0x000020c0u, 0x00008000u, 0x00000000u, + 0x1e000000u, 0x00000000u, 0x00000000u, + 0x00000040u, 0x10040200u, 0x00000000u, + 0x00f40000u, 0x00000000u, 0x00000000u, + 0x00000038u, 0x40000040u, 0x00000002u, + 0x01f40000u, 0x00000000u, 0x00000000u, + 0x00007c40u, 0x00000000u, 0x00000000u, + 0x00000038u, 0x44000040u, 0x00000002u, + 0x000034c0u, 0x01008000u, 0x00000001u, + 0x00000018u, 0xc4480400u, 0x00000008u, + 0x00000340u, 0x11952200u, 0x00000000u, + 0x00007fc1u, 0x01008000u, 0x00000000u, + 0x00007fc1u, 0x01009000u, 0x00000000u, + 0x00002340u, 0x11952200u, 0x00000001u, + 0x00006340u, 0x11952200u, 0x00000001u, + 0x0000ffc0u, 0x3984a010u, 0x00000001u, + 0x2000ffc0u, 0x3984a010u, 0x00000001u, }; /* This vector is a list of bitsets for Boolean properties. The number of @@ -350,196 +241,181 @@ pcre2_ucp.h. */ const uint32_t PRIV(ucd_boolprop_sets)[] = { 0x00000000u, 0x00000000u, 0x00000001u, 0x00000000u, - 0x00000001u, 0x00400800u, - 0x00800001u, 0x00400800u, - 0x00800001u, 0x00050400u, - 0x00800001u, 0x00002400u, - 0x00830001u, 0x00000400u, - 0x00800001u, 0x00000400u, - 0x00800021u, 0x00002400u, - 0x00800011u, 0x00000400u, - 0x00800001u, 0x00000480u, - 0x00800001u, 0x00040400u, - 0x00801001u, 0x00000400u, - 0x00800021u, 0x00050400u, - 0x04830003u, 0x00800001u, - 0x00800021u, 0x00040400u, - 0x00800011u, 0x00000480u, - 0x048003c7u, 0x01900003u, - 0x008003c5u, 0x01900003u, - 0x00808021u, 0x00000480u, - 0x00800001u, 0x00800001u, - 0x00808021u, 0x00000400u, - 0x04800d47u, 0x01800043u, - 0x00800d45u, 0x01800043u, - 0x00800d45u, 0x01820043u, - 0x00000000u, 0x00400800u, - 0x00800000u, 0x00400000u, - 0x00800000u, 0x00000400u, + 0x00000001u, 0x00020040u, + 0x00800001u, 0x00020040u, + 0x00800001u, 0x00002820u, + 0x00800001u, 0x00000120u, + 0x00830001u, 0x00000020u, + 0x00800001u, 0x00000020u, + 0x00800021u, 0x00000120u, + 0x00800011u, 0x00000020u, + 0x00800001u, 0x00000028u, + 0x00800001u, 0x00002020u, + 0x00801001u, 0x00000020u, + 0x00800021u, 0x00002820u, + 0x24830003u, 0x00040000u, + 0x00800021u, 0x00002020u, + 0x00800011u, 0x00000028u, + 0x648003c7u, 0x000c8000u, + 0x608003c5u, 0x000c8000u, + 0x00808021u, 0x00000028u, + 0x20800001u, 0x00040000u, + 0x00808021u, 0x00000020u, + 0x64800d47u, 0x000c0004u, + 0x60800d45u, 0x000c0004u, + 0x60800d45u, 0x000c1004u, + 0x00000000u, 0x00020040u, + 0x00800000u, 0x00020000u, + 0x00800000u, 0x00000020u, 0x00808020u, 0x00000000u, - 0x00a10000u, 0x00000400u, - 0x00800044u, 0x01800043u, - 0x00800010u, 0x00002400u, - 0x00800000u, 0x00000480u, + 0x00a10000u, 0x00000020u, + 0x60800044u, 0x000c0004u, + 0x00800010u, 0x00000120u, + 0x00800000u, 0x00000028u, 0x00002020u, 0x00000000u, - 0x40800000u, 0x00000000u, - 0x00800dc4u, 0x01800043u, - 0x00c08020u, 0x00800001u, 0x00800000u, 0x00000000u, - 0x008003c4u, 0x01900003u, - 0x00800d44u, 0x01800043u, - 0x00800d44u, 0x01820043u, - 0x00804dc4u, 0x01800043u, - 0x00800004u, 0x01800003u, - 0x008007c4u, 0x01900003u, - 0x00800bc4u, 0x01800003u, - 0x00808064u, 0x01800043u, - 0x00808064u, 0x01820043u, - 0x00808024u, 0x01800003u, - 0x00c08024u, 0x01800003u, - 0x01008020u, 0x00800009u, - 0x01008de4u, 0x00800049u, - 0x01002020u, 0x00800009u, - 0x01000020u, 0x00800009u, - 0x01000024u, 0x00800009u, - 0x00808064u, 0x00000043u, - 0x00800000u, 0x00040000u, - 0x00800020u, 0x00840001u, - 0x00800dc4u, 0x018000c3u, - 0x00800044u, 0x01900083u, - 0x00800044u, 0x01900003u, - 0x008003c4u, 0x01900083u, - 0x00800000u, 0x00000080u, - 0x01000020u, 0x00000008u, + 0x60800dc4u, 0x000c0004u, + 0x20c08020u, 0x00040000u, + 0x608003c4u, 0x000c8000u, + 0x60800d44u, 0x000c0004u, + 0x60800d44u, 0x000c1004u, + 0x60804dc4u, 0x000c0004u, + 0x60800004u, 0x000c0000u, + 0x608007c4u, 0x000c8000u, + 0x60800bc4u, 0x000c0000u, + 0x60808064u, 0x000c0004u, + 0x60808064u, 0x000c1004u, + 0x60808024u, 0x000c0000u, + 0x60c08024u, 0x000c0000u, + 0x21008020u, 0x00040000u, + 0x21008de4u, 0x00040004u, + 0x21002020u, 0x00040000u, + 0x21000020u, 0x00040000u, + 0x60808064u, 0x00000004u, + 0x00800000u, 0x00002000u, + 0x20800020u, 0x00042000u, + 0x60800dc4u, 0x000c000cu, + 0x60800044u, 0x000c8008u, + 0x60800044u, 0x000c8000u, + 0x608003c4u, 0x000c8008u, + 0x00800000u, 0x00000008u, + 0x01000020u, 0x00000000u, 0x00800020u, 0x00000000u, - 0x00800000u, 0x00050000u, + 0x00800000u, 0x00002800u, 0x00801000u, 0x00000000u, - 0x01008024u, 0x00800009u, - 0x00000020u, 0x00001000u, + 0x21008024u, 0x00040000u, + 0x21000024u, 0x00040000u, + 0x00000020u, 0x00000080u, 0x00002028u, 0x00000000u, - 0x00c00024u, 0x01800003u, - 0x01000024u, 0x00800109u, - 0x01008020u, 0x00800109u, - 0x00800000u, 0x00800001u, - 0x00804004u, 0x01800003u, - 0x00800024u, 0x01800003u, - 0x01000020u, 0x00800109u, - 0x01008024u, 0x00800109u, - 0x00800004u, 0x00800001u, - 0x00800004u, 0x0180000bu, - 0x03008020u, 0x00800009u, - 0x01000004u, 0x00800009u, - 0x01400024u, 0x00800009u, - 0x01408020u, 0x00800009u, - 0x00800004u, 0x00800003u, - 0x03008024u, 0x00800009u, - 0x00800004u, 0x01800023u, + 0x60c00024u, 0x000c0000u, + 0x20800000u, 0x00040000u, + 0x60804004u, 0x000c0000u, + 0x60800024u, 0x000c0000u, + 0x20800004u, 0x00040000u, + 0x23008020u, 0x00040000u, + 0x21000004u, 0x00040000u, + 0x21408020u, 0x00040000u, + 0x60800004u, 0x00040000u, + 0x23000024u, 0x00040000u, + 0x60800004u, 0x000c0002u, 0x00800010u, 0x00000000u, - 0x00808000u, 0x00800001u, - 0x01004024u, 0x00800009u, - 0x00808004u, 0x00800001u, - 0x00800944u, 0x01800043u, - 0x00800064u, 0x01800043u, - 0x00802004u, 0x01800003u, - 0x00800344u, 0x01900003u, - 0x03008000u, 0x00800009u, + 0x20808000u, 0x00040000u, + 0x21004024u, 0x00040000u, + 0x20808004u, 0x00040000u, + 0x60800944u, 0x000c0004u, + 0x60800064u, 0x000c0004u, + 0x60802004u, 0x000c0000u, + 0x60800344u, 0x000c8000u, + 0x22808000u, 0x00040000u, + 0x22800000u, 0x00040000u, 0x00c00000u, 0x00000000u, - 0x01002020u, 0x00a00009u, - 0x01000024u, 0x0180000bu, - 0x01008020u, 0x00000008u, - 0x01408024u, 0x00800009u, + 0x21002020u, 0x00050000u, + 0x61000024u, 0x000c0000u, + 0x23000020u, 0x00040000u, + 0x01008020u, 0x00000000u, + 0x21408024u, 0x00040000u, 0x00808000u, 0x00000000u, - 0x00800044u, 0x01820043u, - 0x00800064u, 0x01820043u, - 0x01002020u, 0x00800011u, - 0x00022020u, 0x00800019u, - 0x00002028u, 0x00000800u, - 0x00801000u, 0x00000400u, - 0x00800020u, 0x00002400u, - 0x00800000u, 0x00002400u, - 0x00800020u, 0x00050400u, - 0x00800020u, 0x00000400u, - 0x00a10000u, 0x00050400u, - 0x00800000u, 0x00050400u, - 0x00800000u, 0x00800081u, - 0x00800010u, 0x00000400u, - 0x00002020u, 0x00000080u, + 0x60800044u, 0x000c1004u, + 0x60800064u, 0x000c1004u, + 0x01002020u, 0x00000001u, + 0x00022020u, 0x00000001u, + 0x00002028u, 0x00000040u, + 0x00801000u, 0x00000020u, + 0x00800020u, 0x00000120u, + 0x00800000u, 0x00000120u, + 0x00800020u, 0x00000020u, + 0x00a10000u, 0x00002820u, + 0x00800000u, 0x00002820u, + 0x20800000u, 0x00040008u, + 0x00800010u, 0x00000020u, + 0x00002020u, 0x00000008u, 0x00002000u, 0x00000000u, 0x00006020u, 0x00000000u, - 0x40800000u, 0x00000080u, - 0x40801000u, 0x00000080u, - 0x40800010u, 0x00000080u, - 0x01000020u, 0x00800089u, - 0x01020020u, 0x00000008u, - 0x00800044u, 0x018000c3u, - 0x00800000u, 0x01800083u, + 0x00801000u, 0x00000008u, + 0x00800010u, 0x00000008u, + 0x21000020u, 0x00040008u, + 0x01020020u, 0x00000000u, + 0x60800044u, 0x000c000cu, + 0x60800000u, 0x000c0008u, 0x00a10000u, 0x00000000u, - 0x00800000u, 0x01800003u, - 0x00800004u, 0x01800083u, - 0x00a10044u, 0x01800043u, - 0x00800044u, 0x018200c3u, - 0x00a10000u, 0x00000480u, - 0xc0800000u, 0x00000480u, - 0x00800010u, 0x00000480u, - 0x00801000u, 0x00000480u, - 0x00b10000u, 0x00000400u, - 0x00804010u, 0x00000400u, - 0x00a00000u, 0x00000400u, - 0x00000000u, 0x00000400u, - 0x008003c4u, 0x00100000u, - 0x00a103c4u, 0x00100000u, - 0x00800d44u, 0x00000040u, - 0x00b10000u, 0x00000480u, - 0x00a00000u, 0x00000480u, - 0x00a90000u, 0x00000400u, - 0x00b90000u, 0x00000400u, - 0x03000020u, 0x00800009u, - 0x00808024u, 0x00000400u, - 0x00800000u, 0x00040400u, - 0x00800000u, 0x00004000u, + 0x60800000u, 0x000c0000u, + 0x60800004u, 0x000c0008u, + 0x60a10044u, 0x000c0004u, + 0x60800044u, 0x000c100cu, + 0x00a10000u, 0x00000028u, + 0x00800010u, 0x00000028u, + 0x00801000u, 0x00000028u, + 0x00b10000u, 0x00000020u, + 0x00804010u, 0x00000020u, + 0x00a00000u, 0x00000020u, + 0x00000000u, 0x00000020u, + 0x008003c4u, 0x00008000u, + 0x00a103c4u, 0x00008000u, + 0x00800d44u, 0x00000004u, + 0x00b10000u, 0x00000028u, + 0x00a00000u, 0x00000028u, + 0x00a90000u, 0x00000020u, + 0x00b90000u, 0x00000020u, + 0x00808024u, 0x00000020u, + 0x00800000u, 0x00002020u, + 0x00800000u, 0x00000200u, 0x08800000u, 0x00000000u, 0x10800000u, 0x00000000u, - 0x20800000u, 0x00000000u, - 0x00800004u, 0x01800007u, - 0x01008000u, 0x00800009u, - 0x00a11000u, 0x00000400u, - 0x00808020u, 0x00000003u, - 0x00800004u, 0x01880007u, - 0x00808004u, 0x01800003u, - 0x00800004u, 0x00000003u, - 0x00000000u, 0x00000200u, - 0x01022020u, 0x00a00009u, - 0x00800000u, 0x00002000u, - 0x00800020u, 0x00050000u, - 0x00800020u, 0x00040000u, - 0x00801000u, 0x00000080u, - 0x00800010u, 0x00000080u, + 0xe0800004u, 0x000c0000u, + 0x21008000u, 0x00040000u, + 0x00a11000u, 0x00000020u, + 0x60808020u, 0x00000000u, + 0xe0800004u, 0x000c4000u, + 0x60808004u, 0x000c0000u, + 0x60800004u, 0x00000000u, + 0x00000000u, 0x00000010u, + 0x21022020u, 0x00050000u, + 0x00800000u, 0x00000100u, + 0x00800020u, 0x00002800u, 0x00800020u, 0x00002000u, - 0x04800000u, 0x00800001u, - 0x048003c4u, 0x01900003u, - 0x00808020u, 0x00000080u, - 0x04800d44u, 0x01800043u, - 0x00800010u, 0x00002000u, - 0x01008024u, 0x0080000bu, + 0x00800020u, 0x00000100u, + 0x24800000u, 0x00040000u, + 0x648003c4u, 0x000c8000u, + 0x00808020u, 0x00000008u, + 0x64800d44u, 0x000c0004u, + 0x00800010u, 0x00000100u, + 0x61008024u, 0x00040000u, 0x00000020u, 0x00000000u, - 0x00c00004u, 0x01800003u, - 0x00c08004u, 0x01800003u, - 0x01400020u, 0x00800009u, - 0x01000020u, 0x0080000du, - 0x01008004u, 0x00800009u, - 0x01000000u, 0x00800009u, - 0xc0800000u, 0x00000080u, + 0x60c00004u, 0x000c0000u, + 0x21400020u, 0x00040000u, + 0xa1000020u, 0x00040000u, + 0x21000000u, 0x00040000u, 0x00a00000u, 0x00000000u, 0x00b10000u, 0x00000000u, 0x00200000u, 0x00000000u, - 0x00800044u, 0x00100000u, - 0x00a10044u, 0x00100000u, - 0x00930000u, 0x00008000u, + 0x00800044u, 0x00008000u, + 0x00a10044u, 0x00008000u, + 0x00930000u, 0x00000400u, 0x00b90000u, 0x00000000u, 0x00a90000u, 0x00000000u, - 0x00970020u, 0x00000008u, + 0x00970020u, 0x00000000u, 0x00b30000u, 0x00000000u, - 0x01022020u, 0x00000008u, + 0x01022020u, 0x00000000u, }; /* These are the main two-stage UCD tables. The fields in each record are: @@ -548,1550 +424,1430 @@ offset to multichar other cases or zero (8 bits), offset to other case or zero (32 bits, signed), bidi class (5 bits) and script extension (11 bits) packed into a 16-bit field, and offset in binary properties table (16 bits). */ -const ucd_record PRIV(ucd_records)[] = { /* 18516 bytes, record size 12 */ - { 99, 0, 2, 0, 0, 6144, 2, }, /* 0 */ - { 99, 0, 2, 0, 0, 43008, 4, }, /* 1 */ - { 99, 0, 1, 0, 0, 4096, 4, }, /* 2 */ - { 99, 0, 2, 0, 0, 45056, 4, }, /* 3 */ - { 99, 0, 0, 0, 0, 4096, 4, }, /* 4 */ - { 99, 0, 2, 0, 0, 4096, 2, }, /* 5 */ - { 99, 0, 2, 0, 0, 43008, 2, }, /* 6 */ - { 99, 29, 12, 0, 0, 45056, 6, }, /* 7 */ - { 99, 21, 12, 0, 0, 28672, 8, }, /* 8 */ - { 99, 21, 12, 0, 0, 28672, 10, }, /* 9 */ - { 99, 21, 12, 0, 0, 14336, 12, }, /* 10 */ - { 99, 23, 12, 0, 0, 14336, 14, }, /* 11 */ - { 99, 21, 12, 0, 0, 14336, 14, }, /* 12 */ - { 99, 21, 12, 0, 0, 28672, 14, }, /* 13 */ - { 99, 21, 12, 0, 0, 28672, 16, }, /* 14 */ - { 99, 22, 12, 0, 0, 28672, 18, }, /* 15 */ - { 99, 18, 12, 0, 0, 28672, 18, }, /* 16 */ - { 99, 21, 12, 0, 0, 28672, 12, }, /* 17 */ - { 99, 25, 12, 0, 0, 12288, 20, }, /* 18 */ - { 99, 21, 12, 0, 0, 8192, 22, }, /* 19 */ - { 99, 17, 12, 0, 0, 12288, 24, }, /* 20 */ - { 99, 21, 12, 0, 0, 8192, 26, }, /* 21 */ - { 99, 21, 12, 0, 0, 8192, 14, }, /* 22 */ - { 99, 13, 12, 0, 0, 10240, 28, }, /* 23 */ - { 99, 21, 12, 0, 0, 8192, 30, }, /* 24 */ - { 99, 21, 12, 0, 0, 28672, 22, }, /* 25 */ - { 99, 25, 12, 0, 0, 28672, 32, }, /* 26 */ - { 99, 25, 12, 0, 0, 28672, 20, }, /* 27 */ +const ucd_record PRIV(ucd_records)[] = { /* 17076 bytes, record size 12 */ + { 69, 0, 2, 0, 0, 6144, 2, }, /* 0 */ + { 69, 0, 2, 0, 0, 43008, 4, }, /* 1 */ + { 69, 0, 1, 0, 0, 4096, 4, }, /* 2 */ + { 69, 0, 2, 0, 0, 45056, 4, }, /* 3 */ + { 69, 0, 0, 0, 0, 4096, 4, }, /* 4 */ + { 69, 0, 2, 0, 0, 4096, 2, }, /* 5 */ + { 69, 0, 2, 0, 0, 43008, 2, }, /* 6 */ + { 69, 29, 12, 0, 0, 45056, 6, }, /* 7 */ + { 69, 21, 12, 0, 0, 28672, 8, }, /* 8 */ + { 69, 21, 12, 0, 0, 28672, 10, }, /* 9 */ + { 69, 21, 12, 0, 0, 14336, 12, }, /* 10 */ + { 69, 23, 12, 0, 0, 14336, 14, }, /* 11 */ + { 69, 21, 12, 0, 0, 14336, 14, }, /* 12 */ + { 69, 21, 12, 0, 0, 28672, 14, }, /* 13 */ + { 69, 21, 12, 0, 0, 28672, 16, }, /* 14 */ + { 69, 22, 12, 0, 0, 28672, 18, }, /* 15 */ + { 69, 18, 12, 0, 0, 28672, 18, }, /* 16 */ + { 69, 21, 12, 0, 0, 28672, 12, }, /* 17 */ + { 69, 25, 12, 0, 0, 12288, 20, }, /* 18 */ + { 69, 21, 12, 0, 0, 8192, 22, }, /* 19 */ + { 69, 17, 12, 0, 0, 12288, 24, }, /* 20 */ + { 69, 21, 12, 0, 0, 8192, 26, }, /* 21 */ + { 69, 21, 12, 0, 0, 8192, 14, }, /* 22 */ + { 69, 13, 12, 0, 0, 10240, 28, }, /* 23 */ + { 69, 21, 12, 0, 0, 8192, 30, }, /* 24 */ + { 69, 21, 12, 0, 0, 28672, 22, }, /* 25 */ + { 69, 25, 12, 0, 0, 28672, 32, }, /* 26 */ + { 69, 25, 12, 0, 0, 28672, 20, }, /* 27 */ { 0, 9, 12, 0, 32, 18432, 34, }, /* 28 */ { 0, 9, 12, 0, 32, 18432, 36, }, /* 29 */ { 0, 9, 12, 100, 32, 18432, 36, }, /* 30 */ { 0, 9, 12, 1, 32, 18432, 36, }, /* 31 */ - { 99, 24, 12, 0, 0, 28672, 38, }, /* 32 */ - { 99, 16, 12, 0, 0, 28672, 40, }, /* 33 */ - { 99, 24, 12, 0, 0, 28672, 42, }, /* 34 */ + { 69, 24, 12, 0, 0, 28672, 38, }, /* 32 */ + { 69, 16, 12, 0, 0, 28672, 40, }, /* 33 */ + { 69, 24, 12, 0, 0, 28672, 42, }, /* 34 */ { 0, 5, 12, 0, -32, 18432, 44, }, /* 35 */ { 0, 5, 12, 0, -32, 18432, 46, }, /* 36 */ { 0, 5, 12, 0, -32, 18432, 48, }, /* 37 */ { 0, 5, 12, 100, -32, 18432, 46, }, /* 38 */ { 0, 5, 12, 1, -32, 18432, 46, }, /* 39 */ - { 99, 0, 2, 0, 0, 6144, 0, }, /* 40 */ - { 99, 0, 2, 0, 0, 4096, 50, }, /* 41 */ - { 99, 29, 12, 0, 0, 8192, 52, }, /* 42 */ - { 99, 21, 12, 0, 0, 28672, 54, }, /* 43 */ - { 99, 23, 12, 0, 0, 14336, 54, }, /* 44 */ - { 99, 26, 12, 0, 0, 28672, 54, }, /* 45 */ - { 99, 24, 12, 0, 0, 28672, 56, }, /* 46 */ - { 99, 26, 14, 0, 0, 28672, 58, }, /* 47 */ + { 69, 0, 2, 0, 0, 6144, 0, }, /* 40 */ + { 69, 0, 2, 0, 0, 4096, 50, }, /* 41 */ + { 69, 29, 12, 0, 0, 8192, 52, }, /* 42 */ + { 69, 21, 12, 0, 0, 28672, 54, }, /* 43 */ + { 69, 23, 12, 0, 0, 14336, 54, }, /* 44 */ + { 69, 26, 12, 0, 0, 28672, 54, }, /* 45 */ + { 69, 24, 12, 0, 0, 28672, 56, }, /* 46 */ + { 69, 26, 14, 0, 0, 28672, 58, }, /* 47 */ { 0, 7, 12, 0, 0, 18432, 60, }, /* 48 */ - { 99, 20, 12, 0, 0, 28672, 62, }, /* 49 */ - { 99, 25, 12, 0, 0, 28672, 64, }, /* 50 */ - { 99, 1, 2, 0, 0, 6144, 66, }, /* 51 */ - { 99, 26, 12, 0, 0, 14336, 54, }, /* 52 */ - { 99, 25, 12, 0, 0, 14336, 64, }, /* 53 */ - { 99, 15, 12, 0, 0, 10240, 68, }, /* 54 */ - { 99, 5, 12, 26, 775, 18432, 70, }, /* 55 */ - { 99, 21, 12, 0, 0, 28676, 72, }, /* 56 */ - { 99, 19, 12, 0, 0, 28672, 62, }, /* 57 */ - { 99, 15, 12, 0, 0, 28672, 74, }, /* 58 */ - { 0, 9, 12, 0, 32, 18432, 76, }, /* 59 */ - { 0, 9, 12, 104, 32, 18432, 76, }, /* 60 */ + { 69, 20, 12, 0, 0, 28672, 62, }, /* 49 */ + { 69, 25, 12, 0, 0, 28672, 64, }, /* 50 */ + { 69, 1, 2, 0, 0, 6144, 66, }, /* 51 */ + { 69, 26, 12, 0, 0, 14336, 54, }, /* 52 */ + { 69, 25, 12, 0, 0, 14336, 64, }, /* 53 */ + { 69, 15, 12, 0, 0, 10240, 68, }, /* 54 */ + { 69, 5, 12, 26, 775, 18432, 70, }, /* 55 */ + { 69, 21, 12, 0, 0, 28672, 72, }, /* 56 */ + { 69, 19, 12, 0, 0, 28672, 62, }, /* 57 */ + { 69, 15, 12, 0, 0, 28672, 68, }, /* 58 */ + { 0, 9, 12, 0, 32, 18432, 74, }, /* 59 */ + { 0, 9, 12, 104, 32, 18432, 74, }, /* 60 */ { 0, 5, 12, 0, 7615, 18432, 70, }, /* 61 */ - { 0, 5, 12, 0, -32, 18432, 78, }, /* 62 */ - { 0, 5, 12, 104, -32, 18432, 78, }, /* 63 */ - { 0, 5, 12, 0, 121, 18432, 78, }, /* 64 */ - { 0, 9, 12, 0, 1, 18432, 76, }, /* 65 */ - { 0, 5, 12, 0, -1, 18432, 78, }, /* 66 */ - { 0, 5, 12, 0, -1, 18432, 80, }, /* 67 */ - { 0, 9, 12, 0, 0, 18432, 76, }, /* 68 */ - { 0, 5, 12, 0, 0, 18432, 78, }, /* 69 */ + { 0, 5, 12, 0, -32, 18432, 76, }, /* 62 */ + { 0, 5, 12, 104, -32, 18432, 76, }, /* 63 */ + { 0, 5, 12, 0, 121, 18432, 76, }, /* 64 */ + { 0, 9, 12, 0, 1, 18432, 74, }, /* 65 */ + { 0, 5, 12, 0, -1, 18432, 76, }, /* 66 */ + { 0, 5, 12, 0, -1, 18432, 78, }, /* 67 */ + { 0, 9, 12, 0, 0, 18432, 74, }, /* 68 */ + { 0, 5, 12, 0, 0, 18432, 76, }, /* 69 */ { 0, 5, 12, 0, 0, 18432, 60, }, /* 70 */ - { 0, 5, 12, 0, 0, 18432, 82, }, /* 71 */ - { 0, 9, 12, 0, -121, 18432, 76, }, /* 72 */ + { 0, 5, 12, 0, 0, 18432, 80, }, /* 71 */ + { 0, 9, 12, 0, -121, 18432, 74, }, /* 72 */ { 0, 5, 12, 1, 0, 18432, 70, }, /* 73 */ - { 0, 5, 12, 0, 195, 18432, 78, }, /* 74 */ - { 0, 9, 12, 0, 210, 18432, 76, }, /* 75 */ - { 0, 9, 12, 0, 206, 18432, 76, }, /* 76 */ - { 0, 9, 12, 0, 205, 18432, 76, }, /* 77 */ - { 0, 9, 12, 0, 79, 18432, 76, }, /* 78 */ - { 0, 9, 12, 0, 202, 18432, 76, }, /* 79 */ - { 0, 9, 12, 0, 203, 18432, 76, }, /* 80 */ - { 0, 9, 12, 0, 207, 18432, 76, }, /* 81 */ - { 0, 5, 12, 0, 97, 18432, 78, }, /* 82 */ - { 0, 9, 12, 0, 211, 18432, 76, }, /* 83 */ - { 0, 9, 12, 0, 209, 18432, 76, }, /* 84 */ - { 0, 5, 12, 0, 163, 18432, 78, }, /* 85 */ - { 0, 5, 12, 0, 42561, 18432, 78, }, /* 86 */ - { 0, 9, 12, 0, 213, 18432, 76, }, /* 87 */ - { 0, 5, 12, 0, 130, 18432, 78, }, /* 88 */ - { 0, 9, 12, 0, 214, 18432, 76, }, /* 89 */ - { 0, 9, 12, 0, 218, 18432, 76, }, /* 90 */ - { 0, 9, 12, 0, 217, 18432, 76, }, /* 91 */ - { 0, 9, 12, 0, 219, 18432, 76, }, /* 92 */ - { 0, 7, 12, 0, 0, 18432, 84, }, /* 93 */ - { 0, 5, 12, 0, 56, 18432, 78, }, /* 94 */ - { 0, 9, 12, 5, 2, 18432, 86, }, /* 95 */ - { 0, 8, 12, 5, 1, 18432, 88, }, /* 96 */ - { 0, 5, 12, 5, -2, 18432, 78, }, /* 97 */ - { 0, 9, 12, 9, 2, 18432, 86, }, /* 98 */ - { 0, 8, 12, 9, 1, 18432, 88, }, /* 99 */ - { 0, 5, 12, 9, -2, 18432, 78, }, /* 100 */ - { 0, 9, 12, 13, 2, 18432, 86, }, /* 101 */ - { 0, 8, 12, 13, 1, 18432, 88, }, /* 102 */ - { 0, 5, 12, 13, -2, 18432, 78, }, /* 103 */ - { 0, 5, 12, 0, -79, 18432, 78, }, /* 104 */ - { 0, 9, 12, 17, 2, 18432, 86, }, /* 105 */ - { 0, 8, 12, 17, 1, 18432, 88, }, /* 106 */ - { 0, 5, 12, 17, -2, 18432, 78, }, /* 107 */ - { 0, 9, 12, 0, -97, 18432, 76, }, /* 108 */ - { 0, 9, 12, 0, -56, 18432, 76, }, /* 109 */ - { 0, 9, 12, 0, -130, 18432, 76, }, /* 110 */ - { 0, 9, 12, 0, 10795, 18432, 76, }, /* 111 */ - { 0, 9, 12, 0, -163, 18432, 76, }, /* 112 */ - { 0, 9, 12, 0, 10792, 18432, 76, }, /* 113 */ - { 0, 5, 12, 0, 10815, 18432, 78, }, /* 114 */ - { 0, 9, 12, 0, -195, 18432, 76, }, /* 115 */ - { 0, 9, 12, 0, 69, 18432, 76, }, /* 116 */ - { 0, 9, 12, 0, 71, 18432, 76, }, /* 117 */ - { 0, 5, 12, 0, 10783, 18432, 78, }, /* 118 */ - { 0, 5, 12, 0, 10780, 18432, 78, }, /* 119 */ - { 0, 5, 12, 0, 10782, 18432, 78, }, /* 120 */ - { 0, 5, 12, 0, -210, 18432, 78, }, /* 121 */ - { 0, 5, 12, 0, -206, 18432, 78, }, /* 122 */ - { 0, 5, 12, 0, -205, 18432, 78, }, /* 123 */ - { 0, 5, 12, 0, -202, 18432, 78, }, /* 124 */ - { 0, 5, 12, 0, -203, 18432, 78, }, /* 125 */ - { 0, 5, 12, 0, 42319, 18432, 78, }, /* 126 */ - { 0, 5, 12, 0, 42315, 18432, 78, }, /* 127 */ - { 0, 5, 12, 0, -207, 18432, 78, }, /* 128 */ - { 0, 5, 12, 0, 42343, 18432, 78, }, /* 129 */ - { 0, 5, 12, 0, 42280, 18432, 78, }, /* 130 */ - { 0, 5, 12, 0, 42308, 18432, 78, }, /* 131 */ - { 0, 5, 12, 0, -209, 18432, 80, }, /* 132 */ - { 0, 5, 12, 0, -211, 18432, 78, }, /* 133 */ - { 0, 5, 12, 0, 10743, 18432, 78, }, /* 134 */ - { 0, 5, 12, 0, 42305, 18432, 78, }, /* 135 */ - { 0, 5, 12, 0, 10749, 18432, 78, }, /* 136 */ - { 0, 5, 12, 0, -213, 18432, 78, }, /* 137 */ - { 0, 5, 12, 0, -214, 18432, 78, }, /* 138 */ - { 0, 5, 12, 0, 10727, 18432, 78, }, /* 139 */ - { 0, 5, 12, 0, -218, 18432, 78, }, /* 140 */ - { 0, 5, 12, 0, 42307, 18432, 78, }, /* 141 */ - { 0, 5, 12, 0, 42282, 18432, 78, }, /* 142 */ - { 0, 5, 12, 0, -69, 18432, 78, }, /* 143 */ - { 0, 5, 12, 0, -217, 18432, 78, }, /* 144 */ - { 0, 5, 12, 0, -71, 18432, 78, }, /* 145 */ - { 0, 5, 12, 0, -219, 18432, 78, }, /* 146 */ - { 0, 5, 12, 0, 42261, 18432, 80, }, /* 147 */ - { 0, 5, 12, 0, 42258, 18432, 78, }, /* 148 */ - { 0, 6, 12, 0, 0, 18432, 90, }, /* 149 */ - { 0, 6, 12, 0, 0, 18432, 92, }, /* 150 */ - { 99, 6, 12, 0, 0, 28672, 94, }, /* 151 */ - { 99, 6, 12, 0, 0, 18432, 94, }, /* 152 */ - { 99, 6, 12, 0, 0, 18440, 94, }, /* 153 */ - { 99, 6, 12, 0, 0, 18432, 90, }, /* 154 */ - { 99, 6, 12, 0, 0, 28684, 94, }, /* 155 */ - { 99, 6, 12, 0, 0, 28688, 94, }, /* 156 */ - { 99, 6, 12, 0, 0, 18432, 96, }, /* 157 */ - { 99, 24, 12, 0, 0, 28692, 56, }, /* 158 */ - { 99, 24, 12, 0, 0, 28684, 56, }, /* 159 */ - { 29, 24, 12, 0, 0, 28672, 56, }, /* 160 */ - { 106, 12, 3, 0, 0, 26648, 98, }, /* 161 */ - { 106, 12, 3, 0, 0, 26652, 98, }, /* 162 */ - { 106, 12, 3, 0, 0, 26656, 98, }, /* 163 */ - { 106, 12, 3, 0, 0, 26660, 98, }, /* 164 */ - { 106, 12, 3, 0, 0, 26664, 98, }, /* 165 */ - { 106, 12, 3, 0, 0, 26668, 98, }, /* 166 */ - { 106, 12, 3, 0, 0, 26672, 98, }, /* 167 */ - { 106, 12, 3, 0, 0, 26676, 98, }, /* 168 */ - { 106, 12, 3, 0, 0, 26680, 98, }, /* 169 */ - { 106, 12, 3, 0, 0, 26684, 98, }, /* 170 */ - { 106, 12, 3, 0, 0, 26688, 98, }, /* 171 */ - { 106, 12, 3, 0, 0, 26692, 98, }, /* 172 */ - { 106, 12, 3, 0, 0, 26696, 98, }, /* 173 */ - { 106, 12, 3, 0, 0, 26700, 98, }, /* 174 */ - { 106, 12, 3, 0, 0, 26704, 98, }, /* 175 */ - { 106, 12, 3, 0, 0, 26624, 98, }, /* 176 */ - { 106, 12, 3, 0, 0, 26708, 98, }, /* 177 */ - { 106, 12, 3, 0, 0, 26712, 98, }, /* 178 */ - { 106, 12, 3, 0, 0, 26716, 98, }, /* 179 */ - { 106, 12, 3, 0, 0, 26720, 98, }, /* 180 */ - { 106, 12, 3, 0, 0, 26724, 98, }, /* 181 */ - { 106, 12, 3, 0, 0, 26728, 98, }, /* 182 */ - { 106, 12, 3, 0, 0, 26732, 98, }, /* 183 */ - { 106, 12, 3, 0, 0, 26736, 98, }, /* 184 */ - { 106, 12, 3, 0, 0, 26740, 98, }, /* 185 */ - { 106, 12, 3, 21, 116, 26740, 100, }, /* 186 */ - { 106, 12, 3, 0, 0, 26624, 102, }, /* 187 */ - { 106, 12, 3, 0, 0, 26744, 104, }, /* 188 */ - { 106, 12, 3, 0, 0, 26624, 104, }, /* 189 */ - { 106, 12, 3, 0, 0, 26748, 98, }, /* 190 */ - { 106, 12, 3, 0, 0, 26752, 106, }, /* 191 */ - { 1, 9, 12, 0, 1, 18432, 76, }, /* 192 */ - { 1, 5, 12, 0, -1, 18432, 78, }, /* 193 */ - { 99, 6, 12, 0, 0, 28804, 94, }, /* 194 */ - { 1, 24, 12, 0, 0, 28804, 56, }, /* 195 */ - { 98, 2, 12, 0, 0, 18432, 0, }, /* 196 */ - { 1, 6, 12, 0, 0, 18432, 108, }, /* 197 */ - { 1, 5, 12, 0, 130, 18432, 78, }, /* 198 */ - { 99, 21, 12, 0, 0, 28672, 110, }, /* 199 */ - { 1, 9, 12, 0, 116, 18432, 76, }, /* 200 */ - { 1, 24, 12, 0, 0, 28672, 56, }, /* 201 */ - { 1, 9, 12, 0, 38, 18432, 76, }, /* 202 */ - { 99, 21, 12, 0, 0, 28672, 112, }, /* 203 */ - { 1, 9, 12, 0, 37, 18432, 76, }, /* 204 */ - { 1, 9, 12, 0, 64, 18432, 76, }, /* 205 */ - { 1, 9, 12, 0, 63, 18432, 76, }, /* 206 */ - { 1, 5, 12, 0, 7235, 18432, 78, }, /* 207 */ - { 1, 9, 12, 0, 32, 18432, 76, }, /* 208 */ - { 1, 9, 12, 34, 32, 18432, 76, }, /* 209 */ - { 1, 9, 12, 59, 32, 18432, 76, }, /* 210 */ - { 1, 9, 12, 38, 32, 18432, 76, }, /* 211 */ - { 1, 9, 12, 21, 32, 18432, 76, }, /* 212 */ - { 1, 9, 12, 51, 32, 18432, 76, }, /* 213 */ - { 1, 9, 12, 26, 32, 18432, 76, }, /* 214 */ - { 1, 9, 12, 47, 32, 18432, 76, }, /* 215 */ - { 1, 9, 12, 55, 32, 18432, 76, }, /* 216 */ - { 1, 9, 12, 30, 32, 18432, 76, }, /* 217 */ - { 1, 9, 12, 43, 32, 18432, 76, }, /* 218 */ - { 1, 9, 12, 96, 32, 18432, 76, }, /* 219 */ - { 1, 5, 12, 0, -38, 18432, 78, }, /* 220 */ - { 1, 5, 12, 0, -37, 18432, 78, }, /* 221 */ - { 1, 5, 12, 0, 7219, 18432, 78, }, /* 222 */ - { 1, 5, 12, 0, -32, 18432, 78, }, /* 223 */ - { 1, 5, 12, 34, -32, 18432, 78, }, /* 224 */ - { 1, 5, 12, 59, -32, 18432, 78, }, /* 225 */ - { 1, 5, 12, 38, -32, 18432, 78, }, /* 226 */ - { 1, 5, 12, 21, -116, 18432, 78, }, /* 227 */ - { 1, 5, 12, 51, -32, 18432, 78, }, /* 228 */ - { 1, 5, 12, 26, -775, 18432, 78, }, /* 229 */ - { 1, 5, 12, 47, -32, 18432, 78, }, /* 230 */ - { 1, 5, 12, 55, -32, 18432, 78, }, /* 231 */ - { 1, 5, 12, 30, 1, 18432, 70, }, /* 232 */ - { 1, 5, 12, 30, -32, 18432, 78, }, /* 233 */ - { 1, 5, 12, 43, -32, 18432, 78, }, /* 234 */ - { 1, 5, 12, 96, -32, 18432, 78, }, /* 235 */ - { 1, 5, 12, 0, -64, 18432, 78, }, /* 236 */ - { 1, 5, 12, 0, -63, 18432, 78, }, /* 237 */ - { 1, 9, 12, 0, 8, 18432, 76, }, /* 238 */ - { 1, 5, 12, 34, -30, 18432, 114, }, /* 239 */ - { 1, 5, 12, 38, -25, 18432, 114, }, /* 240 */ - { 1, 9, 12, 0, 0, 18432, 116, }, /* 241 */ - { 1, 9, 12, 0, 0, 18432, 118, }, /* 242 */ - { 1, 5, 12, 43, -15, 18432, 114, }, /* 243 */ - { 1, 5, 12, 47, -22, 18432, 70, }, /* 244 */ - { 1, 5, 12, 0, -8, 18432, 78, }, /* 245 */ - { 43, 9, 12, 0, 1, 18432, 76, }, /* 246 */ - { 43, 5, 12, 0, -1, 18432, 78, }, /* 247 */ - { 1, 5, 12, 51, -54, 18432, 114, }, /* 248 */ - { 1, 5, 12, 55, -48, 18432, 114, }, /* 249 */ - { 1, 5, 12, 0, 7, 18432, 78, }, /* 250 */ - { 1, 5, 12, 0, -116, 18432, 80, }, /* 251 */ - { 1, 9, 12, 38, -60, 18432, 120, }, /* 252 */ - { 1, 5, 12, 59, -64, 18432, 114, }, /* 253 */ - { 1, 25, 12, 0, 0, 28672, 122, }, /* 254 */ - { 1, 9, 12, 0, -7, 18432, 76, }, /* 255 */ - { 1, 5, 12, 0, 0, 18432, 60, }, /* 256 */ - { 1, 9, 12, 0, -130, 18432, 76, }, /* 257 */ - { 2, 9, 12, 0, 80, 18432, 76, }, /* 258 */ - { 2, 9, 12, 0, 32, 18432, 76, }, /* 259 */ - { 2, 9, 12, 63, 32, 18432, 76, }, /* 260 */ - { 2, 9, 12, 67, 32, 18432, 76, }, /* 261 */ - { 2, 9, 12, 71, 32, 18432, 76, }, /* 262 */ - { 2, 9, 12, 75, 32, 18432, 76, }, /* 263 */ - { 2, 9, 12, 79, 32, 18432, 76, }, /* 264 */ - { 2, 9, 12, 84, 32, 18432, 76, }, /* 265 */ - { 2, 5, 12, 0, -32, 18432, 78, }, /* 266 */ - { 2, 5, 12, 63, -32, 18432, 78, }, /* 267 */ - { 2, 5, 12, 67, -32, 18432, 78, }, /* 268 */ - { 2, 5, 12, 71, -32, 18432, 78, }, /* 269 */ - { 2, 5, 12, 75, -32, 18432, 78, }, /* 270 */ - { 2, 5, 12, 79, -32, 18432, 78, }, /* 271 */ - { 2, 5, 12, 84, -32, 18432, 78, }, /* 272 */ - { 2, 5, 12, 0, -80, 18432, 78, }, /* 273 */ - { 2, 5, 12, 0, -80, 18432, 80, }, /* 274 */ - { 2, 9, 12, 0, 1, 18432, 76, }, /* 275 */ - { 2, 5, 12, 0, -1, 18432, 78, }, /* 276 */ - { 2, 9, 12, 88, 1, 18432, 76, }, /* 277 */ - { 2, 5, 12, 88, -1, 18432, 78, }, /* 278 */ - { 2, 26, 12, 0, 0, 18432, 74, }, /* 279 */ - { 2, 12, 3, 0, 0, 26760, 98, }, /* 280 */ - { 2, 12, 3, 0, 0, 26764, 98, }, /* 281 */ - { 106, 12, 3, 0, 0, 26768, 98, }, /* 282 */ - { 2, 11, 3, 0, 0, 26624, 124, }, /* 283 */ - { 2, 9, 12, 0, 15, 18432, 76, }, /* 284 */ - { 2, 5, 12, 0, -15, 18432, 78, }, /* 285 */ - { 3, 9, 12, 0, 48, 18432, 76, }, /* 286 */ - { 3, 6, 12, 0, 0, 18432, 94, }, /* 287 */ - { 3, 21, 12, 0, 0, 18432, 74, }, /* 288 */ - { 3, 21, 12, 0, 0, 18432, 126, }, /* 289 */ - { 3, 5, 12, 0, 0, 18432, 60, }, /* 290 */ - { 3, 5, 12, 0, -48, 18432, 78, }, /* 291 */ - { 3, 5, 12, 0, 0, 18432, 70, }, /* 292 */ - { 3, 21, 12, 0, 0, 18580, 128, }, /* 293 */ - { 3, 17, 12, 0, 0, 28672, 130, }, /* 294 */ - { 3, 26, 12, 0, 0, 28672, 74, }, /* 295 */ - { 3, 23, 12, 0, 0, 14336, 74, }, /* 296 */ - { 98, 2, 12, 0, 0, 34816, 0, }, /* 297 */ - { 4, 12, 3, 0, 0, 26624, 98, }, /* 298 */ - { 4, 12, 3, 0, 0, 26624, 104, }, /* 299 */ - { 4, 12, 3, 0, 0, 26624, 132, }, /* 300 */ - { 4, 17, 12, 0, 0, 34816, 130, }, /* 301 */ - { 4, 21, 12, 0, 0, 34816, 74, }, /* 302 */ - { 4, 21, 12, 0, 0, 34816, 110, }, /* 303 */ - { 4, 12, 3, 0, 0, 26624, 106, }, /* 304 */ - { 4, 7, 12, 0, 0, 34816, 84, }, /* 305 */ - { 4, 21, 12, 0, 0, 34816, 126, }, /* 306 */ - { 5, 1, 4, 0, 0, 2048, 134, }, /* 307 */ - { 99, 1, 4, 0, 0, 2048, 134, }, /* 308 */ - { 5, 25, 12, 0, 0, 28672, 122, }, /* 309 */ - { 5, 25, 12, 0, 0, 0, 122, }, /* 310 */ - { 5, 21, 12, 0, 0, 14336, 74, }, /* 311 */ - { 5, 23, 12, 0, 0, 0, 74, }, /* 312 */ - { 99, 21, 12, 0, 0, 8344, 110, }, /* 313 */ - { 5, 21, 12, 0, 0, 0, 74, }, /* 314 */ - { 5, 26, 12, 0, 0, 28672, 74, }, /* 315 */ - { 5, 12, 3, 0, 0, 26624, 106, }, /* 316 */ - { 99, 21, 12, 0, 0, 152, 110, }, /* 317 */ - { 5, 1, 2, 0, 0, 156, 136, }, /* 318 */ - { 5, 21, 12, 0, 0, 0, 128, }, /* 319 */ - { 99, 21, 12, 0, 0, 160, 128, }, /* 320 */ - { 5, 7, 12, 0, 0, 0, 84, }, /* 321 */ - { 99, 6, 12, 0, 0, 164, 138, }, /* 322 */ - { 106, 12, 3, 0, 0, 26792, 132, }, /* 323 */ - { 106, 12, 3, 0, 0, 26792, 106, }, /* 324 */ - { 106, 12, 3, 0, 0, 26792, 140, }, /* 325 */ - { 5, 12, 3, 0, 0, 26624, 132, }, /* 326 */ - { 5, 12, 3, 0, 0, 26624, 142, }, /* 327 */ - { 5, 13, 12, 0, 0, 2220, 144, }, /* 328 */ - { 5, 21, 12, 0, 0, 2048, 74, }, /* 329 */ - { 5, 7, 12, 0, 0, 0, 146, }, /* 330 */ - { 5, 21, 12, 0, 0, 176, 128, }, /* 331 */ - { 5, 12, 3, 0, 0, 26624, 140, }, /* 332 */ - { 5, 12, 3, 0, 0, 26624, 98, }, /* 333 */ - { 5, 6, 12, 0, 0, 0, 94, }, /* 334 */ - { 5, 13, 12, 0, 0, 10240, 144, }, /* 335 */ - { 5, 26, 12, 0, 0, 0, 74, }, /* 336 */ - { 6, 21, 12, 0, 0, 0, 128, }, /* 337 */ - { 6, 21, 12, 0, 0, 0, 110, }, /* 338 */ - { 6, 21, 12, 0, 0, 0, 74, }, /* 339 */ - { 98, 2, 12, 0, 0, 0, 0, }, /* 340 */ - { 6, 1, 4, 0, 0, 0, 134, }, /* 341 */ - { 6, 7, 12, 0, 0, 0, 84, }, /* 342 */ - { 6, 12, 3, 0, 0, 26624, 106, }, /* 343 */ - { 6, 12, 3, 0, 0, 26624, 132, }, /* 344 */ - { 6, 12, 3, 0, 0, 26624, 98, }, /* 345 */ - { 7, 7, 12, 0, 0, 0, 84, }, /* 346 */ - { 7, 12, 3, 0, 0, 26624, 132, }, /* 347 */ - { 48, 13, 12, 0, 0, 34816, 144, }, /* 348 */ - { 48, 7, 12, 0, 0, 34816, 84, }, /* 349 */ - { 48, 12, 3, 0, 0, 26624, 98, }, /* 350 */ - { 48, 6, 12, 0, 0, 34816, 94, }, /* 351 */ - { 48, 26, 12, 0, 0, 28672, 74, }, /* 352 */ - { 48, 21, 12, 0, 0, 28672, 74, }, /* 353 */ - { 48, 21, 12, 0, 0, 28672, 110, }, /* 354 */ - { 48, 21, 12, 0, 0, 28672, 128, }, /* 355 */ - { 48, 6, 12, 0, 0, 34816, 138, }, /* 356 */ - { 48, 12, 3, 0, 0, 26624, 104, }, /* 357 */ - { 48, 23, 12, 0, 0, 34816, 74, }, /* 358 */ - { 54, 7, 12, 0, 0, 34816, 84, }, /* 359 */ - { 54, 12, 3, 0, 0, 26624, 106, }, /* 360 */ - { 54, 12, 3, 0, 0, 26624, 98, }, /* 361 */ - { 54, 6, 12, 0, 0, 34816, 148, }, /* 362 */ - { 54, 12, 3, 0, 0, 26624, 104, }, /* 363 */ - { 54, 21, 12, 0, 0, 34816, 110, }, /* 364 */ - { 54, 21, 12, 0, 0, 34816, 74, }, /* 365 */ - { 54, 21, 12, 0, 0, 34816, 128, }, /* 366 */ - { 59, 7, 12, 0, 0, 34816, 84, }, /* 367 */ - { 59, 12, 3, 0, 0, 26624, 104, }, /* 368 */ - { 59, 21, 12, 0, 0, 34816, 110, }, /* 369 */ - { 5, 24, 12, 0, 0, 0, 126, }, /* 370 */ - { 5, 12, 3, 0, 0, 26624, 150, }, /* 371 */ - { 5, 12, 3, 0, 0, 26624, 104, }, /* 372 */ - { 5, 12, 3, 0, 0, 26624, 152, }, /* 373 */ - { 8, 12, 3, 0, 0, 26624, 106, }, /* 374 */ - { 8, 10, 5, 0, 0, 18432, 154, }, /* 375 */ - { 8, 7, 12, 0, 0, 18432, 84, }, /* 376 */ - { 8, 7, 12, 0, 0, 18432, 156, }, /* 377 */ - { 8, 12, 3, 0, 0, 26624, 98, }, /* 378 */ - { 8, 12, 3, 0, 0, 26624, 158, }, /* 379 */ - { 106, 12, 3, 0, 0, 26804, 98, }, /* 380 */ - { 106, 12, 3, 0, 0, 26808, 98, }, /* 381 */ - { 99, 21, 12, 0, 0, 18620, 128, }, /* 382 */ - { 99, 21, 12, 0, 0, 18624, 128, }, /* 383 */ - { 8, 13, 12, 0, 0, 18628, 144, }, /* 384 */ - { 8, 21, 12, 0, 0, 18432, 74, }, /* 385 */ - { 8, 6, 12, 0, 0, 18432, 94, }, /* 386 */ - { 9, 7, 12, 0, 0, 18432, 84, }, /* 387 */ - { 9, 12, 3, 0, 0, 26624, 106, }, /* 388 */ - { 9, 10, 5, 0, 0, 18432, 154, }, /* 389 */ - { 9, 7, 12, 0, 0, 18432, 156, }, /* 390 */ - { 9, 12, 3, 0, 0, 26624, 98, }, /* 391 */ - { 9, 10, 3, 0, 0, 18432, 160, }, /* 392 */ - { 9, 12, 3, 0, 0, 26624, 158, }, /* 393 */ - { 9, 13, 12, 0, 0, 18632, 144, }, /* 394 */ - { 9, 23, 12, 0, 0, 14336, 74, }, /* 395 */ - { 9, 15, 12, 0, 0, 18432, 74, }, /* 396 */ - { 9, 26, 12, 0, 0, 18432, 74, }, /* 397 */ - { 9, 21, 12, 0, 0, 18432, 74, }, /* 398 */ - { 9, 12, 3, 0, 0, 26624, 104, }, /* 399 */ - { 10, 12, 3, 0, 0, 26624, 106, }, /* 400 */ - { 10, 10, 5, 0, 0, 18432, 154, }, /* 401 */ - { 10, 7, 12, 0, 0, 18432, 84, }, /* 402 */ - { 10, 12, 3, 0, 0, 26624, 98, }, /* 403 */ - { 10, 12, 3, 0, 0, 26624, 158, }, /* 404 */ - { 10, 13, 12, 0, 0, 18636, 144, }, /* 405 */ - { 10, 12, 3, 0, 0, 26624, 162, }, /* 406 */ - { 10, 21, 12, 0, 0, 18432, 74, }, /* 407 */ - { 11, 12, 3, 0, 0, 26624, 106, }, /* 408 */ - { 11, 10, 5, 0, 0, 18432, 154, }, /* 409 */ - { 11, 7, 12, 0, 0, 18432, 84, }, /* 410 */ - { 11, 7, 12, 0, 0, 18432, 156, }, /* 411 */ - { 11, 12, 3, 0, 0, 26624, 98, }, /* 412 */ - { 11, 12, 3, 0, 0, 26624, 158, }, /* 413 */ - { 11, 13, 12, 0, 0, 18640, 144, }, /* 414 */ - { 11, 21, 12, 0, 0, 18432, 74, }, /* 415 */ - { 11, 23, 12, 0, 0, 14336, 74, }, /* 416 */ - { 11, 12, 3, 0, 0, 26624, 162, }, /* 417 */ - { 12, 12, 3, 0, 0, 26624, 106, }, /* 418 */ - { 12, 10, 5, 0, 0, 18432, 154, }, /* 419 */ - { 12, 7, 12, 0, 0, 18432, 84, }, /* 420 */ - { 12, 7, 12, 0, 0, 18432, 156, }, /* 421 */ - { 12, 12, 3, 0, 0, 26624, 98, }, /* 422 */ - { 12, 10, 3, 0, 0, 18432, 160, }, /* 423 */ - { 12, 12, 3, 0, 0, 26624, 158, }, /* 424 */ - { 12, 12, 3, 0, 0, 26624, 164, }, /* 425 */ - { 12, 13, 12, 0, 0, 18432, 144, }, /* 426 */ - { 12, 26, 12, 0, 0, 18432, 74, }, /* 427 */ - { 12, 15, 12, 0, 0, 18432, 74, }, /* 428 */ - { 13, 12, 3, 0, 0, 26624, 106, }, /* 429 */ - { 13, 7, 12, 0, 0, 18432, 84, }, /* 430 */ - { 13, 10, 3, 0, 0, 18432, 160, }, /* 431 */ - { 13, 10, 5, 0, 0, 18432, 154, }, /* 432 */ - { 13, 12, 3, 0, 0, 26624, 158, }, /* 433 */ - { 13, 13, 12, 0, 0, 18644, 144, }, /* 434 */ - { 13, 15, 12, 0, 0, 18644, 74, }, /* 435 */ - { 13, 26, 12, 0, 0, 28884, 74, }, /* 436 */ - { 13, 26, 12, 0, 0, 28672, 74, }, /* 437 */ - { 13, 23, 12, 0, 0, 14336, 74, }, /* 438 */ - { 14, 12, 3, 0, 0, 26624, 106, }, /* 439 */ - { 14, 10, 5, 0, 0, 18432, 154, }, /* 440 */ - { 14, 7, 12, 0, 0, 18432, 84, }, /* 441 */ - { 14, 7, 12, 0, 0, 18432, 156, }, /* 442 */ - { 14, 12, 3, 0, 0, 26624, 98, }, /* 443 */ - { 14, 12, 3, 0, 0, 26624, 158, }, /* 444 */ - { 14, 13, 12, 0, 0, 18432, 144, }, /* 445 */ - { 14, 21, 12, 0, 0, 18432, 74, }, /* 446 */ - { 14, 15, 12, 0, 0, 28672, 74, }, /* 447 */ - { 14, 26, 12, 0, 0, 18432, 74, }, /* 448 */ - { 15, 7, 12, 0, 0, 18432, 84, }, /* 449 */ - { 15, 12, 3, 0, 0, 26624, 106, }, /* 450 */ - { 15, 10, 5, 0, 0, 18432, 154, }, /* 451 */ - { 15, 21, 12, 0, 0, 18432, 74, }, /* 452 */ - { 15, 12, 3, 0, 0, 26624, 98, }, /* 453 */ - { 15, 12, 3, 0, 0, 18432, 106, }, /* 454 */ - { 15, 10, 3, 0, 0, 18432, 160, }, /* 455 */ - { 15, 12, 3, 0, 0, 26624, 158, }, /* 456 */ - { 15, 13, 12, 0, 0, 18648, 144, }, /* 457 */ - { 16, 12, 3, 0, 0, 26624, 106, }, /* 458 */ - { 16, 10, 5, 0, 0, 18432, 154, }, /* 459 */ - { 16, 7, 12, 0, 0, 18432, 84, }, /* 460 */ - { 16, 7, 12, 0, 0, 18432, 156, }, /* 461 */ - { 16, 12, 3, 0, 0, 26624, 158, }, /* 462 */ - { 16, 10, 3, 0, 0, 18432, 160, }, /* 463 */ - { 16, 7, 4, 0, 0, 18432, 84, }, /* 464 */ - { 16, 26, 12, 0, 0, 18432, 74, }, /* 465 */ - { 16, 15, 12, 0, 0, 18432, 74, }, /* 466 */ - { 16, 13, 12, 0, 0, 18432, 144, }, /* 467 */ - { 17, 12, 3, 0, 0, 26624, 106, }, /* 468 */ - { 17, 10, 5, 0, 0, 18432, 154, }, /* 469 */ - { 17, 7, 12, 0, 0, 18432, 84, }, /* 470 */ - { 17, 12, 3, 0, 0, 26624, 158, }, /* 471 */ - { 17, 10, 3, 0, 0, 18432, 160, }, /* 472 */ - { 17, 13, 12, 0, 0, 18432, 144, }, /* 473 */ - { 17, 21, 12, 0, 0, 18432, 74, }, /* 474 */ - { 18, 7, 12, 0, 0, 18432, 84, }, /* 475 */ - { 18, 12, 3, 0, 0, 26624, 106, }, /* 476 */ - { 18, 7, 5, 0, 0, 18432, 166, }, /* 477 */ - { 18, 12, 3, 0, 0, 26624, 168, }, /* 478 */ - { 99, 23, 12, 0, 0, 14336, 74, }, /* 479 */ - { 18, 7, 12, 0, 0, 18432, 170, }, /* 480 */ - { 18, 6, 12, 0, 0, 18432, 138, }, /* 481 */ - { 18, 12, 3, 0, 0, 26624, 98, }, /* 482 */ - { 18, 21, 12, 0, 0, 18432, 74, }, /* 483 */ - { 18, 13, 12, 0, 0, 18432, 144, }, /* 484 */ - { 18, 21, 12, 0, 0, 18432, 110, }, /* 485 */ - { 100, 7, 12, 0, 0, 18432, 84, }, /* 486 */ - { 100, 12, 3, 0, 0, 26624, 106, }, /* 487 */ - { 100, 7, 5, 0, 0, 18432, 166, }, /* 488 */ - { 100, 12, 3, 0, 0, 26624, 158, }, /* 489 */ - { 100, 7, 12, 0, 0, 18432, 170, }, /* 490 */ - { 100, 6, 12, 0, 0, 18432, 138, }, /* 491 */ - { 100, 12, 3, 0, 0, 26624, 98, }, /* 492 */ - { 100, 12, 3, 0, 0, 26624, 104, }, /* 493 */ - { 100, 13, 12, 0, 0, 18432, 144, }, /* 494 */ - { 19, 7, 12, 0, 0, 18432, 84, }, /* 495 */ - { 19, 26, 12, 0, 0, 18432, 74, }, /* 496 */ - { 19, 21, 12, 0, 0, 18432, 74, }, /* 497 */ - { 19, 21, 12, 0, 0, 18432, 110, }, /* 498 */ - { 19, 12, 3, 0, 0, 26624, 98, }, /* 499 */ - { 19, 13, 12, 0, 0, 18432, 144, }, /* 500 */ - { 19, 15, 12, 0, 0, 18432, 74, }, /* 501 */ - { 19, 22, 12, 0, 0, 28672, 172, }, /* 502 */ - { 19, 18, 12, 0, 0, 28672, 172, }, /* 503 */ - { 19, 10, 5, 0, 0, 18432, 174, }, /* 504 */ - { 19, 12, 3, 0, 0, 26624, 106, }, /* 505 */ - { 19, 12, 3, 0, 0, 26624, 176, }, /* 506 */ - { 19, 10, 5, 0, 0, 18432, 154, }, /* 507 */ - { 19, 12, 3, 0, 0, 26624, 132, }, /* 508 */ - { 19, 12, 3, 0, 0, 26624, 158, }, /* 509 */ - { 99, 26, 12, 0, 0, 18432, 74, }, /* 510 */ - { 20, 7, 12, 0, 0, 18432, 84, }, /* 511 */ - { 20, 10, 12, 0, 0, 18432, 154, }, /* 512 */ - { 20, 12, 3, 0, 0, 26624, 106, }, /* 513 */ - { 20, 10, 5, 0, 0, 18432, 154, }, /* 514 */ - { 20, 12, 3, 0, 0, 26624, 98, }, /* 515 */ - { 20, 12, 3, 0, 0, 26624, 158, }, /* 516 */ - { 20, 13, 12, 0, 0, 18652, 144, }, /* 517 */ - { 20, 21, 12, 0, 0, 18432, 128, }, /* 518 */ - { 20, 21, 12, 0, 0, 18432, 74, }, /* 519 */ - { 20, 10, 12, 0, 0, 18432, 178, }, /* 520 */ - { 20, 12, 3, 0, 0, 26624, 132, }, /* 521 */ - { 20, 13, 12, 0, 0, 18432, 144, }, /* 522 */ - { 20, 26, 12, 0, 0, 18432, 74, }, /* 523 */ - { 21, 9, 12, 0, 7264, 18432, 76, }, /* 524 */ - { 21, 5, 12, 0, 3008, 18432, 180, }, /* 525 */ - { 99, 21, 12, 0, 0, 18656, 74, }, /* 526 */ - { 21, 6, 12, 0, 0, 18432, 182, }, /* 527 */ - { 22, 7, 6, 0, 0, 18432, 84, }, /* 528 */ - { 22, 7, 6, 0, 0, 18432, 184, }, /* 529 */ - { 22, 7, 7, 0, 0, 18432, 184, }, /* 530 */ - { 22, 7, 7, 0, 0, 18432, 84, }, /* 531 */ - { 22, 7, 8, 0, 0, 18432, 84, }, /* 532 */ - { 23, 7, 12, 0, 0, 18432, 84, }, /* 533 */ - { 23, 12, 3, 0, 0, 26624, 98, }, /* 534 */ - { 23, 21, 12, 0, 0, 18432, 74, }, /* 535 */ - { 23, 21, 12, 0, 0, 18432, 110, }, /* 536 */ - { 23, 21, 12, 0, 0, 18432, 128, }, /* 537 */ - { 23, 15, 12, 0, 0, 18432, 144, }, /* 538 */ - { 23, 15, 12, 0, 0, 18432, 74, }, /* 539 */ - { 23, 26, 12, 0, 0, 28672, 74, }, /* 540 */ - { 24, 9, 12, 0, 38864, 18432, 186, }, /* 541 */ - { 24, 9, 12, 0, 8, 18432, 186, }, /* 542 */ - { 24, 5, 12, 0, -8, 18432, 70, }, /* 543 */ - { 101, 17, 12, 0, 0, 28672, 130, }, /* 544 */ - { 101, 7, 12, 0, 0, 18432, 84, }, /* 545 */ - { 101, 26, 12, 0, 0, 18432, 74, }, /* 546 */ - { 101, 21, 12, 0, 0, 18432, 128, }, /* 547 */ - { 102, 29, 12, 0, 0, 45056, 52, }, /* 548 */ - { 102, 7, 12, 0, 0, 18432, 84, }, /* 549 */ - { 102, 22, 12, 0, 0, 28672, 172, }, /* 550 */ - { 102, 18, 12, 0, 0, 28672, 172, }, /* 551 */ - { 25, 7, 12, 0, 0, 18432, 84, }, /* 552 */ - { 99, 21, 12, 0, 0, 18660, 110, }, /* 553 */ - { 25, 14, 12, 0, 0, 18432, 84, }, /* 554 */ - { 33, 7, 12, 0, 0, 18432, 84, }, /* 555 */ - { 33, 12, 3, 0, 0, 26624, 106, }, /* 556 */ - { 33, 12, 3, 0, 0, 26624, 158, }, /* 557 */ - { 33, 10, 3, 0, 0, 18432, 188, }, /* 558 */ - { 34, 7, 12, 0, 0, 18432, 84, }, /* 559 */ - { 34, 12, 3, 0, 0, 26624, 106, }, /* 560 */ - { 34, 10, 3, 0, 0, 18432, 188, }, /* 561 */ - { 99, 21, 12, 0, 0, 18664, 128, }, /* 562 */ - { 35, 7, 12, 0, 0, 18432, 84, }, /* 563 */ - { 35, 12, 3, 0, 0, 26624, 106, }, /* 564 */ - { 36, 7, 12, 0, 0, 18432, 84, }, /* 565 */ - { 36, 12, 3, 0, 0, 26624, 106, }, /* 566 */ - { 103, 7, 12, 0, 0, 18432, 84, }, /* 567 */ - { 103, 7, 12, 0, 0, 18432, 146, }, /* 568 */ - { 103, 12, 3, 0, 0, 26624, 102, }, /* 569 */ - { 103, 10, 5, 0, 0, 18432, 154, }, /* 570 */ - { 103, 12, 3, 0, 0, 26624, 106, }, /* 571 */ - { 103, 12, 3, 0, 0, 26624, 98, }, /* 572 */ - { 103, 12, 3, 0, 0, 26624, 158, }, /* 573 */ - { 103, 21, 12, 0, 0, 18432, 128, }, /* 574 */ - { 103, 21, 12, 0, 0, 18432, 110, }, /* 575 */ - { 103, 6, 12, 0, 0, 18432, 148, }, /* 576 */ - { 103, 21, 12, 0, 0, 18432, 74, }, /* 577 */ - { 103, 23, 12, 0, 0, 14336, 74, }, /* 578 */ - { 103, 13, 12, 0, 0, 18432, 144, }, /* 579 */ - { 103, 15, 12, 0, 0, 28672, 74, }, /* 580 */ - { 26, 21, 12, 0, 0, 28672, 74, }, /* 581 */ - { 99, 21, 12, 0, 0, 28908, 110, }, /* 582 */ - { 99, 21, 12, 0, 0, 28908, 128, }, /* 583 */ - { 26, 21, 12, 0, 0, 28672, 110, }, /* 584 */ - { 26, 17, 12, 0, 0, 28672, 130, }, /* 585 */ - { 26, 21, 12, 0, 0, 28672, 128, }, /* 586 */ - { 26, 21, 12, 0, 0, 28672, 190, }, /* 587 */ - { 26, 12, 3, 0, 0, 26624, 192, }, /* 588 */ - { 26, 1, 2, 0, 0, 6144, 66, }, /* 589 */ - { 26, 13, 12, 0, 0, 18432, 144, }, /* 590 */ - { 26, 7, 12, 0, 0, 18432, 84, }, /* 591 */ - { 26, 6, 12, 0, 0, 18432, 138, }, /* 592 */ - { 26, 12, 3, 0, 0, 26624, 194, }, /* 593 */ - { 26, 12, 3, 0, 0, 26624, 106, }, /* 594 */ - { 37, 7, 12, 0, 0, 18432, 84, }, /* 595 */ - { 37, 12, 3, 0, 0, 26624, 106, }, /* 596 */ - { 37, 10, 5, 0, 0, 18432, 154, }, /* 597 */ - { 37, 12, 3, 0, 0, 26624, 98, }, /* 598 */ - { 37, 26, 12, 0, 0, 28672, 74, }, /* 599 */ - { 37, 21, 12, 0, 0, 28672, 128, }, /* 600 */ - { 37, 13, 12, 0, 0, 18432, 144, }, /* 601 */ - { 38, 7, 12, 0, 0, 18432, 84, }, /* 602 */ - { 110, 7, 12, 0, 0, 18432, 84, }, /* 603 */ - { 110, 7, 12, 0, 0, 18432, 170, }, /* 604 */ - { 110, 13, 12, 0, 0, 18432, 144, }, /* 605 */ - { 110, 15, 12, 0, 0, 18432, 144, }, /* 606 */ - { 110, 26, 12, 0, 0, 28672, 74, }, /* 607 */ - { 103, 26, 12, 0, 0, 28672, 74, }, /* 608 */ - { 42, 7, 12, 0, 0, 18432, 84, }, /* 609 */ - { 42, 12, 3, 0, 0, 26624, 106, }, /* 610 */ - { 42, 10, 5, 0, 0, 18432, 154, }, /* 611 */ - { 42, 21, 12, 0, 0, 18432, 74, }, /* 612 */ - { 123, 7, 12, 0, 0, 18432, 84, }, /* 613 */ - { 123, 10, 5, 0, 0, 18432, 154, }, /* 614 */ - { 123, 12, 3, 0, 0, 26624, 106, }, /* 615 */ - { 123, 12, 3, 0, 0, 26624, 158, }, /* 616 */ - { 123, 10, 12, 0, 0, 18432, 154, }, /* 617 */ - { 123, 12, 3, 0, 0, 26624, 98, }, /* 618 */ - { 123, 13, 12, 0, 0, 18432, 144, }, /* 619 */ - { 123, 21, 12, 0, 0, 18432, 74, }, /* 620 */ - { 123, 6, 12, 0, 0, 18432, 138, }, /* 621 */ - { 123, 21, 12, 0, 0, 18432, 128, }, /* 622 */ - { 106, 11, 3, 0, 0, 26624, 196, }, /* 623 */ - { 106, 12, 3, 0, 0, 26624, 106, }, /* 624 */ - { 113, 12, 3, 0, 0, 26624, 106, }, /* 625 */ - { 113, 10, 5, 0, 0, 18432, 154, }, /* 626 */ - { 113, 7, 12, 0, 0, 18432, 84, }, /* 627 */ - { 113, 12, 3, 0, 0, 26624, 98, }, /* 628 */ - { 113, 10, 3, 0, 0, 18432, 160, }, /* 629 */ - { 113, 10, 3, 0, 0, 18432, 188, }, /* 630 */ - { 113, 21, 12, 0, 0, 18432, 128, }, /* 631 */ - { 113, 13, 12, 0, 0, 18432, 144, }, /* 632 */ - { 113, 21, 12, 0, 0, 18432, 74, }, /* 633 */ - { 113, 21, 12, 0, 0, 18432, 110, }, /* 634 */ - { 113, 26, 12, 0, 0, 18432, 74, }, /* 635 */ - { 116, 12, 3, 0, 0, 26624, 106, }, /* 636 */ - { 116, 10, 5, 0, 0, 18432, 154, }, /* 637 */ - { 116, 7, 12, 0, 0, 18432, 84, }, /* 638 */ - { 116, 10, 3, 0, 0, 18432, 188, }, /* 639 */ - { 116, 12, 3, 0, 0, 26624, 158, }, /* 640 */ - { 116, 13, 12, 0, 0, 18432, 144, }, /* 641 */ - { 132, 7, 12, 0, 0, 18432, 84, }, /* 642 */ - { 132, 12, 3, 0, 0, 26624, 98, }, /* 643 */ - { 132, 10, 5, 0, 0, 18432, 154, }, /* 644 */ - { 132, 12, 3, 0, 0, 26624, 106, }, /* 645 */ - { 132, 10, 3, 0, 0, 18432, 188, }, /* 646 */ - { 132, 21, 12, 0, 0, 18432, 74, }, /* 647 */ - { 117, 7, 12, 0, 0, 18432, 84, }, /* 648 */ - { 117, 10, 5, 0, 0, 18432, 154, }, /* 649 */ - { 117, 12, 3, 0, 0, 26624, 106, }, /* 650 */ - { 117, 12, 3, 0, 0, 26624, 198, }, /* 651 */ - { 117, 12, 3, 0, 0, 26624, 98, }, /* 652 */ - { 117, 21, 12, 0, 0, 18432, 128, }, /* 653 */ - { 117, 21, 12, 0, 0, 18432, 110, }, /* 654 */ - { 117, 13, 12, 0, 0, 18432, 144, }, /* 655 */ - { 118, 13, 12, 0, 0, 18432, 144, }, /* 656 */ - { 118, 7, 12, 0, 0, 18432, 84, }, /* 657 */ - { 118, 6, 12, 0, 0, 18432, 94, }, /* 658 */ - { 118, 6, 12, 0, 0, 18432, 96, }, /* 659 */ - { 118, 21, 12, 0, 0, 18432, 128, }, /* 660 */ - { 2, 5, 12, 63, -6222, 18432, 70, }, /* 661 */ - { 2, 5, 12, 67, -6221, 18432, 70, }, /* 662 */ - { 2, 5, 12, 71, -6212, 18432, 70, }, /* 663 */ - { 2, 5, 12, 75, -6210, 18432, 70, }, /* 664 */ - { 2, 5, 12, 79, -6210, 18432, 70, }, /* 665 */ - { 2, 5, 12, 79, -6211, 18432, 70, }, /* 666 */ - { 2, 5, 12, 84, -6204, 18432, 70, }, /* 667 */ - { 2, 5, 12, 88, -6180, 18432, 70, }, /* 668 */ - { 2, 5, 12, 108, 35267, 18432, 70, }, /* 669 */ - { 21, 9, 12, 0, -3008, 18432, 76, }, /* 670 */ - { 116, 21, 12, 0, 0, 18432, 74, }, /* 671 */ - { 106, 12, 3, 0, 0, 26864, 98, }, /* 672 */ - { 106, 12, 3, 0, 0, 26868, 98, }, /* 673 */ - { 99, 21, 12, 0, 0, 18680, 200, }, /* 674 */ - { 106, 12, 3, 0, 0, 26876, 98, }, /* 675 */ - { 106, 12, 3, 0, 0, 26880, 98, }, /* 676 */ - { 106, 12, 3, 0, 0, 26884, 98, }, /* 677 */ - { 99, 10, 5, 0, 0, 18684, 174, }, /* 678 */ - { 99, 7, 12, 0, 0, 18696, 84, }, /* 679 */ - { 99, 7, 12, 0, 0, 18684, 84, }, /* 680 */ - { 99, 7, 12, 0, 0, 18676, 84, }, /* 681 */ - { 99, 7, 12, 0, 0, 18700, 84, }, /* 682 */ - { 99, 7, 12, 0, 0, 18704, 84, }, /* 683 */ - { 106, 12, 3, 0, 0, 26900, 98, }, /* 684 */ - { 99, 10, 5, 0, 0, 18712, 174, }, /* 685 */ - { 106, 12, 3, 0, 0, 26896, 98, }, /* 686 */ - { 99, 7, 12, 0, 0, 18716, 84, }, /* 687 */ - { 2, 5, 12, 0, 0, 18432, 60, }, /* 688 */ - { 1, 6, 12, 0, 0, 18432, 90, }, /* 689 */ - { 2, 6, 12, 0, 0, 18432, 182, }, /* 690 */ - { 0, 5, 12, 0, 35332, 18432, 78, }, /* 691 */ - { 0, 5, 12, 0, 3814, 18432, 78, }, /* 692 */ - { 0, 5, 12, 0, 35384, 18432, 78, }, /* 693 */ - { 0, 5, 12, 0, 0, 18432, 202, }, /* 694 */ - { 0, 6, 12, 0, 0, 18432, 182, }, /* 695 */ - { 0, 6, 12, 0, 0, 18432, 204, }, /* 696 */ - { 1, 6, 12, 0, 0, 18432, 182, }, /* 697 */ - { 106, 12, 3, 0, 0, 26740, 104, }, /* 698 */ - { 106, 12, 3, 0, 0, 26912, 98, }, /* 699 */ - { 106, 12, 3, 0, 0, 26916, 98, }, /* 700 */ - { 0, 9, 12, 92, 1, 18432, 76, }, /* 701 */ - { 0, 5, 12, 92, -1, 18432, 78, }, /* 702 */ - { 0, 5, 12, 0, 0, 18432, 70, }, /* 703 */ - { 0, 5, 12, 92, -58, 18432, 70, }, /* 704 */ - { 0, 9, 12, 0, -7615, 18432, 76, }, /* 705 */ - { 1, 5, 12, 0, 8, 18432, 78, }, /* 706 */ - { 1, 9, 12, 0, -8, 18432, 76, }, /* 707 */ - { 1, 5, 12, 0, 0, 18432, 78, }, /* 708 */ - { 1, 5, 12, 0, 74, 18432, 78, }, /* 709 */ - { 1, 5, 12, 0, 86, 18432, 78, }, /* 710 */ - { 1, 5, 12, 0, 100, 18432, 78, }, /* 711 */ - { 1, 5, 12, 0, 128, 18432, 78, }, /* 712 */ - { 1, 5, 12, 0, 112, 18432, 78, }, /* 713 */ - { 1, 5, 12, 0, 126, 18432, 78, }, /* 714 */ - { 1, 5, 12, 0, 8, 18432, 70, }, /* 715 */ - { 1, 8, 12, 0, -8, 18432, 88, }, /* 716 */ - { 1, 5, 12, 0, 0, 18432, 70, }, /* 717 */ - { 1, 5, 12, 0, 9, 18432, 70, }, /* 718 */ - { 1, 9, 12, 0, -74, 18432, 76, }, /* 719 */ - { 1, 8, 12, 0, -9, 18432, 88, }, /* 720 */ - { 1, 5, 12, 21, -7173, 18432, 78, }, /* 721 */ - { 1, 9, 12, 0, -86, 18432, 76, }, /* 722 */ - { 1, 5, 12, 0, -7235, 18432, 78, }, /* 723 */ - { 1, 9, 12, 0, -100, 18432, 76, }, /* 724 */ - { 1, 5, 12, 0, -7219, 18432, 78, }, /* 725 */ - { 1, 9, 12, 0, -112, 18432, 76, }, /* 726 */ - { 1, 9, 12, 0, -128, 18432, 76, }, /* 727 */ - { 1, 9, 12, 0, -126, 18432, 76, }, /* 728 */ - { 99, 29, 12, 0, 0, 45056, 52, }, /* 729 */ - { 106, 1, 3, 0, 0, 6144, 206, }, /* 730 */ - { 106, 1, 13, 0, 0, 6144, 208, }, /* 731 */ - { 99, 1, 2, 0, 0, 18432, 210, }, /* 732 */ - { 99, 1, 2, 0, 0, 34816, 210, }, /* 733 */ - { 99, 17, 12, 0, 0, 28672, 212, }, /* 734 */ - { 99, 21, 12, 0, 0, 28672, 64, }, /* 735 */ - { 99, 20, 12, 0, 0, 28672, 214, }, /* 736 */ - { 99, 19, 12, 0, 0, 28672, 214, }, /* 737 */ - { 99, 22, 12, 0, 0, 28672, 216, }, /* 738 */ - { 99, 20, 12, 0, 0, 28672, 216, }, /* 739 */ - { 99, 19, 12, 0, 0, 28672, 216, }, /* 740 */ - { 99, 21, 12, 0, 0, 28672, 218, }, /* 741 */ - { 99, 21, 12, 0, 0, 28672, 220, }, /* 742 */ - { 99, 27, 2, 0, 0, 45056, 50, }, /* 743 */ - { 99, 28, 2, 0, 0, 4096, 50, }, /* 744 */ - { 99, 1, 2, 0, 0, 20480, 136, }, /* 745 */ - { 99, 1, 2, 0, 0, 36864, 136, }, /* 746 */ - { 99, 1, 2, 0, 0, 30720, 136, }, /* 747 */ - { 99, 1, 2, 0, 0, 24576, 136, }, /* 748 */ - { 99, 1, 2, 0, 0, 40960, 136, }, /* 749 */ - { 99, 29, 12, 0, 0, 8488, 52, }, /* 750 */ - { 99, 21, 12, 0, 0, 14336, 54, }, /* 751 */ - { 99, 21, 12, 0, 0, 14336, 64, }, /* 752 */ - { 99, 21, 14, 0, 0, 28672, 222, }, /* 753 */ - { 99, 21, 12, 0, 0, 28672, 224, }, /* 754 */ - { 99, 16, 12, 0, 0, 28672, 144, }, /* 755 */ - { 99, 16, 12, 0, 0, 28672, 226, }, /* 756 */ - { 99, 25, 12, 0, 0, 8192, 64, }, /* 757 */ - { 99, 22, 12, 0, 0, 28672, 228, }, /* 758 */ - { 99, 18, 12, 0, 0, 28672, 228, }, /* 759 */ - { 99, 21, 12, 0, 0, 28972, 54, }, /* 760 */ - { 99, 21, 12, 0, 0, 28672, 212, }, /* 761 */ - { 99, 21, 12, 0, 0, 28976, 54, }, /* 762 */ - { 99, 21, 12, 0, 0, 28980, 54, }, /* 763 */ - { 99, 1, 2, 0, 0, 6144, 230, }, /* 764 */ - { 98, 2, 2, 0, 0, 6144, 232, }, /* 765 */ - { 99, 1, 2, 0, 0, 22528, 136, }, /* 766 */ - { 99, 1, 2, 0, 0, 38912, 136, }, /* 767 */ - { 99, 1, 2, 0, 0, 16384, 136, }, /* 768 */ - { 99, 1, 2, 0, 0, 32768, 136, }, /* 769 */ - { 99, 1, 2, 0, 0, 6144, 234, }, /* 770 */ - { 99, 25, 12, 0, 0, 12288, 236, }, /* 771 */ - { 99, 25, 12, 0, 0, 12288, 238, }, /* 772 */ - { 99, 25, 12, 0, 0, 28672, 236, }, /* 773 */ - { 99, 22, 12, 0, 0, 28672, 240, }, /* 774 */ - { 99, 18, 12, 0, 0, 28672, 240, }, /* 775 */ - { 98, 2, 12, 0, 0, 14336, 0, }, /* 776 */ - { 106, 12, 3, 0, 0, 26624, 242, }, /* 777 */ - { 106, 11, 3, 0, 0, 26624, 124, }, /* 778 */ - { 106, 11, 3, 0, 0, 26624, 244, }, /* 779 */ - { 106, 12, 3, 0, 0, 26936, 104, }, /* 780 */ - { 99, 26, 12, 0, 0, 28672, 74, }, /* 781 */ - { 99, 9, 12, 0, 0, 18432, 116, }, /* 782 */ - { 99, 5, 12, 0, 0, 18432, 246, }, /* 783 */ - { 99, 25, 12, 0, 0, 28672, 248, }, /* 784 */ - { 99, 26, 14, 0, 0, 28672, 250, }, /* 785 */ - { 1, 9, 12, 96, -7517, 18432, 76, }, /* 786 */ - { 99, 26, 12, 0, 0, 28672, 122, }, /* 787 */ - { 0, 9, 12, 100, 0, 18432, 76, }, /* 788 */ - { 0, 9, 12, 104, -8262, 18432, 76, }, /* 789 */ - { 99, 26, 12, 0, 0, 14336, 252, }, /* 790 */ - { 0, 9, 12, 0, 28, 18432, 76, }, /* 791 */ - { 99, 7, 12, 0, 0, 18432, 254, }, /* 792 */ - { 99, 5, 14, 0, 0, 18432, 256, }, /* 793 */ - { 99, 25, 12, 0, 0, 28672, 122, }, /* 794 */ - { 99, 5, 12, 0, 0, 18432, 258, }, /* 795 */ - { 0, 5, 12, 0, -28, 18432, 78, }, /* 796 */ - { 0, 14, 12, 0, 16, 18432, 76, }, /* 797 */ - { 0, 14, 12, 0, -16, 18432, 78, }, /* 798 */ - { 0, 14, 12, 0, 0, 18432, 84, }, /* 799 */ - { 99, 25, 14, 0, 0, 28672, 260, }, /* 800 */ - { 99, 26, 14, 0, 0, 28672, 260, }, /* 801 */ - { 99, 26, 12, 0, 0, 28672, 64, }, /* 802 */ - { 99, 25, 12, 0, 0, 28672, 262, }, /* 803 */ - { 99, 25, 12, 0, 0, 28672, 264, }, /* 804 */ - { 99, 25, 12, 0, 0, 12288, 266, }, /* 805 */ - { 99, 22, 12, 0, 0, 28672, 264, }, /* 806 */ - { 99, 18, 12, 0, 0, 28672, 264, }, /* 807 */ - { 99, 26, 14, 0, 0, 28672, 268, }, /* 808 */ - { 99, 22, 12, 0, 0, 28672, 270, }, /* 809 */ - { 99, 18, 12, 0, 0, 28672, 270, }, /* 810 */ - { 99, 26, 12, 0, 0, 18432, 54, }, /* 811 */ - { 99, 26, 14, 0, 0, 28672, 272, }, /* 812 */ - { 98, 2, 12, 0, 0, 18432, 274, }, /* 813 */ - { 99, 15, 12, 0, 0, 10240, 74, }, /* 814 */ - { 99, 26, 12, 0, 26, 18432, 276, }, /* 815 */ - { 99, 26, 14, 0, 26, 18432, 278, }, /* 816 */ - { 99, 26, 12, 0, -26, 18432, 280, }, /* 817 */ - { 99, 25, 14, 0, 0, 28672, 282, }, /* 818 */ - { 99, 26, 14, 0, 0, 28672, 284, }, /* 819 */ - { 99, 26, 14, 0, 0, 28672, 286, }, /* 820 */ - { 99, 25, 14, 0, 0, 28672, 284, }, /* 821 */ - { 99, 26, 14, 0, 0, 18432, 272, }, /* 822 */ - { 99, 26, 14, 0, 0, 28672, 288, }, /* 823 */ - { 109, 26, 12, 0, 0, 18432, 54, }, /* 824 */ - { 99, 26, 12, 0, 0, 28672, 228, }, /* 825 */ - { 44, 9, 12, 0, 48, 18432, 76, }, /* 826 */ - { 44, 5, 12, 0, -48, 18432, 78, }, /* 827 */ - { 0, 9, 12, 0, -10743, 18432, 76, }, /* 828 */ - { 0, 9, 12, 0, -3814, 18432, 76, }, /* 829 */ - { 0, 9, 12, 0, -10727, 18432, 76, }, /* 830 */ - { 0, 5, 12, 0, -10795, 18432, 78, }, /* 831 */ - { 0, 5, 12, 0, -10792, 18432, 78, }, /* 832 */ - { 0, 9, 12, 0, -10780, 18432, 76, }, /* 833 */ - { 0, 9, 12, 0, -10749, 18432, 76, }, /* 834 */ - { 0, 9, 12, 0, -10783, 18432, 76, }, /* 835 */ - { 0, 9, 12, 0, -10782, 18432, 76, }, /* 836 */ - { 0, 9, 12, 0, -10815, 18432, 76, }, /* 837 */ - { 43, 5, 12, 0, 0, 18432, 60, }, /* 838 */ - { 43, 26, 12, 0, 0, 28672, 74, }, /* 839 */ - { 43, 12, 3, 0, 0, 26624, 98, }, /* 840 */ - { 43, 21, 12, 0, 0, 28672, 128, }, /* 841 */ - { 43, 21, 12, 0, 0, 28672, 74, }, /* 842 */ - { 43, 15, 12, 0, 0, 28672, 74, }, /* 843 */ - { 21, 5, 12, 0, -7264, 18432, 78, }, /* 844 */ - { 45, 7, 12, 0, 0, 18432, 84, }, /* 845 */ - { 45, 6, 12, 0, 0, 18432, 148, }, /* 846 */ - { 45, 21, 12, 0, 0, 18432, 74, }, /* 847 */ - { 45, 12, 3, 0, 0, 26624, 290, }, /* 848 */ - { 2, 12, 3, 0, 0, 26624, 106, }, /* 849 */ - { 99, 20, 12, 0, 0, 28672, 228, }, /* 850 */ - { 99, 19, 12, 0, 0, 28672, 228, }, /* 851 */ - { 99, 17, 12, 0, 0, 28988, 212, }, /* 852 */ - { 99, 6, 12, 0, 0, 28672, 292, }, /* 853 */ - { 99, 21, 12, 0, 0, 28992, 54, }, /* 854 */ - { 99, 21, 12, 0, 0, 28996, 54, }, /* 855 */ - { 99, 21, 12, 0, 0, 29000, 224, }, /* 856 */ - { 99, 21, 12, 0, 0, 29004, 294, }, /* 857 */ - { 99, 21, 12, 0, 0, 28812, 54, }, /* 858 */ - { 99, 21, 12, 0, 0, 28672, 294, }, /* 859 */ - { 30, 26, 12, 0, 0, 28672, 296, }, /* 860 */ - { 99, 26, 12, 0, 0, 29008, 298, }, /* 861 */ - { 99, 26, 12, 0, 0, 29008, 300, }, /* 862 */ - { 99, 26, 12, 0, 0, 29008, 302, }, /* 863 */ - { 99, 21, 12, 0, 0, 29012, 294, }, /* 864 */ - { 99, 21, 12, 0, 0, 29016, 224, }, /* 865 */ - { 99, 21, 12, 0, 0, 29020, 54, }, /* 866 */ - { 30, 6, 12, 0, 0, 18432, 138, }, /* 867 */ - { 99, 7, 12, 0, 0, 18784, 304, }, /* 868 */ - { 30, 14, 12, 0, 0, 18432, 304, }, /* 869 */ - { 99, 22, 12, 0, 0, 29028, 228, }, /* 870 */ - { 99, 18, 12, 0, 0, 29028, 228, }, /* 871 */ - { 99, 22, 12, 0, 0, 29032, 228, }, /* 872 */ - { 99, 18, 12, 0, 0, 29032, 228, }, /* 873 */ - { 99, 22, 12, 0, 0, 29036, 62, }, /* 874 */ - { 99, 18, 12, 0, 0, 29036, 62, }, /* 875 */ - { 99, 22, 12, 0, 0, 29036, 228, }, /* 876 */ - { 99, 18, 12, 0, 0, 29036, 228, }, /* 877 */ - { 99, 26, 12, 0, 0, 29020, 54, }, /* 878 */ - { 99, 17, 12, 0, 0, 29020, 212, }, /* 879 */ - { 99, 22, 12, 0, 0, 29020, 216, }, /* 880 */ - { 99, 18, 12, 0, 0, 29020, 216, }, /* 881 */ - { 106, 12, 3, 0, 0, 26992, 98, }, /* 882 */ - { 22, 10, 3, 0, 0, 18432, 306, }, /* 883 */ - { 99, 17, 14, 0, 0, 29020, 308, }, /* 884 */ - { 99, 6, 12, 0, 0, 18804, 138, }, /* 885 */ - { 99, 26, 12, 0, 0, 29020, 74, }, /* 886 */ - { 30, 6, 12, 0, 0, 18432, 148, }, /* 887 */ - { 99, 7, 12, 0, 0, 18808, 84, }, /* 888 */ - { 99, 21, 14, 0, 0, 29048, 250, }, /* 889 */ - { 99, 26, 12, 0, 0, 29024, 74, }, /* 890 */ - { 27, 7, 12, 0, 0, 18432, 84, }, /* 891 */ - { 106, 12, 3, 0, 0, 26996, 98, }, /* 892 */ - { 99, 24, 12, 0, 0, 29044, 310, }, /* 893 */ - { 27, 6, 12, 0, 0, 18432, 138, }, /* 894 */ - { 99, 17, 12, 0, 0, 29044, 130, }, /* 895 */ - { 28, 7, 12, 0, 0, 18432, 84, }, /* 896 */ - { 99, 21, 12, 0, 0, 29036, 144, }, /* 897 */ - { 99, 6, 12, 0, 0, 18804, 96, }, /* 898 */ - { 28, 6, 12, 0, 0, 18432, 138, }, /* 899 */ - { 29, 7, 12, 0, 0, 18432, 84, }, /* 900 */ - { 22, 7, 12, 0, 0, 18432, 84, }, /* 901 */ - { 22, 7, 12, 0, 0, 18432, 184, }, /* 902 */ - { 99, 26, 12, 0, 0, 18784, 74, }, /* 903 */ - { 99, 15, 12, 0, 0, 18784, 74, }, /* 904 */ - { 22, 26, 12, 0, 0, 18432, 74, }, /* 905 */ - { 22, 26, 12, 0, 0, 28672, 74, }, /* 906 */ - { 99, 15, 12, 0, 0, 18432, 74, }, /* 907 */ - { 99, 26, 14, 0, 0, 18784, 250, }, /* 908 */ - { 28, 26, 12, 0, 0, 18432, 74, }, /* 909 */ - { 30, 7, 12, 0, 0, 18432, 312, }, /* 910 */ - { 31, 7, 12, 0, 0, 18432, 84, }, /* 911 */ - { 31, 6, 12, 0, 0, 18432, 138, }, /* 912 */ - { 31, 26, 12, 0, 0, 28672, 74, }, /* 913 */ - { 55, 7, 12, 0, 0, 18432, 84, }, /* 914 */ - { 55, 6, 12, 0, 0, 18432, 148, }, /* 915 */ - { 55, 21, 12, 0, 0, 18432, 110, }, /* 916 */ - { 55, 21, 12, 0, 0, 18432, 128, }, /* 917 */ - { 119, 7, 12, 0, 0, 18432, 84, }, /* 918 */ - { 119, 6, 12, 0, 0, 18432, 138, }, /* 919 */ - { 119, 21, 12, 0, 0, 28672, 110, }, /* 920 */ - { 119, 21, 12, 0, 0, 28672, 128, }, /* 921 */ - { 119, 13, 12, 0, 0, 18432, 144, }, /* 922 */ - { 2, 9, 12, 108, 1, 18432, 76, }, /* 923 */ - { 2, 5, 12, 108, -35267, 18432, 78, }, /* 924 */ - { 2, 7, 12, 0, 0, 18432, 84, }, /* 925 */ - { 2, 21, 12, 0, 0, 28672, 74, }, /* 926 */ - { 2, 12, 3, 0, 0, 26624, 98, }, /* 927 */ - { 2, 6, 12, 0, 0, 28672, 94, }, /* 928 */ - { 2, 6, 12, 0, 0, 18432, 90, }, /* 929 */ - { 126, 7, 12, 0, 0, 18432, 84, }, /* 930 */ - { 126, 14, 12, 0, 0, 18432, 84, }, /* 931 */ - { 126, 12, 3, 0, 0, 26624, 98, }, /* 932 */ - { 126, 21, 12, 0, 0, 18432, 74, }, /* 933 */ - { 126, 21, 12, 0, 0, 18432, 128, }, /* 934 */ - { 126, 21, 12, 0, 0, 18432, 110, }, /* 935 */ - { 99, 24, 12, 0, 0, 29052, 56, }, /* 936 */ - { 0, 9, 12, 0, -35332, 18432, 76, }, /* 937 */ - { 99, 24, 12, 0, 0, 18432, 56, }, /* 938 */ - { 0, 9, 12, 0, -42280, 18432, 76, }, /* 939 */ - { 0, 5, 12, 0, 48, 18432, 78, }, /* 940 */ - { 0, 9, 12, 0, -42308, 18432, 76, }, /* 941 */ - { 0, 9, 12, 0, -42319, 18432, 76, }, /* 942 */ - { 0, 9, 12, 0, -42315, 18432, 76, }, /* 943 */ - { 0, 9, 12, 0, -42305, 18432, 76, }, /* 944 */ - { 0, 9, 12, 0, -42258, 18432, 76, }, /* 945 */ - { 0, 9, 12, 0, -42282, 18432, 76, }, /* 946 */ - { 0, 9, 12, 0, -42261, 18432, 76, }, /* 947 */ - { 0, 9, 12, 0, 928, 18432, 76, }, /* 948 */ - { 0, 9, 12, 0, -48, 18432, 76, }, /* 949 */ - { 0, 9, 12, 0, -42307, 18432, 76, }, /* 950 */ - { 0, 9, 12, 0, -35384, 18432, 76, }, /* 951 */ - { 0, 9, 12, 0, -42343, 18432, 76, }, /* 952 */ - { 0, 9, 12, 0, -42561, 18432, 76, }, /* 953 */ - { 46, 7, 12, 0, 0, 18432, 84, }, /* 954 */ - { 46, 12, 3, 0, 0, 26624, 106, }, /* 955 */ - { 46, 12, 3, 0, 0, 26624, 158, }, /* 956 */ - { 46, 10, 5, 0, 0, 18432, 154, }, /* 957 */ - { 46, 26, 12, 0, 0, 28672, 74, }, /* 958 */ - { 99, 15, 12, 0, 0, 18816, 74, }, /* 959 */ - { 99, 15, 12, 0, 0, 18820, 74, }, /* 960 */ - { 99, 26, 12, 0, 0, 18824, 74, }, /* 961 */ - { 99, 23, 12, 0, 0, 14732, 74, }, /* 962 */ - { 99, 26, 12, 0, 0, 14728, 74, }, /* 963 */ - { 47, 7, 12, 0, 0, 18432, 84, }, /* 964 */ - { 47, 21, 12, 0, 0, 28672, 74, }, /* 965 */ - { 47, 21, 12, 0, 0, 28672, 128, }, /* 966 */ - { 120, 10, 5, 0, 0, 18432, 154, }, /* 967 */ - { 120, 7, 12, 0, 0, 18432, 84, }, /* 968 */ - { 120, 12, 3, 0, 0, 26624, 158, }, /* 969 */ - { 120, 12, 3, 0, 0, 26624, 106, }, /* 970 */ - { 120, 21, 12, 0, 0, 18432, 128, }, /* 971 */ - { 120, 13, 12, 0, 0, 18432, 144, }, /* 972 */ - { 8, 12, 3, 0, 0, 27024, 98, }, /* 973 */ - { 8, 7, 12, 0, 0, 18836, 84, }, /* 974 */ - { 49, 13, 12, 0, 0, 18432, 144, }, /* 975 */ - { 49, 7, 12, 0, 0, 18432, 84, }, /* 976 */ - { 49, 12, 3, 0, 0, 26624, 106, }, /* 977 */ - { 49, 12, 3, 0, 0, 26624, 98, }, /* 978 */ - { 99, 21, 12, 0, 0, 18840, 200, }, /* 979 */ - { 49, 21, 12, 0, 0, 18432, 128, }, /* 980 */ - { 121, 7, 12, 0, 0, 18432, 84, }, /* 981 */ - { 121, 12, 3, 0, 0, 26624, 106, }, /* 982 */ - { 121, 10, 5, 0, 0, 18432, 154, }, /* 983 */ - { 121, 10, 3, 0, 0, 18432, 188, }, /* 984 */ - { 121, 21, 12, 0, 0, 18432, 74, }, /* 985 */ - { 56, 12, 3, 0, 0, 26624, 106, }, /* 986 */ - { 56, 10, 5, 0, 0, 18432, 154, }, /* 987 */ - { 56, 7, 12, 0, 0, 18432, 84, }, /* 988 */ - { 56, 12, 3, 0, 0, 26624, 98, }, /* 989 */ - { 56, 10, 3, 0, 0, 18432, 188, }, /* 990 */ - { 56, 21, 12, 0, 0, 18432, 74, }, /* 991 */ - { 56, 21, 12, 0, 0, 18432, 110, }, /* 992 */ - { 56, 21, 12, 0, 0, 18432, 128, }, /* 993 */ - { 99, 6, 12, 0, 0, 18844, 138, }, /* 994 */ - { 56, 13, 12, 0, 0, 18432, 144, }, /* 995 */ - { 20, 6, 12, 0, 0, 18432, 138, }, /* 996 */ - { 122, 7, 12, 0, 0, 18432, 84, }, /* 997 */ - { 122, 12, 3, 0, 0, 26624, 106, }, /* 998 */ - { 122, 10, 5, 0, 0, 18432, 154, }, /* 999 */ - { 122, 13, 12, 0, 0, 18432, 144, }, /* 1000 */ - { 122, 21, 12, 0, 0, 18432, 74, }, /* 1001 */ - { 122, 21, 12, 0, 0, 18432, 128, }, /* 1002 */ - { 124, 7, 12, 0, 0, 18432, 84, }, /* 1003 */ - { 124, 12, 3, 0, 0, 26624, 106, }, /* 1004 */ - { 124, 7, 12, 0, 0, 18432, 170, }, /* 1005 */ - { 124, 12, 3, 0, 0, 26624, 98, }, /* 1006 */ - { 124, 7, 12, 0, 0, 18432, 314, }, /* 1007 */ - { 124, 6, 12, 0, 0, 18432, 138, }, /* 1008 */ - { 124, 21, 12, 0, 0, 18432, 74, }, /* 1009 */ - { 124, 21, 12, 0, 0, 18432, 110, }, /* 1010 */ - { 127, 7, 12, 0, 0, 18432, 84, }, /* 1011 */ - { 127, 10, 5, 0, 0, 18432, 154, }, /* 1012 */ - { 127, 12, 3, 0, 0, 26624, 106, }, /* 1013 */ - { 127, 21, 12, 0, 0, 18432, 128, }, /* 1014 */ - { 127, 6, 12, 0, 0, 18432, 138, }, /* 1015 */ - { 127, 12, 3, 0, 0, 26624, 158, }, /* 1016 */ - { 0, 5, 12, 0, -928, 18432, 78, }, /* 1017 */ - { 24, 5, 12, 0, -38864, 18432, 70, }, /* 1018 */ - { 127, 10, 5, 0, 0, 18432, 174, }, /* 1019 */ - { 127, 13, 12, 0, 0, 18432, 144, }, /* 1020 */ - { 22, 7, 9, 0, 0, 18432, 84, }, /* 1021 */ - { 22, 7, 10, 0, 0, 18432, 84, }, /* 1022 */ - { 98, 4, 12, 0, 0, 18432, 0, }, /* 1023 */ - { 98, 3, 12, 0, 0, 18432, 0, }, /* 1024 */ - { 30, 7, 12, 0, 0, 18432, 304, }, /* 1025 */ - { 0, 5, 12, 0, 1, 18432, 70, }, /* 1026 */ - { 0, 5, 12, 0, -1, 18432, 70, }, /* 1027 */ - { 4, 25, 12, 0, 0, 12288, 122, }, /* 1028 */ - { 5, 7, 12, 0, 0, 0, 316, }, /* 1029 */ - { 99, 18, 12, 0, 0, 29088, 54, }, /* 1030 */ - { 99, 22, 12, 0, 0, 29088, 54, }, /* 1031 */ - { 98, 2, 12, 0, 0, 6144, 318, }, /* 1032 */ - { 5, 7, 12, 0, 0, 420, 84, }, /* 1033 */ - { 5, 26, 12, 0, 0, 29092, 74, }, /* 1034 */ - { 106, 12, 3, 0, 0, 26624, 192, }, /* 1035 */ - { 106, 12, 3, 0, 0, 26624, 320, }, /* 1036 */ - { 99, 21, 12, 0, 0, 28672, 74, }, /* 1037 */ - { 99, 21, 12, 0, 0, 28672, 128, }, /* 1038 */ - { 99, 21, 12, 0, 0, 28672, 126, }, /* 1039 */ - { 99, 22, 12, 0, 0, 28672, 74, }, /* 1040 */ - { 99, 18, 12, 0, 0, 28672, 74, }, /* 1041 */ - { 99, 17, 12, 0, 0, 28672, 130, }, /* 1042 */ - { 99, 22, 12, 0, 0, 28672, 322, }, /* 1043 */ - { 99, 18, 12, 0, 0, 28672, 322, }, /* 1044 */ - { 99, 21, 12, 0, 0, 8192, 110, }, /* 1045 */ - { 99, 21, 12, 0, 0, 8192, 324, }, /* 1046 */ - { 99, 21, 12, 0, 0, 8192, 326, }, /* 1047 */ - { 99, 22, 12, 0, 0, 28672, 172, }, /* 1048 */ - { 99, 18, 12, 0, 0, 28672, 172, }, /* 1049 */ - { 99, 21, 12, 0, 0, 14336, 74, }, /* 1050 */ - { 99, 21, 12, 0, 0, 28672, 122, }, /* 1051 */ - { 99, 25, 12, 0, 0, 12288, 122, }, /* 1052 */ - { 99, 17, 12, 0, 0, 12288, 328, }, /* 1053 */ - { 99, 25, 12, 0, 0, 28672, 330, }, /* 1054 */ - { 99, 21, 12, 0, 0, 28672, 322, }, /* 1055 */ - { 99, 21, 12, 0, 0, 28672, 332, }, /* 1056 */ - { 99, 17, 12, 0, 0, 12288, 130, }, /* 1057 */ - { 99, 21, 12, 0, 0, 8192, 74, }, /* 1058 */ - { 99, 13, 12, 0, 0, 10240, 334, }, /* 1059 */ - { 0, 9, 12, 0, 32, 18432, 336, }, /* 1060 */ - { 99, 24, 12, 0, 0, 28672, 338, }, /* 1061 */ - { 0, 5, 12, 0, -32, 18432, 340, }, /* 1062 */ - { 99, 21, 12, 0, 0, 29036, 128, }, /* 1063 */ - { 99, 22, 12, 0, 0, 29036, 342, }, /* 1064 */ - { 99, 18, 12, 0, 0, 29036, 342, }, /* 1065 */ - { 99, 21, 12, 0, 0, 29036, 110, }, /* 1066 */ - { 99, 6, 3, 0, 0, 18804, 344, }, /* 1067 */ - { 99, 1, 2, 0, 0, 28672, 346, }, /* 1068 */ - { 39, 7, 12, 0, 0, 18432, 84, }, /* 1069 */ - { 99, 21, 12, 0, 0, 18856, 74, }, /* 1070 */ - { 99, 21, 12, 0, 0, 29096, 74, }, /* 1071 */ - { 99, 21, 12, 0, 0, 18860, 74, }, /* 1072 */ - { 99, 15, 12, 0, 0, 18864, 74, }, /* 1073 */ - { 99, 26, 12, 0, 0, 18860, 74, }, /* 1074 */ - { 1, 14, 12, 0, 0, 28672, 84, }, /* 1075 */ - { 1, 15, 12, 0, 0, 28672, 74, }, /* 1076 */ - { 1, 26, 12, 0, 0, 28672, 74, }, /* 1077 */ - { 1, 26, 12, 0, 0, 18432, 74, }, /* 1078 */ - { 50, 7, 12, 0, 0, 18432, 84, }, /* 1079 */ - { 51, 7, 12, 0, 0, 18432, 84, }, /* 1080 */ - { 106, 12, 3, 0, 0, 27060, 98, }, /* 1081 */ - { 99, 15, 12, 0, 0, 10676, 74, }, /* 1082 */ - { 104, 7, 12, 0, 0, 18432, 84, }, /* 1083 */ - { 104, 15, 12, 0, 0, 18432, 74, }, /* 1084 */ - { 32, 7, 12, 0, 0, 18432, 84, }, /* 1085 */ - { 32, 14, 12, 0, 0, 18432, 84, }, /* 1086 */ - { 73, 7, 12, 0, 0, 18432, 84, }, /* 1087 */ - { 73, 12, 3, 0, 0, 26624, 106, }, /* 1088 */ - { 107, 7, 12, 0, 0, 18432, 84, }, /* 1089 */ - { 107, 21, 12, 0, 0, 18432, 110, }, /* 1090 */ - { 111, 7, 12, 0, 0, 18432, 84, }, /* 1091 */ - { 111, 21, 12, 0, 0, 18432, 110, }, /* 1092 */ - { 111, 14, 12, 0, 0, 18432, 84, }, /* 1093 */ - { 105, 9, 12, 0, 40, 18432, 76, }, /* 1094 */ - { 105, 5, 12, 0, -40, 18432, 78, }, /* 1095 */ - { 40, 7, 12, 0, 0, 18432, 84, }, /* 1096 */ - { 108, 7, 12, 0, 0, 18432, 84, }, /* 1097 */ - { 108, 13, 12, 0, 0, 18432, 144, }, /* 1098 */ - { 80, 9, 12, 0, 40, 18432, 76, }, /* 1099 */ - { 80, 5, 12, 0, -40, 18432, 78, }, /* 1100 */ - { 66, 7, 12, 0, 0, 18432, 84, }, /* 1101 */ - { 64, 7, 12, 0, 0, 18432, 84, }, /* 1102 */ - { 64, 21, 12, 0, 0, 18432, 74, }, /* 1103 */ - { 167, 9, 12, 0, 39, 18432, 76, }, /* 1104 */ - { 167, 5, 12, 0, -39, 18432, 78, }, /* 1105 */ - { 96, 7, 12, 0, 0, 18432, 84, }, /* 1106 */ - { 69, 7, 12, 0, 0, 18432, 84, }, /* 1107 */ - { 0, 6, 12, 0, 0, 18432, 96, }, /* 1108 */ - { 41, 7, 12, 0, 0, 34816, 84, }, /* 1109 */ - { 128, 7, 12, 0, 0, 34816, 84, }, /* 1110 */ - { 128, 21, 12, 0, 0, 34816, 110, }, /* 1111 */ - { 128, 15, 12, 0, 0, 34816, 74, }, /* 1112 */ - { 143, 7, 12, 0, 0, 34816, 84, }, /* 1113 */ - { 143, 26, 12, 0, 0, 34816, 74, }, /* 1114 */ - { 143, 15, 12, 0, 0, 34816, 74, }, /* 1115 */ - { 142, 7, 12, 0, 0, 34816, 84, }, /* 1116 */ - { 142, 15, 12, 0, 0, 34816, 74, }, /* 1117 */ - { 149, 7, 12, 0, 0, 34816, 84, }, /* 1118 */ - { 149, 15, 12, 0, 0, 34816, 74, }, /* 1119 */ - { 115, 7, 12, 0, 0, 34816, 84, }, /* 1120 */ - { 115, 15, 12, 0, 0, 34816, 74, }, /* 1121 */ - { 115, 21, 12, 0, 0, 28672, 110, }, /* 1122 */ - { 52, 7, 12, 0, 0, 34816, 84, }, /* 1123 */ - { 52, 21, 12, 0, 0, 34816, 74, }, /* 1124 */ - { 61, 7, 12, 0, 0, 34816, 84, }, /* 1125 */ - { 134, 7, 12, 0, 0, 34816, 84, }, /* 1126 */ - { 134, 15, 12, 0, 0, 34816, 74, }, /* 1127 */ - { 112, 7, 12, 0, 0, 34816, 84, }, /* 1128 */ - { 112, 12, 3, 0, 0, 26624, 106, }, /* 1129 */ - { 112, 12, 3, 0, 0, 26624, 98, }, /* 1130 */ - { 112, 12, 3, 0, 0, 26624, 158, }, /* 1131 */ - { 112, 15, 12, 0, 0, 34816, 74, }, /* 1132 */ - { 112, 21, 12, 0, 0, 34816, 74, }, /* 1133 */ - { 112, 21, 12, 0, 0, 34816, 128, }, /* 1134 */ - { 129, 7, 12, 0, 0, 34816, 84, }, /* 1135 */ - { 129, 15, 12, 0, 0, 34816, 74, }, /* 1136 */ - { 129, 21, 12, 0, 0, 34816, 74, }, /* 1137 */ - { 141, 7, 12, 0, 0, 34816, 84, }, /* 1138 */ - { 141, 15, 12, 0, 0, 34816, 74, }, /* 1139 */ - { 71, 7, 12, 0, 0, 34816, 84, }, /* 1140 */ - { 71, 26, 12, 0, 0, 34816, 74, }, /* 1141 */ - { 71, 12, 3, 0, 0, 26624, 98, }, /* 1142 */ - { 71, 15, 12, 0, 0, 34816, 74, }, /* 1143 */ - { 71, 21, 12, 0, 0, 34816, 110, }, /* 1144 */ - { 71, 21, 12, 0, 0, 35256, 110, }, /* 1145 */ - { 71, 21, 12, 0, 0, 34816, 74, }, /* 1146 */ - { 53, 7, 12, 0, 0, 34816, 84, }, /* 1147 */ - { 53, 21, 12, 0, 0, 28672, 74, }, /* 1148 */ - { 53, 21, 12, 0, 0, 28672, 110, }, /* 1149 */ - { 130, 7, 12, 0, 0, 34816, 84, }, /* 1150 */ - { 130, 15, 12, 0, 0, 34816, 74, }, /* 1151 */ - { 131, 7, 12, 0, 0, 34816, 84, }, /* 1152 */ - { 131, 15, 12, 0, 0, 34816, 74, }, /* 1153 */ - { 74, 7, 12, 0, 0, 34816, 84, }, /* 1154 */ - { 74, 21, 12, 0, 0, 34816, 110, }, /* 1155 */ - { 74, 15, 12, 0, 0, 34816, 74, }, /* 1156 */ - { 57, 7, 12, 0, 0, 34816, 84, }, /* 1157 */ - { 78, 9, 12, 0, 64, 34816, 76, }, /* 1158 */ - { 78, 5, 12, 0, -64, 34816, 78, }, /* 1159 */ - { 78, 15, 12, 0, 0, 34816, 74, }, /* 1160 */ - { 85, 7, 12, 0, 0, 0, 84, }, /* 1161 */ - { 85, 7, 12, 0, 0, 0, 314, }, /* 1162 */ - { 85, 12, 3, 0, 0, 26624, 132, }, /* 1163 */ - { 85, 13, 12, 0, 0, 2048, 144, }, /* 1164 */ - { 92, 13, 12, 0, 0, 2048, 144, }, /* 1165 */ - { 92, 7, 12, 0, 0, 34816, 84, }, /* 1166 */ - { 92, 6, 12, 0, 0, 34816, 96, }, /* 1167 */ - { 92, 9, 12, 0, 32, 34816, 76, }, /* 1168 */ - { 92, 12, 3, 0, 0, 26624, 132, }, /* 1169 */ - { 92, 12, 3, 0, 0, 26624, 164, }, /* 1170 */ - { 92, 12, 3, 0, 0, 26624, 98, }, /* 1171 */ - { 92, 17, 12, 0, 0, 28672, 130, }, /* 1172 */ - { 92, 6, 12, 0, 0, 34816, 138, }, /* 1173 */ - { 92, 5, 12, 0, -32, 34816, 78, }, /* 1174 */ - { 92, 25, 12, 0, 0, 34816, 122, }, /* 1175 */ - { 5, 15, 12, 0, 0, 2048, 74, }, /* 1176 */ - { 88, 7, 12, 0, 0, 34816, 84, }, /* 1177 */ - { 88, 12, 3, 0, 0, 26624, 106, }, /* 1178 */ - { 88, 17, 12, 0, 0, 34816, 130, }, /* 1179 */ - { 159, 7, 12, 0, 0, 34816, 84, }, /* 1180 */ - { 159, 15, 12, 0, 0, 34816, 74, }, /* 1181 */ - { 86, 7, 12, 0, 0, 0, 84, }, /* 1182 */ - { 86, 12, 3, 0, 0, 26624, 98, }, /* 1183 */ - { 86, 15, 12, 0, 0, 0, 74, }, /* 1184 */ - { 86, 21, 12, 0, 0, 0, 128, }, /* 1185 */ - { 90, 7, 12, 0, 0, 34816, 84, }, /* 1186 */ - { 90, 12, 3, 0, 0, 26624, 98, }, /* 1187 */ - { 90, 21, 12, 0, 0, 34816, 128, }, /* 1188 */ - { 163, 7, 12, 0, 0, 34816, 84, }, /* 1189 */ - { 163, 15, 12, 0, 0, 34816, 74, }, /* 1190 */ - { 160, 7, 12, 0, 0, 34816, 84, }, /* 1191 */ - { 133, 10, 5, 0, 0, 18432, 154, }, /* 1192 */ - { 133, 12, 3, 0, 0, 26624, 106, }, /* 1193 */ - { 133, 7, 12, 0, 0, 18432, 84, }, /* 1194 */ - { 133, 12, 3, 0, 0, 26624, 158, }, /* 1195 */ - { 133, 21, 12, 0, 0, 18432, 128, }, /* 1196 */ - { 133, 21, 12, 0, 0, 18432, 110, }, /* 1197 */ - { 133, 15, 12, 0, 0, 28672, 74, }, /* 1198 */ - { 133, 13, 12, 0, 0, 18432, 144, }, /* 1199 */ - { 133, 12, 3, 0, 0, 26624, 290, }, /* 1200 */ - { 58, 12, 3, 0, 0, 26624, 106, }, /* 1201 */ - { 58, 10, 5, 0, 0, 18432, 154, }, /* 1202 */ - { 58, 7, 12, 0, 0, 18432, 84, }, /* 1203 */ - { 58, 12, 3, 0, 0, 26624, 158, }, /* 1204 */ - { 58, 12, 3, 0, 0, 26624, 98, }, /* 1205 */ - { 58, 21, 12, 0, 0, 18432, 74, }, /* 1206 */ - { 58, 1, 4, 0, 0, 18432, 134, }, /* 1207 */ - { 58, 21, 12, 0, 0, 18432, 128, }, /* 1208 */ - { 136, 7, 12, 0, 0, 18432, 84, }, /* 1209 */ - { 136, 13, 12, 0, 0, 18432, 144, }, /* 1210 */ - { 60, 12, 3, 0, 0, 26624, 106, }, /* 1211 */ - { 60, 7, 12, 0, 0, 18432, 84, }, /* 1212 */ - { 60, 10, 5, 0, 0, 18432, 154, }, /* 1213 */ - { 60, 12, 3, 0, 0, 26624, 158, }, /* 1214 */ - { 60, 13, 12, 0, 0, 18432, 144, }, /* 1215 */ - { 60, 21, 12, 0, 0, 18432, 74, }, /* 1216 */ - { 60, 21, 12, 0, 0, 18432, 128, }, /* 1217 */ - { 70, 7, 12, 0, 0, 18432, 84, }, /* 1218 */ - { 70, 12, 3, 0, 0, 26624, 98, }, /* 1219 */ - { 70, 21, 12, 0, 0, 18432, 74, }, /* 1220 */ - { 62, 12, 3, 0, 0, 26624, 106, }, /* 1221 */ - { 62, 10, 5, 0, 0, 18432, 154, }, /* 1222 */ - { 62, 7, 12, 0, 0, 18432, 84, }, /* 1223 */ - { 62, 10, 3, 0, 0, 18432, 188, }, /* 1224 */ - { 62, 7, 4, 0, 0, 18432, 84, }, /* 1225 */ - { 62, 21, 12, 0, 0, 18432, 128, }, /* 1226 */ - { 62, 21, 12, 0, 0, 18432, 74, }, /* 1227 */ - { 62, 12, 3, 0, 0, 26624, 104, }, /* 1228 */ - { 62, 12, 3, 0, 0, 26624, 98, }, /* 1229 */ - { 62, 13, 12, 0, 0, 18432, 144, }, /* 1230 */ - { 17, 15, 12, 0, 0, 18432, 74, }, /* 1231 */ - { 68, 7, 12, 0, 0, 18432, 84, }, /* 1232 */ - { 68, 10, 5, 0, 0, 18432, 154, }, /* 1233 */ - { 68, 12, 3, 0, 0, 26624, 106, }, /* 1234 */ - { 68, 10, 3, 0, 0, 18432, 188, }, /* 1235 */ - { 68, 12, 3, 0, 0, 26624, 98, }, /* 1236 */ - { 68, 12, 3, 0, 0, 26624, 162, }, /* 1237 */ - { 68, 21, 12, 0, 0, 18432, 128, }, /* 1238 */ - { 68, 21, 12, 0, 0, 18432, 110, }, /* 1239 */ - { 68, 21, 12, 0, 0, 18432, 74, }, /* 1240 */ - { 77, 7, 12, 0, 0, 18432, 84, }, /* 1241 */ - { 77, 21, 12, 0, 0, 18432, 128, }, /* 1242 */ - { 75, 7, 12, 0, 0, 18432, 84, }, /* 1243 */ - { 75, 12, 3, 0, 0, 26624, 106, }, /* 1244 */ - { 75, 10, 5, 0, 0, 18432, 154, }, /* 1245 */ - { 75, 12, 3, 0, 0, 26624, 98, }, /* 1246 */ - { 75, 12, 3, 0, 0, 26624, 158, }, /* 1247 */ - { 75, 13, 12, 0, 0, 18432, 144, }, /* 1248 */ - { 67, 12, 3, 0, 0, 26624, 106, }, /* 1249 */ - { 67, 12, 3, 0, 0, 26836, 106, }, /* 1250 */ - { 67, 10, 5, 0, 0, 18432, 154, }, /* 1251 */ - { 67, 10, 5, 0, 0, 18644, 154, }, /* 1252 */ - { 67, 7, 12, 0, 0, 18432, 84, }, /* 1253 */ - { 106, 12, 3, 0, 0, 26836, 98, }, /* 1254 */ - { 67, 12, 3, 0, 0, 26836, 98, }, /* 1255 */ - { 67, 10, 3, 0, 0, 18432, 160, }, /* 1256 */ - { 67, 10, 3, 0, 0, 18432, 188, }, /* 1257 */ - { 67, 7, 12, 0, 0, 18432, 348, }, /* 1258 */ - { 67, 12, 3, 0, 0, 26624, 98, }, /* 1259 */ - { 97, 7, 12, 0, 0, 18432, 84, }, /* 1260 */ - { 97, 10, 3, 0, 0, 18432, 160, }, /* 1261 */ - { 97, 10, 5, 0, 0, 18432, 154, }, /* 1262 */ - { 97, 12, 3, 0, 0, 26624, 106, }, /* 1263 */ - { 97, 12, 3, 0, 0, 26624, 158, }, /* 1264 */ - { 97, 10, 3, 0, 0, 18432, 188, }, /* 1265 */ - { 97, 7, 4, 0, 0, 18432, 84, }, /* 1266 */ - { 97, 12, 3, 0, 0, 26624, 164, }, /* 1267 */ - { 97, 7, 12, 0, 0, 18432, 350, }, /* 1268 */ - { 97, 21, 12, 0, 0, 18432, 128, }, /* 1269 */ - { 97, 21, 12, 0, 0, 18432, 74, }, /* 1270 */ - { 97, 12, 3, 0, 0, 26624, 98, }, /* 1271 */ - { 153, 7, 12, 0, 0, 18432, 84, }, /* 1272 */ - { 153, 10, 5, 0, 0, 18432, 154, }, /* 1273 */ - { 153, 12, 3, 0, 0, 26624, 106, }, /* 1274 */ - { 153, 12, 3, 0, 0, 26624, 158, }, /* 1275 */ - { 153, 12, 3, 0, 0, 26624, 98, }, /* 1276 */ - { 153, 21, 12, 0, 0, 18432, 128, }, /* 1277 */ - { 153, 21, 12, 0, 0, 18432, 110, }, /* 1278 */ - { 153, 21, 12, 0, 0, 18432, 74, }, /* 1279 */ - { 153, 13, 12, 0, 0, 18432, 144, }, /* 1280 */ - { 153, 12, 3, 0, 0, 26624, 104, }, /* 1281 */ - { 76, 7, 12, 0, 0, 18432, 84, }, /* 1282 */ - { 76, 10, 3, 0, 0, 18432, 160, }, /* 1283 */ - { 76, 10, 5, 0, 0, 18432, 154, }, /* 1284 */ - { 76, 12, 3, 0, 0, 26624, 106, }, /* 1285 */ - { 76, 12, 3, 0, 0, 26624, 158, }, /* 1286 */ - { 76, 12, 3, 0, 0, 26624, 98, }, /* 1287 */ - { 76, 21, 12, 0, 0, 18432, 74, }, /* 1288 */ - { 76, 13, 12, 0, 0, 18432, 144, }, /* 1289 */ - { 145, 7, 12, 0, 0, 18432, 84, }, /* 1290 */ - { 145, 10, 3, 0, 0, 18432, 160, }, /* 1291 */ - { 145, 10, 5, 0, 0, 18432, 154, }, /* 1292 */ - { 145, 12, 3, 0, 0, 26624, 106, }, /* 1293 */ - { 145, 12, 3, 0, 0, 26624, 158, }, /* 1294 */ - { 145, 12, 3, 0, 0, 26624, 98, }, /* 1295 */ - { 145, 21, 12, 0, 0, 18432, 74, }, /* 1296 */ - { 145, 21, 12, 0, 0, 18432, 128, }, /* 1297 */ - { 145, 21, 12, 0, 0, 18432, 110, }, /* 1298 */ - { 145, 21, 12, 0, 0, 18432, 190, }, /* 1299 */ - { 72, 7, 12, 0, 0, 18432, 84, }, /* 1300 */ - { 72, 10, 5, 0, 0, 18432, 154, }, /* 1301 */ - { 72, 12, 3, 0, 0, 26624, 106, }, /* 1302 */ - { 72, 12, 3, 0, 0, 26624, 158, }, /* 1303 */ - { 72, 21, 12, 0, 0, 18432, 128, }, /* 1304 */ - { 72, 21, 12, 0, 0, 18432, 74, }, /* 1305 */ - { 72, 13, 12, 0, 0, 18432, 144, }, /* 1306 */ - { 63, 7, 12, 0, 0, 18432, 84, }, /* 1307 */ - { 63, 12, 3, 0, 0, 26624, 106, }, /* 1308 */ - { 63, 10, 5, 0, 0, 18432, 154, }, /* 1309 */ - { 63, 10, 3, 0, 0, 18432, 188, }, /* 1310 */ - { 63, 12, 3, 0, 0, 26624, 98, }, /* 1311 */ - { 63, 21, 12, 0, 0, 18432, 74, }, /* 1312 */ - { 63, 13, 12, 0, 0, 18432, 144, }, /* 1313 */ - { 147, 7, 12, 0, 0, 18432, 84, }, /* 1314 */ - { 147, 12, 3, 0, 0, 26624, 106, }, /* 1315 */ - { 147, 10, 5, 0, 0, 18432, 154, }, /* 1316 */ - { 147, 10, 12, 0, 0, 18432, 154, }, /* 1317 */ - { 147, 12, 3, 0, 0, 26624, 158, }, /* 1318 */ - { 147, 13, 12, 0, 0, 18432, 144, }, /* 1319 */ - { 147, 15, 12, 0, 0, 18432, 74, }, /* 1320 */ - { 147, 21, 12, 0, 0, 18432, 128, }, /* 1321 */ - { 147, 26, 12, 0, 0, 18432, 74, }, /* 1322 */ - { 83, 7, 12, 0, 0, 18432, 84, }, /* 1323 */ - { 83, 10, 5, 0, 0, 18432, 154, }, /* 1324 */ - { 83, 12, 3, 0, 0, 26624, 106, }, /* 1325 */ - { 83, 12, 3, 0, 0, 26624, 158, }, /* 1326 */ - { 83, 12, 3, 0, 0, 26624, 98, }, /* 1327 */ - { 83, 21, 12, 0, 0, 18432, 74, }, /* 1328 */ - { 146, 9, 12, 0, 32, 18432, 76, }, /* 1329 */ - { 146, 5, 12, 0, -32, 18432, 78, }, /* 1330 */ - { 146, 13, 12, 0, 0, 18432, 144, }, /* 1331 */ - { 146, 15, 12, 0, 0, 18432, 74, }, /* 1332 */ - { 146, 7, 12, 0, 0, 18432, 84, }, /* 1333 */ - { 164, 7, 12, 0, 0, 18432, 84, }, /* 1334 */ - { 164, 10, 3, 0, 0, 18432, 160, }, /* 1335 */ - { 164, 10, 5, 0, 0, 18432, 154, }, /* 1336 */ - { 164, 12, 3, 0, 0, 26624, 106, }, /* 1337 */ - { 164, 10, 3, 0, 0, 18432, 188, }, /* 1338 */ - { 164, 12, 3, 0, 0, 26624, 158, }, /* 1339 */ - { 164, 7, 4, 0, 0, 18432, 84, }, /* 1340 */ - { 164, 12, 3, 0, 0, 26624, 98, }, /* 1341 */ - { 164, 21, 12, 0, 0, 18432, 128, }, /* 1342 */ - { 164, 21, 12, 0, 0, 18432, 74, }, /* 1343 */ - { 164, 13, 12, 0, 0, 18432, 144, }, /* 1344 */ - { 87, 7, 12, 0, 0, 18432, 84, }, /* 1345 */ - { 87, 10, 5, 0, 0, 18432, 154, }, /* 1346 */ - { 87, 12, 3, 0, 0, 26624, 106, }, /* 1347 */ - { 87, 12, 3, 0, 0, 26624, 158, }, /* 1348 */ - { 87, 21, 12, 0, 0, 18432, 74, }, /* 1349 */ - { 156, 7, 12, 0, 0, 18432, 84, }, /* 1350 */ - { 156, 12, 3, 0, 0, 26624, 106, }, /* 1351 */ - { 156, 12, 3, 0, 0, 18432, 106, }, /* 1352 */ - { 156, 12, 3, 0, 0, 26624, 104, }, /* 1353 */ - { 156, 12, 3, 0, 0, 26624, 158, }, /* 1354 */ - { 156, 10, 5, 0, 0, 18432, 154, }, /* 1355 */ - { 156, 7, 4, 0, 0, 18432, 84, }, /* 1356 */ - { 156, 21, 12, 0, 0, 18432, 74, }, /* 1357 */ - { 156, 21, 12, 0, 0, 18432, 128, }, /* 1358 */ - { 155, 7, 12, 0, 0, 18432, 84, }, /* 1359 */ - { 155, 12, 3, 0, 0, 26624, 106, }, /* 1360 */ - { 155, 10, 5, 0, 0, 18432, 154, }, /* 1361 */ - { 155, 7, 4, 0, 0, 18432, 84, }, /* 1362 */ - { 155, 12, 3, 0, 0, 26624, 352, }, /* 1363 */ - { 155, 12, 3, 0, 0, 26624, 158, }, /* 1364 */ - { 155, 21, 12, 0, 0, 18432, 74, }, /* 1365 */ - { 155, 21, 12, 0, 0, 18432, 128, }, /* 1366 */ - { 155, 21, 12, 0, 0, 18432, 110, }, /* 1367 */ - { 144, 7, 12, 0, 0, 18432, 84, }, /* 1368 */ - { 95, 7, 12, 0, 0, 18432, 84, }, /* 1369 */ - { 95, 21, 12, 0, 0, 18432, 74, }, /* 1370 */ - { 95, 13, 12, 0, 0, 18432, 144, }, /* 1371 */ - { 151, 7, 12, 0, 0, 18432, 84, }, /* 1372 */ - { 151, 10, 5, 0, 0, 18432, 154, }, /* 1373 */ - { 151, 12, 3, 0, 0, 26624, 106, }, /* 1374 */ - { 151, 12, 3, 0, 0, 18432, 158, }, /* 1375 */ - { 151, 21, 12, 0, 0, 18432, 128, }, /* 1376 */ - { 151, 21, 12, 0, 0, 18432, 110, }, /* 1377 */ - { 151, 21, 12, 0, 0, 18432, 74, }, /* 1378 */ - { 151, 13, 12, 0, 0, 18432, 144, }, /* 1379 */ - { 151, 15, 12, 0, 0, 18432, 74, }, /* 1380 */ - { 152, 21, 12, 0, 0, 18432, 74, }, /* 1381 */ - { 152, 21, 12, 0, 0, 18432, 110, }, /* 1382 */ - { 152, 7, 12, 0, 0, 18432, 84, }, /* 1383 */ - { 152, 12, 3, 0, 0, 26624, 106, }, /* 1384 */ - { 152, 10, 5, 0, 0, 18432, 154, }, /* 1385 */ - { 82, 7, 12, 0, 0, 18432, 84, }, /* 1386 */ - { 82, 12, 3, 0, 0, 26624, 106, }, /* 1387 */ - { 82, 12, 3, 0, 0, 26624, 98, }, /* 1388 */ - { 82, 12, 3, 0, 0, 26624, 158, }, /* 1389 */ - { 82, 7, 4, 0, 0, 18432, 84, }, /* 1390 */ - { 82, 13, 12, 0, 0, 18432, 144, }, /* 1391 */ - { 84, 7, 12, 0, 0, 18432, 84, }, /* 1392 */ - { 84, 10, 5, 0, 0, 18432, 154, }, /* 1393 */ - { 84, 12, 3, 0, 0, 26624, 106, }, /* 1394 */ - { 84, 12, 3, 0, 0, 26624, 158, }, /* 1395 */ - { 84, 13, 12, 0, 0, 18432, 144, }, /* 1396 */ - { 157, 7, 12, 0, 0, 18432, 84, }, /* 1397 */ - { 157, 12, 3, 0, 0, 26624, 106, }, /* 1398 */ - { 157, 10, 5, 0, 0, 18432, 154, }, /* 1399 */ - { 157, 21, 12, 0, 0, 18432, 128, }, /* 1400 */ - { 168, 12, 3, 0, 0, 26624, 106, }, /* 1401 */ - { 168, 7, 4, 0, 0, 18432, 84, }, /* 1402 */ - { 168, 10, 5, 0, 0, 18432, 154, }, /* 1403 */ - { 168, 7, 12, 0, 0, 18432, 84, }, /* 1404 */ - { 168, 10, 3, 0, 0, 18432, 188, }, /* 1405 */ - { 168, 12, 3, 0, 0, 26624, 158, }, /* 1406 */ - { 168, 21, 12, 0, 0, 18432, 128, }, /* 1407 */ - { 168, 21, 12, 0, 0, 18432, 74, }, /* 1408 */ - { 168, 13, 12, 0, 0, 18432, 144, }, /* 1409 */ - { 168, 12, 3, 0, 0, 26624, 98, }, /* 1410 */ - { 13, 15, 12, 0, 0, 18432, 74, }, /* 1411 */ - { 13, 21, 12, 0, 0, 18432, 74, }, /* 1412 */ - { 114, 7, 12, 0, 0, 18432, 84, }, /* 1413 */ - { 114, 14, 12, 0, 0, 18432, 84, }, /* 1414 */ - { 114, 21, 12, 0, 0, 18432, 110, }, /* 1415 */ - { 89, 7, 12, 0, 0, 18432, 84, }, /* 1416 */ - { 89, 21, 12, 0, 0, 18432, 74, }, /* 1417 */ - { 125, 7, 12, 0, 0, 18432, 84, }, /* 1418 */ - { 125, 1, 2, 0, 0, 18432, 346, }, /* 1419 */ - { 125, 12, 3, 0, 0, 26624, 104, }, /* 1420 */ - { 125, 12, 3, 0, 0, 26624, 98, }, /* 1421 */ - { 148, 7, 12, 0, 0, 18432, 84, }, /* 1422 */ - { 93, 7, 12, 0, 0, 18432, 84, }, /* 1423 */ - { 93, 12, 3, 0, 0, 26624, 106, }, /* 1424 */ - { 93, 10, 5, 0, 0, 18432, 154, }, /* 1425 */ - { 93, 12, 3, 0, 0, 26624, 158, }, /* 1426 */ - { 93, 13, 12, 0, 0, 18432, 144, }, /* 1427 */ - { 140, 7, 12, 0, 0, 18432, 84, }, /* 1428 */ - { 140, 13, 12, 0, 0, 18432, 144, }, /* 1429 */ - { 140, 21, 12, 0, 0, 18432, 128, }, /* 1430 */ - { 166, 7, 12, 0, 0, 18432, 84, }, /* 1431 */ - { 166, 13, 12, 0, 0, 18432, 144, }, /* 1432 */ - { 137, 7, 12, 0, 0, 18432, 84, }, /* 1433 */ - { 137, 12, 3, 0, 0, 26624, 98, }, /* 1434 */ - { 137, 21, 12, 0, 0, 18432, 128, }, /* 1435 */ - { 138, 7, 12, 0, 0, 18432, 84, }, /* 1436 */ - { 138, 12, 3, 0, 0, 26624, 98, }, /* 1437 */ - { 138, 21, 12, 0, 0, 18432, 128, }, /* 1438 */ - { 138, 21, 12, 0, 0, 18432, 110, }, /* 1439 */ - { 138, 21, 12, 0, 0, 18432, 74, }, /* 1440 */ - { 138, 26, 12, 0, 0, 18432, 74, }, /* 1441 */ - { 138, 6, 12, 0, 0, 18432, 148, }, /* 1442 */ - { 138, 6, 12, 0, 0, 18432, 138, }, /* 1443 */ - { 138, 13, 12, 0, 0, 18432, 144, }, /* 1444 */ - { 138, 15, 12, 0, 0, 18432, 74, }, /* 1445 */ - { 170, 6, 12, 0, 0, 18432, 148, }, /* 1446 */ - { 170, 7, 12, 0, 0, 18432, 84, }, /* 1447 */ - { 170, 7, 7, 0, 0, 18432, 84, }, /* 1448 */ - { 170, 6, 12, 0, 0, 18432, 94, }, /* 1449 */ - { 170, 21, 12, 0, 0, 18432, 74, }, /* 1450 */ - { 170, 21, 12, 0, 0, 18432, 128, }, /* 1451 */ - { 170, 13, 12, 0, 0, 18432, 144, }, /* 1452 */ - { 158, 9, 12, 0, 32, 18432, 76, }, /* 1453 */ - { 158, 5, 12, 0, -32, 18432, 78, }, /* 1454 */ - { 158, 15, 12, 0, 0, 18432, 74, }, /* 1455 */ - { 158, 21, 12, 0, 0, 18432, 110, }, /* 1456 */ - { 158, 21, 12, 0, 0, 18432, 128, }, /* 1457 */ - { 158, 21, 12, 0, 0, 18432, 74, }, /* 1458 */ - { 135, 7, 12, 0, 0, 18432, 84, }, /* 1459 */ - { 135, 12, 3, 0, 0, 26624, 106, }, /* 1460 */ - { 135, 10, 5, 0, 0, 18432, 154, }, /* 1461 */ - { 135, 12, 3, 0, 0, 26624, 132, }, /* 1462 */ - { 135, 6, 12, 0, 0, 18432, 94, }, /* 1463 */ - { 81, 6, 12, 0, 0, 18432, 138, }, /* 1464 */ - { 154, 6, 12, 0, 0, 18432, 138, }, /* 1465 */ - { 30, 21, 12, 0, 0, 28672, 74, }, /* 1466 */ - { 165, 12, 3, 0, 0, 26624, 354, }, /* 1467 */ - { 30, 10, 3, 0, 0, 18432, 356, }, /* 1468 */ - { 81, 7, 12, 0, 0, 18432, 304, }, /* 1469 */ - { 165, 7, 12, 0, 0, 18432, 304, }, /* 1470 */ - { 28, 6, 12, 0, 0, 18432, 94, }, /* 1471 */ - { 154, 7, 12, 0, 0, 18432, 304, }, /* 1472 */ - { 65, 7, 12, 0, 0, 18432, 84, }, /* 1473 */ - { 65, 26, 12, 0, 0, 18432, 74, }, /* 1474 */ - { 65, 12, 3, 0, 0, 26624, 104, }, /* 1475 */ - { 65, 12, 3, 0, 0, 26624, 106, }, /* 1476 */ - { 65, 21, 12, 0, 0, 18432, 128, }, /* 1477 */ - { 99, 1, 2, 0, 0, 6472, 66, }, /* 1478 */ - { 99, 13, 12, 0, 0, 10240, 144, }, /* 1479 */ - { 99, 10, 3, 0, 0, 18432, 358, }, /* 1480 */ - { 99, 10, 3, 0, 0, 18432, 306, }, /* 1481 */ - { 1, 12, 3, 0, 0, 26624, 104, }, /* 1482 */ - { 99, 25, 12, 0, 0, 28672, 360, }, /* 1483 */ - { 99, 13, 12, 0, 0, 10240, 226, }, /* 1484 */ - { 150, 26, 12, 0, 0, 18432, 74, }, /* 1485 */ - { 150, 12, 3, 0, 0, 26624, 104, }, /* 1486 */ - { 150, 21, 12, 0, 0, 18432, 110, }, /* 1487 */ - { 150, 21, 12, 0, 0, 18432, 128, }, /* 1488 */ - { 150, 21, 12, 0, 0, 18432, 74, }, /* 1489 */ - { 44, 12, 3, 0, 0, 26624, 106, }, /* 1490 */ - { 2, 6, 12, 0, 0, 18432, 92, }, /* 1491 */ - { 161, 7, 12, 0, 0, 18432, 84, }, /* 1492 */ - { 161, 12, 3, 0, 0, 26624, 98, }, /* 1493 */ - { 161, 6, 12, 0, 0, 18432, 148, }, /* 1494 */ - { 161, 6, 12, 0, 0, 18432, 138, }, /* 1495 */ - { 161, 13, 12, 0, 0, 18432, 144, }, /* 1496 */ - { 161, 26, 12, 0, 0, 18432, 74, }, /* 1497 */ - { 91, 7, 12, 0, 0, 18432, 84, }, /* 1498 */ - { 91, 12, 3, 0, 0, 26624, 98, }, /* 1499 */ - { 162, 7, 12, 0, 0, 18432, 84, }, /* 1500 */ - { 162, 12, 3, 0, 0, 26624, 98, }, /* 1501 */ - { 162, 13, 12, 0, 0, 18432, 144, }, /* 1502 */ - { 162, 23, 12, 0, 0, 14336, 74, }, /* 1503 */ - { 169, 7, 12, 0, 0, 18432, 84, }, /* 1504 */ - { 169, 6, 12, 0, 0, 18432, 148, }, /* 1505 */ - { 169, 12, 3, 0, 0, 26624, 104, }, /* 1506 */ - { 169, 13, 12, 0, 0, 18432, 144, }, /* 1507 */ - { 94, 7, 12, 0, 0, 18432, 84, }, /* 1508 */ - { 94, 12, 3, 0, 0, 26624, 98, }, /* 1509 */ - { 94, 12, 3, 0, 0, 26624, 164, }, /* 1510 */ - { 94, 13, 12, 0, 0, 18432, 144, }, /* 1511 */ - { 94, 21, 12, 0, 0, 18432, 74, }, /* 1512 */ - { 139, 7, 12, 0, 0, 34816, 84, }, /* 1513 */ - { 139, 15, 12, 0, 0, 34816, 74, }, /* 1514 */ - { 139, 12, 3, 0, 0, 26624, 98, }, /* 1515 */ - { 79, 9, 12, 0, 34, 34816, 76, }, /* 1516 */ - { 79, 5, 12, 0, -34, 34816, 78, }, /* 1517 */ - { 79, 12, 3, 0, 0, 26624, 164, }, /* 1518 */ - { 79, 12, 3, 0, 0, 26624, 106, }, /* 1519 */ - { 79, 12, 3, 0, 0, 26624, 98, }, /* 1520 */ - { 79, 6, 12, 0, 0, 34816, 148, }, /* 1521 */ - { 79, 13, 12, 0, 0, 34816, 144, }, /* 1522 */ - { 79, 21, 12, 0, 0, 34816, 74, }, /* 1523 */ - { 99, 15, 12, 0, 0, 0, 74, }, /* 1524 */ - { 99, 26, 12, 0, 0, 0, 74, }, /* 1525 */ - { 99, 23, 12, 0, 0, 0, 74, }, /* 1526 */ - { 5, 7, 12, 0, 0, 0, 254, }, /* 1527 */ - { 99, 26, 14, 0, 0, 28672, 362, }, /* 1528 */ - { 99, 26, 14, 0, 0, 28672, 364, }, /* 1529 */ - { 98, 2, 14, 0, 0, 18432, 366, }, /* 1530 */ - { 99, 26, 12, 0, 0, 18432, 368, }, /* 1531 */ - { 99, 26, 14, 0, 0, 18432, 370, }, /* 1532 */ - { 99, 26, 14, 0, 0, 18432, 364, }, /* 1533 */ - { 99, 26, 11, 0, 0, 18432, 372, }, /* 1534 */ - { 27, 26, 12, 0, 0, 18432, 74, }, /* 1535 */ - { 99, 26, 14, 0, 0, 18432, 250, }, /* 1536 */ - { 99, 26, 14, 0, 0, 18784, 364, }, /* 1537 */ - { 99, 26, 14, 0, 0, 28672, 374, }, /* 1538 */ - { 99, 26, 14, 0, 0, 28672, 376, }, /* 1539 */ - { 99, 24, 3, 0, 0, 28672, 378, }, /* 1540 */ - { 99, 26, 14, 0, 0, 28672, 380, }, /* 1541 */ - { 99, 1, 3, 0, 0, 6144, 382, }, /* 1542 */ + { 0, 5, 12, 0, 195, 18432, 76, }, /* 74 */ + { 0, 9, 12, 0, 210, 18432, 74, }, /* 75 */ + { 0, 9, 12, 0, 206, 18432, 74, }, /* 76 */ + { 0, 9, 12, 0, 205, 18432, 74, }, /* 77 */ + { 0, 9, 12, 0, 79, 18432, 74, }, /* 78 */ + { 0, 9, 12, 0, 202, 18432, 74, }, /* 79 */ + { 0, 9, 12, 0, 203, 18432, 74, }, /* 80 */ + { 0, 9, 12, 0, 207, 18432, 74, }, /* 81 */ + { 0, 5, 12, 0, 97, 18432, 76, }, /* 82 */ + { 0, 9, 12, 0, 211, 18432, 74, }, /* 83 */ + { 0, 9, 12, 0, 209, 18432, 74, }, /* 84 */ + { 0, 5, 12, 0, 163, 18432, 76, }, /* 85 */ + { 0, 9, 12, 0, 213, 18432, 74, }, /* 86 */ + { 0, 5, 12, 0, 130, 18432, 76, }, /* 87 */ + { 0, 9, 12, 0, 214, 18432, 74, }, /* 88 */ + { 0, 9, 12, 0, 218, 18432, 74, }, /* 89 */ + { 0, 9, 12, 0, 217, 18432, 74, }, /* 90 */ + { 0, 9, 12, 0, 219, 18432, 74, }, /* 91 */ + { 0, 7, 12, 0, 0, 18432, 82, }, /* 92 */ + { 0, 5, 12, 0, 56, 18432, 76, }, /* 93 */ + { 0, 9, 12, 5, 2, 18432, 84, }, /* 94 */ + { 0, 8, 12, 5, 1, 18432, 86, }, /* 95 */ + { 0, 5, 12, 5, -2, 18432, 76, }, /* 96 */ + { 0, 9, 12, 9, 2, 18432, 84, }, /* 97 */ + { 0, 8, 12, 9, 1, 18432, 86, }, /* 98 */ + { 0, 5, 12, 9, -2, 18432, 76, }, /* 99 */ + { 0, 9, 12, 13, 2, 18432, 84, }, /* 100 */ + { 0, 8, 12, 13, 1, 18432, 86, }, /* 101 */ + { 0, 5, 12, 13, -2, 18432, 76, }, /* 102 */ + { 0, 5, 12, 0, -79, 18432, 76, }, /* 103 */ + { 0, 9, 12, 17, 2, 18432, 84, }, /* 104 */ + { 0, 8, 12, 17, 1, 18432, 86, }, /* 105 */ + { 0, 5, 12, 17, -2, 18432, 76, }, /* 106 */ + { 0, 9, 12, 0, -97, 18432, 74, }, /* 107 */ + { 0, 9, 12, 0, -56, 18432, 74, }, /* 108 */ + { 0, 9, 12, 0, -130, 18432, 74, }, /* 109 */ + { 0, 9, 12, 0, 10795, 18432, 74, }, /* 110 */ + { 0, 9, 12, 0, -163, 18432, 74, }, /* 111 */ + { 0, 9, 12, 0, 10792, 18432, 74, }, /* 112 */ + { 0, 5, 12, 0, 10815, 18432, 76, }, /* 113 */ + { 0, 9, 12, 0, -195, 18432, 74, }, /* 114 */ + { 0, 9, 12, 0, 69, 18432, 74, }, /* 115 */ + { 0, 9, 12, 0, 71, 18432, 74, }, /* 116 */ + { 0, 5, 12, 0, 10783, 18432, 76, }, /* 117 */ + { 0, 5, 12, 0, 10780, 18432, 76, }, /* 118 */ + { 0, 5, 12, 0, 10782, 18432, 76, }, /* 119 */ + { 0, 5, 12, 0, -210, 18432, 76, }, /* 120 */ + { 0, 5, 12, 0, -206, 18432, 76, }, /* 121 */ + { 0, 5, 12, 0, -205, 18432, 76, }, /* 122 */ + { 0, 5, 12, 0, -202, 18432, 76, }, /* 123 */ + { 0, 5, 12, 0, -203, 18432, 76, }, /* 124 */ + { 0, 5, 12, 0, 42319, 18432, 76, }, /* 125 */ + { 0, 5, 12, 0, 42315, 18432, 76, }, /* 126 */ + { 0, 5, 12, 0, -207, 18432, 76, }, /* 127 */ + { 0, 5, 12, 0, 42280, 18432, 76, }, /* 128 */ + { 0, 5, 12, 0, 42308, 18432, 76, }, /* 129 */ + { 0, 5, 12, 0, -209, 18432, 78, }, /* 130 */ + { 0, 5, 12, 0, -211, 18432, 76, }, /* 131 */ + { 0, 5, 12, 0, 10743, 18432, 76, }, /* 132 */ + { 0, 5, 12, 0, 42305, 18432, 76, }, /* 133 */ + { 0, 5, 12, 0, 10749, 18432, 76, }, /* 134 */ + { 0, 5, 12, 0, -213, 18432, 76, }, /* 135 */ + { 0, 5, 12, 0, -214, 18432, 76, }, /* 136 */ + { 0, 5, 12, 0, 10727, 18432, 76, }, /* 137 */ + { 0, 5, 12, 0, -218, 18432, 76, }, /* 138 */ + { 0, 5, 12, 0, 42307, 18432, 76, }, /* 139 */ + { 0, 5, 12, 0, 42282, 18432, 76, }, /* 140 */ + { 0, 5, 12, 0, -69, 18432, 76, }, /* 141 */ + { 0, 5, 12, 0, -217, 18432, 76, }, /* 142 */ + { 0, 5, 12, 0, -71, 18432, 76, }, /* 143 */ + { 0, 5, 12, 0, -219, 18432, 76, }, /* 144 */ + { 0, 5, 12, 0, 42261, 18432, 78, }, /* 145 */ + { 0, 5, 12, 0, 42258, 18432, 76, }, /* 146 */ + { 0, 6, 12, 0, 0, 18432, 88, }, /* 147 */ + { 0, 6, 12, 0, 0, 18432, 90, }, /* 148 */ + { 69, 6, 12, 0, 0, 28672, 92, }, /* 149 */ + { 69, 6, 12, 0, 0, 18432, 92, }, /* 150 */ + { 69, 6, 12, 0, 0, 18432, 88, }, /* 151 */ + { 69, 6, 12, 0, 0, 18432, 94, }, /* 152 */ + { 22, 24, 12, 0, 0, 28672, 56, }, /* 153 */ + { 84, 12, 3, 0, 0, 26624, 96, }, /* 154 */ + { 84, 12, 3, 0, 0, 26636, 96, }, /* 155 */ + { 84, 12, 3, 21, 116, 26636, 98, }, /* 156 */ + { 84, 12, 3, 0, 0, 26624, 100, }, /* 157 */ + { 84, 12, 3, 0, 0, 26624, 102, }, /* 158 */ + { 84, 12, 3, 0, 0, 26642, 102, }, /* 159 */ + { 1, 9, 12, 0, 1, 18432, 74, }, /* 160 */ + { 1, 5, 12, 0, -1, 18432, 76, }, /* 161 */ + { 1, 24, 12, 0, 0, 28672, 56, }, /* 162 */ + { 68, 2, 12, 0, 0, 18432, 0, }, /* 163 */ + { 1, 6, 12, 0, 0, 18432, 104, }, /* 164 */ + { 1, 5, 12, 0, 130, 18432, 76, }, /* 165 */ + { 69, 21, 12, 0, 0, 28672, 106, }, /* 166 */ + { 1, 9, 12, 0, 116, 18432, 74, }, /* 167 */ + { 1, 9, 12, 0, 38, 18432, 74, }, /* 168 */ + { 69, 21, 12, 0, 0, 28672, 108, }, /* 169 */ + { 1, 9, 12, 0, 37, 18432, 74, }, /* 170 */ + { 1, 9, 12, 0, 64, 18432, 74, }, /* 171 */ + { 1, 9, 12, 0, 63, 18432, 74, }, /* 172 */ + { 1, 5, 12, 0, 0, 18432, 76, }, /* 173 */ + { 1, 9, 12, 0, 32, 18432, 74, }, /* 174 */ + { 1, 9, 12, 34, 32, 18432, 74, }, /* 175 */ + { 1, 9, 12, 59, 32, 18432, 74, }, /* 176 */ + { 1, 9, 12, 38, 32, 18432, 74, }, /* 177 */ + { 1, 9, 12, 21, 32, 18432, 74, }, /* 178 */ + { 1, 9, 12, 51, 32, 18432, 74, }, /* 179 */ + { 1, 9, 12, 26, 32, 18432, 74, }, /* 180 */ + { 1, 9, 12, 47, 32, 18432, 74, }, /* 181 */ + { 1, 9, 12, 55, 32, 18432, 74, }, /* 182 */ + { 1, 9, 12, 30, 32, 18432, 74, }, /* 183 */ + { 1, 9, 12, 43, 32, 18432, 74, }, /* 184 */ + { 1, 9, 12, 96, 32, 18432, 74, }, /* 185 */ + { 1, 5, 12, 0, -38, 18432, 76, }, /* 186 */ + { 1, 5, 12, 0, -37, 18432, 76, }, /* 187 */ + { 1, 5, 12, 0, -32, 18432, 76, }, /* 188 */ + { 1, 5, 12, 34, -32, 18432, 76, }, /* 189 */ + { 1, 5, 12, 59, -32, 18432, 76, }, /* 190 */ + { 1, 5, 12, 38, -32, 18432, 76, }, /* 191 */ + { 1, 5, 12, 21, -116, 18432, 76, }, /* 192 */ + { 1, 5, 12, 51, -32, 18432, 76, }, /* 193 */ + { 1, 5, 12, 26, -775, 18432, 76, }, /* 194 */ + { 1, 5, 12, 47, -32, 18432, 76, }, /* 195 */ + { 1, 5, 12, 55, -32, 18432, 76, }, /* 196 */ + { 1, 5, 12, 30, 1, 18432, 70, }, /* 197 */ + { 1, 5, 12, 30, -32, 18432, 76, }, /* 198 */ + { 1, 5, 12, 43, -32, 18432, 76, }, /* 199 */ + { 1, 5, 12, 96, -32, 18432, 76, }, /* 200 */ + { 1, 5, 12, 0, -64, 18432, 76, }, /* 201 */ + { 1, 5, 12, 0, -63, 18432, 76, }, /* 202 */ + { 1, 9, 12, 0, 8, 18432, 74, }, /* 203 */ + { 1, 5, 12, 34, -30, 18432, 110, }, /* 204 */ + { 1, 5, 12, 38, -25, 18432, 110, }, /* 205 */ + { 1, 9, 12, 0, 0, 18432, 112, }, /* 206 */ + { 1, 9, 12, 0, 0, 18432, 114, }, /* 207 */ + { 1, 5, 12, 43, -15, 18432, 110, }, /* 208 */ + { 1, 5, 12, 47, -22, 18432, 70, }, /* 209 */ + { 1, 5, 12, 0, -8, 18432, 76, }, /* 210 */ + { 34, 9, 12, 0, 1, 18432, 74, }, /* 211 */ + { 34, 5, 12, 0, -1, 18432, 76, }, /* 212 */ + { 1, 5, 12, 51, -54, 18432, 110, }, /* 213 */ + { 1, 5, 12, 55, -48, 18432, 110, }, /* 214 */ + { 1, 5, 12, 0, 7, 18432, 76, }, /* 215 */ + { 1, 5, 12, 0, -116, 18432, 78, }, /* 216 */ + { 1, 9, 12, 38, -60, 18432, 116, }, /* 217 */ + { 1, 5, 12, 59, -64, 18432, 110, }, /* 218 */ + { 1, 25, 12, 0, 0, 28672, 118, }, /* 219 */ + { 1, 9, 12, 0, -7, 18432, 74, }, /* 220 */ + { 1, 5, 12, 0, 0, 18432, 60, }, /* 221 */ + { 1, 9, 12, 0, -130, 18432, 74, }, /* 222 */ + { 2, 9, 12, 0, 80, 18432, 74, }, /* 223 */ + { 2, 9, 12, 0, 32, 18432, 74, }, /* 224 */ + { 2, 9, 12, 63, 32, 18432, 74, }, /* 225 */ + { 2, 9, 12, 67, 32, 18432, 74, }, /* 226 */ + { 2, 9, 12, 71, 32, 18432, 74, }, /* 227 */ + { 2, 9, 12, 75, 32, 18432, 74, }, /* 228 */ + { 2, 9, 12, 79, 32, 18432, 74, }, /* 229 */ + { 2, 9, 12, 84, 32, 18432, 74, }, /* 230 */ + { 2, 5, 12, 0, -32, 18432, 76, }, /* 231 */ + { 2, 5, 12, 63, -32, 18432, 76, }, /* 232 */ + { 2, 5, 12, 67, -32, 18432, 76, }, /* 233 */ + { 2, 5, 12, 71, -32, 18432, 76, }, /* 234 */ + { 2, 5, 12, 75, -32, 18432, 76, }, /* 235 */ + { 2, 5, 12, 79, -32, 18432, 76, }, /* 236 */ + { 2, 5, 12, 84, -32, 18432, 76, }, /* 237 */ + { 2, 5, 12, 0, -80, 18432, 76, }, /* 238 */ + { 2, 5, 12, 0, -80, 18432, 78, }, /* 239 */ + { 2, 9, 12, 0, 1, 18432, 74, }, /* 240 */ + { 2, 5, 12, 0, -1, 18432, 76, }, /* 241 */ + { 2, 9, 12, 88, 1, 18432, 74, }, /* 242 */ + { 2, 5, 12, 88, -1, 18432, 76, }, /* 243 */ + { 2, 26, 12, 0, 0, 18432, 68, }, /* 244 */ + { 2, 12, 3, 0, 0, 26684, 96, }, /* 245 */ + { 2, 12, 3, 0, 0, 26678, 96, }, /* 246 */ + { 84, 12, 3, 0, 0, 26681, 96, }, /* 247 */ + { 2, 11, 3, 0, 0, 26624, 120, }, /* 248 */ + { 2, 9, 12, 0, 15, 18432, 74, }, /* 249 */ + { 2, 5, 12, 0, -15, 18432, 76, }, /* 250 */ + { 70, 9, 12, 0, 48, 18432, 74, }, /* 251 */ + { 70, 6, 12, 0, 0, 18432, 92, }, /* 252 */ + { 70, 21, 12, 0, 0, 18432, 68, }, /* 253 */ + { 70, 21, 12, 0, 0, 18432, 122, }, /* 254 */ + { 70, 5, 12, 0, 0, 18432, 60, }, /* 255 */ + { 70, 5, 12, 0, -48, 18432, 76, }, /* 256 */ + { 70, 5, 12, 0, 0, 18432, 70, }, /* 257 */ + { 70, 21, 12, 0, 0, 18432, 124, }, /* 258 */ + { 70, 17, 12, 0, 0, 28672, 126, }, /* 259 */ + { 70, 26, 12, 0, 0, 28672, 68, }, /* 260 */ + { 70, 23, 12, 0, 0, 14336, 68, }, /* 261 */ + { 68, 2, 12, 0, 0, 34816, 0, }, /* 262 */ + { 71, 12, 3, 0, 0, 26624, 96, }, /* 263 */ + { 71, 12, 3, 0, 0, 26624, 102, }, /* 264 */ + { 71, 12, 3, 0, 0, 26624, 128, }, /* 265 */ + { 71, 17, 12, 0, 0, 34816, 126, }, /* 266 */ + { 71, 21, 12, 0, 0, 34816, 68, }, /* 267 */ + { 71, 21, 12, 0, 0, 34816, 106, }, /* 268 */ + { 71, 12, 3, 0, 0, 26624, 130, }, /* 269 */ + { 71, 7, 12, 0, 0, 34816, 82, }, /* 270 */ + { 71, 21, 12, 0, 0, 34816, 122, }, /* 271 */ + { 3, 1, 4, 0, 0, 2048, 132, }, /* 272 */ + { 69, 1, 4, 0, 0, 2048, 132, }, /* 273 */ + { 3, 25, 12, 0, 0, 28672, 118, }, /* 274 */ + { 3, 25, 12, 0, 0, 0, 118, }, /* 275 */ + { 3, 21, 12, 0, 0, 14336, 68, }, /* 276 */ + { 3, 23, 12, 0, 0, 0, 68, }, /* 277 */ + { 69, 21, 12, 0, 0, 8342, 106, }, /* 278 */ + { 3, 21, 12, 0, 0, 0, 68, }, /* 279 */ + { 3, 26, 12, 0, 0, 28672, 68, }, /* 280 */ + { 3, 12, 3, 0, 0, 26624, 130, }, /* 281 */ + { 69, 21, 12, 0, 0, 150, 106, }, /* 282 */ + { 3, 1, 2, 0, 0, 108, 134, }, /* 283 */ + { 3, 21, 12, 0, 0, 0, 124, }, /* 284 */ + { 69, 21, 12, 0, 0, 159, 124, }, /* 285 */ + { 3, 7, 12, 0, 0, 0, 82, }, /* 286 */ + { 69, 6, 12, 0, 0, 165, 136, }, /* 287 */ + { 84, 12, 3, 0, 0, 26660, 128, }, /* 288 */ + { 84, 12, 3, 0, 0, 26660, 130, }, /* 289 */ + { 3, 12, 3, 0, 0, 26624, 128, }, /* 290 */ + { 3, 12, 3, 0, 0, 26624, 96, }, /* 291 */ + { 3, 13, 12, 0, 0, 2159, 138, }, /* 292 */ + { 3, 21, 12, 0, 0, 2048, 68, }, /* 293 */ + { 3, 7, 12, 0, 0, 0, 140, }, /* 294 */ + { 3, 21, 12, 0, 0, 30, 124, }, /* 295 */ + { 3, 6, 12, 0, 0, 0, 92, }, /* 296 */ + { 3, 13, 12, 0, 0, 10240, 138, }, /* 297 */ + { 3, 26, 12, 0, 0, 0, 68, }, /* 298 */ + { 4, 21, 12, 0, 0, 0, 124, }, /* 299 */ + { 4, 21, 12, 0, 0, 0, 106, }, /* 300 */ + { 4, 21, 12, 0, 0, 0, 68, }, /* 301 */ + { 68, 2, 12, 0, 0, 0, 0, }, /* 302 */ + { 4, 1, 4, 0, 0, 0, 132, }, /* 303 */ + { 4, 7, 12, 0, 0, 0, 82, }, /* 304 */ + { 4, 12, 3, 0, 0, 26624, 130, }, /* 305 */ + { 4, 12, 3, 0, 0, 26624, 128, }, /* 306 */ + { 4, 12, 3, 0, 0, 26624, 96, }, /* 307 */ + { 5, 7, 12, 0, 0, 0, 82, }, /* 308 */ + { 5, 12, 3, 0, 0, 26624, 128, }, /* 309 */ + { 38, 13, 12, 0, 0, 34816, 138, }, /* 310 */ + { 38, 7, 12, 0, 0, 34816, 82, }, /* 311 */ + { 38, 12, 3, 0, 0, 26624, 96, }, /* 312 */ + { 38, 6, 12, 0, 0, 34816, 92, }, /* 313 */ + { 38, 26, 12, 0, 0, 28672, 68, }, /* 314 */ + { 38, 21, 12, 0, 0, 28672, 68, }, /* 315 */ + { 38, 21, 12, 0, 0, 28672, 106, }, /* 316 */ + { 38, 21, 12, 0, 0, 28672, 124, }, /* 317 */ + { 38, 6, 12, 0, 0, 34816, 136, }, /* 318 */ + { 38, 12, 3, 0, 0, 26624, 102, }, /* 319 */ + { 38, 23, 12, 0, 0, 34816, 68, }, /* 320 */ + { 110, 7, 12, 0, 0, 34816, 82, }, /* 321 */ + { 110, 12, 3, 0, 0, 26624, 130, }, /* 322 */ + { 110, 12, 3, 0, 0, 26624, 96, }, /* 323 */ + { 110, 6, 12, 0, 0, 34816, 142, }, /* 324 */ + { 110, 12, 3, 0, 0, 26624, 102, }, /* 325 */ + { 110, 21, 12, 0, 0, 34816, 106, }, /* 326 */ + { 110, 21, 12, 0, 0, 34816, 124, }, /* 327 */ + { 42, 7, 12, 0, 0, 34816, 82, }, /* 328 */ + { 42, 12, 3, 0, 0, 26624, 102, }, /* 329 */ + { 42, 21, 12, 0, 0, 34816, 106, }, /* 330 */ + { 3, 24, 12, 0, 0, 0, 122, }, /* 331 */ + { 3, 12, 3, 0, 0, 26624, 102, }, /* 332 */ + { 6, 12, 3, 0, 0, 26624, 130, }, /* 333 */ + { 6, 10, 5, 0, 0, 18432, 144, }, /* 334 */ + { 6, 7, 12, 0, 0, 18432, 82, }, /* 335 */ + { 6, 12, 3, 0, 0, 26624, 96, }, /* 336 */ + { 6, 12, 3, 0, 0, 26624, 146, }, /* 337 */ + { 84, 12, 3, 0, 0, 26798, 96, }, /* 338 */ + { 84, 12, 3, 0, 0, 26795, 96, }, /* 339 */ + { 69, 21, 12, 0, 0, 18615, 124, }, /* 340 */ + { 69, 21, 12, 0, 0, 18618, 124, }, /* 341 */ + { 6, 13, 12, 0, 0, 18576, 138, }, /* 342 */ + { 6, 21, 12, 0, 0, 18432, 68, }, /* 343 */ + { 6, 6, 12, 0, 0, 18432, 92, }, /* 344 */ + { 7, 7, 12, 0, 0, 18432, 82, }, /* 345 */ + { 7, 12, 3, 0, 0, 26624, 130, }, /* 346 */ + { 7, 10, 5, 0, 0, 18432, 144, }, /* 347 */ + { 7, 12, 3, 0, 0, 26624, 96, }, /* 348 */ + { 7, 10, 3, 0, 0, 18432, 148, }, /* 349 */ + { 7, 12, 3, 0, 0, 26624, 146, }, /* 350 */ + { 7, 13, 12, 0, 0, 18546, 138, }, /* 351 */ + { 7, 23, 12, 0, 0, 14336, 68, }, /* 352 */ + { 7, 15, 12, 0, 0, 18432, 68, }, /* 353 */ + { 7, 26, 12, 0, 0, 18432, 68, }, /* 354 */ + { 7, 21, 12, 0, 0, 18432, 68, }, /* 355 */ + { 7, 12, 3, 0, 0, 26624, 102, }, /* 356 */ + { 8, 12, 3, 0, 0, 26624, 130, }, /* 357 */ + { 8, 10, 5, 0, 0, 18432, 144, }, /* 358 */ + { 8, 7, 12, 0, 0, 18432, 82, }, /* 359 */ + { 8, 12, 3, 0, 0, 26624, 96, }, /* 360 */ + { 8, 12, 3, 0, 0, 26624, 146, }, /* 361 */ + { 8, 13, 12, 0, 0, 18519, 138, }, /* 362 */ + { 8, 21, 12, 0, 0, 18432, 68, }, /* 363 */ + { 9, 12, 3, 0, 0, 26624, 130, }, /* 364 */ + { 9, 10, 5, 0, 0, 18432, 144, }, /* 365 */ + { 9, 7, 12, 0, 0, 18432, 82, }, /* 366 */ + { 9, 12, 3, 0, 0, 26624, 96, }, /* 367 */ + { 9, 12, 3, 0, 0, 26624, 146, }, /* 368 */ + { 9, 13, 12, 0, 0, 18516, 138, }, /* 369 */ + { 9, 21, 12, 0, 0, 18432, 68, }, /* 370 */ + { 9, 23, 12, 0, 0, 14336, 68, }, /* 371 */ + { 10, 12, 3, 0, 0, 26624, 130, }, /* 372 */ + { 10, 10, 5, 0, 0, 18432, 144, }, /* 373 */ + { 10, 7, 12, 0, 0, 18432, 82, }, /* 374 */ + { 10, 12, 3, 0, 0, 26624, 96, }, /* 375 */ + { 10, 10, 3, 0, 0, 18432, 148, }, /* 376 */ + { 10, 12, 3, 0, 0, 26624, 146, }, /* 377 */ + { 10, 12, 3, 0, 0, 26624, 150, }, /* 378 */ + { 10, 13, 12, 0, 0, 18432, 138, }, /* 379 */ + { 10, 26, 12, 0, 0, 18432, 68, }, /* 380 */ + { 10, 15, 12, 0, 0, 18432, 68, }, /* 381 */ + { 11, 12, 3, 0, 0, 26624, 130, }, /* 382 */ + { 11, 7, 12, 0, 0, 18432, 82, }, /* 383 */ + { 11, 10, 3, 0, 0, 18432, 148, }, /* 384 */ + { 11, 10, 5, 0, 0, 18432, 144, }, /* 385 */ + { 11, 12, 3, 0, 0, 26624, 146, }, /* 386 */ + { 11, 13, 12, 0, 0, 18513, 138, }, /* 387 */ + { 11, 15, 12, 0, 0, 18513, 68, }, /* 388 */ + { 11, 26, 12, 0, 0, 28753, 68, }, /* 389 */ + { 11, 26, 12, 0, 0, 28672, 68, }, /* 390 */ + { 11, 23, 12, 0, 0, 14336, 68, }, /* 391 */ + { 12, 12, 3, 0, 0, 26624, 130, }, /* 392 */ + { 12, 10, 5, 0, 0, 18432, 144, }, /* 393 */ + { 12, 7, 12, 0, 0, 18432, 82, }, /* 394 */ + { 12, 12, 3, 0, 0, 26624, 96, }, /* 395 */ + { 12, 12, 3, 0, 0, 26624, 146, }, /* 396 */ + { 12, 13, 12, 0, 0, 18432, 138, }, /* 397 */ + { 12, 21, 12, 0, 0, 18432, 68, }, /* 398 */ + { 12, 15, 12, 0, 0, 28672, 68, }, /* 399 */ + { 12, 26, 12, 0, 0, 18432, 68, }, /* 400 */ + { 13, 7, 12, 0, 0, 18432, 82, }, /* 401 */ + { 13, 12, 3, 0, 0, 26624, 130, }, /* 402 */ + { 13, 10, 5, 0, 0, 18432, 144, }, /* 403 */ + { 13, 21, 12, 0, 0, 18432, 68, }, /* 404 */ + { 13, 12, 3, 0, 0, 26624, 96, }, /* 405 */ + { 13, 12, 3, 0, 0, 18432, 130, }, /* 406 */ + { 13, 10, 3, 0, 0, 18432, 148, }, /* 407 */ + { 13, 12, 3, 0, 0, 26624, 146, }, /* 408 */ + { 13, 13, 12, 0, 0, 18528, 138, }, /* 409 */ + { 14, 12, 3, 0, 0, 26624, 130, }, /* 410 */ + { 14, 10, 5, 0, 0, 18432, 144, }, /* 411 */ + { 14, 7, 12, 0, 0, 18432, 82, }, /* 412 */ + { 14, 12, 3, 0, 0, 26624, 146, }, /* 413 */ + { 14, 10, 3, 0, 0, 18432, 148, }, /* 414 */ + { 14, 7, 4, 0, 0, 18432, 82, }, /* 415 */ + { 14, 26, 12, 0, 0, 18432, 68, }, /* 416 */ + { 14, 15, 12, 0, 0, 18432, 68, }, /* 417 */ + { 14, 13, 12, 0, 0, 18432, 138, }, /* 418 */ + { 15, 12, 3, 0, 0, 26624, 130, }, /* 419 */ + { 15, 10, 5, 0, 0, 18432, 144, }, /* 420 */ + { 15, 7, 12, 0, 0, 18432, 82, }, /* 421 */ + { 15, 12, 3, 0, 0, 26624, 146, }, /* 422 */ + { 15, 10, 3, 0, 0, 18432, 148, }, /* 423 */ + { 15, 13, 12, 0, 0, 18432, 138, }, /* 424 */ + { 15, 21, 12, 0, 0, 18432, 68, }, /* 425 */ + { 72, 7, 12, 0, 0, 18432, 82, }, /* 426 */ + { 72, 12, 3, 0, 0, 26624, 130, }, /* 427 */ + { 72, 7, 5, 0, 0, 18432, 152, }, /* 428 */ + { 72, 12, 3, 0, 0, 26624, 154, }, /* 429 */ + { 69, 23, 12, 0, 0, 14336, 68, }, /* 430 */ + { 72, 7, 12, 0, 0, 18432, 156, }, /* 431 */ + { 72, 6, 12, 0, 0, 18432, 136, }, /* 432 */ + { 72, 12, 3, 0, 0, 26624, 96, }, /* 433 */ + { 72, 21, 12, 0, 0, 18432, 68, }, /* 434 */ + { 72, 13, 12, 0, 0, 18432, 138, }, /* 435 */ + { 72, 21, 12, 0, 0, 18432, 106, }, /* 436 */ + { 73, 7, 12, 0, 0, 18432, 82, }, /* 437 */ + { 73, 12, 3, 0, 0, 26624, 130, }, /* 438 */ + { 73, 7, 5, 0, 0, 18432, 152, }, /* 439 */ + { 73, 12, 3, 0, 0, 26624, 146, }, /* 440 */ + { 73, 7, 12, 0, 0, 18432, 156, }, /* 441 */ + { 73, 6, 12, 0, 0, 18432, 136, }, /* 442 */ + { 73, 12, 3, 0, 0, 26624, 96, }, /* 443 */ + { 73, 12, 3, 0, 0, 26624, 102, }, /* 444 */ + { 73, 13, 12, 0, 0, 18432, 138, }, /* 445 */ + { 74, 7, 12, 0, 0, 18432, 82, }, /* 446 */ + { 74, 26, 12, 0, 0, 18432, 68, }, /* 447 */ + { 74, 21, 12, 0, 0, 18432, 68, }, /* 448 */ + { 74, 21, 12, 0, 0, 18432, 106, }, /* 449 */ + { 74, 12, 3, 0, 0, 26624, 96, }, /* 450 */ + { 74, 13, 12, 0, 0, 18432, 138, }, /* 451 */ + { 74, 15, 12, 0, 0, 18432, 68, }, /* 452 */ + { 74, 22, 12, 0, 0, 28672, 158, }, /* 453 */ + { 74, 18, 12, 0, 0, 28672, 158, }, /* 454 */ + { 74, 10, 5, 0, 0, 18432, 160, }, /* 455 */ + { 74, 12, 3, 0, 0, 26624, 130, }, /* 456 */ + { 74, 12, 3, 0, 0, 26624, 162, }, /* 457 */ + { 74, 10, 5, 0, 0, 18432, 144, }, /* 458 */ + { 74, 12, 3, 0, 0, 26624, 128, }, /* 459 */ + { 74, 12, 3, 0, 0, 26624, 146, }, /* 460 */ + { 69, 26, 12, 0, 0, 18432, 68, }, /* 461 */ + { 16, 7, 12, 0, 0, 18432, 82, }, /* 462 */ + { 16, 10, 12, 0, 0, 18432, 144, }, /* 463 */ + { 16, 12, 3, 0, 0, 26624, 130, }, /* 464 */ + { 16, 10, 5, 0, 0, 18432, 144, }, /* 465 */ + { 16, 12, 3, 0, 0, 26624, 96, }, /* 466 */ + { 16, 12, 3, 0, 0, 26624, 146, }, /* 467 */ + { 16, 13, 12, 0, 0, 18549, 138, }, /* 468 */ + { 16, 21, 12, 0, 0, 18432, 124, }, /* 469 */ + { 16, 21, 12, 0, 0, 18432, 68, }, /* 470 */ + { 16, 10, 12, 0, 0, 18432, 164, }, /* 471 */ + { 16, 12, 3, 0, 0, 26624, 128, }, /* 472 */ + { 16, 13, 12, 0, 0, 18432, 138, }, /* 473 */ + { 16, 26, 12, 0, 0, 18432, 68, }, /* 474 */ + { 17, 9, 12, 0, 7264, 18432, 74, }, /* 475 */ + { 17, 5, 12, 0, 3008, 18432, 166, }, /* 476 */ + { 69, 21, 12, 0, 0, 18510, 68, }, /* 477 */ + { 17, 6, 12, 0, 0, 18432, 168, }, /* 478 */ + { 18, 7, 6, 0, 0, 18432, 82, }, /* 479 */ + { 18, 7, 6, 0, 0, 18432, 170, }, /* 480 */ + { 18, 7, 7, 0, 0, 18432, 170, }, /* 481 */ + { 18, 7, 7, 0, 0, 18432, 82, }, /* 482 */ + { 18, 7, 8, 0, 0, 18432, 82, }, /* 483 */ + { 75, 7, 12, 0, 0, 18432, 82, }, /* 484 */ + { 75, 12, 3, 0, 0, 26624, 96, }, /* 485 */ + { 75, 21, 12, 0, 0, 18432, 68, }, /* 486 */ + { 75, 21, 12, 0, 0, 18432, 106, }, /* 487 */ + { 75, 21, 12, 0, 0, 18432, 124, }, /* 488 */ + { 75, 15, 12, 0, 0, 18432, 138, }, /* 489 */ + { 75, 15, 12, 0, 0, 18432, 68, }, /* 490 */ + { 75, 26, 12, 0, 0, 28672, 68, }, /* 491 */ + { 76, 9, 12, 0, 38864, 18432, 172, }, /* 492 */ + { 76, 9, 12, 0, 8, 18432, 172, }, /* 493 */ + { 76, 5, 12, 0, -8, 18432, 70, }, /* 494 */ + { 77, 17, 12, 0, 0, 28672, 126, }, /* 495 */ + { 77, 7, 12, 0, 0, 18432, 82, }, /* 496 */ + { 77, 26, 12, 0, 0, 18432, 68, }, /* 497 */ + { 77, 21, 12, 0, 0, 18432, 124, }, /* 498 */ + { 78, 29, 12, 0, 0, 45056, 52, }, /* 499 */ + { 78, 7, 12, 0, 0, 18432, 82, }, /* 500 */ + { 78, 22, 12, 0, 0, 28672, 158, }, /* 501 */ + { 78, 18, 12, 0, 0, 28672, 158, }, /* 502 */ + { 79, 7, 12, 0, 0, 18432, 82, }, /* 503 */ + { 69, 21, 12, 0, 0, 18432, 106, }, /* 504 */ + { 79, 14, 12, 0, 0, 18432, 82, }, /* 505 */ + { 25, 7, 12, 0, 0, 18432, 82, }, /* 506 */ + { 25, 12, 3, 0, 0, 26624, 130, }, /* 507 */ + { 25, 12, 3, 0, 0, 26624, 146, }, /* 508 */ + { 25, 10, 5, 0, 0, 18432, 174, }, /* 509 */ + { 26, 7, 12, 0, 0, 18432, 82, }, /* 510 */ + { 26, 12, 3, 0, 0, 26624, 130, }, /* 511 */ + { 26, 10, 5, 0, 0, 18432, 176, }, /* 512 */ + { 69, 21, 12, 0, 0, 18573, 124, }, /* 513 */ + { 27, 7, 12, 0, 0, 18432, 82, }, /* 514 */ + { 27, 12, 3, 0, 0, 26624, 130, }, /* 515 */ + { 28, 7, 12, 0, 0, 18432, 82, }, /* 516 */ + { 28, 12, 3, 0, 0, 26624, 130, }, /* 517 */ + { 80, 7, 12, 0, 0, 18432, 82, }, /* 518 */ + { 80, 7, 12, 0, 0, 18432, 140, }, /* 519 */ + { 80, 12, 3, 0, 0, 26624, 100, }, /* 520 */ + { 80, 10, 5, 0, 0, 18432, 144, }, /* 521 */ + { 80, 12, 3, 0, 0, 26624, 130, }, /* 522 */ + { 80, 12, 3, 0, 0, 26624, 96, }, /* 523 */ + { 80, 12, 3, 0, 0, 26624, 146, }, /* 524 */ + { 80, 21, 12, 0, 0, 18432, 106, }, /* 525 */ + { 80, 6, 12, 0, 0, 18432, 142, }, /* 526 */ + { 80, 21, 12, 0, 0, 18432, 68, }, /* 527 */ + { 80, 23, 12, 0, 0, 14336, 68, }, /* 528 */ + { 80, 13, 12, 0, 0, 18432, 138, }, /* 529 */ + { 80, 15, 12, 0, 0, 28672, 68, }, /* 530 */ + { 19, 21, 12, 0, 0, 28672, 68, }, /* 531 */ + { 69, 21, 12, 0, 0, 28777, 106, }, /* 532 */ + { 69, 21, 12, 0, 0, 28777, 124, }, /* 533 */ + { 19, 21, 12, 0, 0, 28672, 106, }, /* 534 */ + { 19, 17, 12, 0, 0, 28672, 126, }, /* 535 */ + { 19, 21, 12, 0, 0, 28672, 124, }, /* 536 */ + { 19, 21, 12, 0, 0, 28672, 178, }, /* 537 */ + { 19, 12, 3, 0, 0, 26624, 180, }, /* 538 */ + { 19, 1, 2, 0, 0, 6144, 66, }, /* 539 */ + { 19, 13, 12, 0, 0, 18432, 138, }, /* 540 */ + { 19, 7, 12, 0, 0, 18432, 82, }, /* 541 */ + { 19, 6, 12, 0, 0, 18432, 136, }, /* 542 */ + { 19, 12, 3, 0, 0, 26624, 182, }, /* 543 */ + { 19, 12, 3, 0, 0, 26624, 130, }, /* 544 */ + { 29, 7, 12, 0, 0, 18432, 82, }, /* 545 */ + { 29, 12, 3, 0, 0, 26624, 130, }, /* 546 */ + { 29, 10, 5, 0, 0, 18432, 144, }, /* 547 */ + { 29, 12, 3, 0, 0, 26624, 96, }, /* 548 */ + { 29, 26, 12, 0, 0, 28672, 68, }, /* 549 */ + { 29, 21, 12, 0, 0, 28672, 124, }, /* 550 */ + { 29, 13, 12, 0, 0, 18432, 138, }, /* 551 */ + { 30, 7, 12, 0, 0, 18432, 82, }, /* 552 */ + { 89, 7, 12, 0, 0, 18432, 82, }, /* 553 */ + { 89, 7, 12, 0, 0, 18432, 156, }, /* 554 */ + { 89, 13, 12, 0, 0, 18432, 138, }, /* 555 */ + { 89, 15, 12, 0, 0, 18432, 138, }, /* 556 */ + { 89, 26, 12, 0, 0, 28672, 68, }, /* 557 */ + { 80, 26, 12, 0, 0, 28672, 68, }, /* 558 */ + { 33, 7, 12, 0, 0, 18432, 82, }, /* 559 */ + { 33, 12, 3, 0, 0, 26624, 130, }, /* 560 */ + { 33, 10, 5, 0, 0, 18432, 144, }, /* 561 */ + { 33, 21, 12, 0, 0, 18432, 68, }, /* 562 */ + { 106, 7, 12, 0, 0, 18432, 82, }, /* 563 */ + { 106, 10, 5, 0, 0, 18432, 144, }, /* 564 */ + { 106, 12, 3, 0, 0, 26624, 130, }, /* 565 */ + { 106, 12, 3, 0, 0, 26624, 184, }, /* 566 */ + { 106, 10, 12, 0, 0, 18432, 144, }, /* 567 */ + { 106, 12, 3, 0, 0, 26624, 96, }, /* 568 */ + { 106, 13, 12, 0, 0, 18432, 138, }, /* 569 */ + { 106, 21, 12, 0, 0, 18432, 68, }, /* 570 */ + { 106, 6, 12, 0, 0, 18432, 136, }, /* 571 */ + { 106, 21, 12, 0, 0, 18432, 124, }, /* 572 */ + { 84, 11, 3, 0, 0, 26624, 186, }, /* 573 */ + { 84, 12, 3, 0, 0, 26624, 130, }, /* 574 */ + { 93, 12, 3, 0, 0, 26624, 130, }, /* 575 */ + { 93, 10, 5, 0, 0, 18432, 144, }, /* 576 */ + { 93, 7, 12, 0, 0, 18432, 82, }, /* 577 */ + { 93, 12, 3, 0, 0, 26624, 96, }, /* 578 */ + { 93, 10, 3, 0, 0, 18432, 148, }, /* 579 */ + { 93, 10, 5, 0, 0, 18432, 174, }, /* 580 */ + { 93, 13, 12, 0, 0, 18432, 138, }, /* 581 */ + { 93, 21, 12, 0, 0, 18432, 124, }, /* 582 */ + { 93, 21, 12, 0, 0, 18432, 68, }, /* 583 */ + { 93, 21, 12, 0, 0, 18432, 106, }, /* 584 */ + { 93, 26, 12, 0, 0, 18432, 68, }, /* 585 */ + { 96, 12, 3, 0, 0, 26624, 130, }, /* 586 */ + { 96, 10, 5, 0, 0, 18432, 144, }, /* 587 */ + { 96, 7, 12, 0, 0, 18432, 82, }, /* 588 */ + { 96, 10, 5, 0, 0, 18432, 174, }, /* 589 */ + { 96, 12, 3, 0, 0, 26624, 146, }, /* 590 */ + { 96, 13, 12, 0, 0, 18432, 138, }, /* 591 */ + { 119, 7, 12, 0, 0, 18432, 82, }, /* 592 */ + { 119, 12, 3, 0, 0, 26624, 102, }, /* 593 */ + { 119, 10, 5, 0, 0, 18432, 144, }, /* 594 */ + { 119, 12, 3, 0, 0, 26624, 130, }, /* 595 */ + { 119, 10, 5, 0, 0, 18432, 176, }, /* 596 */ + { 119, 21, 12, 0, 0, 18432, 68, }, /* 597 */ + { 97, 7, 12, 0, 0, 18432, 82, }, /* 598 */ + { 97, 10, 5, 0, 0, 18432, 144, }, /* 599 */ + { 97, 12, 3, 0, 0, 26624, 130, }, /* 600 */ + { 97, 12, 3, 0, 0, 26624, 188, }, /* 601 */ + { 97, 12, 3, 0, 0, 26624, 96, }, /* 602 */ + { 97, 21, 12, 0, 0, 18432, 124, }, /* 603 */ + { 97, 21, 12, 0, 0, 18432, 106, }, /* 604 */ + { 97, 13, 12, 0, 0, 18432, 138, }, /* 605 */ + { 98, 13, 12, 0, 0, 18432, 138, }, /* 606 */ + { 98, 7, 12, 0, 0, 18432, 82, }, /* 607 */ + { 98, 6, 12, 0, 0, 18432, 92, }, /* 608 */ + { 98, 6, 12, 0, 0, 18432, 94, }, /* 609 */ + { 98, 21, 12, 0, 0, 18432, 124, }, /* 610 */ + { 2, 5, 12, 63, -6222, 18432, 70, }, /* 611 */ + { 2, 5, 12, 67, -6221, 18432, 70, }, /* 612 */ + { 2, 5, 12, 71, -6212, 18432, 70, }, /* 613 */ + { 2, 5, 12, 75, -6210, 18432, 70, }, /* 614 */ + { 2, 5, 12, 79, -6210, 18432, 70, }, /* 615 */ + { 2, 5, 12, 79, -6211, 18432, 70, }, /* 616 */ + { 2, 5, 12, 84, -6204, 18432, 70, }, /* 617 */ + { 2, 5, 12, 88, -6180, 18432, 70, }, /* 618 */ + { 2, 5, 12, 108, 35267, 18432, 70, }, /* 619 */ + { 17, 9, 12, 0, -3008, 18432, 74, }, /* 620 */ + { 96, 21, 12, 0, 0, 18432, 68, }, /* 621 */ + { 84, 12, 3, 0, 0, 26762, 96, }, /* 622 */ + { 84, 12, 3, 0, 0, 26630, 96, }, /* 623 */ + { 69, 21, 12, 0, 0, 18498, 190, }, /* 624 */ + { 84, 12, 3, 0, 0, 26666, 96, }, /* 625 */ + { 84, 12, 3, 0, 0, 26696, 96, }, /* 626 */ + { 84, 12, 3, 0, 0, 26780, 96, }, /* 627 */ + { 69, 10, 5, 0, 0, 18474, 160, }, /* 628 */ + { 69, 7, 12, 0, 0, 18501, 82, }, /* 629 */ + { 69, 7, 12, 0, 0, 18474, 82, }, /* 630 */ + { 69, 7, 12, 0, 0, 18438, 82, }, /* 631 */ + { 69, 7, 12, 0, 0, 18594, 82, }, /* 632 */ + { 69, 7, 12, 0, 0, 18498, 82, }, /* 633 */ + { 84, 12, 3, 0, 0, 26750, 96, }, /* 634 */ + { 69, 10, 5, 0, 0, 18435, 160, }, /* 635 */ + { 84, 12, 3, 0, 0, 26690, 96, }, /* 636 */ + { 69, 7, 12, 0, 0, 18453, 82, }, /* 637 */ + { 2, 5, 12, 0, 0, 18432, 60, }, /* 638 */ + { 1, 6, 12, 0, 0, 18432, 88, }, /* 639 */ + { 2, 6, 12, 0, 0, 18432, 168, }, /* 640 */ + { 0, 5, 12, 0, 35332, 18432, 76, }, /* 641 */ + { 0, 5, 12, 0, 3814, 18432, 76, }, /* 642 */ + { 0, 5, 12, 0, 35384, 18432, 76, }, /* 643 */ + { 0, 5, 12, 0, 0, 18432, 192, }, /* 644 */ + { 0, 6, 12, 0, 0, 18432, 168, }, /* 645 */ + { 0, 6, 12, 0, 0, 18432, 194, }, /* 646 */ + { 1, 6, 12, 0, 0, 18432, 168, }, /* 647 */ + { 84, 12, 3, 0, 0, 26636, 102, }, /* 648 */ + { 84, 12, 3, 0, 0, 26687, 96, }, /* 649 */ + { 84, 12, 3, 0, 0, 26648, 96, }, /* 650 */ + { 0, 9, 12, 92, 1, 18432, 74, }, /* 651 */ + { 0, 5, 12, 92, -1, 18432, 76, }, /* 652 */ + { 0, 5, 12, 0, 0, 18432, 70, }, /* 653 */ + { 0, 5, 12, 92, -58, 18432, 70, }, /* 654 */ + { 0, 9, 12, 0, -7615, 18432, 74, }, /* 655 */ + { 1, 5, 12, 0, 8, 18432, 76, }, /* 656 */ + { 1, 9, 12, 0, -8, 18432, 74, }, /* 657 */ + { 1, 5, 12, 0, 74, 18432, 76, }, /* 658 */ + { 1, 5, 12, 0, 86, 18432, 76, }, /* 659 */ + { 1, 5, 12, 0, 100, 18432, 76, }, /* 660 */ + { 1, 5, 12, 0, 128, 18432, 76, }, /* 661 */ + { 1, 5, 12, 0, 112, 18432, 76, }, /* 662 */ + { 1, 5, 12, 0, 126, 18432, 76, }, /* 663 */ + { 1, 5, 12, 0, 8, 18432, 70, }, /* 664 */ + { 1, 8, 12, 0, -8, 18432, 86, }, /* 665 */ + { 1, 5, 12, 0, 0, 18432, 70, }, /* 666 */ + { 1, 5, 12, 0, 9, 18432, 70, }, /* 667 */ + { 1, 9, 12, 0, -74, 18432, 74, }, /* 668 */ + { 1, 8, 12, 0, -9, 18432, 86, }, /* 669 */ + { 1, 5, 12, 21, -7173, 18432, 76, }, /* 670 */ + { 1, 9, 12, 0, -86, 18432, 74, }, /* 671 */ + { 1, 9, 12, 0, -100, 18432, 74, }, /* 672 */ + { 1, 9, 12, 0, -112, 18432, 74, }, /* 673 */ + { 1, 9, 12, 0, -128, 18432, 74, }, /* 674 */ + { 1, 9, 12, 0, -126, 18432, 74, }, /* 675 */ + { 69, 29, 12, 0, 0, 45056, 52, }, /* 676 */ + { 84, 1, 3, 0, 0, 6144, 196, }, /* 677 */ + { 84, 1, 13, 0, 0, 6144, 198, }, /* 678 */ + { 69, 1, 2, 0, 0, 18432, 200, }, /* 679 */ + { 69, 1, 2, 0, 0, 34816, 200, }, /* 680 */ + { 69, 17, 12, 0, 0, 28672, 202, }, /* 681 */ + { 69, 21, 12, 0, 0, 28672, 64, }, /* 682 */ + { 69, 20, 12, 0, 0, 28672, 204, }, /* 683 */ + { 69, 19, 12, 0, 0, 28672, 204, }, /* 684 */ + { 69, 22, 12, 0, 0, 28672, 206, }, /* 685 */ + { 69, 20, 12, 0, 0, 28672, 206, }, /* 686 */ + { 69, 19, 12, 0, 0, 28672, 206, }, /* 687 */ + { 69, 21, 12, 0, 0, 28672, 208, }, /* 688 */ + { 69, 27, 2, 0, 0, 45056, 50, }, /* 689 */ + { 69, 28, 2, 0, 0, 4096, 50, }, /* 690 */ + { 69, 1, 2, 0, 0, 20480, 134, }, /* 691 */ + { 69, 1, 2, 0, 0, 36864, 134, }, /* 692 */ + { 69, 1, 2, 0, 0, 30720, 134, }, /* 693 */ + { 69, 1, 2, 0, 0, 24576, 134, }, /* 694 */ + { 69, 1, 2, 0, 0, 40960, 134, }, /* 695 */ + { 69, 29, 12, 0, 0, 8291, 52, }, /* 696 */ + { 69, 21, 12, 0, 0, 14336, 54, }, /* 697 */ + { 69, 21, 12, 0, 0, 14336, 64, }, /* 698 */ + { 69, 21, 14, 0, 0, 28672, 210, }, /* 699 */ + { 69, 21, 12, 0, 0, 28672, 212, }, /* 700 */ + { 69, 16, 12, 0, 0, 28672, 138, }, /* 701 */ + { 69, 16, 12, 0, 0, 28672, 214, }, /* 702 */ + { 69, 25, 12, 0, 0, 8192, 64, }, /* 703 */ + { 69, 22, 12, 0, 0, 28672, 216, }, /* 704 */ + { 69, 18, 12, 0, 0, 28672, 216, }, /* 705 */ + { 69, 21, 12, 0, 0, 28672, 202, }, /* 706 */ + { 69, 1, 2, 0, 0, 6144, 218, }, /* 707 */ + { 68, 2, 2, 0, 0, 6144, 220, }, /* 708 */ + { 69, 1, 2, 0, 0, 22528, 134, }, /* 709 */ + { 69, 1, 2, 0, 0, 38912, 134, }, /* 710 */ + { 69, 1, 2, 0, 0, 16384, 134, }, /* 711 */ + { 69, 1, 2, 0, 0, 32768, 134, }, /* 712 */ + { 69, 1, 2, 0, 0, 6144, 222, }, /* 713 */ + { 69, 25, 12, 0, 0, 12288, 118, }, /* 714 */ + { 69, 25, 12, 0, 0, 12288, 224, }, /* 715 */ + { 69, 25, 12, 0, 0, 28672, 118, }, /* 716 */ + { 69, 22, 12, 0, 0, 28672, 226, }, /* 717 */ + { 69, 18, 12, 0, 0, 28672, 226, }, /* 718 */ + { 68, 2, 12, 0, 0, 14336, 0, }, /* 719 */ + { 84, 12, 3, 0, 0, 26624, 228, }, /* 720 */ + { 84, 11, 3, 0, 0, 26624, 120, }, /* 721 */ + { 84, 11, 3, 0, 0, 26624, 230, }, /* 722 */ + { 84, 12, 3, 0, 0, 26753, 102, }, /* 723 */ + { 69, 26, 12, 0, 0, 28672, 68, }, /* 724 */ + { 69, 9, 12, 0, 0, 18432, 112, }, /* 725 */ + { 69, 5, 12, 0, 0, 18432, 232, }, /* 726 */ + { 69, 25, 12, 0, 0, 28672, 234, }, /* 727 */ + { 69, 26, 14, 0, 0, 28672, 236, }, /* 728 */ + { 1, 9, 12, 96, -7517, 18432, 74, }, /* 729 */ + { 69, 26, 12, 0, 0, 28672, 118, }, /* 730 */ + { 0, 9, 12, 100, 0, 18432, 74, }, /* 731 */ + { 0, 9, 12, 104, -8262, 18432, 74, }, /* 732 */ + { 69, 26, 12, 0, 0, 14336, 238, }, /* 733 */ + { 0, 9, 12, 0, 28, 18432, 74, }, /* 734 */ + { 69, 7, 12, 0, 0, 18432, 240, }, /* 735 */ + { 69, 5, 14, 0, 0, 18432, 242, }, /* 736 */ + { 69, 5, 12, 0, 0, 18432, 244, }, /* 737 */ + { 0, 5, 12, 0, -28, 18432, 76, }, /* 738 */ + { 0, 14, 12, 0, 16, 18432, 74, }, /* 739 */ + { 0, 14, 12, 0, -16, 18432, 76, }, /* 740 */ + { 0, 14, 12, 0, 0, 18432, 82, }, /* 741 */ + { 69, 25, 14, 0, 0, 28672, 246, }, /* 742 */ + { 69, 26, 14, 0, 0, 28672, 246, }, /* 743 */ + { 69, 26, 12, 0, 0, 28672, 64, }, /* 744 */ + { 69, 25, 12, 0, 0, 28672, 248, }, /* 745 */ + { 69, 25, 12, 0, 0, 12288, 250, }, /* 746 */ + { 69, 22, 12, 0, 0, 28672, 248, }, /* 747 */ + { 69, 18, 12, 0, 0, 28672, 248, }, /* 748 */ + { 69, 26, 14, 0, 0, 28672, 252, }, /* 749 */ + { 69, 22, 12, 0, 0, 28672, 254, }, /* 750 */ + { 69, 18, 12, 0, 0, 28672, 254, }, /* 751 */ + { 69, 26, 12, 0, 0, 18432, 54, }, /* 752 */ + { 69, 26, 14, 0, 0, 28672, 256, }, /* 753 */ + { 68, 2, 12, 0, 0, 18432, 258, }, /* 754 */ + { 69, 26, 12, 0, 26, 18432, 260, }, /* 755 */ + { 69, 26, 14, 0, 26, 18432, 262, }, /* 756 */ + { 69, 26, 12, 0, -26, 18432, 264, }, /* 757 */ + { 69, 25, 14, 0, 0, 28672, 266, }, /* 758 */ + { 69, 26, 14, 0, 0, 28672, 268, }, /* 759 */ + { 69, 26, 14, 0, 0, 28672, 270, }, /* 760 */ + { 69, 25, 14, 0, 0, 28672, 268, }, /* 761 */ + { 69, 26, 14, 0, 0, 18432, 256, }, /* 762 */ + { 69, 26, 14, 0, 0, 28672, 272, }, /* 763 */ + { 88, 26, 12, 0, 0, 18432, 54, }, /* 764 */ + { 69, 26, 12, 0, 0, 28672, 216, }, /* 765 */ + { 35, 9, 12, 0, 48, 18432, 74, }, /* 766 */ + { 35, 5, 12, 0, -48, 18432, 76, }, /* 767 */ + { 0, 9, 12, 0, -10743, 18432, 74, }, /* 768 */ + { 0, 9, 12, 0, -3814, 18432, 74, }, /* 769 */ + { 0, 9, 12, 0, -10727, 18432, 74, }, /* 770 */ + { 0, 5, 12, 0, -10795, 18432, 76, }, /* 771 */ + { 0, 5, 12, 0, -10792, 18432, 76, }, /* 772 */ + { 0, 9, 12, 0, -10780, 18432, 74, }, /* 773 */ + { 0, 9, 12, 0, -10749, 18432, 74, }, /* 774 */ + { 0, 9, 12, 0, -10783, 18432, 74, }, /* 775 */ + { 0, 9, 12, 0, -10782, 18432, 74, }, /* 776 */ + { 0, 9, 12, 0, -10815, 18432, 74, }, /* 777 */ + { 34, 5, 12, 0, 0, 18432, 60, }, /* 778 */ + { 34, 26, 12, 0, 0, 28672, 68, }, /* 779 */ + { 34, 12, 3, 0, 0, 26624, 96, }, /* 780 */ + { 34, 21, 12, 0, 0, 28672, 68, }, /* 781 */ + { 34, 15, 12, 0, 0, 28672, 68, }, /* 782 */ + { 17, 5, 12, 0, -7264, 18432, 76, }, /* 783 */ + { 90, 7, 12, 0, 0, 18432, 82, }, /* 784 */ + { 90, 6, 12, 0, 0, 18432, 142, }, /* 785 */ + { 90, 21, 12, 0, 0, 18432, 68, }, /* 786 */ + { 90, 12, 3, 0, 0, 26624, 184, }, /* 787 */ + { 2, 12, 3, 0, 0, 26624, 130, }, /* 788 */ + { 69, 20, 12, 0, 0, 28672, 216, }, /* 789 */ + { 69, 19, 12, 0, 0, 28672, 216, }, /* 790 */ + { 69, 6, 12, 0, 0, 28672, 274, }, /* 791 */ + { 69, 21, 12, 0, 0, 28672, 276, }, /* 792 */ + { 69, 21, 12, 0, 0, 28726, 54, }, /* 793 */ + { 23, 26, 12, 0, 0, 28672, 278, }, /* 794 */ + { 69, 26, 12, 0, 0, 28672, 280, }, /* 795 */ + { 69, 26, 12, 0, 0, 28672, 282, }, /* 796 */ + { 69, 21, 12, 0, 0, 28825, 276, }, /* 797 */ + { 69, 21, 12, 0, 0, 28825, 212, }, /* 798 */ + { 69, 21, 12, 0, 0, 28819, 54, }, /* 799 */ + { 23, 6, 12, 0, 0, 18432, 136, }, /* 800 */ + { 69, 7, 12, 0, 0, 18447, 284, }, /* 801 */ + { 23, 14, 12, 0, 0, 18432, 284, }, /* 802 */ + { 69, 22, 12, 0, 0, 28825, 216, }, /* 803 */ + { 69, 18, 12, 0, 0, 28825, 216, }, /* 804 */ + { 69, 22, 12, 0, 0, 28825, 62, }, /* 805 */ + { 69, 18, 12, 0, 0, 28825, 62, }, /* 806 */ + { 69, 26, 12, 0, 0, 28819, 54, }, /* 807 */ + { 69, 17, 12, 0, 0, 28819, 202, }, /* 808 */ + { 69, 22, 12, 0, 0, 28819, 206, }, /* 809 */ + { 69, 18, 12, 0, 0, 28819, 206, }, /* 810 */ + { 84, 12, 3, 0, 0, 26669, 96, }, /* 811 */ + { 18, 10, 3, 0, 0, 18432, 286, }, /* 812 */ + { 69, 17, 14, 0, 0, 28819, 288, }, /* 813 */ + { 69, 6, 12, 0, 0, 18525, 136, }, /* 814 */ + { 69, 26, 12, 0, 0, 28819, 68, }, /* 815 */ + { 23, 6, 12, 0, 0, 18432, 142, }, /* 816 */ + { 69, 7, 12, 0, 0, 18564, 82, }, /* 817 */ + { 69, 21, 14, 0, 0, 28804, 236, }, /* 818 */ + { 69, 26, 12, 0, 0, 28687, 68, }, /* 819 */ + { 20, 7, 12, 0, 0, 18432, 82, }, /* 820 */ + { 84, 12, 3, 0, 0, 26717, 96, }, /* 821 */ + { 69, 24, 12, 0, 0, 28765, 290, }, /* 822 */ + { 20, 6, 12, 0, 0, 18432, 136, }, /* 823 */ + { 69, 17, 12, 0, 0, 28765, 126, }, /* 824 */ + { 21, 7, 12, 0, 0, 18432, 82, }, /* 825 */ + { 69, 21, 12, 0, 0, 28825, 68, }, /* 826 */ + { 69, 6, 12, 0, 0, 18525, 94, }, /* 827 */ + { 21, 6, 12, 0, 0, 18432, 136, }, /* 828 */ + { 22, 7, 12, 0, 0, 18432, 82, }, /* 829 */ + { 18, 7, 12, 0, 0, 18432, 82, }, /* 830 */ + { 18, 7, 12, 0, 0, 18432, 170, }, /* 831 */ + { 69, 26, 12, 0, 0, 18447, 68, }, /* 832 */ + { 69, 15, 12, 0, 0, 18447, 68, }, /* 833 */ + { 18, 26, 12, 0, 0, 18432, 68, }, /* 834 */ + { 18, 26, 12, 0, 0, 28672, 68, }, /* 835 */ + { 69, 15, 12, 0, 0, 18432, 68, }, /* 836 */ + { 69, 26, 14, 0, 0, 18447, 236, }, /* 837 */ + { 21, 26, 12, 0, 0, 18432, 68, }, /* 838 */ + { 23, 7, 12, 0, 0, 18432, 292, }, /* 839 */ + { 24, 7, 12, 0, 0, 18432, 82, }, /* 840 */ + { 24, 6, 12, 0, 0, 18432, 136, }, /* 841 */ + { 24, 26, 12, 0, 0, 28672, 68, }, /* 842 */ + { 111, 7, 12, 0, 0, 18432, 82, }, /* 843 */ + { 111, 6, 12, 0, 0, 18432, 142, }, /* 844 */ + { 111, 21, 12, 0, 0, 18432, 106, }, /* 845 */ + { 111, 21, 12, 0, 0, 18432, 124, }, /* 846 */ + { 99, 7, 12, 0, 0, 18432, 82, }, /* 847 */ + { 99, 6, 12, 0, 0, 18432, 136, }, /* 848 */ + { 99, 21, 12, 0, 0, 28672, 106, }, /* 849 */ + { 99, 21, 12, 0, 0, 28672, 124, }, /* 850 */ + { 99, 13, 12, 0, 0, 18432, 138, }, /* 851 */ + { 2, 9, 12, 108, 1, 18432, 74, }, /* 852 */ + { 2, 5, 12, 108, -35267, 18432, 76, }, /* 853 */ + { 2, 7, 12, 0, 0, 18432, 82, }, /* 854 */ + { 2, 21, 12, 0, 0, 28672, 68, }, /* 855 */ + { 2, 12, 3, 0, 0, 26624, 96, }, /* 856 */ + { 2, 6, 12, 0, 0, 28672, 92, }, /* 857 */ + { 2, 6, 12, 0, 0, 18432, 88, }, /* 858 */ + { 112, 7, 12, 0, 0, 18432, 82, }, /* 859 */ + { 112, 14, 12, 0, 0, 18432, 82, }, /* 860 */ + { 112, 12, 3, 0, 0, 26624, 96, }, /* 861 */ + { 112, 21, 12, 0, 0, 18432, 68, }, /* 862 */ + { 112, 21, 12, 0, 0, 18432, 124, }, /* 863 */ + { 112, 21, 12, 0, 0, 18432, 106, }, /* 864 */ + { 69, 24, 12, 0, 0, 28762, 56, }, /* 865 */ + { 0, 9, 12, 0, -35332, 18432, 74, }, /* 866 */ + { 69, 24, 12, 0, 0, 18432, 56, }, /* 867 */ + { 0, 9, 12, 0, -42280, 18432, 74, }, /* 868 */ + { 0, 5, 12, 0, 48, 18432, 76, }, /* 869 */ + { 0, 9, 12, 0, -42308, 18432, 74, }, /* 870 */ + { 0, 9, 12, 0, -42319, 18432, 74, }, /* 871 */ + { 0, 9, 12, 0, -42315, 18432, 74, }, /* 872 */ + { 0, 9, 12, 0, -42305, 18432, 74, }, /* 873 */ + { 0, 9, 12, 0, -42258, 18432, 74, }, /* 874 */ + { 0, 9, 12, 0, -42282, 18432, 74, }, /* 875 */ + { 0, 9, 12, 0, -42261, 18432, 74, }, /* 876 */ + { 0, 9, 12, 0, 928, 18432, 74, }, /* 877 */ + { 0, 9, 12, 0, -48, 18432, 74, }, /* 878 */ + { 0, 9, 12, 0, -42307, 18432, 74, }, /* 879 */ + { 0, 9, 12, 0, -35384, 18432, 74, }, /* 880 */ + { 36, 7, 12, 0, 0, 18432, 82, }, /* 881 */ + { 36, 12, 3, 0, 0, 26624, 130, }, /* 882 */ + { 36, 12, 3, 0, 0, 26624, 184, }, /* 883 */ + { 36, 10, 5, 0, 0, 18432, 144, }, /* 884 */ + { 36, 26, 12, 0, 0, 28672, 68, }, /* 885 */ + { 69, 15, 12, 0, 0, 18612, 68, }, /* 886 */ + { 69, 15, 12, 0, 0, 18609, 68, }, /* 887 */ + { 69, 26, 12, 0, 0, 18600, 68, }, /* 888 */ + { 69, 23, 12, 0, 0, 14504, 68, }, /* 889 */ + { 69, 26, 12, 0, 0, 14504, 68, }, /* 890 */ + { 37, 7, 12, 0, 0, 18432, 82, }, /* 891 */ + { 37, 21, 12, 0, 0, 28672, 68, }, /* 892 */ + { 37, 21, 12, 0, 0, 28672, 124, }, /* 893 */ + { 100, 10, 5, 0, 0, 18432, 144, }, /* 894 */ + { 100, 7, 12, 0, 0, 18432, 82, }, /* 895 */ + { 100, 12, 3, 0, 0, 26624, 146, }, /* 896 */ + { 100, 12, 3, 0, 0, 26624, 130, }, /* 897 */ + { 100, 21, 12, 0, 0, 18432, 124, }, /* 898 */ + { 100, 13, 12, 0, 0, 18432, 138, }, /* 899 */ + { 6, 12, 3, 0, 0, 26666, 96, }, /* 900 */ + { 6, 7, 12, 0, 0, 18507, 82, }, /* 901 */ + { 39, 13, 12, 0, 0, 18432, 138, }, /* 902 */ + { 39, 7, 12, 0, 0, 18432, 82, }, /* 903 */ + { 39, 12, 3, 0, 0, 26624, 130, }, /* 904 */ + { 39, 12, 3, 0, 0, 26624, 96, }, /* 905 */ + { 69, 21, 12, 0, 0, 18567, 190, }, /* 906 */ + { 39, 21, 12, 0, 0, 18432, 124, }, /* 907 */ + { 101, 7, 12, 0, 0, 18432, 82, }, /* 908 */ + { 101, 12, 3, 0, 0, 26624, 130, }, /* 909 */ + { 101, 10, 5, 0, 0, 18432, 144, }, /* 910 */ + { 101, 10, 5, 0, 0, 18432, 174, }, /* 911 */ + { 101, 21, 12, 0, 0, 18432, 68, }, /* 912 */ + { 40, 12, 3, 0, 0, 26624, 130, }, /* 913 */ + { 40, 10, 5, 0, 0, 18432, 144, }, /* 914 */ + { 40, 7, 12, 0, 0, 18432, 82, }, /* 915 */ + { 40, 12, 3, 0, 0, 26624, 96, }, /* 916 */ + { 40, 10, 5, 0, 0, 18432, 174, }, /* 917 */ + { 40, 21, 12, 0, 0, 18432, 68, }, /* 918 */ + { 40, 21, 12, 0, 0, 18432, 106, }, /* 919 */ + { 40, 21, 12, 0, 0, 18432, 124, }, /* 920 */ + { 69, 6, 12, 0, 0, 18480, 136, }, /* 921 */ + { 40, 13, 12, 0, 0, 18432, 138, }, /* 922 */ + { 16, 6, 12, 0, 0, 18432, 136, }, /* 923 */ + { 105, 7, 12, 0, 0, 18432, 82, }, /* 924 */ + { 105, 12, 3, 0, 0, 26624, 130, }, /* 925 */ + { 105, 10, 5, 0, 0, 18432, 144, }, /* 926 */ + { 105, 13, 12, 0, 0, 18432, 138, }, /* 927 */ + { 105, 21, 12, 0, 0, 18432, 68, }, /* 928 */ + { 105, 21, 12, 0, 0, 18432, 124, }, /* 929 */ + { 107, 7, 12, 0, 0, 18432, 82, }, /* 930 */ + { 107, 12, 3, 0, 0, 26624, 130, }, /* 931 */ + { 107, 7, 12, 0, 0, 18432, 156, }, /* 932 */ + { 107, 12, 3, 0, 0, 26624, 96, }, /* 933 */ + { 107, 7, 12, 0, 0, 18432, 294, }, /* 934 */ + { 107, 6, 12, 0, 0, 18432, 136, }, /* 935 */ + { 107, 21, 12, 0, 0, 18432, 68, }, /* 936 */ + { 107, 21, 12, 0, 0, 18432, 106, }, /* 937 */ + { 113, 7, 12, 0, 0, 18432, 82, }, /* 938 */ + { 113, 10, 5, 0, 0, 18432, 144, }, /* 939 */ + { 113, 12, 3, 0, 0, 26624, 130, }, /* 940 */ + { 113, 21, 12, 0, 0, 18432, 124, }, /* 941 */ + { 113, 6, 12, 0, 0, 18432, 136, }, /* 942 */ + { 113, 12, 3, 0, 0, 26624, 146, }, /* 943 */ + { 0, 5, 12, 0, -928, 18432, 76, }, /* 944 */ + { 76, 5, 12, 0, -38864, 18432, 70, }, /* 945 */ + { 113, 10, 5, 0, 0, 18432, 160, }, /* 946 */ + { 113, 13, 12, 0, 0, 18432, 138, }, /* 947 */ + { 18, 7, 9, 0, 0, 18432, 82, }, /* 948 */ + { 18, 7, 10, 0, 0, 18432, 82, }, /* 949 */ + { 68, 4, 12, 0, 0, 18432, 0, }, /* 950 */ + { 68, 3, 12, 0, 0, 18432, 0, }, /* 951 */ + { 23, 7, 12, 0, 0, 18432, 284, }, /* 952 */ + { 71, 25, 12, 0, 0, 12288, 118, }, /* 953 */ + { 3, 7, 12, 0, 0, 0, 296, }, /* 954 */ + { 69, 18, 12, 0, 0, 28705, 54, }, /* 955 */ + { 69, 22, 12, 0, 0, 28705, 54, }, /* 956 */ + { 68, 2, 12, 0, 0, 6144, 298, }, /* 957 */ + { 3, 7, 12, 0, 0, 39, 82, }, /* 958 */ + { 3, 26, 12, 0, 0, 28711, 68, }, /* 959 */ + { 84, 12, 3, 0, 0, 26624, 180, }, /* 960 */ + { 84, 12, 3, 0, 0, 26624, 300, }, /* 961 */ + { 69, 21, 12, 0, 0, 28672, 68, }, /* 962 */ + { 69, 21, 12, 0, 0, 28672, 122, }, /* 963 */ + { 69, 22, 12, 0, 0, 28672, 68, }, /* 964 */ + { 69, 18, 12, 0, 0, 28672, 68, }, /* 965 */ + { 69, 17, 12, 0, 0, 28672, 126, }, /* 966 */ + { 69, 22, 12, 0, 0, 28672, 302, }, /* 967 */ + { 69, 18, 12, 0, 0, 28672, 302, }, /* 968 */ + { 69, 21, 12, 0, 0, 8192, 106, }, /* 969 */ + { 69, 21, 12, 0, 0, 8192, 304, }, /* 970 */ + { 69, 21, 12, 0, 0, 8192, 306, }, /* 971 */ + { 69, 21, 12, 0, 0, 28672, 124, }, /* 972 */ + { 69, 22, 12, 0, 0, 28672, 158, }, /* 973 */ + { 69, 18, 12, 0, 0, 28672, 158, }, /* 974 */ + { 69, 21, 12, 0, 0, 14336, 68, }, /* 975 */ + { 69, 21, 12, 0, 0, 28672, 118, }, /* 976 */ + { 69, 17, 12, 0, 0, 12288, 224, }, /* 977 */ + { 69, 25, 12, 0, 0, 28672, 226, }, /* 978 */ + { 69, 21, 12, 0, 0, 28672, 302, }, /* 979 */ + { 69, 21, 12, 0, 0, 28672, 308, }, /* 980 */ + { 69, 17, 12, 0, 0, 12288, 126, }, /* 981 */ + { 69, 21, 12, 0, 0, 8192, 68, }, /* 982 */ + { 69, 13, 12, 0, 0, 10240, 310, }, /* 983 */ + { 0, 9, 12, 0, 32, 18432, 312, }, /* 984 */ + { 69, 24, 12, 0, 0, 28672, 314, }, /* 985 */ + { 0, 5, 12, 0, -32, 18432, 316, }, /* 986 */ + { 69, 21, 12, 0, 0, 28825, 124, }, /* 987 */ + { 69, 22, 12, 0, 0, 28825, 318, }, /* 988 */ + { 69, 18, 12, 0, 0, 28825, 318, }, /* 989 */ + { 69, 21, 12, 0, 0, 28825, 106, }, /* 990 */ + { 69, 6, 3, 0, 0, 18525, 320, }, /* 991 */ + { 69, 1, 2, 0, 0, 28672, 322, }, /* 992 */ + { 31, 7, 12, 0, 0, 18432, 82, }, /* 993 */ + { 69, 21, 12, 0, 0, 18552, 68, }, /* 994 */ + { 69, 21, 12, 0, 0, 28792, 68, }, /* 995 */ + { 69, 21, 12, 0, 0, 18483, 68, }, /* 996 */ + { 69, 15, 12, 0, 0, 18555, 68, }, /* 997 */ + { 69, 26, 12, 0, 0, 18483, 68, }, /* 998 */ + { 1, 14, 12, 0, 0, 28672, 82, }, /* 999 */ + { 1, 15, 12, 0, 0, 28672, 68, }, /* 1000 */ + { 1, 26, 12, 0, 0, 28672, 68, }, /* 1001 */ + { 1, 26, 12, 0, 0, 18432, 68, }, /* 1002 */ + { 102, 7, 12, 0, 0, 18432, 82, }, /* 1003 */ + { 103, 7, 12, 0, 0, 18432, 82, }, /* 1004 */ + { 84, 12, 3, 0, 0, 26651, 96, }, /* 1005 */ + { 69, 15, 12, 0, 0, 10267, 68, }, /* 1006 */ + { 81, 7, 12, 0, 0, 18432, 82, }, /* 1007 */ + { 81, 15, 12, 0, 0, 18432, 68, }, /* 1008 */ + { 82, 7, 12, 0, 0, 18432, 82, }, /* 1009 */ + { 82, 14, 12, 0, 0, 18432, 82, }, /* 1010 */ + { 53, 7, 12, 0, 0, 18432, 82, }, /* 1011 */ + { 53, 12, 3, 0, 0, 26624, 130, }, /* 1012 */ + { 85, 7, 12, 0, 0, 18432, 82, }, /* 1013 */ + { 85, 21, 12, 0, 0, 18432, 106, }, /* 1014 */ + { 91, 7, 12, 0, 0, 18432, 82, }, /* 1015 */ + { 91, 21, 12, 0, 0, 18432, 106, }, /* 1016 */ + { 91, 14, 12, 0, 0, 18432, 82, }, /* 1017 */ + { 83, 9, 12, 0, 40, 18432, 74, }, /* 1018 */ + { 83, 5, 12, 0, -40, 18432, 76, }, /* 1019 */ + { 86, 7, 12, 0, 0, 18432, 82, }, /* 1020 */ + { 87, 7, 12, 0, 0, 18432, 82, }, /* 1021 */ + { 87, 13, 12, 0, 0, 18432, 138, }, /* 1022 */ + { 145, 9, 12, 0, 40, 18432, 74, }, /* 1023 */ + { 145, 5, 12, 0, -40, 18432, 76, }, /* 1024 */ + { 127, 7, 12, 0, 0, 18432, 82, }, /* 1025 */ + { 125, 7, 12, 0, 0, 18432, 82, }, /* 1026 */ + { 125, 21, 12, 0, 0, 18432, 68, }, /* 1027 */ + { 161, 9, 12, 0, 39, 18432, 74, }, /* 1028 */ + { 161, 5, 12, 0, -39, 18432, 76, }, /* 1029 */ + { 49, 7, 12, 0, 0, 18432, 82, }, /* 1030 */ + { 0, 6, 12, 0, 0, 18432, 94, }, /* 1031 */ + { 32, 7, 12, 0, 0, 34816, 82, }, /* 1032 */ + { 114, 7, 12, 0, 0, 34816, 82, }, /* 1033 */ + { 114, 21, 12, 0, 0, 34816, 106, }, /* 1034 */ + { 114, 15, 12, 0, 0, 34816, 68, }, /* 1035 */ + { 133, 7, 12, 0, 0, 34816, 82, }, /* 1036 */ + { 133, 26, 12, 0, 0, 34816, 68, }, /* 1037 */ + { 133, 15, 12, 0, 0, 34816, 68, }, /* 1038 */ + { 132, 7, 12, 0, 0, 34816, 82, }, /* 1039 */ + { 132, 15, 12, 0, 0, 34816, 68, }, /* 1040 */ + { 139, 7, 12, 0, 0, 34816, 82, }, /* 1041 */ + { 139, 15, 12, 0, 0, 34816, 68, }, /* 1042 */ + { 95, 7, 12, 0, 0, 34816, 82, }, /* 1043 */ + { 95, 15, 12, 0, 0, 34816, 68, }, /* 1044 */ + { 95, 21, 12, 0, 0, 28672, 106, }, /* 1045 */ + { 104, 7, 12, 0, 0, 34816, 82, }, /* 1046 */ + { 104, 21, 12, 0, 0, 34816, 68, }, /* 1047 */ + { 122, 7, 12, 0, 0, 34816, 82, }, /* 1048 */ + { 121, 7, 12, 0, 0, 34816, 82, }, /* 1049 */ + { 121, 15, 12, 0, 0, 34816, 68, }, /* 1050 */ + { 92, 7, 12, 0, 0, 34816, 82, }, /* 1051 */ + { 92, 12, 3, 0, 0, 26624, 130, }, /* 1052 */ + { 92, 12, 3, 0, 0, 26624, 102, }, /* 1053 */ + { 92, 12, 3, 0, 0, 26624, 184, }, /* 1054 */ + { 92, 15, 12, 0, 0, 34816, 68, }, /* 1055 */ + { 92, 21, 12, 0, 0, 34816, 68, }, /* 1056 */ + { 92, 21, 12, 0, 0, 34816, 124, }, /* 1057 */ + { 115, 7, 12, 0, 0, 34816, 82, }, /* 1058 */ + { 115, 15, 12, 0, 0, 34816, 68, }, /* 1059 */ + { 115, 21, 12, 0, 0, 34816, 68, }, /* 1060 */ + { 131, 7, 12, 0, 0, 34816, 82, }, /* 1061 */ + { 131, 15, 12, 0, 0, 34816, 68, }, /* 1062 */ + { 51, 7, 12, 0, 0, 34816, 82, }, /* 1063 */ + { 51, 26, 12, 0, 0, 34816, 68, }, /* 1064 */ + { 51, 12, 3, 0, 0, 26624, 96, }, /* 1065 */ + { 51, 15, 12, 0, 0, 34816, 68, }, /* 1066 */ + { 51, 21, 12, 0, 0, 34816, 106, }, /* 1067 */ + { 51, 21, 12, 0, 0, 34918, 106, }, /* 1068 */ + { 51, 21, 12, 0, 0, 34816, 68, }, /* 1069 */ + { 108, 7, 12, 0, 0, 34816, 82, }, /* 1070 */ + { 108, 21, 12, 0, 0, 28672, 68, }, /* 1071 */ + { 108, 21, 12, 0, 0, 28672, 106, }, /* 1072 */ + { 116, 7, 12, 0, 0, 34816, 82, }, /* 1073 */ + { 116, 15, 12, 0, 0, 34816, 68, }, /* 1074 */ + { 117, 7, 12, 0, 0, 34816, 82, }, /* 1075 */ + { 117, 15, 12, 0, 0, 34816, 68, }, /* 1076 */ + { 54, 7, 12, 0, 0, 34816, 82, }, /* 1077 */ + { 54, 21, 12, 0, 0, 34816, 106, }, /* 1078 */ + { 54, 15, 12, 0, 0, 34816, 68, }, /* 1079 */ + { 118, 7, 12, 0, 0, 34816, 82, }, /* 1080 */ + { 140, 9, 12, 0, 64, 34816, 74, }, /* 1081 */ + { 140, 5, 12, 0, -64, 34816, 76, }, /* 1082 */ + { 140, 15, 12, 0, 0, 34816, 68, }, /* 1083 */ + { 62, 7, 12, 0, 0, 0, 82, }, /* 1084 */ + { 62, 7, 12, 0, 0, 0, 294, }, /* 1085 */ + { 62, 12, 3, 0, 0, 26624, 128, }, /* 1086 */ + { 62, 13, 12, 0, 0, 2048, 138, }, /* 1087 */ + { 3, 15, 12, 0, 0, 2048, 68, }, /* 1088 */ + { 65, 7, 12, 0, 0, 34816, 82, }, /* 1089 */ + { 65, 12, 3, 0, 0, 26624, 130, }, /* 1090 */ + { 65, 17, 12, 0, 0, 34816, 126, }, /* 1091 */ + { 152, 7, 12, 0, 0, 34816, 82, }, /* 1092 */ + { 152, 15, 12, 0, 0, 34816, 68, }, /* 1093 */ + { 63, 7, 12, 0, 0, 0, 82, }, /* 1094 */ + { 63, 12, 3, 0, 0, 26624, 96, }, /* 1095 */ + { 63, 15, 12, 0, 0, 0, 68, }, /* 1096 */ + { 63, 21, 12, 0, 0, 0, 124, }, /* 1097 */ + { 67, 7, 12, 0, 0, 34816, 82, }, /* 1098 */ + { 67, 12, 3, 0, 0, 26624, 96, }, /* 1099 */ + { 67, 21, 12, 0, 0, 34816, 124, }, /* 1100 */ + { 156, 7, 12, 0, 0, 34816, 82, }, /* 1101 */ + { 156, 15, 12, 0, 0, 34816, 68, }, /* 1102 */ + { 153, 7, 12, 0, 0, 34816, 82, }, /* 1103 */ + { 120, 10, 5, 0, 0, 18432, 144, }, /* 1104 */ + { 120, 12, 3, 0, 0, 26624, 130, }, /* 1105 */ + { 120, 7, 12, 0, 0, 18432, 82, }, /* 1106 */ + { 120, 12, 3, 0, 0, 26624, 146, }, /* 1107 */ + { 120, 21, 12, 0, 0, 18432, 124, }, /* 1108 */ + { 120, 21, 12, 0, 0, 18432, 106, }, /* 1109 */ + { 120, 15, 12, 0, 0, 28672, 68, }, /* 1110 */ + { 120, 13, 12, 0, 0, 18432, 138, }, /* 1111 */ + { 120, 12, 3, 0, 0, 26624, 184, }, /* 1112 */ + { 41, 12, 3, 0, 0, 26624, 130, }, /* 1113 */ + { 41, 10, 5, 0, 0, 18432, 144, }, /* 1114 */ + { 41, 7, 12, 0, 0, 18432, 82, }, /* 1115 */ + { 41, 12, 3, 0, 0, 26624, 146, }, /* 1116 */ + { 41, 12, 3, 0, 0, 26624, 96, }, /* 1117 */ + { 41, 21, 12, 0, 0, 18432, 68, }, /* 1118 */ + { 41, 1, 4, 0, 0, 18432, 132, }, /* 1119 */ + { 41, 21, 12, 0, 0, 18432, 124, }, /* 1120 */ + { 124, 7, 12, 0, 0, 18432, 82, }, /* 1121 */ + { 124, 13, 12, 0, 0, 18432, 138, }, /* 1122 */ + { 43, 12, 3, 0, 0, 26624, 130, }, /* 1123 */ + { 43, 7, 12, 0, 0, 18432, 82, }, /* 1124 */ + { 43, 10, 5, 0, 0, 18432, 144, }, /* 1125 */ + { 43, 12, 3, 0, 0, 26624, 146, }, /* 1126 */ + { 43, 13, 12, 0, 0, 18432, 138, }, /* 1127 */ + { 43, 21, 12, 0, 0, 18432, 68, }, /* 1128 */ + { 43, 21, 12, 0, 0, 18432, 124, }, /* 1129 */ + { 50, 7, 12, 0, 0, 18432, 82, }, /* 1130 */ + { 50, 12, 3, 0, 0, 26624, 96, }, /* 1131 */ + { 50, 21, 12, 0, 0, 18432, 68, }, /* 1132 */ + { 44, 12, 3, 0, 0, 26624, 130, }, /* 1133 */ + { 44, 10, 5, 0, 0, 18432, 144, }, /* 1134 */ + { 44, 7, 12, 0, 0, 18432, 82, }, /* 1135 */ + { 44, 10, 5, 0, 0, 18432, 174, }, /* 1136 */ + { 44, 7, 4, 0, 0, 18432, 82, }, /* 1137 */ + { 44, 21, 12, 0, 0, 18432, 124, }, /* 1138 */ + { 44, 21, 12, 0, 0, 18432, 68, }, /* 1139 */ + { 44, 12, 3, 0, 0, 26624, 102, }, /* 1140 */ + { 44, 12, 3, 0, 0, 26624, 96, }, /* 1141 */ + { 44, 13, 12, 0, 0, 18432, 138, }, /* 1142 */ + { 15, 15, 12, 0, 0, 18432, 68, }, /* 1143 */ + { 48, 7, 12, 0, 0, 18432, 82, }, /* 1144 */ + { 48, 10, 5, 0, 0, 18432, 144, }, /* 1145 */ + { 48, 12, 3, 0, 0, 26624, 130, }, /* 1146 */ + { 48, 10, 5, 0, 0, 18432, 174, }, /* 1147 */ + { 48, 12, 3, 0, 0, 26624, 96, }, /* 1148 */ + { 48, 21, 12, 0, 0, 18432, 124, }, /* 1149 */ + { 48, 21, 12, 0, 0, 18432, 106, }, /* 1150 */ + { 48, 21, 12, 0, 0, 18432, 68, }, /* 1151 */ + { 57, 7, 12, 0, 0, 18432, 82, }, /* 1152 */ + { 57, 21, 12, 0, 0, 18432, 124, }, /* 1153 */ + { 55, 7, 12, 0, 0, 18432, 82, }, /* 1154 */ + { 55, 12, 3, 0, 0, 26624, 130, }, /* 1155 */ + { 55, 10, 5, 0, 0, 18432, 144, }, /* 1156 */ + { 55, 12, 3, 0, 0, 26624, 96, }, /* 1157 */ + { 55, 12, 3, 0, 0, 26624, 146, }, /* 1158 */ + { 55, 13, 12, 0, 0, 18432, 138, }, /* 1159 */ + { 47, 12, 3, 0, 0, 26624, 130, }, /* 1160 */ + { 47, 12, 3, 0, 0, 26705, 130, }, /* 1161 */ + { 47, 10, 5, 0, 0, 18432, 144, }, /* 1162 */ + { 47, 10, 5, 0, 0, 18513, 144, }, /* 1163 */ + { 47, 7, 12, 0, 0, 18432, 82, }, /* 1164 */ + { 84, 12, 3, 0, 0, 26705, 102, }, /* 1165 */ + { 47, 12, 3, 0, 0, 26705, 96, }, /* 1166 */ + { 47, 10, 3, 0, 0, 18432, 148, }, /* 1167 */ + { 47, 10, 5, 0, 0, 18432, 174, }, /* 1168 */ + { 47, 7, 12, 0, 0, 18432, 324, }, /* 1169 */ + { 47, 12, 3, 0, 0, 26624, 96, }, /* 1170 */ + { 144, 7, 12, 0, 0, 18432, 82, }, /* 1171 */ + { 144, 10, 5, 0, 0, 18432, 144, }, /* 1172 */ + { 144, 12, 3, 0, 0, 26624, 130, }, /* 1173 */ + { 144, 12, 3, 0, 0, 26624, 146, }, /* 1174 */ + { 144, 12, 3, 0, 0, 26624, 96, }, /* 1175 */ + { 144, 21, 12, 0, 0, 18432, 124, }, /* 1176 */ + { 144, 21, 12, 0, 0, 18432, 106, }, /* 1177 */ + { 144, 21, 12, 0, 0, 18432, 68, }, /* 1178 */ + { 144, 13, 12, 0, 0, 18432, 138, }, /* 1179 */ + { 144, 12, 3, 0, 0, 26624, 102, }, /* 1180 */ + { 56, 7, 12, 0, 0, 18432, 82, }, /* 1181 */ + { 56, 10, 3, 0, 0, 18432, 148, }, /* 1182 */ + { 56, 10, 5, 0, 0, 18432, 144, }, /* 1183 */ + { 56, 12, 3, 0, 0, 26624, 130, }, /* 1184 */ + { 56, 12, 3, 0, 0, 26624, 146, }, /* 1185 */ + { 56, 12, 3, 0, 0, 26624, 96, }, /* 1186 */ + { 56, 21, 12, 0, 0, 18432, 68, }, /* 1187 */ + { 56, 13, 12, 0, 0, 18432, 138, }, /* 1188 */ + { 135, 7, 12, 0, 0, 18432, 82, }, /* 1189 */ + { 135, 10, 3, 0, 0, 18432, 148, }, /* 1190 */ + { 135, 10, 5, 0, 0, 18432, 144, }, /* 1191 */ + { 135, 12, 3, 0, 0, 26624, 130, }, /* 1192 */ + { 135, 12, 3, 0, 0, 26624, 146, }, /* 1193 */ + { 135, 12, 3, 0, 0, 26624, 96, }, /* 1194 */ + { 135, 21, 12, 0, 0, 18432, 68, }, /* 1195 */ + { 135, 21, 12, 0, 0, 18432, 124, }, /* 1196 */ + { 135, 21, 12, 0, 0, 18432, 106, }, /* 1197 */ + { 135, 21, 12, 0, 0, 18432, 178, }, /* 1198 */ + { 52, 7, 12, 0, 0, 18432, 82, }, /* 1199 */ + { 52, 10, 5, 0, 0, 18432, 144, }, /* 1200 */ + { 52, 12, 3, 0, 0, 26624, 130, }, /* 1201 */ + { 52, 12, 3, 0, 0, 26624, 146, }, /* 1202 */ + { 52, 21, 12, 0, 0, 18432, 124, }, /* 1203 */ + { 52, 21, 12, 0, 0, 18432, 68, }, /* 1204 */ + { 52, 13, 12, 0, 0, 18432, 138, }, /* 1205 */ + { 45, 7, 12, 0, 0, 18432, 82, }, /* 1206 */ + { 45, 12, 3, 0, 0, 26624, 130, }, /* 1207 */ + { 45, 10, 5, 0, 0, 18432, 144, }, /* 1208 */ + { 45, 10, 5, 0, 0, 18432, 174, }, /* 1209 */ + { 45, 12, 3, 0, 0, 26624, 96, }, /* 1210 */ + { 45, 21, 12, 0, 0, 18432, 68, }, /* 1211 */ + { 45, 13, 12, 0, 0, 18432, 138, }, /* 1212 */ + { 137, 7, 12, 0, 0, 18432, 82, }, /* 1213 */ + { 137, 12, 3, 0, 0, 26624, 130, }, /* 1214 */ + { 137, 10, 12, 0, 0, 18432, 144, }, /* 1215 */ + { 137, 10, 5, 0, 0, 18432, 144, }, /* 1216 */ + { 137, 12, 3, 0, 0, 26624, 146, }, /* 1217 */ + { 137, 13, 12, 0, 0, 18432, 138, }, /* 1218 */ + { 137, 15, 12, 0, 0, 18432, 68, }, /* 1219 */ + { 137, 21, 12, 0, 0, 18432, 124, }, /* 1220 */ + { 137, 26, 12, 0, 0, 18432, 68, }, /* 1221 */ + { 60, 7, 12, 0, 0, 18432, 82, }, /* 1222 */ + { 60, 10, 5, 0, 0, 18432, 144, }, /* 1223 */ + { 60, 12, 3, 0, 0, 26624, 130, }, /* 1224 */ + { 60, 12, 3, 0, 0, 26624, 146, }, /* 1225 */ + { 60, 12, 3, 0, 0, 26624, 96, }, /* 1226 */ + { 60, 21, 12, 0, 0, 18432, 68, }, /* 1227 */ + { 136, 9, 12, 0, 32, 18432, 74, }, /* 1228 */ + { 136, 5, 12, 0, -32, 18432, 76, }, /* 1229 */ + { 136, 13, 12, 0, 0, 18432, 138, }, /* 1230 */ + { 136, 15, 12, 0, 0, 18432, 68, }, /* 1231 */ + { 136, 7, 12, 0, 0, 18432, 82, }, /* 1232 */ + { 157, 7, 12, 0, 0, 18432, 82, }, /* 1233 */ + { 157, 10, 3, 0, 0, 18432, 148, }, /* 1234 */ + { 157, 10, 5, 0, 0, 18432, 144, }, /* 1235 */ + { 157, 12, 3, 0, 0, 26624, 130, }, /* 1236 */ + { 157, 10, 5, 0, 0, 18432, 174, }, /* 1237 */ + { 157, 12, 3, 0, 0, 26624, 146, }, /* 1238 */ + { 157, 7, 4, 0, 0, 18432, 82, }, /* 1239 */ + { 157, 12, 3, 0, 0, 26624, 96, }, /* 1240 */ + { 157, 21, 12, 0, 0, 18432, 124, }, /* 1241 */ + { 157, 21, 12, 0, 0, 18432, 68, }, /* 1242 */ + { 157, 13, 12, 0, 0, 18432, 138, }, /* 1243 */ + { 64, 7, 12, 0, 0, 18432, 82, }, /* 1244 */ + { 64, 10, 5, 0, 0, 18432, 144, }, /* 1245 */ + { 64, 12, 3, 0, 0, 26624, 130, }, /* 1246 */ + { 64, 12, 3, 0, 0, 26624, 146, }, /* 1247 */ + { 64, 21, 12, 0, 0, 18432, 68, }, /* 1248 */ + { 149, 7, 12, 0, 0, 18432, 82, }, /* 1249 */ + { 149, 12, 3, 0, 0, 26624, 130, }, /* 1250 */ + { 149, 12, 3, 0, 0, 18432, 130, }, /* 1251 */ + { 149, 12, 3, 0, 0, 26624, 102, }, /* 1252 */ + { 149, 12, 3, 0, 0, 26624, 146, }, /* 1253 */ + { 149, 10, 5, 0, 0, 18432, 144, }, /* 1254 */ + { 149, 7, 4, 0, 0, 18432, 82, }, /* 1255 */ + { 149, 21, 12, 0, 0, 18432, 68, }, /* 1256 */ + { 149, 21, 12, 0, 0, 18432, 124, }, /* 1257 */ + { 148, 7, 12, 0, 0, 18432, 82, }, /* 1258 */ + { 148, 12, 3, 0, 0, 26624, 130, }, /* 1259 */ + { 148, 10, 5, 0, 0, 18432, 144, }, /* 1260 */ + { 148, 7, 4, 0, 0, 18432, 82, }, /* 1261 */ + { 148, 12, 3, 0, 0, 26624, 326, }, /* 1262 */ + { 148, 12, 3, 0, 0, 26624, 146, }, /* 1263 */ + { 148, 21, 12, 0, 0, 18432, 68, }, /* 1264 */ + { 148, 21, 12, 0, 0, 18432, 124, }, /* 1265 */ + { 148, 21, 12, 0, 0, 18432, 106, }, /* 1266 */ + { 134, 7, 12, 0, 0, 18432, 82, }, /* 1267 */ + { 142, 7, 12, 0, 0, 18432, 82, }, /* 1268 */ + { 142, 10, 5, 0, 0, 18432, 144, }, /* 1269 */ + { 142, 12, 3, 0, 0, 26624, 130, }, /* 1270 */ + { 142, 12, 3, 0, 0, 18432, 146, }, /* 1271 */ + { 142, 21, 12, 0, 0, 18432, 124, }, /* 1272 */ + { 142, 21, 12, 0, 0, 18432, 106, }, /* 1273 */ + { 142, 21, 12, 0, 0, 18432, 68, }, /* 1274 */ + { 142, 13, 12, 0, 0, 18432, 138, }, /* 1275 */ + { 142, 15, 12, 0, 0, 18432, 68, }, /* 1276 */ + { 143, 21, 12, 0, 0, 18432, 68, }, /* 1277 */ + { 143, 21, 12, 0, 0, 18432, 106, }, /* 1278 */ + { 143, 7, 12, 0, 0, 18432, 82, }, /* 1279 */ + { 143, 12, 3, 0, 0, 26624, 130, }, /* 1280 */ + { 143, 10, 5, 0, 0, 18432, 144, }, /* 1281 */ + { 59, 7, 12, 0, 0, 18432, 82, }, /* 1282 */ + { 59, 12, 3, 0, 0, 26624, 130, }, /* 1283 */ + { 59, 12, 3, 0, 0, 26624, 96, }, /* 1284 */ + { 59, 12, 3, 0, 0, 26624, 146, }, /* 1285 */ + { 59, 7, 4, 0, 0, 18432, 82, }, /* 1286 */ + { 59, 13, 12, 0, 0, 18432, 138, }, /* 1287 */ + { 61, 7, 12, 0, 0, 18432, 82, }, /* 1288 */ + { 61, 10, 5, 0, 0, 18432, 144, }, /* 1289 */ + { 61, 12, 3, 0, 0, 26624, 130, }, /* 1290 */ + { 61, 12, 3, 0, 0, 26624, 146, }, /* 1291 */ + { 61, 13, 12, 0, 0, 18432, 138, }, /* 1292 */ + { 150, 7, 12, 0, 0, 18432, 82, }, /* 1293 */ + { 150, 12, 3, 0, 0, 26624, 130, }, /* 1294 */ + { 150, 10, 5, 0, 0, 18432, 144, }, /* 1295 */ + { 150, 21, 12, 0, 0, 18432, 124, }, /* 1296 */ + { 162, 12, 3, 0, 0, 26624, 130, }, /* 1297 */ + { 162, 7, 4, 0, 0, 18432, 82, }, /* 1298 */ + { 162, 10, 5, 0, 0, 18432, 144, }, /* 1299 */ + { 162, 7, 12, 0, 0, 18432, 82, }, /* 1300 */ + { 162, 10, 5, 0, 0, 18432, 176, }, /* 1301 */ + { 162, 12, 3, 0, 0, 26624, 184, }, /* 1302 */ + { 162, 21, 12, 0, 0, 18432, 124, }, /* 1303 */ + { 162, 21, 12, 0, 0, 18432, 68, }, /* 1304 */ + { 162, 13, 12, 0, 0, 18432, 138, }, /* 1305 */ + { 11, 15, 12, 0, 0, 18432, 68, }, /* 1306 */ + { 11, 21, 12, 0, 0, 18432, 68, }, /* 1307 */ + { 94, 7, 12, 0, 0, 18432, 82, }, /* 1308 */ + { 94, 14, 12, 0, 0, 18432, 82, }, /* 1309 */ + { 94, 21, 12, 0, 0, 18432, 106, }, /* 1310 */ + { 66, 7, 12, 0, 0, 18432, 82, }, /* 1311 */ + { 66, 21, 12, 0, 0, 18432, 68, }, /* 1312 */ + { 109, 7, 12, 0, 0, 18432, 82, }, /* 1313 */ + { 109, 1, 2, 0, 0, 18432, 322, }, /* 1314 */ + { 109, 12, 3, 0, 0, 26624, 102, }, /* 1315 */ + { 109, 12, 3, 0, 0, 26624, 96, }, /* 1316 */ + { 138, 7, 12, 0, 0, 18432, 82, }, /* 1317 */ + { 130, 7, 12, 0, 0, 18432, 82, }, /* 1318 */ + { 130, 13, 12, 0, 0, 18432, 138, }, /* 1319 */ + { 130, 21, 12, 0, 0, 18432, 124, }, /* 1320 */ + { 159, 7, 12, 0, 0, 18432, 82, }, /* 1321 */ + { 159, 13, 12, 0, 0, 18432, 138, }, /* 1322 */ + { 126, 7, 12, 0, 0, 18432, 82, }, /* 1323 */ + { 126, 12, 3, 0, 0, 26624, 96, }, /* 1324 */ + { 126, 21, 12, 0, 0, 18432, 124, }, /* 1325 */ + { 128, 7, 12, 0, 0, 18432, 82, }, /* 1326 */ + { 128, 12, 3, 0, 0, 26624, 96, }, /* 1327 */ + { 128, 21, 12, 0, 0, 18432, 124, }, /* 1328 */ + { 128, 21, 12, 0, 0, 18432, 106, }, /* 1329 */ + { 128, 21, 12, 0, 0, 18432, 68, }, /* 1330 */ + { 128, 26, 12, 0, 0, 18432, 68, }, /* 1331 */ + { 128, 6, 12, 0, 0, 18432, 142, }, /* 1332 */ + { 128, 6, 12, 0, 0, 18432, 136, }, /* 1333 */ + { 128, 13, 12, 0, 0, 18432, 138, }, /* 1334 */ + { 128, 15, 12, 0, 0, 18432, 68, }, /* 1335 */ + { 151, 9, 12, 0, 32, 18432, 74, }, /* 1336 */ + { 151, 5, 12, 0, -32, 18432, 76, }, /* 1337 */ + { 151, 15, 12, 0, 0, 18432, 68, }, /* 1338 */ + { 151, 21, 12, 0, 0, 18432, 106, }, /* 1339 */ + { 151, 21, 12, 0, 0, 18432, 124, }, /* 1340 */ + { 151, 21, 12, 0, 0, 18432, 68, }, /* 1341 */ + { 123, 7, 12, 0, 0, 18432, 82, }, /* 1342 */ + { 123, 12, 3, 0, 0, 26624, 130, }, /* 1343 */ + { 123, 10, 5, 0, 0, 18432, 144, }, /* 1344 */ + { 123, 12, 3, 0, 0, 26624, 128, }, /* 1345 */ + { 123, 6, 12, 0, 0, 18432, 92, }, /* 1346 */ + { 146, 6, 12, 0, 0, 18432, 136, }, /* 1347 */ + { 147, 6, 12, 0, 0, 18432, 136, }, /* 1348 */ + { 23, 21, 12, 0, 0, 28672, 68, }, /* 1349 */ + { 158, 12, 3, 0, 0, 26624, 328, }, /* 1350 */ + { 23, 10, 5, 0, 0, 18432, 164, }, /* 1351 */ + { 146, 7, 12, 0, 0, 18432, 284, }, /* 1352 */ + { 158, 7, 12, 0, 0, 18432, 284, }, /* 1353 */ + { 21, 6, 12, 0, 0, 18432, 92, }, /* 1354 */ + { 147, 7, 12, 0, 0, 18432, 284, }, /* 1355 */ + { 46, 7, 12, 0, 0, 18432, 82, }, /* 1356 */ + { 46, 26, 12, 0, 0, 18432, 68, }, /* 1357 */ + { 46, 12, 3, 0, 0, 26624, 102, }, /* 1358 */ + { 46, 12, 3, 0, 0, 26624, 130, }, /* 1359 */ + { 46, 21, 12, 0, 0, 18432, 124, }, /* 1360 */ + { 69, 1, 2, 0, 0, 6153, 66, }, /* 1361 */ + { 69, 10, 3, 0, 0, 18432, 330, }, /* 1362 */ + { 69, 10, 5, 0, 0, 18432, 138, }, /* 1363 */ + { 69, 10, 5, 0, 0, 18432, 160, }, /* 1364 */ + { 69, 10, 3, 0, 0, 18432, 286, }, /* 1365 */ + { 1, 12, 3, 0, 0, 26624, 102, }, /* 1366 */ + { 69, 25, 12, 0, 0, 18432, 118, }, /* 1367 */ + { 69, 13, 12, 0, 0, 10240, 214, }, /* 1368 */ + { 141, 26, 12, 0, 0, 18432, 68, }, /* 1369 */ + { 141, 12, 3, 0, 0, 26624, 102, }, /* 1370 */ + { 141, 21, 12, 0, 0, 18432, 106, }, /* 1371 */ + { 141, 21, 12, 0, 0, 18432, 124, }, /* 1372 */ + { 141, 21, 12, 0, 0, 18432, 68, }, /* 1373 */ + { 35, 12, 3, 0, 0, 26624, 130, }, /* 1374 */ + { 2, 6, 12, 0, 0, 18432, 90, }, /* 1375 */ + { 154, 7, 12, 0, 0, 18432, 82, }, /* 1376 */ + { 154, 12, 3, 0, 0, 26624, 96, }, /* 1377 */ + { 154, 6, 12, 0, 0, 18432, 142, }, /* 1378 */ + { 154, 6, 12, 0, 0, 18432, 136, }, /* 1379 */ + { 154, 13, 12, 0, 0, 18432, 138, }, /* 1380 */ + { 154, 26, 12, 0, 0, 18432, 68, }, /* 1381 */ + { 160, 7, 12, 0, 0, 18432, 82, }, /* 1382 */ + { 160, 12, 3, 0, 0, 26624, 96, }, /* 1383 */ + { 155, 7, 12, 0, 0, 18432, 82, }, /* 1384 */ + { 155, 12, 3, 0, 0, 26624, 96, }, /* 1385 */ + { 155, 13, 12, 0, 0, 18432, 138, }, /* 1386 */ + { 155, 23, 12, 0, 0, 14336, 68, }, /* 1387 */ + { 163, 7, 12, 0, 0, 18432, 82, }, /* 1388 */ + { 163, 6, 12, 0, 0, 18432, 142, }, /* 1389 */ + { 163, 12, 3, 0, 0, 26624, 102, }, /* 1390 */ + { 163, 13, 12, 0, 0, 18432, 138, }, /* 1391 */ + { 129, 7, 12, 0, 0, 34816, 82, }, /* 1392 */ + { 129, 15, 12, 0, 0, 34816, 68, }, /* 1393 */ + { 129, 12, 3, 0, 0, 26624, 96, }, /* 1394 */ + { 58, 9, 12, 0, 34, 34816, 74, }, /* 1395 */ + { 58, 5, 12, 0, -34, 34816, 76, }, /* 1396 */ + { 58, 12, 3, 0, 0, 26624, 150, }, /* 1397 */ + { 58, 12, 3, 0, 0, 26624, 130, }, /* 1398 */ + { 58, 12, 3, 0, 0, 26624, 96, }, /* 1399 */ + { 58, 6, 12, 0, 0, 34816, 142, }, /* 1400 */ + { 58, 13, 12, 0, 0, 34816, 138, }, /* 1401 */ + { 58, 21, 12, 0, 0, 34816, 68, }, /* 1402 */ + { 69, 15, 12, 0, 0, 0, 68, }, /* 1403 */ + { 69, 26, 12, 0, 0, 0, 68, }, /* 1404 */ + { 69, 23, 12, 0, 0, 0, 68, }, /* 1405 */ + { 3, 7, 12, 0, 0, 0, 240, }, /* 1406 */ + { 69, 26, 14, 0, 0, 28672, 332, }, /* 1407 */ + { 69, 26, 14, 0, 0, 28672, 334, }, /* 1408 */ + { 68, 2, 14, 0, 0, 18432, 336, }, /* 1409 */ + { 69, 26, 12, 0, 0, 18432, 338, }, /* 1410 */ + { 69, 26, 14, 0, 0, 18432, 340, }, /* 1411 */ + { 69, 26, 14, 0, 0, 18432, 334, }, /* 1412 */ + { 69, 26, 11, 0, 0, 18432, 342, }, /* 1413 */ + { 20, 26, 12, 0, 0, 18432, 68, }, /* 1414 */ + { 69, 26, 14, 0, 0, 18432, 236, }, /* 1415 */ + { 69, 26, 14, 0, 0, 18447, 334, }, /* 1416 */ + { 69, 26, 14, 0, 0, 28672, 344, }, /* 1417 */ + { 69, 26, 14, 0, 0, 28672, 346, }, /* 1418 */ + { 69, 24, 3, 0, 0, 28672, 348, }, /* 1419 */ + { 69, 26, 14, 0, 0, 28672, 350, }, /* 1420 */ + { 69, 13, 12, 0, 0, 10240, 138, }, /* 1421 */ + { 69, 1, 3, 0, 0, 6144, 352, }, /* 1422 */ }; const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ @@ -2129,36 +1885,36 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ 128,128,129,129,130,131,132,133,134,135,136,137,138,139,140,141, /* U+F800 */ 142,143,144,145,146,147,148,149,150,151,152,153,154,154,155,156, /* U+10000 */ 157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172, /* U+10800 */ -173,174,175,176,177,178,179,180,181,182,146,183,184,185,186,146, /* U+11000 */ -187,188,189,190,191,192,193,194,195,196,197,198,146,199,200,201, /* U+11800 */ -202,202,202,202,202,202,202,203,204,202,205,146,146,146,146,146, /* U+12000 */ -146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,206, /* U+12800 */ -207,207,207,207,207,207,207,207,208,207,207,207,207,207,207,207, /* U+13000 */ -207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, /* U+13800 */ -207,207,207,207,207,207,207,209,210,210,210,210,211,146,146,146, /* U+14000 */ +173,174,175,176,177,178,179,146,180,181,146,182,183,184,185,146, /* U+11000 */ +186,187,188,189,190,191,192,146,193,194,195,196,146,197,198,199, /* U+11800 */ +200,200,200,200,200,200,200,201,202,200,203,146,146,146,146,146, /* U+12000 */ +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,204, /* U+12800 */ +205,205,205,205,205,205,205,205,206,146,146,146,146,146,146,146, /* U+13000 */ +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+13800 */ +146,146,146,146,146,146,146,146,207,207,207,207,208,146,146,146, /* U+14000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+14800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+15000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+15800 */ -146,146,212,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+16000 */ -213,213,213,213,214,215,216,217,146,146,218,146,219,220,221,222, /* U+16800 */ -223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, /* U+17000 */ -223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, /* U+17800 */ -223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,224, /* U+18000 */ -223,223,223,223,223,223,225,225,225,226,227,146,146,146,146,146, /* U+18800 */ +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+16000 */ +209,209,209,209,210,211,212,213,146,146,146,146,214,215,216,217, /* U+16800 */ +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, /* U+17000 */ +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218, /* U+17800 */ +218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,219, /* U+18000 */ +218,218,218,218,218,218,220,220,220,221,222,146,146,146,146,146, /* U+18800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+19000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+19800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+1A000 */ -146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,228, /* U+1A800 */ -229,230,231,232,232,233,146,146,146,146,146,146,146,146,146,146, /* U+1B000 */ -146,146,146,146,146,146,146,146,234,235,146,146,146,146,146,146, /* U+1B800 */ +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,223, /* U+1A800 */ +224,225,226,227,227,228,146,146,146,146,146,146,146,146,146,146, /* U+1B000 */ +146,146,146,146,146,146,146,146,229,230,146,146,146,146,146,146, /* U+1B800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+1C000 */ -146,146,146,146,146,146,146,146,236,237,236,236,236,238,239,240, /* U+1C800 */ -241,242,243,244,245,246,247,146,248,249,250,251,252,253,254,255, /* U+1D000 */ -256,256,256,256,257,258,146,146,146,146,146,146,146,146,259,146, /* U+1D800 */ -260,261,262,146,146,263,146,146,146,264,146,265,146,146,146,266, /* U+1E000 */ -267,268,269,270,270,270,270,270,271,272,273,270,274,275,270,270, /* U+1E800 */ -276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291, /* U+1F000 */ -292,293,294,295,296,297,236,298,281,281,281,281,281,281,281,299, /* U+1F800 */ +146,146,146,146,146,146,146,146,146,146,146,146,146,146,231,232, /* U+1C800 */ +233,234,235,236,237,238,239,146,240,241,242,243,244,245,246,247, /* U+1D000 */ +248,248,248,248,249,250,146,146,146,146,146,146,146,146,251,146, /* U+1D800 */ +252,253,254,146,146,255,146,146,146,256,146,146,146,146,146,257, /* U+1E000 */ +258,259,260,168,168,168,168,168,261,262,263,168,264,265,168,168, /* U+1E800 */ +266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281, /* U+1F000 */ +282,283,284,285,286,287,288,289,271,271,271,271,271,271,271,290, /* U+1F800 */ 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+20000 */ 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+20800 */ 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+21000 */ @@ -2179,23 +1935,23 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+28800 */ 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+29000 */ 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+29800 */ -101,101,101,101,101,101,101,101,101,101,101,101,101,300,101,101, /* U+2A000 */ +101,101,101,101,101,101,101,101,101,101,101,101,101,291,101,101, /* U+2A000 */ 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2A800 */ -101,101,101,101,101,101,101,101,101,101,101,101,101,101,301,101, /* U+2B000 */ -302,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2B800 */ +101,101,101,101,101,101,101,101,101,101,101,101,101,101,292,101, /* U+2B000 */ +293,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2B800 */ 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2C000 */ -101,101,101,101,101,101,101,101,101,101,101,101,101,303,101,101, /* U+2C800 */ +101,101,101,101,101,101,101,101,101,101,101,101,101,294,101,101, /* U+2C800 */ 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2D000 */ 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2D800 */ 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2E000 */ -101,101,101,101,101,101,101,304,101,101,101,101,305,146,146,146, /* U+2E800 */ +101,101,101,101,101,101,101,295,146,146,146,146,146,146,146,146, /* U+2E800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+2F000 */ -129,129,129,129,306,146,146,146,146,146,146,146,146,146,146,307, /* U+2F800 */ +129,129,129,129,296,146,146,146,146,146,146,146,146,146,146,297, /* U+2F800 */ 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+30000 */ 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+30800 */ -101,101,101,101,101,101,308,101,101,101,101,101,101,101,101,101, /* U+31000 */ +101,101,101,101,101,101,298,101,101,101,101,101,101,101,101,101, /* U+31000 */ 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+31800 */ -101,101,101,101,101,101,101,309,146,146,146,146,146,146,146,146, /* U+32000 */ +101,101,101,101,101,101,101,299,146,146,146,146,146,146,146,146, /* U+32000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+32800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+33000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+33800 */ @@ -2222,7 +1978,7 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3E000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3E800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3F000 */ -146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,307, /* U+3F800 */ +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+3F800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+40000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+40800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+41000 */ @@ -2254,7 +2010,7 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4E000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4E800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4F000 */ -146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,307, /* U+4F800 */ +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+4F800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+50000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+50800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+51000 */ @@ -2286,7 +2042,7 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5E000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5E800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5F000 */ -146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,307, /* U+5F800 */ +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+5F800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+60000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+60800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+61000 */ @@ -2318,7 +2074,7 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6E000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6E800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6F000 */ -146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,307, /* U+6F800 */ +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+6F800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+70000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+70800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+71000 */ @@ -2350,7 +2106,7 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7E000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7E800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7F000 */ -146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,307, /* U+7F800 */ +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+7F800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+80000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+80800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+81000 */ @@ -2382,7 +2138,7 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8E000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8E800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8F000 */ -146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,307, /* U+8F800 */ +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+8F800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+90000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+90800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+91000 */ @@ -2414,7 +2170,7 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9E000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9E800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9F000 */ -146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,307, /* U+9F800 */ +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+9F800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A0000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A0800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A1000 */ @@ -2446,7 +2202,7 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AE000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AE800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AF000 */ -146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,307, /* U+AF800 */ +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+AF800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B0000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B0800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B1000 */ @@ -2478,7 +2234,7 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BE000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BE800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BF000 */ -146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,307, /* U+BF800 */ +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+BF800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C0000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C0800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C1000 */ @@ -2510,7 +2266,7 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CE000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CE800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CF000 */ -146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,307, /* U+CF800 */ +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+CF800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D0000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D0800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D1000 */ @@ -2542,9 +2298,9 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DE000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DE800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DF000 */ -146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,307, /* U+DF800 */ -310,311,312,313,311,311,311,311,311,311,311,311,311,311,311,311, /* U+E0000 */ -311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311, /* U+E0800 */ +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+DF800 */ +300,301,302,303,301,301,301,301,301,301,301,301,301,301,301,301, /* U+E0000 */ +301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301, /* U+E0800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E1000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E1800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E2000 */ @@ -2574,7 +2330,7 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EE000 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EE800 */ 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EF000 */ -146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,307, /* U+EF800 */ +146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,297, /* U+EF800 */ 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F0000 */ 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F0800 */ 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F1000 */ @@ -2606,7 +2362,7 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FE000 */ 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FE800 */ 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FF000 */ -128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,314, /* U+FF800 */ +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,304, /* U+FF800 */ 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+100000 */ 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+100800 */ 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+101000 */ @@ -2638,10 +2394,10 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10E000 */ 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10E800 */ 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10F000 */ -128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,314, /* U+10F800 */ +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,304, /* U+10F800 */ }; -const uint16_t PRIV(ucd_stage2)[] = { /* 80640 bytes, block = 128 */ +const uint16_t PRIV(ucd_stage2)[] = { /* 78080 bytes, block = 128 */ /* block 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 3, 4, 0, 0, @@ -2675,553 +2431,553 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 80640 bytes, block = 128 */ /* block 3 */ 74, 75, 65, 66, 65, 66, 76, 65, 66, 77, 77, 65, 66, 70, 78, 79, - 80, 65, 66, 77, 81, 82, 83, 84, 65, 66, 85, 86, 83, 87, 88, 89, - 65, 66, 65, 66, 65, 66, 90, 65, 66, 90, 70, 70, 65, 66, 90, 65, - 66, 91, 91, 65, 66, 65, 66, 92, 65, 66, 70, 93, 65, 66, 70, 94, - 93, 93, 93, 93, 95, 96, 97, 98, 99,100,101,102,103, 65, 66, 65, - 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,104, 65, 66, + 80, 65, 66, 77, 81, 82, 83, 84, 65, 66, 85, 70, 83, 86, 87, 88, + 65, 66, 65, 66, 65, 66, 89, 65, 66, 89, 70, 70, 65, 66, 89, 65, + 66, 90, 90, 65, 66, 65, 66, 91, 65, 66, 70, 92, 65, 66, 70, 93, + 92, 92, 92, 92, 94, 95, 96, 97, 98, 99,100,101,102, 65, 66, 65, + 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,103, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, - 69,105,106,107, 65, 66,108,109, 65, 66, 65, 66, 65, 66, 65, 66, + 69,104,105,106, 65, 66,107,108, 65, 66, 65, 66, 65, 66, 65, 66, /* block 4 */ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, -110, 70, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, - 65, 66, 65, 66, 70, 70, 70, 70, 70, 70,111, 65, 66,112,113,114, -114, 65, 66,115,116,117, 65, 66, 65, 67, 65, 66, 65, 66, 65, 66, -118,119,120,121,122, 70,123,123, 70,124, 70,125,126, 70, 70, 70, -123,127, 70,128,129,130,131, 70,132,133,131,134,135, 70, 70,133, - 70,136,137, 70, 70,138, 70, 70, 70, 70, 70, 70, 70,139, 70, 70, +109, 70, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, + 65, 66, 65, 66, 70, 70, 70, 70, 70, 70,110, 65, 66,111,112,113, +113, 65, 66,114,115,116, 65, 66, 65, 67, 65, 66, 65, 66, 65, 66, +117,118,119,120,121, 70,122,122, 70,123, 70,124,125, 70, 70, 70, +122,126, 70,127, 70,128,129, 70,130,131,129,132,133, 70, 70,131, + 70,134,135, 70, 70,136, 70, 70, 70, 70, 70, 70, 70,137, 70, 70, /* block 5 */ -140, 70,141,140, 70, 70, 70,142,140,143,144,144,145, 70, 70, 70, - 70, 70,146, 70, 93, 70, 70, 70, 70, 70, 70, 70, 70,147,148, 70, +138, 70,139,138, 70, 70, 70,140,138,141,142,142,143, 70, 70, 70, + 70, 70,144, 70, 92, 70, 70, 70, 70, 70, 70, 70, 70,145,146, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, -149,149,150,149,149,149,149,149,149,151,151,152,153,152,152,152, -154,154, 46, 46, 46, 46,151,155,151,155,155,155,151,156,151,151, -157,157, 46, 46, 46, 46, 46,158, 46,159, 46, 46, 46, 46, 46, 46, -149,149,149,149,149, 46, 46, 46, 46, 46,160,160,151, 46,152, 46, +147,147,148,147,147,147,147,147,147,149,149,150,150,150,150,150, +151,151, 46, 46, 46, 46,149,149,149,149,149,149,149,149,149,149, +152,152, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, +147,147,147,147,147, 46, 46, 46, 46, 46,153,153,149, 46,150, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, /* block 6 */ -161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176, -174,177,176,178,176,176,176,176,176,176,176,176,176,176,176,176, -179,176,176,180,181,179,176,176,176,176,176,176,176,182,179,176, -183,184,176,176,176,176,176,176,176,176,176,176,176,176,176,176, -176,176,185,176,176,186,176,176,176,176,176,176,176,176,176,187, -176,176,176,176,176,176,176,176,188,189,189,189,189,176,190,176, -176,176,176,191,191,191,191,191,191,191,191,191,191,191,191,191, -192,193,192,193,194,195,192,193,196,196,197,198,198,198,199,200, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,155,154,154,156,154,154,154,154,154,154,154,154,154,157, +154,154,154,154,154,154,154,154,158,158,158,158,158,154,154,154, +154,154,154,159,159,159,159,159,159,159,159,159,159,159,159,159, +160,161,160,161,149,162,160,161,163,163,164,165,165,165,166,167, /* block 7 */ -196,196,196,196,201, 46,202,203,204,204,204,196,205,196,206,206, -207,208,209,208,208,210,208,208,211,212,213,208,214,208,208,208, -215,216,196,217,208,208,218,208,208,219,208,208,220,221,221,221, -222,223,224,223,223,225,223,223,226,227,228,223,229,223,223,223, -230,231,232,233,223,223,234,223,223,235,223,223,236,237,237,238, -239,240,241,242,242,243,244,245,192,193,192,193,192,193,192,193, -192,193,246,247,246,247,246,247,246,247,246,247,246,247,246,247, -248,249,250,251,252,253,254,192,193,255,192,193,256,257,257,257, +163,163,163,163,162, 46,168,169,170,170,170,163,171,163,172,172, +173,174,175,174,174,176,174,174,177,178,179,174,180,174,174,174, +181,182,163,183,174,174,184,174,174,185,174,174,186,187,187,187, +173,188,189,188,188,190,188,188,191,192,193,188,194,188,188,188, +195,196,197,198,188,188,199,188,188,200,188,188,201,202,202,203, +204,205,206,207,207,208,209,210,160,161,160,161,160,161,160,161, +160,161,211,212,211,212,211,212,211,212,211,212,211,212,211,212, +213,214,215,216,217,218,219,160,161,220,160,161,221,222,222,222, /* block 8 */ -258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258, -259,259,260,259,261,259,259,259,259,259,259,259,259,259,262,259, -259,263,264,259,259,259,259,259,259,259,265,259,259,259,259,259, -266,266,267,266,268,266,266,266,266,266,266,266,266,266,269,266, -266,270,271,266,266,266,266,266,266,266,272,266,266,266,266,266, -273,273,273,273,273,273,274,273,274,273,273,273,273,273,273,273, -275,276,277,278,275,276,275,276,275,276,275,276,275,276,275,276, -275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +224,224,225,224,226,224,224,224,224,224,224,224,224,224,227,224, +224,228,229,224,224,224,224,224,224,224,230,224,224,224,224,224, +231,231,232,231,233,231,231,231,231,231,231,231,231,231,234,231, +231,235,236,231,231,231,231,231,231,231,237,231,231,231,231,231, +238,238,238,238,238,238,239,238,239,238,238,238,238,238,238,238, +240,241,242,243,240,241,240,241,240,241,240,241,240,241,240,241, +240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241, /* block 9 */ -275,276,279,280,281,282,282,281,283,283,275,276,275,276,275,276, -275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276, -275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276, -275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276, -284,275,276,275,276,275,276,275,276,275,276,275,276,275,276,285, -275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276, -275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276, -275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276, +240,241,244,245,246,247,247,246,248,248,240,241,240,241,240,241, +240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241, +240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241, +240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241, +249,240,241,240,241,240,241,240,241,240,241,240,241,240,241,250, +240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241, +240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241, +240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241, /* block 10 */ -275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276, -275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276, -275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276, -196,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, -286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, -286,286,286,286,286,286,286,196,196,287,288,288,288,288,288,289, -290,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291, -291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291, +240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241, +240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241, +240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241, +163,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,163,163,252,253,253,253,253,253,254, +255,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256, +256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256, /* block 11 */ -291,291,291,291,291,291,291,292,290,293,294,196,196,295,295,296, -297,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298, -298,298,299,298,298,298,298,298,298,298,298,298,298,298,298,298, -300,300,300,300,300,300,300,300,300,300,300,300,300,300,301,300, -302,300,300,303,300,304,302,304,297,297,297,297,297,297,297,297, -305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305, -305,305,305,305,305,305,305,305,305,305,305,297,297,297,297,305, -305,305,305,302,306,297,297,297,297,297,297,297,297,297,297,297, +256,256,256,256,256,256,256,257,255,258,259,163,163,260,260,261, +262,263,263,263,263,263,263,263,263,263,263,263,263,263,263,263, +263,263,264,263,263,263,263,263,263,263,263,263,263,263,263,263, +265,265,265,265,265,265,265,265,265,265,265,265,265,265,266,265, +267,265,265,268,265,269,267,269,262,262,262,262,262,262,262,262, +270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270, +270,270,270,270,270,270,270,270,270,270,270,262,262,262,262,270, +270,270,270,267,271,262,262,262,262,262,262,262,262,262,262,262, /* block 12 */ -307,307,307,307,307,308,309,309,310,311,311,312,313,314,315,315, -316,316,316,316,316,316,316,316,316,316,316,317,318,319,319,320, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -322,321,321,321,321,321,321,321,321,321,321,323,323,323,323,323, -323,323,323,324,325,325,316,326,327,316,316,316,316,316,316,316, -328,328,328,328,328,328,328,328,328,328,311,329,329,314,321,321, -324,321,321,330,321,321,321,321,321,321,321,321,321,321,321,321, +272,272,272,272,272,273,274,274,275,276,276,277,278,279,280,280, +281,281,281,281,281,281,281,281,281,281,281,282,283,284,284,285, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +287,286,286,286,286,286,286,286,286,286,286,288,288,288,288,288, +288,288,288,289,289,289,281,290,291,281,281,281,281,281,281,281, +292,292,292,292,292,292,292,292,292,292,276,293,293,279,286,286, +289,286,286,294,286,286,286,286,286,286,286,286,286,286,286,286, /* block 13 */ -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,331,321,316,316,316,316,316,316,332,308,315,333, -333,316,316,332,316,334,334,332,332,315,333,333,333,316,321,321, -335,335,335,335,335,335,335,335,335,335,321,321,321,336,336,321, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,295,286,281,281,281,281,281,281,281,273,280,291, +291,281,281,281,281,296,296,281,281,280,291,291,291,281,286,286, +297,297,297,297,297,297,297,297,297,297,286,286,286,298,298,286, /* block 14 */ -337,337,337,338,338,338,338,338,338,338,338,339,338,339,340,341, -342,343,342,342,342,342,342,342,342,342,342,342,342,342,342,342, -342,342,342,342,342,342,342,342,342,342,342,342,342,342,342,342, -344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344, -345,345,345,345,345,345,345,345,345,345,345,340,340,342,342,342, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, +299,299,299,300,300,300,300,300,300,300,300,301,300,301,302,303, +304,305,304,304,304,304,304,304,304,304,304,304,304,304,304,304, +304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304, +306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306, +307,307,307,307,307,307,307,307,307,307,307,302,302,304,304,304, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, /* block 15 */ -346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,346, -346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,346, -346,346,346,346,346,346,347,347,347,347,347,347,347,347,347,347, -347,346,340,340,340,340,340,340,340,340,340,340,340,340,340,340, -348,348,348,348,348,348,348,348,348,348,349,349,349,349,349,349, -349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349, -349,349,349,349,349,349,349,349,349,349,349,350,350,350,350,350, -350,350,350,350,351,351,352,353,354,355,356,297,297,357,358,358, +308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308, +308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308, +308,308,308,308,308,308,309,309,309,309,309,309,309,309,309,309, +309,308,302,302,302,302,302,302,302,302,302,302,302,302,302,302, +310,310,310,310,310,310,310,310,310,310,311,311,311,311,311,311, +311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311, +311,311,311,311,311,311,311,311,311,311,311,312,312,312,312,312, +312,312,312,312,313,313,314,315,316,317,318,262,262,319,320,320, /* block 16 */ -359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, -359,359,359,359,359,359,360,360,361,361,362,360,360,360,360,360, -360,360,360,360,362,360,360,360,362,360,360,360,360,363,297,297, -364,364,364,364,364,364,365,366,364,366,364,364,364,366,366,297, -367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367, -367,367,367,367,367,367,367,367,367,368,368,368,297,297,369,297, -342,342,342,342,342,342,342,342,342,342,342,340,340,340,340,340, 321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, +321,321,321,321,321,321,322,322,323,323,324,322,322,322,322,322, +322,322,322,322,324,322,322,322,324,322,322,322,322,325,262,262, +326,326,326,326,326,326,326,327,326,327,326,326,326,327,327,262, +328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328, +328,328,328,328,328,328,328,328,328,329,329,329,262,262,330,262, +304,304,304,304,304,304,304,304,304,304,304,302,302,302,302,302, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, /* block 17 */ -321,321,321,321,321,321,321,321,370,321,321,321,321,321,321,340, -307,307,340,340,340,340,340,316,333,333,333,333,333,333,333,333, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,334,327,327,333,327,327,327, -333,333,333,371,316,316,316,316,316,316,316,316,316,316,316,316, -372,372,308,326,326,326,326,326,326,326,333,333,333,333,333,333, -326,326,326,373,326,326,326,326,326,326,326,326,326,326,326,316, +286,286,286,286,286,286,286,286,331,286,286,286,286,286,286,302, +272,272,302,302,302,302,302,302,291,291,291,291,291,291,291,291, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,296,291,291,291,291,291,291, +291,291,291,332,281,281,281,281,281,281,281,281,281,281,281,281, +332,332,273,290,290,290,290,290,290,290,291,291,291,291,291,291, +290,290,290,290,290,290,290,290,290,290,290,290,290,290,290,281, /* block 18 */ -374,374,374,375,376,376,376,376,376,376,376,376,376,376,376,376, -376,376,376,376,376,377,377,377,377,377,377,377,377,377,377,377, -377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377, -377,377,377,377,377,377,377,377,377,377,374,375,378,376,375,375, -375,374,374,374,374,374,374,374,374,375,375,375,375,379,375,375, -376,380,381,176,176,374,374,374,377,377,377,377,377,377,377,377, -376,376,374,374,382,383,384,384,384,384,384,384,384,384,384,384, -385,386,376,376,376,376,376,376,377,377,377,377,377,377,377,377, +333,333,333,334,335,335,335,335,335,335,335,335,335,335,335,335, +335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335, +335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335, +335,335,335,335,335,335,335,335,335,335,333,334,336,335,334,334, +334,333,333,333,333,333,333,333,333,334,334,334,334,337,334,334, +335,338,339,154,154,333,333,333,335,335,335,335,335,335,335,335, +335,335,333,333,340,341,342,342,342,342,342,342,342,342,342,342, +343,344,335,335,335,335,335,335,335,335,335,335,335,335,335,335, /* block 19 */ -387,388,389,389,196,387,387,387,387,387,387,387,387,196,196,387, -387,196,196,387,387,390,390,390,390,390,390,390,390,390,390,390, -390,390,390,390,390,390,390,390,390,196,390,390,390,390,390,390, -390,196,390,196,196,196,390,390,390,390,196,196,391,387,392,389, -389,388,388,388,388,196,196,389,389,196,196,389,389,393,387,196, -196,196,196,196,196,196,196,392,196,196,196,196,390,390,196,390, -387,387,388,388,196,196,394,394,394,394,394,394,394,394,394,394, -390,390,395,395,396,396,396,396,396,396,397,395,387,398,399,196, +345,346,347,347,163,345,345,345,345,345,345,345,345,163,163,345, +345,163,163,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,163,345,345,345,345,345,345, +345,163,345,163,163,163,345,345,345,345,163,163,348,345,349,347, +347,346,346,346,346,163,163,347,347,163,163,347,347,350,345,163, +163,163,163,163,163,163,163,349,163,163,163,163,345,345,163,345, +345,345,346,346,163,163,351,351,351,351,351,351,351,351,351,351, +345,345,352,352,353,353,353,353,353,353,354,352,345,355,356,163, /* block 20 */ -196,400,400,401,196,402,402,402,402,402,402,196,196,196,196,402, -402,196,196,402,402,402,402,402,402,402,402,402,402,402,402,402, -402,402,402,402,402,402,402,402,402,196,402,402,402,402,402,402, -402,196,402,402,196,402,402,196,402,402,196,196,403,196,401,401, -401,400,400,196,196,196,196,400,400,196,196,400,400,404,196,196, -196,400,196,196,196,196,196,196,196,402,402,402,402,196,402,196, -196,196,196,196,196,196,405,405,405,405,405,405,405,405,405,405, -400,406,402,402,402,400,407,196,196,196,196,196,196,196,196,196, +163,357,357,358,163,359,359,359,359,359,359,163,163,163,163,359, +359,163,163,359,359,359,359,359,359,359,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,359,163,359,359,359,359,359,359, +359,163,359,359,163,359,359,163,359,359,163,163,360,163,358,358, +358,357,357,163,163,163,163,357,357,163,163,357,357,361,163,163, +163,357,163,163,163,163,163,163,163,359,359,359,359,163,359,163, +163,163,163,163,163,163,362,362,362,362,362,362,362,362,362,362, +357,357,359,359,359,357,363,163,163,163,163,163,163,163,163,163, /* block 21 */ -196,408,408,409,196,410,410,410,410,410,410,410,410,410,196,410, -410,410,196,410,410,411,411,411,411,411,411,411,411,411,411,411, -411,411,411,411,411,411,411,411,411,196,411,411,411,411,411,411, -411,196,411,411,196,411,411,411,411,411,196,196,412,410,409,409, -409,408,408,408,408,408,196,408,408,409,196,409,409,413,196,196, -410,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -410,410,408,408,196,196,414,414,414,414,414,414,414,414,414,414, -415,416,196,196,196,196,196,196,196,411,408,417,408,412,412,412, +163,364,364,365,163,366,366,366,366,366,366,366,366,366,163,366, +366,366,163,366,366,366,366,366,366,366,366,366,366,366,366,366, +366,366,366,366,366,366,366,366,366,163,366,366,366,366,366,366, +366,163,366,366,163,366,366,366,366,366,163,163,367,366,365,365, +365,364,364,364,364,364,163,364,364,365,163,365,365,368,163,163, +366,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +366,366,364,364,163,163,369,369,369,369,369,369,369,369,369,369, +370,371,163,163,163,163,163,163,163,366,364,364,364,367,367,367, /* block 22 */ -196,418,419,419,196,420,420,420,420,420,420,420,420,196,196,420, -420,196,196,420,420,421,421,421,421,421,421,421,421,421,421,421, -421,421,421,421,421,421,421,421,421,196,421,421,421,421,421,421, -421,196,421,421,196,421,421,421,421,421,196,196,422,420,423,418, -419,418,418,418,418,196,196,419,419,196,196,419,419,424,196,196, -196,196,196,196,196,425,418,423,196,196,196,196,421,421,196,421, -420,420,418,418,196,196,426,426,426,426,426,426,426,426,426,426, -427,421,428,428,428,428,428,428,196,196,196,196,196,196,196,196, +163,372,373,373,163,374,374,374,374,374,374,374,374,163,163,374, +374,163,163,374,374,374,374,374,374,374,374,374,374,374,374,374, +374,374,374,374,374,374,374,374,374,163,374,374,374,374,374,374, +374,163,374,374,163,374,374,374,374,374,163,163,375,374,376,372, +373,372,372,372,372,163,163,373,373,163,163,373,373,377,163,163, +163,163,163,163,163,378,372,376,163,163,163,163,374,374,163,374, +374,374,372,372,163,163,379,379,379,379,379,379,379,379,379,379, +380,374,381,381,381,381,381,381,163,163,163,163,163,163,163,163, /* block 23 */ -196,196,429,430,196,430,430,430,430,430,430,196,196,196,430,430, -430,196,430,430,430,430,196,196,196,430,430,196,430,196,430,430, -196,196,196,430,430,196,196,196,430,430,430,196,196,196,430,430, -430,430,430,430,430,430,430,430,430,430,196,196,196,196,431,432, -429,432,432,196,196,196,432,432,432,196,432,432,432,433,196,196, -430,196,196,196,196,196,196,431,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,434,434,434,434,434,434,434,434,434,434, -435,435,435,436,437,437,437,437,437,438,437,196,196,196,196,196, +163,163,382,383,163,383,383,383,383,383,383,163,163,163,383,383, +383,163,383,383,383,383,163,163,163,383,383,163,383,163,383,383, +163,163,163,383,383,163,163,163,383,383,383,163,163,163,383,383, +383,383,383,383,383,383,383,383,383,383,163,163,163,163,384,385, +382,385,385,163,163,163,385,385,385,163,385,385,385,386,163,163, +383,163,163,163,163,163,163,384,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,387,387,387,387,387,387,387,387,387,387, +388,388,388,389,390,390,390,390,390,391,390,163,163,163,163,163, /* block 24 */ -439,440,440,440,439,441,441,441,441,441,441,441,441,196,441,441, -441,196,441,441,441,442,442,442,442,442,442,442,442,442,442,442, -442,442,442,442,442,442,442,442,442,196,442,442,442,442,442,442, -442,442,442,442,442,442,442,442,442,442,196,196,443,441,439,439, -439,440,440,440,440,196,439,439,439,196,439,439,439,444,196,196, -196,196,196,196,196,439,439,196,442,442,442,196,196,441,196,196, -441,441,439,439,196,196,445,445,445,445,445,445,445,445,445,445, -196,196,196,196,196,196,196,446,447,447,447,447,447,447,447,448, +392,393,393,393,392,394,394,394,394,394,394,394,394,163,394,394, +394,163,394,394,394,394,394,394,394,394,394,394,394,394,394,394, +394,394,394,394,394,394,394,394,394,163,394,394,394,394,394,394, +394,394,394,394,394,394,394,394,394,394,163,163,395,394,392,392, +392,393,393,393,393,163,392,392,392,163,392,392,392,396,163,163, +163,163,163,163,163,392,392,163,394,394,394,163,163,394,163,163, +394,394,392,392,163,163,397,397,397,397,397,397,397,397,397,397, +163,163,163,163,163,163,163,398,399,399,399,399,399,399,399,400, /* block 25 */ -449,450,451,451,452,449,449,449,449,449,449,449,449,196,449,449, -449,196,449,449,449,449,449,449,449,449,449,449,449,449,449,449, -449,449,449,449,449,449,449,449,449,196,449,449,449,449,449,449, -449,449,449,449,196,449,449,449,449,449,196,196,453,449,451,454, -455,451,455,451,451,196,454,455,455,196,455,455,450,456,196,196, -196,196,196,196,196,455,455,196,196,196,196,196,196,449,449,196, -449,449,450,450,196,196,457,457,457,457,457,457,457,457,457,457, -196,449,449,451,196,196,196,196,196,196,196,196,196,196,196,196, +401,402,403,403,404,401,401,401,401,401,401,401,401,163,401,401, +401,163,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,163,401,401,401,401,401,401, +401,401,401,401,163,401,401,401,401,401,163,163,405,401,403,406, +403,403,407,403,403,163,406,403,403,163,403,403,402,408,163,163, +163,163,163,163,163,407,407,163,163,163,163,163,163,401,401,163, +401,401,402,402,163,163,409,409,409,409,409,409,409,409,409,409, +163,401,401,403,163,163,163,163,163,163,163,163,163,163,163,163, /* block 26 */ -458,458,459,459,460,460,460,460,460,460,460,460,460,196,460,460, -460,196,460,460,460,461,461,461,461,461,461,461,461,461,461,461, -461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, -461,461,461,461,461,461,461,461,461,461,461,462,462,460,463,459, -459,458,458,458,458,196,459,459,459,196,459,459,459,462,464,465, -196,196,196,196,460,460,460,463,466,466,466,466,466,466,466,460, -460,460,458,458,196,196,467,467,467,467,467,467,467,467,467,467, -466,466,466,466,466,466,466,466,466,465,460,460,460,460,460,460, +410,410,411,411,412,412,412,412,412,412,412,412,412,163,412,412, +412,163,412,412,412,412,412,412,412,412,412,412,412,412,412,412, +412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412, +412,412,412,412,412,412,412,412,412,412,412,413,413,412,414,411, +411,410,410,410,410,163,411,411,411,163,411,411,411,413,415,416, +163,163,163,163,412,412,412,414,417,417,417,417,417,417,417,412, +412,412,410,410,163,163,418,418,418,418,418,418,418,418,418,418, +417,417,417,417,417,417,417,417,417,416,412,412,412,412,412,412, /* block 27 */ -196,468,469,469,196,470,470,470,470,470,470,470,470,470,470,470, -470,470,470,470,470,470,470,196,196,196,470,470,470,470,470,470, -470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470, -470,470,196,470,470,470,470,470,470,470,470,470,196,470,196,196, -470,470,470,470,470,470,470,196,196,196,471,196,196,196,196,472, -469,469,468,468,468,196,468,196,469,469,469,469,469,469,469,472, -196,196,196,196,196,196,473,473,473,473,473,473,473,473,473,473, -196,196,469,469,474,196,196,196,196,196,196,196,196,196,196,196, +163,419,420,420,163,421,421,421,421,421,421,421,421,421,421,421, +421,421,421,421,421,421,421,163,163,163,421,421,421,421,421,421, +421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421, +421,421,163,421,421,421,421,421,421,421,421,421,163,421,163,163, +421,421,421,421,421,421,421,163,163,163,422,163,163,163,163,423, +420,420,419,419,419,163,419,163,420,420,420,420,420,420,420,423, +163,163,163,163,163,163,424,424,424,424,424,424,424,424,424,424, +163,163,420,420,425,163,163,163,163,163,163,163,163,163,163,163, /* block 28 */ -196,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, -475,476,475,477,476,476,476,476,476,476,478,196,196,196,196,479, -480,480,480,480,480,475,481,482,482,482,482,482,482,476,482,483, -484,484,484,484,484,484,484,484,484,484,485,485,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +163,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, +426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, +426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, +426,427,426,428,427,427,427,427,427,427,429,163,163,163,163,430, +431,431,431,431,431,426,432,433,433,433,433,433,433,427,433,434, +435,435,435,435,435,435,435,435,435,435,436,436,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 29 */ -196,486,486,196,486,196,486,486,486,486,486,196,486,486,486,486, -486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486, -486,486,486,486,196,486,196,486,486,486,486,486,486,486,486,486, -486,487,486,488,487,487,487,487,487,487,489,487,487,486,196,196, -490,490,490,490,490,196,491,196,492,492,492,492,492,487,493,196, -494,494,494,494,494,494,494,494,494,494,196,196,486,486,486,486, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +163,437,437,163,437,163,437,437,437,437,437,163,437,437,437,437, +437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, +437,437,437,437,163,437,163,437,437,437,437,437,437,437,437,437, +437,438,437,439,438,438,438,438,438,438,440,438,438,437,163,163, +441,441,441,441,441,163,442,163,443,443,443,443,443,438,444,163, +445,445,445,445,445,445,445,445,445,445,163,163,437,437,437,437, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 30 */ -495,496,496,496,497,497,497,497,498,497,497,497,497,498,498,498, -498,498,498,496,497,496,496,496,499,499,496,496,496,496,496,496, -500,500,500,500,500,500,500,500,500,500,501,501,501,501,501,501, -501,501,501,501,496,499,496,499,496,499,502,503,502,503,504,504, -495,495,495,495,495,495,495,495,196,495,495,495,495,495,495,495, -495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495, -495,495,495,495,495,495,495,495,495,495,495,495,495,196,196,196, -196,505,505,505,505,505,505,506,505,506,505,505,505,505,505,507, +446,447,447,447,448,448,448,448,449,448,448,448,448,449,449,449, +449,449,449,447,448,447,447,447,450,450,447,447,447,447,447,447, +451,451,451,451,451,451,451,451,451,451,452,452,452,452,452,452, +452,452,452,452,447,450,447,450,447,450,453,454,453,454,455,455, +446,446,446,446,446,446,446,446,163,446,446,446,446,446,446,446, +446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446, +446,446,446,446,446,446,446,446,446,446,446,446,446,163,163,163, +163,456,456,456,456,456,456,457,456,457,456,456,456,456,456,458, /* block 31 */ -505,505,508,508,509,497,499,499,495,495,495,495,495,505,505,505, -505,505,505,505,505,505,505,505,196,505,505,505,505,505,505,505, -505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505, -505,505,505,505,505,505,505,505,505,505,505,505,505,196,496,496, -496,496,496,496,496,496,499,496,496,496,496,496,496,196,496,496, -497,497,497,497,497,510,510,510,510,497,497,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +456,456,459,459,460,448,450,450,446,446,446,446,446,456,456,456, +456,456,456,456,456,456,456,456,163,456,456,456,456,456,456,456, +456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456, +456,456,456,456,456,456,456,456,456,456,456,456,456,163,447,447, +447,447,447,447,447,447,450,447,447,447,447,447,447,163,447,447, +448,448,448,448,448,461,461,461,461,448,448,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 32 */ -511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511, -511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511, -511,511,511,511,511,511,511,511,511,511,511,512,512,513,513,513, -513,514,513,513,513,513,513,515,512,516,516,514,514,513,513,511, -517,517,517,517,517,517,517,517,517,517,518,518,519,519,519,519, -511,511,511,511,511,511,514,514,513,513,511,511,511,511,513,513, -513,511,512,520,520,511,511,512,512,520,520,520,520,520,511,511, -511,513,513,513,513,511,511,511,511,511,511,511,511,511,511,511, +462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462, +462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462, +462,462,462,462,462,462,462,462,462,462,462,463,463,464,464,464, +464,465,464,464,464,464,464,466,463,467,467,465,465,464,464,462, +468,468,468,468,468,468,468,468,468,468,469,469,470,470,470,470, +462,462,462,462,462,462,465,465,464,464,462,462,462,462,464,464, +464,462,463,471,471,462,462,463,463,471,471,471,471,471,462,462, +462,464,464,464,464,462,462,462,462,462,462,462,462,462,462,462, /* block 33 */ -511,511,513,512,514,513,513,520,520,520,520,520,520,521,511,520, -522,522,522,522,522,522,522,522,522,522,520,520,512,513,523,523, -524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524, -524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524, -524,524,524,524,524,524,196,524,196,196,196,196,196,524,196,196, -525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525, -525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525, -525,525,525,525,525,525,525,525,525,525,525,526,527,525,525,525, +462,462,464,463,465,464,464,471,471,471,471,471,471,472,462,471, +473,473,473,473,473,473,473,473,473,473,471,471,463,464,474,474, +475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, +475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, +475,475,475,475,475,475,163,475,163,163,163,163,163,475,163,163, +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +476,476,476,476,476,476,476,476,476,476,476,477,478,476,476,476, /* block 34 */ -528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528, -528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528, -528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528, -528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528, -528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528, -528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,529, -530,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531, -531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531, +479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, +479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, +479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, +479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, +479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, +479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,480, +481,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, +482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, /* block 35 */ -531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531, -531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531, -531,531,531,531,531,531,531,531,532,532,532,532,532,532,532,532, -532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532, -532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532, -532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532, -532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532, -532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532, +482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, +482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, +482,482,482,482,482,482,482,482,483,483,483,483,483,483,483,483, +483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483, +483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483, +483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483, +483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483, +483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483, /* block 36 */ -533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533, -533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533, -533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533, -533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533, -533,533,533,533,533,533,533,533,533,196,533,533,533,533,196,196, -533,533,533,533,533,533,533,196,533,196,533,533,533,533,196,196, -533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533, -533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,163,484,484,484,484,163,163, +484,484,484,484,484,484,484,163,484,163,484,484,484,484,163,163, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, /* block 37 */ -533,533,533,533,533,533,533,533,533,196,533,533,533,533,196,196, -533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533, -533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533, -533,196,533,533,533,533,196,196,533,533,533,533,533,533,533,196, -533,196,533,533,533,533,196,196,533,533,533,533,533,533,533,533, -533,533,533,533,533,533,533,196,533,533,533,533,533,533,533,533, -533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533, -533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533, +484,484,484,484,484,484,484,484,484,163,484,484,484,484,163,163, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,163,484,484,484,484,163,163,484,484,484,484,484,484,484,163, +484,163,484,484,484,484,163,163,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,163,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, /* block 38 */ -533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533, -533,196,533,533,533,533,196,196,533,533,533,533,533,533,533,533, -533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533, -533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533, -533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533, -533,533,533,533,533,533,533,533,533,533,533,196,196,534,534,534, -535,536,537,536,536,536,536,537,537,538,538,538,538,538,538,538, -538,538,539,539,539,539,539,539,539,539,539,539,539,196,196,196, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,163,484,484,484,484,163,163,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,163,163,485,485,485, +486,487,488,487,487,487,487,488,488,489,489,489,489,489,489,489, +489,489,490,490,490,490,490,490,490,490,490,490,490,163,163,163, /* block 39 */ -533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533, -540,540,540,540,540,540,540,540,540,540,196,196,196,196,196,196, -541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541, -541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541, -541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541, -541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541, -541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541, -542,542,542,542,542,542,196,196,543,543,543,543,543,543,196,196, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +491,491,491,491,491,491,491,491,491,491,163,163,163,163,163,163, +492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492, +492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492, +492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492, +492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492, +492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492, +493,493,493,493,493,493,163,163,494,494,494,494,494,494,163,163, /* block 40 */ -544,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, +495,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, /* block 41 */ -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, /* block 42 */ -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,546,547,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,497,498,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, /* block 43 */ -548,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549, -549,549,549,549,549,549,549,549,549,549,549,550,551,196,196,196, -552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, -552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, -552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, -552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, -552,552,552,552,552,552,552,552,552,552,552,553,553,553,554,554, -554,552,552,552,552,552,552,552,552,196,196,196,196,196,196,196, +499,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500, +500,500,500,500,500,500,500,500,500,500,500,501,502,163,163,163, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,503,503,503,503,503,503,503,504,504,504,505,505, +505,503,503,503,503,503,503,503,503,163,163,163,163,163,163,163, /* block 44 */ -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,556,556,557,558,196,196,196,196,196,196,196,196,196,555, -559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559, -559,559,560,560,561,562,562,196,196,196,196,196,196,196,196,196, -563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563, -563,563,564,564,196,196,196,196,196,196,196,196,196,196,196,196, -565,565,565,565,565,565,565,565,565,565,565,565,565,196,565,565, -565,196,566,566,196,196,196,196,196,196,196,196,196,196,196,196, +506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,506, +506,506,507,507,508,509,163,163,163,163,163,163,163,163,163,506, +510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, +510,510,511,511,512,513,513,163,163,163,163,163,163,163,163,163, +514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514, +514,514,515,515,163,163,163,163,163,163,163,163,163,163,163,163, +516,516,516,516,516,516,516,516,516,516,516,516,516,163,516,516, +516,163,517,517,163,163,163,163,163,163,163,163,163,163,163,163, /* block 45 */ -567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567, -567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567, -567,567,567,568,568,567,567,567,567,567,567,567,567,567,567,567, -567,567,567,567,569,569,570,571,571,571,571,571,571,571,570,570, -570,570,570,570,570,570,571,570,570,572,572,572,572,572,572,572, -572,572,573,572,574,574,575,576,577,577,575,578,567,572,196,196, -579,579,579,579,579,579,579,579,579,579,196,196,196,196,196,196, -580,580,580,580,580,580,580,580,580,580,196,196,196,196,196,196, +518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518, +518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518, +518,518,518,519,519,518,518,518,518,518,518,518,518,518,518,518, +518,518,518,518,520,520,521,522,522,522,522,522,522,522,521,521, +521,521,521,521,521,521,522,521,521,523,523,523,523,523,523,523, +523,523,524,523,525,525,525,526,527,527,525,528,518,523,163,163, +529,529,529,529,529,529,529,529,529,529,163,163,163,163,163,163, +530,530,530,530,530,530,530,530,530,530,163,163,163,163,163,163, /* block 46 */ -581,581,582,583,584,582,585,581,584,586,587,588,588,588,589,588, -590,590,590,590,590,590,590,590,590,590,196,196,196,196,196,196, -591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591, -591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591, -591,591,591,592,591,591,591,591,591,591,591,591,591,591,591,591, -591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591, -591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591, -591,591,591,591,591,591,591,591,591,196,196,196,196,196,196,196, +531,531,532,533,534,532,535,531,534,536,537,538,538,538,539,538, +540,540,540,540,540,540,540,540,540,540,163,163,163,163,163,163, +541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541, +541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541, +541,541,541,542,541,541,541,541,541,541,541,541,541,541,541,541, +541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541, +541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541, +541,541,541,541,541,541,541,541,541,163,163,163,163,163,163,163, /* block 47 */ -591,591,591,591,591,593,593,591,591,591,591,591,591,591,591,591, -591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591, -591,591,591,591,591,591,591,591,591,594,591,196,196,196,196,196, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -545,545,545,545,545,545,196,196,196,196,196,196,196,196,196,196, +541,541,541,541,541,543,543,541,541,541,541,541,541,541,541,541, +541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541, +541,541,541,541,541,541,541,541,541,544,541,163,163,163,163,163, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,163,163,163,163,163,163,163,163,163,163, /* block 48 */ -595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595, -595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,196, -596,596,596,597,597,597,597,596,596,597,597,597,196,196,196,196, -597,597,596,597,597,597,597,597,597,598,598,598,196,196,196,196, -599,196,196,196,600,600,601,601,601,601,601,601,601,601,601,601, -602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602, -602,602,602,602,602,602,602,602,602,602,602,602,602,602,196,196, -602,602,602,602,602,196,196,196,196,196,196,196,196,196,196,196, +545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, +545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,163, +546,546,546,547,547,547,547,546,546,547,547,547,163,163,163,163, +547,547,546,547,547,547,547,547,547,548,548,548,163,163,163,163, +549,163,163,163,550,550,551,551,551,551,551,551,551,551,551,551, +552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, +552,552,552,552,552,552,552,552,552,552,552,552,552,552,163,163, +552,552,552,552,552,163,163,163,163,163,163,163,163,163,163,163, /* block 49 */ -603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603, -603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603, -603,603,603,603,603,603,603,603,603,603,603,603,196,196,196,196, -603,603,603,603,603,604,604,604,603,603,604,603,603,603,603,603, -603,603,603,603,603,603,603,603,603,603,196,196,196,196,196,196, -605,605,605,605,605,605,605,605,605,605,606,196,196,196,607,607, -608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608, -608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608, +553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553, +553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553, +553,553,553,553,553,553,553,553,553,553,553,553,163,163,163,163, +553,553,553,553,553,554,554,554,553,553,554,553,553,553,553,553, +553,553,553,553,553,553,553,553,553,553,163,163,163,163,163,163, +555,555,555,555,555,555,555,555,555,555,556,163,163,163,557,557, +558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558, +558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558, /* block 50 */ -609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609, -609,609,609,609,609,609,609,610,610,611,611,610,196,196,612,612, -613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613, -613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613, -613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613, -613,613,613,613,613,614,615,614,615,615,615,615,615,615,615,196, -616,617,615,617,617,615,615,615,615,615,615,615,615,614,614,614, -614,614,614,615,615,618,618,618,618,618,618,618,618,196,196,618, +559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559, +559,559,559,559,559,559,559,560,560,561,561,560,163,163,562,562, +563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563, +563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563, +563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563, +563,563,563,563,563,564,565,564,565,565,565,565,565,565,565,163, +566,567,565,567,567,565,565,565,565,565,565,565,565,564,564,564, +564,564,564,565,565,568,568,568,568,568,568,568,568,163,163,568, /* block 51 */ -619,619,619,619,619,619,619,619,619,619,196,196,196,196,196,196, -619,619,619,619,619,619,619,619,619,619,196,196,196,196,196,196, -620,620,620,620,620,620,620,621,622,622,622,622,620,620,196,196, -176,176,176,176,176,176,176,176,176,176,176,176,176,176,623,624, -624,176,176,176,176,176,176,176,176,176,176,176,624,624,624,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +569,569,569,569,569,569,569,569,569,569,163,163,163,163,163,163, +569,569,569,569,569,569,569,569,569,569,163,163,163,163,163,163, +570,570,570,570,570,570,570,571,572,572,572,572,570,570,163,163, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,573,574, +574,154,154,154,154,154,154,154,154,154,154,154,574,574,574,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 52 */ -625,625,625,625,626,627,627,627,627,627,627,627,627,627,627,627, -627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627, -627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627, -627,627,627,627,628,629,625,625,625,625,625,629,625,629,626,626, -626,626,625,629,630,627,627,627,627,627,627,627,627,196,631,631, -632,632,632,632,632,632,632,632,632,632,631,631,633,634,631,631, -633,635,635,635,635,635,635,635,635,635,635,628,628,628,628,628, -628,628,628,628,635,635,635,635,635,635,635,635,635,631,631,631, +575,575,575,575,576,577,577,577,577,577,577,577,577,577,577,577, +577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577, +577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577, +577,577,577,577,578,579,575,575,575,575,575,576,575,576,576,576, +576,576,575,576,580,577,577,577,577,577,577,577,577,163,163,163, +581,581,581,581,581,581,581,581,581,581,582,582,583,584,582,582, +583,585,585,585,585,585,585,585,585,585,585,578,578,578,578,578, +578,578,578,578,585,585,585,585,585,585,585,585,585,582,582,163, /* block 53 */ -636,636,637,638,638,638,638,638,638,638,638,638,638,638,638,638, -638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638, -638,637,636,636,636,636,637,637,636,636,639,640,636,636,638,638, -641,641,641,641,641,641,641,641,641,641,638,638,638,638,638,638, -642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642, -642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642, -642,642,642,642,642,642,643,644,645,645,644,644,644,645,644,645, -645,645,646,646,196,196,196,196,196,196,196,196,647,647,647,647, +586,586,587,588,588,588,588,588,588,588,588,588,588,588,588,588, +588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588, +588,587,586,586,586,586,587,587,586,586,589,590,586,586,588,588, +591,591,591,591,591,591,591,591,591,591,588,588,588,588,588,588, +592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592, +592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592, +592,592,592,592,592,592,593,594,595,595,594,594,594,595,594,595, +595,595,596,596,163,163,163,163,163,163,163,163,597,597,597,597, /* block 54 */ -648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648, -648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648, -648,648,648,648,649,649,649,649,649,649,649,649,650,650,650,650, -650,650,650,650,649,649,651,652,196,196,196,653,653,654,654,654, -655,655,655,655,655,655,655,655,655,655,196,196,196,648,648,648, -656,656,656,656,656,656,656,656,656,656,657,657,657,657,657,657, -657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657, -657,657,657,657,657,657,657,657,658,658,658,659,658,658,660,660, +598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598, +598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598, +598,598,598,598,599,599,599,599,599,599,599,599,600,600,600,600, +600,600,600,600,599,599,601,602,163,163,163,603,603,604,604,604, +605,605,605,605,605,605,605,605,605,605,163,163,163,598,598,598, +606,606,606,606,606,606,606,606,606,606,607,607,607,607,607,607, +607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607, +607,607,607,607,607,607,607,607,608,608,608,609,608,608,610,610, /* block 55 */ -661,662,663,664,665,666,667,668,669,275,276,196,196,196,196,196, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,196,196,670,670,670, -671,671,671,671,671,671,671,671,196,196,196,196,196,196,196,196, -672,673,672,674,673,675,675,676,675,676,677,673,676,676,673,673, -676,678,673,673,673,673,673,673,673,679,680,681,681,675,681,681, -681,681,682,683,684,680,680,685,686,686,687,196,196,196,196,196, +611,612,613,614,615,616,617,618,619,163,163,163,163,163,163,163, +620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620, +620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620, +620,620,620,620,620,620,620,620,620,620,620,163,163,620,620,620, +621,621,621,621,621,621,621,621,163,163,163,163,163,163,163,163, +622,623,622,624,623,625,625,626,625,626,627,623,626,626,623,623, +626,628,623,623,623,623,623,623,623,629,630,631,631,625,631,631, +631,631,632,633,634,630,630,635,636,636,637,163,163,163,163,163, /* block 56 */ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 70, 70, 70,256,256,256,256,256,688,149,149,149,149, -149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, -149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, -149,149,149,149,149,149,149,149,149,149,149,149,149,689,689,689, -689,689,150,149,149,149,689,689,689,689,689, 70, 70, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70,690,691, 70, 70, 70,692, 70, 70, + 70, 70, 70, 70, 70, 70,221,221,221,221,221,638,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,639,639,639, +639,639,148,147,147,147,639,639,639,639,639, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70,640,641, 70, 70, 70,642, 70, 70, /* block 57 */ - 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,693, 70, - 70, 70, 70, 70, 70, 70,694, 70, 70, 70, 70,695,695,695,695,695, -695,695,695,695,696,695,695,695,696,695,695,695,695,695,695,695, -695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,697, -698,698,189,189,176,176,176,176,176,176,176,176,176,176,176,176, -189,189,189,624,624,624,624,624,624,624,624,624,624,624,624,624, -624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624, -624,624,624,624,624,176,176,176,699,176,700,176,176,176,176,176, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,643, 70, + 70, 70, 70, 70, 70, 70,644, 70, 70, 70, 70,645,645,645,645,645, +645,645,645,645,646,645,645,645,646,645,645,645,645,645,645,645, +645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,647, +648,648,158,158,154,154,154,154,154,154,154,154,154,154,154,154, +158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, +158,158,158,158,158,158,158,574,574,574,574,574,574,574,574,574, +574,574,574,574,574,154,154,154,649,154,650,154,154,154,154,154, /* block 58 */ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, @@ -3230,12 +2986,12 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 80640 bytes, block = 128 */ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, -701,702, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, +651,652, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, /* block 59 */ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, - 65, 66, 65, 66, 65, 66, 69, 69, 69, 69,703,704, 70, 70,705, 70, + 65, 66, 65, 66, 65, 66, 69, 69, 69, 69,653,654, 70, 70,655, 70, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 67, 65, 66, 65, 66, @@ -3244,123 +3000,123 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 80640 bytes, block = 128 */ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, /* block 60 */ -706,706,706,706,706,706,706,706,707,707,707,707,707,707,707,707, -706,706,706,706,706,706,196,196,707,707,707,707,707,707,196,196, -706,706,706,706,706,706,706,706,707,707,707,707,707,707,707,707, -706,706,706,706,706,706,706,706,707,707,707,707,707,707,707,707, -706,706,706,706,706,706,196,196,707,707,707,707,707,707,196,196, -708,706,708,706,708,706,708,706,196,707,196,707,196,707,196,707, -706,706,706,706,706,706,706,706,707,707,707,707,707,707,707,707, -709,709,710,710,710,710,711,711,712,712,713,713,714,714,196,196, +656,656,656,656,656,656,656,656,657,657,657,657,657,657,657,657, +656,656,656,656,656,656,163,163,657,657,657,657,657,657,163,163, +656,656,656,656,656,656,656,656,657,657,657,657,657,657,657,657, +656,656,656,656,656,656,656,656,657,657,657,657,657,657,657,657, +656,656,656,656,656,656,163,163,657,657,657,657,657,657,163,163, +173,656,173,656,173,656,173,656,163,657,163,657,163,657,163,657, +656,656,656,656,656,656,656,656,657,657,657,657,657,657,657,657, +658,658,659,659,659,659,660,660,661,661,662,662,663,663,163,163, /* block 61 */ -715,715,715,715,715,715,715,715,716,716,716,716,716,716,716,716, -715,715,715,715,715,715,715,715,716,716,716,716,716,716,716,716, -715,715,715,715,715,715,715,715,716,716,716,716,716,716,716,716, -706,706,717,718,717,196,708,717,707,707,719,719,720,201,721,201, -201,201,717,718,717,196,708,717,722,722,722,722,720,201,201,201, -706,706,708,723,196,196,708,708,707,707,724,724,196,201,201,201, -706,706,708,725,708,250,708,708,707,707,726,726,255,201,201,201, -196,196,717,718,717,196,708,717,727,727,728,728,720,201,201,196, +664,664,664,664,664,664,664,664,665,665,665,665,665,665,665,665, +664,664,664,664,664,664,664,664,665,665,665,665,665,665,665,665, +664,664,664,664,664,664,664,664,665,665,665,665,665,665,665,665, +656,656,666,667,666,163,173,666,657,657,668,668,669,162,670,162, +162,162,666,667,666,163,173,666,671,671,671,671,669,162,162,162, +656,656,173,173,163,163,173,173,657,657,672,672,163,162,162,162, +656,656,173,173,173,215,173,173,657,657,673,673,220,162,162,162, +163,163,666,667,666,163,173,666,674,674,675,675,669,162,162,163, /* block 62 */ -729,729,729,729,729,729,729,729,729,729,729, 51,730,731,732,733, -734,734,734,734,734,734,735, 43,736,737,738,739,739,740,738,739, - 43, 43, 43, 43,741, 43, 43,742,743,744,745,746,747,748,749,750, -751,751,752,752,752, 43, 43, 43, 43, 49, 57, 43,753,754, 43,755, -756, 43, 43, 43,757,758,759,754,754,753, 43, 43, 43, 43, 43,760, - 43, 43, 50,761,755, 43, 43, 43, 43, 43,762, 43, 43,763, 43,729, - 51,764,764,764,764,765,766,767,768,769,770,770,770,770,770,770, - 54,696,196,196, 54, 54, 54, 54, 54, 54,771,772,773,774,775,695, +676,676,676,676,676,676,676,676,676,676,676, 51,677,678,679,680, +681,681,681,681,681,681,682, 43,683,684,685,686,686,687,685,686, + 43, 43, 43, 43,688, 43, 43,688,689,690,691,692,693,694,695,696, +697,697,698,698,698, 43, 43, 43, 43, 49, 57, 43,699,700, 43,701, +702, 43, 43, 43,703,704,705,700,700,699, 43, 43, 43, 43, 43, 43, + 43, 43, 50,706,701, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,676, + 51,707,707,707,707,708,709,710,711,712,713,713,713,713,713,713, + 54,646,163,163, 54, 54, 54, 54, 54, 54,714,715,716,717,718,645, /* block 63 */ - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,771,772,773,774,775,196, -695,695,695,695,695,695,695,695,695,695,695,695,695,196,196,196, -479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, -479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, -479,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776, -777,777,777,777,777,777,777,777,777,777,777,777,777,778,778,778, -778,777,778,779,778,777,777,189,189,189,189,777,777,777,777,777, -780,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,714,715,716,717,718,163, +645,645,645,645,645,645,645,645,645,645,645,645,645,163,163,163, +430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430, +430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430, +430,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719, +720,720,720,720,720,720,720,720,720,720,720,720,720,721,721,721, +721,720,721,722,721,720,720,158,158,158,158,720,720,720,720,720, +723,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 64 */ -781,781,782,781,781,781,781,782,781,781,783,782,782,782,783,783, -782,782,782,783,781,782,781,781,784,782,782,782,782,782,781,781, -781,781,785,781,782,781,786,781,782,787,788,789,782,782,790,783, -782,782,791,782,783,792,792,792,792,793,781,781,783,783,782,782, -794,794,794,794,794,782,783,783,795,795,781,794,781,781,796,510, +724,724,725,724,724,724,724,725,724,724,726,725,725,725,726,726, +725,725,725,726,724,725,724,724,727,725,725,725,725,725,724,724, +724,724,728,724,725,724,729,724,725,730,731,732,725,725,733,726, +725,725,734,725,726,735,735,735,735,736,724,724,726,726,725,725, +716,716,716,716,716,725,726,726,737,737,724,716,724,724,738,461, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, -797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797, -798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798, +739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739, +740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740, /* block 65 */ -799,799,799, 65, 66,799,799,799,799, 58,781,781,196,196,196,196, - 50, 50, 50, 50,800,801,801,801,801,801, 50, 50,802,802,802,802, - 50,802,802, 50,802,802, 50,802, 45,801,801,802,802,802, 50, 45, -802,802, 45, 45, 45, 45,802,802, 45, 45, 45, 45,802,802,802,802, -802,802,802,802,802,802,802,802,802,802,802,802,802,802, 50, 50, -802,802, 50,802, 50,802,802,802,802,802,802,802, 45,802, 45, 45, - 45, 45, 45, 45,802,802, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, +741,741,741, 65, 66,741,741,741,741, 58,724,724,163,163,163,163, + 50, 50, 50, 50,742,743,743,743,743,743, 50, 50,744,744,744,744, + 50,744,744, 50,744,744, 50,744, 45,743,743,744,744,744, 50, 45, +744,744, 45, 45, 45, 45,744,744, 45, 45, 45, 45,744,744,744,744, +744,744,744,744,744,744,744,744,744,744,744,744,744,744, 50, 50, +744,744, 50,744, 50,744,744,744,744,744,744,744, 45,744, 45, 45, + 45, 45, 45, 45,744,744, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, /* block 66 */ - 50, 50,803, 50, 50, 50, 50,803,804,804,804,804,804,804, 50, 50, - 50, 50,805, 53, 50,804, 50, 50, 50, 50, 50, 50, 50, 50,803,804, -804,804,804, 50,804, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,804,804, 50, 50, - 50, 50, 50,804, 50,804, 50, 50, 50, 50, 50, 50,804, 50, 50, 50, - 50, 50,804,804,804,804, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50,804,804,804,804,804,804,804,804, 50, 50,804,804, -804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804, + 50, 50, 50, 50, 50, 50, 50, 50,745,745,745,745,745,745, 50, 50, + 50, 50,746, 53, 50,745, 50, 50, 50, 50, 50, 50, 50, 50, 50,745, +745,745,745, 50,745, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,745,745, 50, 50, + 50, 50, 50,745, 50,745, 50, 50, 50, 50, 50, 50,745, 50, 50, 50, + 50, 50,745,745,745,745, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50,745,745,745,745,745,745,745,745, 50, 50,745,745, +745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745, /* block 67 */ -804,804,804,804,804,804,804,804,804,804,804,804, 50, 50, 50,804, -804,804,804, 50, 50, 50, 50, 50,804, 50, 50, 50, 50, 50, 50, 50, - 50, 50,804,804, 50, 50,804, 50,804,804, 50,804, 50, 50, 50, 50, -804,804,804,804,804,804,804,804,804, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50,804,804,804,804,804, 50, 50, -804,804, 50, 50, 50, 50,804,804,804,804,804,804,804,804,804,804, -804,804,804,804,804,804,804,804,804,804,804,804,804,804, 50, 50, -804,804,804,804,804, 50,804,804, 50, 50,804,804,804,804,804, 50, +745,745,745,745,745,745,745,745,745,745,745,745, 50, 50, 50,745, +745,745,745, 50, 50, 50, 50, 50,745, 50, 50, 50, 50, 50, 50, 50, + 50, 50,745,745, 50, 50,745, 50,745,745, 50,745, 50, 50, 50, 50, +745,745,745,745,745,745,745,745,745, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50,745,745,745,745,745, 50, 50, +745,745, 50, 50, 50, 50,745,745,745,745,745,745,745,745,745,745, +745,745,745,745,745,745,745,745,745,745,745,745,745,745, 50, 50, +745,745,745,745,745, 50,745,745, 50, 50,745,745,745,745,745, 50, /* block 68 */ - 45, 45, 45, 45, 45, 45, 45, 45,806,807,806,807, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,808,808, 45, 45, 45, 45, - 50, 50, 45, 45, 45, 45, 45, 45, 47,809,810, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45,811,811,811,811,811,811,811,811,811,811, -811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811, -811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811, -811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811, -811,811,811,811,811,811,811,811,811,811,811, 45, 50, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45,747,748,747,748, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,749,749, 45, 45, 45, 45, + 50, 50, 45, 45, 45, 45, 45, 45, 47,750,751, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45,752,752,752,752,752,752,752,752,752,752, +752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752, +752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752, +752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752, +752,752,752,752,752,752,752,752,752,752,752, 45, 50, 45, 45, 45, /* block 69 */ - 45, 45, 45, 45, 45, 45, 45, 45,812, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45,811, 45, 45, 45, 45, 45, 50, 50, 50, 50, 50, + 45, 45, 45, 45, 45, 45, 45, 45,753, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45,752, 45, 45, 45, 45, 45, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50,802,802, 45,802, 45, 45, 45, 45, 45, 45, 45, 45, + 50, 50, 50, 50,744,744, 45,744, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 47, -802, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 50, 50, 50, 50, - 50, 50,802, 45, 45, 45, 45, 45, 45,808,808,808,808, 47, 47, 47, -808, 47, 47,808, 45, 45, 45, 45, 47, 47, 47, 45, 45, 45, 45, 45, +744, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 50, 50, 50, 50, + 50, 50,744, 45, 45, 45, 45, 45, 45,749,749,749,749, 47, 47, 47, +749, 47, 47,749, 45, 45, 45, 45, 47, 47, 47, 45, 45, 45, 45, 45, /* block 70 */ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,813,813,813,813,813,813, -813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,813,813,813,813,813, -813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813, + 45, 45, 45, 45, 45, 45, 45,754,754,754,754,754,754,754,754,754, +754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,754,754,754,754,754, +754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, /* block 71 */ - 58, 58, 58, 58, 58, 58, 58, 58,814,814,814,814,814,814,814,814, -814,814,814,814,814,814,814,814,814,814,814,814,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,815,815,815,815,815,815,815,815,815,815, -815,815,816,815,815,815,815,815,815,815,815,815,815,815,815,815, -817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817, -817,817,817,817,817,817,817,817,817,817, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,755,755,755,755,755,755,755,755,755,755, +755,755,756,755,755,755,755,755,755,755,755,755,755,755,755,755, +757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757, +757,757,757,757,757,757,757,757,757,757, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, /* block 72 */ @@ -3376,2422 +3132,2322 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 80640 bytes, block = 128 */ /* block 73 */ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, -802,802, 45, 45, 45, 45, 45, 45, 45, 45, 47, 47, 45, 45,802,802, -802,802,802,802,802,802,801, 50, 45, 45, 45, 45,802,802,802,802, -801, 50, 45, 45, 45, 45,802,802, 45, 45,802,802, 45, 45, 45,802, -802,802,802,802, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45,802, 45,802, 45, 45,802,802,802,802,802,802, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 50, 50, 50,800,800,818,818, 50, +744,744, 45, 45, 45, 45, 45, 45, 45, 45, 47, 47, 45, 45,744,744, +744,744,744,744,744,744,743, 50, 45, 45, 45, 45,744,744,744,744, +743, 50, 45, 45, 45, 45,744,744, 45, 45,744,744, 45, 45, 45,744, +744,744,744,744, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45,744, 45,744, 45, 45,744,744,744,744,744,744, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 50, 50, 50,742,742,758,758, 50, /* block 74 */ - 47, 47, 47, 47, 47,819,802,812,812,812,812,812,812,812, 47,812, -812, 47,812, 45,808,808,812,812, 47,812,812,812,812,820,812,812, - 47,812, 47, 47,812,812, 47,812,812,812, 47,812,812,812, 47, 47, -812,812,812,812,812,812,812,812, 47, 47, 47,812,812,812,812,812, -801,812,801,812,812,812,812,812,808,808,808,808,808,808,808,808, -808,808,808,808,812,812,812,812,812,812,812,812,812,812,812, 47, -801,819,819,801,812, 47, 47,812, 47,812,812,812,812,819,819,821, -812,812,812,812,812,812,812,812,812,812,812, 47,812,812, 47,808, + 47, 47, 47, 47, 47,759,744,753,753,753,753,753,753,753, 47,753, +753, 47,753, 45,749,749,753,753, 47,753,753,753,753,760,753,753, + 47,753, 47, 47,753,753, 47,753,753,753, 47,753,753,753, 47, 47, +753,753,753,753,753,753,753,753, 47, 47, 47,753,753,753,753,753, +743,753,743,753,753,753,753,753,749,749,749,749,749,749,749,749, +749,749,749,749,753,753,753,753,753,753,753,753,753,753,753, 47, +743,759,759,743,753, 47, 47,753, 47,753,753,753,753,759,759,761, +753,753,753,753,753,753,753,753,753,753,753, 47,753,753, 47,749, /* block 75 */ -812,812,812,812,812,812, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, -812,812, 47,808, 47, 47, 47, 47,812, 47,812, 47, 47,812,812,812, - 47,808,812,812,812,812,812, 47,812,812,808,808,822,812,812,812, - 47, 47,812,812,812,812,812,812,812,812,812,812,812,808,808,812, -812,812,812,812,808,808,812,812, 47,812,812,812,812,812,808, 47, -812, 47,812, 47,808,812,812,812,812,812,812,812,812,812,812,812, -812,812,812,812,812,812,812,812,812, 47,808,812,812,812,812,812, - 47, 47,808,808, 47,808,812, 47, 47,820,808,812,812,808,812,812, +753,753,753,753,753,753, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, +753,753, 47,749, 47, 47, 47, 47,753, 47,753, 47, 47,753,753,753, + 47,749,753,753,753,753,753, 47,753,753,749,749,762,753,753,753, + 47, 47,753,753,753,753,753,753,753,753,753,753,753,749,749,753, +753,753,753,753,749,749,753,753, 47,753,753,753,753,753,749, 47, +753, 47,753, 47,749,753,753,753,753,753,753,753,753,753,753,753, +753,753,753,753,753,753,753,753,753, 47,749,753,753,753,753,753, + 47, 47,749,749, 47,749,753, 47, 47,760,749,753,753,749,753,753, /* block 76 */ -812,812, 47,812,812,808, 45, 45, 47, 47,823,823,820,820,812, 47, -812,812, 47, 45, 47, 45, 47, 45, 45, 45, 45, 45, 45, 47, 45, 45, - 45, 47, 45, 45, 45, 45, 45, 45,808, 45, 45, 45, 45, 45, 45, 45, +753,753, 47,753,753,749, 45, 45, 47, 47,763,763,760,760,753, 47, +753,753, 47, 45, 47, 45, 47, 45, 45, 45, 45, 45, 45, 47, 45, 45, + 45, 47, 45, 45, 45, 45, 45, 45,749, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 47, 47, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 47, 45, 45, 47, 45, 45, 45, 45,808, 45,808, 45, - 45, 45, 45,808,808,808, 45,808, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 47, 47,812,812,812,758,759,758,759,758,759,758,759, -758,759,758,759,758,759, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 45, 45, 45, 45, 47, 45, 45, 47, 45, 45, 45, 45,749, 45,749, 45, + 45, 45, 45,749,749,749, 45,749, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 47, 47,753,753,753,704,705,704,705,704,705,704,705, +704,705,704,705,704,705, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, /* block 77 */ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 45,808,808,808, 45, 45, 45, 45, 45, 45, 45, 45, + 58, 58, 58, 58, 45,749,749,749, 45, 45, 45, 45, 45, 45, 45, 45, 45, 47, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, -808, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,808, - 50, 50, 50,804,804,806,807, 50,804,804, 50,804, 50,804, 50, 50, - 50, 50, 50, 50, 50,804,804, 50, 50, 50, 50, 50,804,804,804, 50, - 50, 50,804,804,804,804,806,807,806,807,806,807,806,807,806,807, +749, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,749, + 50, 50, 50,745,745,747,748, 50,745,745, 50,745, 50,745, 50, 50, + 50, 50, 50, 50, 50,745,745, 50, 50, 50, 50, 50,745,745,745, 50, + 50, 50,745,745,745,745,747,748,747,748,747,748,747,748,747,748, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, /* block 78 */ -824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824, -824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824, -824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824, -824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824, -824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824, -824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824, -824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824, -824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824, +764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764, +764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764, +764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764, +764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764, +764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764, +764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764, +764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764, +764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764, /* block 79 */ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50,800,800, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50,742,742, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, /* block 80 */ - 50, 50, 50,806,807,806,807,806,807,806,807,806,807,806,807,806, -807,806,807,806,807,806,807,806,807, 50, 50,804, 50, 50, 50, 50, -804, 50, 50,804,804,804, 50, 50,804,804,804,804,804,804,804,804, - 50, 50, 50, 50, 50, 50, 50, 50,804, 50, 50, 50, 50, 50, 50, 50, -804,804, 50, 50,804,804, 50, 50, 50, 50, 50, 50, 50, 50, 50,804, -804,804,804, 50,804,804, 50, 50,806,807,806,807, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50,804,804, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50,804, 50, 50,804,804, 50, 50,806,807, 50, 50, + 50, 50, 50,747,748,747,748,747,748,747,748,747,748,747,748,747, +748,747,748,747,748,747,748,747,748, 50, 50,745, 50, 50, 50, 50, +745, 50, 50,745,745,745, 50, 50,745,745,745,745,745,745,745,745, + 50, 50, 50, 50, 50, 50, 50, 50,745, 50, 50, 50, 50, 50, 50, 50, +745,745, 50, 50,745,745, 50, 50, 50, 50, 50, 50, 50, 50, 50,745, +745,745,745, 50,745,745, 50, 50,747,748,747,748, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50,745,745, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50,745, 50, 50,745,745, 50, 50,747,748, 50, 50, /* block 81 */ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,804,804,804,804, 50, - 50, 50, 50, 50,804,804, 50, 50, 50, 50, 50, 50,804,804, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,745,745,745,745, 50, + 50, 50, 50, 50,745,745, 50, 50, 50, 50, 50, 50,745,745, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50,804,804, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50,804,804,804,804,804,804,804, + 50, 50, 50, 50,745,745, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50,745,745,745,745,745,745,745, /* block 82 */ -804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804, -804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804, -804,804,804, 50, 50, 50,804,804,804,804,804,804,804,804, 50,804, -804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804, -804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804, -804,804,804,804,804,804,804, 50, 50, 50, 50, 50, 50, 50,804, 50, - 50, 50, 50,804,804,804, 50, 50, 50, 50, 50, 50,804,804,804, 50, - 50, 50, 50, 50, 50, 50, 50,804,804,804,804, 50, 50, 50, 50, 50, +745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745, +745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745, +745,745,745, 50, 50, 50,745,745,745,745,745,745,745,745, 50,745, +745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745, +745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745, +745,745,745,745,745,745,745, 50, 50, 50, 50, 50, 50, 50,745, 50, + 50, 50, 50,745,745,745, 50, 50, 50, 50, 50, 50,745,745,745, 50, + 50, 50, 50, 50, 50, 50, 50,745,745,745,745, 50, 50, 50, 50, 50, /* block 83 */ 45, 45, 45, 45, 45, 47, 47, 47, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,808,808, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,749,749, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 45, 45, 50, 50, 50, 50, 50, 50, 45, 45, 45, -808, 45, 45, 45, 45,808, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, +749, 45, 45, 45, 45,749, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45,813,813, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45,754,754, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, /* block 84 */ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45,813, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45,754, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,825, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,765, 45, /* block 85 */ -826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826, -826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826, -826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826, -827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827, -827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827, -827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827, - 65, 66,828,829,830,831,832, 65, 66, 65, 66, 65, 66,833,834,835, -836, 70, 65, 66, 70, 65, 66, 70, 70, 70, 70, 70,696,695,837,837, +766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766, +766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766, +766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766, +767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767, +767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767, +767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767, + 65, 66,768,769,770,771,772, 65, 66, 65, 66, 65, 66,773,774,775, +776, 70, 65, 66, 70, 65, 66, 70, 70, 70, 70, 70,646,645,777,777, /* block 86 */ -246,247,246,247,246,247,246,247,246,247,246,247,246,247,246,247, -246,247,246,247,246,247,246,247,246,247,246,247,246,247,246,247, -246,247,246,247,246,247,246,247,246,247,246,247,246,247,246,247, -246,247,246,247,246,247,246,247,246,247,246,247,246,247,246,247, -246,247,246,247,246,247,246,247,246,247,246,247,246,247,246,247, -246,247,246,247,246,247,246,247,246,247,246,247,246,247,246,247, -246,247,246,247,838,839,839,839,839,839,839,246,247,246,247,840, -840,840,246,247,196,196,196,196,196,841,841,841,842,843,842,842, +211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212, +211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212, +211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212, +211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212, +211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212, +211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212, +211,212,211,212,778,779,779,779,779,779,779,211,212,211,212,780, +780,780,211,212,163,163,163,163,163,781,781,781,781,782,781,781, /* block 87 */ -844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844, -844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844, -844,844,844,844,844,844,196,844,196,196,196,196,196,844,196,196, -845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845, -845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845, -845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845, -845,845,845,845,845,845,845,845,196,196,196,196,196,196,196,846, -847,196,196,196,196,196,196,196,196,196,196,196,196,196,196,848, +783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783, +783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783, +783,783,783,783,783,783,163,783,163,163,163,163,163,783,163,163, +784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784, +784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784, +784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784, +784,784,784,784,784,784,784,784,163,163,163,163,163,163,163,785, +786,163,163,163,163,163,163,163,163,163,163,163,163,163,163,787, /* block 88 */ -533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533, -533,533,533,533,533,533,533,196,196,196,196,196,196,196,196,196, -533,533,533,533,533,533,533,196,533,533,533,533,533,533,533,196, -533,533,533,533,533,533,533,196,533,533,533,533,533,533,533,196, -533,533,533,533,533,533,533,196,533,533,533,533,533,533,533,196, -533,533,533,533,533,533,533,196,533,533,533,533,533,533,533,196, -849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849, -849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,163,163,163,163,163,163,163,163,163, +484,484,484,484,484,484,484,163,484,484,484,484,484,484,484,163, +484,484,484,484,484,484,484,163,484,484,484,484,484,484,484,163, +484,484,484,484,484,484,484,163,484,484,484,484,484,484,484,163, +484,484,484,484,484,484,484,163,484,484,484,484,484,484,484,163, +788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788, +788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788, /* block 89 */ - 43, 43,850,851,850,851, 43, 43, 43,850,851, 43,850,851, 43, 43, - 43, 43, 43, 43, 43, 43, 43,852, 43, 43,734, 43,850,851, 43, 43, -850,851,758,759,758,759,758,759,758,759, 43, 43, 43, 43,754,853, -854,855, 43, 43, 43, 43, 43, 43, 43, 43,734,734,856, 43, 43, 43, -734,857,738,858, 43, 43, 43, 43, 43, 43, 43, 43,859, 43,859,859, - 45, 45, 43,754,754,758,759,758,759,758,759,758,759,734,813,813, -813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813, -813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813, + 43, 43,789,790,789,790, 43, 43, 43,789,790, 43,789,790, 43, 43, + 43, 43, 43, 43, 43, 43, 43,681, 43, 43,681, 43,789,790, 43, 43, +789,790,704,705,704,705,704,705,704,705, 43, 43, 43, 43,700,791, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,681,681,700, 43, 43, 43, +681,792,685,793, 43, 43, 43, 43, 43, 43, 43, 43,792, 43,792,792, + 45, 45, 43,700,700,704,705,704,705,704,705,704,705,681,754,754, +754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754, +754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754, /* block 90 */ -860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860, -860,860,860,860,860,860,860,860,860,860,196,860,860,860,860,860, -860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860, -860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860, -860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860, -860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860, -860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860, -860,860,860,860,196,196,196,196,196,196,196,196,196,196,196,196, +794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794, +794,794,794,794,794,794,794,794,794,794,163,794,794,794,794,794, +794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794, +794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794, +794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794, +794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794, +794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794, +794,794,794,794,163,163,163,163,163,163,163,163,163,163,163,163, /* block 91 */ -860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860, -860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860, -860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860, -860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860, -860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860, -860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860, -860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860, -860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860, +794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794, +794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794, +794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794, +794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794, +794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794, +794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794, +794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794, +794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794, /* block 92 */ -860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860, -860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860, -860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860, -860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860, -860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860, -860,860,860,860,860,860,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -861,861,862,862,861,861,861,861,861,861,861,861,861,861,863,863, +794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794, +794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794, +794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794, +794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794, +794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794, +794,794,794,794,794,794,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +795,795,796,796,795,795,795,795,795,795,795,795,163,163,163,163, /* block 93 */ -729,864,865,866,781,867,868,869,870,871,872,873,874,875,874,875, -876,877, 45,878,876,877,876,877,876,877,876,877,879,880,881,881, - 45,869,869,869,869,869,869,869,869,869,882,882,882,882,883,883, -884,885,885,885,885,885,781,886,869,869,869,887,888,889,890,890, -196,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, -891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, -891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, -891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, +676,797,798,799,724,800,801,802,803,804,803,804,805,806,805,806, +803,804, 45,807,803,804,803,804,803,804,803,804,808,809,810,810, + 45,802,802,802,802,802,802,802,802,802,811,811,811,811,812,812, +813,814,814,814,814,814,724,815,802,802,802,816,817,818,819,819, +163,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, /* block 94 */ -891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, -891,891,891,891,891,891,891,196,196,892,892,893,893,894,894,891, -895,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896, -896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896, -896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896, -896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896, -896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896, -896,896,896,896,896,896,896,896,896,896,896,897,898,899,899,896, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,163,163,821,821,822,822,823,823,820, +824,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825, +825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825, +825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825, +825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825, +825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825, +825,825,825,825,825,825,825,825,825,825,825,826,827,828,828,825, /* block 95 */ -196,196,196,196,196,900,900,900,900,900,900,900,900,900,900,900, -900,900,900,900,900,900,900,900,900,900,900,900,900,900,900,900, -900,900,900,900,900,900,900,900,900,900,900,900,900,900,900,900, -196,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901, -901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901, -901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901, -901,901,901,901,902,901,901,901,901,901,901,901,901,901,901,901, -901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901, +163,163,163,163,163,829,829,829,829,829,829,829,829,829,829,829, +829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829, +829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829, +163,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830, +830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830, +830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830, +830,830,830,830,831,830,830,830,830,830,830,830,830,830,830,830, +830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830, /* block 96 */ -901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,196, -903,903,904,904,904,904,903,903,903,903,903,903,903,903,903,903, -900,900,900,900,900,900,900,900,900,900,900,900,900,900,900,900, -900,900,900,900,900,900,900,900,900,900,900,900,900,900,900,900, -890,890,890,890,890,890,890,890,890,890,890,890,890,890,890,890, -890,890,890,890,890,890,890,890,890,890,890,890,890,890,890,890, -890,890,890,890,890,890,196,196,196,196,196,196,196,196,196,861, -896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896, +830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,163, +832,832,833,833,833,833,832,832,832,832,832,832,832,832,832,832, +829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829, +829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829, +819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819, +819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819, +819,819,819,819,163,163,163,163,163,163,163,163,163,163,163,163, +825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825, /* block 97 */ -905,905,905,905,905,905,905,905,905,905,905,905,905,905,905,905, -905,905,905,905,905,905,905,905,905,905,905,905,905,906,906,196, -904,904,904,904,904,904,904,904,904,904,903,903,903,903,903,903, -903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,903, -903,903,903,903,903,903,903,903,907,907,907,907,907,907,907,907, -781, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, -905,905,905,905,905,905,905,905,905,905,905,905,905,905,905,905, -905,905,905,905,905,905,905,905,905,905,905,905,906,906,906,510, +834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834, +834,834,834,834,834,834,834,834,834,834,834,834,834,835,835,163, +833,833,833,833,833,833,833,833,833,833,832,832,832,832,832,832, +832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832, +832,832,832,832,832,832,832,832,836,836,836,836,836,836,836,836, +724, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, +834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834, +834,834,834,834,834,834,834,834,834,834,834,834,835,835,835,461, /* block 98 */ -904,904,904,904,904,904,904,904,904,904,903,903,903,903,903,903, -903,903,903,903,903,903,903,908,903,908,903,903,903,903,903,903, -903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,903, -903, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, -903,903,903,903,903,903,903,903,903,903,903,903,781,781,781,781, -909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909, -909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909, -909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,903, +833,833,833,833,833,833,833,833,833,833,832,832,832,832,832,832, +832,832,832,832,832,832,832,837,832,837,832,832,832,832,832,832, +832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832, +832, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, +832,832,832,832,832,832,832,832,832,832,832,832,724,724,724,724, +838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838, +838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838, +838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,832, /* block 99 */ -909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909, -909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909, -909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909, -909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909, -909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909, -909,909,909,909,909,909,909,909,903,903,903,903,903,903,903,903, -903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,903, -903,510,510,510,510,510,510,781,781,781,781,903,903,903,903,903, +838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838, +838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838, +838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838, +838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838, +838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838, +838,838,838,838,838,838,838,838,832,832,832,832,832,832,832,832, +832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832, +832,461,461,461,461,461,461,724,724,724,724,832,832,832,832,832, /* block 100 */ -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,781,781, -903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,903, -903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,781, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,724,724, +832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832, +832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,724, /* block 101 */ -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, /* block 102 */ -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, /* block 103 */ -911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, -911,911,911,911,911,912,911,911,911,911,911,911,911,911,911,911, -911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, -911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, -911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, -911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, -911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, -911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, +840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840, +840,840,840,840,840,841,840,840,840,840,840,840,840,840,840,840, +840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840, +840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840, +840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840, +840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840, +840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840, +840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840, /* block 104 */ -911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, -911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, -911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, -911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, -911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, -911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, -911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, -911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, +840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840, +840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840, +840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840, +840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840, +840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840, +840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840, +840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840, +840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840, /* block 105 */ -911,911,911,911,911,911,911,911,911,911,911,911,911,196,196,196, -913,913,913,913,913,913,913,913,913,913,913,913,913,913,913,913, -913,913,913,913,913,913,913,913,913,913,913,913,913,913,913,913, -913,913,913,913,913,913,913,913,913,913,913,913,913,913,913,913, -913,913,913,913,913,913,913,196,196,196,196,196,196,196,196,196, -914,914,914,914,914,914,914,914,914,914,914,914,914,914,914,914, -914,914,914,914,914,914,914,914,914,914,914,914,914,914,914,914, -914,914,914,914,914,914,914,914,915,915,915,915,915,915,916,917, +840,840,840,840,840,840,840,840,840,840,840,840,840,163,163,163, +842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842, +842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842, +842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842, +842,842,842,842,842,842,842,163,163,163,163,163,163,163,163,163, +843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843, +843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843, +843,843,843,843,843,843,843,843,844,844,844,844,844,844,845,846, /* block 106 */ -918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918, -918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918, -918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918, -918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918, -918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918, -918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918, -918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918, -918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918, +847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847, +847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847, +847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847, +847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847, +847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847, +847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847, +847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847, +847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847, /* block 107 */ -918,918,918,918,918,918,918,918,918,918,918,918,919,920,921,921, -918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918, -922,922,922,922,922,922,922,922,922,922,918,918,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -275,276,275,276,275,276,275,276,275,276,923,924,275,276,275,276, -275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276, -275,276,275,276,275,276,275,276,275,276,275,276,275,276,925,281, -283,283,283,926,849,849,849,849,849,849,849,849,927,927,926,928, +847,847,847,847,847,847,847,847,847,847,847,847,848,849,850,850, +847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847, +851,851,851,851,851,851,851,851,851,851,847,847,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +240,241,240,241,240,241,240,241,240,241,852,853,240,241,240,241, +240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241, +240,241,240,241,240,241,240,241,240,241,240,241,240,241,854,246, +248,248,248,855,788,788,788,788,788,788,788,788,856,856,855,857, /* block 108 */ -275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276, -275,276,275,276,275,276,275,276,275,276,275,276,929,929,849,849, -930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930, -930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930, -930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930, -930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930, -930,930,930,930,930,930,931,931,931,931,931,931,931,931,931,931, -932,932,933,934,935,935,935,934,196,196,196,196,196,196,196,196, +240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241, +240,241,240,241,240,241,240,241,240,241,240,241,858,858,788,788, +859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859, +859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859, +859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859, +859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859, +859,859,859,859,859,859,860,860,860,860,860,860,860,860,860,860, +861,861,862,863,864,864,864,863,163,163,163,163,163,163,163,163, /* block 109 */ -936,936,936,936,936,936,936,936, 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46,151,151,151,151,151,151,151,151,151, +865,865,865,865,865,865,865,865, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46,149,149,149,149,149,149,149,149,149, 46, 46, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 70, 70, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, -695, 70, 70, 70, 70, 70, 70, 70, 70, 65, 66, 65, 66,937, 65, 66, +645, 70, 70, 70, 70, 70, 70, 70, 70, 65, 66, 65, 66,866, 65, 66, /* block 110 */ - 65, 66, 65, 66, 65, 66, 65, 66,151,938,938, 65, 66,939, 70, 93, - 65, 66, 65, 66,940, 70, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, - 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,941,942,943,944,941, 70, -945,946,947,948, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, - 65, 66, 65, 66,949,950,951, 65, 66, 65, 66,952, 65, 66,196,196, - 65, 66,196, 70,196, 70, 65, 66, 65, 66, 65, 66,953,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,695,695,695, 65, 66, 93,149,149, 70, 93, 93, 93, 93, 93, + 65, 66, 65, 66, 65, 66, 65, 66,149,867,867, 65, 66,868, 70, 92, + 65, 66, 65, 66,869, 70, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, + 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,870,871,872,873,870, 70, +874,875,876,877, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, + 65, 66, 65, 66,878,879,880, 65, 66, 65, 66,163,163,163,163,163, + 65, 66,163, 70,163, 70, 65, 66, 65, 66,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,645,645,645, 65, 66, 92,147,147, 70, 92, 92, 92, 92, 92, /* block 111 */ -954,954,955,954,954,954,956,954,954,954,954,955,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,957,957,955,955,957,958,958,958,958,956,196,196,196, -959,959,959,960,960,960,961,961,962,963,196,196,196,196,196,196, -964,964,964,964,964,964,964,964,964,964,964,964,964,964,964,964, -964,964,964,964,964,964,964,964,964,964,964,964,964,964,964,964, -964,964,964,964,964,964,964,964,964,964,964,964,964,964,964,964, -964,964,964,964,965,965,966,966,196,196,196,196,196,196,196,196, +881,881,882,881,881,881,883,881,881,881,881,882,881,881,881,881, +881,881,881,881,881,881,881,881,881,881,881,881,881,881,881,881, +881,881,881,884,884,882,882,884,885,885,885,885,883,163,163,163, +886,886,886,887,887,887,888,888,889,890,163,163,163,163,163,163, +891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, +891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, +891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, +891,891,891,891,892,892,893,893,163,163,163,163,163,163,163,163, /* block 112 */ -967,967,968,968,968,968,968,968,968,968,968,968,968,968,968,968, -968,968,968,968,968,968,968,968,968,968,968,968,968,968,968,968, -968,968,968,968,968,968,968,968,968,968,968,968,968,968,968,968, -968,968,968,968,967,967,967,967,967,967,967,967,967,967,967,967, -967,967,967,967,969,970,196,196,196,196,196,196,196,196,971,971, -972,972,972,972,972,972,972,972,972,972,196,196,196,196,196,196, -378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378, -378,973,376,974,376,376,376,376,385,385,385,376,385,376,376,374, +894,894,895,895,895,895,895,895,895,895,895,895,895,895,895,895, +895,895,895,895,895,895,895,895,895,895,895,895,895,895,895,895, +895,895,895,895,895,895,895,895,895,895,895,895,895,895,895,895, +895,895,895,895,894,894,894,894,894,894,894,894,894,894,894,894, +894,894,894,894,896,897,163,163,163,163,163,163,163,163,898,898, +899,899,899,899,899,899,899,899,899,899,163,163,163,163,163,163, +336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, +336,900,335,901,335,335,335,335,343,343,343,335,343,335,335,333, /* block 113 */ -975,975,975,975,975,975,975,975,975,975,976,976,976,976,976,976, -976,976,976,976,976,976,976,976,976,976,976,976,976,976,976,976, -976,976,976,976,976,976,977,977,977,977,977,978,978,978,979,980, -981,981,981,981,981,981,981,981,981,981,981,981,981,981,981,981, -981,981,981,981,981,981,981,982,982,982,982,982,982,982,982,982, -982,982,983,984,196,196,196,196,196,196,196,196,196,196,196,985, -528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528, -528,528,528,528,528,528,528,528,528,528,528,528,528,196,196,196, +902,902,902,902,902,902,902,902,902,902,903,903,903,903,903,903, +903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,903, +903,903,903,903,903,903,904,904,904,904,904,905,905,905,906,907, +908,908,908,908,908,908,908,908,908,908,908,908,908,908,908,908, +908,908,908,908,908,908,908,909,909,909,909,909,909,909,909,909, +909,909,910,911,163,163,163,163,163,163,163,163,163,163,163,912, +479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, +479,479,479,479,479,479,479,479,479,479,479,479,479,163,163,163, /* block 114 */ -986,986,986,987,988,988,988,988,988,988,988,988,988,988,988,988, -988,988,988,988,988,988,988,988,988,988,988,988,988,988,988,988, -988,988,988,988,988,988,988,988,988,988,988,988,988,988,988,988, -988,988,988,989,987,987,986,986,986,986,987,987,986,986,987,987, -990,991,991,991,991,991,991,992,993,993,991,991,991,991,196,994, -995,995,995,995,995,995,995,995,995,995,196,196,196,196,991,991, -511,511,511,511,511,521,996,511,511,511,511,511,511,511,511,511, -522,522,522,522,522,522,522,522,522,522,511,511,511,511,511,196, +913,913,913,914,915,915,915,915,915,915,915,915,915,915,915,915, +915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915, +915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915, +915,915,915,916,914,914,913,913,913,913,914,914,913,913,914,914, +917,918,918,918,918,918,918,919,920,920,918,918,918,918,163,921, +922,922,922,922,922,922,922,922,922,922,163,163,163,163,918,918, +462,462,462,462,462,472,923,462,462,462,462,462,462,462,462,462, +473,473,473,473,473,473,473,473,473,473,462,462,462,462,462,163, /* block 115 */ -997,997,997,997,997,997,997,997,997,997,997,997,997,997,997,997, -997,997,997,997,997,997,997,997,997,997,997,997,997,997,997,997, -997,997,997,997,997,997,997,997,997,998,998,998,998,998,998,999, -999,998,998,999,999,998,998,196,196,196,196,196,196,196,196,196, -997,997,997,998,997,997,997,997,997,997,997,997,998,999,196,196, -1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,196,196,1001,1002,1002,1002, -511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511, -996,511,511,511,511,511,511,523,523,523,511,520,521,520,511,511, +924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924, +924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924, +924,924,924,924,924,924,924,924,924,925,925,925,925,925,925,926, +926,925,925,926,926,925,925,163,163,163,163,163,163,163,163,163, +924,924,924,925,924,924,924,924,924,924,924,924,925,926,163,163, +927,927,927,927,927,927,927,927,927,927,163,163,928,929,929,929, +462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462, +923,462,462,462,462,462,462,474,474,474,462,471,472,471,462,462, /* block 116 */ -1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003, -1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003, -1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003, -1004,1003,1004,1004,1004,1005,1005,1004,1004,1005,1003,1005,1005,1003,1004,1006, -1007,1006,1007,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,1003,1003,1008,1009,1010, -1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1012,1013,1013,1012,1012, -1014,1014,1011,1015,1015,1012,1016,196,196,196,196,196,196,196,196,196, +930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930, +930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930, +930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930, +931,930,931,931,931,932,932,931,931,932,930,932,932,930,931,933, +934,933,934,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,930,930,935,936,937, +938,938,938,938,938,938,938,938,938,938,938,939,940,940,939,939, +941,941,938,942,942,939,943,163,163,163,163,163,163,163,163,163, /* block 117 */ -196,533,533,533,533,533,533,196,196,533,533,533,533,533,533,196, -196,533,533,533,533,533,533,196,196,196,196,196,196,196,196,196, -533,533,533,533,533,533,533,196,533,533,533,533,533,533,533,196, +163,484,484,484,484,484,484,163,163,484,484,484,484,484,484,163, +163,484,484,484,484,484,484,163,163,163,163,163,163,163,163,163, +484,484,484,484,484,484,484,163,484,484,484,484,484,484,484,163, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70,1017, 70, 70, 70, 70, 70, 70, 70,938,149,149,149,149, - 70, 70, 70, 70, 70,256, 70, 70, 70,149, 46, 46,196,196,196,196, -1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018, + 70, 70, 70,944, 70, 70, 70, 70, 70, 70, 70,867,147,147,147,147, + 70, 70, 70, 70, 70,221, 70, 70, 70,147, 46, 46,163,163,163,163, +945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945, /* block 118 */ -1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018, -1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018, -1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018, -1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018, -1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011, -1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011, -1011,1011,1011,1012,1012,1013,1012,1012,1013,1012,1012,1014,1019,1016,196,196, -1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,196,196,196,196,196,196, +945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945, +945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945, +945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945, +945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945, +938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938, +938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938, +938,938,938,939,939,940,939,939,940,939,939,941,946,943,163,163, +947,947,947,947,947,947,947,947,947,947,163,163,163,163,163,163, /* block 119 */ -1021,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1021,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1021,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1021,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1021,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, +948,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,948,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,948,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,948,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +948,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, /* block 120 */ -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1021,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1021,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1021,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1021,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1021,1022,1022,1022, +949,949,949,949,949,949,949,949,949,949,949,949,948,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,948,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,948,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +948,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,948,949,949,949, /* block 121 */ -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1021,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1021,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1021,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1021,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,948,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,948,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +948,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,948,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, /* block 122 */ -1022,1022,1022,1022,1022,1022,1022,1022,1021,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1021,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1021,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1021,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1021,1022,1022,1022,1022,1022,1022,1022, +949,949,949,949,949,949,949,949,948,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,948,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +948,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,948,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,948,949,949,949,949,949,949,949, /* block 123 */ -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1021,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1021,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1021,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1021,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,948,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +948,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,948,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,948,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, /* block 124 */ -1022,1022,1022,1022,1021,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1021,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1021,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1021,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1021,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, +949,949,949,949,948,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +948,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,948,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,948,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,948,949,949,949,949,949,949,949,949,949,949,949, /* block 125 */ -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1021,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1021,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1021,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1021,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +948,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,948,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,948,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,948,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, /* block 126 */ -1022,1022,1022,1022,1022,1022,1022,1022,1021,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022, -1022,1022,1022,1022,196,196,196,196,196,196,196,196,196,196,196,196, -531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531, -531,531,531,531,531,531,531,196,196,196,196,532,532,532,532,532, -532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532, -532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532, -532,532,532,532,532,532,532,532,532,532,532,532,196,196,196,196, +949,949,949,949,949,949,949,949,948,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,163,163,163,163,163,163,163,163,163,163,163,163, +482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, +482,482,482,482,482,482,482,163,163,163,163,483,483,483,483,483, +483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483, +483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483, +483,483,483,483,483,483,483,483,483,483,483,483,163,163,163,163, /* block 127 */ -1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023, -1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023, -1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023, -1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023, -1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023, -1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023, -1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023, -1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023, +950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950, +950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950, +950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950, +950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950, +950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950, +950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950, +950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950, +950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950, /* block 128 */ -1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024, -1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024, -1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024, -1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024, -1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024, -1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024, -1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024, -1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024, +951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951, +951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951, +951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951, +951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951, +951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951, +951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951, +951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951, +951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951, /* block 129 */ -1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, -1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, -1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, -1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, -1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, -1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, -1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, -1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, +952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952, +952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952, +952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952, +952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952, +952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952, +952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952, +952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952, +952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952, /* block 130 */ -1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,910,910, -1025,910,1025,910,910,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,910, -1025,910,1025,910,910,1025,1025,910,910,910,1025,1025,1025,1025,1025,1025, -1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, -1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, -1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, -1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,196,196, -1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, +952,952,952,952,952,952,952,952,952,952,952,952,952,952,839,839, +952,839,952,839,839,952,952,952,952,952,952,952,952,952,952,839, +952,839,952,839,839,952,952,839,839,839,952,952,952,952,952,952, +952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952, +952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952, +952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952, +952,952,952,952,952,952,952,952,952,952,952,952,952,952,163,163, +952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952, /* block 131 */ -1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, -1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, -1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, -1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, -1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, -1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952, +952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952, +952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952, +952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952, +952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952, +952,952,952,952,952,952,952,952,952,952,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 132 */ -703,703,703,703,703,1026,1027,196,196,196,196,196,196,196,196,196, -196,196,196,292,292,292,292,292,196,196,196,196,196,305,300,305, -305,305,305,305,305,305,305,305,305,1028,305,305,305,305,305,305, -305,305,305,305,305,305,305,297,305,305,305,305,305,297,305,297, -305,305,297,305,305,297,305,305,305,305,305,305,305,305,305,305, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, +653,653,653,653,653,653,653,163,163,163,163,163,163,163,163,163, +163,163,163,257,257,257,257,257,163,163,163,163,163,270,265,270, +270,270,270,270,270,270,270,270,270,953,270,270,270,270,270,270, +270,270,270,270,270,270,270,262,270,270,270,270,270,262,270,262, +270,270,262,270,270,262,270,270,270,270,270,270,270,270,270,270, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, /* block 133 */ -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,370,370,370,370,370,370,370,370,370,370,370,370,370,370, -370,370,370,340,340,340,340,340,340,340,340,340,340,340,340,340, -340,340,340,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,331,331,331,331,331,331,331,331,331,331,331,331,331,331, +331,331,331,302,302,302,302,302,302,302,302,302,302,302,302,302, +302,302,302,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, /* block 134 */ -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,1029,1029, -1029,1029,1029,1029,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,954,954, +954,954,954,954,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, /* block 135 */ -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, /* block 136 */ -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,1030,1031, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,955,956, +280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, /* block 137 */ -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -340,340,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,340,340,340,340,340,340,340,315, -1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032, -1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032, -321,321,1033,321,321,321,321,321,321,321,1029,1029,312,1034,315,315, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +302,302,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,302,302,302,302,302,302,302,280, +957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957, +957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957, +286,286,958,286,286,286,286,286,286,286,954,954,277,959,280,280, /* block 138 */ -1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1036, -1037,1037,1038,1039,1037,1038,1038,1040,1041,1037,196,196,196,196,196,196, -176,176,176,176,176,176,176,176,176,176,176,176,176,176,927,927, -1037,1042,1042,755,755,1040,1041,1040,1041,1040,1041,1040,1041,1040,1041,1040, -1041,1043,1044,1043,1044,866,866,1040,1041,1037,1037,1037,1037,755,755,755, -1045,199,1046,196,199,1047,1038,1038,1042,1048,1049,1048,1049,1048,1049,1050, -1037,1051,1052,1053,1054,1054,794,196,1051,479,1050,1037,196,196,196,196, -1029,321,1029,321,1029,340,1029,321,1029,321,1029,321,1029,321,1029,321, +960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,961, +962,962,962,963,962,962,962,964,965,962,163,163,163,163,163,163, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,856,856, +962,966,966,701,701,964,965,964,965,964,965,964,965,964,965,964, +965,967,968,967,968,799,799,964,965,962,962,962,962,701,701,701, +969,166,970,163,166,971,972,972,966,973,974,973,974,973,974,975, +962,976,714,977,978,978,716,163,976,430,975,962,163,163,163,163, +954,286,954,286,954,302,954,286,954,286,954,286,954,286,954,286, /* block 139 */ -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,340,340, 51, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286, +286,286,286,286,286,286,286,286,286,286,286,286,286,302,302, 51, /* block 140 */ -196,1038,1055,1050,479,1050,1037,1056,1048,1049,1037,1052,1045,1057,1046,1058, -1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,1047,199,1054,794,1054,1038, -1037,1060,1060,1060,1060,1060,1060, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,1048,1051,1049,1061,755, - 46,1062,1062,1062,1062,1062,1062, 62, 62, 62, 62, 62, 62, 62, 62, 62, - 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,1048,794,1049,794,1048, -1049,1063,1064,1065,1066,897,896,896,896,896,896,896,896,896,896,896, -898,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896, +163,972,979,975,430,975,962,980,973,974,962,714,969,981,970,982, +983,983,983,983,983,983,983,983,983,983,971,166,978,716,978,972, +962,984,984,984,984,984,984, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,973,976,974,985,701, + 46,986,986,986,986,986,986, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,973,716,974,716,973, +974,987,988,989,990,826,825,825,825,825,825,825,825,825,825,825, +827,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825, /* block 141 */ -896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896, -896,896,896,896,896,896,896,896,896,896,896,896,896,896,1067,1067, -902,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901, -901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,196, -196,196,901,901,901,901,901,901,196,196,901,901,901,901,901,901, -196,196,901,901,901,901,901,901,196,196,901,901,901,196,196,196, -479,479,794, 46,781,479,479,196,781,794,794,794,794,781,781,196, -765,765,765,765,765,765,765,765,765,1068,1068,1068,781,781,1032,1032, +825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825, +825,825,825,825,825,825,825,825,825,825,825,825,825,825,991,991, +831,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830, +830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,163, +163,163,830,830,830,830,830,830,163,163,830,830,830,830,830,830, +163,163,830,830,830,830,830,830,163,163,830,830,830,163,163,163, +430,430,716, 46,724,430,430,163,724,716,716,716,716,724,724,163, +708,708,708,708,708,708,708,708,708,992,992,992,724,724,957,957, /* block 142 */ -1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,196,1069,1069,1069, -1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069, -1069,1069,1069,1069,1069,1069,1069,196,1069,1069,1069,1069,1069,1069,1069,1069, -1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,196,1069,1069,196,1069, -1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,196,196, -1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +993,993,993,993,993,993,993,993,993,993,993,993,163,993,993,993, +993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993, +993,993,993,993,993,993,993,163,993,993,993,993,993,993,993,993, +993,993,993,993,993,993,993,993,993,993,993,163,993,993,163,993, +993,993,993,993,993,993,993,993,993,993,993,993,993,993,163,163, +993,993,993,993,993,993,993,993,993,993,993,993,993,993,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 143 */ -1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069, -1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069, -1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069, -1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069, -1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069, -1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069, -1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069, -1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,196,196,196,196,196, +993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993, +993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993, +993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993, +993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993, +993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993, +993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993, +993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993, +993,993,993,993,993,993,993,993,993,993,993,163,163,163,163,163, /* block 144 */ -1070,1071,1072,196,196,196,196,1073,1073,1073,1073,1073,1073,1073,1073,1073, -1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073, -1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073, -1073,1073,1073,1073,196,196,196,1074,1074,1074,1074,1074,1074,1074,1074,1074, -1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075, -1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075, -1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075, -1075,1075,1075,1075,1075,1076,1076,1076,1076,1077,1077,1077,1077,1077,1077,1077, +994,995,996,163,163,163,163,997,997,997,997,997,997,997,997,997, +997,997,997,997,997,997,997,997,997,997,997,997,997,997,997,997, +997,997,997,997,997,997,997,997,997,997,997,997,997,997,997,997, +997,997,997,997,163,163,163,998,998,998,998,998,998,998,998,998, +999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999, +999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999, +999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999, +999,999,999,999,999,1000,1000,1000,1000,1001,1001,1001,1001,1001,1001,1001, /* block 145 */ -1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1076,1076,1077,1078,1078,196, -781,781,781,781,781,781,781,781,781,781,781,781,781,196,196,196, -1077,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,189,196,196, +1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1000,1000,1001,1002,1002,163, +724,724,724,724,724,724,724,724,724,724,724,724,724,163,163,163, +1001,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,158,163,163, /* block 146 */ -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 147 */ -1079,1079,1079,1079,1079,1079,1079,1079,1079,1079,1079,1079,1079,1079,1079,1079, -1079,1079,1079,1079,1079,1079,1079,1079,1079,1079,1079,1079,1079,196,196,196, -1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080, -1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080, -1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080, -1080,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -1081,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082, -1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,196,196,196,196, +1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003, +1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,163,163,163, +1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004, +1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004, +1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004, +1004,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +1005,1006,1006,1006,1006,1006,1006,1006,1006,1006,1006,1006,1006,1006,1006,1006, +1006,1006,1006,1006,1006,1006,1006,1006,1006,1006,1006,1006,163,163,163,163, /* block 148 */ -1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083, -1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083, -1084,1084,1084,1084,196,196,196,196,196,196,196,196,196,1083,1083,1083, -1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085, -1085,1086,1085,1085,1085,1085,1085,1085,1085,1085,1086,196,196,196,196,196, -1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087, -1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087, -1087,1087,1087,1087,1087,1087,1088,1088,1088,1088,1088,196,196,196,196,196, +1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007, +1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007, +1008,1008,1008,1008,163,163,163,163,163,163,163,163,163,1007,1007,1007, +1009,1009,1009,1009,1009,1009,1009,1009,1009,1009,1009,1009,1009,1009,1009,1009, +1009,1010,1009,1009,1009,1009,1009,1009,1009,1009,1010,163,163,163,163,163, +1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011, +1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011, +1011,1011,1011,1011,1011,1011,1012,1012,1012,1012,1012,163,163,163,163,163, /* block 149 */ -1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089, -1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,196,1090, -1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091, -1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091, -1091,1091,1091,1091,196,196,196,196,1091,1091,1091,1091,1091,1091,1091,1091, -1092,1093,1093,1093,1093,1093,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,1013, +1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,1013,163,1014, +1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015, +1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015,1015, +1015,1015,1015,1015,163,163,163,163,1015,1015,1015,1015,1015,1015,1015,1015, +1016,1017,1017,1017,1017,1017,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 150 */ -1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094, -1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094, -1094,1094,1094,1094,1094,1094,1094,1094,1095,1095,1095,1095,1095,1095,1095,1095, -1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095, -1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095, -1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096, -1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096, -1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096, +1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018, +1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018, +1018,1018,1018,1018,1018,1018,1018,1018,1019,1019,1019,1019,1019,1019,1019,1019, +1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019, +1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019, +1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020, +1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020, +1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020, /* block 151 */ -1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,1097, -1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,196,196, -1098,1098,1098,1098,1098,1098,1098,1098,1098,1098,196,196,196,196,196,196, -1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099, -1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099, -1099,1099,1099,1099,196,196,196,196,1100,1100,1100,1100,1100,1100,1100,1100, -1100,1100,1100,1100,1100,1100,1100,1100,1100,1100,1100,1100,1100,1100,1100,1100, -1100,1100,1100,1100,1100,1100,1100,1100,1100,1100,1100,1100,196,196,196,196, +1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021, +1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,163,163, +1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,163,163,163,163,163,163, +1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023, +1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023, +1023,1023,1023,1023,163,163,163,163,1024,1024,1024,1024,1024,1024,1024,1024, +1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024, +1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,163,163,163,163, /* block 152 */ -1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101, -1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101, -1101,1101,1101,1101,1101,1101,1101,1101,196,196,196,196,196,196,196,196, -1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102, -1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102, -1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102, -1102,1102,1102,1102,196,196,196,196,196,196,196,196,196,196,196,1103, -1104,1104,1104,1104,1104,1104,1104,1104,1104,1104,1104,196,1104,1104,1104,1104, +1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, +1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, +1025,1025,1025,1025,1025,1025,1025,1025,163,163,163,163,163,163,163,163, +1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026, +1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026, +1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026, +1026,1026,1026,1026,163,163,163,163,163,163,163,163,163,163,163,1027, +1028,1028,1028,1028,1028,1028,1028,1028,1028,1028,1028,163,1028,1028,1028,1028, /* block 153 */ -1104,1104,1104,1104,1104,1104,1104,1104,1104,1104,1104,196,1104,1104,1104,1104, -1104,1104,1104,196,1104,1104,196,1105,1105,1105,1105,1105,1105,1105,1105,1105, -1105,1105,196,1105,1105,1105,1105,1105,1105,1105,1105,1105,1105,1105,1105,1105, -1105,1105,196,1105,1105,1105,1105,1105,1105,1105,196,1105,1105,196,196,196, -1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106, -1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106, -1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106, -1106,1106,1106,1106,196,196,196,196,196,196,196,196,196,196,196,196, +1028,1028,1028,1028,1028,1028,1028,1028,1028,1028,1028,163,1028,1028,1028,1028, +1028,1028,1028,163,1028,1028,163,1029,1029,1029,1029,1029,1029,1029,1029,1029, +1029,1029,163,1029,1029,1029,1029,1029,1029,1029,1029,1029,1029,1029,1029,1029, +1029,1029,163,1029,1029,1029,1029,1029,1029,1029,163,1029,1029,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 154 */ -1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107, -1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107, -1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107, -1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107, -1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107, -1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107, -1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107, -1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107, +1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030, +1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030, +1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030, +1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030, +1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030, +1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030, +1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030, +1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030, /* block 155 */ -1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107, -1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107, -1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107, -1107,1107,1107,1107,1107,1107,1107,196,196,196,196,196,196,196,196,196, -1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107, -1107,1107,1107,1107,1107,1107,196,196,196,196,196,196,196,196,196,196, -1107,1107,1107,1107,1107,1107,1107,1107,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030, +1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030, +1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030, +1030,1030,1030,1030,1030,1030,1030,163,163,163,163,163,163,163,163,163, +1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030, +1030,1030,1030,1030,1030,1030,163,163,163,163,163,163,163,163,163,163, +1030,1030,1030,1030,1030,1030,1030,1030,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 156 */ -149,1108,1108,149,149,149,196,149,149,149,149,149,149,149,149,149, -149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, -149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, -149,196,149,149,149,149,149,149,149,149,149,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +147,1031,1031,147,147,147,163,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,163,147,147,147,147,147,147,147,147,147,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 157 */ -1109,1109,1109,1109,1109,1109,297,297,1109,297,1109,1109,1109,1109,1109,1109, -1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109, -1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109, -1109,1109,1109,1109,1109,1109,297,1109,1109,297,297,297,1109,297,297,1109, -1110,1110,1110,1110,1110,1110,1110,1110,1110,1110,1110,1110,1110,1110,1110,1110, -1110,1110,1110,1110,1110,1110,297,1111,1112,1112,1112,1112,1112,1112,1112,1112, -1113,1113,1113,1113,1113,1113,1113,1113,1113,1113,1113,1113,1113,1113,1113,1113, -1113,1113,1113,1113,1113,1113,1113,1114,1114,1115,1115,1115,1115,1115,1115,1115, +1032,1032,1032,1032,1032,1032,262,262,1032,262,1032,1032,1032,1032,1032,1032, +1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032, +1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032,1032, +1032,1032,1032,1032,1032,1032,262,1032,1032,262,262,262,1032,262,262,1032, +1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033, +1033,1033,1033,1033,1033,1033,262,1034,1035,1035,1035,1035,1035,1035,1035,1035, +1036,1036,1036,1036,1036,1036,1036,1036,1036,1036,1036,1036,1036,1036,1036,1036, +1036,1036,1036,1036,1036,1036,1036,1037,1037,1038,1038,1038,1038,1038,1038,1038, /* block 158 */ -1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116, -1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,297, -297,297,297,297,297,297,297,1117,1117,1117,1117,1117,1117,1117,1117,1117, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -1118,1118,1118,1118,1118,1118,1118,1118,1118,1118,1118,1118,1118,1118,1118,1118, -1118,1118,1118,297,1118,1118,297,297,297,297,297,1119,1119,1119,1119,1119, +1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,1039, +1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,1039,262, +262,262,262,262,262,262,262,1040,1040,1040,1040,1040,1040,1040,1040,1040, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +1041,1041,1041,1041,1041,1041,1041,1041,1041,1041,1041,1041,1041,1041,1041,1041, +1041,1041,1041,262,1041,1041,262,262,262,262,262,1042,1042,1042,1042,1042, /* block 159 */ -1120,1120,1120,1120,1120,1120,1120,1120,1120,1120,1120,1120,1120,1120,1120,1120, -1120,1120,1120,1120,1120,1120,1121,1121,1121,1121,1121,1121,297,297,297,1122, -1123,1123,1123,1123,1123,1123,1123,1123,1123,1123,1123,1123,1123,1123,1123,1123, -1123,1123,1123,1123,1123,1123,1123,1123,1123,1123,297,297,297,297,297,1124, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, +1043,1043,1043,1043,1043,1043,1043,1043,1043,1043,1043,1043,1043,1043,1043,1043, +1043,1043,1043,1043,1043,1043,1044,1044,1044,1044,1044,1044,262,262,262,1045, +1046,1046,1046,1046,1046,1046,1046,1046,1046,1046,1046,1046,1046,1046,1046,1046, +1046,1046,1046,1046,1046,1046,1046,1046,1046,1046,262,262,262,262,262,1047, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, /* block 160 */ -1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125, -1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125, -1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126, -1126,1126,1126,1126,1126,1126,1126,1126,297,297,297,297,1127,1127,1126,1126, -1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127, -297,297,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127, -1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127, -1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127, +1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048, +1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048,1048, +1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049, +1049,1049,1049,1049,1049,1049,1049,1049,262,262,262,262,1050,1050,1049,1049, +1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050, +262,262,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050, +1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050, +1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050, /* block 161 */ -1128,1129,1129,1129,297,1129,1129,297,297,297,297,297,1129,1129,1129,1129, -1128,1128,1128,1128,297,1128,1128,1128,297,1128,1128,1128,1128,1128,1128,1128, -1128,1128,1128,1128,1128,1128,1128,1128,1128,1128,1128,1128,1128,1128,1128,1128, -1128,1128,1128,1128,1128,1128,297,297,1130,1130,1130,297,297,297,297,1131, -1132,1132,1132,1132,1132,1132,1132,1132,1132,297,297,297,297,297,297,297, -1133,1133,1133,1133,1133,1133,1134,1134,1133,297,297,297,297,297,297,297, -1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135, -1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1136,1136,1137, +1051,1052,1052,1052,262,1052,1052,262,262,262,262,262,1052,1052,1052,1052, +1051,1051,1051,1051,262,1051,1051,1051,262,1051,1051,1051,1051,1051,1051,1051, +1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051, +1051,1051,1051,1051,1051,1051,262,262,1053,1053,1053,262,262,262,262,1054, +1055,1055,1055,1055,1055,1055,1055,1055,1055,262,262,262,262,262,262,262, +1056,1056,1056,1056,1056,1056,1057,1057,1056,262,262,262,262,262,262,262, +1058,1058,1058,1058,1058,1058,1058,1058,1058,1058,1058,1058,1058,1058,1058,1058, +1058,1058,1058,1058,1058,1058,1058,1058,1058,1058,1058,1058,1058,1059,1059,1060, /* block 162 */ -1138,1138,1138,1138,1138,1138,1138,1138,1138,1138,1138,1138,1138,1138,1138,1138, -1138,1138,1138,1138,1138,1138,1138,1138,1138,1138,1138,1138,1138,1139,1139,1139, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -1140,1140,1140,1140,1140,1140,1140,1140,1141,1140,1140,1140,1140,1140,1140,1140, -1140,1140,1140,1140,1140,1140,1140,1140,1140,1140,1140,1140,1140,1140,1140,1140, -1140,1140,1140,1140,1140,1142,1142,297,297,297,297,1143,1143,1143,1143,1143, -1144,1144,1145,1144,1144,1144,1146,297,297,297,297,297,297,297,297,297, +1061,1061,1061,1061,1061,1061,1061,1061,1061,1061,1061,1061,1061,1061,1061,1061, +1061,1061,1061,1061,1061,1061,1061,1061,1061,1061,1061,1061,1061,1062,1062,1062, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +1063,1063,1063,1063,1063,1063,1063,1063,1064,1063,1063,1063,1063,1063,1063,1063, +1063,1063,1063,1063,1063,1063,1063,1063,1063,1063,1063,1063,1063,1063,1063,1063, +1063,1063,1063,1063,1063,1065,1065,262,262,262,262,1066,1066,1066,1066,1066, +1067,1067,1068,1067,1067,1067,1069,262,262,262,262,262,262,262,262,262, /* block 163 */ -1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, -1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, -1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147, -1147,1147,1147,1147,1147,1147,297,297,297,1148,1149,1149,1149,1149,1149,1149, -1150,1150,1150,1150,1150,1150,1150,1150,1150,1150,1150,1150,1150,1150,1150,1150, -1150,1150,1150,1150,1150,1150,297,297,1151,1151,1151,1151,1151,1151,1151,1151, -1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,1152, -1152,1152,1152,297,297,297,297,297,1153,1153,1153,1153,1153,1153,1153,1153, +1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070, +1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070, +1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070,1070, +1070,1070,1070,1070,1070,1070,262,262,262,1071,1072,1072,1072,1072,1072,1072, +1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073, +1073,1073,1073,1073,1073,1073,262,262,1074,1074,1074,1074,1074,1074,1074,1074, +1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075, +1075,1075,1075,262,262,262,262,262,1076,1076,1076,1076,1076,1076,1076,1076, /* block 164 */ -1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154, -1154,1154,297,297,297,297,297,297,297,1155,1155,1155,1155,297,297,297, -297,297,297,297,297,297,297,297,297,1156,1156,1156,1156,1156,1156,1156, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, +1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077, +1077,1077,262,262,262,262,262,262,262,1078,1078,1078,1078,262,262,262, +262,262,262,262,262,262,262,262,262,1079,1079,1079,1079,1079,1079,1079, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, /* block 165 */ -1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157, -1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157, -1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157, -1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157, -1157,1157,1157,1157,1157,1157,1157,1157,1157,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, +1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080, +1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080, +1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080, +1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080,1080, +1080,1080,1080,1080,1080,1080,1080,1080,1080,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, /* block 166 */ -1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158, -1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158, -1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158, -1158,1158,1158,297,297,297,297,297,297,297,297,297,297,297,297,297, -1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159, -1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159, -1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159, -1159,1159,1159,297,297,297,297,297,297,297,1160,1160,1160,1160,1160,1160, +1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081, +1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081, +1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081, +1081,1081,1081,262,262,262,262,262,262,262,262,262,262,262,262,262, +1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082, +1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082, +1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082, +1082,1082,1082,262,262,262,262,262,262,262,1083,1083,1083,1083,1083,1083, /* block 167 */ -1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161, -1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161, -1161,1161,1162,1162,1163,1163,1163,1163,340,340,340,340,340,340,340,340, -1164,1164,1164,1164,1164,1164,1164,1164,1164,1164,340,340,340,340,340,340, -1165,1165,1165,1165,1165,1165,1165,1165,1165,1165,1166,1166,1166,1166,1167,1166, -1168,1168,1168,1168,1168,1168,1168,1168,1168,1168,1168,1168,1168,1168,1168,1168, -1168,1168,1168,1168,1168,1168,297,297,297,1169,1170,1171,1171,1171,1172,1173, -1174,1174,1174,1174,1174,1174,1174,1174,1174,1174,1174,1174,1174,1174,1174,1174, +1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084, +1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084,1084, +1084,1084,1085,1085,1086,1086,1086,1086,302,302,302,302,302,302,302,302, +1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,302,302,302,302,302,302, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, /* block 168 */ -1174,1174,1174,1174,1174,1174,297,297,297,297,297,297,297,297,1175,1175, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, /* block 169 */ -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,1176, -1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,297, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,1088, +1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,262, /* block 170 */ -1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177, -1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177, -1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,297,1178,1178,1179,297,297, -1177,1177,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -340,340,321,321,321,340,340,340,340,340,340,340,340,340,340,340, -340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340, -340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340, -340,340,340,340,340,340,340,340,340,340,340,340,316,333,333,333, +1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089, +1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089, +1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,262,1090,1090,1091,262,262, +1089,1089,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302, +302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302, +302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302, +302,302,302,302,302,302,302,302,302,302,302,302,302,291,291,291, /* block 171 */ -1180,1180,1180,1180,1180,1180,1180,1180,1180,1180,1180,1180,1180,1180,1180,1180, -1180,1180,1180,1180,1180,1180,1180,1180,1180,1180,1180,1180,1180,1181,1181,1181, -1181,1181,1181,1181,1181,1181,1181,1180,297,297,297,297,297,297,297,297, -1182,1182,1182,1182,1182,1182,1182,1182,1182,1182,1182,1182,1182,1182,1182,1182, -1182,1182,1182,1182,1182,1182,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183, -1183,1184,1184,1184,1184,1185,1185,1185,1185,1185,340,340,340,340,340,340, -340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340, -1186,1186,1186,1186,1186,1186,1186,1186,1186,1186,1186,1186,1186,1186,1186,1186, +1092,1092,1092,1092,1092,1092,1092,1092,1092,1092,1092,1092,1092,1092,1092,1092, +1092,1092,1092,1092,1092,1092,1092,1092,1092,1092,1092,1092,1092,1093,1093,1093, +1093,1093,1093,1093,1093,1093,1093,1092,262,262,262,262,262,262,262,262, +1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094, +1094,1094,1094,1094,1094,1094,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095, +1095,1096,1096,1096,1096,1097,1097,1097,1097,1097,302,302,302,302,302,302, +302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302, +1098,1098,1098,1098,1098,1098,1098,1098,1098,1098,1098,1098,1098,1098,1098,1098, /* block 172 */ -1186,1186,1187,1187,1187,1187,1188,1188,1188,1188,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189, -1189,1189,1189,1189,1189,1190,1190,1190,1190,1190,1190,1190,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191, -1191,1191,1191,1191,1191,1191,1191,297,297,297,297,297,297,297,297,297, +1098,1098,1099,1099,1099,1099,1100,1100,1100,1100,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101, +1101,1101,1101,1101,1101,1102,1102,1102,1102,1102,1102,1102,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +1103,1103,1103,1103,1103,1103,1103,1103,1103,1103,1103,1103,1103,1103,1103,1103, +1103,1103,1103,1103,1103,1103,1103,262,262,262,262,262,262,262,262,262, /* block 173 */ -1192,1193,1192,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194, -1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194, -1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194, -1194,1194,1194,1194,1194,1194,1194,1194,1193,1193,1193,1193,1193,1193,1193,1193, -1193,1193,1193,1193,1193,1193,1195,1196,1196,1197,1197,1197,1197,1197,196,196, -196,196,1198,1198,1198,1198,1198,1198,1198,1198,1198,1198,1198,1198,1198,1198, -1198,1198,1198,1198,1198,1198,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199, -1195,1194,1194,1193,1193,1194,196,196,196,196,196,196,196,196,196,1200, +1104,1105,1104,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106, +1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106, +1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106,1106, +1106,1106,1106,1106,1106,1106,1106,1106,1105,1105,1105,1105,1105,1105,1105,1105, +1105,1105,1105,1105,1105,1105,1107,1108,1108,1109,1109,1109,1109,1109,163,163, +163,163,1110,1110,1110,1110,1110,1110,1110,1110,1110,1110,1110,1110,1110,1110, +1110,1110,1110,1110,1110,1110,1111,1111,1111,1111,1111,1111,1111,1111,1111,1111, +1107,1106,1106,1105,1105,1106,163,163,163,163,163,163,163,163,163,1112, /* block 174 */ -1201,1201,1202,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203, -1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203, -1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203, -1202,1202,1202,1201,1201,1201,1201,1202,1202,1204,1205,1206,1206,1207,1208,1208, -1208,1208,1201,196,196,196,196,196,196,196,196,196,196,1207,196,196, -1209,1209,1209,1209,1209,1209,1209,1209,1209,1209,1209,1209,1209,1209,1209,1209, -1209,1209,1209,1209,1209,1209,1209,1209,1209,196,196,196,196,196,196,196, -1210,1210,1210,1210,1210,1210,1210,1210,1210,1210,196,196,196,196,196,196, +1113,1113,1114,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115, +1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115, +1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115,1115, +1114,1114,1114,1113,1113,1113,1113,1114,1114,1116,1117,1118,1118,1119,1120,1120, +1120,1120,1113,163,163,163,163,163,163,163,163,163,163,1119,163,163, +1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121, +1121,1121,1121,1121,1121,1121,1121,1121,1121,163,163,163,163,163,163,163, +1122,1122,1122,1122,1122,1122,1122,1122,1122,1122,163,163,163,163,163,163, /* block 175 */ -1211,1211,1211,1212,1212,1212,1212,1212,1212,1212,1212,1212,1212,1212,1212,1212, -1212,1212,1212,1212,1212,1212,1212,1212,1212,1212,1212,1212,1212,1212,1212,1212, -1212,1212,1212,1212,1212,1212,1212,1211,1211,1211,1211,1211,1213,1211,1211,1211, -1211,1211,1211,1214,1214,196,1215,1215,1215,1215,1215,1215,1215,1215,1215,1215, -1216,1217,1217,1217,1212,1213,1213,1212,196,196,196,196,196,196,196,196, -1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218, -1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218, -1218,1218,1218,1219,1220,1220,1218,196,196,196,196,196,196,196,196,196, +1123,1123,1123,1124,1124,1124,1124,1124,1124,1124,1124,1124,1124,1124,1124,1124, +1124,1124,1124,1124,1124,1124,1124,1124,1124,1124,1124,1124,1124,1124,1124,1124, +1124,1124,1124,1124,1124,1124,1124,1123,1123,1123,1123,1123,1125,1123,1123,1123, +1123,1123,1123,1126,1126,163,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127, +1128,1129,1129,1129,1124,1125,1125,1124,163,163,163,163,163,163,163,163, +1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130, +1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130,1130, +1130,1130,1130,1131,1132,1132,1130,163,163,163,163,163,163,163,163,163, /* block 176 */ -1221,1221,1222,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223, -1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223, -1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223, -1223,1223,1223,1222,1222,1222,1221,1221,1221,1221,1221,1221,1221,1221,1221,1222, -1224,1223,1225,1225,1223,1226,1226,1227,1227,1228,1229,1229,1229,1226,1222,1221, -1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1223,1227,1223,1227,1226,1226, -196,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231, -1231,1231,1231,1231,1231,196,196,196,196,196,196,196,196,196,196,196, +1133,1133,1134,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135, +1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135, +1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135,1135, +1135,1135,1135,1134,1134,1134,1133,1133,1133,1133,1133,1133,1133,1133,1133,1134, +1136,1135,1137,1137,1135,1138,1138,1139,1139,1140,1141,1141,1141,1138,1134,1133, +1142,1142,1142,1142,1142,1142,1142,1142,1142,1142,1135,1139,1135,1139,1138,1138, +163,1143,1143,1143,1143,1143,1143,1143,1143,1143,1143,1143,1143,1143,1143,1143, +1143,1143,1143,1143,1143,163,163,163,163,163,163,163,163,163,163,163, /* block 177 */ -1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232, -1232,1232,196,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232, -1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1233,1233,1233,1234, -1234,1234,1233,1233,1234,1235,1236,1237,1238,1238,1239,1238,1238,1240,1234,1232, -1232,1234,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144, +1144,1144,163,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144, +1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1145,1145,1145,1146, +1146,1146,1145,1145,1146,1147,1148,1146,1149,1149,1150,1149,1149,1151,1146,1144, +1144,1146,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 178 */ -1241,1241,1241,1241,1241,1241,1241,196,1241,196,1241,1241,1241,1241,196,1241, -1241,1241,1241,1241,1241,1241,1241,1241,1241,1241,1241,1241,1241,1241,196,1241, -1241,1241,1241,1241,1241,1241,1241,1241,1241,1242,196,196,196,196,196,196, -1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243, -1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243, -1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1244, -1245,1245,1245,1244,1244,1244,1244,1244,1244,1246,1247,196,196,196,196,196, -1248,1248,1248,1248,1248,1248,1248,1248,1248,1248,196,196,196,196,196,196, +1152,1152,1152,1152,1152,1152,1152,163,1152,163,1152,1152,1152,1152,163,1152, +1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,163,1152, +1152,1152,1152,1152,1152,1152,1152,1152,1152,1153,163,163,163,163,163,163, +1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154, +1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154, +1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1155, +1156,1156,1156,1155,1155,1155,1155,1155,1155,1157,1158,163,163,163,163,163, +1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,163,163,163,163,163,163, /* block 179 */ -1249,1250,1251,1252,196,1253,1253,1253,1253,1253,1253,1253,1253,196,196,1253, -1253,196,196,1253,1253,1253,1253,1253,1253,1253,1253,1253,1253,1253,1253,1253, -1253,1253,1253,1253,1253,1253,1253,1253,1253,196,1253,1253,1253,1253,1253,1253, -1253,196,1253,1253,196,1253,1253,1253,1253,1253,196,1254,1255,1253,1256,1251, -1249,1251,1251,1251,1251,196,196,1251,1251,196,196,1251,1251,1257,196,196, -1253,196,196,196,196,196,196,1256,196,196,196,196,196,1258,1253,1253, -1253,1253,1251,1251,196,196,1259,1259,1259,1259,1259,1259,1259,196,196,196, -1259,1259,1259,1259,1259,196,196,196,196,196,196,196,196,196,196,196, +1160,1161,1162,1163,163,1164,1164,1164,1164,1164,1164,1164,1164,163,163,1164, +1164,163,163,1164,1164,1164,1164,1164,1164,1164,1164,1164,1164,1164,1164,1164, +1164,1164,1164,1164,1164,1164,1164,1164,1164,163,1164,1164,1164,1164,1164,1164, +1164,163,1164,1164,163,1164,1164,1164,1164,1164,163,1165,1166,1164,1167,1162, +1160,1162,1162,1162,1162,163,163,1162,1162,163,163,1162,1162,1168,163,163, +1164,163,163,163,163,163,163,1167,163,163,163,163,163,1169,1164,1164, +1164,1164,1162,1162,163,163,1170,1170,1170,1170,1170,1170,1170,163,163,163, +1170,1170,1170,1170,1170,163,163,163,163,163,163,163,163,163,163,163, /* block 180 */ -1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,196,1260,196,196,1260,196, -1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260, -1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260, -1260,1260,1260,1260,1260,1260,196,1260,1261,1262,1262,1263,1263,1263,1263,1263, -1263,196,1261,196,196,1261,196,1261,1261,1261,1262,196,1262,1262,1264,1265, -1264,1266,1267,1268,1269,1269,196,1270,1270,196,196,196,196,196,196,196, -196,1271,1271,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171, +1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171, +1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171,1171, +1171,1171,1171,1171,1171,1172,1172,1172,1173,1173,1173,1173,1173,1173,1173,1173, +1172,1172,1174,1173,1173,1172,1175,1171,1171,1171,1171,1176,1176,1177,1178,1178, +1179,1179,1179,1179,1179,1179,1179,1179,1179,1179,1177,1177,163,1178,1180,1171, +1171,1171,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 181 */ -1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272, -1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272, -1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272, -1272,1272,1272,1272,1272,1273,1273,1273,1274,1274,1274,1274,1274,1274,1274,1274, -1273,1273,1275,1274,1274,1273,1276,1272,1272,1272,1272,1277,1277,1278,1279,1279, -1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1278,1278,196,1279,1281,1272, -1272,1272,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181, +1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181, +1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1181, +1182,1183,1183,1184,1184,1184,1184,1184,1184,1183,1184,1183,1183,1182,1183,1184, +1184,1183,1185,1186,1181,1181,1187,1181,163,163,163,163,163,163,163,163, +1188,1188,1188,1188,1188,1188,1188,1188,1188,1188,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 182 */ -1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282, -1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282, -1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282, -1283,1284,1284,1285,1285,1285,1285,1285,1285,1284,1285,1284,1284,1283,1284,1285, -1285,1284,1286,1287,1282,1282,1288,1282,196,196,196,196,196,196,196,196, -1289,1289,1289,1289,1289,1289,1289,1289,1289,1289,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189, +1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189, +1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1190, +1191,1191,1192,1192,1192,1192,163,163,1191,1191,1191,1191,1192,1192,1191,1193, +1194,1195,1196,1196,1197,1197,1198,1198,1198,1196,1196,1196,1196,1196,1196,1196, +1196,1196,1196,1196,1196,1196,1196,1196,1189,1189,1189,1189,1192,1192,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 183 */ -1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290, -1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290, -1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1291, -1292,1292,1293,1293,1293,1293,196,196,1292,1292,1292,1292,1293,1293,1292,1294, -1295,1296,1297,1297,1298,1298,1299,1299,1299,1297,1297,1297,1297,1297,1297,1297, -1297,1297,1297,1297,1297,1297,1297,1297,1290,1290,1290,1290,1293,1293,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199, +1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199, +1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199, +1200,1200,1200,1201,1201,1201,1201,1201,1201,1201,1201,1200,1200,1201,1200,1202, +1201,1203,1203,1204,1199,163,163,163,163,163,163,163,163,163,163,163, +1205,1205,1205,1205,1205,1205,1205,1205,1205,1205,163,163,163,163,163,163, +531,531,531,531,531,531,531,531,531,531,531,531,531,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 184 */ -1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300, -1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300, -1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300, -1301,1301,1301,1302,1302,1302,1302,1302,1302,1302,1302,1301,1301,1302,1301,1303, -1302,1304,1304,1305,1300,196,196,196,196,196,196,196,196,196,196,196, -1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,196,196,196,196,196,196, -581,581,581,581,581,581,581,581,581,581,581,581,581,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206, +1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206, +1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1206,1207,1208,1207,1208,1208, +1207,1207,1207,1207,1207,1207,1209,1210,1206,1211,163,163,163,163,163,163, +1212,1212,1212,1212,1212,1212,1212,1212,1212,1212,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 185 */ -1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307, -1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307, -1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1308,1309,1308,1309,1309, -1308,1308,1308,1308,1308,1308,1310,1311,1307,1312,196,196,196,196,196,196, -1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,196,196,196,196,196,196, -522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522, -522,522,522,522,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1213,1213,1213,1213,1213,1213,1213,1213,1213,1213,1213,1213,1213,1213,1213,1213, +1213,1213,1213,1213,1213,1213,1213,1213,1213,1213,1213,163,163,1214,1214,1214, +1215,1215,1214,1214,1214,1214,1216,1214,1214,1214,1214,1217,163,163,163,163, +1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1219,1219,1220,1220,1220,1221, +1213,1213,1213,1213,1213,1213,1213,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 186 */ -1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314, -1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,196,196,1315,1316,1315, -1317,1317,1315,1315,1315,1315,1316,1315,1315,1315,1315,1318,196,196,196,196, -1319,1319,1319,1319,1319,1319,1319,1319,1319,1319,1320,1320,1321,1321,1321,1322, -1314,1314,1314,1314,1314,1314,1314,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222, +1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222, +1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1222,1223,1223,1223,1224, +1224,1224,1224,1224,1224,1224,1224,1224,1223,1225,1226,1227,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 187 */ -1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323, -1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323, -1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1324,1324,1324,1325, -1325,1325,1325,1325,1325,1325,1325,1325,1324,1326,1327,1328,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228, +1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228,1228, +1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229, +1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229,1229, +1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1231,1231,1231,1231,1231,1231, +1231,1231,1231,163,163,163,163,163,163,163,163,163,163,163,163,1232, /* block 188 */ -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329, -1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329, -1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330, -1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330, -1331,1331,1331,1331,1331,1331,1331,1331,1331,1331,1332,1332,1332,1332,1332,1332, -1332,1332,1332,196,196,196,196,196,196,196,196,196,196,196,196,1333, +1233,1233,1233,1233,1233,1233,1233,163,163,1233,163,163,1233,1233,1233,1233, +1233,1233,1233,1233,163,1233,1233,163,1233,1233,1233,1233,1233,1233,1233,1233, +1233,1233,1233,1233,1233,1233,1233,1233,1233,1233,1233,1233,1233,1233,1233,1233, +1234,1235,1235,1235,1235,1235,163,1235,1235,163,163,1236,1236,1237,1238,1239, +1235,1239,1235,1240,1241,1242,1241,163,163,163,163,163,163,163,163,163, +1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 189 */ -1334,1334,1334,1334,1334,1334,1334,196,196,1334,196,196,1334,1334,1334,1334, -1334,1334,1334,1334,196,1334,1334,196,1334,1334,1334,1334,1334,1334,1334,1334, -1334,1334,1334,1334,1334,1334,1334,1334,1334,1334,1334,1334,1334,1334,1334,1334, -1335,1336,1336,1336,1336,1336,196,1336,1336,196,196,1337,1337,1338,1339,1340, -1336,1340,1336,1341,1342,1343,1342,196,196,196,196,196,196,196,196,196, -1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +1244,1244,1244,1244,1244,1244,1244,1244,163,163,1244,1244,1244,1244,1244,1244, +1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244, +1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244,1244, +1244,1245,1245,1245,1246,1246,1246,1246,163,163,1246,1246,1245,1245,1245,1245, +1247,1244,1248,1244,1245,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 190 */ -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -1345,1345,1345,1345,1345,1345,1345,1345,196,196,1345,1345,1345,1345,1345,1345, -1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345, -1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345, -1345,1346,1346,1346,1347,1347,1347,1347,196,196,1347,1347,1346,1346,1346,1346, -1348,1345,1349,1345,1346,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1249,1250,1250,1250,1250,1250,1250,1251,1251,1250,1250,1249,1249,1249,1249,1249, +1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249, +1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249, +1249,1249,1249,1252,1253,1250,1250,1250,1250,1254,1255,1250,1250,1250,1250,1256, +1256,1256,1257,1257,1256,1256,1256,1253,163,163,163,163,163,163,163,163, +1258,1259,1259,1259,1259,1259,1259,1260,1260,1259,1259,1259,1258,1258,1258,1258, +1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258, +1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258,1258, /* block 191 */ -1350,1351,1351,1351,1351,1351,1351,1352,1352,1351,1351,1350,1350,1350,1350,1350, -1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350, -1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350, -1350,1350,1350,1353,1354,1351,1351,1351,1351,1355,1356,1351,1351,1351,1351,1357, -1357,1357,1358,1358,1357,1357,1357,1354,196,196,196,196,196,196,196,196, -1359,1360,1360,1360,1360,1360,1360,1361,1361,1360,1360,1360,1359,1359,1359,1359, -1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359, -1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359, +1258,1258,1258,1258,1261,1261,1261,1261,1261,1261,1259,1259,1259,1259,1259,1259, +1259,1259,1259,1259,1259,1259,1259,1260,1262,1263,1264,1265,1265,1258,1264,1264, +1264,1266,1266,163,163,163,163,163,163,163,163,163,163,163,163,163, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267, +1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267, +1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267,1267, +1267,1267,1267,1267,1267,1267,1267,1267,1267,163,163,163,163,163,163,163, /* block 192 */ -1359,1359,1359,1359,1362,1362,1362,1362,1362,1362,1360,1360,1360,1360,1360,1360, -1360,1360,1360,1360,1360,1360,1360,1361,1363,1364,1365,1366,1366,1359,1365,1365, -1365,1367,1367,196,196,196,196,196,196,196,196,196,196,196,196,196, -545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, -1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368, -1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368, -1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368, -1368,1368,1368,1368,1368,1368,1368,1368,1368,196,196,196,196,196,196,196, +343,343,343,343,343,343,343,343,343,343,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 193 */ -385,385,385,385,385,385,385,385,385,385,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1268,1268,1268,1268,1268,1268,1268,1268,1268,163,1268,1268,1268,1268,1268,1268, +1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1268, +1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1268,1269, +1270,1270,1270,1270,1270,1270,1270,163,1270,1270,1270,1270,1270,1270,1269,1271, +1268,1272,1272,1273,1274,1274,163,163,163,163,163,163,163,163,163,163, +1275,1275,1275,1275,1275,1275,1275,1275,1275,1275,1276,1276,1276,1276,1276,1276, +1276,1276,1276,1276,1276,1276,1276,1276,1276,1276,1276,1276,1276,163,163,163, +1277,1278,1279,1279,1279,1279,1279,1279,1279,1279,1279,1279,1279,1279,1279,1279, /* block 194 */ -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369, -1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369, -1369,1370,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -1371,1371,1371,1371,1371,1371,1371,1371,1371,1371,196,196,196,196,196,196, +1279,1279,1279,1279,1279,1279,1279,1279,1279,1279,1279,1279,1279,1279,1279,1279, +163,163,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280, +1280,1280,1280,1280,1280,1280,1280,1280,163,1281,1280,1280,1280,1280,1280,1280, +1280,1281,1280,1280,1281,1280,1280,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 195 */ -1372,1372,1372,1372,1372,1372,1372,1372,1372,196,1372,1372,1372,1372,1372,1372, -1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372, -1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1373, -1374,1374,1374,1374,1374,1374,1374,196,1374,1374,1374,1374,1374,1374,1373,1375, -1372,1376,1376,1377,1378,1378,196,196,196,196,196,196,196,196,196,196, -1379,1379,1379,1379,1379,1379,1379,1379,1379,1379,1380,1380,1380,1380,1380,1380, -1380,1380,1380,1380,1380,1380,1380,1380,1380,1380,1380,1380,1380,196,196,196, -1381,1382,1383,1383,1383,1383,1383,1383,1383,1383,1383,1383,1383,1383,1383,1383, +1282,1282,1282,1282,1282,1282,1282,163,1282,1282,163,1282,1282,1282,1282,1282, +1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282, +1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282, +1282,1283,1283,1283,1283,1283,1283,163,163,163,1283,163,1283,1283,163,1283, +1283,1283,1284,1283,1285,1285,1286,1283,163,163,163,163,163,163,163,163, +1287,1287,1287,1287,1287,1287,1287,1287,1287,1287,163,163,163,163,163,163, +1288,1288,1288,1288,1288,1288,163,1288,1288,163,1288,1288,1288,1288,1288,1288, +1288,1288,1288,1288,1288,1288,1288,1288,1288,1288,1288,1288,1288,1288,1288,1288, /* block 196 */ -1383,1383,1383,1383,1383,1383,1383,1383,1383,1383,1383,1383,1383,1383,1383,1383, -196,196,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384, -1384,1384,1384,1384,1384,1384,1384,1384,196,1385,1384,1384,1384,1384,1384,1384, -1384,1385,1384,1384,1385,1384,1384,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1288,1288,1288,1288,1288,1288,1288,1288,1288,1288,1289,1289,1289,1289,1289,163, +1290,1290,163,1289,1289,1290,1289,1291,1288,163,163,163,163,163,163,163, +1292,1292,1292,1292,1292,1292,1292,1292,1292,1292,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 197 */ -1386,1386,1386,1386,1386,1386,1386,196,1386,1386,196,1386,1386,1386,1386,1386, -1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386, -1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386, -1386,1387,1387,1387,1387,1387,1387,196,196,196,1387,196,1387,1387,196,1387, -1387,1387,1388,1387,1389,1389,1390,1387,196,196,196,196,196,196,196,196, -1391,1391,1391,1391,1391,1391,1391,1391,1391,1391,196,196,196,196,196,196, -1392,1392,1392,1392,1392,1392,196,1392,1392,196,1392,1392,1392,1392,1392,1392, -1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +1293,1293,1293,1293,1293,1293,1293,1293,1293,1293,1293,1293,1293,1293,1293,1293, +1293,1293,1293,1294,1294,1295,1295,1296,1296,163,163,163,163,163,163,163, /* block 198 */ -1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1393,1393,1393,1393,1393,196, -1394,1394,196,1393,1393,1394,1393,1395,1392,196,196,196,196,196,196,196, -1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1297,1297,1298,1299,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300, +1300,163,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300, +1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300, +1300,1300,1300,1300,1299,1299,1297,1297,1297,1297,1297,163,163,163,1299,1299, +1297,1301,1302,1303,1303,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304, +1305,1305,1305,1305,1305,1305,1305,1305,1305,1305,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 199 */ -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -1397,1397,1397,1397,1397,1397,1397,1397,1397,1397,1397,1397,1397,1397,1397,1397, -1397,1397,1397,1398,1398,1399,1399,1400,1400,196,196,196,196,196,196,196, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +843,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306, +388,388,1306,388,1306,390,390,390,390,390,390,390,390,391,391,391, +391,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390, +390,390,163,163,163,163,163,163,163,163,163,163,163,163,163,1307, /* block 200 */ -1401,1401,1402,1403,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404, -1404,196,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404, -1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404, -1404,1404,1404,1404,1403,1403,1401,1401,1401,1401,1401,196,196,196,1403,1403, -1401,1405,1406,1407,1407,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, -1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1410,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308, +1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308, +1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308, +1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308, +1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308, +1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308, +1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308, +1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308, /* block 201 */ -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -914,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -1411,1411,1411,1411,1411,1411,1411,1411,1411,1411,1411,1411,1411,1411,1411,1411, -435,435,1411,435,1411,437,437,437,437,437,437,437,437,438,438,438, -438,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, -437,437,196,196,196,196,196,196,196,196,196,196,196,196,196,1412, +1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308, +1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 202 */ -1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413, -1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413, -1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413, -1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413, -1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413, -1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413, -1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413, -1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413, +1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309, +1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309, +1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309, +1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309, +1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309, +1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309, +1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,163, +1310,1310,1310,1310,1310,163,163,163,163,163,163,163,163,163,163,163, /* block 203 */ -1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413, -1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308, +1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308, +1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308, +1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308, +1308,1308,1308,1308,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 204 */ -1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414, -1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414, -1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414, -1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414, -1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414, -1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414, -1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,196, -1415,1415,1415,1415,1415,196,196,196,196,196,196,196,196,196,196,196, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311, +1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311, +1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311, +1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311, +1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311, +1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311,1311, +1311,1312,1312,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 205 */ -1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413, -1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413, -1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413, -1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413, -1413,1413,1413,1413,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313, +1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313, +1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313, +1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313, +1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313, +1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313, +1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313, +1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313, /* block 206 */ -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416, -1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416, -1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416, -1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416, -1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416, -1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416, -1416,1417,1417,196,196,196,196,196,196,196,196,196,196,196,196,196, +1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313, +1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313, +1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313, +1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314, +1315,1313,1313,1313,1313,1313,1313,1316,1316,1316,1316,1316,1316,1316,1316,1316, +1316,1316,1316,1316,1316,1316,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 207 */ -1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418, -1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418, -1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418, -1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418, -1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418, -1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418, -1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418, -1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418, +1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317, +1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317, +1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317, +1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317, +1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317, +1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317, +1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317, +1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317, /* block 208 */ -1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418, -1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418, -1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418, -1419,1419,1419,1419,1419,1419,1419,1419,1419,1419,1419,1419,1419,1419,1419,1419, -1420,1418,1418,1418,1418,1418,1418,1421,1421,1421,1421,1421,1421,1421,1421,1421, -1421,1421,1421,1421,1421,1421,196,196,196,196,196,196,196,196,196,196, -1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418, -1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418, +1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317, +1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317, +1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317, +1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317, +1317,1317,1317,1317,1317,1317,1317,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 209 */ -1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418, -1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418, -1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418, -1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418, -1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418, -1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418, -1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418, -1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,196,196,196,196,196, +859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859, +859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859, +859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859, +859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859, +859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859, +859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859, +859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859, +859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859, /* block 210 */ -1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422, -1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422, -1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422, -1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422, -1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422, -1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422, -1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422, -1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422, +859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859, +859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859, +859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859, +859,859,859,859,859,859,859,859,859,163,163,163,163,163,163,163, +1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318, +1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,1318,163, +1319,1319,1319,1319,1319,1319,1319,1319,1319,1319,163,163,163,163,1320,1320, +1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321, /* block 211 */ -1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422, -1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422, -1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422, -1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422, -1422,1422,1422,1422,1422,1422,1422,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321, +1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321, +1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321, +1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,1321,163, +1322,1322,1322,1322,1322,1322,1322,1322,1322,1322,163,163,163,163,163,163, +1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323, +1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,163,163, +1324,1324,1324,1324,1324,1325,163,163,163,163,163,163,163,163,163,163, /* block 212 */ -1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,1423, -1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,1424,1424, -1424,1424,1424,1424,1424,1424,1424,1424,1424,1424,1425,1425,1425,1424,1424,1426, -1427,1427,1427,1427,1427,1427,1427,1427,1427,1427,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326, +1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326, +1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326, +1327,1327,1327,1327,1327,1327,1327,1328,1328,1329,1330,1330,1331,1331,1331,1331, +1332,1332,1333,1333,1328,1331,163,163,163,163,163,163,163,163,163,163, +1334,1334,1334,1334,1334,1334,1334,1334,1334,1334,163,1335,1335,1335,1335,1335, +1335,1335,163,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326, +1326,1326,1326,1326,1326,1326,1326,1326,163,163,163,163,163,1326,1326,1326, /* block 213 */ -930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930, -930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930, -930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930, -930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930, -930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930, -930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930, -930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930, -930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930, +1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326,1326, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 214 */ -930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930, -930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930, -930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930, -930,930,930,930,930,930,930,930,930,196,196,196,196,196,196,196, -1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,1428, -1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,196, -1429,1429,1429,1429,1429,1429,1429,1429,1429,1429,196,196,196,196,1430,1430, -1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336, +1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336,1336, +1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337, +1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337, /* block 215 */ -1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431, -1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431, -1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431, -1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,196, -1432,1432,1432,1432,1432,1432,1432,1432,1432,1432,196,196,196,196,196,196, -1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,1433, -1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,196,196, -1434,1434,1434,1434,1434,1435,196,196,196,196,196,196,196,196,196,196, +1338,1338,1338,1338,1338,1338,1338,1338,1338,1338,1338,1338,1338,1338,1338,1338, +1338,1338,1338,1338,1338,1338,1338,1339,1340,1341,1341,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 216 */ -1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436, -1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436, -1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436, -1437,1437,1437,1437,1437,1437,1437,1438,1438,1439,1440,1440,1441,1441,1441,1441, -1442,1442,1443,1443,1438,1441,196,196,196,196,196,196,196,196,196,196, -1444,1444,1444,1444,1444,1444,1444,1444,1444,1444,196,1445,1445,1445,1445,1445, -1445,1445,196,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436, -1436,1436,1436,1436,1436,1436,1436,1436,196,196,196,196,196,1436,1436,1436, +1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342, +1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342, +1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342, +1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342, +1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,1342,163,163,163,163,1343, +1342,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344, +1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344, +1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344, /* block 217 */ -1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1344,1344,1344,1344,1344,1344,1344,1344,163,163,163,163,163,163,163,1345, +1345,1345,1345,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +1347,1348,1349,800,1350,163,163,163,163,163,163,163,163,163,163,163, +1351,1351,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 218 */ -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -1446,1446,1446,1447,1447,1447,1447,1447,1447,1447,1447,1447,1447,1447,1447,1447, -1447,1447,1447,1447,1447,1447,1447,1447,1447,1447,1447,1447,1447,1447,1447,1447, -1447,1447,1447,1448,1447,1447,1447,1448,1448,1448,1448,1449,1449,1450,1451,1451, -1452,1452,1452,1452,1452,1452,1452,1452,1452,1452,196,196,196,196,196,196, +1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352, +1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352, +1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352, +1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352, +1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352, +1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352, +1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352, +1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352, /* block 219 */ -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453, -1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453, -1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454, -1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454, +1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352, +1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352, +1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352, +1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352, +1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352, +1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352, +1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352,1352, +1352,1352,1352,1352,1352,1352,1352,1352,163,163,163,163,163,163,163,163, /* block 220 */ -1455,1455,1455,1455,1455,1455,1455,1455,1455,1455,1455,1455,1455,1455,1455,1455, -1455,1455,1455,1455,1455,1455,1455,1456,1457,1458,1458,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353, +1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353, +1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353, +1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353, +1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353, +1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353, +1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353, +1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353, /* block 221 */ -1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459, -1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459, -1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459, -1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459, -1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,196,196,196,196,1460, -1459,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461, -1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461, -1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461, +1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353, +1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353, +1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353, +1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353, +1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353,1353, +1353,1353,1353,1353,1353,1353,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 222 */ -1461,1461,1461,1461,1461,1461,1461,1461,196,196,196,196,196,196,196,1462, -1462,1462,1462,1463,1463,1463,1463,1463,1463,1463,1463,1463,1463,1463,1463,1463, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -1464,1465,1466,867,1467,196,196,196,196,196,196,196,196,196,196,196, -1468,1468,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1352,1352,1352,1352,1352,1352,1352,1352,1352,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 223 */ -1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469, -1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469, -1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469, -1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469, -1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469, -1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469, -1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469, -1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +1354,1354,1354,1354,163,1354,1354,1354,1354,1354,1354,1354,163,1354,1354,163, /* block 224 */ -1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469, -1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469, -1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469, -1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469, -1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469, -1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469, -1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469, -1469,1469,1469,1469,1469,1469,1469,1469,196,196,196,196,196,196,196,196, +825,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, /* block 225 */ -1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470, -1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470, -1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470, -1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470, -1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470, -1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470, -1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470, -1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, /* block 226 */ -1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470, -1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470, -1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470, -1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470, -1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470, -1470,1470,1470,1470,1470,1470,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,1470, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +825,825,825,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,820,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +820,820,820,163,163,825,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,825,825,825,825,163,163,163,163,163,163,163,163, +1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355, /* block 227 */ -1469,1469,1469,1469,1469,1469,1469,1469,1469,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355, +1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355, +1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355, +1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355, +1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355, +1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355, +1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355, +1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355, /* block 228 */ -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -1471,1471,1471,1471,196,1471,1471,1471,1471,1471,1471,1471,196,1471,1471,196, +1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355, +1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355, +1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355, +1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355, +1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355, +1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355, +1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355, +1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,1355,163,163,163,163, /* block 229 */ -896,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, -891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, -891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, -891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, -891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, -891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, -891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, -891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, +1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356, +1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356, +1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356, +1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356, +1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356, +1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356, +1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,163,163,163,163,163, +1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,163,163,163, /* block 230 */ -891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, -891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, -891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, -891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, -891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, -891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, -891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, -891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, +1356,1356,1356,1356,1356,1356,1356,1356,1356,163,163,163,163,163,163,163, +1356,1356,1356,1356,1356,1356,1356,1356,1356,1356,163,163,1357,1358,1359,1360, +1361,1361,1361,1361,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 231 */ -891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, -891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, -896,896,896,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,891,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -891,891,891,196,196,896,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,896,896,896,896,196,196,196,196,196,196,196,196, -1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,163,163, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,163,163,163,163,163,163,163,163,163, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, /* block 232 */ -1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472, -1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472, -1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472, -1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472, -1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472, -1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472, -1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472, -1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 233 */ -1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472, -1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472, -1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472, -1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472, -1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472, -1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472, -1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472, -1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,196,196,196,196, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, /* block 234 */ -1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473, -1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473, -1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473, -1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473, -1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473, -1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473, -1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,196,196,196,196,196, -1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,196,196,196, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,163,163,163,163,163,163,163,163,163,163, /* block 235 */ -1473,1473,1473,1473,1473,1473,1473,1473,1473,196,196,196,196,196,196,196, -1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,196,196,1474,1475,1476,1477, -1478,1478,1478,1478,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,163,163,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,1362,1363,154,154,154,461,461,461,1364,1365,1365, +1365,1365,1365, 51, 51, 51, 51, 51, 51, 51, 51,154,154,154,154,154, /* block 236 */ -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, +154,154,154,461,461,154,154,154,154,154,154,154,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,154,154,154,154,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,724,724,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 237 */ -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -1479,1479,1479,1479,1479,1479,1479,1479,1479,1479,196,196,196,196,196,196, +1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001, +1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001, +1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001, +1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001, +1001,1001,1366,1366,1366,1001,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 238 */ -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836, +836,836,836,836,163,163,163,163,163,163,163,163,163,163,163,163, +836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836, +836,836,836,836,163,163,163,163,163,163,163,163,163,163,163,163, /* block 239 */ -176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, -176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, -176,176,176,176,176,176,176,176,176,176,176,176,176,176,196,196, -176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, -176,176,176,176,176,176,176,196,196,196,196,196,196,196,196,196, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,163,163,163,163,163,163,163,163,163, +833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833, +833,833,836,836,836,836,836,836,836,163,163,163,163,163,163,163, /* block 240 */ -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725, +725,725,725,725,725,725,725,725,725,725,726,726,726,726,726,726, +726,726,737,737,726,726,726,726,726,726,726,726,726,726,726,726, +726,726,726,726,725,725,725,725,725,725,725,725,725,725,725,725, +725,725,725,725,725,725,725,725,725,725,725,725,725,725,726,726, +726,726,726,726,726,163,737,737,726,726,726,726,726,726,726,726, +726,726,726,726,726,726,726,726,725,725,725,725,725,725,725,725, +725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725, /* block 241 */ -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, +725,725,726,726,726,726,726,726,726,726,737,737,726,726,726,726, +726,726,726,726,726,726,726,726,726,726,726,726,725,163,725,725, +163,163,725,163,163,725,725,163,163,725,725,725,725,163,725,725, +725,725,725,725,725,725,726,726,726,726,163,726,163,726,737,737, +726,726,726,726,163,726,726,726,726,726,726,726,726,726,726,726, +725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725, +725,725,725,725,725,725,725,725,725,725,726,726,726,726,726,726, +726,726,737,737,726,726,726,726,726,726,726,726,726,726,726,726, /* block 242 */ -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,196,196,196,196,196,196,196,196,196,196, +726,726,726,726,725,725,163,725,725,725,725,163,163,725,725,725, +725,725,725,725,725,163,725,725,725,725,725,725,725,163,726,726, +726,726,726,726,726,726,737,737,726,726,726,726,726,726,726,726, +726,726,726,726,726,726,726,726,725,725,163,725,725,725,725,163, +725,725,725,725,725,163,725,163,163,163,725,725,725,725,725,725, +725,163,726,726,726,726,726,726,726,726,737,737,726,726,726,726, +726,726,726,726,726,726,726,726,726,726,726,726,725,725,725,725, +725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725, /* block 243 */ -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,196,196,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,1480,1480,176,176,176,510,510,510,1481,1481,1481, -1481,1481,1481, 51, 51, 51, 51, 51, 51, 51, 51,176,176,176,176,176, +725,725,725,725,725,725,726,726,726,726,726,726,726,726,737,737, +726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726, +725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725, +725,725,725,725,725,725,725,725,725,725,726,726,726,726,726,726, +726,726,737,737,726,726,726,726,726,726,726,726,726,726,726,726, +726,726,726,726,725,725,725,725,725,725,725,725,725,725,725,725, +725,725,725,725,725,725,725,725,725,725,725,725,725,725,726,726, +726,726,726,726,726,726,737,737,726,726,726,726,726,726,726,726, /* block 244 */ -176,176,176,510,510,176,176,176,176,176,176,176,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,176,176,176,176,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,781,781,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +726,726,726,726,726,726,726,726,725,725,725,725,725,725,725,725, +725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725, +725,725,726,726,726,726,726,726,726,726,737,737,726,726,726,726, +726,726,726,726,726,726,726,726,726,726,726,726,725,725,725,725, +725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725, +725,725,725,725,725,725,726,726,726,726,726,726,726,726,737,737, +726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726, +725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725, /* block 245 */ -1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077, -1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077, -1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077, -1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077, -1077,1077,1482,1482,1482,1077,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +725,725,725,725,725,725,725,725,725,725,726,726,726,726,726,726, +726,726,737,737,726,726,726,726,726,726,726,726,726,726,726,726, +726,726,726,726,726,726,163,163,725,725,725,725,725,725,725,725, +725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725, +725,1367,726,726,726,726,726,726,726,726,726,726,726,726,726,726, +726,726,726,726,726,726,726,726,726,726,726,716,726,726,726,726, +726,726,725,725,725,725,725,725,725,725,725,725,725,725,725,725, +725,725,725,725,725,725,725,725,725,725,725,1367,726,726,726,726, /* block 246 */ -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,907, -907,907,907,907,196,196,196,196,196,196,196,196,196,196,196,196, -907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,907, -907,907,907,907,196,196,196,196,196,196,196,196,196,196,196,196, +726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726, +726,726,726,726,726,716,726,726,726,726,726,726,725,725,725,725, +725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725, +725,725,725,725,725,1367,726,726,726,726,726,726,726,726,726,726, +726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,716, +726,726,726,726,726,726,725,725,725,725,725,725,725,725,725,725, +725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,1367, +726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726, /* block 247 */ -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,196,196,196,196,196,196,196,196,196, -904,904,904,904,904,904,904,904,904,904,904,904,904,904,904,904, -904,904,907,907,907,907,907,907,907,196,196,196,196,196,196,196, +726,726,726,726,726,726,726,726,726,716,726,726,726,726,726,726, +725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725, +725,725,725,725,725,725,725,725,725,1367,726,726,726,726,726,726, +726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726, +726,726,726,716,726,726,726,726,726,726,725,726,163,163,1368,1368, +1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368, +1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368, +1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368,1368, /* block 248 */ -782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782, -782,782,782,782,782,782,782,782,782,782,783,783,783,783,783,783, -783,783,795,795,783,783,783,783,783,783,783,783,783,783,783,783, -783,783,783,783,782,782,782,782,782,782,782,782,782,782,782,782, -782,782,782,782,782,782,782,782,782,782,782,782,782,782,783,783, -783,783,783,783,783,196,795,795,783,783,783,783,783,783,783,783, -783,783,783,783,783,783,783,783,782,782,782,782,782,782,782,782, -782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782, +1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369, +1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369, +1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369, +1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369, +1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369, +1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369, +1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369, +1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369, /* block 249 */ -782,782,783,783,783,783,783,783,783,783,795,795,783,783,783,783, -783,783,783,783,783,783,783,783,783,783,783,783,782,196,782,782, -196,196,782,196,196,782,782,196,196,782,782,782,782,196,782,782, -782,782,782,782,782,782,783,783,783,783,196,783,196,783,795,795, -783,783,783,783,196,783,783,783,783,783,783,783,783,783,783,783, -782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782, -782,782,782,782,782,782,782,782,782,782,783,783,783,783,783,783, -783,783,795,795,783,783,783,783,783,783,783,783,783,783,783,783, +1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370, +1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370, +1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370, +1370,1370,1370,1370,1370,1370,1370,1369,1369,1369,1369,1370,1370,1370,1370,1370, +1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370, +1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370, +1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1369,1369,1369, +1369,1369,1369,1369,1369,1370,1369,1369,1369,1369,1369,1369,1369,1369,1369,1369, /* block 250 */ -783,783,783,783,782,782,196,782,782,782,782,196,196,782,782,782, -782,782,782,782,782,196,782,782,782,782,782,782,782,196,783,783, -783,783,783,783,783,783,795,795,783,783,783,783,783,783,783,783, -783,783,783,783,783,783,783,783,782,782,196,782,782,782,782,196, -782,782,782,782,782,196,782,196,196,196,782,782,782,782,782,782, -782,196,783,783,783,783,783,783,783,783,795,795,783,783,783,783, -783,783,783,783,783,783,783,783,783,783,783,783,782,782,782,782, -782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782, +1369,1369,1369,1369,1370,1369,1369,1371,1372,1371,1371,1373,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,1370,1370,1370,1370,1370, +163,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,1370, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 251 */ -782,782,782,782,782,782,783,783,783,783,783,783,783,783,795,795, -783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783, -782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782, -782,782,782,782,782,782,782,782,782,782,783,783,783,783,783,783, -783,783,795,795,783,783,783,783,783,783,783,783,783,783,783,783, -783,783,783,783,782,782,782,782,782,782,782,782,782,782,782,782, -782,782,782,782,782,782,782,782,782,782,782,782,782,782,783,783, -783,783,783,783,783,783,795,795,783,783,783,783,783,783,783,783, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 92, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,644, 70, 70, 70, 70,163, +163,163,163,163,163, 70, 70, 70, 70, 70, 70,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 252 */ -783,783,783,783,783,783,783,783,782,782,782,782,782,782,782,782, -782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782, -782,782,783,783,783,783,783,783,783,783,795,795,783,783,783,783, -783,783,783,783,783,783,783,783,783,783,783,783,782,782,782,782, -782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782, -782,782,782,782,782,782,783,783,783,783,783,783,783,783,795,795, -783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783, -782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782, +1374,1374,1374,1374,1374,1374,1374,163,1374,1374,1374,1374,1374,1374,1374,1374, +1374,1374,1374,1374,1374,1374,1374,1374,1374,163,163,1374,1374,1374,1374,1374, +1374,1374,163,1374,1374,163,1374,1374,1374,1374,1374,163,163,163,163,163, +858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858, +858,858,858,858,858,858,858,858,858,858,858,858,1375,1375,858,858, +858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858, +858,858,858,858,858,858,858,858,1375,858,858,858,858,858,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 253 */ -782,782,782,782,782,782,782,782,782,782,783,783,783,783,783,783, -783,783,795,795,783,783,783,783,783,783,783,783,783,783,783,783, -783,783,783,783,783,783,196,196,782,782,782,782,782,782,782,782, -782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782, -782,1483,783,783,783,783,783,783,783,783,783,783,783,783,783,783, -783,783,783,783,783,783,783,783,783,783,783,1483,783,783,783,783, -783,783,782,782,782,782,782,782,782,782,782,782,782,782,782,782, -782,782,782,782,782,782,782,782,782,782,782,1483,783,783,783,783, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,788, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 254 */ -783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783, -783,783,783,783,783,1483,783,783,783,783,783,783,782,782,782,782, -782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782, -782,782,782,782,782,1483,783,783,783,783,783,783,783,783,783,783, -783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,1483, -783,783,783,783,783,783,782,782,782,782,782,782,782,782,782,782, -782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,1483, -783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783, +1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376, +1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376, +1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,163,163,163, +1377,1377,1377,1377,1377,1377,1377,1378,1378,1378,1378,1378,1379,1379,163,163, +1380,1380,1380,1380,1380,1380,1380,1380,1380,1380,163,163,163,163,1376,1381, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 255 */ -783,783,783,783,783,783,783,783,783,1483,783,783,783,783,783,783, -782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782, -782,782,782,782,782,782,782,782,782,1483,783,783,783,783,783,783, -783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783, -783,783,783,1483,783,783,783,783,783,783,782,783,196,196,1484,1484, -1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484, -1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484, -1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382, +1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1383,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384, +1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384, +1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1385,1385,1385,1385, +1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,163,163,163,163,163,1387, /* block 256 */ -1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485, -1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485, -1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485, -1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485, -1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485, -1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485, -1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485, -1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +1388,1388,1388,1388,1388,1388,1388,1388,1388,1388,1388,1388,1388,1388,1388,1388, +1388,1388,1388,1388,1388,1388,1388,1388,1388,1388,1388,1389,1390,1390,1390,1390, +1391,1391,1391,1391,1391,1391,1391,1391,1391,1391,163,163,163,163,163,163, /* block 257 */ -1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486, -1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486, -1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486, -1486,1486,1486,1486,1486,1486,1486,1485,1485,1485,1485,1486,1486,1486,1486,1486, -1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486, -1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486, -1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1485,1485,1485, -1485,1485,1485,1485,1485,1486,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +484,484,484,484,484,484,484,163,484,484,484,484,163,484,484,163, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,163, /* block 258 */ -1485,1485,1485,1485,1486,1485,1485,1487,1488,1487,1487,1489,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,1486,1486,1486,1486,1486, -196,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392, +1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392, +1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392, +1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392, +1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392, +1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392, +1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392, +1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392, /* block 259 */ - 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 93, 70, 70, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,694, 70, 70, 70, 70,196, -196,196,196,196,196, 70, 70, 70, 70, 70, 70,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392, +1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392, +1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392, +1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392, +1392,1392,1392,1392,1392,262,262,1393,1393,1393,1393,1393,1393,1393,1393,1393, +1394,1394,1394,1394,1394,1394,1394,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, /* block 260 */ -1490,1490,1490,1490,1490,1490,1490,196,1490,1490,1490,1490,1490,1490,1490,1490, -1490,1490,1490,1490,1490,1490,1490,1490,1490,196,196,1490,1490,1490,1490,1490, -1490,1490,196,1490,1490,196,1490,1490,1490,1490,1490,196,196,196,196,196, -929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, -929,929,929,929,929,929,929,929,929,929,929,929,1491,1491,929,929, -929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, -929,929,929,929,929,929,929,929,1491,929,929,929,929,929,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395, +1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395, +1395,1395,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396, +1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396, +1396,1396,1396,1396,1397,1397,1397,1398,1399,1399,1399,1400,262,262,262,262, +1401,1401,1401,1401,1401,1401,1401,1401,1401,1401,262,262,262,262,1402,1402, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, /* block 261 */ -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,849, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +302,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403, /* block 262 */ -1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492, -1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492, -1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,196,196,196, -1493,1493,1493,1493,1493,1493,1493,1494,1494,1494,1494,1494,1495,1495,196,196, -1496,1496,1496,1496,1496,1496,1496,1496,1496,1496,196,196,196,196,1492,1497, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403, +1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403, +1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1404,1403,1403,1403, +1405,1403,1403,1403,1403,302,302,302,302,302,302,302,302,302,302,302, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, /* block 263 */ -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,1498, -1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,1499,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500, -1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500, -1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1501,1501,1501,1501, -1502,1502,1502,1502,1502,1502,1502,1502,1502,1502,196,196,196,196,196,1503, +302,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403, +1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403, +1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1404,1403, +1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,302,302, +302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, +262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262, /* block 264 */ -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -1504,1504,1504,1504,1504,1504,1504,1504,1504,1504,1504,1504,1504,1504,1504,1504, -1504,1504,1504,1504,1504,1504,1504,1504,1504,1504,1504,1505,1506,1506,1506,1506, -1507,1507,1507,1507,1507,1507,1507,1507,1507,1507,196,196,196,196,196,196, +1406,1406,1406,1406,302,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406, +1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406, +302,1406,1406,302,1406,302,302,1406,302,1406,1406,1406,1406,1406,1406,1406, +1406,1406,1406,302,1406,1406,1406,1406,302,1406,302,1406,302,302,302,302, +302,302,1406,302,302,302,302,1406,302,1406,302,1406,302,1406,1406,1406, +302,1406,1406,302,1406,302,302,1406,302,1406,302,1406,302,1406,302,1406, +302,1406,1406,302,1406,302,302,1406,1406,1406,1406,302,1406,1406,1406,1406, +1406,1406,1406,302,1406,1406,1406,1406,302,1406,1406,1406,1406,302,1406,302, /* block 265 */ -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,1508, -1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,1509,1510, -1508,1511,1511,1511,1511,1511,1511,1511,1511,1511,1511,196,196,196,196,1512, +1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,302,1406,1406,1406,1406,1406, +1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,302,302,302,302, +302,1406,1406,1406,302,1406,1406,1406,1406,1406,302,1406,1406,1406,1406,1406, +1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,1406,302,302,302,302, +302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302, +302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302, +302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302, +274,274,302,302,302,302,302,302,302,302,302,302,302,302,302,302, /* block 266 */ -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -533,533,533,533,533,533,533,196,533,533,533,533,196,533,533,196, -533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,196, +1407,1407,1407,1407,1408,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407, +1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407, +1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1409,1409,1409,1409, +1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407, +1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407, +1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407, +1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407, +1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407, /* block 267 */ -1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513, -1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513, -1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513, -1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513, -1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513, -1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513, -1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513, -1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513, +1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407, +1407,1407,1407,1407,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1409, +1409,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407, +1409,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1408, +1409,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407, +1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407, +1407,1407,1407,1407,1407,1407,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, /* block 268 */ -1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513, -1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513, -1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513, -1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513, -1513,1513,1513,1513,1513,297,297,1514,1514,1514,1514,1514,1514,1514,1514,1514, -1515,1515,1515,1515,1515,1515,1515,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 58, 58,1407,1407,1407, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,1407, +1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410, +1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,461,461,461,461,461,461, +1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410, +1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,724,724,1407,1407,1407,1407, +1411,1411,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,1411,1411, /* block 269 */ -1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516, -1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516, -1516,1516,1517,1517,1517,1517,1517,1517,1517,1517,1517,1517,1517,1517,1517,1517, -1517,1517,1517,1517,1517,1517,1517,1517,1517,1517,1517,1517,1517,1517,1517,1517, -1517,1517,1517,1517,1518,1518,1518,1519,1520,1520,1520,1521,297,297,297,297, -1522,1522,1522,1522,1522,1522,1522,1522,1522,1522,297,297,297,297,1523,1523, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, +1410,1410,1410,1410,1410,1410,1410,1410,1410,1410,461,461,461,461,1412,461, +461,1412,1412,1412,1412,1412,1412,1412,1412,1412,1412,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,1407,1409,1409, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1409,1409,1409,1409,1409,1409,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413, +1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413, /* block 270 */ -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, +1414,1412,1415,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +461,461,461,461,461,461,461,461,461,461,1412,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,1412, +461,461,1412,1412,1412,1412,1412,1415,1412,1412,1412,461,1409,1409,1409,1409, +461,461,461,461,461,461,461,461,461,1409,1409,1409,1409,1409,1409,1409, +1416,1416,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1407,1407,1407,1407,1407,1407,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, /* block 271 */ -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -340,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, /* block 272 */ -1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524, -1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524, -1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1525,1524,1524,1524, -1526,1524,1524,1524,1524,340,340,340,340,340,340,340,340,340,340,340, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,728,1407,1407,728,728,728,728,728,728,728,728,728,1408,1408,1408, +1408,1408,1408,1408,1408,1408,728,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,728,1408,1408, /* block 273 */ -340,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524, -1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524, -1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1525,1524, -1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,340,340, -340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, -297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297, +1408,1408,1408,1408,1408,1417,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1407,1407,728,728,1407,728,728,728,1407,1407,728,728, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1417,1417,1417,1408,1408,1417,1408,1408,1417,1418,1418,728,728,1408, +1408,1408,1408,1408,728,728,728,728,728,728,728,728,728,728,728,728, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1407,1407,728,1408,728,1407,728,1408,1408,1408,1419,1419,1419,1419,1419, /* block 274 */ -1527,1527,1527,1527,340,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527, -1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527, -340,1527,1527,340,1527,340,340,1527,340,1527,1527,1527,1527,1527,1527,1527, -1527,1527,1527,340,1527,1527,1527,1527,340,1527,340,1527,340,340,340,340, -340,340,1527,340,340,340,340,1527,340,1527,340,1527,340,1527,1527,1527, -340,1527,1527,340,1527,340,340,1527,340,1527,340,1527,340,1527,340,1527, -340,1527,1527,340,1527,340,340,1527,1527,1527,1527,340,1527,1527,1527,1527, -1527,1527,1527,340,1527,1527,1527,1527,340,1527,1527,1527,1527,340,1527,340, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,728, +1408,728,1417,1417,1408,1408,1417,1417,1417,1417,1417,1417,1417,1417,1417,1417, +1417,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1417,1417,1417,1417,1417,1417,1417,1417,1417,1417, +1417,1417,1417,1417,1417,1417,1417,1417,1417,1408,1408,1408,1417,1408,1408,1408, /* block 275 */ -1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,340,1527,1527,1527,1527,1527, -1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,340,340,340,340, -340,1527,1527,1527,340,1527,1527,1527,1527,1527,340,1527,1527,1527,1527,1527, -1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,340,340,340,340, -340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340, -340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340, -340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340, -309,309,340,340,340,340,340,340,340,340,340,340,340,340,340,340, +1408,1417,1417,1417,1408,1417,1417,1417,1408,1408,1408,1408,1408,1408,1408,1417, +1408,1417,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1417,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,728,1407,1408, /* block 276 */ -1528,1528,1528,1528,1529,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528, -1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528, -1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1530,1530,1530,1530, -1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528, -1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528, -1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528, -1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528, -1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,724,724, +724,724,724,724,724,724,1407,1407,1407,728,728,1408,1408,1408,1408,1407, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1407,1407,1407,1407,1407,1407,1407,728, +728,1407,1407,728,1418,1418,728,728,728,728,1417,1407,1407,1407,1407,1407, /* block 277 */ -1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528, -1528,1528,1528,1528,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1530, -1530,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528, -1530,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1529, -1530,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528, -1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528, -1528,1528,1528,1528,1528,1528,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, +1407,1407,1407,1407,1407,1407,1407,728,1407,1407,728,728,728,728,1407,1407, +1418,1407,1407,1407,1407,1417,1417,1407,1407,1407,1407,1407,1407,1407,1407,1407, +1407,1407,1407,1407,1408,728,1407,1407,728,1407,1407,1407,1407,1407,1407,1407, +1407,728,728,1407,1407,1407,1407,1407,1407,1407,1407,1407,728,1407,1407,1407, +1407,1407,728,728,728,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407, +1407,728,728,728,1407,1407,1407,1407,1407,1407,1407,1407,728,728,728,1407, +1407,728,1407,728,1407,1407,1407,1407,728,1407,1407,1407,1407,1407,1407,728, +1407,1407,1407,728,1407,1407,1407,1407,1407,1407,728,1408,1408,1408,1408,1408, /* block 278 */ -814,814,814,814,814,814,814,814,814,814,814, 58, 58,1528,1528,1528, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,1528, -1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531, -1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,510,510,510,510,510,510, -1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531, -1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,781,781,1528,1528,1528,1528, -1532,1532,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1532,1532, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1417,1417,1417,1408,1408,1408,1417,1417,1417,1417,1417, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, /* block 279 */ -1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,510,510,510,510,1533,510, -510,1533,1533,1533,1533,1533,1533,1533,1533,1533,1533,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,1528,1530,1530, -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1530,1530,1530,1530,1530,1530,1534,1534,1534,1534,1534,1534,1534,1534,1534,1534, -1534,1534,1534,1534,1534,1534,1534,1534,1534,1534,1534,1534,1534,1534,1534,1534, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1417,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1417,1417,1417,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1417,1408,1408,1408,1408,1408,1407,1407,1407,1407,1407,728,1417,728,728,728, +1408,1408,1408,1407,1407,1408,1408,1408,1409,1409,1409,1409,1408,1408,1408,1408, +728,728,728,728,728,728,1407,1407,1407,728,1407,1408,1408,1409,1409,1409, +728,1407,1407,728,1408,1408,1408,1408,1408,1408,1408,1408,1408,1409,1409,1409, /* block 280 */ -1535,1533,1536,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -510,510,510,510,510,510,510,510,510,510,1533,510,510,510,510,510, -510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,1533, -510,510,1533,1533,1533,1533,1533,1536,1533,1533,1533,510,1530,1530,1530,1530, -510,510,510,510,510,510,510,510,510,1530,1530,1530,1530,1530,1530,1530, -1537,1537,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1528,1528,1528,1528,1528,1528,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,1407,1407,1407,1409,1409,1409,1409,1407,1407,1407,1407,1407, /* block 281 */ -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,1407,1407,1407,1407,1407,1409,1409,1409,1409,1409,1409, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1409,1409,1409,1409, +1408,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, /* block 282 */ -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,785,1528,1528,785,785,785,785,785,785,785,785,785,1529,1529,1529, -1529,1529,1529,1529,1529,1529,785,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,785,1529,1529, +724,724,724,724,724,724,724,724,724,724,724,724,1409,1409,1409,1409, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,1409,1409,1409,1409,1409,1409,1409,1409, +724,724,724,724,724,724,724,724,724,724,1409,1409,1409,1409,1409,1409, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, /* block 283 */ -1529,1529,1529,1529,1529,1538,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1528,1528,785,785,1528,785,785,785,1528,1528,785,785, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1538,1538,1538,1529,1529,1538,1529,1529,1538,1539,1539,785,785,1529, -1529,1529,1529,1529,785,785,785,785,785,785,785,785,785,785,785,785, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1528,1528,785,1529,785,1528,785,1529,1529,1529,1540,1540,1540,1540,1540, +724,724,724,724,724,724,724,724,1409,1409,1409,1409,1409,1409,1409,1409, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,1409,1409, +1407,1407,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, /* block 284 */ -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,785, -1529,785,1538,1538,1529,1529,1538,1538,1538,1538,1538,1538,1538,1538,1538,1538, -1538,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1538,1538,1538,1538,1538,1538,1538,1538,1538,1538, -1538,1538,1538,1538,1538,1538,1538,1538,1538,1529,1529,1529,1538,1529,1529,1529, +724,724,724,724,724,724,724,724,724,724,724,724,1417,1408,1408,1417, +1408,1408,1408,1408,1408,1408,1408,1408,1417,1417,1417,1417,1417,1417,1417,1417, +1408,1408,1408,1408,1408,1408,1417,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1417,1417,1417,1417,1417,1417,1417,1417,1417,1417,1408,724,1417,1417,1417,1408, +1408,1408,1408,1408,1408,1408,724,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1417,1408,1408,1408,1408,1408,1408,1408,1408, /* block 285 */ -1529,1538,1538,1538,1529,1538,1538,1538,1529,1529,1529,1529,1529,1529,1529,1538, -1529,1538,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1538,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,785,1528,1529, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1420,1420,1420,1420,1408,1417,1417,1408,1417,1417,1408,1417,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1417,1417,1417, +1408,1417,1417,1417,1417,1417,1417,1417,1417,1417,1417,1417,1417,1417,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, /* block 286 */ -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,781,781, -781,781,781,781,781,781,1528,1528,1528,785,785,1529,1529,1529,1529,1528, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1528,1528,1528,1528,1528,1528,1528,785, -785,1528,1528,785,1539,1539,785,785,785,785,1538,1528,1528,1528,1528,1528, +1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407, +1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407, +1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407, +1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407, +1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407, +1407,1407,1407,1407,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,1409,1409, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1409,1409,1409, /* block 287 */ -1528,1528,1528,1528,1528,1528,1528,785,1528,1528,785,785,785,785,1528,1528, -1539,1528,1528,1528,1528,1538,1538,1528,1528,1528,1528,1528,1528,1528,1528,1528, -1528,1528,1528,1528,1529,785,1528,1528,785,1528,1528,1528,1528,1528,1528,1528, -1528,785,785,1528,1528,1528,1528,1528,1528,1528,1528,1528,785,1528,1528,1528, -1528,1528,785,785,785,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528, -1528,785,785,785,1528,1528,1528,1528,1528,1528,1528,1528,785,785,785,1528, -1528,785,1528,785,1528,1528,1528,1528,785,1528,1528,1528,1528,1528,1528,785, -1528,1528,1528,785,1528,1528,1528,1528,1528,1528,785,1529,1529,1529,1529,1529, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1409,1409,1409,1409,1409,1409,1409, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1409,1408, +1408,1408,1408,1417,1417,1417,1409,1409,1409,1409,1409,1409,1409,1409,1408,1408, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1409,1409,1409,1409, +1408,1408,1408,1408,1408,1408,1408,1408,1408,1409,1409,1409,1409,1409,1409,1409, +1417,1417,1417,1417,1417,1417,1417,1417,1417,1409,1409,1409,1409,1409,1409,1409, /* block 288 */ -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1538,1538,1538,1529,1529,1529,1538,1538,1538,1538,1538, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, /* block 289 */ -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1538,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1538,1538,1538,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1538,1529,1529,1529,1529,1529,1528,1528,1528,1528,1528,785,1538,785,785,785, -1529,1529,1529,1528,1528,1529,1529,1529,1530,1530,1530,1530,1529,1529,1529,1529, -785,785,785,785,785,785,1528,1528,1528,785,1528,1529,1529,1530,1530,1530, -785,1528,1528,785,1529,1529,1529,1529,1529,1529,1529,1529,1529,1530,1530,1530, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,163,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724, +724,724,724,724,724,724,724,724,724,724,724,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +1421,1421,1421,1421,1421,1421,1421,1421,1421,1421,163,163,163,163,163,163, /* block 290 */ -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,1528,1528,1528,1530,1530,1530,1530,1528,1528,1528,1528,1528, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, +1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,957,957, /* block 291 */ -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,1528,1528,1528,1528,1528,1530,1530,1530,1530,1530,1530, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1530,1530,1530,1530, -1529,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 292 */ -781,781,781,781,781,781,781,781,781,781,781,781,1530,1530,1530,1530, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,1530,1530,1530,1530,1530,1530,1530,1530, -781,781,781,781,781,781,781,781,781,781,1530,1530,1530,1530,1530,1530, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,163,163,163,163,163,163, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, /* block 293 */ -781,781,781,781,781,781,781,781,1530,1530,1530,1530,1530,1530,1530,1530, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,1530,1530, -1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1530,1530,1530,1530, -1528,1528,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,163,163, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, /* block 294 */ -781,781,781,781,781,781,781,781,781,781,781,781,1538,1529,1529,1538, -1529,1529,1529,1529,1529,1529,1529,1529,1538,1538,1538,1538,1538,1538,1538,1538, -1529,1529,1529,1529,1529,1529,1538,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1538,1538,1538,1538,1538,1538,1538,1538,1538,1538,1529,781,1538,1538,1538,1529, -1529,1529,1529,1529,1529,1529,781,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1538,1529,1529,1529,1529,1529,1529,1529,1529, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, /* block 295 */ -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1541,1541,1541,1541,1529,1538,1538,1529,1538,1538,1529,1538,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1538,1538,1538, -1529,1538,1538,1538,1538,1538,1538,1538,1538,1538,1538,1538,1538,1538,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 296 */ -1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528, -1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528, -1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528, -1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528, -1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528, -1528,1528,1528,1528,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1530,1530, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1530,1530,1530, +952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952, +952,952,952,952,952,952,952,952,952,952,952,952,952,952,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 297 */ -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1530,1530,1530,1530,1530,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529, -1529,1529,1529,1538,1538,1538,1529,1530,1530,1530,1530,1530,1530,1530,1529,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1530,1530,1529, -1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1530,1530,1530,1530,1530,1530, -1538,1538,1538,1538,1538,1538,1538,1538,1538,1530,1530,1530,1530,1530,1530,1530, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,957,957, /* block 298 */ -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,196,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781, -1479,1479,1479,1479,1479,1479,1479,1479,1479,1479,196,196,196,196,196,196, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,163,163,163,163,163, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, /* block 299 */ -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530, -1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1032,1032, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, /* block 300 */ -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +708,713,708,708,708,708,708,708,708,708,708,708,708,708,708,708, +708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, +1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422, +1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422, +1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422, +1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422, +1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422, +1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422,1422, /* block 301 */ -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,196,196,196,196,196,196, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, +708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, +708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, +708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, +708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, +708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, +708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, +708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, +708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, /* block 302 */ -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,196,196, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, +960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960, +960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960, +960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960, +960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960, +960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960, +960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960, +960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960, +960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960, /* block 303 */ -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, +960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960, +960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960, +960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960, +960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960, +960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960, +960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960, +960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960, +708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, /* block 304 */ -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, - -/* block 305 */ -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, - -/* block 306 */ -1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, -1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, - -/* block 307 */ -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,1032,1032, - -/* block 308 */ -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,196,196,196,196,196, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, - -/* block 309 */ -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, -196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, - -/* block 310 */ -765,770,765,765,765,765,765,765,765,765,765,765,765,765,765,765, -765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765, -1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542, -1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542, -1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542, -1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542, -1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542, -1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542, - -/* block 311 */ -765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765, -765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765, -765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765, -765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765, -765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765, -765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765, -765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765, -765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765, - -/* block 312 */ -1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035, -1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035, -1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035, -1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035, -1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035, -1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035, -1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035, -1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035, - -/* block 313 */ -1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035, -1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035, -1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035, -1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035, -1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035, -1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035, -1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035, -765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765, - -/* block 314 */ -1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024, -1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024, -1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024, -1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024, -1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024, -1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024, -1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024, -1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1032,1032, +951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951, +951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951, +951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951, +951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951, +951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951, +951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951, +951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951, +951,951,951,951,951,951,951,951,951,951,951,951,951,951,957,957, }; #if UCD_BLOCK_SIZE != 128 diff --git a/ext/pcre/pcre2lib/pcre2_ucp.h b/ext/pcre/pcre2lib/pcre2_ucp.h index 513c54e29e6b7..9ccc82975080e 100644 --- a/ext/pcre/pcre2lib/pcre2_ucp.h +++ b/ext/pcre/pcre2lib/pcre2_ucp.h @@ -132,18 +132,13 @@ enum { ucp_Hex_Digit, ucp_IDS_Binary_Operator, ucp_IDS_Trinary_Operator, - ucp_IDS_Unary_Operator, - ucp_ID_Compat_Math_Continue, - ucp_ID_Compat_Math_Start, ucp_ID_Continue, ucp_ID_Start, ucp_Ideographic, - ucp_InCB, ucp_Join_Control, ucp_Logical_Order_Exception, ucp_Lowercase, ucp_Math, - ucp_Modifier_Combining_Mark, ucp_Noncharacter_Code_Point, ucp_Pattern_Syntax, ucp_Pattern_White_Space, @@ -224,8 +219,6 @@ enum { ucp_Latin, ucp_Greek, ucp_Cyrillic, - ucp_Armenian, - ucp_Hebrew, ucp_Arabic, ucp_Syriac, ucp_Thaana, @@ -239,21 +232,15 @@ enum { ucp_Kannada, ucp_Malayalam, ucp_Sinhala, - ucp_Thai, - ucp_Tibetan, ucp_Myanmar, ucp_Georgian, ucp_Hangul, - ucp_Ethiopic, - ucp_Cherokee, - ucp_Runic, ucp_Mongolian, ucp_Hiragana, ucp_Katakana, ucp_Bopomofo, ucp_Han, ucp_Yi, - ucp_Gothic, ucp_Tagalog, ucp_Hanunoo, ucp_Buhid, @@ -261,33 +248,21 @@ enum { ucp_Limbu, ucp_Tai_Le, ucp_Linear_B, - ucp_Shavian, ucp_Cypriot, ucp_Buginese, ucp_Coptic, ucp_Glagolitic, - ucp_Tifinagh, ucp_Syloti_Nagri, ucp_Phags_Pa, ucp_Nko, ucp_Kayah_Li, - ucp_Lycian, - ucp_Carian, - ucp_Lydian, - ucp_Avestan, - ucp_Samaritan, - ucp_Lisu, ucp_Javanese, - ucp_Old_Turkic, ucp_Kaithi, ucp_Mandaic, ucp_Chakma, - ucp_Meroitic_Hieroglyphs, ucp_Sharada, ucp_Takri, - ucp_Caucasian_Albanian, ucp_Duployan, - ucp_Elbasan, ucp_Grantha, ucp_Khojki, ucp_Linear_A, @@ -299,10 +274,7 @@ enum { ucp_Khudawadi, ucp_Tirhuta, ucp_Multani, - ucp_Old_Hungarian, ucp_Adlam, - ucp_Osage, - ucp_Tangut, ucp_Masaram_Gondi, ucp_Dogra, ucp_Gunjala_Gondi, @@ -312,28 +284,31 @@ enum { ucp_Yezidi, ucp_Cypro_Minoan, ucp_Old_Uyghur, - ucp_Toto, - ucp_Garay, - ucp_Gurung_Khema, - ucp_Ol_Onal, - ucp_Sunuwar, - ucp_Todhri, - ucp_Tulu_Tigalari, /* Scripts which has no characters in other scripts. */ ucp_Unknown, ucp_Common, + ucp_Armenian, + ucp_Hebrew, + ucp_Thai, ucp_Lao, + ucp_Tibetan, + ucp_Ethiopic, + ucp_Cherokee, ucp_Canadian_Aboriginal, ucp_Ogham, + ucp_Runic, ucp_Khmer, ucp_Old_Italic, + ucp_Gothic, ucp_Deseret, ucp_Inherited, ucp_Ugaritic, + ucp_Shavian, ucp_Osmanya, ucp_Braille, ucp_New_Tai_Lue, + ucp_Tifinagh, ucp_Old_Persian, ucp_Kharoshthi, ucp_Balinese, @@ -345,22 +320,32 @@ enum { ucp_Vai, ucp_Saurashtra, ucp_Rejang, + ucp_Lycian, + ucp_Carian, + ucp_Lydian, ucp_Cham, ucp_Tai_Tham, ucp_Tai_Viet, + ucp_Avestan, ucp_Egyptian_Hieroglyphs, + ucp_Samaritan, + ucp_Lisu, ucp_Bamum, ucp_Meetei_Mayek, ucp_Imperial_Aramaic, ucp_Old_South_Arabian, ucp_Inscriptional_Parthian, ucp_Inscriptional_Pahlavi, + ucp_Old_Turkic, ucp_Batak, ucp_Brahmi, ucp_Meroitic_Cursive, + ucp_Meroitic_Hieroglyphs, ucp_Miao, ucp_Sora_Sompeng, + ucp_Caucasian_Albanian, ucp_Bassa_Vah, + ucp_Elbasan, ucp_Pahawh_Hmong, ucp_Mende_Kikakui, ucp_Mro, @@ -373,10 +358,13 @@ enum { ucp_Ahom, ucp_Anatolian_Hieroglyphs, ucp_Hatran, + ucp_Old_Hungarian, ucp_SignWriting, ucp_Bhaiksuki, ucp_Marchen, ucp_Newa, + ucp_Osage, + ucp_Tangut, ucp_Nushu, ucp_Soyombo, ucp_Zanabazar_Square, @@ -390,10 +378,10 @@ enum { ucp_Dives_Akuru, ucp_Khitan_Small_Script, ucp_Tangsa, + ucp_Toto, ucp_Vithkuqi, ucp_Kawi, ucp_Nag_Mundari, - ucp_Kirat_Rai, /* This must be last */ ucp_Script_Count @@ -401,7 +389,7 @@ enum { /* Size of entries in ucd_script_sets[] */ -#define ucd_script_sets_item_size 4 +#define ucd_script_sets_item_size 3 #endif /* PCRE2_UCP_H_IDEMPOTENT_GUARD */ diff --git a/ext/pcre/pcre2lib/pcre2_ucptables.c b/ext/pcre/pcre2lib/pcre2_ucptables.c index d2b34037bea67..2110014c29ed8 100644 --- a/ext/pcre/pcre2lib/pcre2_ucptables.c +++ b/ext/pcre/pcre2lib/pcre2_ucptables.c @@ -199,8 +199,6 @@ the "loose matching" rules that Unicode advises and Perl uses. */ #define STRING_extendedpictographic0 STR_e STR_x STR_t STR_e STR_n STR_d STR_e STR_d STR_p STR_i STR_c STR_t STR_o STR_g STR_r STR_a STR_p STR_h STR_i STR_c "\0" #define STRING_extender0 STR_e STR_x STR_t STR_e STR_n STR_d STR_e STR_r "\0" #define STRING_extpict0 STR_e STR_x STR_t STR_p STR_i STR_c STR_t "\0" -#define STRING_gara0 STR_g STR_a STR_r STR_a "\0" -#define STRING_garay0 STR_g STR_a STR_r STR_a STR_y "\0" #define STRING_geor0 STR_g STR_e STR_o STR_r "\0" #define STRING_georgian0 STR_g STR_e STR_o STR_r STR_g STR_i STR_a STR_n "\0" #define STRING_glag0 STR_g STR_l STR_a STR_g "\0" @@ -221,11 +219,9 @@ the "loose matching" rules that Unicode advises and Perl uses. */ #define STRING_grlink0 STR_g STR_r STR_l STR_i STR_n STR_k "\0" #define STRING_gujarati0 STR_g STR_u STR_j STR_a STR_r STR_a STR_t STR_i "\0" #define STRING_gujr0 STR_g STR_u STR_j STR_r "\0" -#define STRING_gukh0 STR_g STR_u STR_k STR_h "\0" #define STRING_gunjalagondi0 STR_g STR_u STR_n STR_j STR_a STR_l STR_a STR_g STR_o STR_n STR_d STR_i "\0" #define STRING_gurmukhi0 STR_g STR_u STR_r STR_m STR_u STR_k STR_h STR_i "\0" #define STRING_guru0 STR_g STR_u STR_r STR_u "\0" -#define STRING_gurungkhema0 STR_g STR_u STR_r STR_u STR_n STR_g STR_k STR_h STR_e STR_m STR_a "\0" #define STRING_han0 STR_h STR_a STR_n "\0" #define STRING_hang0 STR_h STR_a STR_n STR_g "\0" #define STRING_hangul0 STR_h STR_a STR_n STR_g STR_u STR_l "\0" @@ -246,8 +242,6 @@ the "loose matching" rules that Unicode advises and Perl uses. */ #define STRING_hmnp0 STR_h STR_m STR_n STR_p "\0" #define STRING_hung0 STR_h STR_u STR_n STR_g "\0" #define STRING_idc0 STR_i STR_d STR_c "\0" -#define STRING_idcompatmathcontinue0 STR_i STR_d STR_c STR_o STR_m STR_p STR_a STR_t STR_m STR_a STR_t STR_h STR_c STR_o STR_n STR_t STR_i STR_n STR_u STR_e "\0" -#define STRING_idcompatmathstart0 STR_i STR_d STR_c STR_o STR_m STR_p STR_a STR_t STR_m STR_a STR_t STR_h STR_s STR_t STR_a STR_r STR_t "\0" #define STRING_idcontinue0 STR_i STR_d STR_c STR_o STR_n STR_t STR_i STR_n STR_u STR_e "\0" #define STRING_ideo0 STR_i STR_d STR_e STR_o "\0" #define STRING_ideographic0 STR_i STR_d STR_e STR_o STR_g STR_r STR_a STR_p STR_h STR_i STR_c "\0" @@ -257,10 +251,7 @@ the "loose matching" rules that Unicode advises and Perl uses. */ #define STRING_idst0 STR_i STR_d STR_s STR_t "\0" #define STRING_idstart0 STR_i STR_d STR_s STR_t STR_a STR_r STR_t "\0" #define STRING_idstrinaryoperator0 STR_i STR_d STR_s STR_t STR_r STR_i STR_n STR_a STR_r STR_y STR_o STR_p STR_e STR_r STR_a STR_t STR_o STR_r "\0" -#define STRING_idsu0 STR_i STR_d STR_s STR_u "\0" -#define STRING_idsunaryoperator0 STR_i STR_d STR_s STR_u STR_n STR_a STR_r STR_y STR_o STR_p STR_e STR_r STR_a STR_t STR_o STR_r "\0" #define STRING_imperialaramaic0 STR_i STR_m STR_p STR_e STR_r STR_i STR_a STR_l STR_a STR_r STR_a STR_m STR_a STR_i STR_c "\0" -#define STRING_incb0 STR_i STR_n STR_c STR_b "\0" #define STRING_inherited0 STR_i STR_n STR_h STR_e STR_r STR_i STR_t STR_e STR_d "\0" #define STRING_inscriptionalpahlavi0 STR_i STR_n STR_s STR_c STR_r STR_i STR_p STR_t STR_i STR_o STR_n STR_a STR_l STR_p STR_a STR_h STR_l STR_a STR_v STR_i "\0" #define STRING_inscriptionalparthian0 STR_i STR_n STR_s STR_c STR_r STR_i STR_p STR_t STR_i STR_o STR_n STR_a STR_l STR_p STR_a STR_r STR_t STR_h STR_i STR_a STR_n "\0" @@ -284,10 +275,8 @@ the "loose matching" rules that Unicode advises and Perl uses. */ #define STRING_khoj0 STR_k STR_h STR_o STR_j "\0" #define STRING_khojki0 STR_k STR_h STR_o STR_j STR_k STR_i "\0" #define STRING_khudawadi0 STR_k STR_h STR_u STR_d STR_a STR_w STR_a STR_d STR_i "\0" -#define STRING_kiratrai0 STR_k STR_i STR_r STR_a STR_t STR_r STR_a STR_i "\0" #define STRING_kits0 STR_k STR_i STR_t STR_s "\0" #define STRING_knda0 STR_k STR_n STR_d STR_a "\0" -#define STRING_krai0 STR_k STR_r STR_a STR_i "\0" #define STRING_kthi0 STR_k STR_t STR_h STR_i "\0" #define STRING_l0 STR_l "\0" #define STRING_l_AMPERSAND0 STR_l STR_AMPERSAND "\0" @@ -334,7 +323,6 @@ the "loose matching" rules that Unicode advises and Perl uses. */ #define STRING_masaramgondi0 STR_m STR_a STR_s STR_a STR_r STR_a STR_m STR_g STR_o STR_n STR_d STR_i "\0" #define STRING_math0 STR_m STR_a STR_t STR_h "\0" #define STRING_mc0 STR_m STR_c "\0" -#define STRING_mcm0 STR_m STR_c STR_m "\0" #define STRING_me0 STR_m STR_e "\0" #define STRING_medefaidrin0 STR_m STR_e STR_d STR_e STR_f STR_a STR_i STR_d STR_r STR_i STR_n "\0" #define STRING_medf0 STR_m STR_e STR_d STR_f "\0" @@ -349,7 +337,6 @@ the "loose matching" rules that Unicode advises and Perl uses. */ #define STRING_mlym0 STR_m STR_l STR_y STR_m "\0" #define STRING_mn0 STR_m STR_n "\0" #define STRING_modi0 STR_m STR_o STR_d STR_i "\0" -#define STRING_modifiercombiningmark0 STR_m STR_o STR_d STR_i STR_f STR_i STR_e STR_r STR_c STR_o STR_m STR_b STR_i STR_n STR_i STR_n STR_g STR_m STR_a STR_r STR_k "\0" #define STRING_mong0 STR_m STR_o STR_n STR_g "\0" #define STRING_mongolian0 STR_m STR_o STR_n STR_g STR_o STR_l STR_i STR_a STR_n "\0" #define STRING_mro0 STR_m STR_r STR_o "\0" @@ -392,8 +379,6 @@ the "loose matching" rules that Unicode advises and Perl uses. */ #define STRING_oldsoutharabian0 STR_o STR_l STR_d STR_s STR_o STR_u STR_t STR_h STR_a STR_r STR_a STR_b STR_i STR_a STR_n "\0" #define STRING_oldturkic0 STR_o STR_l STR_d STR_t STR_u STR_r STR_k STR_i STR_c "\0" #define STRING_olduyghur0 STR_o STR_l STR_d STR_u STR_y STR_g STR_h STR_u STR_r "\0" -#define STRING_olonal0 STR_o STR_l STR_o STR_n STR_a STR_l "\0" -#define STRING_onao0 STR_o STR_n STR_a STR_o "\0" #define STRING_oriya0 STR_o STR_r STR_i STR_y STR_a "\0" #define STRING_orkh0 STR_o STR_r STR_k STR_h "\0" #define STRING_orya0 STR_o STR_r STR_y STR_a "\0" @@ -478,8 +463,6 @@ the "loose matching" rules that Unicode advises and Perl uses. */ #define STRING_sterm0 STR_s STR_t STR_e STR_r STR_m "\0" #define STRING_sund0 STR_s STR_u STR_n STR_d "\0" #define STRING_sundanese0 STR_s STR_u STR_n STR_d STR_a STR_n STR_e STR_s STR_e "\0" -#define STRING_sunu0 STR_s STR_u STR_n STR_u "\0" -#define STRING_sunuwar0 STR_s STR_u STR_n STR_u STR_w STR_a STR_r "\0" #define STRING_sylo0 STR_s STR_y STR_l STR_o "\0" #define STRING_sylotinagri0 STR_s STR_y STR_l STR_o STR_t STR_i STR_n STR_a STR_g STR_r STR_i "\0" #define STRING_syrc0 STR_s STR_y STR_r STR_c "\0" @@ -515,11 +498,7 @@ the "loose matching" rules that Unicode advises and Perl uses. */ #define STRING_tirh0 STR_t STR_i STR_r STR_h "\0" #define STRING_tirhuta0 STR_t STR_i STR_r STR_h STR_u STR_t STR_a "\0" #define STRING_tnsa0 STR_t STR_n STR_s STR_a "\0" -#define STRING_todhri0 STR_t STR_o STR_d STR_h STR_r STR_i "\0" -#define STRING_todr0 STR_t STR_o STR_d STR_r "\0" #define STRING_toto0 STR_t STR_o STR_t STR_o "\0" -#define STRING_tulutigalari0 STR_t STR_u STR_l STR_u STR_t STR_i STR_g STR_a STR_l STR_a STR_r STR_i "\0" -#define STRING_tutg0 STR_t STR_u STR_t STR_g "\0" #define STRING_ugar0 STR_u STR_g STR_a STR_r "\0" #define STRING_ugaritic0 STR_u STR_g STR_a STR_r STR_i STR_t STR_i STR_c "\0" #define STRING_uideo0 STR_u STR_i STR_d STR_e STR_o "\0" @@ -711,8 +690,6 @@ const char PRIV(utt_names)[] = STRING_extendedpictographic0 STRING_extender0 STRING_extpict0 - STRING_gara0 - STRING_garay0 STRING_geor0 STRING_georgian0 STRING_glag0 @@ -733,11 +710,9 @@ const char PRIV(utt_names)[] = STRING_grlink0 STRING_gujarati0 STRING_gujr0 - STRING_gukh0 STRING_gunjalagondi0 STRING_gurmukhi0 STRING_guru0 - STRING_gurungkhema0 STRING_han0 STRING_hang0 STRING_hangul0 @@ -758,8 +733,6 @@ const char PRIV(utt_names)[] = STRING_hmnp0 STRING_hung0 STRING_idc0 - STRING_idcompatmathcontinue0 - STRING_idcompatmathstart0 STRING_idcontinue0 STRING_ideo0 STRING_ideographic0 @@ -769,10 +742,7 @@ const char PRIV(utt_names)[] = STRING_idst0 STRING_idstart0 STRING_idstrinaryoperator0 - STRING_idsu0 - STRING_idsunaryoperator0 STRING_imperialaramaic0 - STRING_incb0 STRING_inherited0 STRING_inscriptionalpahlavi0 STRING_inscriptionalparthian0 @@ -796,10 +766,8 @@ const char PRIV(utt_names)[] = STRING_khoj0 STRING_khojki0 STRING_khudawadi0 - STRING_kiratrai0 STRING_kits0 STRING_knda0 - STRING_krai0 STRING_kthi0 STRING_l0 STRING_l_AMPERSAND0 @@ -846,7 +814,6 @@ const char PRIV(utt_names)[] = STRING_masaramgondi0 STRING_math0 STRING_mc0 - STRING_mcm0 STRING_me0 STRING_medefaidrin0 STRING_medf0 @@ -861,7 +828,6 @@ const char PRIV(utt_names)[] = STRING_mlym0 STRING_mn0 STRING_modi0 - STRING_modifiercombiningmark0 STRING_mong0 STRING_mongolian0 STRING_mro0 @@ -904,8 +870,6 @@ const char PRIV(utt_names)[] = STRING_oldsoutharabian0 STRING_oldturkic0 STRING_olduyghur0 - STRING_olonal0 - STRING_onao0 STRING_oriya0 STRING_orkh0 STRING_orya0 @@ -990,8 +954,6 @@ const char PRIV(utt_names)[] = STRING_sterm0 STRING_sund0 STRING_sundanese0 - STRING_sunu0 - STRING_sunuwar0 STRING_sylo0 STRING_sylotinagri0 STRING_syrc0 @@ -1027,11 +989,7 @@ const char PRIV(utt_names)[] = STRING_tirh0 STRING_tirhuta0 STRING_tnsa0 - STRING_todhri0 - STRING_todr0 STRING_toto0 - STRING_tulutigalari0 - STRING_tutg0 STRING_ugar0 STRING_ugaritic0 STRING_uideo0 @@ -1079,7 +1037,7 @@ const char PRIV(utt_names)[] = const ucp_type_table PRIV(utt)[] = { { 0, PT_SCX, ucp_Adlam }, { 6, PT_SCX, ucp_Adlam }, - { 11, PT_SCX, ucp_Caucasian_Albanian }, + { 11, PT_SC, ucp_Caucasian_Albanian }, { 16, PT_BOOL, ucp_ASCII_Hex_Digit }, { 21, PT_SC, ucp_Ahom }, { 26, PT_BOOL, ucp_Alphabetic }, @@ -1088,13 +1046,13 @@ const ucp_type_table PRIV(utt)[] = { { 64, PT_ANY, 0 }, { 68, PT_SCX, ucp_Arabic }, { 73, PT_SCX, ucp_Arabic }, - { 80, PT_SCX, ucp_Armenian }, + { 80, PT_SC, ucp_Armenian }, { 89, PT_SC, ucp_Imperial_Aramaic }, - { 94, PT_SCX, ucp_Armenian }, + { 94, PT_SC, ucp_Armenian }, { 99, PT_BOOL, ucp_ASCII }, { 105, PT_BOOL, ucp_ASCII_Hex_Digit }, - { 119, PT_SCX, ucp_Avestan }, - { 127, PT_SCX, ucp_Avestan }, + { 119, PT_SC, ucp_Avestan }, + { 127, PT_SC, ucp_Avestan }, { 132, PT_SC, ucp_Balinese }, { 137, PT_SC, ucp_Balinese }, { 146, PT_SC, ucp_Bamum }, @@ -1148,11 +1106,11 @@ const ucp_type_table PRIV(utt)[] = { { 480, PT_SCX, ucp_Chakma }, { 485, PT_SC, ucp_Canadian_Aboriginal }, { 504, PT_SC, ucp_Canadian_Aboriginal }, - { 509, PT_SCX, ucp_Carian }, - { 514, PT_SCX, ucp_Carian }, + { 509, PT_SC, ucp_Carian }, + { 514, PT_SC, ucp_Carian }, { 521, PT_BOOL, ucp_Cased }, { 527, PT_BOOL, ucp_Case_Ignorable }, - { 541, PT_SCX, ucp_Caucasian_Albanian }, + { 541, PT_SC, ucp_Caucasian_Albanian }, { 559, PT_PC, ucp_Cc }, { 562, PT_PC, ucp_Cf }, { 565, PT_SCX, ucp_Chakma }, @@ -1162,8 +1120,8 @@ const ucp_type_table PRIV(utt)[] = { { 621, PT_BOOL, ucp_Changes_When_Lowercased }, { 643, PT_BOOL, ucp_Changes_When_Titlecased }, { 665, PT_BOOL, ucp_Changes_When_Uppercased }, - { 687, PT_SCX, ucp_Cherokee }, - { 692, PT_SCX, ucp_Cherokee }, + { 687, PT_SC, ucp_Cherokee }, + { 692, PT_SC, ucp_Cherokee }, { 701, PT_SC, ucp_Chorasmian }, { 712, PT_SC, ucp_Chorasmian }, { 717, PT_BOOL, ucp_Case_Ignorable }, @@ -1206,8 +1164,8 @@ const ucp_type_table PRIV(utt)[] = { { 963, PT_BOOL, ucp_Emoji_Component }, { 969, PT_SC, ucp_Egyptian_Hieroglyphs }, { 974, PT_SC, ucp_Egyptian_Hieroglyphs }, - { 994, PT_SCX, ucp_Elbasan }, - { 999, PT_SCX, ucp_Elbasan }, + { 994, PT_SC, ucp_Elbasan }, + { 999, PT_SC, ucp_Elbasan }, { 1007, PT_SC, ucp_Elymaic }, { 1012, PT_SC, ucp_Elymaic }, { 1020, PT_BOOL, ucp_Emoji_Modifier }, @@ -1217,376 +1175,355 @@ const ucp_type_table PRIV(utt)[] = { { 1060, PT_BOOL, ucp_Emoji_Modifier_Base }, { 1078, PT_BOOL, ucp_Emoji_Presentation }, { 1096, PT_BOOL, ucp_Emoji_Presentation }, - { 1102, PT_SCX, ucp_Ethiopic }, - { 1107, PT_SCX, ucp_Ethiopic }, + { 1102, PT_SC, ucp_Ethiopic }, + { 1107, PT_SC, ucp_Ethiopic }, { 1116, PT_BOOL, ucp_Extender }, { 1120, PT_BOOL, ucp_Extended_Pictographic }, { 1141, PT_BOOL, ucp_Extender }, { 1150, PT_BOOL, ucp_Extended_Pictographic }, - { 1158, PT_SCX, ucp_Garay }, - { 1163, PT_SCX, ucp_Garay }, - { 1169, PT_SCX, ucp_Georgian }, - { 1174, PT_SCX, ucp_Georgian }, - { 1183, PT_SCX, ucp_Glagolitic }, - { 1188, PT_SCX, ucp_Glagolitic }, - { 1199, PT_SCX, ucp_Gunjala_Gondi }, - { 1204, PT_SCX, ucp_Masaram_Gondi }, - { 1209, PT_SCX, ucp_Gothic }, - { 1214, PT_SCX, ucp_Gothic }, - { 1221, PT_SCX, ucp_Grantha }, - { 1226, PT_SCX, ucp_Grantha }, - { 1234, PT_BOOL, ucp_Grapheme_Base }, - { 1247, PT_BOOL, ucp_Grapheme_Extend }, - { 1262, PT_BOOL, ucp_Grapheme_Link }, - { 1275, PT_BOOL, ucp_Grapheme_Base }, - { 1282, PT_SCX, ucp_Greek }, - { 1288, PT_SCX, ucp_Greek }, - { 1293, PT_BOOL, ucp_Grapheme_Extend }, - { 1299, PT_BOOL, ucp_Grapheme_Link }, - { 1306, PT_SCX, ucp_Gujarati }, - { 1315, PT_SCX, ucp_Gujarati }, - { 1320, PT_SCX, ucp_Gurung_Khema }, - { 1325, PT_SCX, ucp_Gunjala_Gondi }, - { 1338, PT_SCX, ucp_Gurmukhi }, - { 1347, PT_SCX, ucp_Gurmukhi }, - { 1352, PT_SCX, ucp_Gurung_Khema }, - { 1364, PT_SCX, ucp_Han }, - { 1368, PT_SCX, ucp_Hangul }, - { 1373, PT_SCX, ucp_Hangul }, - { 1380, PT_SCX, ucp_Han }, - { 1385, PT_SCX, ucp_Hanifi_Rohingya }, - { 1400, PT_SCX, ucp_Hanunoo }, - { 1405, PT_SCX, ucp_Hanunoo }, - { 1413, PT_SC, ucp_Hatran }, - { 1418, PT_SC, ucp_Hatran }, - { 1425, PT_SCX, ucp_Hebrew }, - { 1430, PT_SCX, ucp_Hebrew }, - { 1437, PT_BOOL, ucp_Hex_Digit }, - { 1441, PT_BOOL, ucp_Hex_Digit }, - { 1450, PT_SCX, ucp_Hiragana }, - { 1455, PT_SCX, ucp_Hiragana }, - { 1464, PT_SC, ucp_Anatolian_Hieroglyphs }, - { 1469, PT_SC, ucp_Pahawh_Hmong }, - { 1474, PT_SC, ucp_Nyiakeng_Puachue_Hmong }, - { 1479, PT_SCX, ucp_Old_Hungarian }, - { 1484, PT_BOOL, ucp_ID_Continue }, - { 1488, PT_BOOL, ucp_ID_Compat_Math_Continue }, - { 1509, PT_BOOL, ucp_ID_Compat_Math_Start }, - { 1527, PT_BOOL, ucp_ID_Continue }, - { 1538, PT_BOOL, ucp_Ideographic }, - { 1543, PT_BOOL, ucp_Ideographic }, - { 1555, PT_BOOL, ucp_ID_Start }, - { 1559, PT_BOOL, ucp_IDS_Binary_Operator }, - { 1564, PT_BOOL, ucp_IDS_Binary_Operator }, - { 1582, PT_BOOL, ucp_IDS_Trinary_Operator }, - { 1587, PT_BOOL, ucp_ID_Start }, - { 1595, PT_BOOL, ucp_IDS_Trinary_Operator }, - { 1614, PT_BOOL, ucp_IDS_Unary_Operator }, - { 1619, PT_BOOL, ucp_IDS_Unary_Operator }, - { 1636, PT_SC, ucp_Imperial_Aramaic }, - { 1652, PT_BOOL, ucp_InCB }, - { 1657, PT_SC, ucp_Inherited }, - { 1667, PT_SC, ucp_Inscriptional_Pahlavi }, - { 1688, PT_SC, ucp_Inscriptional_Parthian }, - { 1710, PT_SC, ucp_Old_Italic }, - { 1715, PT_SCX, ucp_Javanese }, - { 1720, PT_SCX, ucp_Javanese }, - { 1729, PT_BOOL, ucp_Join_Control }, - { 1735, PT_BOOL, ucp_Join_Control }, - { 1747, PT_SCX, ucp_Kaithi }, - { 1754, PT_SCX, ucp_Kayah_Li }, - { 1759, PT_SCX, ucp_Katakana }, - { 1764, PT_SCX, ucp_Kannada }, - { 1772, PT_SCX, ucp_Katakana }, - { 1781, PT_SC, ucp_Kawi }, - { 1786, PT_SCX, ucp_Kayah_Li }, - { 1794, PT_SC, ucp_Kharoshthi }, - { 1799, PT_SC, ucp_Kharoshthi }, - { 1810, PT_SC, ucp_Khitan_Small_Script }, - { 1828, PT_SC, ucp_Khmer }, - { 1834, PT_SC, ucp_Khmer }, - { 1839, PT_SCX, ucp_Khojki }, - { 1844, PT_SCX, ucp_Khojki }, - { 1851, PT_SCX, ucp_Khudawadi }, - { 1861, PT_SC, ucp_Kirat_Rai }, - { 1870, PT_SC, ucp_Khitan_Small_Script }, - { 1875, PT_SCX, ucp_Kannada }, - { 1880, PT_SC, ucp_Kirat_Rai }, - { 1885, PT_SCX, ucp_Kaithi }, - { 1890, PT_GC, ucp_L }, - { 1892, PT_LAMP, 0 }, - { 1895, PT_SC, ucp_Tai_Tham }, - { 1900, PT_SC, ucp_Lao }, - { 1904, PT_SC, ucp_Lao }, - { 1909, PT_SCX, ucp_Latin }, - { 1915, PT_SCX, ucp_Latin }, - { 1920, PT_LAMP, 0 }, - { 1923, PT_SC, ucp_Lepcha }, - { 1928, PT_SC, ucp_Lepcha }, - { 1935, PT_SCX, ucp_Limbu }, - { 1940, PT_SCX, ucp_Limbu }, - { 1946, PT_SCX, ucp_Linear_A }, - { 1951, PT_SCX, ucp_Linear_B }, - { 1956, PT_SCX, ucp_Linear_A }, - { 1964, PT_SCX, ucp_Linear_B }, - { 1972, PT_SCX, ucp_Lisu }, - { 1977, PT_PC, ucp_Ll }, - { 1980, PT_PC, ucp_Lm }, - { 1983, PT_PC, ucp_Lo }, - { 1986, PT_BOOL, ucp_Logical_Order_Exception }, - { 1990, PT_BOOL, ucp_Logical_Order_Exception }, - { 2012, PT_BOOL, ucp_Lowercase }, - { 2018, PT_BOOL, ucp_Lowercase }, - { 2028, PT_PC, ucp_Lt }, - { 2031, PT_PC, ucp_Lu }, - { 2034, PT_SCX, ucp_Lycian }, - { 2039, PT_SCX, ucp_Lycian }, - { 2046, PT_SCX, ucp_Lydian }, - { 2051, PT_SCX, ucp_Lydian }, - { 2058, PT_GC, ucp_M }, - { 2060, PT_SCX, ucp_Mahajani }, - { 2069, PT_SCX, ucp_Mahajani }, - { 2074, PT_SC, ucp_Makasar }, - { 2079, PT_SC, ucp_Makasar }, - { 2087, PT_SCX, ucp_Malayalam }, - { 2097, PT_SCX, ucp_Mandaic }, - { 2102, PT_SCX, ucp_Mandaic }, - { 2110, PT_SCX, ucp_Manichaean }, - { 2115, PT_SCX, ucp_Manichaean }, - { 2126, PT_SC, ucp_Marchen }, - { 2131, PT_SC, ucp_Marchen }, - { 2139, PT_SCX, ucp_Masaram_Gondi }, - { 2152, PT_BOOL, ucp_Math }, - { 2157, PT_PC, ucp_Mc }, - { 2160, PT_BOOL, ucp_Modifier_Combining_Mark }, - { 2164, PT_PC, ucp_Me }, - { 2167, PT_SC, ucp_Medefaidrin }, - { 2179, PT_SC, ucp_Medefaidrin }, - { 2184, PT_SC, ucp_Meetei_Mayek }, - { 2196, PT_SC, ucp_Mende_Kikakui }, - { 2201, PT_SC, ucp_Mende_Kikakui }, - { 2214, PT_SC, ucp_Meroitic_Cursive }, - { 2219, PT_SCX, ucp_Meroitic_Hieroglyphs }, - { 2224, PT_SC, ucp_Meroitic_Cursive }, - { 2240, PT_SCX, ucp_Meroitic_Hieroglyphs }, - { 2260, PT_SC, ucp_Miao }, - { 2265, PT_SCX, ucp_Malayalam }, - { 2270, PT_PC, ucp_Mn }, - { 2273, PT_SCX, ucp_Modi }, - { 2278, PT_BOOL, ucp_Modifier_Combining_Mark }, - { 2300, PT_SCX, ucp_Mongolian }, - { 2305, PT_SCX, ucp_Mongolian }, - { 2315, PT_SC, ucp_Mro }, - { 2319, PT_SC, ucp_Mro }, - { 2324, PT_SC, ucp_Meetei_Mayek }, - { 2329, PT_SCX, ucp_Multani }, - { 2334, PT_SCX, ucp_Multani }, - { 2342, PT_SCX, ucp_Myanmar }, - { 2350, PT_SCX, ucp_Myanmar }, - { 2355, PT_GC, ucp_N }, - { 2357, PT_SC, ucp_Nabataean }, - { 2367, PT_SC, ucp_Nag_Mundari }, - { 2372, PT_SC, ucp_Nag_Mundari }, - { 2383, PT_SCX, ucp_Nandinagari }, - { 2388, PT_SCX, ucp_Nandinagari }, - { 2400, PT_SC, ucp_Old_North_Arabian }, - { 2405, PT_SC, ucp_Nabataean }, - { 2410, PT_BOOL, ucp_Noncharacter_Code_Point }, - { 2416, PT_PC, ucp_Nd }, - { 2419, PT_SC, ucp_Newa }, - { 2424, PT_SC, ucp_New_Tai_Lue }, - { 2434, PT_SCX, ucp_Nko }, - { 2438, PT_SCX, ucp_Nko }, - { 2443, PT_PC, ucp_Nl }, - { 2446, PT_PC, ucp_No }, - { 2449, PT_BOOL, ucp_Noncharacter_Code_Point }, - { 2471, PT_SC, ucp_Nushu }, - { 2476, PT_SC, ucp_Nushu }, - { 2482, PT_SC, ucp_Nyiakeng_Puachue_Hmong }, - { 2503, PT_SC, ucp_Ogham }, - { 2508, PT_SC, ucp_Ogham }, - { 2514, PT_SC, ucp_Ol_Chiki }, - { 2522, PT_SC, ucp_Ol_Chiki }, - { 2527, PT_SCX, ucp_Old_Hungarian }, - { 2540, PT_SC, ucp_Old_Italic }, - { 2550, PT_SC, ucp_Old_North_Arabian }, - { 2566, PT_SCX, ucp_Old_Permic }, - { 2576, PT_SC, ucp_Old_Persian }, - { 2587, PT_SC, ucp_Old_Sogdian }, - { 2598, PT_SC, ucp_Old_South_Arabian }, - { 2614, PT_SCX, ucp_Old_Turkic }, - { 2624, PT_SCX, ucp_Old_Uyghur }, - { 2634, PT_SCX, ucp_Ol_Onal }, - { 2641, PT_SCX, ucp_Ol_Onal }, - { 2646, PT_SCX, ucp_Oriya }, - { 2652, PT_SCX, ucp_Old_Turkic }, - { 2657, PT_SCX, ucp_Oriya }, - { 2662, PT_SCX, ucp_Osage }, - { 2668, PT_SCX, ucp_Osage }, - { 2673, PT_SC, ucp_Osmanya }, - { 2678, PT_SC, ucp_Osmanya }, - { 2686, PT_SCX, ucp_Old_Uyghur }, - { 2691, PT_GC, ucp_P }, - { 2693, PT_SC, ucp_Pahawh_Hmong }, - { 2705, PT_SC, ucp_Palmyrene }, - { 2710, PT_SC, ucp_Palmyrene }, - { 2720, PT_BOOL, ucp_Pattern_Syntax }, - { 2727, PT_BOOL, ucp_Pattern_Syntax }, - { 2741, PT_BOOL, ucp_Pattern_White_Space }, - { 2759, PT_BOOL, ucp_Pattern_White_Space }, - { 2765, PT_SC, ucp_Pau_Cin_Hau }, - { 2770, PT_SC, ucp_Pau_Cin_Hau }, - { 2780, PT_PC, ucp_Pc }, - { 2783, PT_BOOL, ucp_Prepended_Concatenation_Mark }, - { 2787, PT_PC, ucp_Pd }, - { 2790, PT_PC, ucp_Pe }, - { 2793, PT_SCX, ucp_Old_Permic }, - { 2798, PT_PC, ucp_Pf }, - { 2801, PT_SCX, ucp_Phags_Pa }, - { 2806, PT_SCX, ucp_Phags_Pa }, - { 2814, PT_SC, ucp_Inscriptional_Pahlavi }, - { 2819, PT_SCX, ucp_Psalter_Pahlavi }, - { 2824, PT_SC, ucp_Phoenician }, - { 2829, PT_SC, ucp_Phoenician }, - { 2840, PT_PC, ucp_Pi }, - { 2843, PT_SC, ucp_Miao }, - { 2848, PT_PC, ucp_Po }, - { 2851, PT_BOOL, ucp_Prepended_Concatenation_Mark }, - { 2878, PT_SC, ucp_Inscriptional_Parthian }, - { 2883, PT_PC, ucp_Ps }, - { 2886, PT_SCX, ucp_Psalter_Pahlavi }, - { 2901, PT_SCX, ucp_Coptic }, - { 2906, PT_SC, ucp_Inherited }, - { 2911, PT_BOOL, ucp_Quotation_Mark }, - { 2917, PT_BOOL, ucp_Quotation_Mark }, - { 2931, PT_BOOL, ucp_Radical }, - { 2939, PT_BOOL, ucp_Regional_Indicator }, - { 2957, PT_SC, ucp_Rejang }, - { 2964, PT_BOOL, ucp_Regional_Indicator }, - { 2967, PT_SC, ucp_Rejang }, - { 2972, PT_SCX, ucp_Hanifi_Rohingya }, - { 2977, PT_SCX, ucp_Runic }, - { 2983, PT_SCX, ucp_Runic }, - { 2988, PT_GC, ucp_S }, - { 2990, PT_SCX, ucp_Samaritan }, - { 3000, PT_SCX, ucp_Samaritan }, - { 3005, PT_SC, ucp_Old_South_Arabian }, - { 3010, PT_SC, ucp_Saurashtra }, - { 3015, PT_SC, ucp_Saurashtra }, - { 3026, PT_PC, ucp_Sc }, - { 3029, PT_BOOL, ucp_Soft_Dotted }, - { 3032, PT_BOOL, ucp_Sentence_Terminal }, - { 3049, PT_SC, ucp_SignWriting }, - { 3054, PT_SCX, ucp_Sharada }, - { 3062, PT_SCX, ucp_Shavian }, - { 3070, PT_SCX, ucp_Shavian }, - { 3075, PT_SCX, ucp_Sharada }, - { 3080, PT_SC, ucp_Siddham }, - { 3085, PT_SC, ucp_Siddham }, - { 3093, PT_SC, ucp_SignWriting }, - { 3105, PT_SCX, ucp_Khudawadi }, - { 3110, PT_SCX, ucp_Sinhala }, - { 3115, PT_SCX, ucp_Sinhala }, - { 3123, PT_PC, ucp_Sk }, - { 3126, PT_PC, ucp_Sm }, - { 3129, PT_PC, ucp_So }, - { 3132, PT_BOOL, ucp_Soft_Dotted }, - { 3143, PT_SCX, ucp_Sogdian }, - { 3148, PT_SCX, ucp_Sogdian }, - { 3156, PT_SC, ucp_Old_Sogdian }, - { 3161, PT_SC, ucp_Sora_Sompeng }, - { 3166, PT_SC, ucp_Sora_Sompeng }, - { 3178, PT_SC, ucp_Soyombo }, - { 3183, PT_SC, ucp_Soyombo }, - { 3191, PT_BOOL, ucp_White_Space }, - { 3197, PT_BOOL, ucp_Sentence_Terminal }, - { 3203, PT_SC, ucp_Sundanese }, - { 3208, PT_SC, ucp_Sundanese }, - { 3218, PT_SCX, ucp_Sunuwar }, - { 3223, PT_SCX, ucp_Sunuwar }, - { 3231, PT_SCX, ucp_Syloti_Nagri }, - { 3236, PT_SCX, ucp_Syloti_Nagri }, - { 3248, PT_SCX, ucp_Syriac }, - { 3253, PT_SCX, ucp_Syriac }, - { 3260, PT_SCX, ucp_Tagalog }, - { 3268, PT_SCX, ucp_Tagbanwa }, - { 3273, PT_SCX, ucp_Tagbanwa }, - { 3282, PT_SCX, ucp_Tai_Le }, - { 3288, PT_SC, ucp_Tai_Tham }, - { 3296, PT_SC, ucp_Tai_Viet }, - { 3304, PT_SCX, ucp_Takri }, - { 3309, PT_SCX, ucp_Takri }, - { 3315, PT_SCX, ucp_Tai_Le }, - { 3320, PT_SC, ucp_New_Tai_Lue }, - { 3325, PT_SCX, ucp_Tamil }, - { 3331, PT_SCX, ucp_Tamil }, - { 3336, PT_SCX, ucp_Tangut }, - { 3341, PT_SC, ucp_Tangsa }, - { 3348, PT_SCX, ucp_Tangut }, - { 3355, PT_SC, ucp_Tai_Viet }, - { 3360, PT_SCX, ucp_Telugu }, - { 3365, PT_SCX, ucp_Telugu }, - { 3372, PT_BOOL, ucp_Terminal_Punctuation }, - { 3377, PT_BOOL, ucp_Terminal_Punctuation }, - { 3397, PT_SCX, ucp_Tifinagh }, - { 3402, PT_SCX, ucp_Tagalog }, - { 3407, PT_SCX, ucp_Thaana }, - { 3412, PT_SCX, ucp_Thaana }, - { 3419, PT_SCX, ucp_Thai }, - { 3424, PT_SCX, ucp_Tibetan }, - { 3432, PT_SCX, ucp_Tibetan }, - { 3437, PT_SCX, ucp_Tifinagh }, - { 3446, PT_SCX, ucp_Tirhuta }, - { 3451, PT_SCX, ucp_Tirhuta }, - { 3459, PT_SC, ucp_Tangsa }, - { 3464, PT_SCX, ucp_Todhri }, - { 3471, PT_SCX, ucp_Todhri }, - { 3476, PT_SCX, ucp_Toto }, - { 3481, PT_SCX, ucp_Tulu_Tigalari }, - { 3494, PT_SCX, ucp_Tulu_Tigalari }, - { 3499, PT_SC, ucp_Ugaritic }, - { 3504, PT_SC, ucp_Ugaritic }, - { 3513, PT_BOOL, ucp_Unified_Ideograph }, - { 3519, PT_BOOL, ucp_Unified_Ideograph }, - { 3536, PT_SC, ucp_Unknown }, - { 3544, PT_BOOL, ucp_Uppercase }, - { 3550, PT_BOOL, ucp_Uppercase }, - { 3560, PT_SC, ucp_Vai }, - { 3564, PT_SC, ucp_Vai }, - { 3569, PT_BOOL, ucp_Variation_Selector }, - { 3587, PT_SC, ucp_Vithkuqi }, - { 3592, PT_SC, ucp_Vithkuqi }, - { 3601, PT_BOOL, ucp_Variation_Selector }, - { 3604, PT_SC, ucp_Wancho }, - { 3611, PT_SC, ucp_Warang_Citi }, - { 3616, PT_SC, ucp_Warang_Citi }, - { 3627, PT_SC, ucp_Wancho }, - { 3632, PT_BOOL, ucp_White_Space }, - { 3643, PT_BOOL, ucp_White_Space }, - { 3650, PT_ALNUM, 0 }, - { 3654, PT_BOOL, ucp_XID_Continue }, - { 3659, PT_BOOL, ucp_XID_Continue }, - { 3671, PT_BOOL, ucp_XID_Start }, - { 3676, PT_BOOL, ucp_XID_Start }, - { 3685, PT_SC, ucp_Old_Persian }, - { 3690, PT_PXSPACE, 0 }, - { 3694, PT_SPACE, 0 }, - { 3698, PT_SC, ucp_Cuneiform }, - { 3703, PT_UCNC, 0 }, - { 3707, PT_WORD, 0 }, - { 3711, PT_SCX, ucp_Yezidi }, - { 3716, PT_SCX, ucp_Yezidi }, - { 3723, PT_SCX, ucp_Yi }, - { 3726, PT_SCX, ucp_Yi }, - { 3731, PT_GC, ucp_Z }, - { 3733, PT_SC, ucp_Zanabazar_Square }, - { 3749, PT_SC, ucp_Zanabazar_Square }, - { 3754, PT_SC, ucp_Inherited }, - { 3759, PT_PC, ucp_Zl }, - { 3762, PT_PC, ucp_Zp }, - { 3765, PT_PC, ucp_Zs }, - { 3768, PT_SC, ucp_Common }, - { 3773, PT_SC, ucp_Unknown } + { 1158, PT_SCX, ucp_Georgian }, + { 1163, PT_SCX, ucp_Georgian }, + { 1172, PT_SCX, ucp_Glagolitic }, + { 1177, PT_SCX, ucp_Glagolitic }, + { 1188, PT_SCX, ucp_Gunjala_Gondi }, + { 1193, PT_SCX, ucp_Masaram_Gondi }, + { 1198, PT_SC, ucp_Gothic }, + { 1203, PT_SC, ucp_Gothic }, + { 1210, PT_SCX, ucp_Grantha }, + { 1215, PT_SCX, ucp_Grantha }, + { 1223, PT_BOOL, ucp_Grapheme_Base }, + { 1236, PT_BOOL, ucp_Grapheme_Extend }, + { 1251, PT_BOOL, ucp_Grapheme_Link }, + { 1264, PT_BOOL, ucp_Grapheme_Base }, + { 1271, PT_SCX, ucp_Greek }, + { 1277, PT_SCX, ucp_Greek }, + { 1282, PT_BOOL, ucp_Grapheme_Extend }, + { 1288, PT_BOOL, ucp_Grapheme_Link }, + { 1295, PT_SCX, ucp_Gujarati }, + { 1304, PT_SCX, ucp_Gujarati }, + { 1309, PT_SCX, ucp_Gunjala_Gondi }, + { 1322, PT_SCX, ucp_Gurmukhi }, + { 1331, PT_SCX, ucp_Gurmukhi }, + { 1336, PT_SCX, ucp_Han }, + { 1340, PT_SCX, ucp_Hangul }, + { 1345, PT_SCX, ucp_Hangul }, + { 1352, PT_SCX, ucp_Han }, + { 1357, PT_SCX, ucp_Hanifi_Rohingya }, + { 1372, PT_SCX, ucp_Hanunoo }, + { 1377, PT_SCX, ucp_Hanunoo }, + { 1385, PT_SC, ucp_Hatran }, + { 1390, PT_SC, ucp_Hatran }, + { 1397, PT_SC, ucp_Hebrew }, + { 1402, PT_SC, ucp_Hebrew }, + { 1409, PT_BOOL, ucp_Hex_Digit }, + { 1413, PT_BOOL, ucp_Hex_Digit }, + { 1422, PT_SCX, ucp_Hiragana }, + { 1427, PT_SCX, ucp_Hiragana }, + { 1436, PT_SC, ucp_Anatolian_Hieroglyphs }, + { 1441, PT_SC, ucp_Pahawh_Hmong }, + { 1446, PT_SC, ucp_Nyiakeng_Puachue_Hmong }, + { 1451, PT_SC, ucp_Old_Hungarian }, + { 1456, PT_BOOL, ucp_ID_Continue }, + { 1460, PT_BOOL, ucp_ID_Continue }, + { 1471, PT_BOOL, ucp_Ideographic }, + { 1476, PT_BOOL, ucp_Ideographic }, + { 1488, PT_BOOL, ucp_ID_Start }, + { 1492, PT_BOOL, ucp_IDS_Binary_Operator }, + { 1497, PT_BOOL, ucp_IDS_Binary_Operator }, + { 1515, PT_BOOL, ucp_IDS_Trinary_Operator }, + { 1520, PT_BOOL, ucp_ID_Start }, + { 1528, PT_BOOL, ucp_IDS_Trinary_Operator }, + { 1547, PT_SC, ucp_Imperial_Aramaic }, + { 1563, PT_SC, ucp_Inherited }, + { 1573, PT_SC, ucp_Inscriptional_Pahlavi }, + { 1594, PT_SC, ucp_Inscriptional_Parthian }, + { 1616, PT_SC, ucp_Old_Italic }, + { 1621, PT_SCX, ucp_Javanese }, + { 1626, PT_SCX, ucp_Javanese }, + { 1635, PT_BOOL, ucp_Join_Control }, + { 1641, PT_BOOL, ucp_Join_Control }, + { 1653, PT_SCX, ucp_Kaithi }, + { 1660, PT_SCX, ucp_Kayah_Li }, + { 1665, PT_SCX, ucp_Katakana }, + { 1670, PT_SCX, ucp_Kannada }, + { 1678, PT_SCX, ucp_Katakana }, + { 1687, PT_SC, ucp_Kawi }, + { 1692, PT_SCX, ucp_Kayah_Li }, + { 1700, PT_SC, ucp_Kharoshthi }, + { 1705, PT_SC, ucp_Kharoshthi }, + { 1716, PT_SC, ucp_Khitan_Small_Script }, + { 1734, PT_SC, ucp_Khmer }, + { 1740, PT_SC, ucp_Khmer }, + { 1745, PT_SCX, ucp_Khojki }, + { 1750, PT_SCX, ucp_Khojki }, + { 1757, PT_SCX, ucp_Khudawadi }, + { 1767, PT_SC, ucp_Khitan_Small_Script }, + { 1772, PT_SCX, ucp_Kannada }, + { 1777, PT_SCX, ucp_Kaithi }, + { 1782, PT_GC, ucp_L }, + { 1784, PT_LAMP, 0 }, + { 1787, PT_SC, ucp_Tai_Tham }, + { 1792, PT_SC, ucp_Lao }, + { 1796, PT_SC, ucp_Lao }, + { 1801, PT_SCX, ucp_Latin }, + { 1807, PT_SCX, ucp_Latin }, + { 1812, PT_LAMP, 0 }, + { 1815, PT_SC, ucp_Lepcha }, + { 1820, PT_SC, ucp_Lepcha }, + { 1827, PT_SCX, ucp_Limbu }, + { 1832, PT_SCX, ucp_Limbu }, + { 1838, PT_SCX, ucp_Linear_A }, + { 1843, PT_SCX, ucp_Linear_B }, + { 1848, PT_SCX, ucp_Linear_A }, + { 1856, PT_SCX, ucp_Linear_B }, + { 1864, PT_SC, ucp_Lisu }, + { 1869, PT_PC, ucp_Ll }, + { 1872, PT_PC, ucp_Lm }, + { 1875, PT_PC, ucp_Lo }, + { 1878, PT_BOOL, ucp_Logical_Order_Exception }, + { 1882, PT_BOOL, ucp_Logical_Order_Exception }, + { 1904, PT_BOOL, ucp_Lowercase }, + { 1910, PT_BOOL, ucp_Lowercase }, + { 1920, PT_PC, ucp_Lt }, + { 1923, PT_PC, ucp_Lu }, + { 1926, PT_SC, ucp_Lycian }, + { 1931, PT_SC, ucp_Lycian }, + { 1938, PT_SC, ucp_Lydian }, + { 1943, PT_SC, ucp_Lydian }, + { 1950, PT_GC, ucp_M }, + { 1952, PT_SCX, ucp_Mahajani }, + { 1961, PT_SCX, ucp_Mahajani }, + { 1966, PT_SC, ucp_Makasar }, + { 1971, PT_SC, ucp_Makasar }, + { 1979, PT_SCX, ucp_Malayalam }, + { 1989, PT_SCX, ucp_Mandaic }, + { 1994, PT_SCX, ucp_Mandaic }, + { 2002, PT_SCX, ucp_Manichaean }, + { 2007, PT_SCX, ucp_Manichaean }, + { 2018, PT_SC, ucp_Marchen }, + { 2023, PT_SC, ucp_Marchen }, + { 2031, PT_SCX, ucp_Masaram_Gondi }, + { 2044, PT_BOOL, ucp_Math }, + { 2049, PT_PC, ucp_Mc }, + { 2052, PT_PC, ucp_Me }, + { 2055, PT_SC, ucp_Medefaidrin }, + { 2067, PT_SC, ucp_Medefaidrin }, + { 2072, PT_SC, ucp_Meetei_Mayek }, + { 2084, PT_SC, ucp_Mende_Kikakui }, + { 2089, PT_SC, ucp_Mende_Kikakui }, + { 2102, PT_SC, ucp_Meroitic_Cursive }, + { 2107, PT_SC, ucp_Meroitic_Hieroglyphs }, + { 2112, PT_SC, ucp_Meroitic_Cursive }, + { 2128, PT_SC, ucp_Meroitic_Hieroglyphs }, + { 2148, PT_SC, ucp_Miao }, + { 2153, PT_SCX, ucp_Malayalam }, + { 2158, PT_PC, ucp_Mn }, + { 2161, PT_SCX, ucp_Modi }, + { 2166, PT_SCX, ucp_Mongolian }, + { 2171, PT_SCX, ucp_Mongolian }, + { 2181, PT_SC, ucp_Mro }, + { 2185, PT_SC, ucp_Mro }, + { 2190, PT_SC, ucp_Meetei_Mayek }, + { 2195, PT_SCX, ucp_Multani }, + { 2200, PT_SCX, ucp_Multani }, + { 2208, PT_SCX, ucp_Myanmar }, + { 2216, PT_SCX, ucp_Myanmar }, + { 2221, PT_GC, ucp_N }, + { 2223, PT_SC, ucp_Nabataean }, + { 2233, PT_SC, ucp_Nag_Mundari }, + { 2238, PT_SC, ucp_Nag_Mundari }, + { 2249, PT_SCX, ucp_Nandinagari }, + { 2254, PT_SCX, ucp_Nandinagari }, + { 2266, PT_SC, ucp_Old_North_Arabian }, + { 2271, PT_SC, ucp_Nabataean }, + { 2276, PT_BOOL, ucp_Noncharacter_Code_Point }, + { 2282, PT_PC, ucp_Nd }, + { 2285, PT_SC, ucp_Newa }, + { 2290, PT_SC, ucp_New_Tai_Lue }, + { 2300, PT_SCX, ucp_Nko }, + { 2304, PT_SCX, ucp_Nko }, + { 2309, PT_PC, ucp_Nl }, + { 2312, PT_PC, ucp_No }, + { 2315, PT_BOOL, ucp_Noncharacter_Code_Point }, + { 2337, PT_SC, ucp_Nushu }, + { 2342, PT_SC, ucp_Nushu }, + { 2348, PT_SC, ucp_Nyiakeng_Puachue_Hmong }, + { 2369, PT_SC, ucp_Ogham }, + { 2374, PT_SC, ucp_Ogham }, + { 2380, PT_SC, ucp_Ol_Chiki }, + { 2388, PT_SC, ucp_Ol_Chiki }, + { 2393, PT_SC, ucp_Old_Hungarian }, + { 2406, PT_SC, ucp_Old_Italic }, + { 2416, PT_SC, ucp_Old_North_Arabian }, + { 2432, PT_SCX, ucp_Old_Permic }, + { 2442, PT_SC, ucp_Old_Persian }, + { 2453, PT_SC, ucp_Old_Sogdian }, + { 2464, PT_SC, ucp_Old_South_Arabian }, + { 2480, PT_SC, ucp_Old_Turkic }, + { 2490, PT_SCX, ucp_Old_Uyghur }, + { 2500, PT_SCX, ucp_Oriya }, + { 2506, PT_SC, ucp_Old_Turkic }, + { 2511, PT_SCX, ucp_Oriya }, + { 2516, PT_SC, ucp_Osage }, + { 2522, PT_SC, ucp_Osage }, + { 2527, PT_SC, ucp_Osmanya }, + { 2532, PT_SC, ucp_Osmanya }, + { 2540, PT_SCX, ucp_Old_Uyghur }, + { 2545, PT_GC, ucp_P }, + { 2547, PT_SC, ucp_Pahawh_Hmong }, + { 2559, PT_SC, ucp_Palmyrene }, + { 2564, PT_SC, ucp_Palmyrene }, + { 2574, PT_BOOL, ucp_Pattern_Syntax }, + { 2581, PT_BOOL, ucp_Pattern_Syntax }, + { 2595, PT_BOOL, ucp_Pattern_White_Space }, + { 2613, PT_BOOL, ucp_Pattern_White_Space }, + { 2619, PT_SC, ucp_Pau_Cin_Hau }, + { 2624, PT_SC, ucp_Pau_Cin_Hau }, + { 2634, PT_PC, ucp_Pc }, + { 2637, PT_BOOL, ucp_Prepended_Concatenation_Mark }, + { 2641, PT_PC, ucp_Pd }, + { 2644, PT_PC, ucp_Pe }, + { 2647, PT_SCX, ucp_Old_Permic }, + { 2652, PT_PC, ucp_Pf }, + { 2655, PT_SCX, ucp_Phags_Pa }, + { 2660, PT_SCX, ucp_Phags_Pa }, + { 2668, PT_SC, ucp_Inscriptional_Pahlavi }, + { 2673, PT_SCX, ucp_Psalter_Pahlavi }, + { 2678, PT_SC, ucp_Phoenician }, + { 2683, PT_SC, ucp_Phoenician }, + { 2694, PT_PC, ucp_Pi }, + { 2697, PT_SC, ucp_Miao }, + { 2702, PT_PC, ucp_Po }, + { 2705, PT_BOOL, ucp_Prepended_Concatenation_Mark }, + { 2732, PT_SC, ucp_Inscriptional_Parthian }, + { 2737, PT_PC, ucp_Ps }, + { 2740, PT_SCX, ucp_Psalter_Pahlavi }, + { 2755, PT_SCX, ucp_Coptic }, + { 2760, PT_SC, ucp_Inherited }, + { 2765, PT_BOOL, ucp_Quotation_Mark }, + { 2771, PT_BOOL, ucp_Quotation_Mark }, + { 2785, PT_BOOL, ucp_Radical }, + { 2793, PT_BOOL, ucp_Regional_Indicator }, + { 2811, PT_SC, ucp_Rejang }, + { 2818, PT_BOOL, ucp_Regional_Indicator }, + { 2821, PT_SC, ucp_Rejang }, + { 2826, PT_SCX, ucp_Hanifi_Rohingya }, + { 2831, PT_SC, ucp_Runic }, + { 2837, PT_SC, ucp_Runic }, + { 2842, PT_GC, ucp_S }, + { 2844, PT_SC, ucp_Samaritan }, + { 2854, PT_SC, ucp_Samaritan }, + { 2859, PT_SC, ucp_Old_South_Arabian }, + { 2864, PT_SC, ucp_Saurashtra }, + { 2869, PT_SC, ucp_Saurashtra }, + { 2880, PT_PC, ucp_Sc }, + { 2883, PT_BOOL, ucp_Soft_Dotted }, + { 2886, PT_BOOL, ucp_Sentence_Terminal }, + { 2903, PT_SC, ucp_SignWriting }, + { 2908, PT_SCX, ucp_Sharada }, + { 2916, PT_SC, ucp_Shavian }, + { 2924, PT_SC, ucp_Shavian }, + { 2929, PT_SCX, ucp_Sharada }, + { 2934, PT_SC, ucp_Siddham }, + { 2939, PT_SC, ucp_Siddham }, + { 2947, PT_SC, ucp_SignWriting }, + { 2959, PT_SCX, ucp_Khudawadi }, + { 2964, PT_SCX, ucp_Sinhala }, + { 2969, PT_SCX, ucp_Sinhala }, + { 2977, PT_PC, ucp_Sk }, + { 2980, PT_PC, ucp_Sm }, + { 2983, PT_PC, ucp_So }, + { 2986, PT_BOOL, ucp_Soft_Dotted }, + { 2997, PT_SCX, ucp_Sogdian }, + { 3002, PT_SCX, ucp_Sogdian }, + { 3010, PT_SC, ucp_Old_Sogdian }, + { 3015, PT_SC, ucp_Sora_Sompeng }, + { 3020, PT_SC, ucp_Sora_Sompeng }, + { 3032, PT_SC, ucp_Soyombo }, + { 3037, PT_SC, ucp_Soyombo }, + { 3045, PT_BOOL, ucp_White_Space }, + { 3051, PT_BOOL, ucp_Sentence_Terminal }, + { 3057, PT_SC, ucp_Sundanese }, + { 3062, PT_SC, ucp_Sundanese }, + { 3072, PT_SCX, ucp_Syloti_Nagri }, + { 3077, PT_SCX, ucp_Syloti_Nagri }, + { 3089, PT_SCX, ucp_Syriac }, + { 3094, PT_SCX, ucp_Syriac }, + { 3101, PT_SCX, ucp_Tagalog }, + { 3109, PT_SCX, ucp_Tagbanwa }, + { 3114, PT_SCX, ucp_Tagbanwa }, + { 3123, PT_SCX, ucp_Tai_Le }, + { 3129, PT_SC, ucp_Tai_Tham }, + { 3137, PT_SC, ucp_Tai_Viet }, + { 3145, PT_SCX, ucp_Takri }, + { 3150, PT_SCX, ucp_Takri }, + { 3156, PT_SCX, ucp_Tai_Le }, + { 3161, PT_SC, ucp_New_Tai_Lue }, + { 3166, PT_SCX, ucp_Tamil }, + { 3172, PT_SCX, ucp_Tamil }, + { 3177, PT_SC, ucp_Tangut }, + { 3182, PT_SC, ucp_Tangsa }, + { 3189, PT_SC, ucp_Tangut }, + { 3196, PT_SC, ucp_Tai_Viet }, + { 3201, PT_SCX, ucp_Telugu }, + { 3206, PT_SCX, ucp_Telugu }, + { 3213, PT_BOOL, ucp_Terminal_Punctuation }, + { 3218, PT_BOOL, ucp_Terminal_Punctuation }, + { 3238, PT_SC, ucp_Tifinagh }, + { 3243, PT_SCX, ucp_Tagalog }, + { 3248, PT_SCX, ucp_Thaana }, + { 3253, PT_SCX, ucp_Thaana }, + { 3260, PT_SC, ucp_Thai }, + { 3265, PT_SC, ucp_Tibetan }, + { 3273, PT_SC, ucp_Tibetan }, + { 3278, PT_SC, ucp_Tifinagh }, + { 3287, PT_SCX, ucp_Tirhuta }, + { 3292, PT_SCX, ucp_Tirhuta }, + { 3300, PT_SC, ucp_Tangsa }, + { 3305, PT_SC, ucp_Toto }, + { 3310, PT_SC, ucp_Ugaritic }, + { 3315, PT_SC, ucp_Ugaritic }, + { 3324, PT_BOOL, ucp_Unified_Ideograph }, + { 3330, PT_BOOL, ucp_Unified_Ideograph }, + { 3347, PT_SC, ucp_Unknown }, + { 3355, PT_BOOL, ucp_Uppercase }, + { 3361, PT_BOOL, ucp_Uppercase }, + { 3371, PT_SC, ucp_Vai }, + { 3375, PT_SC, ucp_Vai }, + { 3380, PT_BOOL, ucp_Variation_Selector }, + { 3398, PT_SC, ucp_Vithkuqi }, + { 3403, PT_SC, ucp_Vithkuqi }, + { 3412, PT_BOOL, ucp_Variation_Selector }, + { 3415, PT_SC, ucp_Wancho }, + { 3422, PT_SC, ucp_Warang_Citi }, + { 3427, PT_SC, ucp_Warang_Citi }, + { 3438, PT_SC, ucp_Wancho }, + { 3443, PT_BOOL, ucp_White_Space }, + { 3454, PT_BOOL, ucp_White_Space }, + { 3461, PT_ALNUM, 0 }, + { 3465, PT_BOOL, ucp_XID_Continue }, + { 3470, PT_BOOL, ucp_XID_Continue }, + { 3482, PT_BOOL, ucp_XID_Start }, + { 3487, PT_BOOL, ucp_XID_Start }, + { 3496, PT_SC, ucp_Old_Persian }, + { 3501, PT_PXSPACE, 0 }, + { 3505, PT_SPACE, 0 }, + { 3509, PT_SC, ucp_Cuneiform }, + { 3514, PT_UCNC, 0 }, + { 3518, PT_WORD, 0 }, + { 3522, PT_SCX, ucp_Yezidi }, + { 3527, PT_SCX, ucp_Yezidi }, + { 3534, PT_SCX, ucp_Yi }, + { 3537, PT_SCX, ucp_Yi }, + { 3542, PT_GC, ucp_Z }, + { 3544, PT_SC, ucp_Zanabazar_Square }, + { 3560, PT_SC, ucp_Zanabazar_Square }, + { 3565, PT_SC, ucp_Inherited }, + { 3570, PT_PC, ucp_Zl }, + { 3573, PT_PC, ucp_Zp }, + { 3576, PT_PC, ucp_Zs }, + { 3579, PT_SC, ucp_Common }, + { 3584, PT_SC, ucp_Unknown } }; const size_t PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table); diff --git a/ext/pcre/pcre2lib/pcre2_util.h b/ext/pcre/pcre2lib/pcre2_util.h deleted file mode 100644 index ea8635552a15e..0000000000000 --- a/ext/pcre/pcre2lib/pcre2_util.h +++ /dev/null @@ -1,132 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE2 is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2024 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * 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. - - * Neither the name of the University of Cambridge 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 OWNER 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 PCRE2_UTIL_H_IDEMPOTENT_GUARD -#define PCRE2_UTIL_H_IDEMPOTENT_GUARD - -/* Assertion macros */ - -#ifdef PCRE2_DEBUG - -#if defined(HAVE_ASSERT_H) && !defined(NDEBUG) -#include -#endif - -/* PCRE2_ASSERT(x) can be used to inject an assert() for conditions -that the code below doesn't support. It is a NOP for non debug builds -but in debug builds will print information about the location of the -code where it triggered and crash. - -It is meant to work like assert(), and therefore the expression used -should indicate what the expected state is, and shouldn't have any -side-effects. */ - -#if defined(HAVE_ASSERT_H) && !defined(NDEBUG) -#define PCRE2_ASSERT(x) assert(x) -#else -#define PCRE2_ASSERT(x) do \ -{ \ - if (!(x)) \ - { \ - fprintf(stderr, "Assertion failed at " __FILE__ ":%d\n", __LINE__); \ - abort(); \ - } \ -} while(0) -#endif - -/* PCRE2_UNREACHABLE() can be used to mark locations on the code that -shouldn't be reached. In non debug builds is defined as a hint for -the compiler to eliminate any code after it, so it is useful also for -performance reasons, but should be used with care because if it is -ever reached will trigger Undefined Behaviour and if you are lucky a -crash. In debug builds it will report the location where it was triggered -and crash. One important point to consider when using this macro, is -that it is only implemented for a few compilers, and therefore can't -be relied on to always be active either, so if it is followed by some -code it is important to make sure that the whole thing is safe to -use even if the macro is not there (ex: make sure there is a `break` -after it if used at the end of a `case`) and to test your code also -with a configuration where the macro will be a NOP. */ - -#if defined(HAVE_ASSERT_H) && !defined(NDEBUG) -#define PCRE2_UNREACHABLE() \ -assert(((void)"Execution reached unexpected point", 0)) -#else -#define PCRE2_UNREACHABLE() do \ -{ \ -fprintf(stderr, "Execution reached unexpected point at " __FILE__ \ - ":%d\n", __LINE__); \ -abort(); \ -} while(0) -#endif - -/* PCRE2_DEBUG_UNREACHABLE() is a debug only version of the previous -macro. It is meant to be used in places where the code is handling -an error situation in code that shouldn't be reached, but that has -some sort of fallback code to normally handle the error. When in -doubt you should use this instead of the previous macro. Like in -the previous case, it is a good idea to document as much as possible -the reason and the actions that should be taken if it ever triggers. */ - -#define PCRE2_DEBUG_UNREACHABLE() PCRE2_UNREACHABLE() - -#endif /* PCRE2_DEBUG */ - -#ifndef PCRE2_DEBUG_UNREACHABLE -#define PCRE2_DEBUG_UNREACHABLE() do {} while(0) -#endif - -#ifndef PCRE2_UNREACHABLE -#ifdef HAVE_BUILTIN_UNREACHABLE -#define PCRE2_UNREACHABLE() __builtin_unreachable() -#elif defined(HAVE_BUILTIN_ASSUME) -#define PCRE2_UNREACHABLE() __assume(0) -#else -#define PCRE2_UNREACHABLE() do {} while(0) -#endif -#endif /* !PCRE2_UNREACHABLE */ - -#ifndef PCRE2_ASSERT -#define PCRE2_ASSERT(x) do {} while(0) -#endif - -#endif /* PCRE2_UTIL_H_IDEMPOTENT_GUARD */ - -/* End of pcre2_util.h */ diff --git a/ext/pcre/pcre2lib/pcre2_xclass.c b/ext/pcre/pcre2lib/pcre2_xclass.c index 25de7cbf38b60..5df25d2c8dfa0 100644 --- a/ext/pcre/pcre2lib/pcre2_xclass.c +++ b/ext/pcre/pcre2lib/pcre2_xclass.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2024 University of Cambridge + New API code Copyright (c) 2016-2023 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -38,9 +38,9 @@ POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------- */ -/* This module contains two internal functions that are used to match -OP_XCLASS and OP_ECLASS. It is used by pcre2_auto_possessify() and by both -pcre2_match() and pcre2_dfa_match(). */ +/* This module contains an internal function that is used to match an extended +class. It is used by pcre2_auto_possessify() and by both pcre2_match() and +pcre2_def_match(). */ #ifdef HAVE_CONFIG_H @@ -66,75 +66,114 @@ Returns: TRUE if character matches, else FALSE */ BOOL -PRIV(xclass)(uint32_t c, PCRE2_SPTR data, const uint8_t *char_lists_end, BOOL utf) +PRIV(xclass)(uint32_t c, PCRE2_SPTR data, BOOL utf) { -/* Update PRIV(update_classbits) when this function is changed. */ PCRE2_UCHAR t; -BOOL not_negated = (*data & XCL_NOT) == 0; -uint32_t type, max_index, min_index, value; -const uint8_t *next_char; +BOOL negated = (*data & XCL_NOT) != 0; #if PCRE2_CODE_UNIT_WIDTH == 8 /* In 8 bit mode, this must always be TRUE. Help the compiler to know that. */ utf = TRUE; #endif -/* Code points < 256 are matched against a bitmap, if one is present. */ +/* Code points < 256 are matched against a bitmap, if one is present. If not, +we still carry on, because there may be ranges that start below 256 in the +additional data. */ -if ((*data++ & XCL_MAP) != 0) +if (c < 256) { - if (c < 256) - return (((const uint8_t *)data)[c/8] & (1u << (c&7))) != 0; - /* Skip bitmap. */ - data += 32 / sizeof(PCRE2_UCHAR); + if ((*data & XCL_HASPROP) == 0) + { + if ((*data & XCL_MAP) == 0) return negated; + return (((uint8_t *)(data + 1))[c/8] & (1u << (c&7))) != 0; + } + if ((*data & XCL_MAP) != 0 && + (((uint8_t *)(data + 1))[c/8] & (1u << (c&7))) != 0) + return !negated; /* char found */ } -/* Match against the list of Unicode properties. We won't ever +/* First skip the bit map if present. Then match against the list of Unicode +properties or large chars or ranges that end with a large char. We won't ever encounter XCL_PROP or XCL_NOTPROP when UTF support is not compiled. */ -#ifdef SUPPORT_UNICODE -if (*data == XCL_PROP || *data == XCL_NOTPROP) + +if ((*data++ & XCL_MAP) != 0) data += 32 / sizeof(PCRE2_UCHAR); + +while ((t = *data++) != XCL_END) { - /* The UCD record is the same for all properties. */ - const ucd_record *prop = GET_UCD(c); + uint32_t x, y; + if (t == XCL_SINGLE) + { +#ifdef SUPPORT_UNICODE + if (utf) + { + GETCHARINC(x, data); /* macro generates multiple statements */ + } + else +#endif + x = *data++; + if (c == x) return !negated; + } + else if (t == XCL_RANGE) + { +#ifdef SUPPORT_UNICODE + if (utf) + { + GETCHARINC(x, data); /* macro generates multiple statements */ + GETCHARINC(y, data); /* macro generates multiple statements */ + } + else +#endif + { + x = *data++; + y = *data++; + } + if (c >= x && c <= y) return !negated; + } - do +#ifdef SUPPORT_UNICODE + else /* XCL_PROP & XCL_NOTPROP */ { int chartype; - BOOL isprop = (*data++) == XCL_PROP; + const ucd_record *prop = GET_UCD(c); + BOOL isprop = t == XCL_PROP; BOOL ok; switch(*data) { + case PT_ANY: + if (isprop) return !negated; + break; + case PT_LAMP: chartype = prop->chartype; if ((chartype == ucp_Lu || chartype == ucp_Ll || - chartype == ucp_Lt) == isprop) return not_negated; + chartype == ucp_Lt) == isprop) return !negated; break; case PT_GC: if ((data[1] == PRIV(ucp_gentype)[prop->chartype]) == isprop) - return not_negated; + return !negated; break; case PT_PC: - if ((data[1] == prop->chartype) == isprop) return not_negated; + if ((data[1] == prop->chartype) == isprop) return !negated; break; case PT_SC: - if ((data[1] == prop->script) == isprop) return not_negated; + if ((data[1] == prop->script) == isprop) return !negated; break; case PT_SCX: ok = (data[1] == prop->script || MAPBIT(PRIV(ucd_script_sets) + UCD_SCRIPTX_PROP(prop), data[1]) != 0); - if (ok == isprop) return not_negated; + if (ok == isprop) return !negated; break; case PT_ALNUM: chartype = prop->chartype; if ((PRIV(ucp_gentype)[chartype] == ucp_L || PRIV(ucp_gentype)[chartype] == ucp_N) == isprop) - return not_negated; + return !negated; break; /* Perl space used to exclude VT, but from Perl 5.18 it is included, @@ -147,12 +186,12 @@ if (*data == XCL_PROP || *data == XCL_NOTPROP) { HSPACE_CASES: VSPACE_CASES: - if (isprop) return not_negated; + if (isprop) return !negated; break; default: if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == isprop) - return not_negated; + return !negated; break; } break; @@ -162,7 +201,7 @@ if (*data == XCL_PROP || *data == XCL_NOTPROP) if ((PRIV(ucp_gentype)[chartype] == ucp_L || PRIV(ucp_gentype)[chartype] == ucp_N || chartype == ucp_Mn || chartype == ucp_Pc) == isprop) - return not_negated; + return !negated; break; case PT_UCNC: @@ -170,24 +209,24 @@ if (*data == XCL_PROP || *data == XCL_NOTPROP) { if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT || c == CHAR_GRAVE_ACCENT) == isprop) - return not_negated; + return !negated; } else { if ((c < 0xd800 || c > 0xdfff) == isprop) - return not_negated; + return !negated; } break; case PT_BIDICL: if ((UCD_BIDICLASS_PROP(prop) == data[1]) == isprop) - return not_negated; + return !negated; break; case PT_BOOL: ok = MAPBIT(PRIV(ucd_boolprop_sets) + UCD_BPROPS_PROP(prop), data[1]) != 0; - if (ok == isprop) return not_negated; + if (ok == isprop) return !negated; break; /* The following three properties can occur only in an XCLASS, as there @@ -209,7 +248,7 @@ if (*data == XCL_PROP || *data == XCL_NOTPROP) (chartype == ucp_Cf && c != 0x061c && c != 0x180e && (c < 0x2066 || c > 0x2069)) )) == isprop) - return not_negated; + return !negated; break; /* Printable character: same as graphic, with the addition of Zs, i.e. @@ -223,7 +262,7 @@ if (*data == XCL_PROP || *data == XCL_NOTPROP) (chartype == ucp_Cf && c != 0x061c && (c < 0x2066 || c > 0x2069)) )) == isprop) - return not_negated; + return !negated; break; /* Punctuation: all Unicode punctuation, plus ASCII characters that @@ -234,7 +273,7 @@ if (*data == XCL_PROP || *data == XCL_NOTPROP) chartype = prop->chartype; if ((PRIV(ucp_gentype)[chartype] == ucp_P || (c < 128 && PRIV(ucp_gentype)[chartype] == ucp_S)) == isprop) - return not_negated; + return !negated; break; /* Perl has two sets of hex digits */ @@ -246,300 +285,24 @@ if (*data == XCL_PROP || *data == XCL_NOTPROP) (c >= 0xff10 && c <= 0xff19) || /* Fullwidth digits */ (c >= 0xff21 && c <= 0xff26) || /* Fullwidth letters */ (c >= 0xff41 && c <= 0xff46)) == isprop) - return not_negated; + return !negated; break; /* This should never occur, but compilers may mutter if there is no default. */ default: - PCRE2_DEBUG_UNREACHABLE(); return FALSE; } data += 2; } - while (*data == XCL_PROP || *data == XCL_NOTPROP); - } #else (void)utf; /* Avoid compiler warning */ #endif /* SUPPORT_UNICODE */ - -/* Match against large chars or ranges that end with a large char. */ -if (*data < XCL_LIST) - { - while ((t = *data++) != XCL_END) - { - uint32_t x, y; - -#ifdef SUPPORT_UNICODE - if (utf) - { - GETCHARINC(x, data); /* macro generates multiple statements */ - } - else -#endif - x = *data++; - - if (t == XCL_SINGLE) - { - /* Since character ranges follow the properties, and they are - sorted, early return is possible for all characters <= x. */ - if (c <= x) return (c == x) ? not_negated : !not_negated; - continue; - } - - PCRE2_ASSERT(t == XCL_RANGE); -#ifdef SUPPORT_UNICODE - if (utf) - { - GETCHARINC(y, data); /* macro generates multiple statements */ - } - else -#endif - y = *data++; - - /* Since character ranges follow the properties, and they are - sorted, early return is possible for all characters <= y. */ - if (c <= y) return (c >= x) ? not_negated : !not_negated; - } - - return !not_negated; /* char did not match */ - } - -#if PCRE2_CODE_UNIT_WIDTH == 8 -type = (uint32_t)(data[0] << 8) | data[1]; -data += 2; -#else -type = data[0]; -data++; -#endif /* CODE_UNIT_WIDTH */ - -/* Align characters. */ -next_char = char_lists_end - (GET(data, 0) << 1); -type &= XCL_TYPE_MASK; - -/* Alignment check. */ -PCRE2_ASSERT(((uintptr_t)next_char & 0x1) == 0); - -if (c >= XCL_CHAR_LIST_HIGH_16_START) - { - max_index = type & XCL_ITEM_COUNT_MASK; - if (max_index == XCL_ITEM_COUNT_MASK) - { - max_index = *(const uint16_t*)next_char; - PCRE2_ASSERT(max_index >= XCL_ITEM_COUNT_MASK); - next_char += 2; - } - - next_char += max_index << 1; - type >>= XCL_TYPE_BIT_LEN; } -if (c < XCL_CHAR_LIST_LOW_32_START) - { - max_index = type & XCL_ITEM_COUNT_MASK; - - c = (uint16_t)((c << XCL_CHAR_SHIFT) | XCL_CHAR_END); - - if (max_index == XCL_ITEM_COUNT_MASK) - { - max_index = *(const uint16_t*)next_char; - PCRE2_ASSERT(max_index >= XCL_ITEM_COUNT_MASK); - next_char += 2; - } - - if (max_index == 0 || c < *(const uint16_t*)next_char) - return ((type & XCL_BEGIN_WITH_RANGE) != 0) == not_negated; - - min_index = 0; - value = ((const uint16_t*)next_char)[--max_index]; - if (c >= value) - return (value == c || (value & XCL_CHAR_END) == 0) == not_negated; - - max_index--; - - /* Binary search of a range. */ - while (TRUE) - { - uint32_t mid_index = (min_index + max_index) >> 1; - value = ((const uint16_t*)next_char)[mid_index]; - - if (c < value) - max_index = mid_index - 1; - else if (((const uint16_t*)next_char)[mid_index + 1] <= c) - min_index = mid_index + 1; - else - return (value == c || (value & XCL_CHAR_END) == 0) == not_negated; - } - } - -/* Skip the 16 bit ranges. */ -max_index = type & XCL_ITEM_COUNT_MASK; -if (max_index == XCL_ITEM_COUNT_MASK) - { - max_index = *(const uint16_t*)next_char; - PCRE2_ASSERT(max_index >= XCL_ITEM_COUNT_MASK); - next_char += 2; - } - -next_char += (max_index << 1); -type >>= XCL_TYPE_BIT_LEN; - -/* Alignment check. */ -PCRE2_ASSERT(((uintptr_t)next_char & 0x3) == 0); - -max_index = type & XCL_ITEM_COUNT_MASK; - -#if PCRE2_CODE_UNIT_WIDTH == 32 -if (c >= XCL_CHAR_LIST_HIGH_32_START) - { - if (max_index == XCL_ITEM_COUNT_MASK) - { - max_index = *(const uint32_t*)next_char; - PCRE2_ASSERT(max_index >= XCL_ITEM_COUNT_MASK); - next_char += 4; - } - - next_char += max_index << 2; - type >>= XCL_TYPE_BIT_LEN; - max_index = type & XCL_ITEM_COUNT_MASK; - } -#endif - -c = (uint32_t)((c << XCL_CHAR_SHIFT) | XCL_CHAR_END); - -if (max_index == XCL_ITEM_COUNT_MASK) - { - max_index = *(const uint32_t*)next_char; - next_char += 4; - } - -if (max_index == 0 || c < *(const uint32_t*)next_char) - return ((type & XCL_BEGIN_WITH_RANGE) != 0) == not_negated; - -min_index = 0; -value = ((const uint32_t*)next_char)[--max_index]; -if (c >= value) - return (value == c || (value & XCL_CHAR_END) == 0) == not_negated; - -max_index--; - -/* Binary search of a range. */ -while (TRUE) - { - uint32_t mid_index = (min_index + max_index) >> 1; - value = ((const uint32_t*)next_char)[mid_index]; - - if (c < value) - max_index = mid_index - 1; - else if (((const uint32_t*)next_char)[mid_index + 1] <= c) - min_index = mid_index + 1; - else - return (value == c || (value & XCL_CHAR_END) == 0) == not_negated; - } -} - - - -/************************************************* -* Match character against an ECLASS * -*************************************************/ - -/* This function is called to match a character against an extended class -used for describing characters using boolean operations on sets. - -Arguments: - c the character - data_start points to the start of the ECLASS data - data_end points one-past-the-last of the ECLASS data - utf TRUE if in UTF mode - -Returns: TRUE if character matches, else FALSE -*/ - -BOOL -PRIV(eclass)(uint32_t c, PCRE2_SPTR data_start, PCRE2_SPTR data_end, - const uint8_t *char_lists_end, BOOL utf) -{ -PCRE2_SPTR ptr = data_start; -PCRE2_UCHAR flags; -uint32_t stack = 0; -int stack_depth = 0; - -PCRE2_ASSERT(data_start < data_end); -flags = *ptr++; -PCRE2_ASSERT((flags & ECL_MAP) == 0 || - (data_end - ptr) >= 32 / (int)sizeof(PCRE2_UCHAR)); - -/* Code points < 256 are matched against a bitmap, if one is present. -Otherwise all codepoints are checked later. */ - -if ((flags & ECL_MAP) != 0) - { - if (c < 256) - return (((const uint8_t *)ptr)[c/8] & (1u << (c&7))) != 0; - - /* Skip the bitmap. */ - ptr += 32 / sizeof(PCRE2_UCHAR); - } - -/* Do a little loop, until we reach the end of the ECLASS. */ -while (ptr < data_end) - { - switch (*ptr) - { - case ECL_AND: - ++ptr; - stack = (stack >> 1) & (stack | ~(uint32_t)1u); - PCRE2_ASSERT(stack_depth >= 2); - --stack_depth; - break; - - case ECL_OR: - ++ptr; - stack = (stack >> 1) | (stack & (uint32_t)1u); - PCRE2_ASSERT(stack_depth >= 2); - --stack_depth; - break; - - case ECL_XOR: - ++ptr; - stack = (stack >> 1) ^ (stack & (uint32_t)1u); - PCRE2_ASSERT(stack_depth >= 2); - --stack_depth; - break; - - case ECL_NOT: - ++ptr; - stack ^= (uint32_t)1u; - PCRE2_ASSERT(stack_depth >= 1); - break; - - case ECL_XCLASS: - { - uint32_t matched = PRIV(xclass)(c, ptr + 1 + LINK_SIZE, char_lists_end, utf); - - ptr += GET(ptr, 1); - stack = (stack << 1) | matched; - ++stack_depth; - break; - } - - /* This should never occur, but compilers may mutter if there is no - default. */ - - default: - PCRE2_DEBUG_UNREACHABLE(); - return FALSE; - } - } - -PCRE2_ASSERT(stack_depth == 1); -(void)stack_depth; /* Ignore unused variable, if assertions are disabled. */ - -/* The final bit left on the stack now holds the match result. */ -return (stack & 1u) != 0; +return negated; /* char did not match */ } /* End of pcre2_xclass.c */ diff --git a/ext/pcre/pcre2lib/sljit/sljitConfig.h b/ext/pcre/pcre2lib/sljit/sljitConfig.h index 993f4fe2fa168..364c8bb7884af 100644 --- a/ext/pcre/pcre2lib/sljit/sljitConfig.h +++ b/ext/pcre/pcre2lib/sljit/sljitConfig.h @@ -29,7 +29,7 @@ #ifdef __cplusplus extern "C" { -#endif /* __cplusplus */ +#endif /* This file contains the basic configuration options for the SLJIT compiler @@ -47,19 +47,19 @@ extern "C" { #ifndef SLJIT_UTIL_STACK /* Enabled by default */ #define SLJIT_UTIL_STACK 1 -#endif /* SLJIT_UTIL_STACK */ +#endif /* Uses user provided allocator to allocate the stack (see SLJIT_UTIL_STACK) */ #ifndef SLJIT_UTIL_SIMPLE_STACK_ALLOCATION /* Disabled by default */ #define SLJIT_UTIL_SIMPLE_STACK_ALLOCATION 0 -#endif /* SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */ +#endif /* Single threaded application. Does not require any locks. */ #ifndef SLJIT_SINGLE_THREADED /* Disabled by default. */ #define SLJIT_SINGLE_THREADED 0 -#endif /* SLJIT_SINGLE_THREADED */ +#endif /* --------------------------------------------------------------------- */ /* Configuration */ @@ -70,7 +70,7 @@ extern "C" { #ifndef SLJIT_STD_MACROS_DEFINED /* Disabled by default. */ #define SLJIT_STD_MACROS_DEFINED 0 -#endif /* SLJIT_STD_MACROS_DEFINED */ +#endif /* Executable code allocation: If SLJIT_EXECUTABLE_ALLOCATOR is not defined, the application should @@ -93,7 +93,7 @@ extern "C" { #ifndef SLJIT_PROT_EXECUTABLE_ALLOCATOR /* Disabled by default. */ #define SLJIT_PROT_EXECUTABLE_ALLOCATOR 0 -#endif /* SLJIT_PROT_EXECUTABLE_ALLOCATOR */ +#endif /* When SLJIT_WX_EXECUTABLE_ALLOCATOR is enabled SLJIT uses an allocator which does not set writable and executable permission @@ -104,7 +104,7 @@ extern "C" { #ifndef SLJIT_WX_EXECUTABLE_ALLOCATOR /* Disabled by default. */ #define SLJIT_WX_EXECUTABLE_ALLOCATOR 0 -#endif /* SLJIT_WX_EXECUTABLE_ALLOCATOR */ +#endif #endif /* !SLJIT_EXECUTABLE_ALLOCATOR */ @@ -112,19 +112,19 @@ extern "C" { #ifndef SLJIT_ARGUMENT_CHECKS /* Disabled by default */ #define SLJIT_ARGUMENT_CHECKS 0 -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif /* Debug checks (assertions, etc.). */ #ifndef SLJIT_DEBUG /* Enabled by default */ #define SLJIT_DEBUG 1 -#endif /* SLJIT_DEBUG */ +#endif /* Verbose operations. */ #ifndef SLJIT_VERBOSE /* Enabled by default */ #define SLJIT_VERBOSE 1 -#endif /* SLJIT_VERBOSE */ +#endif /* SLJIT_IS_FPU_AVAILABLE @@ -137,6 +137,6 @@ extern "C" { #ifdef __cplusplus } /* extern "C" */ -#endif /* __cplusplus */ +#endif #endif /* SLJIT_CONFIG_H_ */ diff --git a/ext/pcre/pcre2lib/sljit/sljitConfigCPU.h b/ext/pcre/pcre2lib/sljit/sljitConfigCPU.h index dcf88efbd4373..2720bdab0bd17 100644 --- a/ext/pcre/pcre2lib/sljit/sljitConfigCPU.h +++ b/ext/pcre/pcre2lib/sljit/sljitConfigCPU.h @@ -169,7 +169,7 @@ #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \ || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) #define SLJIT_CONFIG_ARM_32 1 -#endif /* SLJIT_CONFIG_ARM_V6 || SLJIT_CONFIG_ARM_V7 || SLJIT_CONFIG_ARM_THUMB2 */ +#endif #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) #define SLJIT_CONFIG_X86 1 diff --git a/ext/pcre/pcre2lib/sljit/sljitConfigInternal.h b/ext/pcre/pcre2lib/sljit/sljitConfigInternal.h index 3ae944efb8108..de06dd8e0c021 100644 --- a/ext/pcre/pcre2lib/sljit/sljitConfigInternal.h +++ b/ext/pcre/pcre2lib/sljit/sljitConfigInternal.h @@ -27,6 +27,20 @@ #ifndef SLJIT_CONFIG_INTERNAL_H_ #define SLJIT_CONFIG_INTERNAL_H_ +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_DEBUG && SLJIT_DEBUG && (!defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE))) +#include +#endif + +#if (defined SLJIT_DEBUG && SLJIT_DEBUG \ + && (!defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE) || !defined(SLJIT_HALT_PROCESS))) +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + /* SLJIT defines the following architecture dependent types and macros: @@ -50,26 +64,16 @@ SLJIT_MASKED_SHIFT : all word shifts are always masked SLJIT_MASKED_SHIFT32 : all 32 bit shifts are always masked SLJIT_INDIRECT_CALL : see SLJIT_FUNC_ADDR() for more information - SLJIT_UPPER_BITS_IGNORED : 32 bit operations ignores the upper bits of source registers - SLJIT_UPPER_BITS_ZERO_EXTENDED : 32 bit operations clears the upper bits of destination registers - SLJIT_UPPER_BITS_SIGN_EXTENDED : 32 bit operations replicates the sign bit in the upper bits of destination registers - SLJIT_UPPER_BITS_PRESERVED : 32 bit operations preserves the upper bits of destination registers Constants: SLJIT_NUMBER_OF_REGISTERS : number of available registers SLJIT_NUMBER_OF_SCRATCH_REGISTERS : number of available scratch registers SLJIT_NUMBER_OF_SAVED_REGISTERS : number of available saved registers SLJIT_NUMBER_OF_FLOAT_REGISTERS : number of available floating point registers - SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS : number of available scratch floating point registers - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS : number of available saved floating point registers - SLJIT_NUMBER_OF_VECTOR_REGISTERS : number of available vector registers - SLJIT_NUMBER_OF_SCRATCH_VECTOR_REGISTERS : number of available scratch vector registers - SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS : number of available saved vector registers + SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS : number of available floating point scratch registers + SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS : number of available floating point saved registers SLJIT_NUMBER_OF_TEMPORARY_REGISTERS : number of available temporary registers SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS : number of available temporary floating point registers - SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS : number of available temporary vector registers - SLJIT_SEPARATE_VECTOR_REGISTERS : if this macro is defined, the vector registers do not - overlap with floating point registers SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_sw/sljit_uw array by index SLJIT_F32_SHIFT : the shift required to apply when accessing a single precision floating point array by index @@ -94,33 +98,16 @@ SLJIT_TMP_R(i) : accessing temporary registers SLJIT_TMP_FR0 .. FR9 : accessing temporary floating point registers SLJIT_TMP_FR(i) : accessing temporary floating point registers - SLJIT_TMP_VR0 .. VR9 : accessing temporary vector registers - SLJIT_TMP_VR(i) : accessing temporary vector registers SLJIT_TMP_DEST_REG : a temporary register for results SLJIT_TMP_MEM_REG : a temporary base register for accessing memory (can be the same as SLJIT_TMP_DEST_REG) SLJIT_TMP_DEST_FREG : a temporary register for float results - SLJIT_TMP_DEST_VREG : a temporary register for vector results SLJIT_FUNC : calling convention attribute for both calling JIT from C and C calling back from JIT SLJIT_W(number) : defining 64 bit constants on 64 bit architectures (platform independent helper) SLJIT_F64_SECOND(reg) : provides the register index of the second 32 bit part of a 64 bit floating point register when SLJIT_HAS_F64_AS_F32_PAIR returns non-zero */ -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ - || (defined SLJIT_DEBUG && SLJIT_DEBUG && (!defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE))) -#include -#endif - -#if (defined SLJIT_DEBUG && SLJIT_DEBUG \ - && (!defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE) || !defined(SLJIT_HALT_PROCESS))) -#include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - /***********************************************************/ /* Intel Control-flow Enforcement Technology (CET) spport. */ /***********************************************************/ @@ -298,7 +285,7 @@ extern "C" { #elif defined(_WIN32) #define SLJIT_CACHE_FLUSH(from, to) \ - FlushInstructionCache(GetCurrentProcess(), (void*)(from), (size_t)((char*)(to) - (char*)(from))) + FlushInstructionCache(GetCurrentProcess(), (void*)(from), (char*)(to) - (char*)(from)) #elif (defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) || defined(__clang__) @@ -566,7 +553,7 @@ determine the next executed instruction after return. */ #if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size); SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr); -/* Note: sljitLir.h also defines sljit_free_unused_memory_exec() function. */ +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void); #define SLJIT_BUILTIN_MALLOC_EXEC(size, exec_allocator_data) sljit_malloc_exec(size) #define SLJIT_BUILTIN_FREE_EXEC(ptr, exec_allocator_data) sljit_free_exec(ptr) @@ -604,12 +591,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code); #define SLJIT_TMP_DEST_REG SLJIT_TMP_R0 #define SLJIT_TMP_MEM_REG SLJIT_TMP_R0 #define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0 -#define SLJIT_LOCALS_OFFSET_BASE (8 * (sljit_s32)sizeof(sljit_sw)) +#define SLJIT_LOCALS_OFFSET_BASE (8 * SSIZE_OF(sw)) #define SLJIT_PREF_SHIFT_REG SLJIT_R2 #define SLJIT_MASKED_SHIFT 1 #define SLJIT_MASKED_SHIFT32 1 -#define SLJIT_UPPER_BITS_IGNORED 1 -#define SLJIT_UPPER_BITS_ZERO_EXTENDED 1 #elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) @@ -624,7 +609,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code); #else /* _WIN64 */ #define SLJIT_NUMBER_OF_SAVED_REGISTERS 8 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 10 -#define SLJIT_LOCALS_OFFSET_BASE (4 * (sljit_s32)sizeof(sljit_sw)) +#define SLJIT_LOCALS_OFFSET_BASE (4 * SSIZE_OF(sw)) #endif /* !_WIN64 */ #define SLJIT_TMP_DEST_REG SLJIT_TMP_R0 #define SLJIT_TMP_MEM_REG SLJIT_TMP_R0 @@ -632,8 +617,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code); #define SLJIT_PREF_SHIFT_REG SLJIT_R3 #define SLJIT_MASKED_SHIFT 1 #define SLJIT_MASKED_SHIFT32 1 -#define SLJIT_UPPER_BITS_IGNORED 1 -#define SLJIT_UPPER_BITS_ZERO_EXTENDED 1 #elif (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) @@ -662,8 +645,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code); #define SLJIT_LOCALS_OFFSET_BASE (2 * (sljit_s32)sizeof(sljit_sw)) #define SLJIT_MASKED_SHIFT 1 #define SLJIT_MASKED_SHIFT32 1 -#define SLJIT_UPPER_BITS_IGNORED 1 -#define SLJIT_UPPER_BITS_ZERO_EXTENDED 1 #elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) @@ -684,7 +665,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code); #else #define SLJIT_LOCALS_OFFSET_BASE (3 * (sljit_s32)sizeof(sljit_sw)) #endif /* SLJIT_CONFIG_PPC_64 || _AIX */ -#define SLJIT_UPPER_BITS_IGNORED 1 #elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) @@ -706,7 +686,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code); #define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0 #define SLJIT_MASKED_SHIFT 1 #define SLJIT_MASKED_SHIFT32 1 -#define SLJIT_UPPER_BITS_SIGN_EXTENDED 1 #elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) @@ -716,19 +695,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code); #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 12 #define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2 -#define SLJIT_SEPARATE_VECTOR_REGISTERS 1 -#define SLJIT_NUMBER_OF_VECTOR_REGISTERS 30 -#define SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS 0 -#define SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS 2 #define SLJIT_TMP_DEST_REG SLJIT_TMP_R1 #define SLJIT_TMP_MEM_REG SLJIT_TMP_R1 #define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0 -#define SLJIT_TMP_DEST_VREG SLJIT_TMP_VR0 #define SLJIT_LOCALS_OFFSET_BASE 0 #define SLJIT_MASKED_SHIFT 1 #define SLJIT_MASKED_SHIFT32 1 -#define SLJIT_UPPER_BITS_IGNORED 1 -#define SLJIT_UPPER_BITS_SIGN_EXTENDED 1 #elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) @@ -764,8 +736,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code); #define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0 #define SLJIT_LOCALS_OFFSET_BASE SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE #define SLJIT_MASKED_SHIFT 1 -#define SLJIT_UPPER_BITS_IGNORED 1 -#define SLJIT_UPPER_BITS_PRESERVED 1 #elif (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH) @@ -781,7 +751,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code); #define SLJIT_LOCALS_OFFSET_BASE 0 #define SLJIT_MASKED_SHIFT 1 #define SLJIT_MASKED_SHIFT32 1 -#define SLJIT_UPPER_BITS_SIGN_EXTENDED 1 #elif (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) @@ -799,13 +768,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code); #endif -#if !(defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS) -#define SLJIT_NUMBER_OF_VECTOR_REGISTERS (SLJIT_NUMBER_OF_FLOAT_REGISTERS) -#define SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS (SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS) -#define SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS (SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS) -#define SLJIT_TMP_DEST_VREG (SLJIT_TMP_DEST_FREG) -#endif /* !SLJIT_SEPARATE_VECTOR_REGISTERS */ - #define SLJIT_LOCALS_OFFSET (SLJIT_LOCALS_OFFSET_BASE) #define SLJIT_NUMBER_OF_SCRATCH_REGISTERS \ @@ -814,27 +776,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code); #define SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS \ (SLJIT_NUMBER_OF_FLOAT_REGISTERS - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS) -#define SLJIT_NUMBER_OF_SCRATCH_VECTOR_REGISTERS \ - (SLJIT_NUMBER_OF_VECTOR_REGISTERS - SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS) - -#if (defined SLJIT_UPPER_BITS_ZERO_EXTENDED && SLJIT_UPPER_BITS_ZERO_EXTENDED) \ - + (defined SLJIT_UPPER_BITS_SIGN_EXTENDED && SLJIT_UPPER_BITS_SIGN_EXTENDED) \ - + (defined SLJIT_UPPER_BITS_PRESERVED && SLJIT_UPPER_BITS_PRESERVED) > 1 -#error "Invalid upper bits defintion" -#endif - -#if (defined SLJIT_UPPER_BITS_PRESERVED && SLJIT_UPPER_BITS_PRESERVED) \ - && !(defined SLJIT_UPPER_BITS_IGNORED && SLJIT_UPPER_BITS_IGNORED) -#error "Upper bits preserved requires bits ignored" -#endif - /**********************************/ /* Temporary register management. */ /**********************************/ #define SLJIT_TMP_REGISTER_BASE (SLJIT_NUMBER_OF_REGISTERS + 2) #define SLJIT_TMP_FREGISTER_BASE (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) -#define SLJIT_TMP_VREGISTER_BASE (SLJIT_NUMBER_OF_VECTOR_REGISTERS + 1) /* WARNING: Accessing temporary registers is not recommended, because they are also used by the JIT compiler for various computations. Using them @@ -868,18 +815,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code); #define SLJIT_TMP_FR9 (SLJIT_TMP_FREGISTER_BASE + 9) #define SLJIT_TMP_FR(i) (SLJIT_TMP_FREGISTER_BASE + (i)) -#define SLJIT_TMP_VR0 (SLJIT_TMP_VREGISTER_BASE + 0) -#define SLJIT_TMP_VR1 (SLJIT_TMP_VREGISTER_BASE + 1) -#define SLJIT_TMP_VR2 (SLJIT_TMP_VREGISTER_BASE + 2) -#define SLJIT_TMP_VR3 (SLJIT_TMP_VREGISTER_BASE + 3) -#define SLJIT_TMP_VR4 (SLJIT_TMP_VREGISTER_BASE + 4) -#define SLJIT_TMP_VR5 (SLJIT_TMP_VREGISTER_BASE + 5) -#define SLJIT_TMP_VR6 (SLJIT_TMP_VREGISTER_BASE + 6) -#define SLJIT_TMP_VR7 (SLJIT_TMP_VREGISTER_BASE + 7) -#define SLJIT_TMP_VR8 (SLJIT_TMP_VREGISTER_BASE + 8) -#define SLJIT_TMP_VR9 (SLJIT_TMP_VREGISTER_BASE + 9) -#define SLJIT_TMP_VR(i) (SLJIT_TMP_VREGISTER_BASE + (i)) - /********************************/ /* CPU status flags management. */ /********************************/ diff --git a/ext/pcre/pcre2lib/sljit/sljitLir.c b/ext/pcre/pcre2lib/sljit/sljitLir.c index 6b2d5564c7587..2dca17cd6f078 100644 --- a/ext/pcre/pcre2lib/sljit/sljitLir.c +++ b/ext/pcre/pcre2lib/sljit/sljitLir.c @@ -96,10 +96,9 @@ /* All variable flags are even. */ #define VARIABLE_FLAG_MASK (0x3e << VARIABLE_FLAG_SHIFT) #define GET_FLAG_TYPE(op) ((op) >> VARIABLE_FLAG_SHIFT) -#define GET_FLAG_TYPE_MASK(op) (((op) >> VARIABLE_FLAG_SHIFT) & 0x3e) #define GET_OPCODE(op) \ - ((op) & 0xff) + ((op) & ~(SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) #define HAS_FLAGS(op) \ ((op) & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)) @@ -119,9 +118,9 @@ #if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE) #define ABUF_SIZE 2048 -#else /* !SLJIT_32BIT_ARCHITECTURE */ +#else #define ABUF_SIZE 4096 -#endif /* SLJIT_32BIT_ARCHITECTURE */ +#endif /* Parameter parsing. */ #define REG_MASK 0x7f @@ -140,10 +139,7 @@ #define REG_PAIR_SECOND(reg) ((reg) >> 8) /* Mask for sljit_emit_enter. */ -#define ENTER_GET_REGS(regs) ((regs) & 0xff) -#define ENTER_GET_FLOAT_REGS(regs) (((regs) >> 8) & 0xff) -#define ENTER_GET_VECTOR_REGS(regs) (((regs) >> 16) & 0xff) -#define SLJIT_KEPT_SAVEDS_COUNT(options) ((options) & 0x3) +#define SLJIT_KEPT_SAVEDS_COUNT(options) ((options) & 0x3) /* Getters for simd operations, which returns with log2(size). */ #define SLJIT_SIMD_GET_OPCODE(type) ((type) & 0xff) @@ -338,19 +334,19 @@ #if defined(__NetBSD__) #include "allocator_src/sljitProtExecAllocatorNetBSD.c" -#else /* !__NetBSD__ */ +#else #include "allocator_src/sljitProtExecAllocatorPosix.c" -#endif /* __NetBSD__ */ +#endif #elif (defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR) #if defined(_WIN32) #include "allocator_src/sljitWXExecAllocatorWindows.c" -#else /* !_WIN32 */ +#else #include "allocator_src/sljitWXExecAllocatorPosix.c" -#endif /* _WIN32 */ +#endif -#else /* !SLJIT_PROT_EXECUTABLAE_ALLOCATOR && !SLJIT_WX_EXECUTABLE_ALLOCATOR */ +#else #if defined(_WIN32) #include "allocator_src/sljitExecAllocatorWindows.c" @@ -358,25 +354,25 @@ #include "allocator_src/sljitExecAllocatorApple.c" #elif defined(__FreeBSD__) #include "allocator_src/sljitExecAllocatorFreeBSD.c" -#else /* !_WIN32 && !__APPLE__ && !__FreeBSD__ */ +#else #include "allocator_src/sljitExecAllocatorPosix.c" -#endif /* _WIN32 */ +#endif -#endif /* SLJIT_PROT_EXECUTABLE_ALLOCATOR */ +#endif #else /* !SLJIT_EXECUTABLE_ALLOCATOR */ #ifndef SLJIT_UPDATE_WX_FLAGS #define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) -#endif /* SLJIT_UPDATE_WX_FLAGS */ +#endif #endif /* SLJIT_EXECUTABLE_ALLOCATOR */ #if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR) #define SLJIT_ADD_EXEC_OFFSET(ptr, exec_offset) ((sljit_u8 *)(ptr) + (exec_offset)) -#else /* !SLJIT_PROT_EXECUTABLE_ALLOCATOR */ +#else #define SLJIT_ADD_EXEC_OFFSET(ptr, exec_offset) ((sljit_u8 *)(ptr)) -#endif /* SLJIT_PROT_EXECUTABLE_ALLOCATOR */ +#endif /* Argument checking features. */ @@ -438,7 +434,7 @@ #define CHECK_PTR(x) x #define CHECK_REG_INDEX(x) x -#else /* !SLJIT_ARGUMENT_CHECKS && !SLJIT_DEBUG && !SLJIT_VERBOSE */ +#else /* Arguments are not checked. */ #define CHECK(x) @@ -456,7 +452,7 @@ static sljit_s32 compiler_initialized = 0; /* A thread safe initialization. */ static void init_compiler(void); -#endif /* SLJIT_CONFIG_X86 */ +#endif SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data) { @@ -505,12 +501,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allo compiler->saveds = -1; compiler->fscratches = -1; compiler->fsaveds = -1; -#if (defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ - || (defined SLJIT_VERBOSE && SLJIT_VERBOSE) - compiler->vscratches = -1; - compiler->vsaveds = -1; -#endif /* SLJIT_SEPARATE_VECTOR_REGISTERS || SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */ compiler->local_size = -1; #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) @@ -536,25 +526,17 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allo #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ || (defined SLJIT_DEBUG && SLJIT_DEBUG) - SLJIT_ASSERT(compiler->last_flags == 0 && compiler->logical_local_size == 0); + compiler->last_flags = 0; compiler->last_return = -1; + compiler->logical_local_size = 0; #endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */ -#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ - || (defined SLJIT_VERBOSE && SLJIT_VERBOSE) -#if !(defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS) - compiler->real_fscratches = -1; - compiler->real_fsaveds = -1; -#endif /* !SLJIT_SEPARATE_VECTOR_REGISTERS */ - SLJIT_ASSERT(compiler->skip_checks == 0); -#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */ - #if (defined SLJIT_NEEDS_COMPILER_INIT && SLJIT_NEEDS_COMPILER_INIT) if (!compiler_initialized) { init_compiler(); compiler_initialized = 1; } -#endif /* SLJIT_NEEDS_COMPILER_INIT */ +#endif return compiler; } @@ -582,7 +564,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compile #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) SLJIT_FREE(compiler->cpool, allocator_data); -#endif /* SLJIT_CONFIG_ARM_V6 */ +#endif SLJIT_FREE(compiler, allocator_data); } @@ -625,14 +607,14 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *com #if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE) compiler->status_flags_state = current_flags; -#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */ +#endif #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->last_flags = 0; if ((current_flags & ~(VARIABLE_FLAG_MASK | SLJIT_SET_Z | SLJIT_CURRENT_FLAGS_ALL)) == 0) { compiler->last_flags = GET_FLAG_TYPE(current_flags) | (current_flags & (SLJIT_32 | SLJIT_SET_Z)); } -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif } /* --------------------------------------------------------------------- */ @@ -685,11 +667,11 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compile if (size <= 0 || size > 128) return NULL; size = (size + 7) & ~7; -#else /* !SLJIT_64BIT_ARCHITECTURE */ +#else if (size <= 0 || size > 64) return NULL; size = (size + 3) & ~3; -#endif /* SLJIT_64BIT_ARCHITECTURE */ +#endif return ensure_abuf(compiler, (sljit_uw)size); } @@ -770,55 +752,40 @@ static SLJIT_INLINE sljit_uw sljit_get_next_min(sljit_uw next_label_size, #endif /* !SLJIT_CONFIG_X86 */ -#if !(defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS) - -static void update_float_register_count(struct sljit_compiler *compiler, sljit_s32 scratches, sljit_s32 saveds) +static SLJIT_INLINE void set_emit_enter(struct sljit_compiler *compiler, + sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 vscratches = ENTER_GET_VECTOR_REGS(scratches); - sljit_s32 vsaveds = ENTER_GET_VECTOR_REGS(saveds); - - if (compiler->fscratches < vscratches) - compiler->fscratches = vscratches; - - if (compiler->fsaveds < vsaveds) - compiler->fsaveds = vsaveds; + SLJIT_UNUSED_ARG(args); + SLJIT_UNUSED_ARG(local_size); - if (compiler->fsaveds + compiler->fscratches > SLJIT_NUMBER_OF_FLOAT_REGISTERS) - compiler->fscratches = SLJIT_NUMBER_OF_FLOAT_REGISTERS - compiler->fsaveds; + compiler->options = options; + compiler->scratches = scratches; + compiler->saveds = saveds; + compiler->fscratches = fscratches; + compiler->fsaveds = fsaveds; +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->last_return = args & SLJIT_ARG_MASK; + compiler->logical_local_size = local_size; +#endif } -#endif /* !SLJIT_SEPARATE_VECTOR_REGISTERS */ - -static SLJIT_INLINE void set_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) +static SLJIT_INLINE void set_set_context(struct sljit_compiler *compiler, + sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { SLJIT_UNUSED_ARG(args); SLJIT_UNUSED_ARG(local_size); compiler->options = options; - compiler->scratches = ENTER_GET_REGS(scratches); - compiler->saveds = ENTER_GET_REGS(saveds); - /* These members may be copied to real_* members below. */ - compiler->fscratches = ENTER_GET_FLOAT_REGS(scratches); - compiler->fsaveds = ENTER_GET_FLOAT_REGS(saveds); -#if (defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS) - compiler->vscratches = ENTER_GET_VECTOR_REGS(scratches); - compiler->vsaveds = ENTER_GET_VECTOR_REGS(saveds); -#else /* !SLJIT_SEPARATE_VECTOR_REGISTERS */ -#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ - || (defined SLJIT_VERBOSE && SLJIT_VERBOSE) - compiler->real_fscratches = compiler->fscratches; - compiler->real_fsaveds = compiler->fsaveds; - compiler->vscratches = ENTER_GET_VECTOR_REGS(scratches); - compiler->vsaveds = ENTER_GET_VECTOR_REGS(saveds); -#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */ - update_float_register_count(compiler, scratches, saveds); -#endif /* SLJIT_SEPARATE_VECTOR_REGISTERS */ + compiler->scratches = scratches; + compiler->saveds = saveds; + compiler->fscratches = fscratches; + compiler->fsaveds = fsaveds; #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->last_return = args & SLJIT_ARG_MASK; compiler->logical_local_size = local_size; -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif } static SLJIT_INLINE void set_label(struct sljit_label *label, struct sljit_compiler *compiler) @@ -933,9 +900,9 @@ static sljit_s32 function_check_arguments(sljit_s32 arg_types, sljit_s32 scratch #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) #define CHECK_IF_VIRTUAL_REGISTER(p) ((p) <= SLJIT_S3 && (p) >= SLJIT_S8) -#else /* !SLJIT_CONFIG_X86_32 */ +#else #define CHECK_IF_VIRTUAL_REGISTER(p) 0 -#endif /* SLJIT_CONFIG_X86_32 */ +#endif static sljit_s32 function_check_src_mem(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i) { @@ -1027,47 +994,17 @@ static sljit_s32 function_fcheck(struct sljit_compiler *compiler, sljit_s32 p, s return function_check_src_mem(compiler, p, i); } -static sljit_s32 function_check_is_vreg(struct sljit_compiler *compiler, sljit_s32 vr, sljit_s32 type); - -#define FUNCTION_CHECK_IS_VREG(vr, type) \ - function_check_is_vreg(compiler, (vr), (type)) - -#define FUNCTION_VCHECK(p, i, type) \ - CHECK_ARGUMENT(function_vcheck(compiler, (p), (i), (type))) - -static sljit_s32 function_vcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i, sljit_s32 type) -{ - if (compiler->scratches == -1) - return 0; - - if (FUNCTION_CHECK_IS_VREG(p, type)) - return (i == 0); - - return function_check_src_mem(compiler, p, i); -} - #else /* !SLJIT_CONFIG_ARM_32 && !SLJIT_CONFIG_MIPS_32 */ - #define FUNCTION_CHECK_IS_FREG(fr, is_32) \ function_check_is_freg(compiler, (fr)) static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr) { - sljit_s32 fscratches, fsaveds; - if (compiler->scratches == -1) return 0; -#if (defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS) - fscratches = compiler->fscratches; - fsaveds = compiler->fsaveds; -#else /* SLJIT_SEPARATE_VECTOR_REGISTERS */ - fscratches = compiler->real_fscratches; - fsaveds = compiler->real_fsaveds; -#endif /* !SLJIT_SEPARATE_VECTOR_REGISTERS */ - - return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + fscratches)) - || (fr > (SLJIT_FS0 - fsaveds) && fr <= SLJIT_FS0) + return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->fscratches)) + || (fr > (SLJIT_FS0 - compiler->fsaveds) && fr <= SLJIT_FS0) || (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS)); } @@ -1079,34 +1016,9 @@ static sljit_s32 function_fcheck(struct sljit_compiler *compiler, sljit_s32 p, s if (compiler->scratches == -1) return 0; - if (function_check_is_freg(compiler, p)) - return (i == 0); - - return function_check_src_mem(compiler, p, i); -} - -#define FUNCTION_CHECK_IS_VREG(vr, type) \ - function_check_is_vreg(compiler, (vr)) - -static sljit_s32 function_check_is_vreg(struct sljit_compiler *compiler, sljit_s32 vr) -{ - if (compiler->scratches == -1) - return 0; - - return (vr >= SLJIT_VR0 && vr < (SLJIT_VR0 + compiler->vscratches)) - || (vr > (SLJIT_VS0 - compiler->vsaveds) && vr <= SLJIT_VS0) - || (vr >= SLJIT_TMP_VREGISTER_BASE && vr < (SLJIT_TMP_VREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS)); -} - -#define FUNCTION_VCHECK(p, i, type) \ - CHECK_ARGUMENT(function_vcheck(compiler, (p), (i))) - -static sljit_s32 function_vcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i) -{ - if (compiler->scratches == -1) - return 0; - - if (function_check_is_vreg(compiler, p)) + if ((p >= SLJIT_FR0 && p < (SLJIT_FR0 + compiler->fscratches)) + || (p > (SLJIT_FS0 - compiler->fsaveds) && p <= SLJIT_FS0) + || (p >= SLJIT_TMP_FREGISTER_BASE && p < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS))) return (i == 0); return function_check_src_mem(compiler, p, i); @@ -1127,15 +1039,15 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *comp #ifdef _WIN64 #ifdef __GNUC__ # define SLJIT_PRINT_D "ll" -#else /* !__GNUC__ */ +#else # define SLJIT_PRINT_D "I64" -#endif /* __GNUC__ */ -#else /* !_WIN64 */ +#endif +#else # define SLJIT_PRINT_D "l" -#endif /* _WIN64 */ -#else /* !SLJIT_64BIT_ARCHITECTURE */ +#endif +#else # define SLJIT_PRINT_D "" -#endif /* SLJIT_64BIT_ARCHITECTURE */ +#endif static void sljit_verbose_reg(struct sljit_compiler *compiler, sljit_s32 r) { @@ -1167,73 +1079,57 @@ static void sljit_verbose_freg(struct sljit_compiler *compiler, sljit_s32 r) fprintf(compiler->verbose, "ft%d", r - SLJIT_TMP_FREGISTER_BASE); } -static void sljit_verbose_vreg(struct sljit_compiler *compiler, sljit_s32 r) -{ -#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \ - || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) - if (r >= SLJIT_F64_SECOND(SLJIT_VR0)) { - fprintf(compiler->verbose, "^"); - r -= SLJIT_F64_SECOND(0); - } -#endif /* SLJIT_CONFIG_ARM_32 || SLJIT_CONFIG_MIPS_32 */ - - if (r < (SLJIT_VR0 + compiler->vscratches)) - fprintf(compiler->verbose, "vr%d", r - SLJIT_VR0); - else if (r < SLJIT_TMP_VREGISTER_BASE) - fprintf(compiler->verbose, "vs%d", SLJIT_NUMBER_OF_VECTOR_REGISTERS - r); - else - fprintf(compiler->verbose, "vt%d", r - SLJIT_TMP_VREGISTER_BASE); -} - -static void sljit_verbose_mem(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i) -{ - if (!(p & REG_MASK)) { - fprintf(compiler->verbose, "[%" SLJIT_PRINT_D "d]", i); - return; - } - - fputc('[', compiler->verbose); - sljit_verbose_reg(compiler, (p) & REG_MASK); - if (p & OFFS_REG_MASK) { - fprintf(compiler->verbose, " + "); - sljit_verbose_reg(compiler, OFFS_REG(p)); - if (i) - fprintf(compiler->verbose, " * %d", 1 << (i)); - } else if (i) - fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i)); - fputc(']', compiler->verbose); -} - static void sljit_verbose_param(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i) { - if (p == SLJIT_IMM) - fprintf(compiler->verbose, "#%" SLJIT_PRINT_D "d", i); - else if (p & SLJIT_MEM) - sljit_verbose_mem(compiler, p, i); - else + if ((p) == SLJIT_IMM) + fprintf(compiler->verbose, "#%" SLJIT_PRINT_D "d", (i)); + else if ((p) & SLJIT_MEM) { + if ((p) & REG_MASK) { + fputc('[', compiler->verbose); + sljit_verbose_reg(compiler, (p) & REG_MASK); + if ((p) & OFFS_REG_MASK) { + fprintf(compiler->verbose, " + "); + sljit_verbose_reg(compiler, OFFS_REG(p)); + if (i) + fprintf(compiler->verbose, " * %d", 1 << (i)); + } + else if (i) + fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i)); + fputc(']', compiler->verbose); + } + else + fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i)); + } else sljit_verbose_reg(compiler, p); } static void sljit_verbose_fparam(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i) { - if (p & SLJIT_MEM) - sljit_verbose_mem(compiler, p, i); + if ((p) & SLJIT_MEM) { + if ((p) & REG_MASK) { + fputc('[', compiler->verbose); + sljit_verbose_reg(compiler, (p) & REG_MASK); + if ((p) & OFFS_REG_MASK) { + fprintf(compiler->verbose, " + "); + sljit_verbose_reg(compiler, OFFS_REG(p)); + if (i) + fprintf(compiler->verbose, "%d", 1 << (i)); + } + else if (i) + fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i)); + fputc(']', compiler->verbose); + } + else + fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i)); + } else sljit_verbose_freg(compiler, p); } -static void sljit_verbose_vparam(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i) -{ - if (p & SLJIT_MEM) - sljit_verbose_mem(compiler, p, i); - else - sljit_verbose_vreg(compiler, p); -} - static const char* op0_names[] = { "breakpoint", "nop", "lmul.uw", "lmul.sw", "divmod.u", "divmod.s", "div.u", "div.s", - "memory_barrier", "endbr", "skip_frames_before_return" + "endbr", "skip_frames_before_return" }; static const char* op1_names[] = { @@ -1288,7 +1184,7 @@ static const char* fop2r_names[] = { }; static const char* simd_op2_names[] = { - "and", "or", "xor", "shuffle" + "and", "or", "xor" }; static const char* jump_names[] = { @@ -1328,13 +1224,12 @@ static const char* call_arg_names[] = { || (defined SLJIT_VERBOSE && SLJIT_VERBOSE) #define SLJIT_SKIP_CHECKS(compiler) (compiler)->skip_checks = 1 -#define SLJIT_CHECK_OPCODE(op, flags) ((op) & ~(SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK | (flags))) static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_generate_code(struct sljit_compiler *compiler) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) struct sljit_jump *jump; -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif SLJIT_UNUSED_ARG(compiler); @@ -1346,7 +1241,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_generate_code(struct sljit_com CHECK_ARGUMENT((jump->flags & JUMP_ADDR) || jump->u.label != NULL); jump = jump->next; } -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif CHECK_RETURN_OK; } @@ -1357,17 +1252,9 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_generate_code(struct sljit_com #endif /* !SLJIT_CONFIG_X86 */ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { -#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - sljit_s32 real_scratches = ENTER_GET_REGS(scratches); - sljit_s32 real_saveds = ENTER_GET_REGS(saveds); - sljit_s32 real_fscratches = ENTER_GET_FLOAT_REGS(scratches); - sljit_s32 real_fsaveds = ENTER_GET_FLOAT_REGS(saveds); - sljit_s32 real_vscratches = ENTER_GET_VECTOR_REGS(scratches); - sljit_s32 real_vsaveds = ENTER_GET_VECTOR_REGS(saveds); -#endif /* SLJIT_ARGUMENT_CHECKS */ SLJIT_UNUSED_ARG(compiler); #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) @@ -1377,23 +1264,18 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compil CHECK_ARGUMENT((options & ~SLJIT_ENTER_CPU_SPECIFIC_OPTIONS) == 0); } CHECK_ARGUMENT(SLJIT_KEPT_SAVEDS_COUNT(options) <= 3 && SLJIT_KEPT_SAVEDS_COUNT(options) <= saveds); - CHECK_ARGUMENT((scratches & ~0xffffff) == 0 && (saveds & ~0xffffff) == 0); - CHECK_ARGUMENT(real_scratches >= 0 && real_scratches <= SLJIT_NUMBER_OF_REGISTERS); - CHECK_ARGUMENT(real_saveds >= 0 && real_saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS); - CHECK_ARGUMENT(real_scratches + real_saveds <= SLJIT_NUMBER_OF_REGISTERS); - CHECK_ARGUMENT(real_fscratches >= 0 && real_fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); - CHECK_ARGUMENT(real_fsaveds >= 0 && real_fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS); - CHECK_ARGUMENT(real_fscratches + real_fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); - CHECK_ARGUMENT(real_vscratches >= 0 && real_vscratches <= SLJIT_NUMBER_OF_VECTOR_REGISTERS); - CHECK_ARGUMENT(real_vsaveds >= 0 && real_vsaveds <= SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS); - CHECK_ARGUMENT(real_vscratches + real_vsaveds <= SLJIT_NUMBER_OF_VECTOR_REGISTERS); + CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS); + CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS); + CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS); + CHECK_ARGUMENT(fscratches >= 0 && fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); + CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS); + CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE); CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) <= SLJIT_ARG_TYPE_F32); - CHECK_ARGUMENT(function_check_arguments(arg_types, real_scratches, - (options & SLJIT_ENTER_REG_ARG) ? 0 : real_saveds, real_fscratches)); + CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, (options & SLJIT_ENTER_REG_ARG) ? 0 : saveds, fscratches)); compiler->last_flags = 0; -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " enter ret[%s", call_arg_names[arg_types & SLJIT_ARG_MASK]); @@ -1425,26 +1307,17 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compil } #endif /* !SLJIT_CONFIG_X86 */ - fprintf(compiler->verbose, " scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, vscratches:%d, vsaveds:%d, local_size:%d\n", - ENTER_GET_REGS(scratches), ENTER_GET_REGS(saveds), ENTER_GET_FLOAT_REGS(scratches), ENTER_GET_FLOAT_REGS(saveds), - ENTER_GET_VECTOR_REGS(scratches), ENTER_GET_VECTOR_REGS(saveds), local_size); + fprintf(compiler->verbose, " scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, local_size:%d\n", + scratches, saveds, fscratches, fsaveds, local_size); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { -#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - sljit_s32 real_scratches = ENTER_GET_REGS(scratches); - sljit_s32 real_saveds = ENTER_GET_REGS(saveds); - sljit_s32 real_fscratches = ENTER_GET_FLOAT_REGS(scratches); - sljit_s32 real_fsaveds = ENTER_GET_FLOAT_REGS(saveds); - sljit_s32 real_vscratches = ENTER_GET_VECTOR_REGS(scratches); - sljit_s32 real_vsaveds = ENTER_GET_VECTOR_REGS(saveds); -#endif /* SLJIT_ARGUMENT_CHECKS */ SLJIT_UNUSED_ARG(compiler); #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) @@ -1454,23 +1327,18 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compi CHECK_ARGUMENT((options & ~SLJIT_ENTER_CPU_SPECIFIC_OPTIONS) == 0); } CHECK_ARGUMENT(SLJIT_KEPT_SAVEDS_COUNT(options) <= 3 && SLJIT_KEPT_SAVEDS_COUNT(options) <= saveds); - CHECK_ARGUMENT((scratches & ~0xffffff) == 0 && (saveds & ~0xffffff) == 0); - CHECK_ARGUMENT(real_scratches >= 0 && real_scratches <= SLJIT_NUMBER_OF_REGISTERS); - CHECK_ARGUMENT(real_saveds >= 0 && real_saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS); - CHECK_ARGUMENT(real_scratches + real_saveds <= SLJIT_NUMBER_OF_REGISTERS); - CHECK_ARGUMENT(real_fscratches >= 0 && real_fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); - CHECK_ARGUMENT(real_fsaveds >= 0 && real_fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS); - CHECK_ARGUMENT(real_fscratches + real_fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); - CHECK_ARGUMENT(real_vscratches >= 0 && real_vscratches <= SLJIT_NUMBER_OF_VECTOR_REGISTERS); - CHECK_ARGUMENT(real_vsaveds >= 0 && real_vsaveds <= SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS); - CHECK_ARGUMENT(real_vscratches + real_vsaveds <= SLJIT_NUMBER_OF_VECTOR_REGISTERS); + CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS); + CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS); + CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS); + CHECK_ARGUMENT(fscratches >= 0 && fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); + CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS); + CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE); CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) < SLJIT_ARG_TYPE_F64); - CHECK_ARGUMENT(function_check_arguments(arg_types, real_scratches, - (options & SLJIT_ENTER_REG_ARG) ? 0 : real_saveds, real_fscratches)); + CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, (options & SLJIT_ENTER_REG_ARG) ? 0 : saveds, fscratches)); compiler->last_flags = 0; -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " set_context ret[%s", call_arg_names[arg_types & SLJIT_ARG_MASK]); @@ -1502,11 +1370,10 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compi } #endif /* !SLJIT_CONFIG_X86 */ - fprintf(compiler->verbose, " scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, vscratches:%d, vsaveds:%d, local_size:%d\n", - ENTER_GET_REGS(scratches), ENTER_GET_REGS(saveds), ENTER_GET_FLOAT_REGS(scratches), ENTER_GET_FLOAT_REGS(saveds), - ENTER_GET_VECTOR_REGS(scratches), ENTER_GET_VECTOR_REGS(saveds), local_size); + fprintf(compiler->verbose, " scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, local_size:%d\n", + scratches, saveds, fscratches, fsaveds, local_size); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -1521,13 +1388,13 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return_void(struct sljit_ #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(compiler->last_return == SLJIT_ARG_TYPE_RET_VOID); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " return_void\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -1560,13 +1427,13 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return(struct sljit_compi break; } - if (SLJIT_CHECK_OPCODE(op, 0) < SLJIT_MOV_F64) { + if (GET_OPCODE(op) < SLJIT_MOV_F64) { FUNCTION_CHECK_SRC(src, srcw); } else { FUNCTION_FCHECK(src, srcw, op & SLJIT_32); } compiler->last_flags = 0; -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { if (GET_OPCODE(op) < SLJIT_MOV_F64) { @@ -1579,7 +1446,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return(struct sljit_compi } fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -1588,14 +1455,14 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return_to(struct sljit_co { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) FUNCTION_CHECK_SRC(src, srcw); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " return_to "); sljit_verbose_param(compiler, src, srcw); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -1604,11 +1471,11 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op0(struct sljit_compiler #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT((op >= SLJIT_BREAKPOINT && op <= SLJIT_LMUL_SW) || ((op & ~SLJIT_32) >= SLJIT_DIVMOD_UW && (op & ~SLJIT_32) <= SLJIT_DIV_SW) - || (op >= SLJIT_MEMORY_BARRIER && op <= SLJIT_SKIP_FRAMES_BEFORE_RETURN)); - CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) < SLJIT_LMUL_UW || SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_MEMORY_BARRIER || compiler->scratches >= 2); - if ((SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_LMUL_UW && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_DIV_SW) || op == SLJIT_SKIP_FRAMES_BEFORE_RETURN) + || (op >= SLJIT_ENDBR && op <= SLJIT_SKIP_FRAMES_BEFORE_RETURN)); + CHECK_ARGUMENT(GET_OPCODE(op) < SLJIT_LMUL_UW || GET_OPCODE(op) >= SLJIT_ENDBR || compiler->scratches >= 2); + if ((GET_OPCODE(op) >= SLJIT_LMUL_UW && GET_OPCODE(op) <= SLJIT_DIV_SW) || op == SLJIT_SKIP_FRAMES_BEFORE_RETURN) compiler->last_flags = 0; -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { @@ -1618,7 +1485,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op0(struct sljit_compiler } fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -1632,7 +1499,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_MOV && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_REV_S32); + CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_REV_S32); switch (GET_OPCODE(op)) { case SLJIT_MOV: @@ -1653,7 +1520,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler FUNCTION_CHECK_DST(dst, dstw); FUNCTION_CHECK_SRC(src, srcw); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s%s%s ", op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE], @@ -1664,7 +1531,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler sljit_verbose_param(compiler, src, srcw); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -1679,37 +1546,26 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_atomic_load(struct sljit_ #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_ATOMIC)); - CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, SLJIT_ATOMIC_TEST | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS | SLJIT_SET_Z | VARIABLE_FLAG_MASK) >= SLJIT_MOV - && SLJIT_CHECK_OPCODE(op, SLJIT_ATOMIC_TEST | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS | SLJIT_SET_Z | VARIABLE_FLAG_MASK) <= SLJIT_MOV_P); - CHECK_ARGUMENT((op & (SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS)) != (SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS)); + CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOV_P); + CHECK_ARGUMENT(GET_OPCODE(op) != SLJIT_MOV_S8 && GET_OPCODE(op) != SLJIT_MOV_S16 && GET_OPCODE(op) != SLJIT_MOV_S32); /* All arguments must be valid registers. */ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg)); CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(mem_reg) && !CHECK_IF_VIRTUAL_REGISTER(mem_reg)); - if (GET_OPCODE(op) < SLJIT_MOV_U8 || GET_OPCODE(op) > SLJIT_MOV_S16) { + if (op == SLJIT_MOV32_U8 || op == SLJIT_MOV32_U16) { + /* Only SLJIT_32 is allowed. */ + CHECK_ARGUMENT(!(op & (VARIABLE_FLAG_MASK | SLJIT_SET_Z))); + } else { /* Nothing allowed. */ - CHECK_ARGUMENT(!(op & SLJIT_32)); + CHECK_ARGUMENT(!(op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK))); } compiler->last_flags = 0; #endif /* SLJIT_ARGUMENT_CHECKS */ #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - if (op & SLJIT_ATOMIC_TEST) - CHECK_RETURN_OK; - if (sljit_emit_atomic_load(compiler, op | SLJIT_ATOMIC_TEST, dst_reg, mem_reg)) { - fprintf(compiler->verbose, " # atomic_load: unsupported form, no instructions are emitted\n"); - CHECK_RETURN_OK; - } - - fprintf(compiler->verbose, " atomic_load"); - if (op & SLJIT_ATOMIC_USE_CAS) - fprintf(compiler->verbose, "_cas"); - if (op & SLJIT_ATOMIC_USE_LS) - fprintf(compiler->verbose, "_ls"); - - fprintf(compiler->verbose, "%s%s ", !(op & SLJIT_32) ? "" : "32", + fprintf(compiler->verbose, " atomic_load%s%s ", !(op & SLJIT_32) ? "" : "32", op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE]); sljit_verbose_reg(compiler, dst_reg); fprintf(compiler->verbose, ", ["); @@ -1732,40 +1588,29 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_atomic_store(struct sljit #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_ATOMIC)); - CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, SLJIT_ATOMIC_TEST | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS | SLJIT_SET_Z) >= SLJIT_MOV - && SLJIT_CHECK_OPCODE(op, SLJIT_ATOMIC_TEST | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS | SLJIT_SET_Z) <= SLJIT_MOV_P); - CHECK_ARGUMENT((op & (SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS)) != (SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS)); + CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOV_P); + CHECK_ARGUMENT(GET_OPCODE(op) != SLJIT_MOV_S8 && GET_OPCODE(op) != SLJIT_MOV_S16 && GET_OPCODE(op) != SLJIT_MOV_S32); /* All arguments must be valid registers. */ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src_reg)); CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(mem_reg) && !CHECK_IF_VIRTUAL_REGISTER(mem_reg)); - CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(temp_reg) && (src_reg != temp_reg || (op & SLJIT_ATOMIC_USE_LS))); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(temp_reg) && src_reg != temp_reg); - CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK) || GET_FLAG_TYPE_MASK(op) == SLJIT_ATOMIC_STORED); + CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK) || GET_FLAG_TYPE(op) == SLJIT_ATOMIC_STORED); - if (GET_OPCODE(op) < SLJIT_MOV_U8 || GET_OPCODE(op) > SLJIT_MOV_S16) { - /* Nothing allowed. */ - CHECK_ARGUMENT(!(op & SLJIT_32)); + if (GET_OPCODE(op) == SLJIT_MOV_U8 || GET_OPCODE(op) == SLJIT_MOV_U16) { + /* Only SLJIT_32, SLJIT_ATOMIC_STORED are allowed. */ + CHECK_ARGUMENT(!(op & SLJIT_SET_Z)); + } else { + /* Only SLJIT_ATOMIC_STORED is allowed. */ + CHECK_ARGUMENT(!(op & (SLJIT_32 | SLJIT_SET_Z))); } - compiler->last_flags = GET_FLAG_TYPE_MASK(op) | (op & SLJIT_32); + compiler->last_flags = GET_FLAG_TYPE(op) | (op & SLJIT_32); #endif /* SLJIT_ARGUMENT_CHECKS */ #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - if (op & SLJIT_ATOMIC_TEST) - CHECK_RETURN_OK; - if (sljit_emit_atomic_store(compiler, op | SLJIT_ATOMIC_TEST, src_reg, mem_reg, temp_reg)) { - fprintf(compiler->verbose, " # atomic_store: unsupported form, no instructions are emitted\n"); - CHECK_RETURN_OK; - } - - fprintf(compiler->verbose, " atomic_store"); - if (op & SLJIT_ATOMIC_USE_CAS) - fprintf(compiler->verbose, "_cas"); - if (op & SLJIT_ATOMIC_USE_LS) - fprintf(compiler->verbose, "_ls"); - - fprintf(compiler->verbose, "%s%s%s ", !(op & SLJIT_32) ? "" : "32", + fprintf(compiler->verbose, " atomic_store%s%s%s ", !(op & SLJIT_32) ? "" : "32", op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE], !(op & VARIABLE_FLAG_MASK) ? "" : ".stored"); sljit_verbose_reg(compiler, src_reg); fprintf(compiler->verbose, ", ["); @@ -1789,7 +1634,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_ADD && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_ROTR); + CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD && GET_OPCODE(op) <= SLJIT_ROTR); switch (GET_OPCODE(op)) { case SLJIT_AND: @@ -1842,7 +1687,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler FUNCTION_CHECK_SRC(src1, src1w); FUNCTION_CHECK_SRC(src2, src2w); compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_32 | SLJIT_SET_Z)); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s%s%s%s%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_32) ? "" : "32", @@ -1858,7 +1703,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler sljit_verbose_param(compiler, src2, src2w); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -1873,7 +1718,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2r(struct sljit_compile FUNCTION_CHECK_SRC(src1, src1w); FUNCTION_CHECK_SRC(src2, src2w); compiler->last_flags = 0; -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s%s ", op2r_names[GET_OPCODE(op) - SLJIT_OP2R_BASE], !(op & SLJIT_32) ? "" : "32"); @@ -1885,7 +1730,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2r(struct sljit_compile sljit_verbose_param(compiler, src2, src2w); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -1896,15 +1741,15 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_shift_into(struct sljit_c sljit_s32 src3, sljit_sw src3w) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) == SLJIT_SHL || SLJIT_CHECK_OPCODE(op, 0) == SLJIT_LSHR - || SLJIT_CHECK_OPCODE(op, 0) == SLJIT_MSHL || SLJIT_CHECK_OPCODE(op, 0) == SLJIT_MLSHR); + CHECK_ARGUMENT(GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_LSHR + || GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR); CHECK_ARGUMENT((op & ~(0xff | SLJIT_32 | SLJIT_SHIFT_INTO_NON_ZERO)) == 0); CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg)); CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src1_reg)); CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src2_reg)); FUNCTION_CHECK_SRC(src3, src3w); CHECK_ARGUMENT(dst_reg != src2_reg); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s%s.into%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_32) ? "" : "32", @@ -1919,7 +1764,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_shift_into(struct sljit_c sljit_verbose_param(compiler, src3, src3w); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -1936,14 +1781,14 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_src(struct sljit_compi } else if (op >= SLJIT_PREFETCH_L1 && op <= SLJIT_PREFETCH_ONCE) { CHECK_ARGUMENT(src & SLJIT_MEM); } -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s ", op_src_dst_names[op - SLJIT_OP_SRC_DST_BASE]); sljit_verbose_param(compiler, src, srcw); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -1956,14 +1801,14 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_dst(struct sljit_compi if (op == SLJIT_FAST_ENTER) compiler->last_flags = 0; -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s ", op_src_dst_names[op - SLJIT_OP_SRC_DST_BASE]); sljit_verbose_param(compiler, dst, dstw); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -1975,19 +1820,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_register_index(sljit_s32 t if (type == SLJIT_GP_REGISTER) { CHECK_ARGUMENT((reg > 0 && reg <= SLJIT_NUMBER_OF_REGISTERS) || (reg >= SLJIT_TMP_REGISTER_BASE && reg < (SLJIT_TMP_REGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_REGISTERS))); - } -#if (defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS) - else if (((type >> 12) == 0 || ((type >> 12) >= 3 && (type >> 12) <= 6))) { - CHECK_ARGUMENT((reg > 0 && reg <= SLJIT_NUMBER_OF_VECTOR_REGISTERS) - || (reg >= SLJIT_TMP_VREGISTER_BASE && reg < (SLJIT_TMP_VREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS))); - } -#endif /* SLJIT_SEPARATE_VECTOR_REGISTERS */ - else { - CHECK_ARGUMENT(type == SLJIT_FLOAT_REGISTER || ((type >> 12) == 0 || ((type >> 12) >= 3 && (type >> 12) <= 6) || (type & (3 << 12)) || (type & (4 << 12)) || (type & (5 << 12)) || (type & (6 << 12)))); + } else { + CHECK_ARGUMENT(type == SLJIT_FLOAT_REGISTER || ((type >> 12) == 0 || ((type >> 12) >= 3 && (type >> 12) <= 6))); CHECK_ARGUMENT((reg > 0 && reg <= SLJIT_NUMBER_OF_FLOAT_REGISTERS) || (reg >= SLJIT_TMP_FREGISTER_BASE && reg < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS))); } -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif CHECK_RETURN_OK; } @@ -1996,7 +1834,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_custom(struct sljit_co { #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) sljit_u32 i; -#endif /* SLJIT_VERBOSE */ +#endif SLJIT_UNUSED_ARG(compiler); @@ -2010,12 +1848,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_custom(struct sljit_co || (size == 4 && (((sljit_sw)instruction) & 0x3) == 0)); #elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) CHECK_ARGUMENT(size == 2 || size == 4 || size == 6); -#else /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_ARM_THUMB2 && !SLJIT_CONFIG_S390X */ +#else CHECK_ARGUMENT(size == 4 && (((sljit_sw)instruction) & 0x3) == 0); -#endif /* SLJIT_CONFIG_X86 */ +#endif compiler->last_flags = 0; -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " op_custom"); @@ -2023,7 +1861,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_custom(struct sljit_co fprintf(compiler->verbose, " 0x%x", ((sljit_u8*)instruction)[i]); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2038,11 +1876,11 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1(struct sljit_compile #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); - CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_MOV_F64 && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_ABS_F64); + CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV_F64 && GET_OPCODE(op) <= SLJIT_ABS_F64); CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); FUNCTION_FCHECK(src, srcw, op & SLJIT_32); FUNCTION_FCHECK(dst, dstw, op & SLJIT_32); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) @@ -2057,7 +1895,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1(struct sljit_compile sljit_verbose_fparam(compiler, src, srcw); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2067,7 +1905,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_cmp(struct sljit_com { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->last_flags = GET_FLAG_TYPE(op) | (op & SLJIT_32); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif if (SLJIT_UNLIKELY(compiler->skip_checks)) { compiler->skip_checks = 0; @@ -2076,13 +1914,13 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_cmp(struct sljit_com #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); - CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) == SLJIT_CMP_F64); + CHECK_ARGUMENT(GET_OPCODE(op) == SLJIT_CMP_F64); CHECK_ARGUMENT(!(op & SLJIT_SET_Z)); CHECK_ARGUMENT((op & VARIABLE_FLAG_MASK) || (GET_FLAG_TYPE(op) >= SLJIT_F_EQUAL && GET_FLAG_TYPE(op) <= SLJIT_ORDERED_LESS_EQUAL)); FUNCTION_FCHECK(src1, src1w, op & SLJIT_32); FUNCTION_FCHECK(src2, src2w, op & SLJIT_32); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s%s", fop1_names[SLJIT_CMP_F64 - SLJIT_FOP1_BASE], (op & SLJIT_32) ? ".f32" : ".f64"); @@ -2095,7 +1933,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_cmp(struct sljit_com sljit_verbose_fparam(compiler, src2, src2w); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2113,7 +1951,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_sw_from_f64(str CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); FUNCTION_FCHECK(src, srcw, op & SLJIT_32); FUNCTION_CHECK_DST(dst, dstw); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s%s.from%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE], @@ -2124,7 +1962,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_sw_from_f64(str sljit_verbose_fparam(compiler, src, srcw); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2142,7 +1980,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_f64_from_w(stru CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); FUNCTION_CHECK_SRC(src, srcw); FUNCTION_FCHECK(dst, dstw, op & SLJIT_32); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s%s.from.%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE], @@ -2153,7 +1991,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_f64_from_w(stru sljit_verbose_param(compiler, src, srcw); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2169,12 +2007,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2(struct sljit_compile #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); - CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_ADD_F64 && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_DIV_F64); + CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD_F64 && GET_OPCODE(op) <= SLJIT_DIV_F64); CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); FUNCTION_FCHECK(src1, src1w, op & SLJIT_32); FUNCTION_FCHECK(src2, src2w, op & SLJIT_32); FUNCTION_FCHECK(dst, dstw, op & SLJIT_32); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s%s ", fop2_names[GET_OPCODE(op) - SLJIT_FOP2_BASE], (op & SLJIT_32) ? ".f32" : ".f64"); @@ -2185,7 +2023,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2(struct sljit_compile sljit_verbose_fparam(compiler, src2, src2w); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2196,11 +2034,11 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2r(struct sljit_compil { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); - CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) == SLJIT_COPYSIGN_F64); + CHECK_ARGUMENT(GET_OPCODE(op) == SLJIT_COPYSIGN_F64); FUNCTION_FCHECK(src1, src1w, op & SLJIT_32); FUNCTION_FCHECK(src2, src2w, op & SLJIT_32); CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(dst_freg, op & SLJIT_32)); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s%s ", fop2r_names[GET_OPCODE(op) - SLJIT_FOP2R_BASE], (op & SLJIT_32) ? ".f32" : ".f64"); @@ -2211,7 +2049,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2r(struct sljit_compil sljit_verbose_fparam(compiler, src2, src2w); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2228,14 +2066,14 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fset32(struct sljit_compi #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 1)); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " fset32 "); sljit_verbose_freg(compiler, freg); fprintf(compiler->verbose, ", %f\n", value); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2252,14 +2090,14 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fset64(struct sljit_compi #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0)); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " fset64 "); sljit_verbose_freg(compiler, freg); fprintf(compiler->verbose, ", %f\n", value); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2268,7 +2106,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcopy(struct sljit_compil { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); - CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_COPY_TO_F64 && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_COPY_FROM_F64); + CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_COPY_TO_F64 && GET_OPCODE(op) <= SLJIT_COPY_FROM_F64); CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, op & SLJIT_32)); @@ -2297,7 +2135,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcopy(struct sljit_compil break; } #endif /* SLJIT_64BIT_ARCHITECTURE */ -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " copy%s_%s_f%s ", (op & SLJIT_32) ? "32" : "", @@ -2317,7 +2155,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcopy(struct sljit_compil fprintf(compiler->verbose, "\n"); } } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2332,12 +2170,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_label(struct sljit_compil #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->last_flags = 0; -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) fprintf(compiler->verbose, "label:\n"); -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2347,9 +2185,9 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_label(struct sljit_compil #define CHECK_UNORDERED(type, last_flags) \ ((((type) & 0xfe) == SLJIT_ORDERED) && \ ((last_flags) & 0xff) >= SLJIT_UNORDERED && ((last_flags) & 0xff) <= SLJIT_ORDERED_LESS_EQUAL) -#else /* !SLJIT_CONFIG_X86 || SLJIT_CONFIG_ARM */ +#else #define CHECK_UNORDERED(type, last_flags) 0 -#endif /* SLJIT_CONFIG_X86 || SLJIT_CONFIG_ARM */ +#endif #endif /* SLJIT_ARGUMENT_CHECKS */ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type) @@ -2373,12 +2211,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_jump(struct sljit_compile CHECK_ARGUMENT((type & 0xfe) == (compiler->last_flags & 0xff) || CHECK_UNORDERED(type, compiler->last_flags)); } -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) fprintf(compiler->verbose, " jump%s %s\n", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff]); -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2399,7 +2237,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_call(struct sljit_compile CHECK_ARGUMENT((type & 0xff) != SLJIT_CALL_REG_ARG); } } -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s%s%s ret[%s", jump_names[type & 0xff], @@ -2419,7 +2257,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_call(struct sljit_compile } fprintf(compiler->verbose, "]\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2433,7 +2271,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmp(struct sljit_compiler FUNCTION_CHECK_SRC(src1, src1w); FUNCTION_CHECK_SRC(src2, src2w); compiler->last_flags = 0; -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " cmp%s%s %s, ", (type & SLJIT_32) ? "32" : "", @@ -2443,7 +2281,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmp(struct sljit_compiler sljit_verbose_param(compiler, src2, src2w); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2458,7 +2296,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcmp(struct sljit_compile FUNCTION_FCHECK(src1, src1w, type & SLJIT_32); FUNCTION_FCHECK(src2, src2w, type & SLJIT_32); compiler->last_flags = 0; -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " fcmp%s%s %s, ", (type & SLJIT_32) ? ".f32" : ".f64", @@ -2468,7 +2306,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcmp(struct sljit_compile sljit_verbose_fparam(compiler, src2, src2w); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2483,14 +2321,14 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_ijump(struct sljit_compil #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(type >= SLJIT_JUMP && type <= SLJIT_FAST_CALL); FUNCTION_CHECK_SRC(src, srcw); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " ijump.%s ", jump_names[type]); sljit_verbose_param(compiler, src, srcw); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2513,7 +2351,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_icall(struct sljit_compil CHECK_ARGUMENT((type & 0xff) != SLJIT_CALL_REG_ARG); } } -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " i%s%s ret[%s", jump_names[type & 0xff], @@ -2534,7 +2372,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_icall(struct sljit_compil sljit_verbose_param(compiler, src, srcw); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2545,7 +2383,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_com #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(type >= SLJIT_EQUAL && type <= SLJIT_ORDERED_LESS_EQUAL); CHECK_ARGUMENT(op == SLJIT_MOV || op == SLJIT_MOV32 - || (SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_AND && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_XOR)); + || (GET_OPCODE(op) >= SLJIT_AND && GET_OPCODE(op) <= SLJIT_XOR)); CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)); if (type <= SLJIT_NOT_ZERO) @@ -2558,7 +2396,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_com if (GET_OPCODE(op) >= SLJIT_ADD) compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_32 | SLJIT_SET_Z)); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " flags.%s%s%s ", @@ -2568,7 +2406,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_com sljit_verbose_param(compiler, dst, dstw); fprintf(compiler->verbose, ", %s\n", jump_names[type]); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2595,7 +2433,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_select(struct sljit_compi } else CHECK_ARGUMENT((cond & 0xfe) == (compiler->last_flags & 0xff) || CHECK_UNORDERED(cond, compiler->last_flags)); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " select%s %s, ", @@ -2608,7 +2446,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_select(struct sljit_compi sljit_verbose_reg(compiler, src2_reg); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2635,7 +2473,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fselect(struct sljit_comp } else CHECK_ARGUMENT((cond & 0xfe) == (compiler->last_flags & 0xff) || CHECK_UNORDERED(cond, compiler->last_flags)); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " fselect%s %s, ", @@ -2648,7 +2486,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fselect(struct sljit_comp sljit_verbose_freg(compiler, src2_freg); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2702,7 +2540,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler } FUNCTION_CHECK_SRC_MEM(mem, memw); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { if ((type & 0xff) == SLJIT_MOV32) @@ -2734,7 +2572,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler sljit_verbose_param(compiler, mem, memw); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2753,7 +2591,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem_update(struct sljit_c CHECK_ARGUMENT((mem & REG_MASK) != 0 && (mem & REG_MASK) != reg); FUNCTION_CHECK_SRC_MEM(mem, memw); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { if (type & SLJIT_MEM_SUPP) @@ -2779,7 +2617,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem_update(struct sljit_c sljit_verbose_param(compiler, mem, memw); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2803,7 +2641,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem(struct sljit_compile CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32))); CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, type & SLJIT_32)); FUNCTION_CHECK_SRC_MEM(mem, memw); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s.%s", @@ -2823,7 +2661,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem(struct sljit_compile sljit_verbose_param(compiler, mem, memw); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -2837,7 +2675,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem_update(struct sljit_ CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_POST)) == 0); FUNCTION_CHECK_SRC_MEM(mem, memw); CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, type & SLJIT_32)); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { if (type & SLJIT_MEM_SUPP) @@ -2857,12 +2695,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem_update(struct sljit_ sljit_verbose_param(compiler, mem, memw); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 srcdst, sljit_sw srcdstw) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) @@ -2871,14 +2709,14 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_mov(struct sljit_com CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type)); CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) <= SLJIT_SIMD_GET_REG_SIZE(type)); CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM2_SIZE(type) <= (srcdst & SLJIT_MEM) ? SLJIT_SIMD_GET_REG_SIZE(type) : 0); - CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(vreg, type)); - FUNCTION_VCHECK(srcdst, srcdstw, type); -#endif /* SLJIT_ARGUMENT_CHECKS */ + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0)); + FUNCTION_FCHECK(srcdst, srcdstw, 0); +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { if (type & SLJIT_SIMD_TEST) CHECK_RETURN_OK; - if (sljit_emit_simd_mov(compiler, type | SLJIT_SIMD_TEST, vreg, srcdst, srcdstw) == SLJIT_ERR_UNSUPPORTED) { + if (sljit_emit_simd_mov(compiler, type | SLJIT_SIMD_TEST, freg, srcdst, srcdstw) == SLJIT_ERR_UNSUPPORTED) { fprintf(compiler->verbose, " # simd_mem: unsupported form, no instructions are emitted\n"); CHECK_RETURN_OK; } @@ -2894,17 +2732,17 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_mov(struct sljit_com else fprintf(compiler->verbose, ".al%d ", (8 << SLJIT_SIMD_GET_ELEM2_SIZE(type))); - sljit_verbose_vreg(compiler, vreg); + sljit_verbose_freg(compiler, freg); fprintf(compiler->verbose, ", "); - sljit_verbose_vparam(compiler, srcdst, srcdstw); + sljit_verbose_fparam(compiler, srcdst, srcdstw); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_sw srcw) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) @@ -2912,7 +2750,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_replicate(struct slj CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(0)) == 0); CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type)); CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type)); - CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(vreg, type)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0)); if (type & SLJIT_SIMD_FLOAT) { if (src == SLJIT_IMM) { @@ -2923,12 +2761,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_replicate(struct slj } else if (src != SLJIT_IMM) { FUNCTION_CHECK_DST(src, srcw); } -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { if (type & SLJIT_SIMD_TEST) CHECK_RETURN_OK; - if (sljit_emit_simd_replicate(compiler, type | SLJIT_SIMD_TEST, vreg, src, srcw) == SLJIT_ERR_UNSUPPORTED) { + if (sljit_emit_simd_replicate(compiler, type | SLJIT_SIMD_TEST, freg, src, srcw) == SLJIT_ERR_UNSUPPORTED) { fprintf(compiler->verbose, " # simd_dup: unsupported form, no instructions are emitted\n"); CHECK_RETURN_OK; } @@ -2938,7 +2776,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_replicate(struct slj (type & SLJIT_SIMD_FLOAT) ? "f" : "", (8 << SLJIT_SIMD_GET_ELEM_SIZE(type))); - sljit_verbose_vreg(compiler, vreg); + sljit_verbose_freg(compiler, freg); fprintf(compiler->verbose, ", "); if (type & SLJIT_SIMD_FLOAT) sljit_verbose_fparam(compiler, src, srcw); @@ -2946,12 +2784,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_replicate(struct slj sljit_verbose_param(compiler, src, srcw); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, sljit_s32 lane_index, + sljit_s32 freg, sljit_s32 lane_index, sljit_s32 srcdst, sljit_sw srcdstw) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) @@ -2963,7 +2801,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_lane_mov(struct slji CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type)); CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type)); CHECK_ARGUMENT(!(type & SLJIT_32) || SLJIT_SIMD_GET_ELEM_SIZE(type) <= 2); - CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(vreg, type)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0)); CHECK_ARGUMENT(lane_index >= 0 && lane_index < (1 << (SLJIT_SIMD_GET_REG_SIZE(type) - SLJIT_SIMD_GET_ELEM_SIZE(type)))); if (type & SLJIT_SIMD_FLOAT) { @@ -2971,12 +2809,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_lane_mov(struct slji } else if ((type & SLJIT_SIMD_STORE) || srcdst != SLJIT_IMM) { FUNCTION_CHECK_DST(srcdst, srcdstw); } -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { if (type & SLJIT_SIMD_TEST) CHECK_RETURN_OK; - if (sljit_emit_simd_lane_mov(compiler, type | SLJIT_SIMD_TEST, vreg, lane_index, srcdst, srcdstw) == SLJIT_ERR_UNSUPPORTED) { + if (sljit_emit_simd_lane_mov(compiler, type | SLJIT_SIMD_TEST, freg, lane_index, srcdst, srcdstw) == SLJIT_ERR_UNSUPPORTED) { fprintf(compiler->verbose, " # simd_move_lane: unsupported form, no instructions are emitted\n"); CHECK_RETURN_OK; } @@ -2990,7 +2828,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_lane_mov(struct slji (type & SLJIT_SIMD_FLOAT) ? "f" : "", (8 << SLJIT_SIMD_GET_ELEM_SIZE(type))); - sljit_verbose_vreg(compiler, vreg); + sljit_verbose_freg(compiler, freg); fprintf(compiler->verbose, "[%d], ", lane_index); if (type & SLJIT_SIMD_FLOAT) sljit_verbose_fparam(compiler, srcdst, srcdstw); @@ -2998,12 +2836,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_lane_mov(struct slji sljit_verbose_param(compiler, srcdst, srcdstw); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_s32 src_lane_index) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) @@ -3011,15 +2849,15 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_lane_replicate(struc CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(0)) == 0); CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type)); CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type)); - CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(vreg, type)); - CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(src, type)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(src, 0)); CHECK_ARGUMENT(src_lane_index >= 0 && src_lane_index < (1 << (SLJIT_SIMD_GET_REG_SIZE(type) - SLJIT_SIMD_GET_ELEM_SIZE(type)))); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { if (type & SLJIT_SIMD_TEST) CHECK_RETURN_OK; - if (sljit_emit_simd_lane_replicate(compiler, type | SLJIT_SIMD_TEST, vreg, src, src_lane_index) == SLJIT_ERR_UNSUPPORTED) { + if (sljit_emit_simd_lane_replicate(compiler, type | SLJIT_SIMD_TEST, freg, src, src_lane_index) == SLJIT_ERR_UNSUPPORTED) { fprintf(compiler->verbose, " # simd_lane_replicate: unsupported form, no instructions are emitted\n"); CHECK_RETURN_OK; } @@ -3029,17 +2867,17 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_lane_replicate(struc (type & SLJIT_SIMD_FLOAT) ? "f" : "", (8 << SLJIT_SIMD_GET_ELEM_SIZE(type))); - sljit_verbose_vreg(compiler, vreg); + sljit_verbose_freg(compiler, freg); fprintf(compiler->verbose, ", "); - sljit_verbose_vreg(compiler, src); + sljit_verbose_freg(compiler, src); fprintf(compiler->verbose, "[%d]\n", src_lane_index); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_sw srcw) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) @@ -3049,14 +2887,14 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_extend(struct sljit_ CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type)); CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM2_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type)); CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_ELEM2_SIZE(type)); - CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(vreg, type)); - FUNCTION_VCHECK(src, srcw, type); -#endif /* SLJIT_ARGUMENT_CHECKS */ + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0)); + FUNCTION_FCHECK(src, srcw, SLJIT_SIMD_GET_ELEM_SIZE(type) == 2); +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { if (type & SLJIT_SIMD_TEST) CHECK_RETURN_OK; - if (sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_TEST, vreg, src, srcw) == SLJIT_ERR_UNSUPPORTED) { + if (sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_TEST, freg, src, srcw) == SLJIT_ERR_UNSUPPORTED) { fprintf(compiler->verbose, " # simd_extend: unsupported form, no instructions are emitted\n"); CHECK_RETURN_OK; } @@ -3069,17 +2907,17 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_extend(struct sljit_ (type & SLJIT_SIMD_FLOAT) ? "f" : "", (8 << SLJIT_SIMD_GET_ELEM_SIZE(type))); - sljit_verbose_vreg(compiler, vreg); + sljit_verbose_freg(compiler, freg); fprintf(compiler->verbose, ", "); - sljit_verbose_vparam(compiler, src, srcw); + sljit_verbose_fparam(compiler, src, srcw); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 dst, sljit_sw dstw) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) @@ -3087,14 +2925,14 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_sign(struct sljit_co CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(SLJIT_32)) == SLJIT_SIMD_STORE); CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type)); CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type)); - CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(vreg, type)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0)); FUNCTION_CHECK_DST(dst, dstw); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { if (type & SLJIT_SIMD_TEST) CHECK_RETURN_OK; - if (sljit_emit_simd_sign(compiler, type | SLJIT_SIMD_TEST, vreg, dst, dstw) == SLJIT_ERR_UNSUPPORTED) { + if (sljit_emit_simd_sign(compiler, type | SLJIT_SIMD_TEST, freg, dst, dstw) == SLJIT_ERR_UNSUPPORTED) { fprintf(compiler->verbose, " # simd_sign: unsupported form, no instructions are emitted\n"); CHECK_RETURN_OK; } @@ -3105,56 +2943,50 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_sign(struct sljit_co (type & SLJIT_SIMD_FLOAT) ? "f" : "", (8 << SLJIT_SIMD_GET_ELEM_SIZE(type))); - sljit_verbose_vreg(compiler, vreg); + sljit_verbose_freg(compiler, freg); fprintf(compiler->verbose, ", "); sljit_verbose_param(compiler, dst, dstw); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w) + sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD)); - CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK2(0)) >= SLJIT_SIMD_OP2_AND && (type & SLJIT_SIMD_TYPE_MASK2(0)) <= SLJIT_SIMD_OP2_SHUFFLE); + CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(0)) >= SLJIT_SIMD_OP2_AND && (type & SLJIT_SIMD_TYPE_MASK(0)) <= SLJIT_SIMD_OP2_XOR); CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type)); CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) <= SLJIT_SIMD_GET_REG_SIZE(type)); - CHECK_ARGUMENT(SLJIT_SIMD_GET_OPCODE(type) != SLJIT_SIMD_OP2_SHUFFLE || (SLJIT_SIMD_GET_ELEM_SIZE(type) == 0 && !(type & SLJIT_SIMD_FLOAT))); - CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM2_SIZE(type) <= (src2 & SLJIT_MEM) ? SLJIT_SIMD_GET_REG_SIZE(type) : 0); - CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(dst_vreg, type)); - CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(src1_vreg, type)); - FUNCTION_VCHECK(src2, src2w, type); -#endif /* SLJIT_ARGUMENT_CHECKS */ + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(dst_freg, 0)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(src1_freg, 0)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(src2_freg, 0)); +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { if (type & SLJIT_SIMD_TEST) CHECK_RETURN_OK; - if (sljit_emit_simd_op2(compiler, type | SLJIT_SIMD_TEST, dst_vreg, src1_vreg, src2, src2w) == SLJIT_ERR_UNSUPPORTED) { + if (sljit_emit_simd_op2(compiler, type | SLJIT_SIMD_TEST, dst_freg, src1_freg, src2_freg) == SLJIT_ERR_UNSUPPORTED) { fprintf(compiler->verbose, " # simd_op2: unsupported form, no instructions are emitted\n"); CHECK_RETURN_OK; } - fprintf(compiler->verbose, " simd_%s.%d.%s%d", + fprintf(compiler->verbose, " simd_%s.%d.%s%d ", simd_op2_names[SLJIT_SIMD_GET_OPCODE(type) - 1], (8 << SLJIT_SIMD_GET_REG_SIZE(type)), (type & SLJIT_SIMD_FLOAT) ? "f" : "", (8 << SLJIT_SIMD_GET_ELEM_SIZE(type))); - if ((type & 0x3f000000) != SLJIT_SIMD_MEM_UNALIGNED) - fprintf(compiler->verbose, ".al%d", (8 << SLJIT_SIMD_GET_ELEM2_SIZE(type))); - - fprintf(compiler->verbose, " "); - sljit_verbose_vreg(compiler, dst_vreg); + sljit_verbose_freg(compiler, dst_freg); fprintf(compiler->verbose, ", "); - sljit_verbose_vreg(compiler, src1_vreg); + sljit_verbose_freg(compiler, src1_freg); fprintf(compiler->verbose, ", "); - sljit_verbose_vparam(compiler, src2, src2w); + sljit_verbose_freg(compiler, src2_freg); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -3165,14 +2997,14 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_co #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) FUNCTION_CHECK_DST(dst, dstw); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " local_base "); sljit_verbose_param(compiler, dst, dstw); fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", offset); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -3182,14 +3014,14 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compil #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) FUNCTION_CHECK_DST(dst, dstw); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " const "); sljit_verbose_param(compiler, dst, dstw); fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", init_value); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -3197,14 +3029,14 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mov_addr(struct sljit_com { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) FUNCTION_CHECK_DST(dst, dstw); -#endif /* SLJIT_ARGUMENT_CHECKS */ +#endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " mov_addr "); sljit_verbose_param(compiler, dst, dstw); fprintf(compiler->verbose, "\n"); } -#endif /* SLJIT_VERBOSE */ +#endif CHECK_RETURN_OK; } @@ -3282,23 +3114,23 @@ static sljit_s32 sljit_emit_fmem_unaligned(struct sljit_compiler *compiler, slji #define SLJIT_CPUINFO_PART1 " 32bit (" #elif (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) #define SLJIT_CPUINFO_PART1 " 64bit (" -#else /* !SLJIT_32BIT_ARCHITECTURE && !SLJIT_64BIT_ARCHITECTURE */ +#else #error "Internal error: CPU type info missing" -#endif /* SLJIT_32BIT_ARCHITECTURE */ +#endif #if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) #define SLJIT_CPUINFO_PART2 "little endian + " #elif (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) #define SLJIT_CPUINFO_PART2 "big endian + " -#else /* !SLJIT_LITTLE_ENDIAN && !SLJIT_BIG_ENDIAN */ +#else #error "Internal error: CPU type info missing" -#endif /* SLJIT_LITTLE_ENDIAN */ +#endif #if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED) #define SLJIT_CPUINFO_PART3 "unaligned)" -#else /* !SLJIT_UNALIGNED */ +#else #define SLJIT_CPUINFO_PART3 "aligned)" -#endif /* SLJIT_UNALIGNED */ +#endif #define SLJIT_CPUINFO SLJIT_CPUINFO_PART1 SLJIT_CPUINFO_PART2 SLJIT_CPUINFO_PART3 @@ -3322,7 +3154,7 @@ static sljit_s32 sljit_emit_fmem_unaligned(struct sljit_compiler *compiler, slji # include "sljitNativeS390X.c" #elif (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH) # include "sljitNativeLOONGARCH_64.c" -#endif /* SLJIT_CONFIG_X86 */ +#endif #include "sljitSerialize.c" @@ -3332,10 +3164,10 @@ static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *comp /* At the moment the pointer size is always equal to sljit_sw. May be changed in the future. */ if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_P)) return SLJIT_SUCCESS; -#else /* !SLJIT_64BIT_ARCHITECTURE */ +#else if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_U32 || op == SLJIT_MOV_S32 || op == SLJIT_MOV_P)) return SLJIT_SUCCESS; -#endif /* SLJIT_64BIT_ARCHITECTURE */ +#endif SLJIT_SKIP_CHECKS(compiler); return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw); @@ -3417,7 +3249,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler if (src2 == SLJIT_IMM && !src2w) return emit_cmp_to0(compiler, type, src1, src1w); } -#endif /* SLJIT_CONFIG_ARM_64 */ +#endif if (SLJIT_UNLIKELY(src1 == SLJIT_IMM && src2 != SLJIT_IMM)) { /* Immediate is preferred as second argument by most architectures. */ @@ -3557,18 +3389,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler #if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \ && !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \ && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \ - && !(defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \ && !(defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 srcdst, sljit_sw srcdstw) { CHECK_ERROR(); - CHECK(check_sljit_emit_simd_mov(compiler, type, vreg, srcdst, srcdstw)); + CHECK(check_sljit_emit_simd_mov(compiler, type, freg, srcdst, srcdstw)); SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(type); - SLJIT_UNUSED_ARG(vreg); + SLJIT_UNUSED_ARG(freg); SLJIT_UNUSED_ARG(srcdst); SLJIT_UNUSED_ARG(srcdstw); @@ -3576,14 +3407,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *co } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_sw srcw) { CHECK_ERROR(); - CHECK(check_sljit_emit_simd_replicate(compiler, type, vreg, src, srcw)); + CHECK(check_sljit_emit_simd_replicate(compiler, type, freg, src, srcw)); SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(type); - SLJIT_UNUSED_ARG(vreg); + SLJIT_UNUSED_ARG(freg); SLJIT_UNUSED_ARG(src); SLJIT_UNUSED_ARG(srcw); @@ -3591,14 +3422,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, sljit_s32 lane_index, + sljit_s32 freg, sljit_s32 lane_index, sljit_s32 srcdst, sljit_sw srcdstw) { CHECK_ERROR(); - CHECK(check_sljit_emit_simd_lane_mov(compiler, type, vreg, lane_index, srcdst, srcdstw)); + CHECK(check_sljit_emit_simd_lane_mov(compiler, type, freg, lane_index, srcdst, srcdstw)); SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(type); - SLJIT_UNUSED_ARG(vreg); + SLJIT_UNUSED_ARG(freg); SLJIT_UNUSED_ARG(lane_index); SLJIT_UNUSED_ARG(srcdst); SLJIT_UNUSED_ARG(srcdstw); @@ -3607,14 +3438,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_s32 src_lane_index) { CHECK_ERROR(); - CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, vreg, src, src_lane_index)); + CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, freg, src, src_lane_index)); SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(type); - SLJIT_UNUSED_ARG(vreg); + SLJIT_UNUSED_ARG(freg); SLJIT_UNUSED_ARG(src); SLJIT_UNUSED_ARG(src_lane_index); @@ -3622,14 +3453,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_sw srcw) { CHECK_ERROR(); - CHECK(check_sljit_emit_simd_extend(compiler, type, vreg, src, srcw)); + CHECK(check_sljit_emit_simd_extend(compiler, type, freg, src, srcw)); SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(type); - SLJIT_UNUSED_ARG(vreg); + SLJIT_UNUSED_ARG(freg); SLJIT_UNUSED_ARG(src); SLJIT_UNUSED_ARG(srcw); @@ -3637,14 +3468,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 dst, sljit_sw dstw) { CHECK_ERROR(); - CHECK(check_sljit_emit_simd_sign(compiler, type, vreg, dst, dstw)); + CHECK(check_sljit_emit_simd_sign(compiler, type, freg, dst, dstw)); SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(type); - SLJIT_UNUSED_ARG(vreg); + SLJIT_UNUSED_ARG(freg); SLJIT_UNUSED_ARG(dst); SLJIT_UNUSED_ARG(dstw); @@ -3652,16 +3483,56 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w) + sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg) { CHECK_ERROR(); - CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w)); + CHECK(check_sljit_emit_simd_op2(compiler, type, dst_freg, src1_freg, src2_freg)); SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(type); - SLJIT_UNUSED_ARG(dst_vreg); - SLJIT_UNUSED_ARG(src1_vreg); - SLJIT_UNUSED_ARG(src2); - SLJIT_UNUSED_ARG(src2w); + SLJIT_UNUSED_ARG(dst_freg); + SLJIT_UNUSED_ARG(src1_freg); + SLJIT_UNUSED_ARG(src2_freg); + + return SLJIT_ERR_UNSUPPORTED; +} + +#endif /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_ARM */ + +#if !(defined(SLJIT_CONFIG_X86) && SLJIT_CONFIG_X86) \ + && !(defined(SLJIT_CONFIG_ARM) && SLJIT_CONFIG_ARM) \ + && !(defined(SLJIT_CONFIG_S390X) && SLJIT_CONFIG_S390X) \ + && !(defined(SLJIT_CONFIG_LOONGARCH) && SLJIT_CONFIG_LOONGARCH) + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, + sljit_s32 op, + sljit_s32 dst_reg, + sljit_s32 mem_reg) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(op); + SLJIT_UNUSED_ARG(dst_reg); + SLJIT_UNUSED_ARG(mem_reg); + + CHECK_ERROR(); + CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg)); + + return SLJIT_ERR_UNSUPPORTED; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, + sljit_s32 op, + sljit_s32 src_reg, + sljit_s32 mem_reg, + sljit_s32 temp_reg) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(op); + SLJIT_UNUSED_ARG(src_reg); + SLJIT_UNUSED_ARG(mem_reg); + SLJIT_UNUSED_ARG(temp_reg); + + CHECK_ERROR(); + CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg)); return SLJIT_ERR_UNSUPPORTED; } diff --git a/ext/pcre/pcre2lib/sljit/sljitLir.h b/ext/pcre/pcre2lib/sljit/sljitLir.h index 60d34f1543057..8b6fa69a0a299 100644 --- a/ext/pcre/pcre2lib/sljit/sljitLir.h +++ b/ext/pcre/pcre2lib/sljit/sljitLir.h @@ -87,7 +87,7 @@ of sljitConfigInternal.h */ #ifdef __cplusplus extern "C" { -#endif /* __cplusplus */ +#endif /* Version numbers. */ #define SLJIT_MAJOR_VERSION 0 @@ -251,7 +251,7 @@ extern "C" { #define SLJIT_FS7 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 7) #define SLJIT_FS8 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 8) #define SLJIT_FS9 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 9) -/* All FS registers provided by the architecture can be accessed by SLJIT_FS(i) +/* All S registers provided by the architecture can be accessed by SLJIT_FS(i) The i parameter must be >= 0 and < SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS. */ #define SLJIT_FS(i) (SLJIT_NUMBER_OF_FLOAT_REGISTERS - (i)) @@ -262,52 +262,6 @@ extern "C" { #define SLJIT_RETURN_FREG SLJIT_FR0 -/* --------------------------------------------------------------------- */ -/* Vector registers */ -/* --------------------------------------------------------------------- */ - -/* Vector registers are storage areas, which are used for Single Instruction - Multiple Data (SIMD) computations. The VR and VS register sets overlap - in the same way as R and S register sets. See above. - - The storage space of vector registers often overlap with floating point - registers. In this case setting the value of SLJIT_VR(i) destroys the - value of SLJIT_FR(i) and vice versa. See SLJIT_SEPARATE_VECTOR_REGISTERS - macro. */ - -/* Vector scratch registers. */ -#define SLJIT_VR0 1 -#define SLJIT_VR1 2 -#define SLJIT_VR2 3 -#define SLJIT_VR3 4 -#define SLJIT_VR4 5 -#define SLJIT_VR5 6 -#define SLJIT_VR6 7 -#define SLJIT_VR7 8 -#define SLJIT_VR8 9 -#define SLJIT_VR9 10 -/* All VR registers provided by the architecture can be accessed by SLJIT_VR(i) - The i parameter must be >= 0 and < SLJIT_NUMBER_OF_VECTOR_REGISTERS. */ -#define SLJIT_VR(i) (1 + (i)) - -/* Vector saved registers. */ -#define SLJIT_VS0 (SLJIT_NUMBER_OF_VECTOR_REGISTERS) -#define SLJIT_VS1 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 1) -#define SLJIT_VS2 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 2) -#define SLJIT_VS3 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 3) -#define SLJIT_VS4 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 4) -#define SLJIT_VS5 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 5) -#define SLJIT_VS6 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 6) -#define SLJIT_VS7 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 7) -#define SLJIT_VS8 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 8) -#define SLJIT_VS9 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 9) -/* All VS registers provided by the architecture can be accessed by SLJIT_VS(i) - The i parameter must be >= 0 and < SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS. */ -#define SLJIT_VS(i) (SLJIT_NUMBER_OF_VECTOR_REGISTERS - (i)) - -/* Vector registers >= SLJIT_FIRST_SAVED_VECTOR_REG are saved registers. */ -#define SLJIT_FIRST_SAVED_VECTOR_REG (SLJIT_VS0 - SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS + 1) - /* --------------------------------------------------------------------- */ /* Argument type definitions */ /* --------------------------------------------------------------------- */ @@ -529,15 +483,6 @@ struct sljit_compiler { sljit_s32 fscratches; /* Available float saved registers. */ sljit_s32 fsaveds; -#if (defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS) \ - || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ - || (defined SLJIT_DEBUG && SLJIT_DEBUG) \ - || (defined SLJIT_VERBOSE && SLJIT_VERBOSE) - /* Available vector scratch registers. */ - sljit_s32 vscratches; - /* Available vector saved registers. */ - sljit_s32 vsaveds; -#endif /* SLJIT_SEPARATE_VECTOR_REGISTERS || SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG || SLJIT_VERBOSE */ /* Local stack size. */ sljit_s32 local_size; /* Maximum code size. */ @@ -618,7 +563,6 @@ struct sljit_compiler { FILE* verbose; #endif /* SLJIT_VERBOSE */ - /* Note: SLJIT_DEBUG enables SLJIT_ARGUMENT_CHECKS. */ #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ || (defined SLJIT_DEBUG && SLJIT_DEBUG) /* Flags specified by the last arithmetic instruction. @@ -633,13 +577,6 @@ struct sljit_compiler { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ || (defined SLJIT_DEBUG && SLJIT_DEBUG) \ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE) -#if !(defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS) - /* Available float scratch registers. */ - sljit_s32 real_fscratches; - /* Available float saved registers. */ - sljit_s32 real_fsaveds; -#endif /* !SLJIT_SEPARATE_VECTOR_REGISTERS */ - /* Trust arguments when an API function is called. Used internally for calling API functions. */ sljit_s32 skip_checks; @@ -697,7 +634,7 @@ static SLJIT_INLINE void* sljit_compiler_get_user_data(struct sljit_compiler *co #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) /* Passing NULL disables verbose. */ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose); -#endif /* SLJIT_VERBOSE */ +#endif /* Option bits for sljit_generate_code. */ @@ -743,9 +680,7 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler support while others (e.g. move with update) are emulated if not available. However, even when a feature is emulated, specialized code paths may be faster than the emulation. Some limitations are emulated as well so their - general case is supported but it has extra performance costs. - - Note: sljitConfigInternal.h also provides several feature detection macros. */ + general case is supported but it has extra performance costs. */ /* [Not emulated] Floating-point support is available. */ #define SLJIT_HAS_FPU 0 @@ -780,22 +715,20 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler a simd operation represents the same 128 bit register, and both SLJIT_FR0 and SLJIT_FR1 are overwritten. */ #define SLJIT_SIMD_REGS_ARE_PAIRS 13 -/* [Not emulated] Atomic support is available. */ -#define SLJIT_HAS_ATOMIC 14 -/* [Not emulated] Memory barrier support is available. */ -#define SLJIT_HAS_MEMORY_BARRIER 15 +/* [Not emulated] Atomic support is available (fine-grained). */ +#define SLJIT_HAS_ATOMIC 14 #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) /* [Not emulated] AVX support is available on x86. */ #define SLJIT_HAS_AVX 100 /* [Not emulated] AVX2 support is available on x86. */ #define SLJIT_HAS_AVX2 101 -#endif /* SLJIT_CONFIG_X86 */ +#endif #if (defined SLJIT_CONFIG_LOONGARCH) /* [Not emulated] LASX support is available on LoongArch */ #define SLJIT_HAS_LASX 201 -#endif /* SLJIT_CONFIG_LOONGARCH */ +#endif SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type); @@ -816,65 +749,42 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type); with an error code. */ /* - The executable code is a callable function from the viewpoint - of the C language. Function calls must conform with the ABI - (Application Binary Interface) of the target platform, which - specify the purpose of machine registers and stack handling - among other things. The sljit_emit_enter function emits the - necessary instructions for setting up an entry point for the - executable code. This is often called as function prologue. - - The "options" argument can be used to pass configuration options - to the sljit compiler which affects the generated code, until - another sljit_emit_enter or sljit_set_context is called. The + The executable code is a function from the viewpoint of the C + language. The function calls must conform to the ABI (Application + Binary Interface) of the platform, which specify the purpose of + machine registers and stack handling among other things. The + sljit_emit_enter function emits the necessary instructions for + setting up a new context for the executable code. This is often + called as function prologue. Furthermore the options argument + can be used to pass configuration options to the compiler. The available options are listed before sljit_emit_enter. The function argument list is specified by the SLJIT_ARGSx (SLJIT_ARGS0 .. SLJIT_ARGS4) macros. Currently maximum four arguments are supported. See the description of SLJIT_ARGSx - macros about argument passing. - - The register set used by the function must be declared as well. - The number of scratch and saved registers available to the - function must be passed to sljit_emit_enter. Only R registers - between R0 and "scratches" argument can be used later. E.g. - if "scratches" is set to two, the scratch register set will - be limited to SLJIT_R0 and SLJIT_R1. The S registers are - declared in a similar manner, but their count is specified - by "saveds" argument. The floating point scratch and saved - registers can be set by using "scratches" and "saveds" argument - as well, but their value must be passed to the SLJIT_ENTER_FLOAT - macro, see below. - - The sljit_emit_enter is also capable of allocating a stack - space for local data. The "local_size" argument contains the - size in bytes of this local area, and it can be accessed using - SLJIT_MEM1(SLJIT_SP). The memory area between SLJIT_SP (inclusive) - and SLJIT_SP + local_size (exclusive) can be modified freely - until the function returns. The alocated stack space is an - uninitialized memory area. - - Floating point scratch and saved registers must be specified - by the SLJIT_ENTER_FLOAT macro, which result value should be - combined with scratches / saveds argument. - - Examples: - To use three scratch and four floating point scratch - registers, the "scratches" argument must be set to: - 3 | SLJIT_ENTER_FLOAT(4) - - To use six saved and five floating point saved - registers, the "saveds" argument must be set to: - 6 | SLJIT_ENTER_FLOAT(5) + macros about argument passing. Furthermore the register set + used by the function must be declared as well. The number of + scratch and saved registers available to the function must + be passed to sljit_emit_enter. Only R registers between R0 + and "scratches" argument can be used later. E.g. if "scratches" + is set to two, the scratch register set will be limited to + SLJIT_R0 and SLJIT_R1. The S registers and the floating point + registers ("fscratches" and "fsaveds") are specified in a + similar manner. The sljit_emit_enter is also capable of + allocating a stack space for local data. The "local_size" + argument contains the size in bytes of this local area, and + it can be accessed using SLJIT_MEM1(SLJIT_SP). The memory + area between SLJIT_SP (inclusive) and SLJIT_SP + local_size + (exclusive) can be modified freely until the function returns. + The stack space is not initialized to zero. Note: the following conditions must met: 0 <= scratches <= SLJIT_NUMBER_OF_REGISTERS 0 <= saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS - - 0 <= float scratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS - 0 <= float saveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS - float scratches + float saveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS + 0 <= fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS + 0 <= fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS + fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS Note: the compiler can use saved registers as scratch registers, but the opposite is not supported @@ -883,8 +793,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type); overwrites the previous context. */ -/* The following options are available for sljit_emit_enter. */ - /* Saved registers between SLJIT_S0 and SLJIT_S(n - 1) (inclusive) are not saved / restored on function enter / return. Instead, these registers can be used to pass / return data (such as @@ -900,27 +808,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type); and all arguments must be stored in scratch registers. */ #define SLJIT_ENTER_REG_ARG 0x00000004 +/* The local_size must be >= 0 and <= SLJIT_MAX_LOCAL_SIZE. */ +#define SLJIT_MAX_LOCAL_SIZE 1048576 + #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) /* Use VEX prefix for all SIMD operations on x86. */ #define SLJIT_ENTER_USE_VEX 0x00010000 #endif /* !SLJIT_CONFIG_X86 */ -/* Macros for other sljit_emit_enter arguments. */ - -/* Floating point scratch and saved registers can be - specified by SLJIT_ENTER_FLOAT. */ -#define SLJIT_ENTER_FLOAT(regs) ((regs) << 8) - -/* Vector scratch and saved registers can be specified - by SLJIT_ENTER_VECTOR. */ -#define SLJIT_ENTER_VECTOR(regs) ((regs) << 16) - -/* The local_size must be >= 0 and <= SLJIT_MAX_LOCAL_SIZE. */ -#define SLJIT_MAX_LOCAL_SIZE 1048576 - SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size); + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size); /* The SLJIT compiler has a current context (which contains the local stack space size, number of used registers, etc.) which is initialized @@ -936,8 +834,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi the previous context. */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size); + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size); /* Return to the caller function. The sljit_emit_return_void function does not return with any value. The sljit_emit_return function returns @@ -1194,21 +1092,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *c the behaviour is undefined. */ #define SLJIT_DIV_SW (SLJIT_OP0_BASE + 7) #define SLJIT_DIV_S32 (SLJIT_DIV_SW | SLJIT_32) -/* Flags: - (does not modify flags) - May return with SLJIT_ERR_UNSUPPORTED if SLJIT_HAS_MEMORY_BARRIER - feature is not supported (calling sljit_has_cpu_feature() with - this feature option returns with 0). */ -#define SLJIT_MEMORY_BARRIER (SLJIT_OP0_BASE + 8) /* Flags: - (does not modify flags) ENDBR32 instruction for x86-32 and ENDBR64 instruction for x86-64 when Intel Control-flow Enforcement Technology (CET) is enabled. No instructions are emitted for other architectures. */ -#define SLJIT_ENDBR (SLJIT_OP0_BASE + 9) +#define SLJIT_ENDBR (SLJIT_OP0_BASE + 8) /* Flags: - (may destroy flags) Skip stack frames before return when Intel Control-flow Enforcement Technology (CET) is enabled. No instructions are emitted for other architectures. */ -#define SLJIT_SKIP_FRAMES_BEFORE_RETURN (SLJIT_OP0_BASE + 10) +#define SLJIT_SKIP_FRAMES_BEFORE_RETURN (SLJIT_OP0_BASE + 9) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op); @@ -1997,21 +1890,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler /* The following options are used by several simd operations. */ -/* Load data into a vector register, this is the default */ +/* Load data into a simd register, this is the default */ #define SLJIT_SIMD_LOAD 0x000000 -/* Store data from a vector register */ +/* Store data from a simd register */ #define SLJIT_SIMD_STORE 0x000001 -/* The vector register contains floating point values */ +/* The simd register contains floating point values */ #define SLJIT_SIMD_FLOAT 0x000400 /* Tests whether the operation is available */ #define SLJIT_SIMD_TEST 0x000800 -/* Move data to/from a 64 bit (8 byte) long vector register */ +/* Move data to/from a 64 bit (8 byte) long SIMD register */ #define SLJIT_SIMD_REG_64 (3 << 12) -/* Move data to/from a 128 bit (16 byte) long vector register */ +/* Move data to/from a 128 bit (16 byte) long SIMD register */ #define SLJIT_SIMD_REG_128 (4 << 12) -/* Move data to/from a 256 bit (32 byte) long vector register */ +/* Move data to/from a 256 bit (32 byte) long SIMD register */ #define SLJIT_SIMD_REG_256 (5 << 12) -/* Move data to/from a 512 bit (64 byte) long vector register */ +/* Move data to/from a 512 bit (64 byte) long SIMD register */ #define SLJIT_SIMD_REG_512 (6 << 12) /* Element size is 8 bit long (this is the default), usually cannot be combined with SLJIT_SIMD_FLOAT */ #define SLJIT_SIMD_ELEM_8 (0 << 18) @@ -2026,8 +1919,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler /* Element size is 256 bit long */ #define SLJIT_SIMD_ELEM_256 (5 << 18) -/* The following options are used by sljit_emit_simd_mov() - and sljit_emit_simd_op2(). */ +/* The following options are used by sljit_emit_simd_mov(). */ /* Memory address is unaligned (this is the default) */ #define SLJIT_SIMD_MEM_UNALIGNED (0 << 24) @@ -2044,7 +1936,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler /* Memory address is 512 bit aligned */ #define SLJIT_SIMD_MEM_ALIGNED_512 (6 << 24) -/* Moves data between a vector register and memory. +/* Moves data between a simd register and memory. If the operation is not supported, it returns with SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed, @@ -2052,21 +1944,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler type must be a combination of SLJIT_SIMD_* and SLJIT_SIMD_MEM_* options - vreg is the source or destination vector register + freg is the source or destination simd register of the operation - srcdst must be a memory operand or a vector register + srcdst must be a memory operand or a simd register Note: The alignment and element size must be - less or equal than vector register size. + less or equal than simd register size. Flags: - (does not modify flags) */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 srcdst, sljit_sw srcdstw); -/* Replicates a scalar value to all lanes of a vector +/* Replicates a scalar value to all lanes of a simd register. If the operation is not supported, it returns with @@ -2075,7 +1967,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *co type must be a combination of SLJIT_SIMD_* options except SLJIT_SIMD_STORE. - vreg is the destination vector register of the operation + freg is the destination simd register of the operation src is the value which is replicated Note: @@ -2085,7 +1977,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *co Flags: - (does not modify flags) */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_sw srcw); /* The following options are used by sljit_emit_simd_lane_mov(). */ @@ -2095,7 +1987,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil /* Sign extend the integer value stored from the lane. */ #define SLJIT_SIMD_LANE_SIGNED 0x000004 -/* Moves data between a vector register lane and a register or +/* Moves data between a simd register lane and a register or memory. If the srcdst argument is a register, it must be a floating point register when SLJIT_SIMD_FLOAT is specified, or a general purpose register otherwise. @@ -2111,7 +2003,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil is set and SLJIT_SIMD_FLOAT is not set SLJIT_SIMD_LANE_ZERO - when SLJIT_SIMD_LOAD is specified - vreg is the source or destination vector register + freg is the source or destination simd register of the operation lane_index is the index of the lane srcdst is the destination operand for loads, and @@ -2123,11 +2015,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil Flags: - (does not modify flags) */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, sljit_s32 lane_index, + sljit_s32 freg, sljit_s32 lane_index, sljit_s32 srcdst, sljit_sw srcdstw); /* Replicates a scalar value from a lane to all lanes - of a vector register. + of a simd register. If the operation is not supported, it returns with SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed, @@ -2135,14 +2027,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile type must be a combination of SLJIT_SIMD_* options except SLJIT_SIMD_STORE. - vreg is the destination vector register of the operation - src is the vector register which lane is replicated + freg is the destination simd register of the operation + src is the simd register which lane is replicated src_lane_index is the lane index of the src register Flags: - (does not modify flags) */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_s32 src_lane_index); /* The following options are used by sljit_emit_simd_load_extend(). */ @@ -2156,7 +2048,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c /* Extend data to 64 bit */ #define SLJIT_SIMD_EXTEND_64 (3 << 24) -/* Extend elements and stores them in a vector register. +/* Extend elements and stores them in a simd register. The extension operation increases the size of the elements (e.g. from 16 bit to 64 bit). For integer values, the extension can be signed or unsigned. @@ -2167,15 +2059,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c type must be a combination of SLJIT_SIMD_*, and SLJIT_SIMD_EXTEND_* options except SLJIT_SIMD_STORE - vreg is the destination vector register of the operation - src must be a memory operand or a vector register. + freg is the destination simd register of the operation + src must be a memory operand or a simd register. In the latter case, the source elements are stored in the lower half of the register. Flags: - (does not modify flags) */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_sw srcw); /* Extract the highest bit (usually the sign bit) from @@ -2187,16 +2079,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler type must be a combination of SLJIT_SIMD_* and SLJIT_32 options except SLJIT_SIMD_LOAD - vreg is the source vector register of the operation + freg is the source simd register of the operation dst is the destination operand Flags: - (does not modify flags) */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 dst, sljit_sw dstw); -/* The following operations are used by sljit_emit_simd_op2(). */ +/* The following options are used by sljit_emit_simd_op2(). */ /* Binary 'and' operation */ #define SLJIT_SIMD_OP2_AND 0x000001 @@ -2204,40 +2096,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c #define SLJIT_SIMD_OP2_OR 0x000002 /* Binary 'xor' operation */ #define SLJIT_SIMD_OP2_XOR 0x000003 -/* Shuffle bytes of src1 using the indicies in src2 */ -#define SLJIT_SIMD_OP2_SHUFFLE 0x000004 -/* Perform simd operations using vector registers. +/* Perform simd operations using simd registers. If the operation is not supported, it returns with SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed, it does not emit any instructions. - type must be a combination of SLJIT_SIMD_*, SLJIT_SIMD_MEM_* - and SLJIT_SIMD_OP2_* options except SLJIT_SIMD_LOAD - and SLJIT_SIMD_STORE - dst_vreg is the destination register of the operation - src1_vreg is the first source register of the operation - src2 is the second source operand of the operation + type must be a combination of SLJIT_SIMD_* and SLJIT_SIMD_OP2_ + options except SLJIT_SIMD_LOAD and SLJIT_SIMD_STORE + dst_freg is the destination register of the operation + src1_freg is the first source register of the operation + src1_freg is the second source register of the operation Flags: - (does not modify flags) */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w); - -/* The following operations are used by sljit_emit_atomic_load() and - sljit_emit_atomic_store() operations. */ - -/* Tests whether the atomic operation is available (does not generate - any instructions). When a load from is allowed, its corresponding - store form is allowed and vice versa. */ -#define SLJIT_ATOMIC_TEST 0x10000 -/* The compiler must generate compare and swap instruction. - When this bit is set, calling sljit_emit_atomic_load() is optional. */ -#define SLJIT_ATOMIC_USE_CAS 0x20000 -/* The compiler must generate load-acquire and store-release instructions. - When this bit is set, the temp_reg for sljit_emit_atomic_store is not used. */ -#define SLJIT_ATOMIC_USE_LS 0x40000 + sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg); /* The sljit_emit_atomic_load and sljit_emit_atomic_store operation pair can perform an atomic read-modify-write operation. First, an unsigned @@ -2246,17 +2121,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *co sljit_emit_atomic_store. A thread can only perform a single atomic operation at a time. + Note: atomic operations are experimental, and not implemented + for all cpus. + The following conditions must be satisfied, or the operation is undefined: - the address provided in mem_reg must be divisible by the size of the value (only naturally aligned updates are supported) - - no memory operations are allowed between the load and store operations + - no memory writes are allowed between the load and store operations + regardless of its target address (currently read operations are + allowed, but this might change in the future) - the memory operation (op) and the base address (stored in mem_reg) passed to the load/store operations must be the same (the mem_reg can be a different register, only its value must be the same) - - a store must always follow a load for the same transaction. + - an store must always follow a load for the same transaction. - op must be between SLJIT_MOV and SLJIT_MOV_P + op must be between SLJIT_MOV and SLJIT_MOV_P, excluding all + signed loads such as SLJIT_MOV32_S16 dst_reg is the register where the data will be loaded into mem_reg is the base address of the memory load (it cannot be SLJIT_SP or a virtual register on x86-32) @@ -2270,19 +2151,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler allows performing an atomic read-modify-write operation. See the description of sljit_emit_atomic_load. - op must be between SLJIT_MOV and SLJIT_MOV_P + op must be between SLJIT_MOV and SLJIT_MOV_P, excluding all signed + loads such as SLJIT_MOV32_S16 src_reg is the register which value is stored into the memory mem_reg is the base address of the memory store (it cannot be SLJIT_SP or a virtual register on x86-32) - temp_reg is a scratch register, which must be initialized with - the value loaded into the dst_reg during the corresponding - sljit_emit_atomic_load operation, or the operation is undefined. - The temp_reg register preserves its value, if the memory store - is successful. Otherwise, its value is undefined. - - Flags: ATOMIC_STORED - if ATOMIC_STORED flag is set, it represents that the memory - is updated with a new value. Otherwise the memory is unchanged. */ + temp_reg is a not preserved scratch register, which must be + initialized with the value loaded into the dst_reg during the + corresponding sljit_emit_atomic_load operation, or the operation + is undefined + + Flags: ATOMIC_STORED is set if the operation is successful, + otherwise the memory remains unchanged. */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src_reg, sljit_s32 mem_reg, @@ -2577,10 +2457,10 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct it is sometimes desired to free all unused memory regions, e.g. before the application terminates. */ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void); -#endif /* SLJIT_EXECUTABLE_ALLOCATOR */ +#endif #ifdef __cplusplus } /* extern "C" */ -#endif /* __cplusplus */ +#endif #endif /* SLJIT_LIR_H_ */ diff --git a/ext/pcre/pcre2lib/sljit/sljitNativeARM_32.c b/ext/pcre/pcre2lib/sljit/sljitNativeARM_32.c index 327dc824efc6e..a253c06f01008 100644 --- a/ext/pcre/pcre2lib/sljit/sljitNativeARM_32.c +++ b/ext/pcre/pcre2lib/sljit/sljitNativeARM_32.c @@ -114,7 +114,6 @@ static const sljit_u8 freg_ebit_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) << 1) #define CLZ 0xe16f0f10 #define CMN 0xe1600000 #define CMP 0xe1400000 -#define DMB_SY 0xf57ff05f #define EOR 0xe0200000 #define LDR 0xe5100000 #define LDR_POST 0xe4100000 @@ -181,7 +180,6 @@ static const sljit_u8 freg_ebit_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) << 1) #define VST1_s 0xf4800000 #define VSTR_F32 0xed000a00 #define VSUB_F32 0xee300a40 -#define VTBL 0xf3b00800 #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) /* Arm v7 specific instructions. */ @@ -200,28 +198,11 @@ static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s if (is_32 && fr >= SLJIT_F64_SECOND(SLJIT_FR0)) fr -= SLJIT_F64_SECOND(0); - return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->real_fscratches)) - || (fr > (SLJIT_FS0 - compiler->real_fsaveds) && fr <= SLJIT_FS0) + return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->fscratches)) + || (fr > (SLJIT_FS0 - compiler->fsaveds) && fr <= SLJIT_FS0) || (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS)); } -static sljit_s32 function_check_is_vreg(struct sljit_compiler *compiler, sljit_s32 vr, sljit_s32 type) -{ - sljit_s32 vr_low = vr; - - if (compiler->scratches == -1) - return 0; - - if (SLJIT_SIMD_GET_REG_SIZE(type) == 4) { - vr += (vr & 0x1); - vr_low = vr - 1; - } - - return (vr >= SLJIT_VR0 && vr < (SLJIT_VR0 + compiler->vscratches)) - || (vr_low > (SLJIT_VS0 - compiler->vsaveds) && vr_low <= SLJIT_VS0) - || (vr >= SLJIT_TMP_VREGISTER_BASE && vr < (SLJIT_TMP_VREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS)); -} - #endif /* SLJIT_ARGUMENT_CHECKS */ #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) @@ -383,7 +364,7 @@ static sljit_uw patch_pc_relative_loads(sljit_uw *last_pc_patch, sljit_uw *code_ while (last_pc_patch < code_ptr) { /* Data transfer instruction with Rn == r15. */ - if ((*last_pc_patch & 0x0e4f0000) == 0x040f0000) { + if ((*last_pc_patch & 0x0e0f0000) == 0x040f0000) { diff = (sljit_uw)(const_pool - last_pc_patch); ind = (*last_pc_patch) & 0xfff; @@ -495,14 +476,6 @@ static SLJIT_INLINE sljit_s32 emit_imm(struct sljit_compiler *compiler, sljit_s3 static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_uw *code_ptr, sljit_uw *code, sljit_sw executable_offset) { sljit_sw diff; - sljit_uw target_addr; - sljit_uw jump_addr = (sljit_uw)code_ptr; - sljit_uw orig_addr = jump->addr; - SLJIT_UNUSED_ARG(executable_offset); - -#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) - jump->addr = jump_addr; -#endif if (jump->flags & SLJIT_REWRITABLE_JUMP) return 0; @@ -513,17 +486,12 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_uw #endif /* SLJIT_CONFIG_ARM_V6 */ if (jump->flags & JUMP_ADDR) - target_addr = jump->u.target; + diff = ((sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2) - executable_offset); else { SLJIT_ASSERT(jump->u.label != NULL); - target_addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset); - - if (jump->u.label->size > orig_addr) - jump_addr = (sljit_uw)(code + orig_addr); + diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)(code_ptr + 2)); } - diff = (sljit_sw)target_addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr + 8, executable_offset); - /* Branch to Thumb code has not been optimized yet. */ if (diff & 0x3) return 0; @@ -535,9 +503,12 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_uw jump->flags |= PATCH_B; return 1; } - } else if (diff <= 0x01ffffff && diff >= -0x02000000) { - *code_ptr = (B - CONDITIONAL) | (*code_ptr & COND_MASK); - jump->flags |= PATCH_B; + } + else { + if (diff <= 0x01ffffff && diff >= -0x02000000) { + *code_ptr = (B - CONDITIONAL) | (*code_ptr & COND_MASK); + jump->flags |= PATCH_B; + } } #else /* !SLJIT_CONFIG_ARM_V6 */ if (diff <= 0x01ffffff && diff >= -0x02000000) { @@ -743,21 +714,16 @@ static void set_const_value(sljit_uw addr, sljit_sw executable_offset, sljit_uw static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset) { sljit_uw addr; - sljit_uw jump_addr = (sljit_uw)code_ptr; sljit_sw diff; SLJIT_UNUSED_ARG(executable_offset); if (jump->flags & JUMP_ADDR) addr = jump->u.target; - else { + else addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset); - if (jump->u.label->size > jump->addr) - jump_addr = (sljit_uw)(code + jump->addr); - } - /* The pc+8 offset is represented by the 2 * SSIZE_OF(ins) below. */ - diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset); + diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); if ((diff & 0x3) == 0 && diff <= (0x3fc + 2 * SSIZE_OF(ins)) && diff >= (-0x3fc + 2 * SSIZE_OF(ins))) { jump->flags |= PATCH_B; @@ -818,10 +784,6 @@ static void reduce_code_size(struct sljit_compiler *compiler) if (!(jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR))) { /* Unit size: instruction. */ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr - 2; - if (jump->u.label->size > jump->addr) { - SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr); - diff -= (sljit_sw)size_reduce; - } if (diff <= (0x01ffffff / SSIZE_OF(ins)) && diff >= (-0x02000000 / SSIZE_OF(ins))) total_size = 1 - 1; @@ -834,11 +796,6 @@ static void reduce_code_size(struct sljit_compiler *compiler) if (!(jump->flags & JUMP_ADDR)) { diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr; - if (jump->u.label->size > jump->addr) { - SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr); - diff -= (sljit_sw)size_reduce; - } - if (diff <= 0xff + 2 && diff >= -0xff + 2) total_size = 0; } @@ -960,6 +917,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil jump->addr = (sljit_uw)code_ptr; #else /* !SLJIT_CONFIG_ARM_V6 */ word_count += jump->flags >> JUMP_SIZE_SHIFT; + jump->addr = (sljit_uw)code_ptr; if (!detect_jump_type(jump, code_ptr, code, executable_offset)) { code_ptr[2] = code_ptr[0]; addr = ((code_ptr[0] & 0xf) << 12); @@ -1173,9 +1131,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) case SLJIT_HAS_COPY_F32: case SLJIT_HAS_COPY_F64: case SLJIT_HAS_ATOMIC: -#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) - case SLJIT_HAS_MEMORY_BARRIER: -#endif /* SLJIT_CONFIG_ARM_V7 */ return 1; case SLJIT_HAS_CTZ: @@ -1270,11 +1225,9 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 sljit_s32 src2, sljit_sw src2w); SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 fscratches; - sljit_s32 fsaveds; sljit_uw imm, offset; sljit_s32 i, tmp, size, word_arg_count; sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options); @@ -1287,15 +1240,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi #endif CHECK_ERROR(); - CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size)); - set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size); - - scratches = ENTER_GET_REGS(scratches); - saveds = ENTER_GET_REGS(saveds); - fscratches = compiler->fscratches; - fsaveds = compiler->fsaveds; + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); imm = 0; + tmp = SLJIT_S0 - saveds; for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) imm |= (sljit_uw)1 << reg_map[i]; @@ -1442,21 +1391,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 fscratches; - sljit_s32 fsaveds; sljit_s32 size; CHECK_ERROR(); - CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size)); - set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size); + CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); - scratches = ENTER_GET_REGS(scratches); - saveds = ENTER_GET_REGS(saveds); - fscratches = compiler->fscratches; - fsaveds = compiler->fsaveds; size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1); /* Doubles are saved, so alignment is unaffected. */ @@ -2421,12 +2364,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */); } return SLJIT_SUCCESS; - case SLJIT_MEMORY_BARRIER: -#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) - return push_inst(compiler, DMB_SY); -#else /* !SLJIT_CONFIG_ARM_V7 */ - return SLJIT_ERR_UNSUPPORTED; -#endif /* SLJIT_CONFIG_ARM_V7 */ case SLJIT_ENDBR: case SLJIT_SKIP_FRAMES_BEFORE_RETURN: return SLJIT_SUCCESS; @@ -2693,7 +2630,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, slji if (type == SLJIT_FLOAT_REGISTER || type == SLJIT_SIMD_REG_64) return freg_map[reg]; - if (type == SLJIT_SIMD_REG_128) + if (type != SLJIT_SIMD_REG_128) return freg_map[reg] & ~0x1; return -1; @@ -3168,9 +3105,9 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile if (type >= SLJIT_FAST_CALL) PTR_FAIL_IF(prepare_blx(compiler)); + jump->addr = compiler->size; PTR_FAIL_IF(push_inst_with_unique_literal(compiler, ((EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0)) & ~COND_MASK) | get_cc(compiler, type), 0)); - jump->addr = compiler->size - 1; if (jump->flags & SLJIT_REWRITABLE_JUMP) compiler->patches++; @@ -3970,7 +3907,7 @@ static SLJIT_INLINE sljit_s32 simd_get_quad_reg_index(sljit_s32 freg) #define SLJIT_QUAD_OTHER_HALF(freg) ((((freg) & 0x1) << 1) - 1) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 srcdst, sljit_sw srcdstw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -3979,7 +3916,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *co sljit_ins ins; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_mov(compiler, type, vreg, srcdst, srcdstw)); + CHECK(check_sljit_emit_simd_mov(compiler, type, freg, srcdst, srcdstw)); ADJUST_LOCAL_OFFSET(srcdst, srcdstw); @@ -3993,16 +3930,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *co return SLJIT_SUCCESS; if (reg_size == 4) - vreg = simd_get_quad_reg_index(vreg); + freg = simd_get_quad_reg_index(freg); if (!(srcdst & SLJIT_MEM)) { if (reg_size == 4) srcdst = simd_get_quad_reg_index(srcdst); if (type & SLJIT_SIMD_STORE) - ins = VD(srcdst) | VN(vreg) | VM(vreg); + ins = VD(srcdst) | VN(freg) | VM(freg); else - ins = VD(vreg) | VN(srcdst) | VM(srcdst); + ins = VD(freg) | VN(srcdst) | VM(srcdst); if (reg_size == 4) ins |= (sljit_ins)1 << 6; @@ -4015,7 +3952,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *co if (elem_size > 3) elem_size = 3; - ins = ((type & SLJIT_SIMD_STORE) ? VST1 : VLD1) | VD(vreg) + ins = ((type & SLJIT_SIMD_STORE) ? VST1 : VLD1) | VD(freg) | (sljit_ins)((reg_size == 3) ? (0x7 << 8) : (0xa << 8)); SLJIT_ASSERT(reg_size >= alignment); @@ -4123,7 +4060,7 @@ static sljit_ins simd_get_imm(sljit_s32 elem_size, sljit_uw value) } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_sw srcw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -4131,7 +4068,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil sljit_ins ins, imm; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_replicate(compiler, type, vreg, src, srcw)); + CHECK(check_sljit_emit_simd_replicate(compiler, type, freg, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); @@ -4145,24 +4082,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil return SLJIT_SUCCESS; if (reg_size == 4) - vreg = simd_get_quad_reg_index(vreg); + freg = simd_get_quad_reg_index(freg); if (src == SLJIT_IMM && srcw == 0) - return push_inst(compiler, VMOV_i | ((reg_size == 4) ? (1 << 6) : 0) | VD(vreg)); + return push_inst(compiler, VMOV_i | ((reg_size == 4) ? (1 << 6) : 0) | VD(freg)); if (SLJIT_UNLIKELY(elem_size == 3)) { SLJIT_ASSERT(type & SLJIT_SIMD_FLOAT); if (src & SLJIT_MEM) { - FAIL_IF(emit_fop_mem(compiler, FPU_LOAD | SLJIT_32, vreg, src, srcw)); - src = vreg; - } else if (vreg != src) - FAIL_IF(push_inst(compiler, VORR | VD(vreg) | VN(src) | VM(src))); + FAIL_IF(emit_fop_mem(compiler, FPU_LOAD | SLJIT_32, freg, src, srcw)); + src = freg; + } else if (freg != src) + FAIL_IF(push_inst(compiler, VORR | VD(freg) | VN(src) | VM(src))); - vreg += SLJIT_QUAD_OTHER_HALF(vreg); + freg += SLJIT_QUAD_OTHER_HALF(freg); - if (vreg != src) - return push_inst(compiler, VORR | VD(vreg) | VN(src) | VM(src)); + if (freg != src) + return push_inst(compiler, VORR | VD(freg) | VN(src) | VM(src)); return SLJIT_SUCCESS; } @@ -4174,7 +4111,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil if (reg_size == 4) ins |= (sljit_ins)1 << 5; - return push_inst(compiler, VLD1_r | ins | VD(vreg) | RN(src) | 0xf); + return push_inst(compiler, VLD1_r | ins | VD(freg) | RN(src) | 0xf); } if (type & SLJIT_SIMD_FLOAT) { @@ -4184,7 +4121,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil if (reg_size == 4) ins |= (sljit_ins)1 << 6; - return push_inst(compiler, VDUP_s | ins | VD(vreg) | (sljit_ins)freg_map[src]); + return push_inst(compiler, VDUP_s | ins | VD(freg) | (sljit_ins)freg_map[src]); } if (src == SLJIT_IMM) { @@ -4197,7 +4134,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil if (reg_size == 4) imm |= (sljit_ins)1 << 6; - return push_inst(compiler, VMOV_i | imm | VD(vreg)); + return push_inst(compiler, VMOV_i | imm | VD(freg)); } FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw)); @@ -4219,11 +4156,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil if (reg_size == 4) ins |= (sljit_ins)1 << 21; - return push_inst(compiler, VDUP | ins | VN(vreg) | RD(src)); + return push_inst(compiler, VDUP | ins | VN(freg) | RD(src)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, sljit_s32 lane_index, + sljit_s32 freg, sljit_s32 lane_index, sljit_s32 srcdst, sljit_sw srcdstw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -4231,7 +4168,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile sljit_ins ins; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_lane_mov(compiler, type, vreg, lane_index, srcdst, srcdstw)); + CHECK(check_sljit_emit_simd_lane_mov(compiler, type, freg, lane_index, srcdst, srcdstw)); ADJUST_LOCAL_OFFSET(srcdst, srcdstw); @@ -4245,7 +4182,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile return SLJIT_SUCCESS; if (reg_size == 4) - vreg = simd_get_quad_reg_index(vreg); + freg = simd_get_quad_reg_index(freg); if (type & SLJIT_SIMD_LANE_ZERO) { ins = (reg_size == 3) ? 0 : ((sljit_ins)1 << 6); @@ -4253,62 +4190,62 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile if (type & SLJIT_SIMD_FLOAT) { if (elem_size == 3 && !(srcdst & SLJIT_MEM)) { if (lane_index == 1) - vreg += SLJIT_QUAD_OTHER_HALF(vreg); + freg += SLJIT_QUAD_OTHER_HALF(freg); - if (srcdst != vreg) - FAIL_IF(push_inst(compiler, VORR | VD(vreg) | VN(srcdst) | VM(srcdst))); + if (srcdst != freg) + FAIL_IF(push_inst(compiler, VORR | VD(freg) | VN(srcdst) | VM(srcdst))); - vreg += SLJIT_QUAD_OTHER_HALF(vreg); - return push_inst(compiler, VMOV_i | VD(vreg)); + freg += SLJIT_QUAD_OTHER_HALF(freg); + return push_inst(compiler, VMOV_i | VD(freg)); } - if (srcdst == vreg || (elem_size == 3 && srcdst == (vreg + SLJIT_QUAD_OTHER_HALF(vreg)))) { - FAIL_IF(push_inst(compiler, VORR | ins | VD(TMP_FREG2) | VN(vreg) | VM(vreg))); + if (srcdst == freg || (elem_size == 3 && srcdst == (freg + SLJIT_QUAD_OTHER_HALF(freg)))) { + FAIL_IF(push_inst(compiler, VORR | ins | VD(TMP_FREG2) | VN(freg) | VM(freg))); srcdst = TMP_FREG2; srcdstw = 0; } } - FAIL_IF(push_inst(compiler, VMOV_i | ins | VD(vreg))); + FAIL_IF(push_inst(compiler, VMOV_i | ins | VD(freg))); } if (reg_size == 4 && lane_index >= (0x8 >> elem_size)) { lane_index -= (0x8 >> elem_size); - vreg += SLJIT_QUAD_OTHER_HALF(vreg); + freg += SLJIT_QUAD_OTHER_HALF(freg); } if (srcdst & SLJIT_MEM) { if (elem_size == 3) - return emit_fop_mem(compiler, ((type & SLJIT_SIMD_STORE) ? 0 : FPU_LOAD) | SLJIT_32, vreg, srcdst, srcdstw); + return emit_fop_mem(compiler, ((type & SLJIT_SIMD_STORE) ? 0 : FPU_LOAD) | SLJIT_32, freg, srcdst, srcdstw); FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw)); lane_index = lane_index << elem_size; ins = (sljit_ins)((elem_size << 10) | (lane_index << 5)); - return push_inst(compiler, ((type & SLJIT_SIMD_STORE) ? VST1_s : VLD1_s) | ins | VD(vreg) | RN(srcdst) | 0xf); + return push_inst(compiler, ((type & SLJIT_SIMD_STORE) ? VST1_s : VLD1_s) | ins | VD(freg) | RN(srcdst) | 0xf); } if (type & SLJIT_SIMD_FLOAT) { if (elem_size == 3) { if (type & SLJIT_SIMD_STORE) - return push_inst(compiler, VORR | VD(srcdst) | VN(vreg) | VM(vreg)); - return push_inst(compiler, VMOV_F32 | SLJIT_32 | VD(vreg) | VM(srcdst)); + return push_inst(compiler, VORR | VD(srcdst) | VN(freg) | VM(freg)); + return push_inst(compiler, VMOV_F32 | SLJIT_32 | VD(freg) | VM(srcdst)); } if (type & SLJIT_SIMD_STORE) { - if (freg_ebit_map[vreg] == 0) { + if (freg_ebit_map[freg] == 0) { if (lane_index == 1) - vreg = SLJIT_F64_SECOND(vreg); + freg = SLJIT_F64_SECOND(freg); - return push_inst(compiler, VMOV_F32 | VD(srcdst) | VM(vreg)); + return push_inst(compiler, VMOV_F32 | VD(srcdst) | VM(freg)); } - FAIL_IF(push_inst(compiler, VMOV_s | (1 << 20) | ((sljit_ins)lane_index << 21) | VN(vreg) | RD(TMP_REG1))); + FAIL_IF(push_inst(compiler, VMOV_s | (1 << 20) | ((sljit_ins)lane_index << 21) | VN(freg) | RD(TMP_REG1))); return push_inst(compiler, VMOV | VN(srcdst) | RD(TMP_REG1)); } FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(srcdst) | RD(TMP_REG1))); - return push_inst(compiler, VMOV_s | ((sljit_ins)lane_index << 21) | VN(vreg) | RD(TMP_REG1)); + return push_inst(compiler, VMOV_s | ((sljit_ins)lane_index << 21) | VN(freg) | RD(TMP_REG1)); } if (srcdst == SLJIT_IMM) { @@ -4336,11 +4273,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile ins |= (1 << 23); } - return push_inst(compiler, VMOV_s | ins | VN(vreg) | RD(srcdst)); + return push_inst(compiler, VMOV_s | ins | VN(freg) | RD(srcdst)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_s32 src_lane_index) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -4348,7 +4285,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c sljit_ins ins; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, vreg, src, src_lane_index)); + CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, freg, src, src_lane_index)); if (reg_size != 3 && reg_size != 4) return SLJIT_ERR_UNSUPPORTED; @@ -4360,7 +4297,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c return SLJIT_SUCCESS; if (reg_size == 4) { - vreg = simd_get_quad_reg_index(vreg); + freg = simd_get_quad_reg_index(freg); src = simd_get_quad_reg_index(src); if (src_lane_index >= (0x8 >> elem_size)) { @@ -4370,13 +4307,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c } if (elem_size == 3) { - if (vreg != src) - FAIL_IF(push_inst(compiler, VORR | VD(vreg) | VN(src) | VM(src))); + if (freg != src) + FAIL_IF(push_inst(compiler, VORR | VD(freg) | VN(src) | VM(src))); - vreg += SLJIT_QUAD_OTHER_HALF(vreg); + freg += SLJIT_QUAD_OTHER_HALF(freg); - if (vreg != src) - return push_inst(compiler, VORR | VD(vreg) | VN(src) | VM(src)); + if (freg != src) + return push_inst(compiler, VORR | VD(freg) | VN(src) | VM(src)); return SLJIT_SUCCESS; } @@ -4385,11 +4322,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c if (reg_size == 4) ins |= (sljit_ins)1 << 6; - return push_inst(compiler, VDUP_s | ins | VD(vreg) | VM(src)); + return push_inst(compiler, VDUP_s | ins | VD(freg) | VM(src)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_sw srcw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -4398,7 +4335,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler sljit_s32 dst_reg; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_extend(compiler, type, vreg, src, srcw)); + CHECK(check_sljit_emit_simd_extend(compiler, type, freg, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); @@ -4412,20 +4349,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler return SLJIT_SUCCESS; if (reg_size == 4) - vreg = simd_get_quad_reg_index(vreg); + freg = simd_get_quad_reg_index(freg); if (src & SLJIT_MEM) { FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw)); if (reg_size == 4 && elem2_size - elem_size == 1) - FAIL_IF(push_inst(compiler, VLD1 | (0x7 << 8) | VD(vreg) | RN(src) | 0xf)); + FAIL_IF(push_inst(compiler, VLD1 | (0x7 << 8) | VD(freg) | RN(src) | 0xf)); else - FAIL_IF(push_inst(compiler, VLD1_s | (sljit_ins)((reg_size - elem2_size + elem_size) << 10) | VD(vreg) | RN(src) | 0xf)); - src = vreg; + FAIL_IF(push_inst(compiler, VLD1_s | (sljit_ins)((reg_size - elem2_size + elem_size) << 10) | VD(freg) | RN(src) | 0xf)); + src = freg; } else if (reg_size == 4) src = simd_get_quad_reg_index(src); if (!(type & SLJIT_SIMD_FLOAT)) { - dst_reg = (reg_size == 4) ? vreg : TMP_FREG2; + dst_reg = (reg_size == 4) ? freg : TMP_FREG2; do { FAIL_IF(push_inst(compiler, VSHLL | ((type & SLJIT_SIMD_EXTEND_SIGNED) ? 0 : (1 << 24)) @@ -4434,27 +4371,27 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler } while (++elem_size < elem2_size); if (dst_reg == TMP_FREG2) - return push_inst(compiler, VORR | VD(vreg) | VN(TMP_FREG2) | VM(TMP_FREG2)); + return push_inst(compiler, VORR | VD(freg) | VN(TMP_FREG2) | VM(TMP_FREG2)); return SLJIT_SUCCESS; } /* No SIMD variant, must use VFP instead. */ SLJIT_ASSERT(reg_size == 4); - if (vreg == src) { - vreg += SLJIT_QUAD_OTHER_HALF(vreg); - FAIL_IF(push_inst(compiler, VCVT_F64_F32 | VD(vreg) | VM(src) | 0x20)); - vreg += SLJIT_QUAD_OTHER_HALF(vreg); - return push_inst(compiler, VCVT_F64_F32 | VD(vreg) | VM(src)); + if (freg == src) { + freg += SLJIT_QUAD_OTHER_HALF(freg); + FAIL_IF(push_inst(compiler, VCVT_F64_F32 | VD(freg) | VM(src) | 0x20)); + freg += SLJIT_QUAD_OTHER_HALF(freg); + return push_inst(compiler, VCVT_F64_F32 | VD(freg) | VM(src)); } - FAIL_IF(push_inst(compiler, VCVT_F64_F32 | VD(vreg) | VM(src))); - vreg += SLJIT_QUAD_OTHER_HALF(vreg); - return push_inst(compiler, VCVT_F64_F32 | VD(vreg) | VM(src) | 0x20); + FAIL_IF(push_inst(compiler, VCVT_F64_F32 | VD(freg) | VM(src))); + freg += SLJIT_QUAD_OTHER_HALF(freg); + return push_inst(compiler, VCVT_F64_F32 | VD(freg) | VM(src) | 0x20); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 dst, sljit_sw dstw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -4463,7 +4400,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c sljit_s32 dst_r; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_sign(compiler, type, vreg, dst, dstw)); + CHECK(check_sljit_emit_simd_sign(compiler, type, freg, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); @@ -4496,12 +4433,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c } if (reg_size == 4) { - vreg = simd_get_quad_reg_index(vreg); + freg = simd_get_quad_reg_index(freg); ins |= (sljit_ins)1 << 6; } SLJIT_ASSERT((freg_map[TMP_FREG2] & 0x1) == 0); - FAIL_IF(push_inst(compiler, ins | VD(TMP_FREG2) | VM(vreg))); + FAIL_IF(push_inst(compiler, ins | VD(TMP_FREG2) | VM(freg))); if (reg_size == 4 && elem_size > 0) FAIL_IF(push_inst(compiler, VMOVN | ((sljit_ins)(elem_size - 1) << 18) | VD(TMP_FREG2) | VM(TMP_FREG2))); @@ -4531,16 +4468,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w) + sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); - sljit_s32 alignment; - sljit_ins ins = 0, load_ins; + sljit_ins ins = 0; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w)); - ADJUST_LOCAL_OFFSET(src2, src2w); + CHECK(check_sljit_emit_simd_op2(compiler, type, dst_freg, src1_freg, src2_freg)); if (reg_size != 3 && reg_size != 4) return SLJIT_ERR_UNSUPPORTED; @@ -4548,9 +4483,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *co if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3)) return SLJIT_ERR_UNSUPPORTED; - if (type & SLJIT_SIMD_TEST) - return SLJIT_SUCCESS; - switch (SLJIT_SIMD_GET_OPCODE(type)) { case SLJIT_SIMD_OP2_AND: ins = VAND; @@ -4561,51 +4493,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *co case SLJIT_SIMD_OP2_XOR: ins = VEOR; break; - case SLJIT_SIMD_OP2_SHUFFLE: - ins = VTBL; - break; } - if (src2 & SLJIT_MEM) { - if (elem_size > 3) - elem_size = 3; - - load_ins = VLD1 | (sljit_ins)((reg_size == 3) ? (0x7 << 8) : (0xa << 8)); - alignment = SLJIT_SIMD_GET_ELEM2_SIZE(type); - - SLJIT_ASSERT(reg_size >= alignment); - - if (alignment == 3) - load_ins |= 0x10; - else if (alignment >= 4) - load_ins |= 0x20; - - FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src2, src2w)); - FAIL_IF(push_inst(compiler, load_ins | VD(TMP_FREG2) | RN(src2) | ((sljit_ins)elem_size) << 6 | 0xf)); - src2 = TMP_FREG2; - } + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; if (reg_size == 4) { - dst_vreg = simd_get_quad_reg_index(dst_vreg); - src1_vreg = simd_get_quad_reg_index(src1_vreg); - src2 = simd_get_quad_reg_index(src2); - - if (SLJIT_SIMD_GET_OPCODE(type) == SLJIT_SIMD_OP2_SHUFFLE) { - ins |= (sljit_ins)1 << 8; - - FAIL_IF(push_inst(compiler, ins | VD(dst_vreg != src1_vreg ? dst_vreg : TMP_FREG2) | VN(src1_vreg) | VM(src2))); - src2 += SLJIT_QUAD_OTHER_HALF(src2); - FAIL_IF(push_inst(compiler, ins | VD(dst_vreg + SLJIT_QUAD_OTHER_HALF(dst_vreg)) | VN(src1_vreg) | VM(src2))); - - if (dst_vreg == src1_vreg) - return push_inst(compiler, VORR | VD(dst_vreg) | VN(TMP_FREG2) | VM(TMP_FREG2)); - return SLJIT_SUCCESS; - } - + dst_freg = simd_get_quad_reg_index(dst_freg); + src1_freg = simd_get_quad_reg_index(src1_freg); + src2_freg = simd_get_quad_reg_index(src2_freg); ins |= (sljit_ins)1 << 6; } - return push_inst(compiler, ins | VD(dst_vreg) | VN(src1_vreg) | VM(src2)); + return push_inst(compiler, ins | VD(dst_freg) | VN(src1_freg) | VM(src2_freg)); } #undef FPU_LOAD @@ -4619,15 +4519,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler CHECK_ERROR(); CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg)); - if (op & SLJIT_ATOMIC_USE_CAS) - return SLJIT_ERR_UNSUPPORTED; - switch (GET_OPCODE(op)) { - case SLJIT_MOV_S8: - case SLJIT_MOV_S16: - case SLJIT_MOV_S32: - return SLJIT_ERR_UNSUPPORTED; - case SLJIT_MOV_U8: ins = LDREXB; break; @@ -4639,9 +4531,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler break; } - if (op & SLJIT_ATOMIC_TEST) - return SLJIT_SUCCESS; - return push_inst(compiler, ins | RN(mem_reg) | RD(dst_reg)); } @@ -4658,15 +4547,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler CHECK_ERROR(); CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg)); - if (op & SLJIT_ATOMIC_USE_CAS) - return SLJIT_ERR_UNSUPPORTED; - switch (GET_OPCODE(op)) { - case SLJIT_MOV_S8: - case SLJIT_MOV_S16: - case SLJIT_MOV_S32: - return SLJIT_ERR_UNSUPPORTED; - case SLJIT_MOV_U8: ins = STREXB; break; @@ -4678,9 +4559,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler break; } - if (op & SLJIT_ATOMIC_TEST) - return SLJIT_SUCCESS; - FAIL_IF(push_inst(compiler, ins | RN(mem_reg) | RD(TMP_REG1) | RM(src_reg))); if (op & SLJIT_SET_ATOMIC_STORED) return push_inst(compiler, CMP | SET_FLAGS | SRC2_IMM | RN(TMP_REG1)); diff --git a/ext/pcre/pcre2lib/sljit/sljitNativeARM_64.c b/ext/pcre/pcre2lib/sljit/sljitNativeARM_64.c index d80c9e546ee79..5331ebdf42962 100644 --- a/ext/pcre/pcre2lib/sljit/sljitNativeARM_64.c +++ b/ext/pcre/pcre2lib/sljit/sljitNativeARM_64.c @@ -91,7 +91,6 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define CLZ 0xdac01000 #define CSEL 0x9a800000 #define CSINC 0x9a800400 -#define DMB_SY 0xd5033fbf #define DUP_e 0x0e000400 #define DUP_g 0x0e000c00 #define EOR 0xca000000 @@ -172,7 +171,6 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define SUBI 0xd1000000 #define SUBS 0xeb000000 #define TBZ 0x36000000 -#define TBL_v 0x0e000000 #define UBFM 0xd3400000 #define UCVTF 0x9e630000 #define UDIV 0x9ac00800 @@ -210,11 +208,7 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i { sljit_sw diff; sljit_uw target_addr; - sljit_uw jump_addr = (sljit_uw)code_ptr; - sljit_uw orig_addr = jump->addr; - SLJIT_UNUSED_ARG(executable_offset); - jump->addr = jump_addr; if (jump->flags & SLJIT_REWRITABLE_JUMP) goto exit; @@ -222,13 +216,10 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i target_addr = jump->u.target; else { SLJIT_ASSERT(jump->u.label != NULL); - target_addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset); - - if (jump->u.label->size > orig_addr) - jump_addr = (sljit_uw)(code + orig_addr); + target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset; } - diff = (sljit_sw)target_addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset); + diff = (sljit_sw)target_addr - (sljit_sw)code_ptr - executable_offset; if (jump->flags & IS_COND) { diff += SSIZE_OF(ins); @@ -280,21 +271,16 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset) { sljit_uw addr; - sljit_uw jump_addr = (sljit_uw)code_ptr; sljit_sw diff; SLJIT_UNUSED_ARG(executable_offset); SLJIT_ASSERT(jump->flags < ((sljit_uw)4 << JUMP_SIZE_SHIFT)); if (jump->flags & JUMP_ADDR) addr = jump->u.target; - else { + else addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset); - if (jump->u.label->size > jump->addr) - jump_addr = (sljit_uw)(code + jump->addr); - } - - diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset); + diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); if (diff <= 0xfffff && diff >= -0x100000) { jump->flags |= PATCH_B; @@ -436,10 +422,6 @@ static void reduce_code_size(struct sljit_compiler *compiler) } else { /* Unit size: instruction. */ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr; - if (jump->u.label->size > jump->addr) { - SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr); - diff -= (sljit_sw)size_reduce; - } if ((jump->flags & IS_COND) && (diff + 1) <= (0xfffff / SSIZE_OF(ins)) && (diff + 1) >= (-0x100000 / SSIZE_OF(ins))) total_size = 0; @@ -457,10 +439,6 @@ static void reduce_code_size(struct sljit_compiler *compiler) if (!(jump->flags & JUMP_ADDR)) { diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr; - if (jump->u.label->size > jump->addr) { - SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr); - diff -= (sljit_sw)size_reduce; - } if (diff <= (0xfffff / SSIZE_OF(ins)) && diff >= (-0x100000 / SSIZE_OF(ins))) total_size = 0; @@ -538,6 +516,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil if (next_min_addr == next_jump_addr) { if (!(jump->flags & JUMP_MOV_ADDR)) { word_count = word_count - 1 + (jump->flags >> JUMP_SIZE_SHIFT); + jump->addr = (sljit_uw)code_ptr; code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset); SLJIT_ASSERT((jump->flags & PATCH_COND) || ((sljit_uw)code_ptr - jump->addr < (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins))); } else { @@ -614,7 +593,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) case SLJIT_HAS_COPY_F32: case SLJIT_HAS_COPY_F64: case SLJIT_HAS_ATOMIC: - case SLJIT_HAS_MEMORY_BARRIER: return 1; default: @@ -1230,23 +1208,16 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, s /* --------------------------------------------------------------------- */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 fscratches; - sljit_s32 fsaveds; sljit_s32 prev, fprev, saved_regs_size, i, tmp; sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options); sljit_ins offs; CHECK_ERROR(); - CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size)); - set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size); - - scratches = ENTER_GET_REGS(scratches); - saveds = ENTER_GET_REGS(saveds); - fscratches = compiler->fscratches; - fsaveds = compiler->fsaveds; + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 2); saved_regs_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); @@ -1412,21 +1383,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 fscratches; - sljit_s32 fsaveds; sljit_s32 saved_regs_size; CHECK_ERROR(); - CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size)); - set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size); + CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); - scratches = ENTER_GET_REGS(scratches); - saveds = ENTER_GET_REGS(saveds); - fscratches = compiler->fscratches; - fsaveds = compiler->fsaveds; saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 2); saved_regs_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); @@ -1572,7 +1537,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile op = GET_OPCODE(op); switch (op) { case SLJIT_BREAKPOINT: - return push_inst(compiler, BRK | (0xf000 << 5)); + return push_inst(compiler, BRK); case SLJIT_NOP: return push_inst(compiler, NOP); case SLJIT_LMUL_UW: @@ -1589,8 +1554,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile case SLJIT_DIV_UW: case SLJIT_DIV_SW: return push_inst(compiler, ((op == SLJIT_DIV_UW ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1)); - case SLJIT_MEMORY_BARRIER: - return push_inst(compiler, DMB_SY); case SLJIT_ENDBR: case SLJIT_SKIP_FRAMES_BEFORE_RETURN: return SLJIT_SUCCESS; @@ -2812,7 +2775,7 @@ static sljit_s32 sljit_emit_simd_mem_offset(struct sljit_compiler *compiler, slj } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 srcdst, sljit_sw srcdstw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -2820,7 +2783,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *co sljit_ins ins; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_mov(compiler, type, vreg, srcdst, srcdstw)); + CHECK(check_sljit_emit_simd_mov(compiler, type, freg, srcdst, srcdstw)); ADJUST_LOCAL_OFFSET(srcdst, srcdstw); @@ -2835,9 +2798,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *co if (!(srcdst & SLJIT_MEM)) { if (type & SLJIT_SIMD_STORE) - ins = VD(srcdst) | VN(vreg) | VM(vreg); + ins = VD(srcdst) | VN(freg) | VM(freg); else - ins = VD(vreg) | VN(srcdst) | VM(srcdst); + ins = VD(freg) | VN(srcdst) | VM(srcdst); if (reg_size == 4) ins |= (1 << 30); @@ -2855,7 +2818,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *co if (reg_size == 4) ins |= (1 << 30); - return push_inst(compiler, ins | ((sljit_ins)elem_size << 10) | RN(srcdst) | VT(vreg)); + return push_inst(compiler, ins | ((sljit_ins)elem_size << 10) | RN(srcdst) | VT(freg)); } static sljit_ins simd_get_imm(sljit_s32 elem_size, sljit_uw value) @@ -2960,7 +2923,7 @@ static sljit_ins simd_get_imm(sljit_s32 elem_size, sljit_uw value) } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_sw srcw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -2968,7 +2931,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil sljit_ins ins, imm; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_replicate(compiler, type, vreg, src, srcw)); + CHECK(check_sljit_emit_simd_replicate(compiler, type, freg, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); @@ -2989,7 +2952,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil if (reg_size == 4) ins |= (sljit_ins)1 << 30; - return push_inst(compiler, LD1R | ins | RN(src) | VT(vreg)); + return push_inst(compiler, LD1R | ins | RN(src) | VT(freg)); } ins = (sljit_ins)1 << (16 + elem_size); @@ -2999,9 +2962,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil if (type & SLJIT_SIMD_FLOAT) { if (src == SLJIT_IMM) - return push_inst(compiler, MOVI | (ins & ((sljit_ins)1 << 30)) | VD(vreg)); + return push_inst(compiler, MOVI | (ins & ((sljit_ins)1 << 30)) | VD(freg)); - return push_inst(compiler, DUP_e | ins | VD(vreg) | VN(src)); + return push_inst(compiler, DUP_e | ins | VD(freg) | VN(src)); } if (src == SLJIT_IMM) { @@ -3013,18 +2976,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil if (imm != ~(sljit_ins)0) { imm |= ins & ((sljit_ins)1 << 30); - return push_inst(compiler, MOVI | imm | VD(vreg)); + return push_inst(compiler, MOVI | imm | VD(freg)); } FAIL_IF(load_immediate(compiler, TMP_REG2, srcw)); src = TMP_REG2; } - return push_inst(compiler, DUP_g | ins | VD(vreg) | RN(src)); + return push_inst(compiler, DUP_g | ins | VD(freg) | RN(src)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, sljit_s32 lane_index, + sljit_s32 freg, sljit_s32 lane_index, sljit_s32 srcdst, sljit_sw srcdstw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -3032,7 +2995,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile sljit_ins ins; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_lane_mov(compiler, type, vreg, lane_index, srcdst, srcdstw)); + CHECK(check_sljit_emit_simd_lane_mov(compiler, type, freg, lane_index, srcdst, srcdstw)); ADJUST_LOCAL_OFFSET(srcdst, srcdstw); @@ -3048,13 +3011,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile if (type & SLJIT_SIMD_LANE_ZERO) { ins = (reg_size == 3) ? 0 : ((sljit_ins)1 << 30); - if ((type & SLJIT_SIMD_FLOAT) && vreg == srcdst) { - FAIL_IF(push_inst(compiler, ORR_v | ins | VD(TMP_FREG1) | VN(vreg) | VM(vreg))); + if ((type & SLJIT_SIMD_FLOAT) && freg == srcdst) { + FAIL_IF(push_inst(compiler, ORR_v | ins | VD(TMP_FREG1) | VN(freg) | VM(freg))); srcdst = TMP_FREG1; srcdstw = 0; } - FAIL_IF(push_inst(compiler, MOVI | ins | VD(vreg))); + FAIL_IF(push_inst(compiler, MOVI | ins | VD(freg))); } if (srcdst & SLJIT_MEM) { @@ -3070,14 +3033,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile lane_index = lane_index << elem_size; ins |= (sljit_ins)(((lane_index & 0x8) << 27) | ((lane_index & 0x7) << 10)); - return push_inst(compiler, ((type & SLJIT_SIMD_STORE) ? ST1_s : LD1_s) | ins | RN(srcdst) | VT(vreg)); + return push_inst(compiler, ((type & SLJIT_SIMD_STORE) ? ST1_s : LD1_s) | ins | RN(srcdst) | VT(freg)); } if (type & SLJIT_SIMD_FLOAT) { if (type & SLJIT_SIMD_STORE) - ins = INS_e | ((sljit_ins)1 << (16 + elem_size)) | ((sljit_ins)lane_index << (11 + elem_size)) | VD(srcdst) | VN(vreg); + ins = INS_e | ((sljit_ins)1 << (16 + elem_size)) | ((sljit_ins)lane_index << (11 + elem_size)) | VD(srcdst) | VN(freg); else - ins = INS_e | ((((sljit_ins)lane_index << 1) | 1) << (16 + elem_size)) | VD(vreg) | VN(srcdst); + ins = INS_e | ((((sljit_ins)lane_index << 1) | 1) << (16 + elem_size)) | VD(freg) | VN(srcdst); return push_inst(compiler, ins); } @@ -3091,7 +3054,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile } if (type & SLJIT_SIMD_STORE) { - ins = RD(srcdst) | VN(vreg); + ins = RD(srcdst) | VN(freg); if ((type & SLJIT_SIMD_LANE_SIGNED) && (elem_size < 2 || (elem_size == 2 && !(type & SLJIT_32)))) { ins |= SMOV; @@ -3101,7 +3064,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile } else ins |= UMOV; } else - ins = INS | VD(vreg) | RN(srcdst); + ins = INS | VD(freg) | RN(srcdst); if (elem_size == 3) ins |= (sljit_ins)1 << 30; @@ -3110,7 +3073,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_s32 src_lane_index) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -3118,7 +3081,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c sljit_ins ins; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, vreg, src, src_lane_index)); + CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, freg, src, src_lane_index)); if (reg_size != 3 && reg_size != 4) return SLJIT_ERR_UNSUPPORTED; @@ -3134,11 +3097,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c if (reg_size == 4) ins |= (sljit_ins)1 << 30; - return push_inst(compiler, DUP_e | ins | VD(vreg) | VN(src)); + return push_inst(compiler, DUP_e | ins | VD(freg) | VN(src)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_sw srcw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -3146,7 +3109,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler sljit_s32 elem2_size = SLJIT_SIMD_GET_ELEM2_SIZE(type); CHECK_ERROR(); - CHECK(check_sljit_emit_simd_extend(compiler, type, vreg, src, srcw)); + CHECK(check_sljit_emit_simd_extend(compiler, type, freg, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); @@ -3163,28 +3126,28 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw)); if (reg_size == 4 && elem2_size - elem_size == 1) - FAIL_IF(push_inst(compiler, LD1 | ((sljit_ins)elem_size << 10) | RN(src) | VT(vreg))); + FAIL_IF(push_inst(compiler, LD1 | ((sljit_ins)elem_size << 10) | RN(src) | VT(freg))); else - FAIL_IF(push_inst(compiler, LD1_s | ((sljit_ins)0x2000 << (reg_size - elem2_size + elem_size)) | RN(src) | VT(vreg))); - src = vreg; + FAIL_IF(push_inst(compiler, LD1_s | ((sljit_ins)0x2000 << (reg_size - elem2_size + elem_size)) | RN(src) | VT(freg))); + src = freg; } if (type & SLJIT_SIMD_FLOAT) { SLJIT_ASSERT(reg_size == 4); - return push_inst(compiler, FCVTL | (1 << 22) | VD(vreg) | VN(src)); + return push_inst(compiler, FCVTL | (1 << 22) | VD(freg) | VN(src)); } do { FAIL_IF(push_inst(compiler, ((type & SLJIT_SIMD_EXTEND_SIGNED) ? SSHLL : USHLL) - | ((sljit_ins)1 << (19 + elem_size)) | VD(vreg) | VN(src))); - src = vreg; + | ((sljit_ins)1 << (19 + elem_size)) | VD(freg) | VN(src))); + src = freg; } while (++elem_size < elem2_size); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 dst, sljit_sw dstw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -3193,7 +3156,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c sljit_s32 dst_r; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_sign(compiler, type, vreg, dst, dstw)); + CHECK(check_sljit_emit_simd_sign(compiler, type, freg, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); @@ -3228,7 +3191,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c if (reg_size == 4) ins |= (1 << 30); - FAIL_IF(push_inst(compiler, ins | VD(TMP_FREG1) | VN(vreg))); + FAIL_IF(push_inst(compiler, ins | VD(TMP_FREG1) | VN(freg))); if (reg_size == 4 && elem_size > 0) FAIL_IF(push_inst(compiler, XTN | ((sljit_ins)(elem_size - 1) << 22) | VD(TMP_FREG1) | VN(TMP_FREG1))); @@ -3261,15 +3224,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w) + sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); sljit_ins ins = 0; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w)); - ADJUST_LOCAL_OFFSET(src2, src2w); + CHECK(check_sljit_emit_simd_op2(compiler, type, dst_freg, src1_freg, src2_freg)); if (reg_size != 3 && reg_size != 4) return SLJIT_ERR_UNSUPPORTED; @@ -3277,9 +3239,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *co if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3)) return SLJIT_ERR_UNSUPPORTED; - if (type & SLJIT_SIMD_TEST) - return SLJIT_SUCCESS; - switch (SLJIT_SIMD_GET_OPCODE(type)) { case SLJIT_SIMD_OP2_AND: ins = AND_v; @@ -3290,24 +3249,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *co case SLJIT_SIMD_OP2_XOR: ins = EOR_v; break; - case SLJIT_SIMD_OP2_SHUFFLE: - ins = TBL_v; - break; } - if (src2 & SLJIT_MEM) { - if (elem_size > 3) - elem_size = 3; - - FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src2, src2w)); - push_inst(compiler, LD1 | (reg_size == 4 ? (1 << 30) : 0) | ((sljit_ins)elem_size << 10) | RN(src2) | VT(TMP_FREG1)); - src2 = TMP_FREG1; - } + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; if (reg_size == 4) ins |= (sljit_ins)1 << 30; - return push_inst(compiler, ins | VD(dst_vreg) | VN(src1_vreg) | VM(src2)); + return push_inst(compiler, ins | VD(dst_freg) | VN(src1_freg) | VM(src2_freg)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op, @@ -3319,55 +3269,39 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler CHECK_ERROR(); CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg)); -#ifndef __ARM_FEATURE_ATOMICS - if (op & SLJIT_ATOMIC_USE_CAS) - return SLJIT_ERR_UNSUPPORTED; -#endif /* ARM_FEATURE_ATOMICS */ - +#ifdef __ARM_FEATURE_ATOMICS switch (GET_OPCODE(op)) { - case SLJIT_MOV_S8: - case SLJIT_MOV_S16: - case SLJIT_MOV_S32: - return SLJIT_ERR_UNSUPPORTED; - case SLJIT_MOV32: case SLJIT_MOV_U32: -#ifdef __ARM_FEATURE_ATOMICS - if (!(op & SLJIT_ATOMIC_USE_LS)) - ins = LDR ^ (1 << 30); - else -#endif /* ARM_FEATURE_ATOMICS */ - ins = LDXR ^ (1 << 30); + ins = LDR ^ (1 << 30); + break; + case SLJIT_MOV_U16: + ins = LDRH; break; case SLJIT_MOV_U8: -#ifdef __ARM_FEATURE_ATOMICS - if (!(op & SLJIT_ATOMIC_USE_LS)) - ins = LDRB; - else -#endif /* ARM_FEATURE_ATOMICS */ - ins = LDXRB; + ins = LDRB; + break; + default: + ins = LDR; + break; + } +#else /* !__ARM_FEATURE_ATOMICS */ + switch (GET_OPCODE(op)) { + case SLJIT_MOV32: + case SLJIT_MOV_U32: + ins = LDXR ^ (1 << 30); + break; + case SLJIT_MOV_U8: + ins = LDXRB; break; case SLJIT_MOV_U16: -#ifdef __ARM_FEATURE_ATOMICS - if (!(op & SLJIT_ATOMIC_USE_LS)) - ins = LDRH; - else -#endif /* ARM_FEATURE_ATOMICS */ - ins = LDXRH; + ins = LDXRH; break; default: -#ifdef __ARM_FEATURE_ATOMICS - if (!(op & SLJIT_ATOMIC_USE_LS)) - ins = LDR; - else -#endif /* ARM_FEATURE_ATOMICS */ - ins = LDXR; + ins = LDXR; break; } - - if (op & SLJIT_ATOMIC_TEST) - return SLJIT_SUCCESS; - +#endif /* ARM_FEATURE_ATOMICS */ return push_inst(compiler, ins | RN(mem_reg) | RT(dst_reg)); } @@ -3377,65 +3311,55 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler sljit_s32 temp_reg) { sljit_ins ins; + sljit_s32 tmp = temp_reg; sljit_ins cmp = 0; + sljit_ins inv_bits = W_OP; CHECK_ERROR(); CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg)); #ifdef __ARM_FEATURE_ATOMICS - if (!(op & SLJIT_ATOMIC_USE_LS)) { - if (op & SLJIT_SET_ATOMIC_STORED) - cmp = (SUBS ^ W_OP) | RD(TMP_ZERO); - - switch (GET_OPCODE(op)) { - case SLJIT_MOV_S8: - case SLJIT_MOV_S16: - case SLJIT_MOV_S32: - return SLJIT_ERR_UNSUPPORTED; - - case SLJIT_MOV32: - case SLJIT_MOV_U32: - ins = CAS ^ (1 << 30); - break; - case SLJIT_MOV_U16: - ins = CASH; - break; - case SLJIT_MOV_U8: - ins = CASB; - break; - default: - ins = CAS; - if (cmp) - cmp ^= W_OP; - break; - } - - if (op & SLJIT_ATOMIC_TEST) - return SLJIT_SUCCESS; + if (op & SLJIT_SET_ATOMIC_STORED) + cmp = (SUBS ^ W_OP) | RD(TMP_ZERO); + switch (GET_OPCODE(op)) { + case SLJIT_MOV32: + case SLJIT_MOV_U32: + ins = CAS ^ (1 << 30); + break; + case SLJIT_MOV_U16: + ins = CASH; + break; + case SLJIT_MOV_U8: + ins = CASB; + break; + default: + ins = CAS; + inv_bits = 0; if (cmp) - FAIL_IF(push_inst(compiler, ((MOV ^ W_OP) ^ (cmp & W_OP)) | RM(temp_reg) | RD(TMP_REG2))); - - FAIL_IF(push_inst(compiler, ins | RM(temp_reg) | RN(mem_reg) | RD(src_reg))); - if (!cmp) - return SLJIT_SUCCESS; + cmp ^= W_OP; + break; + } - return push_inst(compiler, cmp | RM(TMP_REG2) | RN(temp_reg)); + if (cmp) { + FAIL_IF(push_inst(compiler, (MOV ^ inv_bits) | RM(temp_reg) | RD(TMP_REG1))); + tmp = TMP_REG1; } + FAIL_IF(push_inst(compiler, ins | RM(tmp) | RN(mem_reg) | RD(src_reg))); + if (!cmp) + return SLJIT_SUCCESS; + + FAIL_IF(push_inst(compiler, cmp | RM(tmp) | RN(temp_reg))); + FAIL_IF(push_inst(compiler, (CSET ^ inv_bits) | RD(tmp))); + return push_inst(compiler, cmp | RM(tmp) | RN(TMP_ZERO)); #else /* !__ARM_FEATURE_ATOMICS */ - if (op & SLJIT_ATOMIC_USE_CAS) - return SLJIT_ERR_UNSUPPORTED; -#endif /* __ARM_FEATURE_ATOMICS */ + SLJIT_UNUSED_ARG(tmp); + SLJIT_UNUSED_ARG(inv_bits); if (op & SLJIT_SET_ATOMIC_STORED) cmp = (SUBI ^ W_OP) | (1 << 29); switch (GET_OPCODE(op)) { - case SLJIT_MOV_S8: - case SLJIT_MOV_S16: - case SLJIT_MOV_S32: - return SLJIT_ERR_UNSUPPORTED; - case SLJIT_MOV32: case SLJIT_MOV_U32: ins = STXR ^ (1 << 30); @@ -3451,13 +3375,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler break; } - if (op & SLJIT_ATOMIC_TEST) - return SLJIT_SUCCESS; - - FAIL_IF(push_inst(compiler, ins | RM(TMP_REG2) | RN(mem_reg) | RT(src_reg))); - if (!cmp) - return SLJIT_SUCCESS; - return push_inst(compiler, cmp | RD(TMP_ZERO) | RN(TMP_REG2)); + FAIL_IF(push_inst(compiler, ins | RM(TMP_REG1) | RN(mem_reg) | RT(src_reg))); + return cmp ? push_inst(compiler, cmp | RD(TMP_ZERO) | RN(TMP_REG1)) : SLJIT_SUCCESS; +#endif /* __ARM_FEATURE_ATOMICS */ } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset) diff --git a/ext/pcre/pcre2lib/sljit/sljitNativeARM_T2_32.c b/ext/pcre/pcre2lib/sljit/sljitNativeARM_T2_32.c index d8058ab6ea4b6..799954a85996f 100644 --- a/ext/pcre/pcre2lib/sljit/sljitNativeARM_T2_32.c +++ b/ext/pcre/pcre2lib/sljit/sljitNativeARM_T2_32.c @@ -138,7 +138,6 @@ static const sljit_u8 freg_ebit_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) << 1) #define CMPI_W 0xf1b00f00 #define CMP_X 0x4500 #define CMP_W 0xebb00f00 -#define DMB_SY 0xf3bf8f5f #define EORI 0xf0800000 #define EORS 0x4040 #define EOR_W 0xea800000 @@ -254,7 +253,6 @@ static const sljit_u8 freg_ebit_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) << 1) #define VST1_s 0xf9800000 #define VSTR_F32 0xed000a00 #define VSUB_F32 0xee300a40 -#define VTBL 0xffb00800 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) @@ -266,28 +264,11 @@ static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s if (is_32 && fr >= SLJIT_F64_SECOND(SLJIT_FR0)) fr -= SLJIT_F64_SECOND(0); - return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->real_fscratches)) - || (fr > (SLJIT_FS0 - compiler->real_fsaveds) && fr <= SLJIT_FS0) + return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->fscratches)) + || (fr > (SLJIT_FS0 - compiler->fsaveds) && fr <= SLJIT_FS0) || (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS)); } -static sljit_s32 function_check_is_vreg(struct sljit_compiler *compiler, sljit_s32 vr, sljit_s32 type) -{ - sljit_s32 vr_low = vr; - - if (compiler->scratches == -1) - return 0; - - if (SLJIT_SIMD_GET_REG_SIZE(type) == 4) { - vr += (vr & 0x1); - vr_low = vr - 1; - } - - return (vr >= SLJIT_VR0 && vr < (SLJIT_VR0 + compiler->vscratches)) - || (vr_low > (SLJIT_VS0 - compiler->vsaveds) && vr_low <= SLJIT_VS0) - || (vr >= SLJIT_TMP_VREGISTER_BASE && vr < (SLJIT_TMP_VREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS)); -} - #endif /* SLJIT_ARGUMENT_CHECKS */ static sljit_s32 push_inst16(struct sljit_compiler *compiler, sljit_ins inst) @@ -339,12 +320,7 @@ static SLJIT_INLINE void modify_imm32_const(sljit_u16 *inst, sljit_uw new_imm) static SLJIT_INLINE sljit_u16* detect_jump_type(struct sljit_jump *jump, sljit_u16 *code_ptr, sljit_u16 *code, sljit_sw executable_offset) { sljit_sw diff; - sljit_uw target_addr; - sljit_uw jump_addr = (sljit_uw)code_ptr; - sljit_uw orig_addr = jump->addr; - SLJIT_UNUSED_ARG(executable_offset); - jump->addr = jump_addr; if (jump->flags & SLJIT_REWRITABLE_JUMP) goto exit; @@ -352,17 +328,12 @@ static SLJIT_INLINE sljit_u16* detect_jump_type(struct sljit_jump *jump, sljit_u /* Branch to ARM code is not optimized yet. */ if (!(jump->u.target & 0x1)) goto exit; - target_addr = jump->u.target; + diff = (sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2) - executable_offset; } else { SLJIT_ASSERT(jump->u.label != NULL); - target_addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset); - - if (jump->u.label->size > orig_addr) - jump_addr = (sljit_uw)(code + orig_addr); + diff = (sljit_sw)(code + jump->u.label->size) - (sljit_sw)(code_ptr + 2); } - diff = (sljit_sw)target_addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr + 4, executable_offset); - if (jump->flags & IS_COND) { SLJIT_ASSERT(!(jump->flags & IS_BL)); /* Size of the prefix IT instruction. */ @@ -409,21 +380,16 @@ static SLJIT_INLINE sljit_u16* detect_jump_type(struct sljit_jump *jump, sljit_u static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_u16 *code_ptr, sljit_u16 *code, sljit_sw executable_offset) { sljit_uw addr; - sljit_uw jump_addr = (sljit_uw)code_ptr; sljit_sw diff; SLJIT_UNUSED_ARG(executable_offset); if (jump->flags & JUMP_ADDR) addr = jump->u.target; - else { + else addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset); - if (jump->u.label->size > jump->addr) - jump_addr = (sljit_uw)(code + jump->addr); - } - /* The pc+4 offset is represented by the 2 * SSIZE_OF(sljit_u16) below. */ - diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset); + diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); /* Note: ADR with imm8 does not set the last bit (Thumb2 flag). */ @@ -551,10 +517,6 @@ static void reduce_code_size(struct sljit_compiler *compiler) if (!(jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR))) { /* Unit size: instruction. */ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr - 2; - if (jump->u.label->size > jump->addr) { - SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr); - diff -= (sljit_sw)size_reduce; - } if (jump->flags & IS_COND) { diff++; @@ -578,10 +540,6 @@ static void reduce_code_size(struct sljit_compiler *compiler) if (!(jump->flags & JUMP_ADDR)) { diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr; - if (jump->u.label->size > jump->addr) { - SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr); - diff -= (sljit_sw)size_reduce; - } if (diff <= (0xffd / SSIZE_OF(u16)) && diff >= (-0xfff / SSIZE_OF(u16))) total_size = 1; @@ -654,6 +612,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil if (next_min_addr == next_jump_addr) { if (!(jump->flags & JUMP_MOV_ADDR)) { half_count = half_count - 1 + (jump->flags >> JUMP_SIZE_SHIFT); + jump->addr = (sljit_uw)code_ptr; code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset); SLJIT_ASSERT((sljit_uw)code_ptr - jump->addr < ((jump->flags >> JUMP_SIZE_SHIFT) + ((jump->flags & 0xf0) <= PATCH_TYPE2)) * sizeof(sljit_u16)); @@ -735,7 +694,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) case SLJIT_HAS_COPY_F32: case SLJIT_HAS_COPY_F64: case SLJIT_HAS_ATOMIC: - case SLJIT_HAS_MEMORY_BARRIER: return 1; default: @@ -1409,11 +1367,9 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit /* --------------------------------------------------------------------- */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 fscratches; - sljit_s32 fsaveds; sljit_s32 size, i, tmp, word_arg_count; sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options); sljit_uw offset; @@ -1427,13 +1383,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi #endif CHECK_ERROR(); - CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size)); - set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size); - - scratches = ENTER_GET_REGS(scratches); - saveds = ENTER_GET_REGS(saveds); - fscratches = compiler->fscratches; - fsaveds = compiler->fsaveds; + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); tmp = SLJIT_S0 - saveds; for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) @@ -1626,21 +1577,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 fscratches; - sljit_s32 fsaveds; sljit_s32 size; CHECK_ERROR(); - CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size)); - set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size); + CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); - scratches = ENTER_GET_REGS(scratches); - saveds = ENTER_GET_REGS(saveds); - fscratches = compiler->fscratches; - fsaveds = compiler->fsaveds; size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1); /* Doubles are saved, so alignment is unaffected. */ @@ -1959,8 +1904,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile } return SLJIT_SUCCESS; #endif /* __ARM_FEATURE_IDIV || __ARM_ARCH_EXT_IDIV__ */ - case SLJIT_MEMORY_BARRIER: - return push_inst32(compiler, DMB_SY); case SLJIT_ENDBR: case SLJIT_SKIP_FRAMES_BEFORE_RETURN: return SLJIT_SUCCESS; @@ -2261,7 +2204,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, slji if (type == SLJIT_FLOAT_REGISTER || type == SLJIT_SIMD_REG_64) return freg_map[reg]; - if (type == SLJIT_SIMD_REG_128) + if (type != SLJIT_SIMD_REG_128) return freg_map[reg] & ~0x1; return -1; @@ -3639,7 +3582,7 @@ static SLJIT_INLINE sljit_s32 simd_get_quad_reg_index(sljit_s32 freg) #define SLJIT_QUAD_OTHER_HALF(freg) ((((freg) & 0x1) << 1) - 1) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 srcdst, sljit_sw srcdstw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -3648,7 +3591,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *co sljit_ins ins; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_mov(compiler, type, vreg, srcdst, srcdstw)); + CHECK(check_sljit_emit_simd_mov(compiler, type, freg, srcdst, srcdstw)); ADJUST_LOCAL_OFFSET(srcdst, srcdstw); @@ -3662,16 +3605,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *co return SLJIT_SUCCESS; if (reg_size == 4) - vreg = simd_get_quad_reg_index(vreg); + freg = simd_get_quad_reg_index(freg); if (!(srcdst & SLJIT_MEM)) { if (reg_size == 4) srcdst = simd_get_quad_reg_index(srcdst); if (type & SLJIT_SIMD_STORE) - ins = VD4(srcdst) | VN4(vreg) | VM4(vreg); + ins = VD4(srcdst) | VN4(freg) | VM4(freg); else - ins = VD4(vreg) | VN4(srcdst) | VM4(srcdst); + ins = VD4(freg) | VN4(srcdst) | VM4(srcdst); if (reg_size == 4) ins |= (sljit_ins)1 << 6; @@ -3684,7 +3627,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *co if (elem_size > 3) elem_size = 3; - ins = ((type & SLJIT_SIMD_STORE) ? VST1 : VLD1) | VD4(vreg) + ins = ((type & SLJIT_SIMD_STORE) ? VST1 : VLD1) | VD4(freg) | (sljit_ins)((reg_size == 3) ? (0x7 << 8) : (0xa << 8)); SLJIT_ASSERT(reg_size >= alignment); @@ -3792,7 +3735,7 @@ static sljit_ins simd_get_imm(sljit_s32 elem_size, sljit_uw value) } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_sw srcw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -3800,7 +3743,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil sljit_ins ins, imm; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_replicate(compiler, type, vreg, src, srcw)); + CHECK(check_sljit_emit_simd_replicate(compiler, type, freg, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); @@ -3814,24 +3757,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil return SLJIT_SUCCESS; if (reg_size == 4) - vreg = simd_get_quad_reg_index(vreg); + freg = simd_get_quad_reg_index(freg); if (src == SLJIT_IMM && srcw == 0) - return push_inst32(compiler, VMOV_i | ((reg_size == 4) ? (1 << 6) : 0) | VD4(vreg)); + return push_inst32(compiler, VMOV_i | ((reg_size == 4) ? (1 << 6) : 0) | VD4(freg)); if (SLJIT_UNLIKELY(elem_size == 3)) { SLJIT_ASSERT(type & SLJIT_SIMD_FLOAT); if (src & SLJIT_MEM) { - FAIL_IF(emit_fop_mem(compiler, FPU_LOAD | SLJIT_32, vreg, src, srcw)); - src = vreg; - } else if (vreg != src) - FAIL_IF(push_inst32(compiler, VORR | VD4(vreg) | VN4(src) | VM4(src))); + FAIL_IF(emit_fop_mem(compiler, FPU_LOAD | SLJIT_32, freg, src, srcw)); + src = freg; + } else if (freg != src) + FAIL_IF(push_inst32(compiler, VORR | VD4(freg) | VN4(src) | VM4(src))); - vreg += SLJIT_QUAD_OTHER_HALF(vreg); + freg += SLJIT_QUAD_OTHER_HALF(freg); - if (vreg != src) - return push_inst32(compiler, VORR | VD4(vreg) | VN4(src) | VM4(src)); + if (freg != src) + return push_inst32(compiler, VORR | VD4(freg) | VN4(src) | VM4(src)); return SLJIT_SUCCESS; } @@ -3843,7 +3786,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil if (reg_size == 4) ins |= 1 << 5; - return push_inst32(compiler, VLD1_r | ins | VD4(vreg) | RN4(src) | 0xf); + return push_inst32(compiler, VLD1_r | ins | VD4(freg) | RN4(src) | 0xf); } if (type & SLJIT_SIMD_FLOAT) { @@ -3853,7 +3796,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil if (reg_size == 4) ins |= (sljit_ins)1 << 6; - return push_inst32(compiler, VDUP_s | ins | VD4(vreg) | (sljit_ins)freg_map[src]); + return push_inst32(compiler, VDUP_s | ins | VD4(freg) | (sljit_ins)freg_map[src]); } if (src == SLJIT_IMM) { @@ -3866,7 +3809,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil if (reg_size == 4) imm |= (sljit_ins)1 << 6; - return push_inst32(compiler, VMOV_i | imm | VD4(vreg)); + return push_inst32(compiler, VMOV_i | imm | VD4(freg)); } FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw)); @@ -3888,11 +3831,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil if (reg_size == 4) ins |= (sljit_ins)1 << 21; - return push_inst32(compiler, VDUP | ins | VN4(vreg) | RT4(src)); + return push_inst32(compiler, VDUP | ins | VN4(freg) | RT4(src)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, sljit_s32 lane_index, + sljit_s32 freg, sljit_s32 lane_index, sljit_s32 srcdst, sljit_sw srcdstw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -3900,7 +3843,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile sljit_ins ins; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_lane_mov(compiler, type, vreg, lane_index, srcdst, srcdstw)); + CHECK(check_sljit_emit_simd_lane_mov(compiler, type, freg, lane_index, srcdst, srcdstw)); ADJUST_LOCAL_OFFSET(srcdst, srcdstw); @@ -3914,7 +3857,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile return SLJIT_SUCCESS; if (reg_size == 4) - vreg = simd_get_quad_reg_index(vreg); + freg = simd_get_quad_reg_index(freg); if (type & SLJIT_SIMD_LANE_ZERO) { ins = (reg_size == 3) ? 0 : ((sljit_ins)1 << 6); @@ -3922,62 +3865,62 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile if (type & SLJIT_SIMD_FLOAT) { if (elem_size == 3 && !(srcdst & SLJIT_MEM)) { if (lane_index == 1) - vreg += SLJIT_QUAD_OTHER_HALF(vreg); + freg += SLJIT_QUAD_OTHER_HALF(freg); - if (srcdst != vreg) - FAIL_IF(push_inst32(compiler, VORR | VD4(vreg) | VN4(srcdst) | VM4(srcdst))); + if (srcdst != freg) + FAIL_IF(push_inst32(compiler, VORR | VD4(freg) | VN4(srcdst) | VM4(srcdst))); - vreg += SLJIT_QUAD_OTHER_HALF(vreg); - return push_inst32(compiler, VMOV_i | VD4(vreg)); + freg += SLJIT_QUAD_OTHER_HALF(freg); + return push_inst32(compiler, VMOV_i | VD4(freg)); } - if (srcdst == vreg || (elem_size == 3 && srcdst == (vreg + SLJIT_QUAD_OTHER_HALF(vreg)))) { - FAIL_IF(push_inst32(compiler, VORR | ins | VD4(TMP_FREG2) | VN4(vreg) | VM4(vreg))); + if (srcdst == freg || (elem_size == 3 && srcdst == (freg + SLJIT_QUAD_OTHER_HALF(freg)))) { + FAIL_IF(push_inst32(compiler, VORR | ins | VD4(TMP_FREG2) | VN4(freg) | VM4(freg))); srcdst = TMP_FREG2; srcdstw = 0; } } - FAIL_IF(push_inst32(compiler, VMOV_i | ins | VD4(vreg))); + FAIL_IF(push_inst32(compiler, VMOV_i | ins | VD4(freg))); } if (reg_size == 4 && lane_index >= (0x8 >> elem_size)) { lane_index -= (0x8 >> elem_size); - vreg += SLJIT_QUAD_OTHER_HALF(vreg); + freg += SLJIT_QUAD_OTHER_HALF(freg); } if (srcdst & SLJIT_MEM) { if (elem_size == 3) - return emit_fop_mem(compiler, ((type & SLJIT_SIMD_STORE) ? 0 : FPU_LOAD) | SLJIT_32, vreg, srcdst, srcdstw); + return emit_fop_mem(compiler, ((type & SLJIT_SIMD_STORE) ? 0 : FPU_LOAD) | SLJIT_32, freg, srcdst, srcdstw); FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw)); lane_index = lane_index << elem_size; ins = (sljit_ins)((elem_size << 10) | (lane_index << 5)); - return push_inst32(compiler, ((type & SLJIT_SIMD_STORE) ? VST1_s : VLD1_s) | ins | VD4(vreg) | RN4(srcdst) | 0xf); + return push_inst32(compiler, ((type & SLJIT_SIMD_STORE) ? VST1_s : VLD1_s) | ins | VD4(freg) | RN4(srcdst) | 0xf); } if (type & SLJIT_SIMD_FLOAT) { if (elem_size == 3) { if (type & SLJIT_SIMD_STORE) - return push_inst32(compiler, VORR | VD4(srcdst) | VN4(vreg) | VM4(vreg)); - return push_inst32(compiler, VMOV_F32 | SLJIT_32 | VD4(vreg) | VM4(srcdst)); + return push_inst32(compiler, VORR | VD4(srcdst) | VN4(freg) | VM4(freg)); + return push_inst32(compiler, VMOV_F32 | SLJIT_32 | VD4(freg) | VM4(srcdst)); } if (type & SLJIT_SIMD_STORE) { - if (freg_ebit_map[vreg] == 0) { + if (freg_ebit_map[freg] == 0) { if (lane_index == 1) - vreg = SLJIT_F64_SECOND(vreg); + freg = SLJIT_F64_SECOND(freg); - return push_inst32(compiler, VMOV_F32 | VD4(srcdst) | VM4(vreg)); + return push_inst32(compiler, VMOV_F32 | VD4(srcdst) | VM4(freg)); } - FAIL_IF(push_inst32(compiler, VMOV_s | (1 << 20) | ((sljit_ins)lane_index << 21) | VN4(vreg) | RT4(TMP_REG1))); + FAIL_IF(push_inst32(compiler, VMOV_s | (1 << 20) | ((sljit_ins)lane_index << 21) | VN4(freg) | RT4(TMP_REG1))); return push_inst32(compiler, VMOV | VN4(srcdst) | RT4(TMP_REG1)); } FAIL_IF(push_inst32(compiler, VMOV | (1 << 20) | VN4(srcdst) | RT4(TMP_REG1))); - return push_inst32(compiler, VMOV_s | ((sljit_ins)lane_index << 21) | VN4(vreg) | RT4(TMP_REG1)); + return push_inst32(compiler, VMOV_s | ((sljit_ins)lane_index << 21) | VN4(freg) | RT4(TMP_REG1)); } if (srcdst == SLJIT_IMM) { @@ -4005,11 +3948,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile ins |= (1 << 23); } - return push_inst32(compiler, VMOV_s | ins | VN4(vreg) | RT4(srcdst)); + return push_inst32(compiler, VMOV_s | ins | VN4(freg) | RT4(srcdst)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_s32 src_lane_index) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -4017,7 +3960,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c sljit_ins ins; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, vreg, src, src_lane_index)); + CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, freg, src, src_lane_index)); if (reg_size != 3 && reg_size != 4) return SLJIT_ERR_UNSUPPORTED; @@ -4029,7 +3972,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c return SLJIT_SUCCESS; if (reg_size == 4) { - vreg = simd_get_quad_reg_index(vreg); + freg = simd_get_quad_reg_index(freg); src = simd_get_quad_reg_index(src); if (src_lane_index >= (0x8 >> elem_size)) { @@ -4039,13 +3982,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c } if (elem_size == 3) { - if (vreg != src) - FAIL_IF(push_inst32(compiler, VORR | VD4(vreg) | VN4(src) | VM4(src))); + if (freg != src) + FAIL_IF(push_inst32(compiler, VORR | VD4(freg) | VN4(src) | VM4(src))); - vreg += SLJIT_QUAD_OTHER_HALF(vreg); + freg += SLJIT_QUAD_OTHER_HALF(freg); - if (vreg != src) - return push_inst32(compiler, VORR | VD4(vreg) | VN4(src) | VM4(src)); + if (freg != src) + return push_inst32(compiler, VORR | VD4(freg) | VN4(src) | VM4(src)); return SLJIT_SUCCESS; } @@ -4054,11 +3997,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c if (reg_size == 4) ins |= (sljit_ins)1 << 6; - return push_inst32(compiler, VDUP_s | ins | VD4(vreg) | VM4(src)); + return push_inst32(compiler, VDUP_s | ins | VD4(freg) | VM4(src)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_sw srcw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -4067,7 +4010,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler sljit_s32 dst_reg; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_extend(compiler, type, vreg, src, srcw)); + CHECK(check_sljit_emit_simd_extend(compiler, type, freg, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); @@ -4081,20 +4024,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler return SLJIT_SUCCESS; if (reg_size == 4) - vreg = simd_get_quad_reg_index(vreg); + freg = simd_get_quad_reg_index(freg); if (src & SLJIT_MEM) { FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw)); if (reg_size == 4 && elem2_size - elem_size == 1) - FAIL_IF(push_inst32(compiler, VLD1 | (0x7 << 8) | VD4(vreg) | RN4(src) | 0xf)); + FAIL_IF(push_inst32(compiler, VLD1 | (0x7 << 8) | VD4(freg) | RN4(src) | 0xf)); else - FAIL_IF(push_inst32(compiler, VLD1_s | (sljit_ins)((reg_size - elem2_size + elem_size) << 10) | VD4(vreg) | RN4(src) | 0xf)); - src = vreg; + FAIL_IF(push_inst32(compiler, VLD1_s | (sljit_ins)((reg_size - elem2_size + elem_size) << 10) | VD4(freg) | RN4(src) | 0xf)); + src = freg; } else if (reg_size == 4) src = simd_get_quad_reg_index(src); if (!(type & SLJIT_SIMD_FLOAT)) { - dst_reg = (reg_size == 4) ? vreg : TMP_FREG2; + dst_reg = (reg_size == 4) ? freg : TMP_FREG2; do { FAIL_IF(push_inst32(compiler, VSHLL | ((type & SLJIT_SIMD_EXTEND_SIGNED) ? 0 : (1 << 28)) @@ -4103,27 +4046,27 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler } while (++elem_size < elem2_size); if (dst_reg == TMP_FREG2) - return push_inst32(compiler, VORR | VD4(vreg) | VN4(TMP_FREG2) | VM4(TMP_FREG2)); + return push_inst32(compiler, VORR | VD4(freg) | VN4(TMP_FREG2) | VM4(TMP_FREG2)); return SLJIT_SUCCESS; } /* No SIMD variant, must use VFP instead. */ SLJIT_ASSERT(reg_size == 4); - if (vreg == src) { - vreg += SLJIT_QUAD_OTHER_HALF(vreg); - FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | VD4(vreg) | VM4(src) | 0x20)); - vreg += SLJIT_QUAD_OTHER_HALF(vreg); - return push_inst32(compiler, VCVT_F64_F32 | VD4(vreg) | VM4(src)); + if (freg == src) { + freg += SLJIT_QUAD_OTHER_HALF(freg); + FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | VD4(freg) | VM4(src) | 0x20)); + freg += SLJIT_QUAD_OTHER_HALF(freg); + return push_inst32(compiler, VCVT_F64_F32 | VD4(freg) | VM4(src)); } - FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | VD4(vreg) | VM4(src))); - vreg += SLJIT_QUAD_OTHER_HALF(vreg); - return push_inst32(compiler, VCVT_F64_F32 | VD4(vreg) | VM4(src) | 0x20); + FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | VD4(freg) | VM4(src))); + freg += SLJIT_QUAD_OTHER_HALF(freg); + return push_inst32(compiler, VCVT_F64_F32 | VD4(freg) | VM4(src) | 0x20); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 dst, sljit_sw dstw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -4132,7 +4075,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c sljit_s32 dst_r; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_sign(compiler, type, vreg, dst, dstw)); + CHECK(check_sljit_emit_simd_sign(compiler, type, freg, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); @@ -4165,12 +4108,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c } if (reg_size == 4) { - vreg = simd_get_quad_reg_index(vreg); + freg = simd_get_quad_reg_index(freg); ins |= (sljit_ins)1 << 6; } SLJIT_ASSERT((freg_map[TMP_FREG2] & 0x1) == 0); - FAIL_IF(push_inst32(compiler, ins | VD4(TMP_FREG2) | VM4(vreg))); + FAIL_IF(push_inst32(compiler, ins | VD4(TMP_FREG2) | VM4(freg))); if (reg_size == 4 && elem_size > 0) FAIL_IF(push_inst32(compiler, VMOVN | ((sljit_ins)(elem_size - 1) << 18) | VD4(TMP_FREG2) | VM4(TMP_FREG2))); @@ -4200,16 +4143,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w) + sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); - sljit_s32 alignment; - sljit_ins ins = 0, load_ins; + sljit_ins ins = 0; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w)); - ADJUST_LOCAL_OFFSET(src2, src2w); + CHECK(check_sljit_emit_simd_op2(compiler, type, dst_freg, src1_freg, src2_freg)); if (reg_size != 3 && reg_size != 4) return SLJIT_ERR_UNSUPPORTED; @@ -4217,9 +4158,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *co if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3)) return SLJIT_ERR_UNSUPPORTED; - if (type & SLJIT_SIMD_TEST) - return SLJIT_SUCCESS; - switch (SLJIT_SIMD_GET_OPCODE(type)) { case SLJIT_SIMD_OP2_AND: ins = VAND; @@ -4230,51 +4168,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *co case SLJIT_SIMD_OP2_XOR: ins = VEOR; break; - case SLJIT_SIMD_OP2_SHUFFLE: - ins = VTBL; - break; } - if (src2 & SLJIT_MEM) { - if (elem_size > 3) - elem_size = 3; - - load_ins = VLD1 | (sljit_ins)((reg_size == 3) ? (0x7 << 8) : (0xa << 8)); - alignment = SLJIT_SIMD_GET_ELEM2_SIZE(type); - - SLJIT_ASSERT(reg_size >= alignment); - - if (alignment == 3) - load_ins |= 0x10; - else if (alignment >= 4) - load_ins |= 0x20; - - FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src2, src2w)); - FAIL_IF(push_inst32(compiler, load_ins | VD4(TMP_FREG2) | RN4(src2) | ((sljit_ins)elem_size) << 6 | 0xf)); - src2 = TMP_FREG2; - } + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; if (reg_size == 4) { - dst_vreg = simd_get_quad_reg_index(dst_vreg); - src1_vreg = simd_get_quad_reg_index(src1_vreg); - src2 = simd_get_quad_reg_index(src2); - - if (SLJIT_SIMD_GET_OPCODE(type) == SLJIT_SIMD_OP2_SHUFFLE) { - ins |= (sljit_ins)1 << 8; - - FAIL_IF(push_inst32(compiler, ins | VD4(dst_vreg != src1_vreg ? dst_vreg : TMP_FREG2) | VN4(src1_vreg) | VM4(src2))); - src2 += SLJIT_QUAD_OTHER_HALF(src2); - FAIL_IF(push_inst32(compiler, ins | VD4(dst_vreg + SLJIT_QUAD_OTHER_HALF(dst_vreg)) | VN4(src1_vreg) | VM4(src2))); - - if (dst_vreg == src1_vreg) - return push_inst32(compiler, VORR | VD4(dst_vreg) | VN4(TMP_FREG2) | VM4(TMP_FREG2)); - return SLJIT_SUCCESS; - } - + dst_freg = simd_get_quad_reg_index(dst_freg); + src1_freg = simd_get_quad_reg_index(src1_freg); + src2_freg = simd_get_quad_reg_index(src2_freg); ins |= (sljit_ins)1 << 6; } - return push_inst32(compiler, ins | VD4(dst_vreg) | VN4(src1_vreg) | VM4(src2)); + return push_inst32(compiler, ins | VD4(dst_freg) | VN4(src1_freg) | VM4(src2_freg)); } #undef FPU_LOAD @@ -4288,15 +4194,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler CHECK_ERROR(); CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg)); - if (op & SLJIT_ATOMIC_USE_CAS) - return SLJIT_ERR_UNSUPPORTED; - switch (GET_OPCODE(op)) { - case SLJIT_MOV_S8: - case SLJIT_MOV_S16: - case SLJIT_MOV_S32: - return SLJIT_ERR_UNSUPPORTED; - case SLJIT_MOV_U8: ins = LDREXB; break; @@ -4308,9 +4206,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler break; } - if (op & SLJIT_ATOMIC_TEST) - return SLJIT_SUCCESS; - return push_inst32(compiler, ins | RN4(mem_reg) | RT4(dst_reg)); } @@ -4327,15 +4222,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler CHECK_ERROR(); CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg)); - if (op & SLJIT_ATOMIC_USE_CAS) - return SLJIT_ERR_UNSUPPORTED; - switch (GET_OPCODE(op)) { - case SLJIT_MOV_S8: - case SLJIT_MOV_S16: - case SLJIT_MOV_S32: - return SLJIT_ERR_UNSUPPORTED; - case SLJIT_MOV_U8: ins = STREXB | RM4(TMP_REG1); break; @@ -4347,9 +4234,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler break; } - if (op & SLJIT_ATOMIC_TEST) - return SLJIT_SUCCESS; - FAIL_IF(push_inst32(compiler, ins | RN4(mem_reg) | RT4(src_reg))); if (op & SLJIT_SET_ATOMIC_STORED) return push_inst32(compiler, CMPI_W | RN4(TMP_REG1)); diff --git a/ext/pcre/pcre2lib/sljit/sljitNativeLOONGARCH_64.c b/ext/pcre/pcre2lib/sljit/sljitNativeLOONGARCH_64.c index 73868ca186a43..2e1d742aee74a 100644 --- a/ext/pcre/pcre2lib/sljit/sljitNativeLOONGARCH_64.c +++ b/ext/pcre/pcre2lib/sljit/sljitNativeLOONGARCH_64.c @@ -250,9 +250,6 @@ lower parts in the instruction word, denoted by the “L” and “H” suffixes #define AMCAS_W OPC_3R(0x70B2) #define AMCAS_D OPC_3R(0x70B3) -/* Memory barrier instructions */ -#define DBAR OPC_3R(0x70e4) - /* Other instructions */ #define BREAK OPC_3R(0x54) #define DBGCALL OPC_3R(0x55) @@ -351,7 +348,6 @@ lower parts in the instruction word, denoted by the “L” and “H” suffixes #define VREPLGR2VR OPC_2R(0x1ca7c0) #define VREPLVE OPC_3R(0xe244) #define VREPLVEI OPC_2R(0x1cbde0) -#define VSHUF_B OPC_4R(0xd5) #define XVPERMI OPC_2RI8(0x1dfa) #define I12_MAX (0x7ff) @@ -390,8 +386,6 @@ static sljit_u32 hwcap_feature_list = 0; #define GET_CFG2 0 #define GET_HWCAP 1 -#define LOONGARCH_SUPPORT_AMCAS (LOONGARCH_CFG2_LAMCAS & get_cpu_features(GET_CFG2)) - static SLJIT_INLINE sljit_u32 get_cpu_features(sljit_u32 feature_type) { if (cfg2_feature_list == 0) @@ -411,15 +405,14 @@ static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins) return SLJIT_SUCCESS; } -static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset) +static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset) { sljit_sw diff; sljit_uw target_addr; - sljit_uw jump_addr = (sljit_uw)code_ptr; - sljit_uw orig_addr = jump->addr; - SLJIT_UNUSED_ARG(executable_offset); + sljit_ins *inst; + + inst = (sljit_ins *)jump->addr; - jump->addr = jump_addr; if (jump->flags & SLJIT_REWRITABLE_JUMP) goto exit; @@ -427,23 +420,20 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i target_addr = jump->u.target; else { SLJIT_ASSERT(jump->u.label != NULL); - target_addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset); - - if (jump->u.label->size > orig_addr) - jump_addr = (sljit_uw)(code + orig_addr); + target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset; } - diff = (sljit_sw)target_addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset); + diff = (sljit_sw)target_addr - (sljit_sw)inst - executable_offset; if (jump->flags & IS_COND) { diff += SSIZE_OF(ins); if (diff >= BRANCH16_MIN && diff <= BRANCH16_MAX) { - code_ptr--; - code_ptr[0] = (code_ptr[0] & 0xfc0003ff) ^ 0x4000000; + inst--; + inst[0] = (inst[0] & 0xfc0003ff) ^ 0x4000000; jump->flags |= PATCH_B; - jump->addr = (sljit_uw)code_ptr; - return code_ptr; + jump->addr = (sljit_uw)inst; + return inst; } diff -= SSIZE_OF(ins); @@ -451,65 +441,60 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i if (diff >= JUMP_MIN && diff <= JUMP_MAX) { if (jump->flags & IS_COND) { - code_ptr[-1] |= (sljit_ins)IMM_I16(2); + inst[-1] |= (sljit_ins)IMM_I16(2); } jump->flags |= PATCH_J; - return code_ptr; + return inst; } if (diff >= S32_MIN && diff <= S32_MAX) { if (jump->flags & IS_COND) - code_ptr[-1] |= (sljit_ins)IMM_I16(3); + inst[-1] |= (sljit_ins)IMM_I16(3); jump->flags |= PATCH_REL32; - code_ptr[1] = code_ptr[0]; - return code_ptr + 1; + inst[1] = inst[0]; + return inst + 1; } if (target_addr <= (sljit_uw)S32_MAX) { if (jump->flags & IS_COND) - code_ptr[-1] |= (sljit_ins)IMM_I16(3); + inst[-1] |= (sljit_ins)IMM_I16(3); jump->flags |= PATCH_ABS32; - code_ptr[1] = code_ptr[0]; - return code_ptr + 1; + inst[1] = inst[0]; + return inst + 1; } if (target_addr <= S52_MAX) { if (jump->flags & IS_COND) - code_ptr[-1] |= (sljit_ins)IMM_I16(4); + inst[-1] |= (sljit_ins)IMM_I16(4); jump->flags |= PATCH_ABS52; - code_ptr[2] = code_ptr[0]; - return code_ptr + 2; + inst[2] = inst[0]; + return inst + 2; } exit: if (jump->flags & IS_COND) - code_ptr[-1] |= (sljit_ins)IMM_I16(5); - code_ptr[3] = code_ptr[0]; - return code_ptr + 3; + inst[-1] |= (sljit_ins)IMM_I16(5); + inst[3] = inst[0]; + return inst + 3; } static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset) { sljit_uw addr; - sljit_uw jump_addr = (sljit_uw)code_ptr; sljit_sw diff; SLJIT_UNUSED_ARG(executable_offset); SLJIT_ASSERT(jump->flags < ((sljit_uw)6 << JUMP_SIZE_SHIFT)); if (jump->flags & JUMP_ADDR) addr = jump->u.target; - else { + else addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset); - if (jump->u.label->size > jump->addr) - jump_addr = (sljit_uw)(code + jump->addr); - } - - diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset); + diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); if (diff >= S32_MIN && diff <= S32_MAX) { SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT)); @@ -632,10 +617,6 @@ static void reduce_code_size(struct sljit_compiler *compiler) } else { /* Unit size: instruction. */ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr; - if (jump->u.label->size > jump->addr) { - SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr); - diff -= (sljit_sw)size_reduce; - } if ((jump->flags & IS_COND) && (diff + 1) <= (BRANCH16_MAX / SSIZE_OF(ins)) && (diff + 1) >= (BRANCH16_MIN / SSIZE_OF(ins))) total_size = 0; @@ -654,10 +635,6 @@ static void reduce_code_size(struct sljit_compiler *compiler) if (!(jump->flags & JUMP_ADDR)) { /* Real size minus 1. Unit size: instruction. */ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr; - if (jump->u.label->size > jump->addr) { - SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr); - diff -= (sljit_sw)size_reduce; - } if (diff >= (S32_MIN / SSIZE_OF(ins)) && diff <= (S32_MAX / SSIZE_OF(ins))) total_size = 1; @@ -733,7 +710,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil if (next_min_addr == next_jump_addr) { if (!(jump->flags & JUMP_MOV_ADDR)) { word_count = word_count - 1 + (jump->flags >> JUMP_SIZE_SHIFT); - code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset); + jump->addr = (sljit_uw)code_ptr; + code_ptr = detect_jump_type(jump, code, executable_offset); SLJIT_ASSERT((jump->flags & PATCH_B) || ((sljit_uw)code_ptr - jump->addr < (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins))); } else { word_count += jump->flags >> JUMP_SIZE_SHIFT; @@ -826,6 +804,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) case SLJIT_HAS_SIMD: return (LOONGARCH_HWCAP_LSX & get_cpu_features(GET_HWCAP)); + case SLJIT_HAS_ATOMIC: + return (LOONGARCH_CFG2_LAMCAS & get_cpu_features(GET_CFG2)); + case SLJIT_HAS_CLZ: case SLJIT_HAS_CTZ: case SLJIT_HAS_REV: @@ -833,8 +814,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) case SLJIT_HAS_PREFETCH: case SLJIT_HAS_COPY_F32: case SLJIT_HAS_COPY_F64: - case SLJIT_HAS_ATOMIC: - case SLJIT_HAS_MEMORY_BARRIER: return 1; default: @@ -910,22 +889,16 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw); SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 fscratches; - sljit_s32 fsaveds; sljit_s32 i, tmp, offset; sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options); CHECK_ERROR(); - CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size)); - set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size); + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); - scratches = ENTER_GET_REGS(scratches); - saveds = ENTER_GET_REGS(saveds); - fscratches = compiler->fscratches; - fsaveds = compiler->fsaveds; local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1); local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); @@ -1000,20 +973,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi #undef STACK_MAX_DISTANCE SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 fscratches; - sljit_s32 fsaveds; - CHECK_ERROR(); - CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size)); - set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size); + CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); - scratches = ENTER_GET_REGS(scratches); - saveds = ENTER_GET_REGS(saveds); - fscratches = compiler->fscratches; - fsaveds = compiler->fsaveds; local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1); local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); @@ -1918,8 +1884,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile return push_inst(compiler, ((op & SLJIT_32)? DIV_WU: DIV_DU) | RD(SLJIT_R0) | RJ(SLJIT_R0) | RK(SLJIT_R1)); case SLJIT_DIV_SW: return push_inst(compiler, INST(DIV, op) | RD(SLJIT_R0) | RJ(SLJIT_R0) | RK(SLJIT_R1)); - case SLJIT_MEMORY_BARRIER: - return push_inst(compiler, DBAR); case SLJIT_ENDBR: case SLJIT_SKIP_FRAMES_BEFORE_RETURN: return SLJIT_SUCCESS; @@ -2680,8 +2644,10 @@ static sljit_ins get_jump_instruction(sljit_s32 type) { switch (type) { case SLJIT_EQUAL: + case SLJIT_ATOMIC_NOT_STORED: return BNE | RJ(EQUAL_FLAG) | RD(TMP_ZERO); case SLJIT_NOT_EQUAL: + case SLJIT_ATOMIC_STORED: return BEQ | RJ(EQUAL_FLAG) | RD(TMP_ZERO); case SLJIT_LESS: case SLJIT_GREATER: @@ -2689,7 +2655,6 @@ static sljit_ins get_jump_instruction(sljit_s32 type) case SLJIT_SIG_GREATER: case SLJIT_OVERFLOW: case SLJIT_CARRY: - case SLJIT_ATOMIC_STORED: return BEQ | RJ(OTHER_FLAG) | RD(TMP_ZERO); case SLJIT_GREATER_EQUAL: case SLJIT_LESS_EQUAL: @@ -2697,7 +2662,6 @@ static sljit_ins get_jump_instruction(sljit_s32 type) case SLJIT_SIG_LESS_EQUAL: case SLJIT_NOT_OVERFLOW: case SLJIT_NOT_CARRY: - case SLJIT_ATOMIC_NOT_STORED: return BNE | RJ(OTHER_FLAG) | RD(TMP_ZERO); case SLJIT_F_EQUAL: case SLJIT_ORDERED_EQUAL: @@ -2969,7 +2933,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co break; case SLJIT_ATOMIC_STORED: case SLJIT_ATOMIC_NOT_STORED: - FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RJ(OTHER_FLAG) | IMM_I12(1))); + FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RJ(EQUAL_FLAG) | IMM_I12(1))); src_r = dst_r; invert ^= 0x1; break; @@ -3198,14 +3162,14 @@ static sljit_s32 sljit_emit_simd_mem_offset(struct sljit_compiler *compiler, slj } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 srcdst, sljit_sw srcdstw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); sljit_ins ins = 0; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_mov(compiler, type, vreg, srcdst, srcdstw)); + CHECK(check_sljit_emit_simd_mov(compiler, type, freg, srcdst, srcdstw)); ADJUST_LOCAL_OFFSET(srcdst, srcdstw); @@ -3220,9 +3184,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *co if (!(srcdst & SLJIT_MEM)) { if (type & SLJIT_SIMD_STORE) - ins = FRD(srcdst) | FRJ(vreg) | FRK(vreg); + ins = FRD(srcdst) | FRJ(freg) | FRK(freg); else - ins = FRD(vreg) | FRJ(srcdst) | FRK(srcdst); + ins = FRD(freg) | FRJ(srcdst) | FRK(srcdst); if (reg_size == 5) ins |= VOR_V | (sljit_ins)1 << 26; @@ -3238,15 +3202,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *co ins = (type & SLJIT_SIMD_STORE) ? XVST : XVLD; if (FAST_IS_REG(srcdst) && srcdst >= 0 && (srcdstw >= I12_MIN && srcdstw <= I12_MAX)) - return push_inst(compiler, ins | FRD(vreg) | RJ((sljit_u8)srcdst) | IMM_I12(srcdstw)); + return push_inst(compiler, ins | FRD(freg) | RJ((sljit_u8)srcdst) | IMM_I12(srcdstw)); else { FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw)); - return push_inst(compiler, ins | FRD(vreg) | RJ(srcdst) | IMM_I12(0)); + return push_inst(compiler, ins | FRD(freg) | RJ(srcdst) | IMM_I12(0)); } } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_sw srcw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -3254,7 +3218,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil sljit_ins ins = 0; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_replicate(compiler, type, vreg, src, srcw)); + CHECK(check_sljit_emit_simd_replicate(compiler, type, freg, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); @@ -3273,7 +3237,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil if (reg_size == 5) ins = (sljit_ins)1 << 25; - return push_inst(compiler, VLDREPL | ins | FRD(vreg) | RJ(src) | (sljit_ins)1 << (23 - elem_size)); + return push_inst(compiler, VLDREPL | ins | FRD(freg) | RJ(src) | (sljit_ins)1 << (23 - elem_size)); } if (reg_size == 5) @@ -3281,13 +3245,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil if (type & SLJIT_SIMD_FLOAT) { if (src == SLJIT_IMM) - return push_inst(compiler, VREPLGR2VR | ins | FRD(vreg) | RJ(TMP_ZERO) | (sljit_ins)elem_size << 10); + return push_inst(compiler, VREPLGR2VR | ins | FRD(freg) | RJ(TMP_ZERO) | (sljit_ins)elem_size << 10); - FAIL_IF(push_inst(compiler, VREPLVE | ins | FRD(vreg) | FRJ(src) | RK(TMP_ZERO) | (sljit_ins)elem_size << 15)); + FAIL_IF(push_inst(compiler, VREPLVE | ins | FRD(freg) | FRJ(src) | RK(TMP_ZERO) | (sljit_ins)elem_size << 15)); if (reg_size == 5) { ins = (sljit_ins)(0x44 << 10); - return push_inst(compiler, XVPERMI | ins | FRD(vreg) | FRJ(vreg)); + return push_inst(compiler, XVPERMI | ins | FRD(freg) | FRJ(freg)); } return SLJIT_SUCCESS; @@ -3300,11 +3264,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil src = TMP_REG2; } - return push_inst(compiler, ins | FRD(vreg) | RJ(src)); + return push_inst(compiler, ins | FRD(freg) | RJ(src)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, sljit_s32 lane_index, + sljit_s32 freg, sljit_s32 lane_index, sljit_s32 srcdst, sljit_sw srcdstw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -3312,7 +3276,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile sljit_ins ins = 0; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_lane_mov(compiler, type, vreg, lane_index, srcdst, srcdstw)); + CHECK(check_sljit_emit_simd_lane_mov(compiler, type, freg, lane_index, srcdst, srcdstw)); ADJUST_LOCAL_OFFSET(srcdst, srcdstw); @@ -3334,13 +3298,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile if (type & SLJIT_SIMD_LANE_ZERO) { ins = (reg_size == 5) ? ((sljit_ins)1 << 26) : 0; - if ((type & SLJIT_SIMD_FLOAT) && vreg == srcdst) { - FAIL_IF(push_inst(compiler, VOR_V | ins | FRD(TMP_FREG1) | FRJ(vreg) | FRK(vreg))); + if ((type & SLJIT_SIMD_FLOAT) && freg == srcdst) { + FAIL_IF(push_inst(compiler, VOR_V | ins | FRD(TMP_FREG1) | FRJ(freg) | FRK(freg))); srcdst = TMP_FREG1; srcdstw = 0; } - FAIL_IF(push_inst(compiler, VXOR_V | ins | FRD(vreg) | FRJ(vreg) | FRK(vreg))); + FAIL_IF(push_inst(compiler, VXOR_V | ins | FRD(freg) | FRJ(freg) | FRK(freg))); } if (srcdst & SLJIT_MEM) { @@ -3351,7 +3315,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile if (type & SLJIT_SIMD_STORE) { ins |= (sljit_ins)lane_index << 18 | (sljit_ins)(1 << (23 - elem_size)); - return push_inst(compiler, VSTELM | ins | FRD(vreg) | RJ(srcdst)); + return push_inst(compiler, VSTELM | ins | FRD(freg) | RJ(srcdst)); } else { emit_op_mem(compiler, (elem_size == 3 ? WORD_DATA : (elem_size == 2 ? INT_DATA : (elem_size == 1 ? HALF_DATA : BYTE_DATA))) | LOAD_DATA, TMP_REG1, srcdst | SLJIT_MEM, 0); srcdst = TMP_REG1; @@ -3359,20 +3323,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile if (reg_size == 5) { if (elem_size < 2) { - FAIL_IF(push_inst(compiler, VOR_V | (sljit_ins)1 << 26 | FRD(TMP_FREG1) | FRJ(vreg) | FRK(vreg))); + FAIL_IF(push_inst(compiler, VOR_V | (sljit_ins)1 << 26 | FRD(TMP_FREG1) | FRJ(freg) | FRK(freg))); if (lane_index >= (2 << (3 - elem_size))) { - FAIL_IF(push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(TMP_FREG1) | FRJ(vreg) | IMM_I8(1))); + FAIL_IF(push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(TMP_FREG1) | FRJ(freg) | IMM_I8(1))); FAIL_IF(push_inst(compiler, VINSGR2VR | ins | FRD(TMP_FREG1) | RJ(srcdst) | IMM_V(lane_index % (2 << (3 - elem_size))))); - return push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(vreg) | FRJ(TMP_FREG1) | IMM_I8(2)); + return push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(freg) | FRJ(TMP_FREG1) | IMM_I8(2)); } else { - FAIL_IF(push_inst(compiler, VINSGR2VR | ins | FRD(vreg) | RJ(srcdst) | IMM_V(lane_index))); - return push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(vreg) | FRJ(TMP_FREG1) | IMM_I8(18)); + FAIL_IF(push_inst(compiler, VINSGR2VR | ins | FRD(freg) | RJ(srcdst) | IMM_V(lane_index))); + return push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(freg) | FRJ(TMP_FREG1) | IMM_I8(18)); } } else ins = (sljit_ins)(0x3f ^ (0x3f >> elem_size)) << 10 | (sljit_ins)1 << 26; } - return push_inst(compiler, VINSGR2VR | ins | FRD(vreg) | RJ(srcdst) | IMM_V(lane_index)); + return push_inst(compiler, VINSGR2VR | ins | FRD(freg) | RJ(srcdst) | IMM_V(lane_index)); } } @@ -3380,11 +3344,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile ins = (reg_size == 5) ? (sljit_ins)(0x3f ^ (0x3f >> elem_size)) << 10 | (sljit_ins)1 << 26 : (sljit_ins)(0x3f ^ (0x1f >> elem_size)) << 10; if (type & SLJIT_SIMD_STORE) { - FAIL_IF(push_inst(compiler, VPICKVE2GR_U | ins | RD(TMP_REG1) | FRJ(vreg) | IMM_V(lane_index))); + FAIL_IF(push_inst(compiler, VPICKVE2GR_U | ins | RD(TMP_REG1) | FRJ(freg) | IMM_V(lane_index))); return push_inst(compiler, VINSGR2VR | ins | FRD(srcdst) | RJ(TMP_REG1) | IMM_V(0)); } else { FAIL_IF(push_inst(compiler, VPICKVE2GR_U | ins | RD(TMP_REG1) | FRJ(srcdst) | IMM_V(0))); - return push_inst(compiler, VINSGR2VR | ins | FRD(vreg) | RJ(TMP_REG1) | IMM_V(lane_index)); + return push_inst(compiler, VINSGR2VR | ins | FRD(freg) | RJ(TMP_REG1) | IMM_V(lane_index)); } } @@ -3409,8 +3373,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile else ins |= VPICKVE2GR_U; - FAIL_IF(push_inst(compiler, VOR_V | (sljit_ins)1 << 26 | FRD(TMP_FREG1) | FRJ(vreg) | FRK(vreg))); - FAIL_IF(push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(TMP_FREG1) | FRJ(vreg) | IMM_I8(1))); + FAIL_IF(push_inst(compiler, VOR_V | (sljit_ins)1 << 26 | FRD(TMP_FREG1) | FRJ(freg) | FRK(freg))); + FAIL_IF(push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(TMP_FREG1) | FRJ(freg) | IMM_I8(1))); return push_inst(compiler, ins | RD(srcdst) | FRJ(TMP_FREG1) | IMM_V(lane_index % (2 << (3 - elem_size)))); } } else { @@ -3419,33 +3383,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile } } - return push_inst(compiler, ins | RD(srcdst) | FRJ(vreg) | IMM_V(lane_index)); + return push_inst(compiler, ins | RD(srcdst) | FRJ(freg) | IMM_V(lane_index)); } else { ins = (sljit_ins)(0x3f ^ (0x1f >> elem_size)) << 10; if (reg_size == 5) { if (elem_size < 2) { - FAIL_IF(push_inst(compiler, VOR_V | (sljit_ins)1 << 26 | FRD(TMP_FREG1) | FRJ(vreg) | FRK(vreg))); + FAIL_IF(push_inst(compiler, VOR_V | (sljit_ins)1 << 26 | FRD(TMP_FREG1) | FRJ(freg) | FRK(freg))); if (lane_index >= (2 << (3 - elem_size))) { - FAIL_IF(push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(TMP_FREG1) | FRJ(vreg) | IMM_I8(1))); + FAIL_IF(push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(TMP_FREG1) | FRJ(freg) | IMM_I8(1))); FAIL_IF(push_inst(compiler, VINSGR2VR | ins | FRD(TMP_FREG1) | RJ(srcdst) | IMM_V(lane_index % (2 << (3 - elem_size))))); - return push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(vreg) | FRJ(TMP_FREG1) | IMM_I8(2)); + return push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(freg) | FRJ(TMP_FREG1) | IMM_I8(2)); } else { - FAIL_IF(push_inst(compiler, VINSGR2VR | ins | FRD(vreg) | RJ(srcdst) | IMM_V(lane_index))); - return push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(vreg) | FRJ(TMP_FREG1) | IMM_I8(18)); + FAIL_IF(push_inst(compiler, VINSGR2VR | ins | FRD(freg) | RJ(srcdst) | IMM_V(lane_index))); + return push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(freg) | FRJ(TMP_FREG1) | IMM_I8(18)); } } else ins = (sljit_ins)(0x3f ^ (0x3f >> elem_size)) << 10 | (sljit_ins)1 << 26; } - return push_inst(compiler, VINSGR2VR | ins | FRD(vreg) | RJ(srcdst) | IMM_V(lane_index)); + return push_inst(compiler, VINSGR2VR | ins | FRD(freg) | RJ(srcdst) | IMM_V(lane_index)); } return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_s32 src_lane_index) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -3453,7 +3417,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c sljit_ins ins = 0; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, vreg, src, src_lane_index)); + CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, freg, src, src_lane_index)); if (reg_size != 5 && reg_size != 4) return SLJIT_ERR_UNSUPPORTED; @@ -3467,18 +3431,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c ins = (sljit_ins)(0x3f ^ (0x1f >> elem_size)) << 10; if (reg_size == 5) { - FAIL_IF(push_inst(compiler, VREPLVEI | (sljit_ins)1 << 26 | ins | FRD(vreg) | FRJ(src) | IMM_V(src_lane_index % (2 << (3 - elem_size))))); + FAIL_IF(push_inst(compiler, VREPLVEI | (sljit_ins)1 << 26 | ins | FRD(freg) | FRJ(src) | IMM_V(src_lane_index % (2 << (3 - elem_size))))); ins = (src_lane_index < (2 << (3 - elem_size))) ? (sljit_ins)(0x44 << 10) : (sljit_ins)(0xee << 10); - return push_inst(compiler, XVPERMI | ins | FRD(vreg) | FRJ(vreg)); + return push_inst(compiler, XVPERMI | ins | FRD(freg) | FRJ(freg)); } - return push_inst(compiler, VREPLVEI | ins | FRD(vreg) | FRJ(src) | IMM_V(src_lane_index)); + return push_inst(compiler, VREPLVEI | ins | FRD(freg) | FRJ(src) | IMM_V(src_lane_index)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_sw srcw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -3487,7 +3451,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler sljit_ins ins = 0; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_extend(compiler, type, vreg, src, srcw)); + CHECK(check_sljit_emit_simd_extend(compiler, type, freg, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); @@ -3507,12 +3471,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler ins = (type & SLJIT_SIMD_STORE) ? XVST : XVLD; if (FAST_IS_REG(src) && src >= 0 && (srcw >= I12_MIN && srcw <= I12_MAX)) - FAIL_IF(push_inst(compiler, ins | FRD(vreg) | RJ(src) | IMM_I12(srcw))); + FAIL_IF(push_inst(compiler, ins | FRD(freg) | RJ(src) | IMM_I12(srcw))); else { FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw)); - FAIL_IF(push_inst(compiler, ins | FRD(vreg) | RJ(src) | IMM_I12(0))); + FAIL_IF(push_inst(compiler, ins | FRD(freg) | RJ(src) | IMM_I12(0))); } - src = vreg; + src = freg; } if (type & SLJIT_SIMD_FLOAT) { @@ -3525,7 +3489,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler FAIL_IF(push_inst(compiler, XVPERMI | FRD(src) | FRJ(src) | IMM_I8(16))); } - return push_inst(compiler, VFCVTL_D_S | ins | FRD(vreg) | FRJ(src)); + return push_inst(compiler, VFCVTL_D_S | ins | FRD(freg) | FRJ(src)); } ins = (type & SLJIT_SIMD_EXTEND_SIGNED) ? VSLLWIL : (VSLLWIL | (sljit_ins)1 << 18); @@ -3537,15 +3501,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler if (reg_size == 5) FAIL_IF(push_inst(compiler, XVPERMI | FRD(src) | FRJ(src) | IMM_I8(16))); - FAIL_IF(push_inst(compiler, ins | ((sljit_ins)1 << (13 + elem_size)) | FRD(vreg) | FRJ(src))); - src = vreg; + FAIL_IF(push_inst(compiler, ins | ((sljit_ins)1 << (13 + elem_size)) | FRD(freg) | FRJ(src))); + src = freg; } while (++elem_size < elem2_size); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 dst, sljit_sw dstw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -3554,7 +3518,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c sljit_s32 dst_r; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_sign(compiler, type, vreg, dst, dstw)); + CHECK(check_sljit_emit_simd_sign(compiler, type, freg, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); @@ -3575,7 +3539,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c if (reg_size == 5) ins = (sljit_ins)1 << 26; - FAIL_IF(push_inst(compiler, VMSKLTZ | ins | (sljit_ins)(elem_size << 10) | FRD(TMP_FREG1) | FRJ(vreg))); + FAIL_IF(push_inst(compiler, VMSKLTZ | ins | (sljit_ins)(elem_size << 10) | FRD(TMP_FREG1) | FRJ(freg))); FAIL_IF(push_inst(compiler, VPICKVE2GR_U | (sljit_ins)(0x3c << 10) | RD(dst_r) | FRJ(TMP_FREG1))); @@ -3592,15 +3556,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w) + sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); sljit_ins ins = 0; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w)); - ADJUST_LOCAL_OFFSET(src2, src2w); + CHECK(check_sljit_emit_simd_op2(compiler, type, dst_freg, src1_freg, src2_freg)); if (reg_size != 5 && reg_size != 4) return SLJIT_ERR_UNSUPPORTED; @@ -3614,12 +3577,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *co if (type & SLJIT_SIMD_TEST) return SLJIT_SUCCESS; - if (src2 & SLJIT_MEM) { - FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src2, src2w)); - FAIL_IF(push_inst(compiler, (reg_size == 4 ? VLD : XVLD) | FRD(TMP_FREG1) | RJ(src2) | IMM_I12(0))); - src2 = TMP_FREG1; - } - switch (SLJIT_SIMD_GET_OPCODE(type)) { case SLJIT_SIMD_OP2_AND: ins = VAND_V; @@ -3630,17 +3587,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *co case SLJIT_SIMD_OP2_XOR: ins = VXOR_V; break; - case SLJIT_SIMD_OP2_SHUFFLE: - if (reg_size != 4) - return SLJIT_ERR_UNSUPPORTED; - - return push_inst(compiler, VSHUF_B | FRD(dst_vreg) | FRJ(src1_vreg) | FRK(src1_vreg) | FRA(src2)); } if (reg_size == 5) ins |= (sljit_ins)1 << 26; - return push_inst(compiler, ins | FRD(dst_vreg) | FRJ(src1_vreg) | FRK(src2)); + return push_inst(compiler, ins | FRD(dst_freg) | FRJ(src1_freg) | FRK(src2_freg)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, @@ -3653,45 +3605,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler CHECK_ERROR(); CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg)); - if ((op & SLJIT_ATOMIC_USE_LS) || !LOONGARCH_SUPPORT_AMCAS) { - if (op & SLJIT_ATOMIC_USE_CAS) - return SLJIT_ERR_UNSUPPORTED; - - switch (GET_OPCODE(op)) { - case SLJIT_MOV: - case SLJIT_MOV_P: - ins = LL_D; - break; - case SLJIT_MOV_S32: - case SLJIT_MOV32: - ins = LL_W; - break; - - default: - return SLJIT_ERR_UNSUPPORTED; - } - - if (op & SLJIT_ATOMIC_TEST) - return SLJIT_SUCCESS; - - return push_inst(compiler, ins | RD(dst_reg) | RJ(mem_reg)); - } - switch(GET_OPCODE(op)) { - case SLJIT_MOV_S8: - ins = LD_B; - break; case SLJIT_MOV_U8: ins = LD_BU; break; - case SLJIT_MOV_S16: - ins = LD_H; - break; case SLJIT_MOV_U16: ins = LD_HU; break; case SLJIT_MOV32: - case SLJIT_MOV_S32: ins = LD_W; break; case SLJIT_MOV_U32: @@ -3702,9 +3623,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler break; } - if (op & SLJIT_ATOMIC_TEST) - return SLJIT_SUCCESS; - return push_inst(compiler, ins | RD(dst_reg) | RJ(mem_reg) | IMM_I12(0)); } @@ -3721,48 +3639,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler CHECK_ERROR(); CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg)); - if ((op & SLJIT_ATOMIC_USE_LS) || !LOONGARCH_SUPPORT_AMCAS) { - if (op & SLJIT_ATOMIC_USE_CAS) - return SLJIT_ERR_UNSUPPORTED; - - switch (GET_OPCODE(op)) { - case SLJIT_MOV: - case SLJIT_MOV_P: - ins = SC_D; - break; - case SLJIT_MOV_S32: - case SLJIT_MOV32: - ins = SC_W; - break; - - default: - return SLJIT_ERR_UNSUPPORTED; - } - - if (op & SLJIT_ATOMIC_TEST) - return SLJIT_SUCCESS; - - FAIL_IF(push_inst(compiler, ADD_D | RD(OTHER_FLAG) | RJ(src_reg) | RK(TMP_ZERO))); - return push_inst(compiler, ins | RD(OTHER_FLAG) | RJ(mem_reg)); - } - switch (GET_OPCODE(op)) { - case SLJIT_MOV_S8: - ins = AMCAS_B; - break; case SLJIT_MOV_U8: ins = AMCAS_B; unsign = BSTRPICK_D | (7 << 16); break; - case SLJIT_MOV_S16: - ins = AMCAS_H; - break; case SLJIT_MOV_U16: ins = AMCAS_H; unsign = BSTRPICK_D | (15 << 16); break; case SLJIT_MOV32: - case SLJIT_MOV_S32: ins = AMCAS_W; break; case SLJIT_MOV_U32: @@ -3774,12 +3660,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler break; } - if (op & SLJIT_ATOMIC_TEST) - return SLJIT_SUCCESS; - if (op & SLJIT_SET_ATOMIC_STORED) { - FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG3) | RJ(temp_reg) | RK(TMP_ZERO))); - tmp = TMP_REG3; + FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RJ(temp_reg) | RK(TMP_ZERO))); + tmp = TMP_REG1; } FAIL_IF(push_inst(compiler, ins | RD(tmp) | RJ(mem_reg) | RK(src_reg))); if (!(op & SLJIT_SET_ATOMIC_STORED)) @@ -3788,8 +3671,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler if (unsign) FAIL_IF(push_inst(compiler, unsign | RD(tmp) | RJ(tmp))); - FAIL_IF(push_inst(compiler, XOR | RD(OTHER_FLAG) | RJ(tmp) | RK(temp_reg))); - return push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RJ(OTHER_FLAG) | IMM_I12(1)); + FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RJ(tmp) | RK(temp_reg))); + return push_inst(compiler, SLTUI | RD(EQUAL_FLAG) | RJ(EQUAL_FLAG) | IMM_I12(1)); } static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value, sljit_ins last_ins) diff --git a/ext/pcre/pcre2lib/sljit/sljitNativeMIPS_common.c b/ext/pcre/pcre2lib/sljit/sljitNativeMIPS_common.c index 1b951fe18348e..88eb30b7f163b 100644 --- a/ext/pcre/pcre2lib/sljit/sljitNativeMIPS_common.c +++ b/ext/pcre/pcre2lib/sljit/sljitNativeMIPS_common.c @@ -249,8 +249,6 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define LDL (HI(26)) #define LDR (HI(27)) #define LDC1 (HI(53)) -#define LL (HI(48)) -#define LLD (HI(52)) #define LUI (HI(15)) #define LW (HI(35)) #define LWL (HI(34)) @@ -290,8 +288,6 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define ROTR (HI(0) | (1 << 21) | LO(2)) #define ROTRV (HI(0) | (1 << 6) | LO(6)) #endif /* SLJIT_MIPS_REV >= 2 */ -#define SC (HI(56)) -#define SCD (HI(60)) #define SD (HI(63)) #define SDL (HI(44)) #define SDR (HI(45)) @@ -312,7 +308,6 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define SWL (HI(42)) #define SWR (HI(46)) #define SWC1 (HI(57)) -#define SYNC (HI(0) | LO(15)) #define TRUNC_W_S (HI(17) | FMT_S | LO(13)) #if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2 #define WSBH (HI(31) | (2 << 6) | LO(32)) @@ -386,21 +381,11 @@ static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s if (is_32 && fr >= SLJIT_F64_SECOND(SLJIT_FR0)) fr -= SLJIT_F64_SECOND(0); - return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->real_fscratches)) - || (fr > (SLJIT_FS0 - compiler->real_fsaveds) && fr <= SLJIT_FS0) + return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->fscratches)) + || (fr > (SLJIT_FS0 - compiler->fsaveds) && fr <= SLJIT_FS0) || (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS)); } -static sljit_s32 function_check_is_vreg(struct sljit_compiler *compiler, sljit_s32 vr, sljit_s32 type) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(vr); - SLJIT_UNUSED_ARG(type); - - /* SIMD is not supported. */ - return 0; -} - #endif /* SLJIT_CONFIG_MIPS_32 && SLJIT_ARGUMENT_CHECKS */ static void get_cpu_features(void) @@ -872,8 +857,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) case SLJIT_HAS_CLZ: case SLJIT_HAS_CMOV: case SLJIT_HAS_PREFETCH: - case SLJIT_HAS_ATOMIC: - case SLJIT_HAS_MEMORY_BARRIER: return 1; case SLJIT_HAS_CTZ: @@ -945,22 +928,17 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit #endif SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches); - sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds); sljit_ins base; sljit_s32 i, tmp, offset; sljit_s32 arg_count, word_arg_count, float_arg_count; sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options); CHECK_ERROR(); - CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size)); - set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size); - - scratches = ENTER_GET_REGS(scratches); - saveds = ENTER_GET_REGS(saveds); + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1); #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) @@ -1160,18 +1138,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches); - sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds); - CHECK_ERROR(); - CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size)); - set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size); - - scratches = ENTER_GET_REGS(scratches); - saveds = ENTER_GET_REGS(saveds); + CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1); #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) @@ -2490,12 +2462,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0))); return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1)); #endif /* SLJIT_MIPS_REV >= 6 */ - case SLJIT_MEMORY_BARRIER: -#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) - return push_inst(compiler, SYNC, UNMOVABLE_INS); -#else /* SLJIT_MIPS_REV < 1 */ - return SLJIT_ERR_UNSUPPORTED; -#endif /* SLJIT_MIPS_REV >= 1 */ case SLJIT_ENDBR: case SLJIT_SKIP_FRAMES_BEFORE_RETURN: return SLJIT_SUCCESS; @@ -3346,7 +3312,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile case SLJIT_SIG_GREATER: case SLJIT_OVERFLOW: case SLJIT_CARRY: - case SLJIT_ATOMIC_STORED: BR_Z(OTHER_FLAG); break; case SLJIT_GREATER_EQUAL: @@ -3355,7 +3320,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile case SLJIT_SIG_LESS_EQUAL: case SLJIT_NOT_OVERFLOW: case SLJIT_NOT_CARRY: - case SLJIT_ATOMIC_NOT_STORED: BR_NZ(OTHER_FLAG); break; case SLJIT_F_NOT_EQUAL: @@ -4245,80 +4209,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil #undef TO_ARGW_HI -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op, - sljit_s32 dst_reg, - sljit_s32 mem_reg) -{ - sljit_ins ins; - - CHECK_ERROR(); - CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg)); - - if (op & SLJIT_ATOMIC_USE_CAS) - return SLJIT_ERR_UNSUPPORTED; - - switch (GET_OPCODE(op)) { - case SLJIT_MOV: - case SLJIT_MOV_P: -#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) - ins = LLD; - break; -#endif /* SLJIT_CONFIG_MIPS_64 */ - case SLJIT_MOV_S32: - case SLJIT_MOV32: - ins = LL; - break; - - default: - return SLJIT_ERR_UNSUPPORTED; - } - - if (op & SLJIT_ATOMIC_TEST) - return SLJIT_SUCCESS; - - return push_inst(compiler, ins | T(dst_reg) | S(mem_reg), DR(dst_reg)); -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op, - sljit_s32 src_reg, - sljit_s32 mem_reg, - sljit_s32 temp_reg) -{ - sljit_ins ins; - - /* temp_reg == mem_reg is undefined so use another temp register */ - SLJIT_UNUSED_ARG(temp_reg); - - CHECK_ERROR(); - CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg)); - - if (op & SLJIT_ATOMIC_USE_CAS) - return SLJIT_ERR_UNSUPPORTED; - - switch (GET_OPCODE(op)) { - case SLJIT_MOV: - case SLJIT_MOV_P: -#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) - ins = SCD; - break; -#endif /* SLJIT_CONFIG_RISCV_64 */ - case SLJIT_MOV_S32: - case SLJIT_MOV32: - op |= SLJIT_32; - ins = SC; - break; - - default: - return SLJIT_ERR_UNSUPPORTED; - } - - if (op & SLJIT_ATOMIC_TEST) - return SLJIT_SUCCESS; - - FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src_reg) | TA(0) | DA(OTHER_FLAG), OTHER_FLAG)); - return push_inst(compiler, ins | TA(OTHER_FLAG) | S(mem_reg), OTHER_FLAG); -} - SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) { struct sljit_const *const_; diff --git a/ext/pcre/pcre2lib/sljit/sljitNativePPC_common.c b/ext/pcre/pcre2lib/sljit/sljitNativePPC_common.c index 3d2268e896bff..1f17d90423eb6 100644 --- a/ext/pcre/pcre2lib/sljit/sljitNativePPC_common.c +++ b/ext/pcre/pcre2lib/sljit/sljitNativePPC_common.c @@ -187,12 +187,10 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define LD (HI(58) | 0) #define LFD (HI(50)) #define LFS (HI(48)) -#define LDARX (HI(31) | LO(84)) #if defined(_ARCH_PWR7) && _ARCH_PWR7 #define LDBRX (HI(31) | LO(532)) #endif /* POWER7 */ #define LHBRX (HI(31) | LO(790)) -#define LWARX (HI(31) | LO(20)) #define LWBRX (HI(31) | LO(534)) #define LWZ (HI(32)) #define MFCR (HI(31) | LO(19)) @@ -233,7 +231,6 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #if defined(_ARCH_PWR7) && _ARCH_PWR7 #define STDBRX (HI(31) | LO(660)) #endif /* POWER7 */ -#define STDCX (HI(31) | LO(214)) #define STDU (HI(62) | 1) #define STDUX (HI(31) | LO(181)) #define STFD (HI(54)) @@ -242,14 +239,12 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define STHBRX (HI(31) | LO(918)) #define STW (HI(36)) #define STWBRX (HI(31) | LO(662)) -#define STWCX (HI(31) | LO(150)) #define STWU (HI(37)) #define STWUX (HI(31) | LO(183)) #define SUBF (HI(31) | LO(40)) #define SUBFC (HI(31) | LO(8)) #define SUBFE (HI(31) | LO(136)) #define SUBFIC (HI(8)) -#define SYNC (HI(31) | LO(598)) #define XOR (HI(31) | LO(316)) #define XORI (HI(26)) #define XORIS (HI(27)) @@ -319,11 +314,7 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i { sljit_sw diff; sljit_uw target_addr; - sljit_uw jump_addr = (sljit_uw)code_ptr; - sljit_uw orig_addr = jump->addr; - SLJIT_UNUSED_ARG(executable_offset); - jump->addr = jump_addr; #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL)) goto exit; @@ -337,9 +328,6 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i else { SLJIT_ASSERT(jump->u.label != NULL); target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset; - - if (jump->u.label->size > orig_addr) - jump_addr = (sljit_uw)(code + orig_addr); } #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) @@ -347,7 +335,7 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i goto keep_address; #endif - diff = (sljit_sw)target_addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset); + diff = (sljit_sw)target_addr - (sljit_sw)code_ptr - executable_offset; if (jump->flags & IS_COND) { if (diff <= 0x7fff && diff >= -0x8000) { @@ -559,10 +547,6 @@ static void reduce_code_size(struct sljit_compiler *compiler) } else { /* Unit size: instruction. */ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr; - if (jump->u.label->size > jump->addr) { - SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr); - diff -= (sljit_sw)size_reduce; - } if (jump->flags & IS_COND) { if (diff <= (0x7fff / SSIZE_OF(ins)) && diff >= (-0x8000 / SSIZE_OF(ins))) @@ -608,9 +592,6 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil sljit_ins *buf_ptr; sljit_ins *buf_end; sljit_uw word_count; -#if (defined SLJIT_DEBUG && SLJIT_DEBUG) - sljit_uw jump_addr; -#endif SLJIT_NEXT_DEFINE_TYPES; sljit_sw executable_offset; @@ -667,11 +648,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil if (next_min_addr == next_jump_addr) { if (!(jump->flags & JUMP_MOV_ADDR)) { word_count += jump->flags >> JUMP_SIZE_SHIFT; -#if (defined SLJIT_DEBUG && SLJIT_DEBUG) - jump_addr = (sljit_uw)code_ptr; -#endif + jump->addr = (sljit_uw)code_ptr; code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset); - SLJIT_ASSERT(((sljit_uw)code_ptr - jump_addr <= (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins))); + SLJIT_ASSERT(((sljit_uw)code_ptr - jump->addr <= (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins))); } else { jump->addr = (sljit_uw)code_ptr; #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) @@ -769,8 +748,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) case SLJIT_HAS_CLZ: case SLJIT_HAS_ROT: case SLJIT_HAS_PREFETCH: - case SLJIT_HAS_ATOMIC: - case SLJIT_HAS_MEMORY_BARRIER: return 1; case SLJIT_HAS_CTZ: @@ -868,11 +845,9 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flag #define STACK_MAX_DISTANCE (0x8000 - SSIZE_OF(sw) - LR_SAVE_OFFSET) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches); - sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds); sljit_s32 i, tmp, base, offset; sljit_s32 word_arg_count = 0; sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options); @@ -881,11 +856,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi #endif CHECK_ERROR(); - CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size)); - set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size); + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); - scratches = ENTER_GET_REGS(scratches); - saveds = ENTER_GET_REGS(saveds); local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 0) + GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); @@ -989,18 +962,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches); - sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds); - CHECK_ERROR(); - CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size)); - set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size); + CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); - scratches = ENTER_GET_REGS(scratches); - saveds = ENTER_GET_REGS(saveds); local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 0) + GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); @@ -1431,8 +1399,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile #else return push_inst(compiler, (op == SLJIT_DIV_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)); #endif - case SLJIT_MEMORY_BARRIER: - return push_inst(compiler, SYNC); case SLJIT_ENDBR: case SLJIT_SKIP_FRAMES_BEFORE_RETURN: return SLJIT_SUCCESS; @@ -2456,7 +2422,6 @@ static sljit_ins get_bo_bi_flags(struct sljit_compiler *compiler, sljit_s32 type /* fallthrough */ case SLJIT_EQUAL: - case SLJIT_ATOMIC_STORED: return (12 << 21) | (2 << 16); case SLJIT_CARRY: @@ -2465,7 +2430,6 @@ static sljit_ins get_bo_bi_flags(struct sljit_compiler *compiler, sljit_s32 type /* fallthrough */ case SLJIT_NOT_EQUAL: - case SLJIT_ATOMIC_NOT_STORED: return (4 << 21) | (2 << 16); case SLJIT_LESS: @@ -2722,12 +2686,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co break; case SLJIT_EQUAL: - case SLJIT_ATOMIC_STORED: bit = 2; break; case SLJIT_NOT_EQUAL: - case SLJIT_ATOMIC_NOT_STORED: bit = 2; invert = 1; break; @@ -3144,78 +3106,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | IMM(memw)); } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op, - sljit_s32 dst_reg, - sljit_s32 mem_reg) -{ - sljit_ins ins; - - CHECK_ERROR(); - CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg)); - - if (op & SLJIT_ATOMIC_USE_CAS) - return SLJIT_ERR_UNSUPPORTED; - - switch (GET_OPCODE(op)) { - case SLJIT_MOV: - case SLJIT_MOV_P: -#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - ins = LDARX; - break; -#endif /* SLJIT_CONFIG_RISCV_64 */ - case SLJIT_MOV_U32: - case SLJIT_MOV32: - ins = LWARX; - break; - - default: - return SLJIT_ERR_UNSUPPORTED; - } - - if (op & SLJIT_ATOMIC_TEST) - return SLJIT_SUCCESS; - - return push_inst(compiler, ins | D(dst_reg) | B(mem_reg)); -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op, - sljit_s32 src_reg, - sljit_s32 mem_reg, - sljit_s32 temp_reg) -{ - sljit_ins ins; - - /* temp_reg == mem_reg is undefined so use another temp register */ - SLJIT_UNUSED_ARG(temp_reg); - - CHECK_ERROR(); - CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg)); - - if (op & SLJIT_ATOMIC_USE_CAS) - return SLJIT_ERR_UNSUPPORTED; - - switch (GET_OPCODE(op)) { - case SLJIT_MOV: - case SLJIT_MOV_P: -#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - ins = STDCX | 0x1; - break; -#endif /* SLJIT_CONFIG_RISCV_64 */ - case SLJIT_MOV_U32: - case SLJIT_MOV32: - ins = STWCX | 0x1; - break; - - default: - return SLJIT_ERR_UNSUPPORTED; - } - - if (op & SLJIT_ATOMIC_TEST) - return SLJIT_SUCCESS; - - return push_inst(compiler, ins | D(src_reg) | B(mem_reg)); -} - SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) { struct sljit_const *const_; diff --git a/ext/pcre/pcre2lib/sljit/sljitNativeRISCV_common.c b/ext/pcre/pcre2lib/sljit/sljitNativeRISCV_common.c index d3ba46dba8b31..d86100a80ceff 100644 --- a/ext/pcre/pcre2lib/sljit/sljitNativeRISCV_common.c +++ b/ext/pcre/pcre2lib/sljit/sljitNativeRISCV_common.c @@ -50,9 +50,6 @@ typedef sljit_u32 sljit_ins; #define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) #define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) -#define TMP_VREG1 (SLJIT_NUMBER_OF_VECTOR_REGISTERS + 1) -#define TMP_VREG2 (SLJIT_NUMBER_OF_VECTOR_REGISTERS + 2) - static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = { 0, 10, 11, 12, 13, 14, 15, 16, 17, 29, 30, 31, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 9, 8, 2, 6, 1, 7, 5, 28 }; @@ -61,10 +58,6 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { 0, 10, 11, 12, 13, 14, 15, 16, 17, 2, 3, 4, 5, 6, 7, 28, 29, 30, 31, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 9, 8, 0, 1, }; -static const sljit_u8 vreg_map[SLJIT_NUMBER_OF_VECTOR_REGISTERS + 3] = { - 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 -}; - /* --------------------------------------------------------------------- */ /* Instrucion forms */ /* --------------------------------------------------------------------- */ @@ -75,9 +68,6 @@ static const sljit_u8 vreg_map[SLJIT_NUMBER_OF_VECTOR_REGISTERS + 3] = { #define FRD(rd) ((sljit_ins)freg_map[rd] << 7) #define FRS1(rs1) ((sljit_ins)freg_map[rs1] << 15) #define FRS2(rs2) ((sljit_ins)freg_map[rs2] << 20) -#define VRD(rd) ((sljit_ins)vreg_map[rd] << 7) -#define VRS1(rs1) ((sljit_ins)vreg_map[rs1] << 15) -#define VRS2(rs2) ((sljit_ins)vreg_map[rs2] << 20) #define IMM_I(imm) ((sljit_ins)(imm) << 20) #define IMM_S(imm) ((((sljit_ins)(imm) & 0xfe0) << 20) | (((sljit_ins)(imm) & 0x1f) << 7)) @@ -87,15 +77,6 @@ static const sljit_u8 vreg_map[SLJIT_NUMBER_OF_VECTOR_REGISTERS + 3] = { #define F12(f) ((sljit_ins)(f) << 20) #define F7(f) ((sljit_ins)(f) << 25) -/* Vector instruction types. */ -#define OPFVF (F3(0x5) | OPC(0x57)) -#define OPFVV (F3(0x1) | OPC(0x57)) -#define OPIVI (F3(0x3) | OPC(0x57)) -#define OPIVV (F3(0x0) | OPC(0x57)) -#define OPIVX (F3(0x4) | OPC(0x57)) -#define OPMVV (F3(0x2) | OPC(0x57)) -#define OPMVX (F3(0x6) | OPC(0x57)) - #define ADD (F7(0x0) | F3(0x0) | OPC(0x33)) #define ADDI (F3(0x0) | OPC(0x13)) #define AND (F7(0x0) | F3(0x7) | OPC(0x33)) @@ -107,16 +88,11 @@ static const sljit_u8 vreg_map[SLJIT_NUMBER_OF_VECTOR_REGISTERS + 3] = { #define BGE (F3(0x5) | OPC(0x63)) #define BLTU (F3(0x6) | OPC(0x63)) #define BGEU (F3(0x7) | OPC(0x63)) -#if defined __riscv_zbb -#define CLZ (F7(0x30) | F3(0x1) | OPC(0x13)) -#define CTZ (F7(0x30) | F12(0x1) | F3(0x1) | OPC(0x13)) -#endif /* __riscv_zbb */ #define DIV (F7(0x1) | F3(0x4) | OPC(0x33)) #define DIVU (F7(0x1) | F3(0x5) | OPC(0x33)) #define EBREAK (F12(0x1) | F3(0x0) | OPC(0x73)) #define FADD_S (F7(0x0) | F3(0x7) | OPC(0x53)) #define FDIV_S (F7(0xc) | F3(0x7) | OPC(0x53)) -#define FENCE (F3(0x0) | OPC(0xf)) #define FEQ_S (F7(0x50) | F3(0x2) | OPC(0x53)) #define FLD (F3(0x3) | OPC(0x7)) #define FLE_S (F7(0x50) | F3(0x0) | OPC(0x53)) @@ -140,7 +116,6 @@ static const sljit_u8 vreg_map[SLJIT_NUMBER_OF_VECTOR_REGISTERS + 3] = { #define LD (F3(0x3) | OPC(0x3)) #define LUI (OPC(0x37)) #define LW (F3(0x2) | OPC(0x3)) -#define LR (F7(0x8) | OPC(0x2f)) #define MUL (F7(0x1) | F3(0x0) | OPC(0x33)) #define MULH (F7(0x1) | F3(0x1) | OPC(0x33)) #define MULHU (F7(0x1) | F3(0x3) | OPC(0x33)) @@ -148,73 +123,21 @@ static const sljit_u8 vreg_map[SLJIT_NUMBER_OF_VECTOR_REGISTERS + 3] = { #define ORI (F3(0x6) | OPC(0x13)) #define REM (F7(0x1) | F3(0x6) | OPC(0x33)) #define REMU (F7(0x1) | F3(0x7) | OPC(0x33)) -#if defined __riscv_zbb -#if defined SLJIT_CONFIG_RISCV_32 -#define REV8 (F12(0x698) | F3(0x5) | OPC(0x13)) -#elif defined SLJIT_CONFIG_RISCV_64 -#define REV8 (F12(0x6b8) | F3(0x5) | OPC(0x13)) -#endif /* SLJIT_CONFIG_RISCV_32 */ -#define ROL (F7(0x30) | F3(0x1) | OPC(0x33)) -#define ROR (F7(0x30) | F3(0x5) | OPC(0x33)) -#define RORI (F7(0x30) | F3(0x5) | OPC(0x13)) -#endif /* __riscv_zbb */ -#define SC (F7(0xc) | OPC(0x2f)) #define SD (F3(0x3) | OPC(0x23)) -#if defined __riscv_zbb -#define SEXTB (F7(0x30) | F12(0x4) | F3(0x1) | OPC(0x13)) -#define SEXTH (F7(0x30) | F12(0x5) | F3(0x1) | OPC(0x13)) -#endif /* __riscv_zbb */ -#if defined __riscv_zba -#define SH1ADD (F7(0x10) | F3(0x2) | OPC(0x33)) -#define SH2ADD (F7(0x10) | F3(0x4) | OPC(0x33)) -#define SH3ADD (F7(0x10) | F3(0x6) | OPC(0x33)) -#endif /* __riscv_zba */ #define SLL (F7(0x0) | F3(0x1) | OPC(0x33)) -#define SLLI (F3(0x1) | OPC(0x13)) +#define SLLI (IMM_I(0x0) | F3(0x1) | OPC(0x13)) #define SLT (F7(0x0) | F3(0x2) | OPC(0x33)) #define SLTI (F3(0x2) | OPC(0x13)) #define SLTU (F7(0x0) | F3(0x3) | OPC(0x33)) #define SLTUI (F3(0x3) | OPC(0x13)) #define SRL (F7(0x0) | F3(0x5) | OPC(0x33)) -#define SRLI (F3(0x5) | OPC(0x13)) +#define SRLI (IMM_I(0x0) | F3(0x5) | OPC(0x13)) #define SRA (F7(0x20) | F3(0x5) | OPC(0x33)) -#define SRAI (F7(0x20) | F3(0x5) | OPC(0x13)) +#define SRAI (IMM_I(0x400) | F3(0x5) | OPC(0x13)) #define SUB (F7(0x20) | F3(0x0) | OPC(0x33)) #define SW (F3(0x2) | OPC(0x23)) -#define VAND_VV (F7(0x13) | OPIVV) -#define VFMV_FS (F7(0x21) | OPFVV) -#define VFMV_SF (F7(0x21) | OPFVF) -#define VFMV_VF (F7(0x2f) | OPFVF) -#define VFWCVT_FFV (F7(0x25) | (0xc << 15) | OPFVV) -#define VL (F7(0x1) | OPC(0x7)) -#define VMSLE_VI (F7(0x3b) | OPIVI) -#define VMV_SX (F7(0x21) | OPMVX) -#define VMV_VI (F7(0x2f) | OPIVI) -#define VMV_VV (F7(0x2f) | OPIVV) -#define VMV_VX (F7(0x2f) | OPIVX) -#define VMV_XS (F7(0x21) | OPMVV) -#define VOR_VV (F7(0x15) | OPIVV) -#define VSETIVLI (F7(0x60) | F3(0x7) | OPC(0x57)) -#define VS (F7(0x1) | OPC(0x27)) -#define VSLIDEDOWN_VX (F7(0x1f) | OPIVX) -#define VSLIDEDOWN_VI (F7(0x1f) | OPIVI) -#define VSLIDEUP_VX (F7(0x1d) | OPIVX) -#define VSLIDEUP_VI (F7(0x1d) | OPIVI) -#define VRGATHER_VI (F7(0x19) | OPIVI) -#define VRGATHER_VV (F7(0x19) | OPIVV) -#define VXOR_VV (F7(0x17) | OPIVV) -#define VZEXT_VF2 (F7(0x25) | (0x6 << 15) | OPMVV) -#define VZEXT_VF4 (F7(0x25) | (0x4 << 15) | OPMVV) -#define VZEXT_VF8 (F7(0x25) | (0x2 << 15) | OPMVV) #define XOR (F7(0x0) | F3(0x4) | OPC(0x33)) #define XORI (F3(0x4) | OPC(0x13)) -#if defined __riscv_zbb -#if defined SLJIT_CONFIG_RISCV_32 -#define ZEXTH (F7(0x4) | F3(0x4) | OPC(0x33)) -#elif defined SLJIT_CONFIG_RISCV_64 -#define ZEXTH (F7(0x4) | F3(0x4) | OPC(0x3B)) -#endif /* SLJIT_CONFIG_RISCV_32 */ -#endif /* __riscv_zbb */ #define SIMM_MAX (0x7ff) #define SIMM_MIN (-0x800) @@ -228,7 +151,7 @@ static const sljit_u8 vreg_map[SLJIT_NUMBER_OF_VECTOR_REGISTERS + 3] = { #define S32_MIN (-0x80000000l) #define S44_MAX (0x7fffffff7ffl) #define S52_MAX (0x7ffffffffffffl) -#endif /* SLJIT_CONFIG_RISCV_64 */ +#endif static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins) { @@ -244,15 +167,14 @@ static sljit_s32 push_imm_s_inst(struct sljit_compiler *compiler, sljit_ins ins, return push_inst(compiler, ins | IMM_S(imm)); } -static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset) +static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset) { sljit_sw diff; sljit_uw target_addr; - sljit_uw jump_addr = (sljit_uw)code_ptr; - sljit_uw orig_addr = jump->addr; - SLJIT_UNUSED_ARG(executable_offset); + sljit_ins *inst; + + inst = (sljit_ins *)jump->addr; - jump->addr = jump_addr; if (jump->flags & SLJIT_REWRITABLE_JUMP) goto exit; @@ -260,23 +182,20 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i target_addr = jump->u.target; else { SLJIT_ASSERT(jump->u.label != NULL); - target_addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset); - - if (jump->u.label->size > orig_addr) - jump_addr = (sljit_uw)(code + orig_addr); + target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset; } - diff = (sljit_sw)target_addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset); + diff = (sljit_sw)target_addr - (sljit_sw)inst - executable_offset; if (jump->flags & IS_COND) { diff += SSIZE_OF(ins); if (diff >= BRANCH_MIN && diff <= BRANCH_MAX) { - code_ptr--; - code_ptr[0] = (code_ptr[0] & 0x1fff07f) ^ 0x1000; + inst--; + inst[0] = (inst[0] & 0x1fff07f) ^ 0x1000; jump->flags |= PATCH_B; - jump->addr = (sljit_uw)code_ptr; - return code_ptr; + jump->addr = (sljit_uw)inst; + return inst; } diff -= SSIZE_OF(ins); @@ -285,62 +204,62 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i if (diff >= JUMP_MIN && diff <= JUMP_MAX) { if (jump->flags & IS_COND) { #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) - code_ptr[-1] -= (sljit_ins)(1 * sizeof(sljit_ins)) << 7; -#else /* !SLJIT_CONFIG_RISCV_32 */ - code_ptr[-1] -= (sljit_ins)(5 * sizeof(sljit_ins)) << 7; -#endif /* SLJIT_CONFIG_RISCV_32 */ + inst[-1] -= (sljit_ins)(1 * sizeof(sljit_ins)) << 7; +#else + inst[-1] -= (sljit_ins)(5 * sizeof(sljit_ins)) << 7; +#endif } jump->flags |= PATCH_J; - return code_ptr; + return inst; } #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) if (diff >= S32_MIN && diff <= S32_MAX) { if (jump->flags & IS_COND) - code_ptr[-1] -= (sljit_ins)(4 * sizeof(sljit_ins)) << 7; + inst[-1] -= (sljit_ins)(4 * sizeof(sljit_ins)) << 7; jump->flags |= PATCH_REL32; - code_ptr[1] = code_ptr[0]; - return code_ptr + 1; + inst[1] = inst[0]; + return inst + 1; } if (target_addr <= (sljit_uw)S32_MAX) { if (jump->flags & IS_COND) - code_ptr[-1] -= (sljit_ins)(4 * sizeof(sljit_ins)) << 7; + inst[-1] -= (sljit_ins)(4 * sizeof(sljit_ins)) << 7; jump->flags |= PATCH_ABS32; - code_ptr[1] = code_ptr[0]; - return code_ptr + 1; + inst[1] = inst[0]; + return inst + 1; } if (target_addr <= S44_MAX) { if (jump->flags & IS_COND) - code_ptr[-1] -= (sljit_ins)(2 * sizeof(sljit_ins)) << 7; + inst[-1] -= (sljit_ins)(2 * sizeof(sljit_ins)) << 7; jump->flags |= PATCH_ABS44; - code_ptr[3] = code_ptr[0]; - return code_ptr + 3; + inst[3] = inst[0]; + return inst + 3; } if (target_addr <= S52_MAX) { if (jump->flags & IS_COND) - code_ptr[-1] -= (sljit_ins)(1 * sizeof(sljit_ins)) << 7; + inst[-1] -= (sljit_ins)(1 * sizeof(sljit_ins)) << 7; jump->flags |= PATCH_ABS52; - code_ptr[4] = code_ptr[0]; - return code_ptr + 4; + inst[4] = inst[0]; + return inst + 4; } -#endif /* SLJIT_CONFIG_RISCV_64 */ +#endif exit: #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) - code_ptr[1] = code_ptr[0]; - return code_ptr + 1; -#else /* !SLJIT_CONFIG_RISCV_32 */ - code_ptr[5] = code_ptr[0]; - return code_ptr + 5; -#endif /* SLJIT_CONFIG_RISCV_32 */ + inst[1] = inst[0]; + return inst + 1; +#else + inst[5] = inst[0]; + return inst + 5; +#endif } #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) @@ -348,21 +267,16 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset) { sljit_uw addr; - sljit_uw jump_addr = (sljit_uw)code_ptr; sljit_sw diff; SLJIT_UNUSED_ARG(executable_offset); SLJIT_ASSERT(jump->flags < ((sljit_uw)6 << JUMP_SIZE_SHIFT)); if (jump->flags & JUMP_ADDR) addr = jump->u.target; - else { + else addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset); - if (jump->u.label->size > jump->addr) - jump_addr = (sljit_uw)(code + jump->addr); - } - - diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset); + diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); if (diff >= S32_MIN && diff <= S32_MAX) { SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT)); @@ -402,7 +316,7 @@ static SLJIT_INLINE void load_addr_to_reg(struct sljit_jump *jump, sljit_sw exec sljit_u32 reg = (flags & JUMP_MOV_ADDR) ? *ins : TMP_REG1; #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) sljit_sw high; -#endif /* SLJIT_CONFIG_RISCV_64 */ +#endif SLJIT_UNUSED_ARG(executable_offset); #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) @@ -423,7 +337,7 @@ static SLJIT_INLINE void load_addr_to_reg(struct sljit_jump *jump, sljit_sw exec ins[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(addr); return; } -#endif /* SLJIT_CONFIG_RISCV_64 */ +#endif if ((addr & 0x800) != 0) addr += 0x1000; @@ -539,10 +453,6 @@ static void reduce_code_size(struct sljit_compiler *compiler) } else { /* Unit size: instruction. */ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr; - if (jump->u.label->size > jump->addr) { - SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr); - diff -= (sljit_sw)size_reduce; - } if ((jump->flags & IS_COND) && (diff + 1) <= (BRANCH_MAX / SSIZE_OF(ins)) && (diff + 1) >= (BRANCH_MIN / SSIZE_OF(ins))) total_size = 0; @@ -564,10 +474,6 @@ static void reduce_code_size(struct sljit_compiler *compiler) if (!(jump->flags & JUMP_ADDR)) { /* Real size minus 1. Unit size: instruction. */ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr; - if (jump->u.label->size > jump->addr) { - SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr); - diff -= (sljit_sw)size_reduce; - } if (diff >= (S32_MIN / SSIZE_OF(ins)) && diff <= (S32_MAX / SSIZE_OF(ins))) total_size = 1; @@ -646,7 +552,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil if (next_min_addr == next_jump_addr) { if (!(jump->flags & JUMP_MOV_ADDR)) { word_count = word_count - 1 + (jump->flags >> JUMP_SIZE_SHIFT); - code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset); + jump->addr = (sljit_uw)code_ptr; + code_ptr = detect_jump_type(jump, code, executable_offset); SLJIT_ASSERT((jump->flags & PATCH_B) || ((sljit_uw)code_ptr - jump->addr < (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins))); } else { #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) @@ -735,7 +642,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) return (SLJIT_IS_FPU_AVAILABLE) != 0; #elif defined(__riscv_float_abi_soft) return 0; -#else /* !SLJIT_IS_FPU_AVAILABLE && !__riscv_float_abi_soft */ +#else return 1; #endif /* SLJIT_IS_FPU_AVAILABLE */ case SLJIT_HAS_ZERO_REGISTER: @@ -743,19 +650,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) case SLJIT_HAS_COPY_F64: #endif /* !SLJIT_CONFIG_RISCV_64 */ - case SLJIT_HAS_ATOMIC: - case SLJIT_HAS_MEMORY_BARRIER: -#ifdef __riscv_vector - case SLJIT_HAS_SIMD: -#endif /* __riscv_vector */ - return 1; -#ifdef __riscv_zbb - case SLJIT_HAS_CLZ: - case SLJIT_HAS_CTZ: - case SLJIT_HAS_REV: - case SLJIT_HAS_ROT: return 1; -#endif /* __riscv_zbb */ default: return 0; } @@ -813,36 +708,32 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) #define STACK_STORE SW #define STACK_LOAD LW -#else /* !SLJIT_CONFIG_RISCV_32 */ +#else #define STACK_STORE SD #define STACK_LOAD LD -#endif /* SLJIT_CONFIG_RISCV_32 */ +#endif #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) #include "sljitNativeRISCV_32.c" -#else /* !SLJIT_CONFIG_RISCV_32 */ +#else #include "sljitNativeRISCV_64.c" -#endif /* SLJIT_CONFIG_RISCV_32 */ +#endif #define STACK_MAX_DISTANCE (-SIMM_MIN) static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw); SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches); - sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds); sljit_s32 i, tmp, offset; sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options); CHECK_ERROR(); - CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size)); - set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size); + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); - scratches = ENTER_GET_REGS(scratches); - saveds = ENTER_GET_REGS(saveds); local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1); #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) { @@ -850,9 +741,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi local_size += SSIZE_OF(sw); local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); } -#else /* !SLJIT_CONFIG_RISCV_32 */ +#else local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); -#endif /* SLJIT_CONFIG_RISCV_32 */ +#endif local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf; compiler->local_size = local_size; @@ -887,7 +778,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi /* This alignment is valid because offset is not used after storing FPU regs. */ if ((offset & SSIZE_OF(sw)) != 0) offset -= SSIZE_OF(sw); -#endif /* SLJIT_CONFIG_RISCV_32 */ +#endif tmp = SLJIT_FS0 - fsaveds; for (i = SLJIT_FS0; i > tmp; i--) { @@ -930,18 +821,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi #undef STACK_MAX_DISTANCE SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches); - sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds); - CHECK_ERROR(); - CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size)); - set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size); + CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); - scratches = ENTER_GET_REGS(scratches); - saveds = ENTER_GET_REGS(saveds); local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1); #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) { @@ -949,9 +835,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp local_size += SSIZE_OF(sw); local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); } -#else /* !SLJIT_CONFIG_RISCV_32 */ +#else local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); -#endif /* SLJIT_CONFIG_RISCV_32 */ +#endif compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf; return SLJIT_SUCCESS; @@ -997,7 +883,7 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit /* This alignment is valid because offset is not used after storing FPU regs. */ if ((offset & SSIZE_OF(sw)) != 0) offset -= SSIZE_OF(sw); -#endif /* SLJIT_CONFIG_RISCV_32 */ +#endif tmp = SLJIT_FS0 - compiler->fsaveds; for (i = SLJIT_FS0; i > tmp; i--) { @@ -1053,9 +939,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *c #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) #define ARCH_32_64(a, b) a -#else /* !SLJIT_CONFIG_RISCV_32 */ +#else #define ARCH_32_64(a, b) b -#endif /* SLJIT_CONFIG_RISCV_32 */ +#endif static const sljit_ins data_transfer_insts[16 + 4] = { /* u w s */ ARCH_32_64(F3(0x2) | OPC(0x23) /* sw */, F3(0x3) | OPC(0x23) /* sd */), @@ -1148,9 +1034,6 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl sljit_s32 base = arg & REG_MASK; sljit_s32 tmp_r = (flags & MEM_USE_TMP2) ? TMP_REG2 : TMP_REG1; sljit_sw offset, argw_hi; -#if defined __riscv_zba - sljit_ins ins = ADD; -#endif /* __riscv_zba */ SLJIT_ASSERT(arg & SLJIT_MEM); if (!(next_arg & SLJIT_MEM)) { @@ -1161,20 +1044,6 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { argw &= 0x3; -#if defined __riscv_zba - switch (argw) { - case 1: - ins = SH1ADD; - break; - case 2: - ins = SH2ADD; - break; - case 3: - ins = SH3ADD; - break; - } - FAIL_IF(push_inst(compiler, ins | RD(tmp_r) | RS1(OFFS_REG(arg)) | RS2(base))); -#else /* !__riscv_zba */ /* Using the cache. */ if (argw == compiler->cache_argw) { if (arg == compiler->cache_arg) @@ -1206,8 +1075,6 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl } else FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(!argw ? OFFS_REG(arg) : TMP_REG3))); -#endif /* __riscv_zba */ - return push_mem_inst(compiler, flags, reg, tmp_r, 0); } @@ -1294,7 +1161,7 @@ static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, slji #define WORD_32 0x08 #define IMM_EXTEND(v) (IMM_I((op & SLJIT_32) ? (v) : (32 + (v)))) #endif /* SLJIT_CONFIG_RISCV_32 */ -#ifndef __riscv_zbb + static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src) { sljit_s32 is_clz = (GET_OPCODE(op) == SLJIT_CLZ); @@ -1397,7 +1264,6 @@ static sljit_s32 emit_rev16(struct sljit_compiler *compiler, sljit_s32 op, sljit FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SRLI : SRAI) | WORD | RD(dst) | RS1(dst) | IMM_I(word_size - 16))); return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1)); } -#endif /* !__riscv_zbb */ #define EMIT_LOGICAL(op_imm, op_reg) \ if (flags & SRC2_IMM) { \ @@ -1443,9 +1309,6 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl return SLJIT_SUCCESS; case SLJIT_MOV_S8: -#if defined __riscv_zbb - return push_inst(compiler, SEXTB | RD(dst) | RS1(src2)); -#else /* !__riscv_zbb */ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM)); if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(24))); @@ -1453,12 +1316,8 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl } SLJIT_ASSERT(dst == src2); return SLJIT_SUCCESS; -#endif /* __riscv_zbb */ case SLJIT_MOV_U16: -#if defined __riscv_zbb - return push_inst(compiler, ZEXTH | RD(dst) | RS1(src2)); -#else /* !__riscv_zbb */ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM)); if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(16))); @@ -1466,12 +1325,8 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl } SLJIT_ASSERT(dst == src2); return SLJIT_SUCCESS; -#endif /* __riscv_zbb */ case SLJIT_MOV_S16: -#if defined __riscv_zbb - return push_inst(compiler, SEXTH | RD(dst) | RS1(src2)); -#else /* !__riscv_zbb */ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM)); if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(16))); @@ -1479,7 +1334,6 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl } SLJIT_ASSERT(dst == src2); return SLJIT_SUCCESS; -#endif /* !__riscv_zbb */ #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) case SLJIT_MOV_U32: @@ -1500,59 +1354,24 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl #endif /* SLJIT_CONFIG_RISCV_64 */ case SLJIT_CLZ: -#if defined __riscv_zbb - return push_inst(compiler, CLZ | WORD | RD(dst) | RS1(src2)); -#endif /* __riscv_zbb */ case SLJIT_CTZ: -#if defined __riscv_zbb - return push_inst(compiler, CTZ | WORD | RD(dst) | RS1(src2)); -#else /* !__riscv_zbb */ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM)); return emit_clz_ctz(compiler, op, dst, src2); -#endif /* __riscv_zbb */ case SLJIT_REV: -#if defined __riscv_zbb - SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM)); - FAIL_IF(push_inst(compiler, REV8 | RD(dst) | RS1(src2))); -#if defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64 - if (op & SLJIT_32) - return push_inst(compiler, SRAI | RD(dst) | RS1(dst) | IMM_I(32)); - return SLJIT_SUCCESS; -#else /* !SLJIT_CONFIG_RISCV_64 */ - return SLJIT_SUCCESS; -#endif /* SLJIT_CONFIG_RISCV_64 */ -#endif /* __riscv_zbb */ case SLJIT_REV_S32: -#if ((defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) || defined __riscv_zbb) +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) case SLJIT_REV_U32: -#endif /* SLJIT_CONFIG_RISCV_32 || __riscv_zbb */ +#endif /* SLJIT_CONFIG_RISCV_32 */ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM)); -#if defined __riscv_zbb - FAIL_IF(push_inst(compiler, REV8 | RD(dst) | RS1(src2))); -#if defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64 - return push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U32 ? SRLI : SRAI )| RD(dst) | RS1(dst) | IMM_I(32)); -#else /* !SLJIT_CONFIG_RISCV_64 */ - return SLJIT_SUCCESS; -#endif /* SLJIT_CONFIG_RISCV_64 */ -#else /* !__riscv_zbb */ return emit_rev(compiler, op, dst, src2); -#endif /* __riscv_zbb */ + case SLJIT_REV_U16: case SLJIT_REV_S16: SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM)); -#if defined __riscv_zbb - FAIL_IF(push_inst(compiler, REV8 | RD(dst) | RS1(src2))); -#if defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64 - return push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SRLI : SRAI )| RD(dst) | RS1(dst) | IMM_I(48)); -#else /* !SLJIT_CONFIG_RISCV_64 */ - return push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SRLI : SRAI) | RD(dst) | RS1(dst) | IMM_I(16)); -#endif /* SLJIT_CONFIG_RISCV_64 */ -#else /* !__riscv_zbb */ return emit_rev16(compiler, op, dst, src2); -#endif /* __riscv_zbb */ -#if ((defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) && !defined __riscv_zbb) +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) case SLJIT_REV_U32: SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM) && dst != TMP_REG1); FAIL_IF(emit_rev(compiler, op, dst, src2)); @@ -1560,7 +1379,8 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl return SLJIT_SUCCESS; FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(dst) | IMM_I(32))); return push_inst(compiler, SRLI | RD(dst) | RS1(dst) | IMM_I(32)); -#endif /* SLJIT_CONFIG_RISCV_64 && !__riscv_zbb */ +#endif /* SLJIT_CONFIG_RISCV_32 */ + case SLJIT_ADD: /* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; @@ -1848,16 +1668,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl case SLJIT_ROTR: if (flags & SRC2_IMM) { SLJIT_ASSERT(src2 != 0); -#if defined __riscv_zbb - if (GET_OPCODE(op) == SLJIT_ROTL) { -#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) - src2 = ((op & SLJIT_32) ? 32 : 64) - src2; -#else /* !SLJIT_CONFIG_RISCV_64 */ - src2 = 32 - src2; -#endif /* SLJIT_CONFIG_RISCV_64 */ - } - return push_inst(compiler, RORI | WORD | RD(dst) | RS1(src1) | IMM_I(src2)); -#else /* !__riscv_zbb */ + op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SLLI : SRLI; FAIL_IF(push_inst(compiler, op_imm | WORD | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2))); @@ -1869,12 +1680,8 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SRLI : SLLI; FAIL_IF(push_inst(compiler, op_imm | WORD | RD(dst) | RS1(src1) | IMM_I(src2))); return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)); -#endif /* !__riscv_zbb */ } -#if defined __riscv_zbb - return push_inst(compiler, (GET_OPCODE(op) == SLJIT_ROTL ? ROL : ROR) | WORD | RD(dst) | RS1(src1) | RS2(src2)); -#else /* !__riscv_zbb */ if (src2 == TMP_ZERO) { if (dst != src1) return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(0)); @@ -1887,7 +1694,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl op_reg = (GET_OPCODE(op) == SLJIT_ROTL) ? SRL : SLL; FAIL_IF(push_inst(compiler, op_reg | WORD | RD(dst) | RS1(src1) | RS2(EQUAL_FLAG))); return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)); -#endif /* !riscv_zbb */ + default: SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; @@ -2074,8 +1881,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile return push_inst(compiler, DIVU | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1)); case SLJIT_DIV_SW: return push_inst(compiler, DIV | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1)); - case SLJIT_MEMORY_BARRIER: - return push_inst(compiler, FENCE | 0x0ff00000); case SLJIT_ENDBR: case SLJIT_SKIP_FRAMES_BEFORE_RETURN: return SLJIT_SUCCESS; @@ -2098,7 +1903,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) if (op & SLJIT_32) flags = INT_DATA | SIGNED_DATA; -#endif /* SLJIT_CONFIG_RISCV_64 */ +#endif switch (GET_OPCODE(op)) { case SLJIT_MOV: @@ -2106,7 +1911,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile case SLJIT_MOV_U32: case SLJIT_MOV_S32: case SLJIT_MOV32: -#endif /* SLJIT_CONFIG_RISCV_32 */ +#endif case SLJIT_MOV_P: return emit_op(compiler, SLJIT_MOV, WORD_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, srcw); @@ -2118,7 +1923,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile /* Logical operators have no W variant, so sign extended input is necessary for them. */ case SLJIT_MOV32: return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_s32)srcw : srcw); -#endif /* SLJIT_CONFIG_RISCV_64 */ +#endif case SLJIT_MOV_U8: return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_u8)srcw : srcw); @@ -2171,7 +1976,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile if (src2 == SLJIT_IMM) src2w = (sljit_s32)src2w; } -#endif /* SLJIT_CONFIG_RISCV_64 */ +#endif switch (GET_OPCODE(op)) { case SLJIT_ADD: @@ -2399,10 +2204,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, slji if (type == SLJIT_GP_REGISTER) return reg_map[reg]; - if (type == SLJIT_FLOAT_REGISTER) - return freg_map[reg]; + if (type != SLJIT_FLOAT_REGISTER) + return -1; - return vreg_map[reg]; + return freg_map[reg]; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, @@ -2429,9 +2234,9 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp { #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) # define flags (sljit_u32)0 -#else /* !SLJIT_CONFIG_RISCV_32 */ +#else sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)) << 21; -#endif /* SLJIT_CONFIG_RISCV_32 */ +#endif sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; if (src & SLJIT_MEM) { @@ -2445,15 +2250,15 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp if (dst & SLJIT_MEM) { #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) return emit_op_mem2(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0); -#else /* !SLJIT_CONFIG_RISCV_32 */ +#else return emit_op_mem2(compiler, flags ? WORD_DATA : INT_DATA, TMP_REG2, dst, dstw, 0, 0); -#endif /* SLJIT_CONFIG_RISCV_32 */ +#endif } return SLJIT_SUCCESS; #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) # undef flags -#endif /* SLJIT_CONFIG_RISCV_32 */ +#endif } static sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_ins ins, @@ -2751,9 +2556,9 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) #define BRANCH_LENGTH ((sljit_ins)(3 * sizeof(sljit_ins)) << 7) -#else /* !SLJIT_CONFIG_RISCV_32 */ +#else #define BRANCH_LENGTH ((sljit_ins)(7 * sizeof(sljit_ins)) << 7) -#endif /* SLJIT_CONFIG_RISCV_32 */ +#endif static sljit_ins get_jump_instruction(sljit_s32 type) { @@ -2768,7 +2573,6 @@ static sljit_ins get_jump_instruction(sljit_s32 type) case SLJIT_SIG_GREATER: case SLJIT_OVERFLOW: case SLJIT_CARRY: - case SLJIT_ATOMIC_NOT_STORED: case SLJIT_F_EQUAL: case SLJIT_ORDERED_EQUAL: case SLJIT_ORDERED_NOT_EQUAL: @@ -2787,7 +2591,6 @@ static sljit_ins get_jump_instruction(sljit_s32 type) case SLJIT_SIG_LESS_EQUAL: case SLJIT_NOT_OVERFLOW: case SLJIT_NOT_CARRY: - case SLJIT_ATOMIC_STORED: case SLJIT_F_NOT_EQUAL: case SLJIT_UNORDERED_OR_NOT_EQUAL: case SLJIT_UNORDERED_OR_EQUAL: @@ -2884,7 +2687,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler } if (src2 & SLJIT_MEM) { - PTR_FAIL_IF(emit_op_mem2(compiler, flags | (src1 == TMP_REG1 ? MEM_USE_TMP2 : 0), src2_tmp_reg, src2, src2w, 0, 0)); + PTR_FAIL_IF(emit_op_mem2(compiler, flags, src2_tmp_reg, src2, src2w, 0, 0)); src2 = src2_tmp_reg; } @@ -3022,9 +2825,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co sljit_s32 saved_op = op; #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) sljit_s32 mem_type = WORD_DATA; -#else /* !SLJIT_CONFIG_RISCV_32 */ +#else sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA; -#endif /* SLJIT_CONFIG_RISCV_32 */ +#endif CHECK_ERROR(); CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type)); @@ -3059,10 +2862,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co src_r = dst_r; invert ^= 0x1; break; - case SLJIT_ATOMIC_STORED: - case SLJIT_ATOMIC_NOT_STORED: - invert ^= 0x1; - break; } } else { invert = 0; @@ -3267,561 +3066,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile #undef TO_ARGW_HI -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op, - sljit_s32 dst_reg, - sljit_s32 mem_reg) -{ - sljit_ins ins; - - CHECK_ERROR(); - CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg)); - - if (op & SLJIT_ATOMIC_USE_CAS) - return SLJIT_ERR_UNSUPPORTED; - - switch (GET_OPCODE(op)) { - case SLJIT_MOV: - case SLJIT_MOV_P: -#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) - ins = LR | (3 << 12); - break; -#endif /* SLJIT_CONFIG_RISCV_64 */ - case SLJIT_MOV_S32: - case SLJIT_MOV32: - ins = LR | (2 << 12); - break; - - default: - return SLJIT_ERR_UNSUPPORTED; - } - - if (op & SLJIT_ATOMIC_TEST) - return SLJIT_SUCCESS; - - return push_inst(compiler, ins | RD(dst_reg) | RS1(mem_reg)); -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op, - sljit_s32 src_reg, - sljit_s32 mem_reg, - sljit_s32 temp_reg) -{ - sljit_ins ins; - - /* temp_reg == mem_reg is undefined so use another temp register */ - SLJIT_UNUSED_ARG(temp_reg); - - CHECK_ERROR(); - CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg)); - - if (op & SLJIT_ATOMIC_USE_CAS) - return SLJIT_ERR_UNSUPPORTED; - - switch (GET_OPCODE(op)) { - case SLJIT_MOV: - case SLJIT_MOV_P: -#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) - ins = SC | (3 << 12); - break; -#endif /* SLJIT_CONFIG_RISCV_64 */ - case SLJIT_MOV_S32: - case SLJIT_MOV32: - ins = SC | (2 << 12); - break; - - default: - return SLJIT_ERR_UNSUPPORTED; - } - - if (op & SLJIT_ATOMIC_TEST) - return SLJIT_SUCCESS; - - return push_inst(compiler, ins | RD(OTHER_FLAG) | RS1(mem_reg) | RS2(src_reg)); -} - -/* - SEW = Selected element width - LMUL = Vector register group multiplier - - VLMUL values (in binary): - 100 : reserved - 101 : 1/8 - 110 : 1/4 - 111 : 1/2 - 000 : 1 - 001 : 2 - 010 : 4 - 011 : 8 -*/ - -static SLJIT_INLINE sljit_s32 sljit_emit_vsetivli(struct sljit_compiler *compiler, sljit_s32 type, sljit_ins vlmul) -{ - sljit_ins elem_size = (sljit_ins)SLJIT_SIMD_GET_ELEM_SIZE(type); - sljit_ins avl = (sljit_ins)1 << (SLJIT_SIMD_GET_REG_SIZE(type) - elem_size); - - return push_inst(compiler, VSETIVLI | RD(TMP_REG1) | (elem_size << 23) | (vlmul << 20) | (avl << 15)); -} - -static SLJIT_INLINE sljit_s32 sljit_emit_vsetivli_size(struct sljit_compiler *compiler, sljit_s32 reg_size, sljit_s32 elem_size) -{ - sljit_ins avl = (sljit_ins)1 << (reg_size - elem_size); - return push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | (avl << 15)); -} - -static sljit_s32 sljit_emit_vmem(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 elem_size, sljit_s32 mem, sljit_sw memw) -{ - sljit_s32 base = mem & REG_MASK; - - if (elem_size > 0) - ins |= (1 << 14) | ((sljit_ins)elem_size << 12); - - if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { - memw &= 0x3; - - if (SLJIT_UNLIKELY(memw)) { - FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG1) | RS1(OFFS_REG(mem)) | IMM_I(memw))); - } - - FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(base) | RS2(!memw ? OFFS_REG(mem) : TMP_REG1))); - return push_inst(compiler, ins | RS1(TMP_REG1)); - } - - if (memw == 0) - return push_inst(compiler, ins | RS1(base)); - - if (memw <= SIMM_MAX && memw >= SIMM_MIN) { - FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(base) | IMM_I(memw))); - return push_inst(compiler, ins | RS1(TMP_REG1)); - } - - FAIL_IF(load_immediate(compiler, TMP_REG1, memw, TMP_REG3)); - - if (base != 0) - FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(base))); - - return push_inst(compiler, ins | RS1(TMP_REG1)); -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, - sljit_s32 srcdst, sljit_sw srcdstw) -{ - sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); - sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); - sljit_ins ins; - - CHECK_ERROR(); - CHECK(check_sljit_emit_simd_mov(compiler, type, vreg, srcdst, srcdstw)); - - ADJUST_LOCAL_OFFSET(srcdst, srcdstw); - - if (reg_size != 4) - return SLJIT_ERR_UNSUPPORTED; - - if (type & SLJIT_SIMD_TEST) - return SLJIT_SUCCESS; - - if (elem_size > 3) - elem_size = 3; - - FAIL_IF(sljit_emit_vsetivli_size(compiler, reg_size, elem_size)); - - if (srcdst & SLJIT_MEM) { - ins = (type & SLJIT_SIMD_STORE) ? VS : VL; - return sljit_emit_vmem(compiler, ins | VRD(vreg), elem_size, srcdst, srcdstw); - } - - if (type & SLJIT_SIMD_STORE) - ins = VRD(srcdst) | VRS1(vreg); - else - ins = VRD(vreg) | VRS1(srcdst); - - return push_inst(compiler, VMV_VV | ins); -} - -static sljit_s32 sljit_simd_get_mem_flags(sljit_s32 elem_size) -{ - switch (elem_size) { - case 0: - return BYTE_DATA; - case 1: - return HALF_DATA; -#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) - case 2: - return INT_DATA; -#endif /* SLJIT_CONFIG_RISCV_64 */ - default: - return WORD_DATA; - } -} - -static sljit_sw sljit_simd_get_imm(sljit_s32 elem_size, sljit_sw imm) -{ - switch (elem_size) { - case 0: - return (sljit_s8)imm; - case 1: - return (sljit_s16)imm; -#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) - case 2: - return (sljit_s32)imm; -#endif /* SLJIT_CONFIG_RISCV_64 */ - default: - return imm; - } -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, - sljit_s32 src, sljit_sw srcw) -{ - sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); - sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); - sljit_s32 flags; - - CHECK_ERROR(); - CHECK(check_sljit_emit_simd_replicate(compiler, type, vreg, src, srcw)); - - ADJUST_LOCAL_OFFSET(src, srcw); - - if (reg_size != 4) - return SLJIT_ERR_UNSUPPORTED; - -#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) - if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : elem_size > 2) - return SLJIT_ERR_UNSUPPORTED; -#else /* !SLJIT_CONFIG_RISCV_32 */ - if (((type & SLJIT_SIMD_FLOAT) && elem_size < 2) || elem_size > 3) - return SLJIT_ERR_UNSUPPORTED; -#endif /* SLJIT_CONFIG_RISCV_32 */ - - if (type & SLJIT_SIMD_TEST) - return SLJIT_SUCCESS; - - FAIL_IF(sljit_emit_vsetivli(compiler, type, 0)); - - if (type & SLJIT_SIMD_FLOAT) { - if (src == SLJIT_IMM) - return push_inst(compiler, VMV_VI | VRD(vreg) | ((sljit_ins)(srcw & 0x1f) << 15)); - - if (src & SLJIT_MEM) { - flags = (elem_size == 2) ? SINGLE_DATA : DOUBLE_DATA; - FAIL_IF(emit_op_mem(compiler, flags | LOAD_DATA, TMP_FREG1, src, srcw)); - src = TMP_FREG1; - } - - return push_inst(compiler, VFMV_VF | VRD(vreg) | FRS1(src)); - } - - if (src == SLJIT_IMM) { - srcw = sljit_simd_get_imm(elem_size, srcw); - - if (srcw >= -0x10 && srcw <= 0xf) - return push_inst(compiler, VMV_VI | VRD(vreg) | ((sljit_ins)(srcw & 0x1f) << 15)); - - FAIL_IF(load_immediate(compiler, TMP_REG1, srcw, TMP_REG3)); - src = TMP_REG1; - } else if (src & SLJIT_MEM) { - FAIL_IF(emit_op_mem(compiler, sljit_simd_get_mem_flags(elem_size) | LOAD_DATA, TMP_REG1, src, srcw)); - src = TMP_REG1; - } - - return push_inst(compiler, VMV_VX | VRD(vreg) | RS1(src)); -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, sljit_s32 lane_index, - sljit_s32 srcdst, sljit_sw srcdstw) -{ - sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); - sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); - sljit_s32 flags; - - CHECK_ERROR(); - CHECK(check_sljit_emit_simd_lane_mov(compiler, type, vreg, lane_index, srcdst, srcdstw)); - - ADJUST_LOCAL_OFFSET(srcdst, srcdstw); - - if (reg_size != 4) - return SLJIT_ERR_UNSUPPORTED; - -#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) - if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : elem_size > 2) - return SLJIT_ERR_UNSUPPORTED; -#else /* !SLJIT_CONFIG_RISCV_32 */ - if (((type & SLJIT_SIMD_FLOAT) && elem_size < 2) || elem_size > 3) - return SLJIT_ERR_UNSUPPORTED; -#endif /* SLJIT_CONFIG_RISCV_32 */ - - if (type & SLJIT_SIMD_TEST) - return SLJIT_SUCCESS; - - if (type & SLJIT_SIMD_STORE) { - FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | (1 << 15))); - - if (lane_index > 0) { - FAIL_IF(push_inst(compiler, VSLIDEDOWN_VI | VRD(TMP_VREG1) | ((sljit_ins)lane_index << 15) | VRS2(vreg))); - vreg = TMP_VREG1; - } - - if (srcdst & SLJIT_MEM) - return sljit_emit_vmem(compiler, VS | VRD(vreg), elem_size, srcdst, srcdstw); - - if (type & SLJIT_SIMD_FLOAT) - return push_inst(compiler, VFMV_FS | FRD(srcdst) | VRS2(vreg)); - - FAIL_IF(push_inst(compiler, VMV_XS | RD(srcdst) | VRS2(vreg))); - -#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) - if ((type & SLJIT_SIMD_LANE_SIGNED) || elem_size >= 2) - return SLJIT_SUCCESS; -#else /* !SLJIT_CONFIG_RISCV_32 */ - if ((type & SLJIT_SIMD_LANE_SIGNED) || elem_size >= 3 || (elem_size == 2 && (type & SLJIT_32))) - return SLJIT_SUCCESS; -#endif /* SLJIT_CONFIG_RISCV_32 */ - - if (elem_size == 0) - return push_inst(compiler, ANDI | RD(srcdst) | RS1(srcdst) | IMM_I(0xff)); - -#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) - flags = 16; -#else /* !SLJIT_CONFIG_RISCV_32 */ - flags = (elem_size == 1) ? 48 : 32; -#endif /* SLJIT_CONFIG_RISCV_32 */ - - FAIL_IF(push_inst(compiler, SLLI | RD(srcdst) | RS1(srcdst) | IMM_I(flags))); - return push_inst(compiler, SRLI | RD(srcdst) | RS1(srcdst) | IMM_I(flags)); - } - - if (type & SLJIT_SIMD_LANE_ZERO) { - FAIL_IF(sljit_emit_vsetivli(compiler, type, 0)); - FAIL_IF(push_inst(compiler, VMV_VI | VRD(vreg))); - } - - if (srcdst & SLJIT_MEM) { - FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | (1 << 15))); - FAIL_IF(sljit_emit_vmem(compiler, VL | VRD(lane_index > 0 ? TMP_VREG1 : vreg), elem_size, srcdst, srcdstw)); - - if (lane_index == 0) - return SLJIT_SUCCESS; - - FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | ((sljit_ins)(lane_index + 1) << 15))); - return push_inst(compiler, VSLIDEUP_VI | VRD(vreg) | ((sljit_ins)lane_index << 15) | VRS2(TMP_VREG1)); - } - - if (!(type & SLJIT_SIMD_LANE_ZERO) || lane_index > 0) - FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | ((sljit_ins)(lane_index + 1) << 15))); - - if (type & SLJIT_SIMD_FLOAT) { - FAIL_IF(push_inst(compiler, VFMV_SF | VRD(lane_index > 0 ? TMP_VREG1 : vreg) | FRS1(srcdst))); - - if (lane_index == 0) - return SLJIT_SUCCESS; - - return push_inst(compiler, VSLIDEUP_VI | VRD(vreg) | ((sljit_ins)lane_index << 15) | VRS2(TMP_VREG1)); - } - - if (srcdst == SLJIT_IMM) { - srcdstw = sljit_simd_get_imm(elem_size, srcdstw); - FAIL_IF(load_immediate(compiler, TMP_REG1, srcdstw, TMP_REG3)); - srcdst = TMP_REG1; - } - - FAIL_IF(push_inst(compiler, VMV_SX | VRD(lane_index > 0 ? TMP_VREG1 : vreg) | RS1(srcdst))); - - if (lane_index == 0) - return SLJIT_SUCCESS; - - return push_inst(compiler, VSLIDEUP_VI | VRD(vreg) | ((sljit_ins)lane_index << 15) | VRS2(TMP_VREG1)); -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, - sljit_s32 src, sljit_s32 src_lane_index) -{ - sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); - sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); - - CHECK_ERROR(); - CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, vreg, src, src_lane_index)); - - if (reg_size != 4) - return SLJIT_ERR_UNSUPPORTED; - - if (((type & SLJIT_SIMD_FLOAT) && elem_size < 2) || elem_size > 3) - return SLJIT_ERR_UNSUPPORTED; - - if (type & SLJIT_SIMD_TEST) - return SLJIT_SUCCESS; - - FAIL_IF(sljit_emit_vsetivli(compiler, type, 0)); - - FAIL_IF(push_inst(compiler, VRGATHER_VI | VRD(vreg != src ? vreg : TMP_VREG1) | ((sljit_ins)src_lane_index << 15) | VRS2(src))); - if (vreg == src) - return push_inst(compiler, VMV_VV | VRD(vreg) | VRS1(TMP_VREG1)); - return SLJIT_SUCCESS; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, - sljit_s32 src, sljit_sw srcw) -{ - sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); - sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); - sljit_s32 elem2_size = SLJIT_SIMD_GET_ELEM2_SIZE(type); - sljit_ins ins; - - CHECK_ERROR(); - CHECK(check_sljit_emit_simd_extend(compiler, type, vreg, src, srcw)); - - ADJUST_LOCAL_OFFSET(src, srcw); - - if (reg_size != 4) - return SLJIT_ERR_UNSUPPORTED; - -#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) - if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : elem_size > 2) - return SLJIT_ERR_UNSUPPORTED; -#else /* !SLJIT_CONFIG_RISCV_32 */ - if (((type & SLJIT_SIMD_FLOAT) && elem_size < 2) || elem_size > 3) - return SLJIT_ERR_UNSUPPORTED; -#endif /* SLJIT_CONFIG_RISCV_32 */ - - if (type & SLJIT_SIMD_TEST) - return SLJIT_SUCCESS; - - if ((src & SLJIT_MEM) || vreg == src) { - ins = (sljit_ins)1 << (reg_size - elem2_size); - FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | (ins << 15))); - - if (src & SLJIT_MEM) - FAIL_IF(sljit_emit_vmem(compiler, VL | VRD(TMP_VREG1), elem_size, src, srcw)); - else - FAIL_IF(push_inst(compiler, VMV_VV | VRD(TMP_VREG1) | VRS1(src))); - - src = TMP_VREG1; - } - - if (type & SLJIT_SIMD_FLOAT) { - FAIL_IF(sljit_emit_vsetivli(compiler, type, 0x7)); - return push_inst(compiler, VFWCVT_FFV | VRD(vreg) | VRS2(src)); - } - - ins = (sljit_ins)1 << (reg_size - elem2_size); - FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem2_size << 23) | (ins << 15))); - - switch (elem2_size - elem_size) { - case 1: - ins = VZEXT_VF2; - break; - case 2: - ins = VZEXT_VF4; - break; - default: - ins = VZEXT_VF8; - break; - } - - if (type & SLJIT_SIMD_EXTEND_SIGNED) - ins |= 1 << 15; - - return push_inst(compiler, ins | VRD(vreg) | VRS2(src)); -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, - sljit_s32 dst, sljit_sw dstw) -{ - sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); - sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); - sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; - - CHECK_ERROR(); - CHECK(check_sljit_emit_simd_sign(compiler, type, vreg, dst, dstw)); - - ADJUST_LOCAL_OFFSET(dst, dstw); - - if (reg_size != 4) - return SLJIT_ERR_UNSUPPORTED; - - if (((type & SLJIT_SIMD_FLOAT) && elem_size < 2) || elem_size > 3) - return SLJIT_ERR_UNSUPPORTED; - - FAIL_IF(sljit_emit_vsetivli(compiler, type, 0)); - FAIL_IF(push_inst(compiler, VMV_VI | VRD(TMP_VREG1) | (0x0 << 15))); - FAIL_IF(push_inst(compiler, VMSLE_VI | VRD(TMP_VREG1) | (0x0 << 15) | VRS2(vreg))); - - FAIL_IF(sljit_emit_vsetivli_size(compiler, 2, 2)); - FAIL_IF(push_inst(compiler, VMV_XS | RD(dst_r) | VRS2(TMP_VREG1))); - - if (dst & SLJIT_MEM) - return emit_op_mem(compiler, (type & SLJIT_32) ? INT_DATA : WORD_DATA, dst_r, dst, dstw); - return SLJIT_SUCCESS; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w) -{ - sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); - sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); - sljit_ins ins = 0; - - CHECK_ERROR(); - CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w)); - - ADJUST_LOCAL_OFFSET(src2, src2w); - - if (reg_size != 4) - return SLJIT_ERR_UNSUPPORTED; - - if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3)) - return SLJIT_ERR_UNSUPPORTED; - - if (type & SLJIT_SIMD_TEST) - return SLJIT_SUCCESS; - - switch (SLJIT_SIMD_GET_OPCODE(type)) { - case SLJIT_SIMD_OP2_AND: - ins = VAND_VV; - break; - case SLJIT_SIMD_OP2_OR: - ins = VOR_VV; - break; - case SLJIT_SIMD_OP2_XOR: - ins = VXOR_VV; - break; - case SLJIT_SIMD_OP2_SHUFFLE: - ins = VRGATHER_VV; - elem_size = 0; - break; - } - - if (elem_size > 3) - elem_size = 3; - - FAIL_IF(sljit_emit_vsetivli_size(compiler, reg_size, elem_size)); - - if (src2 & SLJIT_MEM) { - FAIL_IF(sljit_emit_vmem(compiler, VL | VRD(TMP_VREG1), elem_size, src2, src2w)); - src2 = TMP_VREG1; - } - - if (SLJIT_SIMD_GET_OPCODE(type) != SLJIT_SIMD_OP2_SHUFFLE) - return push_inst(compiler, ins | VRD(dst_vreg) | VRS1(src1_vreg) | VRS2(src2)); - - if (dst_vreg == src2) { - FAIL_IF(push_inst(compiler, VMV_VV | VRD(TMP_VREG1) | VRS1(src2))); - src2 = TMP_VREG1; - } - - if (dst_vreg == src1_vreg) { - FAIL_IF(push_inst(compiler, VMV_VV | VRD(TMP_VREG2) | VRS1(src1_vreg))); - src1_vreg = TMP_VREG2; - } - - return push_inst(compiler, ins | VRD(dst_vreg) | VRS1(src2) | VRS2(src1_vreg)); -} - SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) { struct sljit_const *const_; diff --git a/ext/pcre/pcre2lib/sljit/sljitNativeS390X.c b/ext/pcre/pcre2lib/sljit/sljitNativeS390X.c index 7ce9f9fcdcc58..99e846350fdd6 100644 --- a/ext/pcre/pcre2lib/sljit/sljitNativeS390X.c +++ b/ext/pcre/pcre2lib/sljit/sljitNativeS390X.c @@ -1638,7 +1638,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) case SLJIT_HAS_COPY_F64: case SLJIT_HAS_SIMD: case SLJIT_HAS_ATOMIC: - case SLJIT_HAS_MEMORY_BARRIER: return 1; case SLJIT_HAS_CTZ: @@ -1661,26 +1660,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) /* --------------------------------------------------------------------- */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 fscratches; - sljit_s32 fsaveds; sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options); sljit_s32 offset, i, tmp; CHECK_ERROR(); - CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size)); - set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size); + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); /* Saved registers are stored in callee allocated save area. */ SLJIT_ASSERT(gpr(SLJIT_FIRST_SAVED_REG) == r6 && gpr(SLJIT_S0) == r13); - scratches = ENTER_GET_REGS(scratches); - saveds = ENTER_GET_REGS(saveds); - fscratches = compiler->fscratches; - fsaveds = compiler->fsaveds; - offset = 2 * SSIZE_OF(sw); if (saveds + scratches >= SLJIT_NUMBER_OF_REGISTERS) { if (saved_arg_count == 0) { @@ -1764,12 +1756,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { CHECK_ERROR(); - CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size)); - set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size); + CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); compiler->local_size = (local_size + SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE + 0xf) & ~0xf; return SLJIT_SUCCESS; @@ -1931,7 +1923,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile return SLJIT_SUCCESS; case SLJIT_DIV_S32: case SLJIT_DIVMOD_S32: - FAIL_IF(push_inst(compiler, 0xeb00000000dc /* srak */ | R36A(tmp0) | R32A(arg0) | (31 << 16))); + FAIL_IF(push_inst(compiler, lhi(tmp0, 0))); FAIL_IF(push_inst(compiler, lr(tmp1, arg0))); FAIL_IF(push_inst(compiler, dr(tmp0, arg1))); FAIL_IF(push_inst(compiler, lr(arg0, tmp1))); /* quotient */ @@ -1958,8 +1950,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile return push_inst(compiler, lgr(arg1, tmp0)); /* remainder */ return SLJIT_SUCCESS; - case SLJIT_MEMORY_BARRIER: - return push_inst(compiler, 0x0700 /* bcr */ | (0xe << 4) | 0); case SLJIT_ENDBR: return SLJIT_SUCCESS; case SLJIT_SKIP_FRAMES_BEFORE_RETURN: @@ -2485,9 +2475,14 @@ static sljit_s32 sljit_emit_sub(struct sljit_compiler *compiler, sljit_s32 op, ins = (op & SLJIT_32) ? 0xc20d00000000 /* cfi */ : 0xc20c00000000 /* cgfi */; return emit_ri(compiler, ins, src1, src1, src1w, src2w, RIL_A); } - } else if ((op & SLJIT_32) || is_u32(src2w)) { - ins = (op & SLJIT_32) ? 0xc20f00000000 /* clfi */ : 0xc20e00000000 /* clgfi */; - return emit_ri(compiler, ins, src1, src1, src1w, src2w, RIL_A); + } + else { + if ((op & SLJIT_32) || is_u32(src2w)) { + ins = (op & SLJIT_32) ? 0xc20f00000000 /* clfi */ : 0xc20e00000000 /* clgfi */; + return emit_ri(compiler, ins, src1, src1, src1w, src2w, RIL_A); + } + if (is_s16(src2w)) + return emit_rie_d(compiler, 0xec00000000db /* alghsik */, (sljit_s32)tmp0, src1, src1w, src2w); } } else if (src2 & SLJIT_MEM) { @@ -3187,7 +3182,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, slji if (type == SLJIT_GP_REGISTER) return (sljit_s32)gpr(reg); - if (type != SLJIT_FLOAT_REGISTER && type != SLJIT_SIMD_REG_128) + if (type != SLJIT_FLOAT_REGISTER) return -1; return (sljit_s32)freg_map[reg]; @@ -3939,7 +3934,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 srcdst, sljit_sw srcdstw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -3949,7 +3944,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *co sljit_ins ins; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_mov(compiler, type, vreg, srcdst, srcdstw)); + CHECK(check_sljit_emit_simd_mov(compiler, type, freg, srcdst, srcdstw)); ADJUST_LOCAL_OFFSET(srcdst, srcdstw); @@ -3964,15 +3959,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *co if (!(srcdst & SLJIT_MEM)) { if (type & SLJIT_SIMD_STORE) - ins = F36(srcdst) | F32(vreg); + ins = F36(srcdst) | F32(freg); else - ins = F36(vreg) | F32(srcdst); + ins = F36(freg) | F32(srcdst); return push_inst(compiler, 0xe70000000056 /* vlr */ | ins); } FAIL_IF(make_addr_bx(compiler, &addr, srcdst, srcdstw, tmp1)); - ins = F36(vreg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset); + ins = F36(freg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset); if (alignment >= 4) ins |= 4 << 12; @@ -3983,7 +3978,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *co } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_sw srcw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -3993,7 +3988,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil sljit_sw sign_ext; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_replicate(compiler, type, vreg, src, srcw)); + CHECK(check_sljit_emit_simd_replicate(compiler, type, freg, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); @@ -4008,15 +4003,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil if (src & SLJIT_MEM) { FAIL_IF(make_addr_bx(compiler, &addr, src, srcw, tmp1)); - return push_inst(compiler, 0xe70000000005 /* vlrep */ | F36(vreg) + return push_inst(compiler, 0xe70000000005 /* vlrep */ | F36(freg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset) | ((sljit_ins)elem_size << 12)); } if (type & SLJIT_SIMD_FLOAT) { if (src == SLJIT_IMM) - return push_inst(compiler, 0xe70000000044 /* vgbm */ | F36(vreg)); + return push_inst(compiler, 0xe70000000044 /* vgbm */ | F36(freg)); - return push_inst(compiler, 0xe7000000004d /* vrep */ | F36(vreg) | F32(src) | ((sljit_ins)elem_size << 12)); + return push_inst(compiler, 0xe7000000004d /* vrep */ | F36(freg) | F32(src) | ((sljit_ins)elem_size << 12)); } if (src == SLJIT_IMM) { @@ -4048,10 +4043,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil if (sign_ext != 0x10000) { if (sign_ext == 0 || sign_ext == -1) - return push_inst(compiler, 0xe70000000044 /* vgbm */ | F36(vreg) + return push_inst(compiler, 0xe70000000044 /* vgbm */ | F36(freg) | (sign_ext == 0 ? 0 : ((sljit_ins)0xffff << 16))); - return push_inst(compiler, 0xe70000000045 /* vrepi */ | F36(vreg) + return push_inst(compiler, 0xe70000000045 /* vrepi */ | F36(freg) | ((sljit_ins)srcw << 16) | ((sljit_ins)elem_size << 12)); } @@ -4060,12 +4055,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil } else reg = gpr(src); - FAIL_IF(push_inst(compiler, 0xe70000000022 /* vlvg */ | F36(vreg) | R32A(reg) | ((sljit_ins)elem_size << 12))); - return push_inst(compiler, 0xe7000000004d /* vrep */ | F36(vreg) | F32(vreg) | ((sljit_ins)elem_size << 12)); + FAIL_IF(push_inst(compiler, 0xe70000000022 /* vlvg */ | F36(freg) | R32A(reg) | ((sljit_ins)elem_size << 12))); + return push_inst(compiler, 0xe7000000004d /* vrep */ | F36(freg) | F32(freg) | ((sljit_ins)elem_size << 12)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, sljit_s32 lane_index, + sljit_s32 freg, sljit_s32 lane_index, sljit_s32 srcdst, sljit_sw srcdstw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -4075,7 +4070,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile sljit_ins ins = 0; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_lane_mov(compiler, type, vreg, lane_index, srcdst, srcdstw)); + CHECK(check_sljit_emit_simd_lane_mov(compiler, type, freg, lane_index, srcdst, srcdstw)); ADJUST_LOCAL_OFFSET(srcdst, srcdstw); @@ -4090,20 +4085,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile if (srcdst & SLJIT_MEM) { FAIL_IF(make_addr_bx(compiler, &addr, srcdst, srcdstw, tmp1)); - ins = F36(vreg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset); + ins = F36(freg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset); } if (type & SLJIT_SIMD_LANE_ZERO) { if ((srcdst & SLJIT_MEM) && lane_index == ((1 << (3 - elem_size)) - 1)) return push_inst(compiler, 0xe70000000004 /* vllez */ | ins | ((sljit_ins)elem_size << 12)); - if ((type & SLJIT_SIMD_FLOAT) && vreg == srcdst) { - FAIL_IF(push_inst(compiler, 0xe70000000056 /* vlr */ | F36(TMP_FREG1) | F32(vreg))); + if ((type & SLJIT_SIMD_FLOAT) && freg == srcdst) { + FAIL_IF(push_inst(compiler, 0xe70000000056 /* vlr */ | F36(TMP_FREG1) | F32(freg))); srcdst = TMP_FREG1; srcdstw = 0; } - FAIL_IF(push_inst(compiler, 0xe70000000044 /* vgbm */ | F36(vreg))); + FAIL_IF(push_inst(compiler, 0xe70000000044 /* vgbm */ | F36(freg))); } if (srcdst & SLJIT_MEM) { @@ -4131,19 +4126,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile if (type & SLJIT_SIMD_FLOAT) { if (type & SLJIT_SIMD_STORE) - return push_inst(compiler, 0xe7000000004d /* vrep */ | F36(srcdst) | F32(vreg) | ((sljit_ins)lane_index << 16) | ((sljit_ins)elem_size << 12)); + return push_inst(compiler, 0xe7000000004d /* vrep */ | F36(srcdst) | F32(freg) | ((sljit_ins)lane_index << 16) | ((sljit_ins)elem_size << 12)); if (elem_size == 3) { if (lane_index == 0) - ins = F32(srcdst) | F28(vreg) | (1 << 12); + ins = F32(srcdst) | F28(freg) | (1 << 12); else - ins = F32(vreg) | F28(srcdst); + ins = F32(freg) | F28(srcdst); - return push_inst(compiler, 0xe70000000084 /* vpdi */ | F36(vreg) | ins); + return push_inst(compiler, 0xe70000000084 /* vpdi */ | F36(freg) | ins); } FAIL_IF(push_inst(compiler, 0xe70000000021 /* vlgv */ | R36A(tmp0) | F32(srcdst) | ((sljit_ins)2 << 12))); - return push_inst(compiler, 0xe70000000022 /* vlvg */ | F36(vreg) | R32A(tmp0) | ((sljit_ins)lane_index << 16) | ((sljit_ins)2 << 12)); + return push_inst(compiler, 0xe70000000022 /* vlvg */ | F36(freg) | R32A(tmp0) | ((sljit_ins)lane_index << 16) | ((sljit_ins)2 << 12)); } if (srcdst == SLJIT_IMM) { @@ -4172,7 +4167,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile } if (ins != 0) - return push_inst(compiler, ins | F36(vreg) | ((sljit_ins)srcdstw << 16) | ((sljit_ins)lane_index << 12)); + return push_inst(compiler, ins | F36(freg) | ((sljit_ins)srcdstw << 16) | ((sljit_ins)lane_index << 12)); push_load_imm_inst(compiler, tmp0, srcdstw); reg = tmp0; @@ -4182,9 +4177,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile ins = ((sljit_ins)lane_index << 16) | ((sljit_ins)elem_size << 12); if (!(type & SLJIT_SIMD_STORE)) - return push_inst(compiler, 0xe70000000022 /* vlvg */ | F36(vreg) | R32A(reg) | ins); + return push_inst(compiler, 0xe70000000022 /* vlvg */ | F36(freg) | R32A(reg) | ins); - FAIL_IF(push_inst(compiler, 0xe70000000021 /* vlgv */ | R36A(reg) | F32(vreg) | ins)); + FAIL_IF(push_inst(compiler, 0xe70000000021 /* vlgv */ | R36A(reg) | F32(freg) | ins)); if (!(type & SLJIT_SIMD_LANE_SIGNED) || elem_size >= 3) return SLJIT_SUCCESS; @@ -4205,14 +4200,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_s32 src_lane_index) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); CHECK_ERROR(); - CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, vreg, src, src_lane_index)); + CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, freg, src, src_lane_index)); if (reg_size != 4) return SLJIT_ERR_UNSUPPORTED; @@ -4223,12 +4218,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c if (type & SLJIT_SIMD_TEST) return SLJIT_SUCCESS; - return push_inst(compiler, 0xe7000000004d /* vrep */ | F36(vreg) | F32(src) + return push_inst(compiler, 0xe7000000004d /* vrep */ | F36(freg) | F32(src) | ((sljit_ins)src_lane_index << 16) | ((sljit_ins)elem_size << 12)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_sw srcw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -4238,7 +4233,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler sljit_ins ins; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_extend(compiler, type, vreg, src, srcw)); + CHECK(check_sljit_emit_simd_extend(compiler, type, freg, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); @@ -4253,7 +4248,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler if (src & SLJIT_MEM) { FAIL_IF(make_addr_bx(compiler, &addr, src, srcw, tmp1)); - ins = F36(vreg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset); + ins = F36(freg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset); switch (elem2_size - elem_size) { case 1: @@ -4268,27 +4263,27 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler } FAIL_IF(push_inst(compiler, ins)); - src = vreg; + src = freg; } if (type & SLJIT_SIMD_FLOAT) { - FAIL_IF(push_inst(compiler, 0xe700000000d5 /* vuplh */ | F36(vreg) | F32(src) | (2 << 12))); - FAIL_IF(push_inst(compiler, 0xe70000000030 /* vesl */ | F36(vreg) | F32(vreg) | (32 << 16) | (3 << 12))); - return push_inst(compiler, 0xe700000000c4 /* vfll */ | F36(vreg) | F32(vreg) | (2 << 12)); + FAIL_IF(push_inst(compiler, 0xe700000000d5 /* vuplh */ | F36(freg) | F32(src) | (2 << 12))); + FAIL_IF(push_inst(compiler, 0xe70000000030 /* vesl */ | F36(freg) | F32(freg) | (32 << 16) | (3 << 12))); + return push_inst(compiler, 0xe700000000c4 /* vfll */ | F36(freg) | F32(freg) | (2 << 12)); } - ins = ((type & SLJIT_SIMD_EXTEND_SIGNED) ? 0xe700000000d7 /* vuph */ : 0xe700000000d5 /* vuplh */) | F36(vreg); + ins = ((type & SLJIT_SIMD_EXTEND_SIGNED) ? 0xe700000000d7 /* vuph */ : 0xe700000000d5 /* vuplh */) | F36(freg); do { FAIL_IF(push_inst(compiler, ins | F32(src) | ((sljit_ins)elem_size << 12))); - src = vreg; + src = freg; } while (++elem_size < elem2_size); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 dst, sljit_sw dstw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -4296,7 +4291,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c sljit_gpr dst_r; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_sign(compiler, type, vreg, dst, dstw)); + CHECK(check_sljit_emit_simd_sign(compiler, type, freg, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); @@ -4329,7 +4324,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c if (elem_size != 0) FAIL_IF(push_inst(compiler, 0xe70000000022 /* vlvg */ | F36(TMP_FREG1) | R32A(tmp0) | (1 << 16) | (3 << 12))); - FAIL_IF(push_inst(compiler, 0xe70000000085 /* vbperm */ | F36(TMP_FREG1) | F32(vreg) | F28(TMP_FREG1))); + FAIL_IF(push_inst(compiler, 0xe70000000085 /* vbperm */ | F36(TMP_FREG1) | F32(freg) | F28(TMP_FREG1))); dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0; FAIL_IF(push_inst(compiler, 0xe70000000021 /* vlgv */ | R36A(dst_r) | F32(TMP_FREG1) @@ -4342,17 +4337,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w) + sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); - sljit_s32 alignment; - struct addr addr; - sljit_ins ins = 0, load_ins; + sljit_ins ins = 0; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w)); - ADJUST_LOCAL_OFFSET(src2, src2w); + CHECK(check_sljit_emit_simd_op2(compiler, type, dst_freg, src1_freg, src2_freg)); if (reg_size != 4) return SLJIT_ERR_UNSUPPORTED; @@ -4373,29 +4365,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *co case SLJIT_SIMD_OP2_XOR: ins = 0xe7000000006d /* vx */; break; - case SLJIT_SIMD_OP2_SHUFFLE: - ins = 0xe7000000008c /* vperm */; - break; } - if (src2 & SLJIT_MEM) { - FAIL_IF(make_addr_bx(compiler, &addr, src2, src2w, tmp1)); - load_ins = 0xe70000000006 /* vl */ | F36(TMP_FREG1) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset); - alignment = SLJIT_SIMD_GET_ELEM2_SIZE(type); - - if (alignment >= 4) - load_ins |= 4 << 12; - else if (alignment == 3) - load_ins |= 3 << 12; - - FAIL_IF(push_inst(compiler, load_ins)); - src2 = TMP_FREG1; - } - - if (SLJIT_SIMD_GET_OPCODE(type) == SLJIT_SIMD_OP2_SHUFFLE) - return push_inst(compiler, ins | F36(dst_vreg) | F32(src1_vreg) | F28(src1_vreg) | F12(src2)); + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; - return push_inst(compiler, ins | F36(dst_vreg) | F32(src1_vreg) | F28(src2)); + return push_inst(compiler, ins | F36(dst_freg) | F32(src1_freg) | F28(src2_freg)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op, @@ -4405,22 +4380,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler CHECK_ERROR(); CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg)); - if (op & SLJIT_ATOMIC_USE_LS) - return SLJIT_ERR_UNSUPPORTED; - - switch (GET_OPCODE(op)) { - case SLJIT_MOV32: - case SLJIT_MOV_U32: - case SLJIT_MOV: - case SLJIT_MOV_P: - if (op & SLJIT_ATOMIC_TEST) - return SLJIT_SUCCESS; - - SLJIT_SKIP_CHECKS(compiler); - return sljit_emit_op1(compiler, op & ~SLJIT_ATOMIC_USE_CAS, dst_reg, 0, SLJIT_MEM1(mem_reg), 0); - default: - return SLJIT_ERR_UNSUPPORTED; - } + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_op1(compiler, op, dst_reg, 0, SLJIT_MEM1(mem_reg), 0); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op, @@ -4428,33 +4389,44 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler sljit_s32 mem_reg, sljit_s32 temp_reg) { - sljit_ins ins; + sljit_ins mask; sljit_gpr tmp_r = gpr(temp_reg); sljit_gpr mem_r = gpr(mem_reg); CHECK_ERROR(); CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg)); - if (op & SLJIT_ATOMIC_USE_LS) - return SLJIT_ERR_UNSUPPORTED; - switch (GET_OPCODE(op)) { case SLJIT_MOV32: case SLJIT_MOV_U32: - ins = 0xba000000 /* cs */ | R20A(tmp_r) | R16A(gpr(src_reg)) | R12A(mem_r); + return push_inst(compiler, 0xba000000 /* cs */ | R20A(tmp_r) | R16A(gpr(src_reg)) | R12A(mem_r)); + case SLJIT_MOV_U8: + mask = 0xff; break; - case SLJIT_MOV: - case SLJIT_MOV_P: - ins = 0xeb0000000030 /* csg */ | R36A(tmp_r) | R32A(gpr(src_reg)) | R28A(mem_r); + case SLJIT_MOV_U16: + mask = 0xffff; break; default: - return SLJIT_ERR_UNSUPPORTED; + return push_inst(compiler, 0xeb0000000030 /* csg */ | R36A(tmp_r) | R32A(gpr(src_reg)) | R28A(mem_r)); } - if (op & SLJIT_ATOMIC_TEST) - return SLJIT_SUCCESS; + /* tmp0 = (src_reg ^ tmp_r) & mask */ + FAIL_IF(push_inst(compiler, 0xa50f0000 /* llill */ | R20A(tmp1) | mask)); + FAIL_IF(push_inst(compiler, 0xb9e70000 /* xgrk */ | R4A(tmp0) | R0A(gpr(src_reg)) | R12A(tmp_r))); + FAIL_IF(push_inst(compiler, 0xa7090000 /* lghi */ | R20A(tmp_r) | 0xfffc)); + FAIL_IF(push_inst(compiler, 0xb9800000 /* ngr */ | R4A(tmp0) | R0A(tmp1))); - return push_inst(compiler, ins); + /* tmp0 = tmp0 << (((mem_r ^ 0x3) & 0x3) << 3) */ + FAIL_IF(push_inst(compiler, 0xa50f0000 /* llill */ | R20A(tmp1) | (sljit_ins)((mask == 0xff) ? 0x18 : 0x10))); + FAIL_IF(push_inst(compiler, 0xb9800000 /* ngr */ | R4A(tmp_r) | R0A(mem_r))); + FAIL_IF(push_inst(compiler, 0xec0000000057 /* rxsbg */ | R36A(tmp1) | R32A(mem_r) | (59 << 24) | (60 << 16) | (3 << 8))); + FAIL_IF(push_inst(compiler, 0xeb000000000d /* sllg */ | R36A(tmp0) | R32A(tmp0) | R28A(tmp1))); + + /* Already computed: tmp_r = mem_r & ~0x3 */ + + FAIL_IF(push_inst(compiler, 0x58000000 /* l */ | R20A(tmp1) | R12A(tmp_r))); + FAIL_IF(push_inst(compiler, 0x1700 /* x */ | R4A(tmp0) | R0A(tmp1))); + return push_inst(compiler, 0xba000000 /* cs */ | R20A(tmp1) | R16A(tmp0) | R12A(tmp_r)); } /* --------------------------------------------------------------------- */ diff --git a/ext/pcre/pcre2lib/sljit/sljitNativeX86_32.c b/ext/pcre/pcre2lib/sljit/sljitNativeX86_32.c index 217a1498abe18..59ea04a5c81b1 100644 --- a/ext/pcre/pcre2lib/sljit/sljitNativeX86_32.c +++ b/ext/pcre/pcre2lib/sljit/sljitNativeX86_32.c @@ -311,8 +311,8 @@ static sljit_u8* detect_far_jump_type(struct sljit_jump *jump, sljit_u8 *code_pt #define ENTER_TMP_TO_S 0x00002 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_s32 word_arg_count, saved_arg_count, float_arg_count; sljit_s32 size, args_size, types, status; @@ -323,10 +323,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi #endif CHECK_ERROR(); - CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size)); - set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size); - - scratches = ENTER_GET_REGS(scratches); + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); /* Emit ENDBR32 at function entry if needed. */ FAIL_IF(emit_endbranch(compiler)); @@ -538,16 +536,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_s32 args_size; CHECK_ERROR(); - CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size)); - set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size); - - scratches = ENTER_GET_REGS(scratches); + CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); arg_types >>= SLJIT_ARG_SHIFT; args_size = 0; diff --git a/ext/pcre/pcre2lib/sljit/sljitNativeX86_64.c b/ext/pcre/pcre2lib/sljit/sljitNativeX86_64.c index e4d3db828fa09..1ab79293c7efc 100644 --- a/ext/pcre/pcre2lib/sljit/sljitNativeX86_64.c +++ b/ext/pcre/pcre2lib/sljit/sljitNativeX86_64.c @@ -454,16 +454,14 @@ typedef struct { #endif /* _WIN64 */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_uw size; sljit_s32 word_arg_count = 0; sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options); sljit_s32 saved_regs_size, tmp, i; #ifdef _WIN64 - sljit_s32 fscratches; - sljit_s32 fsaveds; sljit_s32 saved_float_regs_size; sljit_s32 saved_float_regs_offset = 0; sljit_s32 float_arg_count = 0; @@ -471,15 +469,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi sljit_u8 *inst; CHECK_ERROR(); - CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size)); - set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size); - - scratches = ENTER_GET_REGS(scratches); -#ifdef _WIN64 - saveds = ENTER_GET_REGS(saveds); - fscratches = compiler->fscratches; - fsaveds = compiler->fsaveds; -#endif /* _WIN64 */ + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); if (options & SLJIT_ENTER_REG_ARG) arg_types = 0; @@ -639,27 +630,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, - sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size) + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_s32 saved_regs_size; #ifdef _WIN64 - sljit_s32 fscratches; - sljit_s32 fsaveds; sljit_s32 saved_float_regs_size; #endif /* _WIN64 */ CHECK_ERROR(); - CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size)); - set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size); - - scratches = ENTER_GET_REGS(scratches); + CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); #ifdef _WIN64 - saveds = ENTER_GET_REGS(saveds); - fscratches = compiler->fscratches; - fsaveds = compiler->fsaveds; - local_size += SLJIT_LOCALS_OFFSET; saved_float_regs_size = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sse2_reg); diff --git a/ext/pcre/pcre2lib/sljit/sljitNativeX86_common.c b/ext/pcre/pcre2lib/sljit/sljitNativeX86_common.c index 9f599d5fb0899..ecb7e9be3b0e0 100644 --- a/ext/pcre/pcre2lib/sljit/sljitNativeX86_common.c +++ b/ext/pcre/pcre2lib/sljit/sljitNativeX86_common.c @@ -239,7 +239,6 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2] = { #define MOVDDUP_x_xm 0x12 #define MOVDQA_x_xm 0x6f #define MOVDQA_xm_x 0x7f -#define MOVDQU_x_xm 0x6f #define MOVHLPS_x_x 0x12 #define MOVHPD_m_x 0x17 #define MOVHPD_x_m 0x16 @@ -399,13 +398,6 @@ static sljit_u32 cpu_feature_list = 0; #include #elif defined(_MSC_VER) && _MSC_VER >= 1400 #include -#elif defined(__INTEL_COMPILER) -#include -#endif - -#if (defined(_MSC_VER) && _MSC_VER >= 1400) || defined(__INTEL_COMPILER) \ - || (defined(__INTEL_LLVM_COMPILER) && defined(__XSAVE__)) -#include #endif /******************************************************/ @@ -433,20 +425,49 @@ static SLJIT_INLINE void sljit_unaligned_store_sw(void *addr, sljit_sw value) static void execute_cpu_id(sljit_u32 info[4]) { -#if (defined(_MSC_VER) && _MSC_VER >= 1400) \ - || (defined(__INTEL_COMPILER) && __INTEL_COMPILER == 2021 && __INTEL_COMPILER_UPDATE >= 7) +#if defined(_MSC_VER) && _MSC_VER >= 1400 __cpuidex((int*)info, (int)info[0], (int)info[2]); -#elif (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1900) +#elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_C) || defined(__TINYC__) - __get_cpuid_count(info[0], info[2], info, info + 1, info + 2, info + 3); + /* AT&T syntax. */ + __asm__ ( +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + "movl %0, %%esi\n" + "movl (%%esi), %%eax\n" + "movl 8(%%esi), %%ecx\n" + "pushl %%ebx\n" + "cpuid\n" + "movl %%eax, (%%esi)\n" + "movl %%ebx, 4(%%esi)\n" + "popl %%ebx\n" + "movl %%ecx, 8(%%esi)\n" + "movl %%edx, 12(%%esi)\n" +#else /* !SLJIT_CONFIG_X86_32 */ + "movq %0, %%rsi\n" + "movl (%%rsi), %%eax\n" + "movl 8(%%rsi), %%ecx\n" + "cpuid\n" + "movl %%eax, (%%rsi)\n" + "movl %%ebx, 4(%%rsi)\n" + "movl %%ecx, 8(%%rsi)\n" + "movl %%edx, 12(%%rsi)\n" +#endif /* SLJIT_CONFIG_X86_32 */ + : + : "r" (info) +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + : "memory", "eax", "ecx", "edx", "esi" +#else /* !SLJIT_CONFIG_X86_32 */ + : "memory", "rax", "rbx", "rcx", "rdx", "rsi" +#endif /* SLJIT_CONFIG_X86_32 */ + ); -#elif (defined(_MSC_VER) || defined(__INTEL_COMPILER)) \ - && (defined(SLJIT_CONFIG_X86_32) && SLJIT_CONFIG_X86_32) +#else /* _MSC_VER < 1400 */ /* Intel syntax. */ __asm { +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) mov esi, info mov eax, [esi] mov ecx, [esi + 8] @@ -455,48 +476,30 @@ static void execute_cpu_id(sljit_u32 info[4]) mov [esi + 4], ebx mov [esi + 8], ecx mov [esi + 12], edx +#else /* !SLJIT_CONFIG_X86_32 */ + mov rsi, info + mov eax, [rsi] + mov ecx, [rsi + 8] + cpuid + mov [rsi], eax + mov [rsi + 4], ebx + mov [rsi + 8], ecx + mov [rsi + 12], edx +#endif /* SLJIT_CONFIG_X86_32 */ } -#else - - __asm__ __volatile__ ( - "cpuid\n" - : "=a" (info[0]), "=b" (info[1]), "=c" (info[2]), "=d" (info[3]) - : "0" (info[0]), "2" (info[2]) - ); - -#endif +#endif /* _MSC_VER && _MSC_VER >= 1400 */ } static sljit_u32 execute_get_xcr0_low(void) { sljit_u32 xcr0; -#if (defined(_MSC_VER) && _MSC_VER >= 1400) || defined(__INTEL_COMPILER) \ - || (defined(__INTEL_LLVM_COMPILER) && defined(__XSAVE__)) +#if defined(_MSC_VER) && _MSC_VER >= 1400 xcr0 = (sljit_u32)_xgetbv(0); -#elif defined(__TINYC__) - - __asm__ ( - "xorl %%ecx, %%ecx\n" - ".byte 0x0f\n" - ".byte 0x01\n" - ".byte 0xd0\n" - : "=a" (xcr0) - : -#if defined(SLJIT_CONFIG_X86_32) && SLJIT_CONFIG_X86_32 - : "ecx", "edx" -#else /* !SLJIT_CONFIG_X86_32 */ - : "rcx", "rdx" -#endif /* SLJIT_CONFIG_X86_32 */ - ); - -#elif (defined(__INTEL_LLVM_COMPILER) && __INTEL_LLVM_COMPILER < 20220100) \ - || (defined(__clang__) && __clang_major__ < 14) \ - || (defined(__GNUC__) && __GNUC__ < 3) \ - || defined(__SUNPRO_C) || defined(__SUNPRO_CC) +#elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_C) || defined(__TINYC__) /* AT&T syntax. */ __asm__ ( @@ -504,37 +507,23 @@ static sljit_u32 execute_get_xcr0_low(void) "xgetbv\n" : "=a" (xcr0) : -#if defined(SLJIT_CONFIG_X86_32) && SLJIT_CONFIG_X86_32 +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) : "ecx", "edx" #else /* !SLJIT_CONFIG_X86_32 */ : "rcx", "rdx" #endif /* SLJIT_CONFIG_X86_32 */ ); -#elif defined(_MSC_VER) +#else /* _MSC_VER < 1400 */ /* Intel syntax. */ __asm { - xor ecx, ecx + mov ecx, 0 xgetbv mov xcr0, eax } -#else - - __asm__ ( - "xor{l %%ecx, %%ecx | ecx, ecx}\n" - "xgetbv\n" - : "=a" (xcr0) - : -#if defined(SLJIT_CONFIG_X86_32) && SLJIT_CONFIG_X86_32 - : "ecx", "edx" -#else /* !SLJIT_CONFIG_X86_32 */ - : "rcx", "rdx" -#endif /* SLJIT_CONFIG_X86_32 */ - ); - -#endif +#endif /* _MSC_VER && _MSC_VER >= 1400 */ return xcr0; } @@ -560,10 +549,6 @@ static void get_cpu_features(void) if (max_id >= 1) { info[0] = 1; -#if defined(SLJIT_CONFIG_X86_32) && SLJIT_CONFIG_X86_32 - /* Winchip 2 and Cyrix MII bugs */ - info[1] = info[2] = 0; -#endif execute_cpu_id(info); if (info[2] & 0x80000) @@ -580,17 +565,11 @@ static void get_cpu_features(void) feature_list |= CPU_FEATURE_CMOV; } - info[0] = 0x80000000; + info[0] = 0x80000001; execute_cpu_id(info); - max_id = info[0]; - - if (max_id >= 0x80000001) { - info[0] = 0x80000001; - execute_cpu_id(info); - if (info[2] & 0x20) - feature_list |= CPU_FEATURE_LZCNT; - } + if (info[2] & 0x20) + feature_list |= CPU_FEATURE_LZCNT; if ((feature_list & CPU_FEATURE_OSXSAVE) && (execute_get_xcr0_low() & 0x4) == 0) feature_list &= ~(sljit_u32)(CPU_FEATURE_AVX | CPU_FEATURE_AVX2); @@ -680,23 +659,18 @@ static sljit_u8* detect_near_jump_type(struct sljit_jump *jump, sljit_u8 *code_p sljit_uw type = jump->flags >> TYPE_SHIFT; sljit_s32 short_jump; sljit_uw label_addr; - sljit_uw jump_addr; - - jump_addr = (sljit_uw)code_ptr; - if (!(jump->flags & JUMP_ADDR)) { - label_addr = (sljit_uw)(code + jump->u.label->size); - if (jump->u.label->size > jump->addr) - jump_addr = (sljit_uw)(code + jump->addr); - } else + if (jump->flags & JUMP_ADDR) label_addr = jump->u.target - (sljit_uw)executable_offset; + else + label_addr = (sljit_uw)(code + jump->u.label->size); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - if ((sljit_sw)(label_addr - (jump_addr + 6)) > HALFWORD_MAX || (sljit_sw)(label_addr - (jump_addr + 5)) < HALFWORD_MIN) + if ((sljit_sw)(label_addr - (sljit_uw)(code_ptr + 6)) > HALFWORD_MAX || (sljit_sw)(label_addr - (sljit_uw)(code_ptr + 5)) < HALFWORD_MIN) return detect_far_jump_type(jump, code_ptr); #endif /* SLJIT_CONFIG_X86_64 */ - short_jump = (sljit_sw)(label_addr - (jump_addr + 2)) >= -0x80 && (sljit_sw)(label_addr - (jump_addr + 2)) <= 0x7f; + short_jump = (sljit_sw)(label_addr - (sljit_uw)(code_ptr + 2)) >= -0x80 && (sljit_sw)(label_addr - (sljit_uw)(code_ptr + 2)) <= 0x7f; if (type == SLJIT_JUMP) { if (short_jump) @@ -818,7 +792,6 @@ static void reduce_code_size(struct sljit_compiler *compiler) if (next_min_addr != next_jump_addr) continue; - jump->addr -= size_reduce; if (!(jump->flags & JUMP_MOV_ADDR)) { #if (defined SLJIT_DEBUG && SLJIT_DEBUG) size_reduce_max = size_reduce + (((jump->flags >> TYPE_SHIFT) < SLJIT_JUMP) ? CJUMP_MAX_SIZE : JUMP_MAX_SIZE); @@ -832,11 +805,7 @@ static void reduce_code_size(struct sljit_compiler *compiler) #endif /* SLJIT_CONFIG_X86_64 */ } else { /* Unit size: instruction. */ - diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr; - if (jump->u.label->size > jump->addr) { - SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr); - diff -= (sljit_sw)size_reduce; - } + diff = (sljit_sw)jump->u.label->size - (sljit_sw)(jump->addr - size_reduce); type = jump->flags >> TYPE_SHIFT; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) @@ -876,7 +845,7 @@ static void reduce_code_size(struct sljit_compiler *compiler) #endif /* SLJIT_DEBUG */ if (!(jump->flags & JUMP_ADDR)) { - diff = (sljit_sw)jump->u.label->size - (sljit_sw)(jump->addr - 3); + diff = (sljit_sw)jump->u.label->size - (sljit_sw)(jump->addr - size_reduce - 3); if (diff <= HALFWORD_MAX && diff >= HALFWORD_MIN) size_reduce += 3; @@ -1048,7 +1017,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) case SLJIT_HAS_COPY_F32: case SLJIT_HAS_COPY_F64: case SLJIT_HAS_ATOMIC: - case SLJIT_HAS_MEMORY_BARRIER: return 1; #if !(defined SLJIT_IS_FPU_AVAILABLE) || SLJIT_IS_FPU_AVAILABLE @@ -1508,14 +1476,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0); #endif break; - case SLJIT_MEMORY_BARRIER: - inst = (sljit_u8*)ensure_buf(compiler, 1 + 3); - FAIL_IF(!inst); - INC_SIZE(3); - inst[0] = GROUP_0F; - inst[1] = 0xae; - inst[2] = 0xf0; - return SLJIT_SUCCESS; case SLJIT_ENDBR: return emit_endbranch(compiler); case SLJIT_SKIP_FRAMES_BEFORE_RETURN: @@ -3506,7 +3466,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co sljit_u8 cond_set; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) sljit_s32 reg; - sljit_uw size; #endif /* !SLJIT_CONFIG_X86_64 */ /* ADJUST_LOCAL_OFFSET and CHECK_EXTRA_REGS might overwrite these values. */ sljit_s32 dst_save = dst; @@ -3523,52 +3482,35 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst)) { - size = 3 + 2; - if (reg_map[TMP_REG1] >= 4) - size += 1 + 1; - else if (reg_map[dst] >= 4) - size++; - - inst = (sljit_u8*)ensure_buf(compiler, 1 + size); + inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 + 3); FAIL_IF(!inst); - INC_SIZE(size); + INC_SIZE(4 + 3); /* Set low register to conditional flag. */ - if (reg_map[TMP_REG1] >= 4) - *inst++ = (reg_map[TMP_REG1] <= 7) ? REX : REX_B; - - inst[0] = GROUP_0F; - inst[1] = cond_set; - inst[2] = MOD_REG | reg_lmap[TMP_REG1]; - inst += 3; - - if (reg_map[TMP_REG1] >= 4 || reg_map[dst] >= 4) - *inst++ = U8(REX | (reg_map[TMP_REG1] <= 7 ? 0 : REX_R) | (reg_map[dst] <= 7 ? 0 : REX_B)); - - inst[0] = OR_rm8_r8; - inst[1] = U8(MOD_REG | (reg_lmap[TMP_REG1] << 3) | reg_lmap[dst]); + inst[0] = (reg_map[TMP_REG1] <= 7) ? REX : REX_B; + inst[1] = GROUP_0F; + inst[2] = cond_set; + inst[3] = MOD_REG | reg_lmap[TMP_REG1]; + inst[4] = U8(REX | (reg_map[TMP_REG1] <= 7 ? 0 : REX_R) | (reg_map[dst] <= 7 ? 0 : REX_B)); + inst[5] = OR_rm8_r8; + inst[6] = U8(MOD_REG | (reg_lmap[TMP_REG1] << 3) | reg_lmap[dst]); return SLJIT_SUCCESS; } reg = (GET_OPCODE(op) < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG1; - size = 3 + (reg_map[reg] >= 4) + 4; - inst = (sljit_u8*)ensure_buf(compiler, 1 + size); + inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 + 4); FAIL_IF(!inst); - INC_SIZE(size); + INC_SIZE(4 + 4); /* Set low register to conditional flag. */ - - if (reg_map[reg] >= 4) - *inst++ = (reg_map[reg] <= 7) ? REX : REX_B; - - inst[0] = GROUP_0F; - inst[1] = cond_set; - inst[2] = MOD_REG | reg_lmap[reg]; - - inst[3] = REX_W | (reg_map[reg] <= 7 ? 0 : (REX_B | REX_R)); + inst[0] = (reg_map[reg] <= 7) ? REX : REX_B; + inst[1] = GROUP_0F; + inst[2] = cond_set; + inst[3] = MOD_REG | reg_lmap[reg]; + inst[4] = REX_W | (reg_map[reg] <= 7 ? 0 : (REX_B | REX_R)); /* The movzx instruction does not affect flags. */ - inst[4] = GROUP_0F; - inst[5] = MOVZX_r_rm8; - inst[6] = U8(MOD_REG | (reg_lmap[reg] << 3) | reg_lmap[reg]); + inst[5] = GROUP_0F; + inst[6] = MOVZX_r_rm8; + inst[7] = U8(MOD_REG | (reg_lmap[reg] << 3) | reg_lmap[reg]); if (reg != TMP_REG1) return SLJIT_SUCCESS; @@ -3675,7 +3617,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *com } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 srcdst, sljit_sw srcdstw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -3684,7 +3626,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *co sljit_uw op; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_mov(compiler, type, vreg, srcdst, srcdstw)); + CHECK(check_sljit_emit_simd_mov(compiler, type, freg, srcdst, srcdstw)); ADJUST_LOCAL_OFFSET(srcdst, srcdstw); @@ -3728,13 +3670,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *co return SLJIT_SUCCESS; if ((op & VEX_256) || ((cpu_feature_list & CPU_FEATURE_AVX) && (compiler->options & SLJIT_ENTER_USE_VEX))) - return emit_vex_instruction(compiler, op, vreg, 0, srcdst, srcdstw); + return emit_vex_instruction(compiler, op, freg, 0, srcdst, srcdstw); - return emit_groupf(compiler, op, vreg, srcdst, srcdstw); + return emit_groupf(compiler, op, freg, srcdst, srcdstw); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_sw srcw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -3745,7 +3687,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil sljit_uw op; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_replicate(compiler, type, vreg, src, srcw)); + CHECK(check_sljit_emit_simd_replicate(compiler, type, freg, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); @@ -3811,48 +3753,48 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil if (elem_size >= 3) compiler->mode32 = 0; #endif /* SLJIT_CONFIG_X86_64 */ - FAIL_IF(emit_vex_instruction(compiler, MOVD_x_rm | VEX_AUTO_W | EX86_PREF_66 | EX86_SSE2_OP1, vreg, 0, src, srcw)); + FAIL_IF(emit_vex_instruction(compiler, MOVD_x_rm | VEX_AUTO_W | EX86_PREF_66 | EX86_SSE2_OP1, freg, 0, src, srcw)); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 1; #endif /* SLJIT_CONFIG_X86_64 */ - src = vreg; + src = freg; srcw = 0; } if (reg_size == 5) op |= VEX_256; - return emit_vex_instruction(compiler, op, vreg, 0, src, srcw); + return emit_vex_instruction(compiler, op, freg, 0, src, srcw); } } if (type & SLJIT_SIMD_FLOAT) { if (src == SLJIT_IMM) { if (use_vex) - return emit_vex_instruction(compiler, XORPD_x_xm | (reg_size == 5 ? VEX_256 : 0) | (elem_size == 3 ? EX86_PREF_66 : 0) | EX86_SSE2 | VEX_SSE2_OPV, vreg, vreg, vreg, 0); + return emit_vex_instruction(compiler, XORPD_x_xm | (reg_size == 5 ? VEX_256 : 0) | (elem_size == 3 ? EX86_PREF_66 : 0) | EX86_SSE2 | VEX_SSE2_OPV, freg, freg, freg, 0); - return emit_groupf(compiler, XORPD_x_xm | (elem_size == 3 ? EX86_PREF_66 : 0) | EX86_SSE2, vreg, vreg, 0); + return emit_groupf(compiler, XORPD_x_xm | (elem_size == 3 ? EX86_PREF_66 : 0) | EX86_SSE2, freg, freg, 0); } SLJIT_ASSERT(reg_size == 4); if (use_vex) { if (elem_size == 3) - return emit_vex_instruction(compiler, MOVDDUP_x_xm | EX86_PREF_F2 | EX86_SSE2, vreg, 0, src, srcw); + return emit_vex_instruction(compiler, MOVDDUP_x_xm | EX86_PREF_F2 | EX86_SSE2, freg, 0, src, srcw); SLJIT_ASSERT(!(src & SLJIT_MEM)); - FAIL_IF(emit_vex_instruction(compiler, SHUFPS_x_xm | EX86_SSE2 | VEX_SSE2_OPV, vreg, src, src, 0)); + FAIL_IF(emit_vex_instruction(compiler, SHUFPS_x_xm | EX86_SSE2 | VEX_SSE2_OPV, freg, src, src, 0)); return emit_byte(compiler, 0); } - if (elem_size == 2 && vreg != src) { - FAIL_IF(emit_sse2_load(compiler, 1, vreg, src, srcw)); - src = vreg; + if (elem_size == 2 && freg != src) { + FAIL_IF(emit_sse2_load(compiler, 1, freg, src, srcw)); + src = freg; srcw = 0; } op = (elem_size == 2 ? SHUFPS_x_xm : MOVDDUP_x_xm) | (elem_size == 2 ? 0 : EX86_PREF_F2) | EX86_SSE2; - FAIL_IF(emit_groupf(compiler, op, vreg, src, srcw)); + FAIL_IF(emit_groupf(compiler, op, freg, src, srcw)); if (elem_size == 2) return emit_byte(compiler, 0); @@ -3878,9 +3820,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil if (srcw == 0 || srcw == -1) { if (use_vex) - return emit_vex_instruction(compiler, (srcw == 0 ? PXOR_x_xm : PCMPEQD_x_xm) | (reg_size == 5 ? VEX_256 : 0) | EX86_PREF_66 | EX86_SSE2 | VEX_SSE2_OPV, vreg, vreg, vreg, 0); + return emit_vex_instruction(compiler, (srcw == 0 ? PXOR_x_xm : PCMPEQD_x_xm) | (reg_size == 5 ? VEX_256 : 0) | EX86_PREF_66 | EX86_SSE2 | VEX_SSE2_OPV, freg, freg, freg, 0); - return emit_groupf(compiler, (srcw == 0 ? PXOR_x_xm : PCMPEQD_x_xm) | EX86_PREF_66 | EX86_SSE2, vreg, vreg, 0); + return emit_groupf(compiler, (srcw == 0 ? PXOR_x_xm : PCMPEQD_x_xm) | EX86_PREF_66 | EX86_SSE2, freg, freg, 0); } #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) @@ -3922,11 +3864,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil if (use_vex) { if (opcode != MOVD_x_rm) { op = (opcode == 0x3a) ? (PINSRB_x_rm_i8 | VEX_OP_0F3A) : opcode; - FAIL_IF(emit_vex_instruction(compiler, op | EX86_PREF_66 | EX86_SSE2_OP1 | VEX_SSE2_OPV, vreg, vreg, src, srcw)); + FAIL_IF(emit_vex_instruction(compiler, op | EX86_PREF_66 | EX86_SSE2_OP1 | VEX_SSE2_OPV, freg, freg, src, srcw)); } else - FAIL_IF(emit_vex_instruction(compiler, MOVD_x_rm | VEX_AUTO_W | EX86_PREF_66 | EX86_SSE2_OP1, vreg, 0, src, srcw)); + FAIL_IF(emit_vex_instruction(compiler, MOVD_x_rm | VEX_AUTO_W | EX86_PREF_66 | EX86_SSE2_OP1, freg, 0, src, srcw)); } else { - inst = emit_x86_instruction(compiler, op | EX86_PREF_66 | EX86_SSE2_OP1, vreg, 0, src, srcw); + inst = emit_x86_instruction(compiler, op | EX86_PREF_66 | EX86_SSE2_OP1, freg, 0, src, srcw); FAIL_IF(!inst); inst[0] = GROUP_0F; inst[1] = opcode; @@ -3937,13 +3879,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil } } - if ((cpu_feature_list & CPU_FEATURE_AVX2) && use_vex && elem_size >= 2) { + if (use_vex && elem_size >= 2) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) op = VPBROADCASTD_x_xm; #else /* !SLJIT_CONFIG_X86_32 */ op = (elem_size == 3) ? VPBROADCASTQ_x_xm : VPBROADCASTD_x_xm; #endif /* SLJIT_CONFIG_X86_32 */ - return emit_vex_instruction(compiler, op | ((reg_size == 5) ? VEX_256 : 0) | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, vreg, 0, vreg, 0); + return emit_vex_instruction(compiler, op | ((reg_size == 5) ? VEX_256 : 0) | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, 0, freg, 0); } SLJIT_ASSERT(reg_size == 4); @@ -3955,37 +3897,37 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil case 0: if (use_vex) { FAIL_IF(emit_vex_instruction(compiler, PXOR_x_xm | EX86_PREF_66 | EX86_SSE2 | VEX_SSE2_OPV, TMP_FREG, TMP_FREG, TMP_FREG, 0)); - return emit_vex_instruction(compiler, PSHUFB_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2 | VEX_SSE2_OPV, vreg, vreg, TMP_FREG, 0); + return emit_vex_instruction(compiler, PSHUFB_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2 | VEX_SSE2_OPV, freg, freg, TMP_FREG, 0); } FAIL_IF(emit_groupf(compiler, PXOR_x_xm | EX86_PREF_66 | EX86_SSE2, TMP_FREG, TMP_FREG, 0)); - return emit_groupf_ext(compiler, PSHUFB_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, vreg, TMP_FREG, 0); + return emit_groupf_ext(compiler, PSHUFB_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, TMP_FREG, 0); case 1: if (use_vex) - FAIL_IF(emit_vex_instruction(compiler, PSHUFLW_x_xm | EX86_PREF_F2 | EX86_SSE2, vreg, 0, vreg, 0)); + FAIL_IF(emit_vex_instruction(compiler, PSHUFLW_x_xm | EX86_PREF_F2 | EX86_SSE2, freg, 0, freg, 0)); else - FAIL_IF(emit_groupf(compiler, PSHUFLW_x_xm | EX86_PREF_F2 | EX86_SSE2, vreg, vreg, 0)); + FAIL_IF(emit_groupf(compiler, PSHUFLW_x_xm | EX86_PREF_F2 | EX86_SSE2, freg, freg, 0)); FAIL_IF(emit_byte(compiler, 0)); /* fallthrough */ default: if (use_vex) - FAIL_IF(emit_vex_instruction(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, vreg, 0, vreg, 0)); + FAIL_IF(emit_vex_instruction(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, freg, 0, freg, 0)); else - FAIL_IF(emit_groupf(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, vreg, vreg, 0)); + FAIL_IF(emit_groupf(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, freg, freg, 0)); return emit_byte(compiler, 0); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) case 3: compiler->mode32 = 1; if (use_vex) - FAIL_IF(emit_vex_instruction(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, vreg, 0, vreg, 0)); + FAIL_IF(emit_vex_instruction(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, freg, 0, freg, 0)); else - FAIL_IF(emit_groupf(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, vreg, vreg, 0)); + FAIL_IF(emit_groupf(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, freg, freg, 0)); return emit_byte(compiler, 0x44); #endif /* SLJIT_CONFIG_X86_64 */ } } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, sljit_s32 lane_index, + sljit_s32 freg, sljit_s32 lane_index, sljit_s32 srcdst, sljit_sw srcdstw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -3994,7 +3936,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile sljit_u8 *inst; sljit_u8 opcode = 0; sljit_uw op; - sljit_s32 vreg_orig = vreg; + sljit_s32 freg_orig = freg; #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) sljit_s32 srcdst_is_ereg = 0; sljit_s32 srcdst_orig = 0; @@ -4002,7 +3944,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile #endif /* SLJIT_CONFIG_X86_32 */ CHECK_ERROR(); - CHECK(check_sljit_emit_simd_lane_mov(compiler, type, vreg, lane_index, srcdst, srcdstw)); + CHECK(check_sljit_emit_simd_lane_mov(compiler, type, freg, lane_index, srcdst, srcdstw)); ADJUST_LOCAL_OFFSET(srcdst, srcdstw); @@ -4062,29 +4004,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile if (elem_size == 2) { if (use_vex) - return emit_vex_instruction(compiler, MOVD_x_rm | VEX_AUTO_W | EX86_PREF_66 | EX86_SSE2_OP1, vreg, 0, srcdst, srcdstw); - return emit_groupf(compiler, MOVD_x_rm | EX86_PREF_66 | EX86_SSE2_OP1, vreg, srcdst, srcdstw); + return emit_vex_instruction(compiler, MOVD_x_rm | VEX_AUTO_W | EX86_PREF_66 | EX86_SSE2_OP1, freg, 0, srcdst, srcdstw); + return emit_groupf(compiler, MOVD_x_rm | EX86_PREF_66 | EX86_SSE2_OP1, freg, srcdst, srcdstw); } } else if (srcdst & SLJIT_MEM) { SLJIT_ASSERT(elem_size == 2 || elem_size == 3); if (use_vex) - return emit_vex_instruction(compiler, MOVSD_x_xm | (elem_size == 2 ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, vreg, 0, srcdst, srcdstw); - return emit_groupf(compiler, MOVSD_x_xm | (elem_size == 2 ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, vreg, srcdst, srcdstw); + return emit_vex_instruction(compiler, MOVSD_x_xm | (elem_size == 2 ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, freg, 0, srcdst, srcdstw); + return emit_groupf(compiler, MOVSD_x_xm | (elem_size == 2 ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, freg, srcdst, srcdstw); } else if (elem_size == 3) { if (use_vex) - return emit_vex_instruction(compiler, MOVQ_x_xm | EX86_PREF_F3 | EX86_SSE2, vreg, 0, srcdst, 0); - return emit_groupf(compiler, MOVQ_x_xm | EX86_PREF_F3 | EX86_SSE2, vreg, srcdst, 0); + return emit_vex_instruction(compiler, MOVQ_x_xm | EX86_PREF_F3 | EX86_SSE2, freg, 0, srcdst, 0); + return emit_groupf(compiler, MOVQ_x_xm | EX86_PREF_F3 | EX86_SSE2, freg, srcdst, 0); } else if (use_vex) { FAIL_IF(emit_vex_instruction(compiler, XORPD_x_xm | EX86_SSE2 | VEX_SSE2_OPV, TMP_FREG, TMP_FREG, TMP_FREG, 0)); - return emit_vex_instruction(compiler, MOVSD_x_xm | EX86_PREF_F3 | EX86_SSE2 | VEX_SSE2_OPV, vreg, TMP_FREG, srcdst, 0); + return emit_vex_instruction(compiler, MOVSD_x_xm | EX86_PREF_F3 | EX86_SSE2 | VEX_SSE2_OPV, freg, TMP_FREG, srcdst, 0); } } if (reg_size == 5 && lane_index >= (1 << (4 - elem_size))) { - vreg = TMP_FREG; + freg = TMP_FREG; lane_index -= (1 << (4 - elem_size)); - } else if ((type & SLJIT_SIMD_FLOAT) && vreg == srcdst) { + } else if ((type & SLJIT_SIMD_FLOAT) && freg == srcdst) { if (use_vex) FAIL_IF(emit_vex_instruction(compiler, MOVSD_x_xm | (elem_size == 2 ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2 | VEX_SSE2_OPV, TMP_FREG, TMP_FREG, srcdst, srcdstw)); else @@ -4097,14 +4039,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile | ((type & SLJIT_SIMD_FLOAT) ? XORPD_x_xm : PXOR_x_xm) | EX86_SSE2; if (use_vex) - FAIL_IF(emit_vex_instruction(compiler, op | (reg_size == 5 ? VEX_256 : 0) | VEX_SSE2_OPV, vreg, vreg, vreg, 0)); + FAIL_IF(emit_vex_instruction(compiler, op | (reg_size == 5 ? VEX_256 : 0) | VEX_SSE2_OPV, freg, freg, freg, 0)); else - FAIL_IF(emit_groupf(compiler, op, vreg, vreg, 0)); + FAIL_IF(emit_groupf(compiler, op, freg, freg, 0)); } else if (reg_size == 5 && lane_index >= (1 << (4 - elem_size))) { - FAIL_IF(emit_vex_instruction(compiler, ((type & SLJIT_SIMD_FLOAT) ? VEXTRACTF128_x_ym : VEXTRACTI128_x_ym) | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, vreg, 0, TMP_FREG, 0)); + FAIL_IF(emit_vex_instruction(compiler, ((type & SLJIT_SIMD_FLOAT) ? VEXTRACTF128_x_ym : VEXTRACTI128_x_ym) | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, freg, 0, TMP_FREG, 0)); FAIL_IF(emit_byte(compiler, 1)); - vreg = TMP_FREG; + freg = TMP_FREG; lane_index -= (1 << (4 - elem_size)); } @@ -4117,55 +4059,55 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile op = lane_index == 0 ? MOVLPD_x_m : MOVHPD_x_m; /* VEX prefix clears upper bits of the target register. */ - if (use_vex && ((type & SLJIT_SIMD_STORE) || reg_size == 4 || vreg == TMP_FREG)) + if (use_vex && ((type & SLJIT_SIMD_STORE) || reg_size == 4 || freg == TMP_FREG)) FAIL_IF(emit_vex_instruction(compiler, op | EX86_PREF_66 | EX86_SSE2 - | ((type & SLJIT_SIMD_STORE) ? 0 : VEX_SSE2_OPV), vreg, (type & SLJIT_SIMD_STORE) ? 0 : vreg, srcdst, srcdstw)); + | ((type & SLJIT_SIMD_STORE) ? 0 : VEX_SSE2_OPV), freg, (type & SLJIT_SIMD_STORE) ? 0 : freg, srcdst, srcdstw)); else - FAIL_IF(emit_groupf(compiler, op | EX86_PREF_66 | EX86_SSE2, vreg, srcdst, srcdstw)); + FAIL_IF(emit_groupf(compiler, op | EX86_PREF_66 | EX86_SSE2, freg, srcdst, srcdstw)); - /* In case of store, vreg is not TMP_FREG. */ + /* In case of store, freg is not TMP_FREG. */ } else if (type & SLJIT_SIMD_STORE) { if (lane_index == 1) { if (use_vex) - return emit_vex_instruction(compiler, MOVHLPS_x_x | EX86_SSE2 | VEX_SSE2_OPV, srcdst, srcdst, vreg, 0); - return emit_groupf(compiler, MOVHLPS_x_x | EX86_SSE2, srcdst, vreg, 0); + return emit_vex_instruction(compiler, MOVHLPS_x_x | EX86_SSE2 | VEX_SSE2_OPV, srcdst, srcdst, freg, 0); + return emit_groupf(compiler, MOVHLPS_x_x | EX86_SSE2, srcdst, freg, 0); } if (use_vex) - return emit_vex_instruction(compiler, MOVSD_x_xm | EX86_PREF_F2 | EX86_SSE2 | VEX_SSE2_OPV, srcdst, srcdst, vreg, 0); - return emit_sse2_load(compiler, 0, srcdst, vreg, 0); - } else if (use_vex && (reg_size == 4 || vreg == TMP_FREG)) { + return emit_vex_instruction(compiler, MOVSD_x_xm | EX86_PREF_F2 | EX86_SSE2 | VEX_SSE2_OPV, srcdst, srcdst, freg, 0); + return emit_sse2_load(compiler, 0, srcdst, freg, 0); + } else if (use_vex && (reg_size == 4 || freg == TMP_FREG)) { if (lane_index == 1) - FAIL_IF(emit_vex_instruction(compiler, MOVLHPS_x_x | EX86_SSE2 | VEX_SSE2_OPV, vreg, vreg, srcdst, 0)); + FAIL_IF(emit_vex_instruction(compiler, MOVLHPS_x_x | EX86_SSE2 | VEX_SSE2_OPV, freg, freg, srcdst, 0)); else - FAIL_IF(emit_vex_instruction(compiler, MOVSD_x_xm | EX86_PREF_F2 | EX86_SSE2 | VEX_SSE2_OPV, vreg, vreg, srcdst, 0)); + FAIL_IF(emit_vex_instruction(compiler, MOVSD_x_xm | EX86_PREF_F2 | EX86_SSE2 | VEX_SSE2_OPV, freg, freg, srcdst, 0)); } else { if (lane_index == 1) - FAIL_IF(emit_groupf(compiler, MOVLHPS_x_x | EX86_SSE2, vreg, srcdst, 0)); + FAIL_IF(emit_groupf(compiler, MOVLHPS_x_x | EX86_SSE2, freg, srcdst, 0)); else - FAIL_IF(emit_sse2_load(compiler, 0, vreg, srcdst, 0)); + FAIL_IF(emit_sse2_load(compiler, 0, freg, srcdst, 0)); } } else if (type & SLJIT_SIMD_STORE) { if (lane_index == 0) { if (use_vex) - return emit_vex_instruction(compiler, MOVSD_xm_x | EX86_PREF_F3 | EX86_SSE2 | ((srcdst & SLJIT_MEM) ? 0 : VEX_SSE2_OPV), - vreg, ((srcdst & SLJIT_MEM) ? 0 : srcdst), srcdst, srcdstw); - return emit_sse2_store(compiler, 1, srcdst, srcdstw, vreg); + return emit_vex_instruction(compiler, ((srcdst & SLJIT_MEM) ? MOVSD_xm_x : MOVSD_x_xm) | EX86_PREF_F3 | EX86_SSE2 + | ((srcdst & SLJIT_MEM) ? 0 : VEX_SSE2_OPV), freg, ((srcdst & SLJIT_MEM) ? 0 : freg), srcdst, srcdstw); + return emit_sse2_store(compiler, 1, srcdst, srcdstw, freg); } if (srcdst & SLJIT_MEM) { if (use_vex) - FAIL_IF(emit_vex_instruction(compiler, EXTRACTPS_x_xm | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, vreg, 0, srcdst, srcdstw)); + FAIL_IF(emit_vex_instruction(compiler, EXTRACTPS_x_xm | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, freg, 0, srcdst, srcdstw)); else - FAIL_IF(emit_groupf_ext(compiler, EXTRACTPS_x_xm | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, vreg, srcdst, srcdstw)); + FAIL_IF(emit_groupf_ext(compiler, EXTRACTPS_x_xm | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, freg, srcdst, srcdstw)); return emit_byte(compiler, U8(lane_index)); } if (use_vex) { - FAIL_IF(emit_vex_instruction(compiler, SHUFPS_x_xm | EX86_SSE2 | VEX_SSE2_OPV, srcdst, vreg, vreg, 0)); + FAIL_IF(emit_vex_instruction(compiler, SHUFPS_x_xm | EX86_SSE2 | VEX_SSE2_OPV, srcdst, freg, freg, 0)); return emit_byte(compiler, U8(lane_index)); } - if (srcdst == vreg) + if (srcdst == freg) op = SHUFPS_x_xm | EX86_SSE2; else { switch (lane_index) { @@ -4182,7 +4124,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile } } - FAIL_IF(emit_groupf(compiler, op, srcdst, vreg, 0)); + FAIL_IF(emit_groupf(compiler, op, srcdst, freg, 0)); op &= 0xff; if (op == SHUFPS_x_xm || op == PSHUFD_x_xm) @@ -4191,23 +4133,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile return SLJIT_SUCCESS; } else { if (lane_index != 0 || (srcdst & SLJIT_MEM)) { - FAIL_IF(emit_groupf_ext(compiler, INSERTPS_x_xm | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, vreg, srcdst, srcdstw)); + FAIL_IF(emit_groupf_ext(compiler, INSERTPS_x_xm | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, freg, srcdst, srcdstw)); FAIL_IF(emit_byte(compiler, U8(lane_index << 4))); } else - FAIL_IF(emit_sse2_store(compiler, 1, vreg, 0, srcdst)); + FAIL_IF(emit_sse2_store(compiler, 1, freg, 0, srcdst)); } - if (vreg != TMP_FREG || (type & SLJIT_SIMD_STORE)) + if (freg != TMP_FREG || (type & SLJIT_SIMD_STORE)) return SLJIT_SUCCESS; SLJIT_ASSERT(reg_size == 5); if (type & SLJIT_SIMD_LANE_ZERO) { - FAIL_IF(emit_vex_instruction(compiler, VPERMPD_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, vreg_orig, 0, TMP_FREG, 0)); + FAIL_IF(emit_vex_instruction(compiler, VPERMPD_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, freg_orig, 0, TMP_FREG, 0)); return emit_byte(compiler, 0x4e); } - FAIL_IF(emit_vex_instruction(compiler, VINSERTF128_y_y_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2 | VEX_SSE2_OPV, vreg_orig, vreg_orig, TMP_FREG, 0)); + FAIL_IF(emit_vex_instruction(compiler, VINSERTF128_y_y_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2 | VEX_SSE2_OPV, freg_orig, freg_orig, TMP_FREG, 0)); return emit_byte(compiler, 1); } @@ -4244,9 +4186,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile if (use_vex && (type & SLJIT_SIMD_STORE)) { op = opcode | ((op == 3) ? VEX_OP_0F3A : 0); - FAIL_IF(emit_vex_instruction(compiler, op | EX86_PREF_66 | VEX_AUTO_W | EX86_SSE2_OP1 | VEX_SSE2_OPV, vreg, 0, srcdst, srcdstw)); + FAIL_IF(emit_vex_instruction(compiler, op | EX86_PREF_66 | VEX_AUTO_W | EX86_SSE2_OP1 | VEX_SSE2_OPV, freg, 0, srcdst, srcdstw)); } else { - inst = emit_x86_instruction(compiler, op | EX86_PREF_66 | EX86_SSE2_OP1, vreg, 0, srcdst, srcdstw); + inst = emit_x86_instruction(compiler, op | EX86_PREF_66 | EX86_SSE2_OP1, freg, 0, srcdst, srcdstw); FAIL_IF(!inst); inst[0] = GROUP_0F; @@ -4260,15 +4202,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile FAIL_IF(emit_byte(compiler, U8(lane_index))); if (!(type & SLJIT_SIMD_LANE_SIGNED) || (srcdst & SLJIT_MEM)) { - if (vreg == TMP_FREG && !(type & SLJIT_SIMD_STORE)) { + if (freg == TMP_FREG && !(type & SLJIT_SIMD_STORE)) { SLJIT_ASSERT(reg_size == 5); if (type & SLJIT_SIMD_LANE_ZERO) { - FAIL_IF(emit_vex_instruction(compiler, VPERMQ_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, vreg_orig, 0, TMP_FREG, 0)); + FAIL_IF(emit_vex_instruction(compiler, VPERMQ_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, freg_orig, 0, TMP_FREG, 0)); return emit_byte(compiler, 0x4e); } - FAIL_IF(emit_vex_instruction(compiler, VINSERTI128_y_y_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2 | VEX_SSE2_OPV, vreg_orig, vreg_orig, TMP_FREG, 0)); + FAIL_IF(emit_vex_instruction(compiler, VINSERTI128_y_y_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2 | VEX_SSE2_OPV, freg_orig, freg_orig, TMP_FREG, 0)); return emit_byte(compiler, 1); } @@ -4320,7 +4262,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_s32 src_lane_index) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -4335,7 +4277,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c #endif /* SLJIT_CONFIG_X86_32 */ CHECK_ERROR(); - CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, vreg, src, src_lane_index)); + CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, freg, src, src_lane_index)); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 1; @@ -4359,9 +4301,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c if (reg_size == 5) { if (src_lane_index == 0) - return emit_vex_instruction(compiler, VBROADCASTSD_x_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, vreg, 0, src, 0); + return emit_vex_instruction(compiler, VBROADCASTSD_x_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, 0, src, 0); - FAIL_IF(emit_vex_instruction(compiler, VPERMPD_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, vreg, 0, src, 0)); + FAIL_IF(emit_vex_instruction(compiler, VPERMPD_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, freg, 0, src, 0)); byte = U8(byte | (byte << 2)); return emit_byte(compiler, U8(byte | (byte << 4))); @@ -4369,8 +4311,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c if (src_lane_index == 0) { if (use_vex) - return emit_vex_instruction(compiler, MOVDDUP_x_xm | EX86_PREF_F2 | EX86_SSE2, vreg, 0, src, 0); - return emit_groupf(compiler, MOVDDUP_x_xm | EX86_PREF_F2 | EX86_SSE2, vreg, src, 0); + return emit_vex_instruction(compiler, MOVDDUP_x_xm | EX86_PREF_F2 | EX86_SSE2, freg, 0, src, 0); + return emit_groupf(compiler, MOVDDUP_x_xm | EX86_PREF_F2 | EX86_SSE2, freg, src, 0); } /* Changes it to SHUFPD_x_xm. */ @@ -4384,9 +4326,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c SLJIT_ASSERT(elem_size == 2); if (src_lane_index == 0) - return emit_vex_instruction(compiler, VBROADCASTSS_x_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, vreg, 0, src, 0); + return emit_vex_instruction(compiler, VBROADCASTSS_x_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, 0, src, 0); - FAIL_IF(emit_vex_instruction(compiler, VPERMPD_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, vreg, 0, src, 0)); + FAIL_IF(emit_vex_instruction(compiler, VPERMPD_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, freg, 0, src, 0)); byte = 0x44; if (src_lane_index >= 4) { @@ -4395,15 +4337,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c } FAIL_IF(emit_byte(compiler, byte)); - FAIL_IF(emit_vex_instruction(compiler, SHUFPS_x_xm | VEX_256 | pref | EX86_SSE2 | VEX_SSE2_OPV, vreg, vreg, vreg, 0)); + FAIL_IF(emit_vex_instruction(compiler, SHUFPS_x_xm | VEX_256 | pref | EX86_SSE2 | VEX_SSE2_OPV, freg, freg, freg, 0)); byte = U8(src_lane_index); } else if (use_vex) { - FAIL_IF(emit_vex_instruction(compiler, SHUFPS_x_xm | pref | EX86_SSE2 | VEX_SSE2_OPV, vreg, src, src, 0)); + FAIL_IF(emit_vex_instruction(compiler, SHUFPS_x_xm | pref | EX86_SSE2 | VEX_SSE2_OPV, freg, src, src, 0)); } else { - if (vreg != src) - FAIL_IF(emit_groupf(compiler, MOVAPS_x_xm | pref | EX86_SSE2, vreg, src, 0)); + if (freg != src) + FAIL_IF(emit_groupf(compiler, MOVAPS_x_xm | pref | EX86_SSE2, freg, src, 0)); - FAIL_IF(emit_groupf(compiler, SHUFPS_x_xm | pref | EX86_SSE2, vreg, vreg, 0)); + FAIL_IF(emit_groupf(compiler, SHUFPS_x_xm | pref | EX86_SSE2, freg, freg, 0)); } if (elem_size == 2) { @@ -4420,13 +4362,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c if (elem_size == 0) { if (reg_size == 5 && src_lane_index >= 16) { - FAIL_IF(emit_vex_instruction(compiler, VPERMQ_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, vreg, 0, src, 0)); + FAIL_IF(emit_vex_instruction(compiler, VPERMQ_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, freg, 0, src, 0)); FAIL_IF(emit_byte(compiler, src_lane_index >= 24 ? 0xff : 0xaa)); src_lane_index &= 0x7; - src = vreg; + src = freg; } - if (src_lane_index != 0 || (vreg != src && (!(cpu_feature_list & CPU_FEATURE_AVX2) || !use_vex))) { + if (src_lane_index != 0 || (freg != src && (!(cpu_feature_list & CPU_FEATURE_AVX2) || !use_vex))) { pref = 0; if ((src_lane_index & 0x3) == 0) { @@ -4437,33 +4379,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c byte = U8(src_lane_index >> 1); } else { if (!use_vex) { - if (vreg != src) - FAIL_IF(emit_groupf(compiler, MOVDQA_x_xm | EX86_PREF_66 | EX86_SSE2, vreg, src, 0)); + if (freg != src) + FAIL_IF(emit_groupf(compiler, MOVDQA_x_xm | EX86_PREF_66 | EX86_SSE2, freg, src, 0)); - FAIL_IF(emit_groupf(compiler, PSRLDQ_x | EX86_PREF_66 | EX86_SSE2_OP2, opcode3, vreg, 0)); + FAIL_IF(emit_groupf(compiler, PSRLDQ_x | EX86_PREF_66 | EX86_SSE2_OP2, opcode3, freg, 0)); } else - FAIL_IF(emit_vex_instruction(compiler, PSRLDQ_x | EX86_PREF_66 | EX86_SSE2_OP2 | VEX_SSE2_OPV, opcode3, vreg, src, 0)); + FAIL_IF(emit_vex_instruction(compiler, PSRLDQ_x | EX86_PREF_66 | EX86_SSE2_OP2 | VEX_SSE2_OPV, opcode3, freg, src, 0)); FAIL_IF(emit_byte(compiler, U8(src_lane_index))); } if (pref != 0) { if (use_vex) - FAIL_IF(emit_vex_instruction(compiler, PSHUFLW_x_xm | pref | EX86_SSE2, vreg, 0, src, 0)); + FAIL_IF(emit_vex_instruction(compiler, PSHUFLW_x_xm | pref | EX86_SSE2, freg, 0, src, 0)); else - FAIL_IF(emit_groupf(compiler, PSHUFLW_x_xm | pref | EX86_SSE2, vreg, src, 0)); + FAIL_IF(emit_groupf(compiler, PSHUFLW_x_xm | pref | EX86_SSE2, freg, src, 0)); FAIL_IF(emit_byte(compiler, byte)); } - src = vreg; + src = freg; } if (use_vex && (cpu_feature_list & CPU_FEATURE_AVX2)) - return emit_vex_instruction(compiler, VPBROADCASTB_x_xm | (reg_size == 5 ? VEX_256 : 0) | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, vreg, 0, src, 0); + return emit_vex_instruction(compiler, VPBROADCASTB_x_xm | (reg_size == 5 ? VEX_256 : 0) | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, 0, src, 0); SLJIT_ASSERT(reg_size == 4); FAIL_IF(emit_groupf(compiler, PXOR_x_xm | EX86_PREF_66 | EX86_SSE2, TMP_FREG, TMP_FREG, 0)); - return emit_groupf_ext(compiler, PSHUFB_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, vreg, TMP_FREG, 0); + return emit_groupf_ext(compiler, PSHUFB_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, TMP_FREG, 0); } if ((cpu_feature_list & CPU_FEATURE_AVX2) && use_vex && src_lane_index == 0 && elem_size <= 3) { @@ -4482,7 +4424,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c if (reg_size == 5) pref |= VEX_256; - return emit_vex_instruction(compiler, pref, vreg, 0, src, 0); + return emit_vex_instruction(compiler, pref, freg, 0, src, 0); } if (reg_size == 5) { @@ -4501,22 +4443,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c pref = 0; break; default: - FAIL_IF(emit_vex_instruction(compiler, VPERMQ_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, vreg, 0, src, 0)); + FAIL_IF(emit_vex_instruction(compiler, VPERMQ_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, freg, 0, src, 0)); return emit_byte(compiler, U8(src_lane_index == 0 ? 0x44 : 0xee)); } if (pref != 0) { - FAIL_IF(emit_vex_instruction(compiler, pref, vreg, 0, src, 0)); + FAIL_IF(emit_vex_instruction(compiler, pref, freg, 0, src, 0)); byte = U8(byte | (byte << 2)); FAIL_IF(emit_byte(compiler, U8(byte | (byte << 4)))); if (src_lane_index == 0) - return emit_vex_instruction(compiler, VPBROADCASTQ_x_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, vreg, 0, vreg, 0); + return emit_vex_instruction(compiler, VPBROADCASTQ_x_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, 0, freg, 0); - src = vreg; + src = freg; } - FAIL_IF(emit_vex_instruction(compiler, VPERMQ_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, vreg, 0, src, 0)); + FAIL_IF(emit_vex_instruction(compiler, VPERMQ_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, freg, 0, src, 0)); byte = U8(src_lane_index); byte = U8(byte | (byte << 2)); return emit_byte(compiler, U8(byte | (byte << 4))); @@ -4529,16 +4471,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c pref = (src_lane_index & 2) == 0 ? EX86_PREF_F2 : EX86_PREF_F3; if (use_vex) - FAIL_IF(emit_vex_instruction(compiler, PSHUFLW_x_xm | pref | EX86_SSE2, vreg, 0, src, 0)); + FAIL_IF(emit_vex_instruction(compiler, PSHUFLW_x_xm | pref | EX86_SSE2, freg, 0, src, 0)); else - FAIL_IF(emit_groupf(compiler, PSHUFLW_x_xm | pref | EX86_SSE2, vreg, src, 0)); + FAIL_IF(emit_groupf(compiler, PSHUFLW_x_xm | pref | EX86_SSE2, freg, src, 0)); byte = U8(byte | (byte << 2)); FAIL_IF(emit_byte(compiler, U8(byte | (byte << 4)))); if ((cpu_feature_list & CPU_FEATURE_AVX2) && use_vex && pref == EX86_PREF_F2) - return emit_vex_instruction(compiler, VPBROADCASTD_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, vreg, 0, vreg, 0); + return emit_vex_instruction(compiler, VPBROADCASTD_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, 0, freg, 0); - src = vreg; + src = freg; /* fallthrough */ case 2: byte = U8(src_lane_index); @@ -4551,14 +4493,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c } if (use_vex) - FAIL_IF(emit_vex_instruction(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, vreg, 0, src, 0)); + FAIL_IF(emit_vex_instruction(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, freg, 0, src, 0)); else - FAIL_IF(emit_groupf(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, vreg, src, 0)); + FAIL_IF(emit_groupf(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, freg, src, 0)); return emit_byte(compiler, U8(byte | (byte << 4))); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 src, sljit_sw srcw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -4568,7 +4510,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler sljit_u8 opcode; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_extend(compiler, type, vreg, src, srcw)); + CHECK(check_sljit_emit_simd_extend(compiler, type, freg, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); @@ -4591,8 +4533,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler return SLJIT_SUCCESS; if (use_vex) - return emit_vex_instruction(compiler, CVTPS2PD_x_xm | ((reg_size == 5) ? VEX_256 : 0) | EX86_SSE2, vreg, 0, src, srcw); - return emit_groupf(compiler, CVTPS2PD_x_xm | EX86_SSE2, vreg, src, srcw); + return emit_vex_instruction(compiler, CVTPS2PD_x_xm | ((reg_size == 5) ? VEX_256 : 0) | EX86_SSE2, freg, 0, src, srcw); + return emit_groupf(compiler, CVTPS2PD_x_xm | EX86_SSE2, freg, src, srcw); } switch (elem_size) { @@ -4628,12 +4570,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler return SLJIT_SUCCESS; if (use_vex) - return emit_vex_instruction(compiler, opcode | ((reg_size == 5) ? VEX_256 : 0) | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, vreg, 0, src, srcw); - return emit_groupf_ext(compiler, opcode | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, vreg, src, srcw); + return emit_vex_instruction(compiler, opcode | ((reg_size == 5) ? VEX_256 : 0) | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, 0, src, srcw); + return emit_groupf_ext(compiler, opcode | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, src, srcw); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 vreg, + sljit_s32 freg, sljit_s32 dst, sljit_sw dstw) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); @@ -4644,7 +4586,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c sljit_u8 *inst; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_sign(compiler, type, vreg, dst, dstw)); + CHECK(check_sljit_emit_simd_sign(compiler, type, freg, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); @@ -4665,10 +4607,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c switch (elem_size) { case 1: if (use_vex) - FAIL_IF(emit_vex_instruction(compiler, PACKSSWB_x_xm | EX86_PREF_66 | EX86_SSE2 | VEX_SSE2_OPV, TMP_FREG, vreg, vreg, 0)); + FAIL_IF(emit_vex_instruction(compiler, PACKSSWB_x_xm | EX86_PREF_66 | EX86_SSE2 | VEX_SSE2_OPV, TMP_FREG, freg, freg, 0)); else - FAIL_IF(emit_groupf(compiler, PACKSSWB_x_xm | EX86_PREF_66 | EX86_SSE2, TMP_FREG, vreg, 0)); - vreg = TMP_FREG; + FAIL_IF(emit_groupf(compiler, PACKSSWB_x_xm | EX86_PREF_66 | EX86_SSE2, TMP_FREG, freg, 0)); + freg = TMP_FREG; break; case 2: op = EX86_SSE2_OP2; @@ -4679,9 +4621,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c op |= (elem_size < 2) ? PMOVMSKB_r_x : MOVMSKPS_r_x; if (use_vex) - FAIL_IF(emit_vex_instruction(compiler, op, dst_r, 0, vreg, 0)); + FAIL_IF(emit_vex_instruction(compiler, op, dst_r, 0, freg, 0)); else - FAIL_IF(emit_groupf(compiler, op, dst_r, vreg, 0)); + FAIL_IF(emit_groupf(compiler, op, dst_r, freg, 0)); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = type & SLJIT_32; @@ -4708,9 +4650,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; if (elem_size == 1) { - FAIL_IF(emit_vex_instruction(compiler, VEXTRACTI128_x_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, vreg, 0, TMP_FREG, 0)); + FAIL_IF(emit_vex_instruction(compiler, VEXTRACTI128_x_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, freg, 0, TMP_FREG, 0)); FAIL_IF(emit_byte(compiler, 1)); - FAIL_IF(emit_vex_instruction(compiler, PACKSSWB_x_xm | VEX_256 | EX86_PREF_66 | EX86_SSE2 | VEX_SSE2_OPV, TMP_FREG, vreg, TMP_FREG, 0)); + FAIL_IF(emit_vex_instruction(compiler, PACKSSWB_x_xm | VEX_256 | EX86_PREF_66 | EX86_SSE2 | VEX_SSE2_OPV, TMP_FREG, freg, TMP_FREG, 0)); FAIL_IF(emit_groupf(compiler, PMOVMSKB_r_x | EX86_PREF_66 | EX86_SSE2_OP2, dst_r, TMP_FREG, 0)); } else { op = MOVMSKPS_r_x | VEX_256 | EX86_SSE2_OP2; @@ -4720,7 +4662,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c else if (elem_size == 3) op |= EX86_PREF_66; - FAIL_IF(emit_vex_instruction(compiler, op, dst_r, 0, vreg, 0)); + FAIL_IF(emit_vex_instruction(compiler, op, dst_r, 0, freg, 0)); } if (dst_r == TMP_REG1) { @@ -4734,7 +4676,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c } static sljit_s32 emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 dst_vreg, sljit_s32 src_vreg) + sljit_s32 dst_freg, sljit_s32 src_freg) { sljit_uw op = ((type & SLJIT_SIMD_FLOAT) ? MOVAPS_x_xm : MOVDQA_x_xm) | EX86_SSE2; @@ -4743,21 +4685,18 @@ static sljit_s32 emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type, if (!(type & SLJIT_SIMD_FLOAT) || SLJIT_SIMD_GET_ELEM_SIZE(type) == 3) op |= EX86_PREF_66; - return emit_groupf(compiler, op, dst_vreg, src_vreg, 0); + return emit_groupf(compiler, op, dst_freg, src_freg, 0); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w) + sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg) { sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); - sljit_s32 use_vex = (cpu_feature_list & CPU_FEATURE_AVX) && (compiler->options & SLJIT_ENTER_USE_VEX); sljit_uw op = 0; - sljit_uw mov_op = 0; CHECK_ERROR(); - CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w)); - ADJUST_LOCAL_OFFSET(src2, src2w); + CHECK(check_sljit_emit_simd_op2(compiler, type, dst_freg, src1_freg, src2_freg)); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 1; @@ -4791,52 +4730,27 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *co if (!(type & SLJIT_SIMD_FLOAT) || elem_size == 3) op |= EX86_PREF_66; break; - - case SLJIT_SIMD_OP2_SHUFFLE: - if (reg_size != 4) - return SLJIT_ERR_UNSUPPORTED; - - op = PSHUFB_x_xm | EX86_PREF_66 | VEX_OP_0F38; - break; } if (type & SLJIT_SIMD_TEST) return SLJIT_SUCCESS; - if ((src2 & SLJIT_MEM) && SLJIT_SIMD_GET_ELEM2_SIZE(type) < reg_size) { - mov_op = ((type & SLJIT_SIMD_FLOAT) ? (MOVUPS_x_xm | (elem_size == 3 ? EX86_PREF_66 : 0)) : (MOVDQU_x_xm | EX86_PREF_F3)) | EX86_SSE2; - if (use_vex) - FAIL_IF(emit_vex_instruction(compiler, mov_op, TMP_FREG, 0, src2, src2w)); - else - FAIL_IF(emit_groupf(compiler, mov_op, TMP_FREG, src2, src2w)); - - src2 = TMP_FREG; - src2w = 0; - } - - if (reg_size == 5 || use_vex) { + if (reg_size == 5 || ((cpu_feature_list & CPU_FEATURE_AVX) && (compiler->options & SLJIT_ENTER_USE_VEX))) { if (reg_size == 5) op |= VEX_256; - return emit_vex_instruction(compiler, op | EX86_SSE2 | VEX_SSE2_OPV, dst_vreg, src1_vreg, src2, src2w); + return emit_vex_instruction(compiler, op | EX86_SSE2 | VEX_SSE2_OPV, dst_freg, src1_freg, src2_freg, 0); } - if (dst_vreg != src1_vreg) { - if (dst_vreg == src2) { - if (SLJIT_SIMD_GET_OPCODE(type) == SLJIT_SIMD_OP2_SHUFFLE) { - FAIL_IF(emit_simd_mov(compiler, type, TMP_FREG, src2)); - FAIL_IF(emit_simd_mov(compiler, type, dst_vreg, src1_vreg)); - src2 = TMP_FREG; - src2w = 0; - } else - src2 = src1_vreg; - } else - FAIL_IF(emit_simd_mov(compiler, type, dst_vreg, src1_vreg)); + if (dst_freg != src1_freg) { + if (dst_freg == src2_freg) + src2_freg = src1_freg; + else + FAIL_IF(emit_simd_mov(compiler, type, dst_freg, src1_freg)); } - if (op & (VEX_OP_0F38 | VEX_OP_0F3A)) - return emit_groupf_ext(compiler, op | EX86_SSE2, dst_vreg, src2, src2w); - return emit_groupf(compiler, op | EX86_SSE2, dst_vreg, src2, src2w); + FAIL_IF(emit_groupf(compiler, op | EX86_SSE2, dst_freg, src2_freg, 0)); + return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op, @@ -4846,14 +4760,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler CHECK_ERROR(); CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg)); - if ((op & SLJIT_ATOMIC_USE_LS) || GET_OPCODE(op) == SLJIT_MOV_S8 || GET_OPCODE(op) == SLJIT_MOV_S16 || GET_OPCODE(op) == SLJIT_MOV_S32) - return SLJIT_ERR_UNSUPPORTED; - - if (op & SLJIT_ATOMIC_TEST) - return SLJIT_SUCCESS; - SLJIT_SKIP_CHECKS(compiler); - return sljit_emit_op1(compiler, op & ~SLJIT_ATOMIC_USE_CAS, dst_reg, 0, SLJIT_MEM1(mem_reg), 0); + return sljit_emit_op1(compiler, op, dst_reg, 0, SLJIT_MEM1(mem_reg), 0); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op, @@ -4862,9 +4770,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler sljit_s32 temp_reg) { sljit_uw pref; + sljit_s32 free_reg = TMP_REG1; #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - sljit_s32 saved_reg = TMP_REG1; - sljit_s32 swap_tmp = 0; sljit_sw srcw = 0; sljit_sw tempw = 0; #endif /* SLJIT_CONFIG_X86_32 */ @@ -4877,43 +4784,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler SLJIT_ASSERT(FAST_IS_REG(src_reg) || src_reg == SLJIT_MEM1(SLJIT_SP)); SLJIT_ASSERT(FAST_IS_REG(temp_reg) || temp_reg == SLJIT_MEM1(SLJIT_SP)); - if ((op & SLJIT_ATOMIC_USE_LS) || GET_OPCODE(op) == SLJIT_MOV_S8 || GET_OPCODE(op) == SLJIT_MOV_S16 || GET_OPCODE(op) == SLJIT_MOV_S32) - return SLJIT_ERR_UNSUPPORTED; - - if (op & SLJIT_ATOMIC_TEST) - return SLJIT_SUCCESS; - op = GET_OPCODE(op); - #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - if (temp_reg == SLJIT_TMP_DEST_REG) { - FAIL_IF(emit_byte(compiler, XCHG_EAX_r | reg_map[TMP_REG1])); - - if (src_reg == SLJIT_R0) - src_reg = TMP_REG1; - if (mem_reg == SLJIT_R0) - mem_reg = TMP_REG1; - - temp_reg = SLJIT_R0; - swap_tmp = 1; - } - - /* Src is virtual register or its low byte is not accessible. */ if ((src_reg & SLJIT_MEM) || (op == SLJIT_MOV_U8 && reg_map[src_reg] >= 4)) { - SLJIT_ASSERT(src_reg != SLJIT_R1 && temp_reg != SLJIT_TMP_DEST_REG); - - if (swap_tmp) { - saved_reg = (mem_reg != SLJIT_R1) ? SLJIT_R1 : SLJIT_R2; - - EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, saved_reg, 0); - EMIT_MOV(compiler, saved_reg, 0, src_reg, srcw); - } else - EMIT_MOV(compiler, TMP_REG1, 0, src_reg, srcw); + /* Src is virtual register or its low byte is not accessible. */ + SLJIT_ASSERT(src_reg != SLJIT_R1); + free_reg = src_reg; - src_reg = saved_reg; + EMIT_MOV(compiler, TMP_REG1, 0, src_reg, srcw); + src_reg = TMP_REG1; if (mem_reg == src_reg) - mem_reg = saved_reg; + mem_reg = TMP_REG1; } #endif /* SLJIT_CONFIG_X86_32 */ @@ -4921,37 +4803,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 0; - EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_R0, 0); + EMIT_MOV(compiler, free_reg, 0, SLJIT_R0, 0); EMIT_MOV(compiler, SLJIT_R0, 0, temp_reg, 0); if (src_reg == SLJIT_R0) - src_reg = TMP_REG2; + src_reg = free_reg; if (mem_reg == SLJIT_R0) - mem_reg = TMP_REG2; + mem_reg = free_reg; #else /* !SLJIT_CONFIG_X86_64 */ - SLJIT_ASSERT(!swap_tmp); - - if (src_reg == TMP_REG1) { - if (mem_reg == SLJIT_R0) { - EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R1, 0); - EMIT_MOV(compiler, SLJIT_R1, 0, SLJIT_R0, 0); - EMIT_MOV(compiler, SLJIT_R0, 0, temp_reg, tempw); + if (src_reg == TMP_REG1 && mem_reg == SLJIT_R0 && (free_reg & SLJIT_MEM)) { + EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R1, 0); + EMIT_MOV(compiler, SLJIT_R1, 0, SLJIT_R0, 0); + EMIT_MOV(compiler, SLJIT_R0, 0, temp_reg, tempw); - mem_reg = SLJIT_R1; - saved_reg = SLJIT_R1; - } else { - EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R0, 0); - EMIT_MOV(compiler, SLJIT_R0, 0, temp_reg, tempw); - saved_reg = SLJIT_R0; - } + mem_reg = SLJIT_R1; + free_reg = SLJIT_R1; } else { - EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R0, 0); + EMIT_MOV(compiler, free_reg, 0, SLJIT_R0, 0); EMIT_MOV(compiler, SLJIT_R0, 0, temp_reg, tempw); if (src_reg == SLJIT_R0) - src_reg = TMP_REG1; + src_reg = free_reg; if (mem_reg == SLJIT_R0) - mem_reg = TMP_REG1; + mem_reg = free_reg; } #endif /* SLJIT_CONFIG_X86_64 */ } @@ -4973,25 +4847,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler FAIL_IF(emit_groupf(compiler, (op == SLJIT_MOV_U8 ? CMPXCHG_rm8_r : CMPXCHG_rm_r) | pref, src_reg, SLJIT_MEM1(mem_reg), 0)); -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - if (swap_tmp) { - SLJIT_ASSERT(temp_reg == SLJIT_R0); - FAIL_IF(emit_byte(compiler, XCHG_EAX_r | reg_map[TMP_REG1])); - - if (saved_reg != TMP_REG1) - return emit_mov(compiler, saved_reg, 0, SLJIT_MEM1(SLJIT_SP), 0); - return SLJIT_SUCCESS; - } -#endif /* SLJIT_CONFIG_X86_32 */ - if (temp_reg != SLJIT_R0) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 0; - return emit_mov(compiler, SLJIT_R0, 0, TMP_REG2, 0); + return emit_mov(compiler, SLJIT_R0, 0, TMP_REG1, 0); #else /* !SLJIT_CONFIG_X86_64 */ - EMIT_MOV(compiler, SLJIT_R0, 0, (saved_reg == SLJIT_R0) ? SLJIT_MEM1(SLJIT_SP) : saved_reg, 0); - if (saved_reg == SLJIT_R1) - return emit_mov(compiler, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_SP), 0); + EMIT_MOV(compiler, SLJIT_R0, 0, free_reg, 0); + if (free_reg != TMP_REG1) + return emit_mov(compiler, free_reg, 0, (free_reg == SLJIT_R1) ? SLJIT_MEM1(SLJIT_SP) : TMP_REG1, 0); #endif /* SLJIT_CONFIG_X86_64 */ } return SLJIT_SUCCESS; diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index 8e0fb2cce5f9b..b59bd87f92385 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -1132,12 +1132,12 @@ static zend_always_inline bool is_known_valid_utf8( zend_string *subject_str, PCRE2_SIZE start_offset) { if (!ZSTR_IS_VALID_UTF8(subject_str)) { /* We don't know whether the string is valid UTF-8 or not. */ - return 0; + return false; } if (start_offset == ZSTR_LEN(subject_str)) { /* Degenerate case: Offset points to end of string. */ - return 1; + return true; } /* Check that the offset does not point to an UTF-8 continuation byte. */ @@ -1687,10 +1687,10 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su walk = ZSTR_VAL(replace_str); replace_end = walk + ZSTR_LEN(replace_str); walk_last = 0; - simple_string = 1; + simple_string = true; while (walk < replace_end) { if ('\\' == *walk || '$' == *walk) { - simple_string = 0; + simple_string = false; if (walk_last == '\\') { walk++; walk_last = 0; diff --git a/ext/pcre/tests/grep2.phpt b/ext/pcre/tests/grep2.phpt index 9721dfbd9eec1..a953b13c49d54 100644 --- a/ext/pcre/tests/grep2.phpt +++ b/ext/pcre/tests/grep2.phpt @@ -21,7 +21,7 @@ var_dump(preg_last_error() == PREG_RECURSION_LIMIT_ERROR); ?> --EXPECTF-- -Warning: preg_grep(): Compilation failed: quantifier does not follow a repeatable item at offset 0 in %sgrep2.php on line %d +Warning: preg_grep(): Compilation failed: quantifier does not follow a repeatable item at offset %r(0|1)%r in %sgrep2.php on line %d bool(false) array(3) { [5]=> diff --git a/ext/pcre/tests/pcre_extra.phpt b/ext/pcre/tests/pcre_extra.phpt index 730c7299390cb..660e0a1488a1d 100644 --- a/ext/pcre/tests/pcre_extra.phpt +++ b/ext/pcre/tests/pcre_extra.phpt @@ -8,8 +8,8 @@ var_dump(preg_match('/\y/X', '\y')); ?> --EXPECTF-- -Warning: preg_match(): Compilation failed: unrecognized character follows \ at offset 1 in %spcre_extra.php on line 3 +Warning: preg_match(): Compilation failed: unrecognized character follows \ at offset %r(1|2)%r in %spcre_extra.php on line 3 bool(false) -Warning: preg_match(): Compilation failed: unrecognized character follows \ at offset 1 in %spcre_extra.php on line 4 +Warning: preg_match(): Compilation failed: unrecognized character follows \ at offset %r(1|2)%r in %spcre_extra.php on line 4 bool(false) diff --git a/ext/pcre/tests/preg_replace_callback_array_error.phpt b/ext/pcre/tests/preg_replace_callback_array_error.phpt index fc531b3b02a10..02f50d048cd0e 100644 --- a/ext/pcre/tests/preg_replace_callback_array_error.phpt +++ b/ext/pcre/tests/preg_replace_callback_array_error.phpt @@ -21,18 +21,6 @@ var_dump( ) ); -var_dump( - preg_replace_callback_array( - [ - '/a/' => 'b', - null => function () { - return 'ok'; - }, - ], - 'a' - ) -); - // backslashes var_dump( @@ -92,9 +80,6 @@ var_dump( Warning: preg_replace_callback_array(): Empty regular expression in %spreg_replace_callback_array_error.php on line %d NULL -Warning: preg_replace_callback_array(): Empty regular expression in %spreg_replace_callback_array_error.php on line %d -NULL - Warning: preg_replace_callback_array(): Delimiter must not be alphanumeric, backslash, or NUL byte in %spreg_replace_callback_array_error.php on line %d NULL diff --git a/ext/pcre/tests/split.phpt b/ext/pcre/tests/split.phpt index df4b9af92f2f9..27f1c85b433ea 100644 --- a/ext/pcre/tests/split.phpt +++ b/ext/pcre/tests/split.phpt @@ -16,7 +16,7 @@ var_dump(preg_split('/\d*/', 'ab2c3u', -1, PREG_SPLIT_NO_EMPTY)); ?> --EXPECTF-- -Warning: preg_split(): Compilation failed: quantifier does not follow a repeatable item at offset 0 in %ssplit.php on line %d +Warning: preg_split(): Compilation failed: quantifier does not follow a repeatable item at offset %r(0|1)%r in %ssplit.php on line %d bool(false) array(3) { [0]=> diff --git a/ext/pdo/pdo_arginfo.h b/ext/pdo/pdo_arginfo.h index d2df2f0b0eb23..8f452cf4b032c 100644 --- a/ext/pdo/pdo_arginfo.h +++ b/ext/pdo/pdo_arginfo.h @@ -24,9 +24,9 @@ static zend_class_entry *register_class_PDOException(zend_class_entry *class_ent zval property_errorInfo_default_value; ZVAL_NULL(&property_errorInfo_default_value); - zend_string *property_errorInfo_name = zend_string_init("errorInfo", sizeof("errorInfo") - 1, 1); + zend_string *property_errorInfo_name = zend_string_init("errorInfo", sizeof("errorInfo") - 1, true); zend_declare_typed_property(class_entry, property_errorInfo_name, &property_errorInfo_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ARRAY|MAY_BE_NULL)); - zend_string_release(property_errorInfo_name); + zend_string_release_ex(property_errorInfo_name, true); return class_entry; } diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 9588f23d420c5..34f19e364faa7 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) { @@ -800,7 +805,7 @@ PDO_API bool pdo_get_bool_param(bool *bval, const zval *value) *bval = false; return true; case IS_LONG: - *bval = zval_is_true(value); + *bval = zend_is_true(value); return true; case IS_STRING: /* TODO Should string be allowed? */ default: @@ -1185,7 +1190,7 @@ PHP_METHOD(PDO, query) pdo_stmt_t *stmt; zend_string *statement; zend_long fetch_mode; - bool fetch_mode_is_null = 1; + bool fetch_mode_is_null = true; zval *args = NULL; uint32_t num_args = 0; pdo_dbh_object_t *dbh_obj = Z_PDO_OBJECT_P(ZEND_THIS); @@ -1313,6 +1318,10 @@ 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); + } + zend_free_internal_arg_info(&func->internal_function, false); efree(func); } /* }}} */ @@ -1325,10 +1334,40 @@ 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); + } + zend_free_internal_arg_info(&func->internal_function, true); 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) { @@ -1357,7 +1396,7 @@ bool pdo_hash_methods(pdo_dbh_object_t *dbh_obj, int kind) func.type = ZEND_INTERNAL_FUNCTION; func.handler = funcs->handler; func.function_name = zend_string_init(funcs->fname, strlen(funcs->fname), dbh->is_persistent); - func.scope = dbh_obj->std.ce; + func.scope = pdo_dbh_ce; func.prototype = NULL; ZEND_MAP_PTR(func.run_time_cache) = rt_cache_size ? pecalloc(rt_cache_size, 1, dbh->is_persistent) : NULL; func.T = ZEND_OBSERVER_ENABLED; @@ -1366,11 +1405,24 @@ 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; - func.arg_info = (zend_internal_arg_info*)funcs->arg_info + 1; + uint32_t num_arg_info = 1 + funcs->num_args; + if (func.fn_flags & ZEND_ACC_VARIADIC) { + num_arg_info++; + } + + zend_arg_info *arg_info = safe_pemalloc(num_arg_info, + sizeof(zend_arg_info), 0, dbh->is_persistent); + for (uint32_t i = 0; i < num_arg_info; i++) { + zend_convert_internal_arg_info(&arg_info[i], + &funcs->arg_info[i], i == 0, dbh->is_persistent); + } + + func.arg_info = arg_info + 1; func.num_args = funcs->num_args; if (info->required_num_args == (uint32_t)-1) { func.required_num_args = funcs->num_args; @@ -1394,8 +1446,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++; } @@ -1528,7 +1608,7 @@ static void pdo_dbh_free_storage(zend_object *std) dbh->methods->persistent_shutdown(dbh); } zend_object_std_dtor(std); - dbh_free(dbh, 0); + dbh_free(dbh, false); } zend_object *pdo_dbh_new(zend_class_entry *ce) @@ -1552,7 +1632,7 @@ ZEND_RSRC_DTOR_FUNC(php_pdo_pdbh_dtor) /* {{{ */ { if (res->ptr) { pdo_dbh_t *dbh = (pdo_dbh_t*)res->ptr; - dbh_free(dbh, 1); + dbh_free(dbh, true); res->ptr = NULL; } } diff --git a/ext/pdo/pdo_dbh_arginfo.h b/ext/pdo/pdo_dbh_arginfo.h index 71df4c519e1a7..cc622a52e2688 100644 --- a/ext/pdo/pdo_dbh_arginfo.h +++ b/ext/pdo/pdo_dbh_arginfo.h @@ -111,454 +111,454 @@ static zend_class_entry *register_class_PDO(void) zval const_PARAM_NULL_value; ZVAL_LONG(&const_PARAM_NULL_value, LONG_CONST(PDO_PARAM_NULL)); - zend_string *const_PARAM_NULL_name = zend_string_init_interned("PARAM_NULL", sizeof("PARAM_NULL") - 1, 1); + zend_string *const_PARAM_NULL_name = zend_string_init_interned("PARAM_NULL", sizeof("PARAM_NULL") - 1, true); zend_declare_typed_class_constant(class_entry, const_PARAM_NULL_name, &const_PARAM_NULL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PARAM_NULL_name); + zend_string_release_ex(const_PARAM_NULL_name, true); ZEND_ASSERT(LONG_CONST(PDO_PARAM_NULL) == 0); zval const_PARAM_BOOL_value; ZVAL_LONG(&const_PARAM_BOOL_value, LONG_CONST(PDO_PARAM_BOOL)); - zend_string *const_PARAM_BOOL_name = zend_string_init_interned("PARAM_BOOL", sizeof("PARAM_BOOL") - 1, 1); + zend_string *const_PARAM_BOOL_name = zend_string_init_interned("PARAM_BOOL", sizeof("PARAM_BOOL") - 1, true); zend_declare_typed_class_constant(class_entry, const_PARAM_BOOL_name, &const_PARAM_BOOL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PARAM_BOOL_name); + zend_string_release_ex(const_PARAM_BOOL_name, true); ZEND_ASSERT(LONG_CONST(PDO_PARAM_BOOL) == 5); zval const_PARAM_INT_value; ZVAL_LONG(&const_PARAM_INT_value, LONG_CONST(PDO_PARAM_INT)); - zend_string *const_PARAM_INT_name = zend_string_init_interned("PARAM_INT", sizeof("PARAM_INT") - 1, 1); + zend_string *const_PARAM_INT_name = zend_string_init_interned("PARAM_INT", sizeof("PARAM_INT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PARAM_INT_name, &const_PARAM_INT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PARAM_INT_name); + zend_string_release_ex(const_PARAM_INT_name, true); ZEND_ASSERT(LONG_CONST(PDO_PARAM_INT) == 1); zval const_PARAM_STR_value; ZVAL_LONG(&const_PARAM_STR_value, LONG_CONST(PDO_PARAM_STR)); - zend_string *const_PARAM_STR_name = zend_string_init_interned("PARAM_STR", sizeof("PARAM_STR") - 1, 1); + zend_string *const_PARAM_STR_name = zend_string_init_interned("PARAM_STR", sizeof("PARAM_STR") - 1, true); zend_declare_typed_class_constant(class_entry, const_PARAM_STR_name, &const_PARAM_STR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PARAM_STR_name); + zend_string_release_ex(const_PARAM_STR_name, true); ZEND_ASSERT(LONG_CONST(PDO_PARAM_STR) == 2); zval const_PARAM_LOB_value; ZVAL_LONG(&const_PARAM_LOB_value, LONG_CONST(PDO_PARAM_LOB)); - zend_string *const_PARAM_LOB_name = zend_string_init_interned("PARAM_LOB", sizeof("PARAM_LOB") - 1, 1); + zend_string *const_PARAM_LOB_name = zend_string_init_interned("PARAM_LOB", sizeof("PARAM_LOB") - 1, true); zend_declare_typed_class_constant(class_entry, const_PARAM_LOB_name, &const_PARAM_LOB_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PARAM_LOB_name); + zend_string_release_ex(const_PARAM_LOB_name, true); ZEND_ASSERT(LONG_CONST(PDO_PARAM_LOB) == 3); zval const_PARAM_STMT_value; ZVAL_LONG(&const_PARAM_STMT_value, LONG_CONST(PDO_PARAM_STMT)); - zend_string *const_PARAM_STMT_name = zend_string_init_interned("PARAM_STMT", sizeof("PARAM_STMT") - 1, 1); + zend_string *const_PARAM_STMT_name = zend_string_init_interned("PARAM_STMT", sizeof("PARAM_STMT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PARAM_STMT_name, &const_PARAM_STMT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PARAM_STMT_name); + zend_string_release_ex(const_PARAM_STMT_name, true); ZEND_ASSERT(LONG_CONST(PDO_PARAM_STMT) == 4); zval const_PARAM_INPUT_OUTPUT_value; ZVAL_LONG(&const_PARAM_INPUT_OUTPUT_value, LONG_CONST(PDO_PARAM_INPUT_OUTPUT)); - zend_string *const_PARAM_INPUT_OUTPUT_name = zend_string_init_interned("PARAM_INPUT_OUTPUT", sizeof("PARAM_INPUT_OUTPUT") - 1, 1); + zend_string *const_PARAM_INPUT_OUTPUT_name = zend_string_init_interned("PARAM_INPUT_OUTPUT", sizeof("PARAM_INPUT_OUTPUT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PARAM_INPUT_OUTPUT_name, &const_PARAM_INPUT_OUTPUT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PARAM_INPUT_OUTPUT_name); + zend_string_release_ex(const_PARAM_INPUT_OUTPUT_name, true); zval const_PARAM_STR_NATL_value; ZVAL_LONG(&const_PARAM_STR_NATL_value, LONG_CONST(PDO_PARAM_STR_NATL)); - zend_string *const_PARAM_STR_NATL_name = zend_string_init_interned("PARAM_STR_NATL", sizeof("PARAM_STR_NATL") - 1, 1); + zend_string *const_PARAM_STR_NATL_name = zend_string_init_interned("PARAM_STR_NATL", sizeof("PARAM_STR_NATL") - 1, true); zend_declare_typed_class_constant(class_entry, const_PARAM_STR_NATL_name, &const_PARAM_STR_NATL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PARAM_STR_NATL_name); + zend_string_release_ex(const_PARAM_STR_NATL_name, true); zval const_PARAM_STR_CHAR_value; ZVAL_LONG(&const_PARAM_STR_CHAR_value, LONG_CONST(PDO_PARAM_STR_CHAR)); - zend_string *const_PARAM_STR_CHAR_name = zend_string_init_interned("PARAM_STR_CHAR", sizeof("PARAM_STR_CHAR") - 1, 1); + zend_string *const_PARAM_STR_CHAR_name = zend_string_init_interned("PARAM_STR_CHAR", sizeof("PARAM_STR_CHAR") - 1, true); zend_declare_typed_class_constant(class_entry, const_PARAM_STR_CHAR_name, &const_PARAM_STR_CHAR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PARAM_STR_CHAR_name); + zend_string_release_ex(const_PARAM_STR_CHAR_name, true); zval const_PARAM_EVT_ALLOC_value; ZVAL_LONG(&const_PARAM_EVT_ALLOC_value, LONG_CONST(PDO_PARAM_EVT_ALLOC)); - zend_string *const_PARAM_EVT_ALLOC_name = zend_string_init_interned("PARAM_EVT_ALLOC", sizeof("PARAM_EVT_ALLOC") - 1, 1); + zend_string *const_PARAM_EVT_ALLOC_name = zend_string_init_interned("PARAM_EVT_ALLOC", sizeof("PARAM_EVT_ALLOC") - 1, true); zend_declare_typed_class_constant(class_entry, const_PARAM_EVT_ALLOC_name, &const_PARAM_EVT_ALLOC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PARAM_EVT_ALLOC_name); + zend_string_release_ex(const_PARAM_EVT_ALLOC_name, true); zval const_PARAM_EVT_FREE_value; ZVAL_LONG(&const_PARAM_EVT_FREE_value, LONG_CONST(PDO_PARAM_EVT_FREE)); - zend_string *const_PARAM_EVT_FREE_name = zend_string_init_interned("PARAM_EVT_FREE", sizeof("PARAM_EVT_FREE") - 1, 1); + zend_string *const_PARAM_EVT_FREE_name = zend_string_init_interned("PARAM_EVT_FREE", sizeof("PARAM_EVT_FREE") - 1, true); zend_declare_typed_class_constant(class_entry, const_PARAM_EVT_FREE_name, &const_PARAM_EVT_FREE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PARAM_EVT_FREE_name); + zend_string_release_ex(const_PARAM_EVT_FREE_name, true); zval const_PARAM_EVT_EXEC_PRE_value; ZVAL_LONG(&const_PARAM_EVT_EXEC_PRE_value, LONG_CONST(PDO_PARAM_EVT_EXEC_PRE)); - zend_string *const_PARAM_EVT_EXEC_PRE_name = zend_string_init_interned("PARAM_EVT_EXEC_PRE", sizeof("PARAM_EVT_EXEC_PRE") - 1, 1); + zend_string *const_PARAM_EVT_EXEC_PRE_name = zend_string_init_interned("PARAM_EVT_EXEC_PRE", sizeof("PARAM_EVT_EXEC_PRE") - 1, true); zend_declare_typed_class_constant(class_entry, const_PARAM_EVT_EXEC_PRE_name, &const_PARAM_EVT_EXEC_PRE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PARAM_EVT_EXEC_PRE_name); + zend_string_release_ex(const_PARAM_EVT_EXEC_PRE_name, true); zval const_PARAM_EVT_EXEC_POST_value; ZVAL_LONG(&const_PARAM_EVT_EXEC_POST_value, LONG_CONST(PDO_PARAM_EVT_EXEC_POST)); - zend_string *const_PARAM_EVT_EXEC_POST_name = zend_string_init_interned("PARAM_EVT_EXEC_POST", sizeof("PARAM_EVT_EXEC_POST") - 1, 1); + zend_string *const_PARAM_EVT_EXEC_POST_name = zend_string_init_interned("PARAM_EVT_EXEC_POST", sizeof("PARAM_EVT_EXEC_POST") - 1, true); zend_declare_typed_class_constant(class_entry, const_PARAM_EVT_EXEC_POST_name, &const_PARAM_EVT_EXEC_POST_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PARAM_EVT_EXEC_POST_name); + zend_string_release_ex(const_PARAM_EVT_EXEC_POST_name, true); zval const_PARAM_EVT_FETCH_PRE_value; ZVAL_LONG(&const_PARAM_EVT_FETCH_PRE_value, LONG_CONST(PDO_PARAM_EVT_FETCH_PRE)); - zend_string *const_PARAM_EVT_FETCH_PRE_name = zend_string_init_interned("PARAM_EVT_FETCH_PRE", sizeof("PARAM_EVT_FETCH_PRE") - 1, 1); + zend_string *const_PARAM_EVT_FETCH_PRE_name = zend_string_init_interned("PARAM_EVT_FETCH_PRE", sizeof("PARAM_EVT_FETCH_PRE") - 1, true); zend_declare_typed_class_constant(class_entry, const_PARAM_EVT_FETCH_PRE_name, &const_PARAM_EVT_FETCH_PRE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PARAM_EVT_FETCH_PRE_name); + zend_string_release_ex(const_PARAM_EVT_FETCH_PRE_name, true); zval const_PARAM_EVT_FETCH_POST_value; ZVAL_LONG(&const_PARAM_EVT_FETCH_POST_value, LONG_CONST(PDO_PARAM_EVT_FETCH_POST)); - zend_string *const_PARAM_EVT_FETCH_POST_name = zend_string_init_interned("PARAM_EVT_FETCH_POST", sizeof("PARAM_EVT_FETCH_POST") - 1, 1); + zend_string *const_PARAM_EVT_FETCH_POST_name = zend_string_init_interned("PARAM_EVT_FETCH_POST", sizeof("PARAM_EVT_FETCH_POST") - 1, true); zend_declare_typed_class_constant(class_entry, const_PARAM_EVT_FETCH_POST_name, &const_PARAM_EVT_FETCH_POST_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PARAM_EVT_FETCH_POST_name); + zend_string_release_ex(const_PARAM_EVT_FETCH_POST_name, true); zval const_PARAM_EVT_NORMALIZE_value; ZVAL_LONG(&const_PARAM_EVT_NORMALIZE_value, LONG_CONST(PDO_PARAM_EVT_NORMALIZE)); - zend_string *const_PARAM_EVT_NORMALIZE_name = zend_string_init_interned("PARAM_EVT_NORMALIZE", sizeof("PARAM_EVT_NORMALIZE") - 1, 1); + zend_string *const_PARAM_EVT_NORMALIZE_name = zend_string_init_interned("PARAM_EVT_NORMALIZE", sizeof("PARAM_EVT_NORMALIZE") - 1, true); zend_declare_typed_class_constant(class_entry, const_PARAM_EVT_NORMALIZE_name, &const_PARAM_EVT_NORMALIZE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PARAM_EVT_NORMALIZE_name); + zend_string_release_ex(const_PARAM_EVT_NORMALIZE_name, true); zval const_FETCH_DEFAULT_value; ZVAL_LONG(&const_FETCH_DEFAULT_value, LONG_CONST(PDO_FETCH_USE_DEFAULT)); - zend_string *const_FETCH_DEFAULT_name = zend_string_init_interned("FETCH_DEFAULT", sizeof("FETCH_DEFAULT") - 1, 1); + zend_string *const_FETCH_DEFAULT_name = zend_string_init_interned("FETCH_DEFAULT", sizeof("FETCH_DEFAULT") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_DEFAULT_name, &const_FETCH_DEFAULT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_DEFAULT_name); + zend_string_release_ex(const_FETCH_DEFAULT_name, true); zval const_FETCH_LAZY_value; ZVAL_LONG(&const_FETCH_LAZY_value, LONG_CONST(PDO_FETCH_LAZY)); - zend_string *const_FETCH_LAZY_name = zend_string_init_interned("FETCH_LAZY", sizeof("FETCH_LAZY") - 1, 1); + zend_string *const_FETCH_LAZY_name = zend_string_init_interned("FETCH_LAZY", sizeof("FETCH_LAZY") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_LAZY_name, &const_FETCH_LAZY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_LAZY_name); + zend_string_release_ex(const_FETCH_LAZY_name, true); zval const_FETCH_ASSOC_value; ZVAL_LONG(&const_FETCH_ASSOC_value, LONG_CONST(PDO_FETCH_ASSOC)); - zend_string *const_FETCH_ASSOC_name = zend_string_init_interned("FETCH_ASSOC", sizeof("FETCH_ASSOC") - 1, 1); + zend_string *const_FETCH_ASSOC_name = zend_string_init_interned("FETCH_ASSOC", sizeof("FETCH_ASSOC") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_ASSOC_name, &const_FETCH_ASSOC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_ASSOC_name); + zend_string_release_ex(const_FETCH_ASSOC_name, true); zval const_FETCH_NUM_value; ZVAL_LONG(&const_FETCH_NUM_value, LONG_CONST(PDO_FETCH_NUM)); - zend_string *const_FETCH_NUM_name = zend_string_init_interned("FETCH_NUM", sizeof("FETCH_NUM") - 1, 1); + zend_string *const_FETCH_NUM_name = zend_string_init_interned("FETCH_NUM", sizeof("FETCH_NUM") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_NUM_name, &const_FETCH_NUM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_NUM_name); + zend_string_release_ex(const_FETCH_NUM_name, true); zval const_FETCH_BOTH_value; ZVAL_LONG(&const_FETCH_BOTH_value, LONG_CONST(PDO_FETCH_BOTH)); - zend_string *const_FETCH_BOTH_name = zend_string_init_interned("FETCH_BOTH", sizeof("FETCH_BOTH") - 1, 1); + zend_string *const_FETCH_BOTH_name = zend_string_init_interned("FETCH_BOTH", sizeof("FETCH_BOTH") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_BOTH_name, &const_FETCH_BOTH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_BOTH_name); + zend_string_release_ex(const_FETCH_BOTH_name, true); zval const_FETCH_OBJ_value; ZVAL_LONG(&const_FETCH_OBJ_value, LONG_CONST(PDO_FETCH_OBJ)); - zend_string *const_FETCH_OBJ_name = zend_string_init_interned("FETCH_OBJ", sizeof("FETCH_OBJ") - 1, 1); + zend_string *const_FETCH_OBJ_name = zend_string_init_interned("FETCH_OBJ", sizeof("FETCH_OBJ") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_OBJ_name, &const_FETCH_OBJ_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_OBJ_name); + zend_string_release_ex(const_FETCH_OBJ_name, true); zval const_FETCH_BOUND_value; ZVAL_LONG(&const_FETCH_BOUND_value, LONG_CONST(PDO_FETCH_BOUND)); - zend_string *const_FETCH_BOUND_name = zend_string_init_interned("FETCH_BOUND", sizeof("FETCH_BOUND") - 1, 1); + zend_string *const_FETCH_BOUND_name = zend_string_init_interned("FETCH_BOUND", sizeof("FETCH_BOUND") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_BOUND_name, &const_FETCH_BOUND_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_BOUND_name); + zend_string_release_ex(const_FETCH_BOUND_name, true); zval const_FETCH_COLUMN_value; ZVAL_LONG(&const_FETCH_COLUMN_value, LONG_CONST(PDO_FETCH_COLUMN)); - zend_string *const_FETCH_COLUMN_name = zend_string_init_interned("FETCH_COLUMN", sizeof("FETCH_COLUMN") - 1, 1); + zend_string *const_FETCH_COLUMN_name = zend_string_init_interned("FETCH_COLUMN", sizeof("FETCH_COLUMN") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_COLUMN_name, &const_FETCH_COLUMN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_COLUMN_name); + zend_string_release_ex(const_FETCH_COLUMN_name, true); zval const_FETCH_CLASS_value; ZVAL_LONG(&const_FETCH_CLASS_value, LONG_CONST(PDO_FETCH_CLASS)); - zend_string *const_FETCH_CLASS_name = zend_string_init_interned("FETCH_CLASS", sizeof("FETCH_CLASS") - 1, 1); + zend_string *const_FETCH_CLASS_name = zend_string_init_interned("FETCH_CLASS", sizeof("FETCH_CLASS") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_CLASS_name, &const_FETCH_CLASS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_CLASS_name); + zend_string_release_ex(const_FETCH_CLASS_name, true); zval const_FETCH_INTO_value; ZVAL_LONG(&const_FETCH_INTO_value, LONG_CONST(PDO_FETCH_INTO)); - zend_string *const_FETCH_INTO_name = zend_string_init_interned("FETCH_INTO", sizeof("FETCH_INTO") - 1, 1); + zend_string *const_FETCH_INTO_name = zend_string_init_interned("FETCH_INTO", sizeof("FETCH_INTO") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_INTO_name, &const_FETCH_INTO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_INTO_name); + zend_string_release_ex(const_FETCH_INTO_name, true); zval const_FETCH_FUNC_value; ZVAL_LONG(&const_FETCH_FUNC_value, LONG_CONST(PDO_FETCH_FUNC)); - zend_string *const_FETCH_FUNC_name = zend_string_init_interned("FETCH_FUNC", sizeof("FETCH_FUNC") - 1, 1); + zend_string *const_FETCH_FUNC_name = zend_string_init_interned("FETCH_FUNC", sizeof("FETCH_FUNC") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_FUNC_name, &const_FETCH_FUNC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_FUNC_name); + zend_string_release_ex(const_FETCH_FUNC_name, true); zval const_FETCH_GROUP_value; ZVAL_LONG(&const_FETCH_GROUP_value, LONG_CONST(PDO_FETCH_GROUP)); - zend_string *const_FETCH_GROUP_name = zend_string_init_interned("FETCH_GROUP", sizeof("FETCH_GROUP") - 1, 1); + zend_string *const_FETCH_GROUP_name = zend_string_init_interned("FETCH_GROUP", sizeof("FETCH_GROUP") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_GROUP_name, &const_FETCH_GROUP_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_GROUP_name); + zend_string_release_ex(const_FETCH_GROUP_name, true); zval const_FETCH_UNIQUE_value; ZVAL_LONG(&const_FETCH_UNIQUE_value, LONG_CONST(PDO_FETCH_UNIQUE)); - zend_string *const_FETCH_UNIQUE_name = zend_string_init_interned("FETCH_UNIQUE", sizeof("FETCH_UNIQUE") - 1, 1); + zend_string *const_FETCH_UNIQUE_name = zend_string_init_interned("FETCH_UNIQUE", sizeof("FETCH_UNIQUE") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_UNIQUE_name, &const_FETCH_UNIQUE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_UNIQUE_name); + zend_string_release_ex(const_FETCH_UNIQUE_name, true); zval const_FETCH_KEY_PAIR_value; ZVAL_LONG(&const_FETCH_KEY_PAIR_value, LONG_CONST(PDO_FETCH_KEY_PAIR)); - zend_string *const_FETCH_KEY_PAIR_name = zend_string_init_interned("FETCH_KEY_PAIR", sizeof("FETCH_KEY_PAIR") - 1, 1); + zend_string *const_FETCH_KEY_PAIR_name = zend_string_init_interned("FETCH_KEY_PAIR", sizeof("FETCH_KEY_PAIR") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_KEY_PAIR_name, &const_FETCH_KEY_PAIR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_KEY_PAIR_name); + zend_string_release_ex(const_FETCH_KEY_PAIR_name, true); zval const_FETCH_CLASSTYPE_value; ZVAL_LONG(&const_FETCH_CLASSTYPE_value, LONG_CONST(PDO_FETCH_CLASSTYPE)); - zend_string *const_FETCH_CLASSTYPE_name = zend_string_init_interned("FETCH_CLASSTYPE", sizeof("FETCH_CLASSTYPE") - 1, 1); + zend_string *const_FETCH_CLASSTYPE_name = zend_string_init_interned("FETCH_CLASSTYPE", sizeof("FETCH_CLASSTYPE") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_CLASSTYPE_name, &const_FETCH_CLASSTYPE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_CLASSTYPE_name); + zend_string_release_ex(const_FETCH_CLASSTYPE_name, true); zval const_FETCH_SERIALIZE_value; ZVAL_LONG(&const_FETCH_SERIALIZE_value, LONG_CONST(PDO_FETCH_SERIALIZE)); - zend_string *const_FETCH_SERIALIZE_name = zend_string_init_interned("FETCH_SERIALIZE", sizeof("FETCH_SERIALIZE") - 1, 1); + zend_string *const_FETCH_SERIALIZE_name = zend_string_init_interned("FETCH_SERIALIZE", sizeof("FETCH_SERIALIZE") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_SERIALIZE_name, &const_FETCH_SERIALIZE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_SERIALIZE_name); + zend_string_release_ex(const_FETCH_SERIALIZE_name, true); zval const_FETCH_PROPS_LATE_value; ZVAL_LONG(&const_FETCH_PROPS_LATE_value, LONG_CONST(PDO_FETCH_PROPS_LATE)); - zend_string *const_FETCH_PROPS_LATE_name = zend_string_init_interned("FETCH_PROPS_LATE", sizeof("FETCH_PROPS_LATE") - 1, 1); + zend_string *const_FETCH_PROPS_LATE_name = zend_string_init_interned("FETCH_PROPS_LATE", sizeof("FETCH_PROPS_LATE") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_PROPS_LATE_name, &const_FETCH_PROPS_LATE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_PROPS_LATE_name); + zend_string_release_ex(const_FETCH_PROPS_LATE_name, true); zval const_FETCH_NAMED_value; ZVAL_LONG(&const_FETCH_NAMED_value, LONG_CONST(PDO_FETCH_NAMED)); - zend_string *const_FETCH_NAMED_name = zend_string_init_interned("FETCH_NAMED", sizeof("FETCH_NAMED") - 1, 1); + zend_string *const_FETCH_NAMED_name = zend_string_init_interned("FETCH_NAMED", sizeof("FETCH_NAMED") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_NAMED_name, &const_FETCH_NAMED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_NAMED_name); + zend_string_release_ex(const_FETCH_NAMED_name, true); zval const_ATTR_AUTOCOMMIT_value; ZVAL_LONG(&const_ATTR_AUTOCOMMIT_value, LONG_CONST(PDO_ATTR_AUTOCOMMIT)); - zend_string *const_ATTR_AUTOCOMMIT_name = zend_string_init_interned("ATTR_AUTOCOMMIT", sizeof("ATTR_AUTOCOMMIT") - 1, 1); + zend_string *const_ATTR_AUTOCOMMIT_name = zend_string_init_interned("ATTR_AUTOCOMMIT", sizeof("ATTR_AUTOCOMMIT") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_AUTOCOMMIT_name, &const_ATTR_AUTOCOMMIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_AUTOCOMMIT_name); + zend_string_release_ex(const_ATTR_AUTOCOMMIT_name, true); zval const_ATTR_PREFETCH_value; ZVAL_LONG(&const_ATTR_PREFETCH_value, LONG_CONST(PDO_ATTR_PREFETCH)); - zend_string *const_ATTR_PREFETCH_name = zend_string_init_interned("ATTR_PREFETCH", sizeof("ATTR_PREFETCH") - 1, 1); + zend_string *const_ATTR_PREFETCH_name = zend_string_init_interned("ATTR_PREFETCH", sizeof("ATTR_PREFETCH") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_PREFETCH_name, &const_ATTR_PREFETCH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_PREFETCH_name); + zend_string_release_ex(const_ATTR_PREFETCH_name, true); zval const_ATTR_TIMEOUT_value; ZVAL_LONG(&const_ATTR_TIMEOUT_value, LONG_CONST(PDO_ATTR_TIMEOUT)); - zend_string *const_ATTR_TIMEOUT_name = zend_string_init_interned("ATTR_TIMEOUT", sizeof("ATTR_TIMEOUT") - 1, 1); + zend_string *const_ATTR_TIMEOUT_name = zend_string_init_interned("ATTR_TIMEOUT", sizeof("ATTR_TIMEOUT") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_TIMEOUT_name, &const_ATTR_TIMEOUT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_TIMEOUT_name); + zend_string_release_ex(const_ATTR_TIMEOUT_name, true); zval const_ATTR_ERRMODE_value; ZVAL_LONG(&const_ATTR_ERRMODE_value, LONG_CONST(PDO_ATTR_ERRMODE)); - zend_string *const_ATTR_ERRMODE_name = zend_string_init_interned("ATTR_ERRMODE", sizeof("ATTR_ERRMODE") - 1, 1); + zend_string *const_ATTR_ERRMODE_name = zend_string_init_interned("ATTR_ERRMODE", sizeof("ATTR_ERRMODE") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_ERRMODE_name, &const_ATTR_ERRMODE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_ERRMODE_name); + zend_string_release_ex(const_ATTR_ERRMODE_name, true); zval const_ATTR_SERVER_VERSION_value; ZVAL_LONG(&const_ATTR_SERVER_VERSION_value, LONG_CONST(PDO_ATTR_SERVER_VERSION)); - zend_string *const_ATTR_SERVER_VERSION_name = zend_string_init_interned("ATTR_SERVER_VERSION", sizeof("ATTR_SERVER_VERSION") - 1, 1); + zend_string *const_ATTR_SERVER_VERSION_name = zend_string_init_interned("ATTR_SERVER_VERSION", sizeof("ATTR_SERVER_VERSION") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_SERVER_VERSION_name, &const_ATTR_SERVER_VERSION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_SERVER_VERSION_name); + zend_string_release_ex(const_ATTR_SERVER_VERSION_name, true); zval const_ATTR_CLIENT_VERSION_value; ZVAL_LONG(&const_ATTR_CLIENT_VERSION_value, LONG_CONST(PDO_ATTR_CLIENT_VERSION)); - zend_string *const_ATTR_CLIENT_VERSION_name = zend_string_init_interned("ATTR_CLIENT_VERSION", sizeof("ATTR_CLIENT_VERSION") - 1, 1); + zend_string *const_ATTR_CLIENT_VERSION_name = zend_string_init_interned("ATTR_CLIENT_VERSION", sizeof("ATTR_CLIENT_VERSION") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_CLIENT_VERSION_name, &const_ATTR_CLIENT_VERSION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_CLIENT_VERSION_name); + zend_string_release_ex(const_ATTR_CLIENT_VERSION_name, true); zval const_ATTR_SERVER_INFO_value; ZVAL_LONG(&const_ATTR_SERVER_INFO_value, LONG_CONST(PDO_ATTR_SERVER_INFO)); - zend_string *const_ATTR_SERVER_INFO_name = zend_string_init_interned("ATTR_SERVER_INFO", sizeof("ATTR_SERVER_INFO") - 1, 1); + zend_string *const_ATTR_SERVER_INFO_name = zend_string_init_interned("ATTR_SERVER_INFO", sizeof("ATTR_SERVER_INFO") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_SERVER_INFO_name, &const_ATTR_SERVER_INFO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_SERVER_INFO_name); + zend_string_release_ex(const_ATTR_SERVER_INFO_name, true); zval const_ATTR_CONNECTION_STATUS_value; ZVAL_LONG(&const_ATTR_CONNECTION_STATUS_value, LONG_CONST(PDO_ATTR_CONNECTION_STATUS)); - zend_string *const_ATTR_CONNECTION_STATUS_name = zend_string_init_interned("ATTR_CONNECTION_STATUS", sizeof("ATTR_CONNECTION_STATUS") - 1, 1); + zend_string *const_ATTR_CONNECTION_STATUS_name = zend_string_init_interned("ATTR_CONNECTION_STATUS", sizeof("ATTR_CONNECTION_STATUS") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_CONNECTION_STATUS_name, &const_ATTR_CONNECTION_STATUS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_CONNECTION_STATUS_name); + zend_string_release_ex(const_ATTR_CONNECTION_STATUS_name, true); zval const_ATTR_CASE_value; ZVAL_LONG(&const_ATTR_CASE_value, LONG_CONST(PDO_ATTR_CASE)); - zend_string *const_ATTR_CASE_name = zend_string_init_interned("ATTR_CASE", sizeof("ATTR_CASE") - 1, 1); + zend_string *const_ATTR_CASE_name = zend_string_init_interned("ATTR_CASE", sizeof("ATTR_CASE") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_CASE_name, &const_ATTR_CASE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_CASE_name); + zend_string_release_ex(const_ATTR_CASE_name, true); zval const_ATTR_CURSOR_NAME_value; ZVAL_LONG(&const_ATTR_CURSOR_NAME_value, LONG_CONST(PDO_ATTR_CURSOR_NAME)); - zend_string *const_ATTR_CURSOR_NAME_name = zend_string_init_interned("ATTR_CURSOR_NAME", sizeof("ATTR_CURSOR_NAME") - 1, 1); + zend_string *const_ATTR_CURSOR_NAME_name = zend_string_init_interned("ATTR_CURSOR_NAME", sizeof("ATTR_CURSOR_NAME") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_CURSOR_NAME_name, &const_ATTR_CURSOR_NAME_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_CURSOR_NAME_name); + zend_string_release_ex(const_ATTR_CURSOR_NAME_name, true); zval const_ATTR_CURSOR_value; ZVAL_LONG(&const_ATTR_CURSOR_value, LONG_CONST(PDO_ATTR_CURSOR)); - zend_string *const_ATTR_CURSOR_name = zend_string_init_interned("ATTR_CURSOR", sizeof("ATTR_CURSOR") - 1, 1); + zend_string *const_ATTR_CURSOR_name = zend_string_init_interned("ATTR_CURSOR", sizeof("ATTR_CURSOR") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_CURSOR_name, &const_ATTR_CURSOR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_CURSOR_name); + zend_string_release_ex(const_ATTR_CURSOR_name, true); zval const_ATTR_ORACLE_NULLS_value; ZVAL_LONG(&const_ATTR_ORACLE_NULLS_value, LONG_CONST(PDO_ATTR_ORACLE_NULLS)); - zend_string *const_ATTR_ORACLE_NULLS_name = zend_string_init_interned("ATTR_ORACLE_NULLS", sizeof("ATTR_ORACLE_NULLS") - 1, 1); + zend_string *const_ATTR_ORACLE_NULLS_name = zend_string_init_interned("ATTR_ORACLE_NULLS", sizeof("ATTR_ORACLE_NULLS") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_ORACLE_NULLS_name, &const_ATTR_ORACLE_NULLS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_ORACLE_NULLS_name); + zend_string_release_ex(const_ATTR_ORACLE_NULLS_name, true); zval const_ATTR_PERSISTENT_value; ZVAL_LONG(&const_ATTR_PERSISTENT_value, LONG_CONST(PDO_ATTR_PERSISTENT)); - zend_string *const_ATTR_PERSISTENT_name = zend_string_init_interned("ATTR_PERSISTENT", sizeof("ATTR_PERSISTENT") - 1, 1); + zend_string *const_ATTR_PERSISTENT_name = zend_string_init_interned("ATTR_PERSISTENT", sizeof("ATTR_PERSISTENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_PERSISTENT_name, &const_ATTR_PERSISTENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_PERSISTENT_name); + zend_string_release_ex(const_ATTR_PERSISTENT_name, true); zval const_ATTR_STATEMENT_CLASS_value; ZVAL_LONG(&const_ATTR_STATEMENT_CLASS_value, LONG_CONST(PDO_ATTR_STATEMENT_CLASS)); - zend_string *const_ATTR_STATEMENT_CLASS_name = zend_string_init_interned("ATTR_STATEMENT_CLASS", sizeof("ATTR_STATEMENT_CLASS") - 1, 1); + zend_string *const_ATTR_STATEMENT_CLASS_name = zend_string_init_interned("ATTR_STATEMENT_CLASS", sizeof("ATTR_STATEMENT_CLASS") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_STATEMENT_CLASS_name, &const_ATTR_STATEMENT_CLASS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_STATEMENT_CLASS_name); + zend_string_release_ex(const_ATTR_STATEMENT_CLASS_name, true); zval const_ATTR_FETCH_TABLE_NAMES_value; ZVAL_LONG(&const_ATTR_FETCH_TABLE_NAMES_value, LONG_CONST(PDO_ATTR_FETCH_TABLE_NAMES)); - zend_string *const_ATTR_FETCH_TABLE_NAMES_name = zend_string_init_interned("ATTR_FETCH_TABLE_NAMES", sizeof("ATTR_FETCH_TABLE_NAMES") - 1, 1); + zend_string *const_ATTR_FETCH_TABLE_NAMES_name = zend_string_init_interned("ATTR_FETCH_TABLE_NAMES", sizeof("ATTR_FETCH_TABLE_NAMES") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_FETCH_TABLE_NAMES_name, &const_ATTR_FETCH_TABLE_NAMES_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_FETCH_TABLE_NAMES_name); + zend_string_release_ex(const_ATTR_FETCH_TABLE_NAMES_name, true); zval const_ATTR_FETCH_CATALOG_NAMES_value; ZVAL_LONG(&const_ATTR_FETCH_CATALOG_NAMES_value, LONG_CONST(PDO_ATTR_FETCH_CATALOG_NAMES)); - zend_string *const_ATTR_FETCH_CATALOG_NAMES_name = zend_string_init_interned("ATTR_FETCH_CATALOG_NAMES", sizeof("ATTR_FETCH_CATALOG_NAMES") - 1, 1); + zend_string *const_ATTR_FETCH_CATALOG_NAMES_name = zend_string_init_interned("ATTR_FETCH_CATALOG_NAMES", sizeof("ATTR_FETCH_CATALOG_NAMES") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_FETCH_CATALOG_NAMES_name, &const_ATTR_FETCH_CATALOG_NAMES_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_FETCH_CATALOG_NAMES_name); + zend_string_release_ex(const_ATTR_FETCH_CATALOG_NAMES_name, true); zval const_ATTR_DRIVER_NAME_value; ZVAL_LONG(&const_ATTR_DRIVER_NAME_value, LONG_CONST(PDO_ATTR_DRIVER_NAME)); - zend_string *const_ATTR_DRIVER_NAME_name = zend_string_init_interned("ATTR_DRIVER_NAME", sizeof("ATTR_DRIVER_NAME") - 1, 1); + zend_string *const_ATTR_DRIVER_NAME_name = zend_string_init_interned("ATTR_DRIVER_NAME", sizeof("ATTR_DRIVER_NAME") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_DRIVER_NAME_name, &const_ATTR_DRIVER_NAME_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_DRIVER_NAME_name); + zend_string_release_ex(const_ATTR_DRIVER_NAME_name, true); zval const_ATTR_STRINGIFY_FETCHES_value; ZVAL_LONG(&const_ATTR_STRINGIFY_FETCHES_value, LONG_CONST(PDO_ATTR_STRINGIFY_FETCHES)); - zend_string *const_ATTR_STRINGIFY_FETCHES_name = zend_string_init_interned("ATTR_STRINGIFY_FETCHES", sizeof("ATTR_STRINGIFY_FETCHES") - 1, 1); + zend_string *const_ATTR_STRINGIFY_FETCHES_name = zend_string_init_interned("ATTR_STRINGIFY_FETCHES", sizeof("ATTR_STRINGIFY_FETCHES") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_STRINGIFY_FETCHES_name, &const_ATTR_STRINGIFY_FETCHES_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_STRINGIFY_FETCHES_name); + zend_string_release_ex(const_ATTR_STRINGIFY_FETCHES_name, true); zval const_ATTR_MAX_COLUMN_LEN_value; ZVAL_LONG(&const_ATTR_MAX_COLUMN_LEN_value, LONG_CONST(PDO_ATTR_MAX_COLUMN_LEN)); - zend_string *const_ATTR_MAX_COLUMN_LEN_name = zend_string_init_interned("ATTR_MAX_COLUMN_LEN", sizeof("ATTR_MAX_COLUMN_LEN") - 1, 1); + zend_string *const_ATTR_MAX_COLUMN_LEN_name = zend_string_init_interned("ATTR_MAX_COLUMN_LEN", sizeof("ATTR_MAX_COLUMN_LEN") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_MAX_COLUMN_LEN_name, &const_ATTR_MAX_COLUMN_LEN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_MAX_COLUMN_LEN_name); + zend_string_release_ex(const_ATTR_MAX_COLUMN_LEN_name, true); zval const_ATTR_EMULATE_PREPARES_value; ZVAL_LONG(&const_ATTR_EMULATE_PREPARES_value, LONG_CONST(PDO_ATTR_EMULATE_PREPARES)); - zend_string *const_ATTR_EMULATE_PREPARES_name = zend_string_init_interned("ATTR_EMULATE_PREPARES", sizeof("ATTR_EMULATE_PREPARES") - 1, 1); + zend_string *const_ATTR_EMULATE_PREPARES_name = zend_string_init_interned("ATTR_EMULATE_PREPARES", sizeof("ATTR_EMULATE_PREPARES") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_EMULATE_PREPARES_name, &const_ATTR_EMULATE_PREPARES_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_EMULATE_PREPARES_name); + zend_string_release_ex(const_ATTR_EMULATE_PREPARES_name, true); zval const_ATTR_DEFAULT_FETCH_MODE_value; ZVAL_LONG(&const_ATTR_DEFAULT_FETCH_MODE_value, LONG_CONST(PDO_ATTR_DEFAULT_FETCH_MODE)); - zend_string *const_ATTR_DEFAULT_FETCH_MODE_name = zend_string_init_interned("ATTR_DEFAULT_FETCH_MODE", sizeof("ATTR_DEFAULT_FETCH_MODE") - 1, 1); + zend_string *const_ATTR_DEFAULT_FETCH_MODE_name = zend_string_init_interned("ATTR_DEFAULT_FETCH_MODE", sizeof("ATTR_DEFAULT_FETCH_MODE") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_DEFAULT_FETCH_MODE_name, &const_ATTR_DEFAULT_FETCH_MODE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_DEFAULT_FETCH_MODE_name); + zend_string_release_ex(const_ATTR_DEFAULT_FETCH_MODE_name, true); zval const_ATTR_DEFAULT_STR_PARAM_value; ZVAL_LONG(&const_ATTR_DEFAULT_STR_PARAM_value, LONG_CONST(PDO_ATTR_DEFAULT_STR_PARAM)); - zend_string *const_ATTR_DEFAULT_STR_PARAM_name = zend_string_init_interned("ATTR_DEFAULT_STR_PARAM", sizeof("ATTR_DEFAULT_STR_PARAM") - 1, 1); + zend_string *const_ATTR_DEFAULT_STR_PARAM_name = zend_string_init_interned("ATTR_DEFAULT_STR_PARAM", sizeof("ATTR_DEFAULT_STR_PARAM") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_DEFAULT_STR_PARAM_name, &const_ATTR_DEFAULT_STR_PARAM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_DEFAULT_STR_PARAM_name); + zend_string_release_ex(const_ATTR_DEFAULT_STR_PARAM_name, true); zval const_ERRMODE_SILENT_value; ZVAL_LONG(&const_ERRMODE_SILENT_value, LONG_CONST(PDO_ERRMODE_SILENT)); - zend_string *const_ERRMODE_SILENT_name = zend_string_init_interned("ERRMODE_SILENT", sizeof("ERRMODE_SILENT") - 1, 1); + zend_string *const_ERRMODE_SILENT_name = zend_string_init_interned("ERRMODE_SILENT", sizeof("ERRMODE_SILENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_ERRMODE_SILENT_name, &const_ERRMODE_SILENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ERRMODE_SILENT_name); + zend_string_release_ex(const_ERRMODE_SILENT_name, true); zval const_ERRMODE_WARNING_value; ZVAL_LONG(&const_ERRMODE_WARNING_value, LONG_CONST(PDO_ERRMODE_WARNING)); - zend_string *const_ERRMODE_WARNING_name = zend_string_init_interned("ERRMODE_WARNING", sizeof("ERRMODE_WARNING") - 1, 1); + zend_string *const_ERRMODE_WARNING_name = zend_string_init_interned("ERRMODE_WARNING", sizeof("ERRMODE_WARNING") - 1, true); zend_declare_typed_class_constant(class_entry, const_ERRMODE_WARNING_name, &const_ERRMODE_WARNING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ERRMODE_WARNING_name); + zend_string_release_ex(const_ERRMODE_WARNING_name, true); zval const_ERRMODE_EXCEPTION_value; ZVAL_LONG(&const_ERRMODE_EXCEPTION_value, LONG_CONST(PDO_ERRMODE_EXCEPTION)); - zend_string *const_ERRMODE_EXCEPTION_name = zend_string_init_interned("ERRMODE_EXCEPTION", sizeof("ERRMODE_EXCEPTION") - 1, 1); + zend_string *const_ERRMODE_EXCEPTION_name = zend_string_init_interned("ERRMODE_EXCEPTION", sizeof("ERRMODE_EXCEPTION") - 1, true); zend_declare_typed_class_constant(class_entry, const_ERRMODE_EXCEPTION_name, &const_ERRMODE_EXCEPTION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ERRMODE_EXCEPTION_name); + zend_string_release_ex(const_ERRMODE_EXCEPTION_name, true); zval const_CASE_NATURAL_value; ZVAL_LONG(&const_CASE_NATURAL_value, LONG_CONST(PDO_CASE_NATURAL)); - zend_string *const_CASE_NATURAL_name = zend_string_init_interned("CASE_NATURAL", sizeof("CASE_NATURAL") - 1, 1); + zend_string *const_CASE_NATURAL_name = zend_string_init_interned("CASE_NATURAL", sizeof("CASE_NATURAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_CASE_NATURAL_name, &const_CASE_NATURAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CASE_NATURAL_name); + zend_string_release_ex(const_CASE_NATURAL_name, true); zval const_CASE_LOWER_value; ZVAL_LONG(&const_CASE_LOWER_value, LONG_CONST(PDO_CASE_LOWER)); - zend_string *const_CASE_LOWER_name = zend_string_init_interned("CASE_LOWER", sizeof("CASE_LOWER") - 1, 1); + zend_string *const_CASE_LOWER_name = zend_string_init_interned("CASE_LOWER", sizeof("CASE_LOWER") - 1, true); zend_declare_typed_class_constant(class_entry, const_CASE_LOWER_name, &const_CASE_LOWER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CASE_LOWER_name); + zend_string_release_ex(const_CASE_LOWER_name, true); zval const_CASE_UPPER_value; ZVAL_LONG(&const_CASE_UPPER_value, LONG_CONST(PDO_CASE_UPPER)); - zend_string *const_CASE_UPPER_name = zend_string_init_interned("CASE_UPPER", sizeof("CASE_UPPER") - 1, 1); + zend_string *const_CASE_UPPER_name = zend_string_init_interned("CASE_UPPER", sizeof("CASE_UPPER") - 1, true); zend_declare_typed_class_constant(class_entry, const_CASE_UPPER_name, &const_CASE_UPPER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CASE_UPPER_name); + zend_string_release_ex(const_CASE_UPPER_name, true); zval const_NULL_NATURAL_value; ZVAL_LONG(&const_NULL_NATURAL_value, LONG_CONST(PDO_NULL_NATURAL)); - zend_string *const_NULL_NATURAL_name = zend_string_init_interned("NULL_NATURAL", sizeof("NULL_NATURAL") - 1, 1); + zend_string *const_NULL_NATURAL_name = zend_string_init_interned("NULL_NATURAL", sizeof("NULL_NATURAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_NULL_NATURAL_name, &const_NULL_NATURAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NULL_NATURAL_name); + zend_string_release_ex(const_NULL_NATURAL_name, true); zval const_NULL_EMPTY_STRING_value; ZVAL_LONG(&const_NULL_EMPTY_STRING_value, LONG_CONST(PDO_NULL_EMPTY_STRING)); - zend_string *const_NULL_EMPTY_STRING_name = zend_string_init_interned("NULL_EMPTY_STRING", sizeof("NULL_EMPTY_STRING") - 1, 1); + zend_string *const_NULL_EMPTY_STRING_name = zend_string_init_interned("NULL_EMPTY_STRING", sizeof("NULL_EMPTY_STRING") - 1, true); zend_declare_typed_class_constant(class_entry, const_NULL_EMPTY_STRING_name, &const_NULL_EMPTY_STRING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NULL_EMPTY_STRING_name); + zend_string_release_ex(const_NULL_EMPTY_STRING_name, true); zval const_NULL_TO_STRING_value; ZVAL_LONG(&const_NULL_TO_STRING_value, LONG_CONST(PDO_NULL_TO_STRING)); - zend_string *const_NULL_TO_STRING_name = zend_string_init_interned("NULL_TO_STRING", sizeof("NULL_TO_STRING") - 1, 1); + zend_string *const_NULL_TO_STRING_name = zend_string_init_interned("NULL_TO_STRING", sizeof("NULL_TO_STRING") - 1, true); zend_declare_typed_class_constant(class_entry, const_NULL_TO_STRING_name, &const_NULL_TO_STRING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NULL_TO_STRING_name); + zend_string_release_ex(const_NULL_TO_STRING_name, true); zval const_ERR_NONE_value; zend_string *const_ERR_NONE_value_str = zend_string_init(PDO_ERR_NONE, strlen(PDO_ERR_NONE), 1); ZVAL_STR(&const_ERR_NONE_value, const_ERR_NONE_value_str); - zend_string *const_ERR_NONE_name = zend_string_init_interned("ERR_NONE", sizeof("ERR_NONE") - 1, 1); + zend_string *const_ERR_NONE_name = zend_string_init_interned("ERR_NONE", sizeof("ERR_NONE") - 1, true); zend_declare_typed_class_constant(class_entry, const_ERR_NONE_name, &const_ERR_NONE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(const_ERR_NONE_name); + zend_string_release_ex(const_ERR_NONE_name, true); zval const_FETCH_ORI_NEXT_value; ZVAL_LONG(&const_FETCH_ORI_NEXT_value, LONG_CONST(PDO_FETCH_ORI_NEXT)); - zend_string *const_FETCH_ORI_NEXT_name = zend_string_init_interned("FETCH_ORI_NEXT", sizeof("FETCH_ORI_NEXT") - 1, 1); + zend_string *const_FETCH_ORI_NEXT_name = zend_string_init_interned("FETCH_ORI_NEXT", sizeof("FETCH_ORI_NEXT") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_ORI_NEXT_name, &const_FETCH_ORI_NEXT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_ORI_NEXT_name); + zend_string_release_ex(const_FETCH_ORI_NEXT_name, true); zval const_FETCH_ORI_PRIOR_value; ZVAL_LONG(&const_FETCH_ORI_PRIOR_value, LONG_CONST(PDO_FETCH_ORI_PRIOR)); - zend_string *const_FETCH_ORI_PRIOR_name = zend_string_init_interned("FETCH_ORI_PRIOR", sizeof("FETCH_ORI_PRIOR") - 1, 1); + zend_string *const_FETCH_ORI_PRIOR_name = zend_string_init_interned("FETCH_ORI_PRIOR", sizeof("FETCH_ORI_PRIOR") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_ORI_PRIOR_name, &const_FETCH_ORI_PRIOR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_ORI_PRIOR_name); + zend_string_release_ex(const_FETCH_ORI_PRIOR_name, true); zval const_FETCH_ORI_FIRST_value; ZVAL_LONG(&const_FETCH_ORI_FIRST_value, LONG_CONST(PDO_FETCH_ORI_FIRST)); - zend_string *const_FETCH_ORI_FIRST_name = zend_string_init_interned("FETCH_ORI_FIRST", sizeof("FETCH_ORI_FIRST") - 1, 1); + zend_string *const_FETCH_ORI_FIRST_name = zend_string_init_interned("FETCH_ORI_FIRST", sizeof("FETCH_ORI_FIRST") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_ORI_FIRST_name, &const_FETCH_ORI_FIRST_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_ORI_FIRST_name); + zend_string_release_ex(const_FETCH_ORI_FIRST_name, true); zval const_FETCH_ORI_LAST_value; ZVAL_LONG(&const_FETCH_ORI_LAST_value, LONG_CONST(PDO_FETCH_ORI_LAST)); - zend_string *const_FETCH_ORI_LAST_name = zend_string_init_interned("FETCH_ORI_LAST", sizeof("FETCH_ORI_LAST") - 1, 1); + zend_string *const_FETCH_ORI_LAST_name = zend_string_init_interned("FETCH_ORI_LAST", sizeof("FETCH_ORI_LAST") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_ORI_LAST_name, &const_FETCH_ORI_LAST_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_ORI_LAST_name); + zend_string_release_ex(const_FETCH_ORI_LAST_name, true); zval const_FETCH_ORI_ABS_value; ZVAL_LONG(&const_FETCH_ORI_ABS_value, LONG_CONST(PDO_FETCH_ORI_ABS)); - zend_string *const_FETCH_ORI_ABS_name = zend_string_init_interned("FETCH_ORI_ABS", sizeof("FETCH_ORI_ABS") - 1, 1); + zend_string *const_FETCH_ORI_ABS_name = zend_string_init_interned("FETCH_ORI_ABS", sizeof("FETCH_ORI_ABS") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_ORI_ABS_name, &const_FETCH_ORI_ABS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_ORI_ABS_name); + zend_string_release_ex(const_FETCH_ORI_ABS_name, true); zval const_FETCH_ORI_REL_value; ZVAL_LONG(&const_FETCH_ORI_REL_value, LONG_CONST(PDO_FETCH_ORI_REL)); - zend_string *const_FETCH_ORI_REL_name = zend_string_init_interned("FETCH_ORI_REL", sizeof("FETCH_ORI_REL") - 1, 1); + zend_string *const_FETCH_ORI_REL_name = zend_string_init_interned("FETCH_ORI_REL", sizeof("FETCH_ORI_REL") - 1, true); zend_declare_typed_class_constant(class_entry, const_FETCH_ORI_REL_name, &const_FETCH_ORI_REL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FETCH_ORI_REL_name); + zend_string_release_ex(const_FETCH_ORI_REL_name, true); zval const_CURSOR_FWDONLY_value; ZVAL_LONG(&const_CURSOR_FWDONLY_value, LONG_CONST(PDO_CURSOR_FWDONLY)); - zend_string *const_CURSOR_FWDONLY_name = zend_string_init_interned("CURSOR_FWDONLY", sizeof("CURSOR_FWDONLY") - 1, 1); + zend_string *const_CURSOR_FWDONLY_name = zend_string_init_interned("CURSOR_FWDONLY", sizeof("CURSOR_FWDONLY") - 1, true); zend_declare_typed_class_constant(class_entry, const_CURSOR_FWDONLY_name, &const_CURSOR_FWDONLY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CURSOR_FWDONLY_name); + zend_string_release_ex(const_CURSOR_FWDONLY_name, true); zval const_CURSOR_SCROLL_value; ZVAL_LONG(&const_CURSOR_SCROLL_value, LONG_CONST(PDO_CURSOR_SCROLL)); - zend_string *const_CURSOR_SCROLL_name = zend_string_init_interned("CURSOR_SCROLL", sizeof("CURSOR_SCROLL") - 1, 1); + zend_string *const_CURSOR_SCROLL_name = zend_string_init_interned("CURSOR_SCROLL", sizeof("CURSOR_SCROLL") - 1, true); zend_declare_typed_class_constant(class_entry, const_CURSOR_SCROLL_name, &const_CURSOR_SCROLL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CURSOR_SCROLL_name); + zend_string_release_ex(const_CURSOR_SCROLL_name, true); zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "__construct", sizeof("__construct") - 1), 2, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); diff --git a/ext/pdo/pdo_sql_parser.re b/ext/pdo/pdo_sql_parser.re index a87fd473404ec..1897f9f238bf1 100644 --- a/ext/pdo/pdo_sql_parser.re +++ b/ext/pdo/pdo_sql_parser.re @@ -300,6 +300,12 @@ safe: } plc->quoted = stmt->dbh->methods->quoter(stmt->dbh, buf, param_type); + if (plc->quoted == NULL) { + /* bork */ + ret = -1; + strncpy(stmt->error_code, stmt->dbh->error_code, 6); + goto clean_up; + } } } diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 697940d94260d..73d4530e8f657 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -55,17 +55,17 @@ static inline bool rewrite_name_to_position(pdo_stmt_t *stmt, struct pdo_bound_p if (stmt->named_rewrite_template) { /* this is not an error here */ - return 1; + return true; } if (!param->name) { /* do the reverse; map the parameter number to the name */ if ((name = zend_hash_index_find_ptr(stmt->bound_param_map, param->paramno)) != NULL) { param->name = zend_string_copy(name); - return 1; + return true; } /* TODO Error? */ pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "parameter was not defined"); - return 0; + return false; } ZEND_HASH_FOREACH_PTR(stmt->bound_param_map, name) { @@ -79,29 +79,29 @@ static inline bool rewrite_name_to_position(pdo_stmt_t *stmt, struct pdo_bound_p return -1; } param->paramno = position; - return 1; + return true; } ZEND_HASH_FOREACH_END(); /* TODO Error? */ pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "parameter was not defined"); - return 0; + return false; } - return 1; + return true; } /* }}} */ /* trigger callback hook for parameters */ static bool dispatch_param_event(pdo_stmt_t *stmt, enum pdo_param_event event_type) /* {{{ */ { - bool ret = 1, is_param = 1; + bool ret = true, is_param = true; struct pdo_bound_param_data *param; HashTable *ht; if (stmt->dbh->skip_param_evt & (1 << event_type)) { - return 1; + return true; } if (!stmt->methods->param_hook) { - return 1; + return true; } ht = stmt->bound_params; @@ -110,14 +110,14 @@ static bool dispatch_param_event(pdo_stmt_t *stmt, enum pdo_param_event event_ty if (ht) { ZEND_HASH_FOREACH_PTR(ht, param) { if (!stmt->methods->param_hook(stmt, param, event_type)) { - ret = 0; + ret = false; break; } } ZEND_HASH_FOREACH_END(); } if (ret && is_param) { ht = stmt->bound_columns; - is_param = 0; + is_param = false; goto iterate; } @@ -272,7 +272,7 @@ static bool really_register_bound_param(struct pdo_bound_param_data *param, pdo_ if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_STR && param->max_value_len <= 0 && !Z_ISNULL_P(parameter)) { if (!try_convert_to_string(parameter)) { - return 0; + return false; } } else if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_INT && (Z_TYPE_P(parameter) == IS_FALSE || Z_TYPE_P(parameter) == IS_TRUE)) { convert_to_long(parameter); @@ -326,7 +326,7 @@ static bool really_register_bound_param(struct pdo_bound_param_data *param, pdo_ zend_string_release_ex(param->name, 0); param->name = NULL; } - return 0; + return false; } /* ask the driver to perform any normalization it needs on the @@ -340,7 +340,7 @@ static bool really_register_bound_param(struct pdo_bound_param_data *param, pdo_ zend_string_release_ex(param->name, 0); param->name = NULL; } - return 0; + return false; } } @@ -371,10 +371,10 @@ static bool really_register_bound_param(struct pdo_bound_param_data *param, pdo_ } /* param->parameter is freed by hash dtor */ ZVAL_UNDEF(¶m->parameter); - return 0; + return false; } } - return 1; + return true; } /* }}} */ @@ -563,24 +563,24 @@ static inline void fetch_value(pdo_stmt_t *stmt, zval *dest, int colno, enum pdo static bool do_fetch_common(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori, zend_long offset) /* {{{ */ { if (!stmt->executed) { - return 0; + return false; } if (!dispatch_param_event(stmt, PDO_PARAM_EVT_FETCH_PRE)) { - return 0; + return false; } if (!stmt->methods->fetcher(stmt, ori, offset)) { - return 0; + return false; } /* some drivers might need to describe the columns now */ if (!stmt->columns && !pdo_stmt_describe_columns(stmt)) { - return 0; + return false; } if (!dispatch_param_event(stmt, PDO_PARAM_EVT_FETCH_POST)) { - return 0; + return false; } if (stmt->bound_columns) { @@ -607,7 +607,7 @@ static bool do_fetch_common(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori, ze } ZEND_HASH_FOREACH_END(); } - return 1; + return true; } /* }}} */ @@ -771,9 +771,10 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "No fetch class specified"); goto in_fetch_error; } - ctor_arguments = stmt->fetch.cls.ctor_args; } ZEND_ASSERT(ce != NULL); + + ctor_arguments = stmt->fetch.cls.ctor_args; if (flags & PDO_FETCH_SERIALIZE) { if (!ce->unserialize) { /* As this option is deprecated we do not bother to mention the class name. */ @@ -1052,7 +1053,7 @@ PHP_METHOD(PDOStatement, fetch) array_init_size(return_value, 1); bool success = pdo_do_key_pair_fetch(stmt, ori, off, Z_ARRVAL_P(return_value)); if (!success) { - zval_dtor(return_value); + zval_ptr_dtor_nogc(return_value); PDO_HANDLE_STMT_ERR(); RETURN_FALSE; } @@ -1506,9 +1507,9 @@ static bool generic_stmt_attr_get(pdo_stmt_t *stmt, zval *return_value, zend_lon switch (attr) { case PDO_ATTR_EMULATE_PREPARES: RETVAL_BOOL(stmt->supports_placeholders == PDO_PLACEHOLDER_NONE); - return 1; + return true; } - return 0; + return false; } PHP_METHOD(PDOStatement, getAttribute) @@ -1788,12 +1789,12 @@ static bool pdo_stmt_do_next_rowset(pdo_stmt_t *stmt) if (!stmt->methods->next_rowset(stmt)) { /* Set the executed flag to 0 to reallocate columns on next execute */ stmt->executed = 0; - return 0; + return false; } pdo_stmt_describe_columns(stmt); - return 1; + return true; } PHP_METHOD(PDOStatement, nextRowset) diff --git a/ext/pdo/pdo_stmt_arginfo.h b/ext/pdo/pdo_stmt_arginfo.h index 0d4131d5be493..0be8ee82d84d6 100644 --- a/ext/pdo/pdo_stmt_arginfo.h +++ b/ext/pdo/pdo_stmt_arginfo.h @@ -142,9 +142,9 @@ static zend_class_entry *register_class_PDOStatement(zend_class_entry *class_ent zval property_queryString_default_value; ZVAL_UNDEF(&property_queryString_default_value); - zend_string *property_queryString_name = zend_string_init("queryString", sizeof("queryString") - 1, 1); + zend_string *property_queryString_name = zend_string_init("queryString", sizeof("queryString") - 1, true); zend_declare_typed_property(class_entry, property_queryString_name, &property_queryString_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_queryString_name); + zend_string_release_ex(property_queryString_name, true); return class_entry; } @@ -158,9 +158,9 @@ static zend_class_entry *register_class_PDORow(void) zval property_queryString_default_value; ZVAL_UNDEF(&property_queryString_default_value); - zend_string *property_queryString_name = zend_string_init("queryString", sizeof("queryString") - 1, 1); + zend_string *property_queryString_name = zend_string_init("queryString", sizeof("queryString") - 1, true); zend_declare_typed_property(class_entry, property_queryString_name, &property_queryString_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_queryString_name); + zend_string_release_ex(property_queryString_name, true); return class_entry; } 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/gh20553.phpt b/ext/pdo/tests/gh20553.phpt new file mode 100644 index 0000000000000..fe0b84c27ebb0 --- /dev/null +++ b/ext/pdo/tests/gh20553.phpt @@ -0,0 +1,97 @@ +--TEST-- +GH-20553: PHP 8.5.0 regression: PDO::FETCH_CLASSTYPE ignores $constructorArgs +--EXTENSIONS-- +pdo +--SKIPIF-- + +--FILE-- + PDO::FETCH_CLASS, + 'PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE' + => PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, + 'PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE' + => PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE, + 'PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE | PDO::FETCH_PROPS_LATE' + => PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE | PDO::FETCH_PROPS_LATE, +]; + +foreach ($fetchModes as $combinedModes => $fetchMode) { + echo '## ' . $combinedModes . PHP_EOL; + $db->query($sql)->fetchAll( + $fetchMode, + 'dumpy', + ['constructor argument #1'] + ); + echo PHP_EOL; +} +?> +--EXPECT-- +## PDO::FETCH_CLASS +'pdo_fetch_class_type_class' = 'dummy' +'foo' = 'bar' +'abc' = 'dfg' +constructor called, + my class is 'dumpy' + input parameters: array ( + 0 => 'constructor argument #1', +) + +## PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE +constructor called, + my class is 'dumpy' + input parameters: array ( + 0 => 'constructor argument #1', +) +'pdo_fetch_class_type_class' = 'dummy' +'foo' = 'bar' +'abc' = 'dfg' + +## PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE +'foo' = 'bar' +'abc' = 'dfg' +constructor called, + my class is 'dummy' + input parameters: array ( + 0 => 'constructor argument #1', +) + +## PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE | PDO::FETCH_PROPS_LATE +constructor called, + my class is 'dummy' + input parameters: array ( + 0 => 'constructor argument #1', +) +'foo' = 'bar' +'abc' = 'dfg' 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/dblib_driver.c b/ext/pdo_dblib/dblib_driver.c index 132e5c2e4dee1..68e251c2b6a9a 100644 --- a/ext/pdo_dblib/dblib_driver.c +++ b/ext/pdo_dblib/dblib_driver.c @@ -145,20 +145,20 @@ static zend_long dblib_handle_doer(pdo_dbh_t *dbh, const zend_string *sql) static zend_string* dblib_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype) { pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data; - bool use_national_character_set = 0; + bool use_national_character_set = false; size_t i; char *q; size_t quotedlen = 0, extralen = 0; zend_string *quoted_str; if (H->assume_national_character_set_strings) { - use_national_character_set = 1; + use_national_character_set = true; } if ((paramtype & PDO_PARAM_STR_NATL) == PDO_PARAM_STR_NATL) { - use_national_character_set = 1; + use_national_character_set = true; } if ((paramtype & PDO_PARAM_STR_CHAR) == PDO_PARAM_STR_CHAR) { - use_national_character_set = 0; + use_national_character_set = false; } /* Detect quoted length, adding extra char for doubled single quotes */ 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/pdo_dblib_arginfo.h b/ext/pdo_dblib/pdo_dblib_arginfo.h index 1cf6c60d7a3b0..2452255265a33 100644 --- a/ext/pdo_dblib/pdo_dblib_arginfo.h +++ b/ext/pdo_dblib/pdo_dblib_arginfo.h @@ -10,45 +10,45 @@ static zend_class_entry *register_class_Pdo_Dblib(zend_class_entry *class_entry_ zval const_ATTR_CONNECTION_TIMEOUT_value; ZVAL_LONG(&const_ATTR_CONNECTION_TIMEOUT_value, PDO_DBLIB_ATTR_CONNECTION_TIMEOUT); - zend_string *const_ATTR_CONNECTION_TIMEOUT_name = zend_string_init_interned("ATTR_CONNECTION_TIMEOUT", sizeof("ATTR_CONNECTION_TIMEOUT") - 1, 1); + zend_string *const_ATTR_CONNECTION_TIMEOUT_name = zend_string_init_interned("ATTR_CONNECTION_TIMEOUT", sizeof("ATTR_CONNECTION_TIMEOUT") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_CONNECTION_TIMEOUT_name, &const_ATTR_CONNECTION_TIMEOUT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_CONNECTION_TIMEOUT_name); + zend_string_release_ex(const_ATTR_CONNECTION_TIMEOUT_name, true); zval const_ATTR_QUERY_TIMEOUT_value; ZVAL_LONG(&const_ATTR_QUERY_TIMEOUT_value, PDO_DBLIB_ATTR_QUERY_TIMEOUT); - zend_string *const_ATTR_QUERY_TIMEOUT_name = zend_string_init_interned("ATTR_QUERY_TIMEOUT", sizeof("ATTR_QUERY_TIMEOUT") - 1, 1); + zend_string *const_ATTR_QUERY_TIMEOUT_name = zend_string_init_interned("ATTR_QUERY_TIMEOUT", sizeof("ATTR_QUERY_TIMEOUT") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_QUERY_TIMEOUT_name, &const_ATTR_QUERY_TIMEOUT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_QUERY_TIMEOUT_name); + zend_string_release_ex(const_ATTR_QUERY_TIMEOUT_name, true); zval const_ATTR_STRINGIFY_UNIQUEIDENTIFIER_value; ZVAL_LONG(&const_ATTR_STRINGIFY_UNIQUEIDENTIFIER_value, PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER); - zend_string *const_ATTR_STRINGIFY_UNIQUEIDENTIFIER_name = zend_string_init_interned("ATTR_STRINGIFY_UNIQUEIDENTIFIER", sizeof("ATTR_STRINGIFY_UNIQUEIDENTIFIER") - 1, 1); + zend_string *const_ATTR_STRINGIFY_UNIQUEIDENTIFIER_name = zend_string_init_interned("ATTR_STRINGIFY_UNIQUEIDENTIFIER", sizeof("ATTR_STRINGIFY_UNIQUEIDENTIFIER") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_STRINGIFY_UNIQUEIDENTIFIER_name, &const_ATTR_STRINGIFY_UNIQUEIDENTIFIER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_STRINGIFY_UNIQUEIDENTIFIER_name); + zend_string_release_ex(const_ATTR_STRINGIFY_UNIQUEIDENTIFIER_name, true); zval const_ATTR_VERSION_value; ZVAL_LONG(&const_ATTR_VERSION_value, PDO_DBLIB_ATTR_VERSION); - zend_string *const_ATTR_VERSION_name = zend_string_init_interned("ATTR_VERSION", sizeof("ATTR_VERSION") - 1, 1); + zend_string *const_ATTR_VERSION_name = zend_string_init_interned("ATTR_VERSION", sizeof("ATTR_VERSION") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_VERSION_name, &const_ATTR_VERSION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_VERSION_name); + zend_string_release_ex(const_ATTR_VERSION_name, true); zval const_ATTR_TDS_VERSION_value; ZVAL_LONG(&const_ATTR_TDS_VERSION_value, PDO_DBLIB_ATTR_TDS_VERSION); - zend_string *const_ATTR_TDS_VERSION_name = zend_string_init_interned("ATTR_TDS_VERSION", sizeof("ATTR_TDS_VERSION") - 1, 1); + zend_string *const_ATTR_TDS_VERSION_name = zend_string_init_interned("ATTR_TDS_VERSION", sizeof("ATTR_TDS_VERSION") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_TDS_VERSION_name, &const_ATTR_TDS_VERSION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_TDS_VERSION_name); + zend_string_release_ex(const_ATTR_TDS_VERSION_name, true); zval const_ATTR_SKIP_EMPTY_ROWSETS_value; ZVAL_LONG(&const_ATTR_SKIP_EMPTY_ROWSETS_value, PDO_DBLIB_ATTR_SKIP_EMPTY_ROWSETS); - zend_string *const_ATTR_SKIP_EMPTY_ROWSETS_name = zend_string_init_interned("ATTR_SKIP_EMPTY_ROWSETS", sizeof("ATTR_SKIP_EMPTY_ROWSETS") - 1, 1); + zend_string *const_ATTR_SKIP_EMPTY_ROWSETS_name = zend_string_init_interned("ATTR_SKIP_EMPTY_ROWSETS", sizeof("ATTR_SKIP_EMPTY_ROWSETS") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_SKIP_EMPTY_ROWSETS_name, &const_ATTR_SKIP_EMPTY_ROWSETS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_SKIP_EMPTY_ROWSETS_name); + zend_string_release_ex(const_ATTR_SKIP_EMPTY_ROWSETS_name, true); zval const_ATTR_DATETIME_CONVERT_value; ZVAL_LONG(&const_ATTR_DATETIME_CONVERT_value, PDO_DBLIB_ATTR_DATETIME_CONVERT); - zend_string *const_ATTR_DATETIME_CONVERT_name = zend_string_init_interned("ATTR_DATETIME_CONVERT", sizeof("ATTR_DATETIME_CONVERT") - 1, 1); + zend_string *const_ATTR_DATETIME_CONVERT_name = zend_string_init_interned("ATTR_DATETIME_CONVERT", sizeof("ATTR_DATETIME_CONVERT") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_DATETIME_CONVERT_name, &const_ATTR_DATETIME_CONVERT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_DATETIME_CONVERT_name); + zend_string_release_ex(const_ATTR_DATETIME_CONVERT_name, true); return class_entry; } 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_driver.c b/ext/pdo_firebird/firebird_driver.c index f6d5b1144f382..8eea24a65353f 100644 --- a/ext/pdo_firebird/firebird_driver.c +++ b/ext/pdo_firebird/firebird_driver.c @@ -297,7 +297,7 @@ static FbTokenType php_firebird_get_token(const char** begin, const char* end) static int php_firebird_preprocess(const zend_string* sql, char* sql_out, HashTable* named_params) { - bool passAsIs = 1, execBlock = 0; + bool passAsIs = true, execBlock = false; zend_long pindex = -1; char pname[254], ident[253], ident2[253]; unsigned int l; @@ -354,7 +354,7 @@ static int php_firebird_preprocess(const zend_string* sql, char* sql_out, HashTa strncpy(ident2, i2, l); ident2[l] = '\0'; execBlock = !strcasecmp(ident2, "BLOCK"); - passAsIs = 0; + passAsIs = false; } else { @@ -592,7 +592,7 @@ static void firebird_handle_closer(pdo_dbh_t *dbh) /* {{{ */ php_firebird_rollback_transaction(dbh); } } - H->in_manually_txn = 0; + H->in_manually_txn = false; /* isc_detach_database returns 0 on success, 1 on failure. */ if (H->db && isc_detach_database(H->isc_status, &H->db)) { @@ -904,7 +904,7 @@ static bool firebird_handle_manually_begin(pdo_dbh_t *dbh) /* {{{ */ if (!php_firebird_begin_transaction(dbh, /* auto commit mode */ false)) { return false; } - H->in_manually_txn = 1; + H->in_manually_txn = true; return true; } /* }}} */ @@ -954,7 +954,7 @@ static bool firebird_handle_manually_commit(pdo_dbh_t *dbh) /* {{{ */ return false; } } - H->in_manually_txn = 0; + H->in_manually_txn = false; return true; } /* }}} */ @@ -990,7 +990,7 @@ static bool firebird_handle_manually_rollback(pdo_dbh_t *dbh) /* {{{ */ return false; } } - H->in_manually_txn = 0; + H->in_manually_txn = false; return true; } /* }}} */ @@ -1353,7 +1353,7 @@ static int pdo_firebird_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* dbh->password = pestrdup(vars[5].optval, dbh->is_persistent); } - H->in_manually_txn = 0; + H->in_manually_txn = false; H->is_writable_txn = pdo_attr_lval(driver_options, PDO_FB_WRITABLE_TRANSACTION, 1); zend_long txn_isolation_level = pdo_attr_lval(driver_options, PDO_FB_TRANSACTION_ISOLATION_LEVEL, PDO_FB_REPEATABLE_READ); if (txn_isolation_level == PDO_FB_READ_COMMITTED || 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/pdo_firebird_arginfo.h b/ext/pdo_firebird/pdo_firebird_arginfo.h index a5a9c562c9c12..fd500a6130c0a 100644 --- a/ext/pdo_firebird/pdo_firebird_arginfo.h +++ b/ext/pdo_firebird/pdo_firebird_arginfo.h @@ -20,51 +20,51 @@ static zend_class_entry *register_class_Pdo_Firebird(zend_class_entry *class_ent zval const_ATTR_DATE_FORMAT_value; ZVAL_LONG(&const_ATTR_DATE_FORMAT_value, PDO_FB_ATTR_DATE_FORMAT); - zend_string *const_ATTR_DATE_FORMAT_name = zend_string_init_interned("ATTR_DATE_FORMAT", sizeof("ATTR_DATE_FORMAT") - 1, 1); + zend_string *const_ATTR_DATE_FORMAT_name = zend_string_init_interned("ATTR_DATE_FORMAT", sizeof("ATTR_DATE_FORMAT") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_DATE_FORMAT_name, &const_ATTR_DATE_FORMAT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_DATE_FORMAT_name); + zend_string_release_ex(const_ATTR_DATE_FORMAT_name, true); zval const_ATTR_TIME_FORMAT_value; ZVAL_LONG(&const_ATTR_TIME_FORMAT_value, PDO_FB_ATTR_TIME_FORMAT); - zend_string *const_ATTR_TIME_FORMAT_name = zend_string_init_interned("ATTR_TIME_FORMAT", sizeof("ATTR_TIME_FORMAT") - 1, 1); + zend_string *const_ATTR_TIME_FORMAT_name = zend_string_init_interned("ATTR_TIME_FORMAT", sizeof("ATTR_TIME_FORMAT") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_TIME_FORMAT_name, &const_ATTR_TIME_FORMAT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_TIME_FORMAT_name); + zend_string_release_ex(const_ATTR_TIME_FORMAT_name, true); zval const_ATTR_TIMESTAMP_FORMAT_value; ZVAL_LONG(&const_ATTR_TIMESTAMP_FORMAT_value, PDO_FB_ATTR_TIMESTAMP_FORMAT); - zend_string *const_ATTR_TIMESTAMP_FORMAT_name = zend_string_init_interned("ATTR_TIMESTAMP_FORMAT", sizeof("ATTR_TIMESTAMP_FORMAT") - 1, 1); + zend_string *const_ATTR_TIMESTAMP_FORMAT_name = zend_string_init_interned("ATTR_TIMESTAMP_FORMAT", sizeof("ATTR_TIMESTAMP_FORMAT") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_TIMESTAMP_FORMAT_name, &const_ATTR_TIMESTAMP_FORMAT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_TIMESTAMP_FORMAT_name); + zend_string_release_ex(const_ATTR_TIMESTAMP_FORMAT_name, true); zval const_TRANSACTION_ISOLATION_LEVEL_value; ZVAL_LONG(&const_TRANSACTION_ISOLATION_LEVEL_value, PDO_FB_TRANSACTION_ISOLATION_LEVEL); - zend_string *const_TRANSACTION_ISOLATION_LEVEL_name = zend_string_init_interned("TRANSACTION_ISOLATION_LEVEL", sizeof("TRANSACTION_ISOLATION_LEVEL") - 1, 1); + zend_string *const_TRANSACTION_ISOLATION_LEVEL_name = zend_string_init_interned("TRANSACTION_ISOLATION_LEVEL", sizeof("TRANSACTION_ISOLATION_LEVEL") - 1, true); zend_declare_typed_class_constant(class_entry, const_TRANSACTION_ISOLATION_LEVEL_name, &const_TRANSACTION_ISOLATION_LEVEL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TRANSACTION_ISOLATION_LEVEL_name); + zend_string_release_ex(const_TRANSACTION_ISOLATION_LEVEL_name, true); zval const_READ_COMMITTED_value; ZVAL_LONG(&const_READ_COMMITTED_value, PDO_FB_READ_COMMITTED); - zend_string *const_READ_COMMITTED_name = zend_string_init_interned("READ_COMMITTED", sizeof("READ_COMMITTED") - 1, 1); + zend_string *const_READ_COMMITTED_name = zend_string_init_interned("READ_COMMITTED", sizeof("READ_COMMITTED") - 1, true); zend_declare_typed_class_constant(class_entry, const_READ_COMMITTED_name, &const_READ_COMMITTED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_READ_COMMITTED_name); + zend_string_release_ex(const_READ_COMMITTED_name, true); zval const_REPEATABLE_READ_value; ZVAL_LONG(&const_REPEATABLE_READ_value, PDO_FB_REPEATABLE_READ); - zend_string *const_REPEATABLE_READ_name = zend_string_init_interned("REPEATABLE_READ", sizeof("REPEATABLE_READ") - 1, 1); + zend_string *const_REPEATABLE_READ_name = zend_string_init_interned("REPEATABLE_READ", sizeof("REPEATABLE_READ") - 1, true); zend_declare_typed_class_constant(class_entry, const_REPEATABLE_READ_name, &const_REPEATABLE_READ_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_REPEATABLE_READ_name); + zend_string_release_ex(const_REPEATABLE_READ_name, true); zval const_SERIALIZABLE_value; ZVAL_LONG(&const_SERIALIZABLE_value, PDO_FB_SERIALIZABLE); - zend_string *const_SERIALIZABLE_name = zend_string_init_interned("SERIALIZABLE", sizeof("SERIALIZABLE") - 1, 1); + zend_string *const_SERIALIZABLE_name = zend_string_init_interned("SERIALIZABLE", sizeof("SERIALIZABLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_SERIALIZABLE_name, &const_SERIALIZABLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SERIALIZABLE_name); + zend_string_release_ex(const_SERIALIZABLE_name, true); zval const_WRITABLE_TRANSACTION_value; ZVAL_LONG(&const_WRITABLE_TRANSACTION_value, PDO_FB_WRITABLE_TRANSACTION); - zend_string *const_WRITABLE_TRANSACTION_name = zend_string_init_interned("WRITABLE_TRANSACTION", sizeof("WRITABLE_TRANSACTION") - 1, 1); + zend_string *const_WRITABLE_TRANSACTION_name = zend_string_init_interned("WRITABLE_TRANSACTION", sizeof("WRITABLE_TRANSACTION") - 1, true); zend_declare_typed_class_constant(class_entry, const_WRITABLE_TRANSACTION_name, &const_WRITABLE_TRANSACTION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WRITABLE_TRANSACTION_name); + zend_string_release_ex(const_WRITABLE_TRANSACTION_name, true); return class_entry; } 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..808f4acbfa37d 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) { @@ -308,21 +308,21 @@ static zend_string *pdo_mysql_last_insert_id(pdo_dbh_t *dbh, const zend_string * static zend_string* mysql_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype ) { pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data; - bool use_national_character_set = 0; - bool use_binary = 0; + bool use_national_character_set = false; + bool use_binary = false; size_t quotedlen; if ((paramtype & PDO_PARAM_LOB) == PDO_PARAM_LOB) { - use_binary = 1; + use_binary = true; } else { if (H->assume_national_character_set_strings) { - use_national_character_set = 1; + use_national_character_set = true; } if ((paramtype & PDO_PARAM_STR_NATL) == PDO_PARAM_STR_NATL) { - use_national_character_set = 1; + use_national_character_set = true; } if ((paramtype & PDO_PARAM_STR_CHAR) == PDO_PARAM_STR_CHAR) { - use_national_character_set = 0; + use_national_character_set = false; } } diff --git a/ext/pdo_mysql/mysql_statement.c b/ext/pdo_mysql/mysql_statement.c index cf01791407e2b..8b2519ce90aa3 100644 --- a/ext/pdo_mysql/mysql_statement.c +++ b/ext/pdo_mysql/mysql_statement.c @@ -713,7 +713,7 @@ static int pdo_mysql_stmt_get_col( static char *type_to_name_native(int type) /* {{{ */ { -#define PDO_MYSQL_NATIVE_TYPE_NAME(x) case FIELD_TYPE_##x: return #x; +#define PDO_MYSQL_NATIVE_TYPE_NAME(x) case MYSQL_TYPE_##x: return #x; switch (type) { PDO_MYSQL_NATIVE_TYPE_NAME(STRING) @@ -746,6 +746,13 @@ static char *type_to_name_native(int type) /* {{{ */ PDO_MYSQL_NATIVE_TYPE_NAME(DATE) #ifdef FIELD_TYPE_NEWDATE PDO_MYSQL_NATIVE_TYPE_NAME(NEWDATE) +#endif + /* The following 2 don't have BC FIELD_TYPE_* aliases. */ +#if (MYSQL_VERSION_ID >= 90000 && !defined(MARIADB_BASE_VERSION)) || defined(PDO_USE_MYSQLND) + PDO_MYSQL_NATIVE_TYPE_NAME(VECTOR) +#endif +#if MYSQL_VERSION_ID >= 50708 || defined(PDO_USE_MYSQLND) + PDO_MYSQL_NATIVE_TYPE_NAME(JSON) #endif PDO_MYSQL_NATIVE_TYPE_NAME(TIME) PDO_MYSQL_NATIVE_TYPE_NAME(DATETIME) 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/pdo_mysql_arginfo.h b/ext/pdo_mysql/pdo_mysql_arginfo.h index 0e9c04bd3cfd3..516109fa0520a 100644 --- a/ext/pdo_mysql/pdo_mysql_arginfo.h +++ b/ext/pdo_mysql/pdo_mysql_arginfo.h @@ -20,124 +20,124 @@ static zend_class_entry *register_class_Pdo_Mysql(zend_class_entry *class_entry_ zval const_ATTR_USE_BUFFERED_QUERY_value; ZVAL_LONG(&const_ATTR_USE_BUFFERED_QUERY_value, PDO_MYSQL_ATTR_USE_BUFFERED_QUERY); - zend_string *const_ATTR_USE_BUFFERED_QUERY_name = zend_string_init_interned("ATTR_USE_BUFFERED_QUERY", sizeof("ATTR_USE_BUFFERED_QUERY") - 1, 1); + zend_string *const_ATTR_USE_BUFFERED_QUERY_name = zend_string_init_interned("ATTR_USE_BUFFERED_QUERY", sizeof("ATTR_USE_BUFFERED_QUERY") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_USE_BUFFERED_QUERY_name, &const_ATTR_USE_BUFFERED_QUERY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_USE_BUFFERED_QUERY_name); + zend_string_release_ex(const_ATTR_USE_BUFFERED_QUERY_name, true); zval const_ATTR_LOCAL_INFILE_value; ZVAL_LONG(&const_ATTR_LOCAL_INFILE_value, PDO_MYSQL_ATTR_LOCAL_INFILE); - zend_string *const_ATTR_LOCAL_INFILE_name = zend_string_init_interned("ATTR_LOCAL_INFILE", sizeof("ATTR_LOCAL_INFILE") - 1, 1); + zend_string *const_ATTR_LOCAL_INFILE_name = zend_string_init_interned("ATTR_LOCAL_INFILE", sizeof("ATTR_LOCAL_INFILE") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_LOCAL_INFILE_name, &const_ATTR_LOCAL_INFILE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_LOCAL_INFILE_name); + zend_string_release_ex(const_ATTR_LOCAL_INFILE_name, true); zval const_ATTR_INIT_COMMAND_value; ZVAL_LONG(&const_ATTR_INIT_COMMAND_value, PDO_MYSQL_ATTR_INIT_COMMAND); - zend_string *const_ATTR_INIT_COMMAND_name = zend_string_init_interned("ATTR_INIT_COMMAND", sizeof("ATTR_INIT_COMMAND") - 1, 1); + zend_string *const_ATTR_INIT_COMMAND_name = zend_string_init_interned("ATTR_INIT_COMMAND", sizeof("ATTR_INIT_COMMAND") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_INIT_COMMAND_name, &const_ATTR_INIT_COMMAND_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_INIT_COMMAND_name); + zend_string_release_ex(const_ATTR_INIT_COMMAND_name, true); #if !defined(PDO_USE_MYSQLND) zval const_ATTR_MAX_BUFFER_SIZE_value; ZVAL_LONG(&const_ATTR_MAX_BUFFER_SIZE_value, PDO_MYSQL_ATTR_MAX_BUFFER_SIZE); - zend_string *const_ATTR_MAX_BUFFER_SIZE_name = zend_string_init_interned("ATTR_MAX_BUFFER_SIZE", sizeof("ATTR_MAX_BUFFER_SIZE") - 1, 1); + zend_string *const_ATTR_MAX_BUFFER_SIZE_name = zend_string_init_interned("ATTR_MAX_BUFFER_SIZE", sizeof("ATTR_MAX_BUFFER_SIZE") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_MAX_BUFFER_SIZE_name, &const_ATTR_MAX_BUFFER_SIZE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_MAX_BUFFER_SIZE_name); + zend_string_release_ex(const_ATTR_MAX_BUFFER_SIZE_name, true); zval const_ATTR_READ_DEFAULT_FILE_value; ZVAL_LONG(&const_ATTR_READ_DEFAULT_FILE_value, PDO_MYSQL_ATTR_READ_DEFAULT_FILE); - zend_string *const_ATTR_READ_DEFAULT_FILE_name = zend_string_init_interned("ATTR_READ_DEFAULT_FILE", sizeof("ATTR_READ_DEFAULT_FILE") - 1, 1); + zend_string *const_ATTR_READ_DEFAULT_FILE_name = zend_string_init_interned("ATTR_READ_DEFAULT_FILE", sizeof("ATTR_READ_DEFAULT_FILE") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_READ_DEFAULT_FILE_name, &const_ATTR_READ_DEFAULT_FILE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_READ_DEFAULT_FILE_name); + zend_string_release_ex(const_ATTR_READ_DEFAULT_FILE_name, true); zval const_ATTR_READ_DEFAULT_GROUP_value; ZVAL_LONG(&const_ATTR_READ_DEFAULT_GROUP_value, PDO_MYSQL_ATTR_READ_DEFAULT_GROUP); - zend_string *const_ATTR_READ_DEFAULT_GROUP_name = zend_string_init_interned("ATTR_READ_DEFAULT_GROUP", sizeof("ATTR_READ_DEFAULT_GROUP") - 1, 1); + zend_string *const_ATTR_READ_DEFAULT_GROUP_name = zend_string_init_interned("ATTR_READ_DEFAULT_GROUP", sizeof("ATTR_READ_DEFAULT_GROUP") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_READ_DEFAULT_GROUP_name, &const_ATTR_READ_DEFAULT_GROUP_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_READ_DEFAULT_GROUP_name); + zend_string_release_ex(const_ATTR_READ_DEFAULT_GROUP_name, true); #endif zval const_ATTR_COMPRESS_value; ZVAL_LONG(&const_ATTR_COMPRESS_value, PDO_MYSQL_ATTR_COMPRESS); - zend_string *const_ATTR_COMPRESS_name = zend_string_init_interned("ATTR_COMPRESS", sizeof("ATTR_COMPRESS") - 1, 1); + zend_string *const_ATTR_COMPRESS_name = zend_string_init_interned("ATTR_COMPRESS", sizeof("ATTR_COMPRESS") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_COMPRESS_name, &const_ATTR_COMPRESS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_COMPRESS_name); + zend_string_release_ex(const_ATTR_COMPRESS_name, true); zval const_ATTR_DIRECT_QUERY_value; ZVAL_LONG(&const_ATTR_DIRECT_QUERY_value, PDO_ATTR_EMULATE_PREPARES); - zend_string *const_ATTR_DIRECT_QUERY_name = zend_string_init_interned("ATTR_DIRECT_QUERY", sizeof("ATTR_DIRECT_QUERY") - 1, 1); + zend_string *const_ATTR_DIRECT_QUERY_name = zend_string_init_interned("ATTR_DIRECT_QUERY", sizeof("ATTR_DIRECT_QUERY") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_DIRECT_QUERY_name, &const_ATTR_DIRECT_QUERY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_DIRECT_QUERY_name); + zend_string_release_ex(const_ATTR_DIRECT_QUERY_name, true); zval const_ATTR_FOUND_ROWS_value; ZVAL_LONG(&const_ATTR_FOUND_ROWS_value, PDO_MYSQL_ATTR_FOUND_ROWS); - zend_string *const_ATTR_FOUND_ROWS_name = zend_string_init_interned("ATTR_FOUND_ROWS", sizeof("ATTR_FOUND_ROWS") - 1, 1); + zend_string *const_ATTR_FOUND_ROWS_name = zend_string_init_interned("ATTR_FOUND_ROWS", sizeof("ATTR_FOUND_ROWS") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_FOUND_ROWS_name, &const_ATTR_FOUND_ROWS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_FOUND_ROWS_name); + zend_string_release_ex(const_ATTR_FOUND_ROWS_name, true); zval const_ATTR_IGNORE_SPACE_value; ZVAL_LONG(&const_ATTR_IGNORE_SPACE_value, PDO_MYSQL_ATTR_IGNORE_SPACE); - zend_string *const_ATTR_IGNORE_SPACE_name = zend_string_init_interned("ATTR_IGNORE_SPACE", sizeof("ATTR_IGNORE_SPACE") - 1, 1); + zend_string *const_ATTR_IGNORE_SPACE_name = zend_string_init_interned("ATTR_IGNORE_SPACE", sizeof("ATTR_IGNORE_SPACE") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_IGNORE_SPACE_name, &const_ATTR_IGNORE_SPACE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_IGNORE_SPACE_name); + zend_string_release_ex(const_ATTR_IGNORE_SPACE_name, true); zval const_ATTR_SSL_KEY_value; ZVAL_LONG(&const_ATTR_SSL_KEY_value, PDO_MYSQL_ATTR_SSL_KEY); - zend_string *const_ATTR_SSL_KEY_name = zend_string_init_interned("ATTR_SSL_KEY", sizeof("ATTR_SSL_KEY") - 1, 1); + zend_string *const_ATTR_SSL_KEY_name = zend_string_init_interned("ATTR_SSL_KEY", sizeof("ATTR_SSL_KEY") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_SSL_KEY_name, &const_ATTR_SSL_KEY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_SSL_KEY_name); + zend_string_release_ex(const_ATTR_SSL_KEY_name, true); zval const_ATTR_SSL_CERT_value; ZVAL_LONG(&const_ATTR_SSL_CERT_value, PDO_MYSQL_ATTR_SSL_CERT); - zend_string *const_ATTR_SSL_CERT_name = zend_string_init_interned("ATTR_SSL_CERT", sizeof("ATTR_SSL_CERT") - 1, 1); + zend_string *const_ATTR_SSL_CERT_name = zend_string_init_interned("ATTR_SSL_CERT", sizeof("ATTR_SSL_CERT") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_SSL_CERT_name, &const_ATTR_SSL_CERT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_SSL_CERT_name); + zend_string_release_ex(const_ATTR_SSL_CERT_name, true); zval const_ATTR_SSL_CA_value; ZVAL_LONG(&const_ATTR_SSL_CA_value, PDO_MYSQL_ATTR_SSL_CA); - zend_string *const_ATTR_SSL_CA_name = zend_string_init_interned("ATTR_SSL_CA", sizeof("ATTR_SSL_CA") - 1, 1); + zend_string *const_ATTR_SSL_CA_name = zend_string_init_interned("ATTR_SSL_CA", sizeof("ATTR_SSL_CA") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_SSL_CA_name, &const_ATTR_SSL_CA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_SSL_CA_name); + zend_string_release_ex(const_ATTR_SSL_CA_name, true); zval const_ATTR_SSL_CAPATH_value; ZVAL_LONG(&const_ATTR_SSL_CAPATH_value, PDO_MYSQL_ATTR_SSL_CAPATH); - zend_string *const_ATTR_SSL_CAPATH_name = zend_string_init_interned("ATTR_SSL_CAPATH", sizeof("ATTR_SSL_CAPATH") - 1, 1); + zend_string *const_ATTR_SSL_CAPATH_name = zend_string_init_interned("ATTR_SSL_CAPATH", sizeof("ATTR_SSL_CAPATH") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_SSL_CAPATH_name, &const_ATTR_SSL_CAPATH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_SSL_CAPATH_name); + zend_string_release_ex(const_ATTR_SSL_CAPATH_name, true); zval const_ATTR_SSL_CIPHER_value; ZVAL_LONG(&const_ATTR_SSL_CIPHER_value, PDO_MYSQL_ATTR_SSL_CIPHER); - zend_string *const_ATTR_SSL_CIPHER_name = zend_string_init_interned("ATTR_SSL_CIPHER", sizeof("ATTR_SSL_CIPHER") - 1, 1); + zend_string *const_ATTR_SSL_CIPHER_name = zend_string_init_interned("ATTR_SSL_CIPHER", sizeof("ATTR_SSL_CIPHER") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_SSL_CIPHER_name, &const_ATTR_SSL_CIPHER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_SSL_CIPHER_name); + zend_string_release_ex(const_ATTR_SSL_CIPHER_name, true); #if MYSQL_VERSION_ID > 50605 || defined(PDO_USE_MYSQLND) zval const_ATTR_SERVER_PUBLIC_KEY_value; ZVAL_LONG(&const_ATTR_SERVER_PUBLIC_KEY_value, PDO_MYSQL_ATTR_SERVER_PUBLIC_KEY); - zend_string *const_ATTR_SERVER_PUBLIC_KEY_name = zend_string_init_interned("ATTR_SERVER_PUBLIC_KEY", sizeof("ATTR_SERVER_PUBLIC_KEY") - 1, 1); + zend_string *const_ATTR_SERVER_PUBLIC_KEY_name = zend_string_init_interned("ATTR_SERVER_PUBLIC_KEY", sizeof("ATTR_SERVER_PUBLIC_KEY") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_SERVER_PUBLIC_KEY_name, &const_ATTR_SERVER_PUBLIC_KEY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_SERVER_PUBLIC_KEY_name); + zend_string_release_ex(const_ATTR_SERVER_PUBLIC_KEY_name, true); #endif zval const_ATTR_MULTI_STATEMENTS_value; ZVAL_LONG(&const_ATTR_MULTI_STATEMENTS_value, PDO_MYSQL_ATTR_MULTI_STATEMENTS); - zend_string *const_ATTR_MULTI_STATEMENTS_name = zend_string_init_interned("ATTR_MULTI_STATEMENTS", sizeof("ATTR_MULTI_STATEMENTS") - 1, 1); + zend_string *const_ATTR_MULTI_STATEMENTS_name = zend_string_init_interned("ATTR_MULTI_STATEMENTS", sizeof("ATTR_MULTI_STATEMENTS") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_MULTI_STATEMENTS_name, &const_ATTR_MULTI_STATEMENTS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_MULTI_STATEMENTS_name); + zend_string_release_ex(const_ATTR_MULTI_STATEMENTS_name, true); #if defined(PDO_USE_MYSQLND) zval const_ATTR_SSL_VERIFY_SERVER_CERT_value; ZVAL_LONG(&const_ATTR_SSL_VERIFY_SERVER_CERT_value, PDO_MYSQL_ATTR_SSL_VERIFY_SERVER_CERT); - zend_string *const_ATTR_SSL_VERIFY_SERVER_CERT_name = zend_string_init_interned("ATTR_SSL_VERIFY_SERVER_CERT", sizeof("ATTR_SSL_VERIFY_SERVER_CERT") - 1, 1); + zend_string *const_ATTR_SSL_VERIFY_SERVER_CERT_name = zend_string_init_interned("ATTR_SSL_VERIFY_SERVER_CERT", sizeof("ATTR_SSL_VERIFY_SERVER_CERT") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_SSL_VERIFY_SERVER_CERT_name, &const_ATTR_SSL_VERIFY_SERVER_CERT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_SSL_VERIFY_SERVER_CERT_name); + zend_string_release_ex(const_ATTR_SSL_VERIFY_SERVER_CERT_name, true); #endif #if MYSQL_VERSION_ID >= 80021 || defined(PDO_USE_MYSQLND) zval const_ATTR_LOCAL_INFILE_DIRECTORY_value; ZVAL_LONG(&const_ATTR_LOCAL_INFILE_DIRECTORY_value, PDO_MYSQL_ATTR_LOCAL_INFILE_DIRECTORY); - zend_string *const_ATTR_LOCAL_INFILE_DIRECTORY_name = zend_string_init_interned("ATTR_LOCAL_INFILE_DIRECTORY", sizeof("ATTR_LOCAL_INFILE_DIRECTORY") - 1, 1); + zend_string *const_ATTR_LOCAL_INFILE_DIRECTORY_name = zend_string_init_interned("ATTR_LOCAL_INFILE_DIRECTORY", sizeof("ATTR_LOCAL_INFILE_DIRECTORY") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_LOCAL_INFILE_DIRECTORY_name, &const_ATTR_LOCAL_INFILE_DIRECTORY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_LOCAL_INFILE_DIRECTORY_name); + zend_string_release_ex(const_ATTR_LOCAL_INFILE_DIRECTORY_name, true); #endif return class_entry; 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/gh20122.phpt b/ext/pdo_mysql/tests/gh20122.phpt new file mode 100644 index 0000000000000..f4abc266335af --- /dev/null +++ b/ext/pdo_mysql/tests/gh20122.phpt @@ -0,0 +1,32 @@ +--TEST-- +GH-20122 (getColumnMeta() for JSON-column in MySQL) +--EXTENSIONS-- +pdo +pdo_mysql +--SKIPIF-- + +--FILE-- +exec('CREATE TABLE test_gh20122 (bar JSON)'); +$db->exec('INSERT INTO test_gh20122 VALUES("[]")'); + +$stmt = $db->query('SELECT * from test_gh20122'); +$meta = $stmt->getColumnMeta(0); + +// Note: JSON is an alias for LONGTEXT on MariaDB! +echo $meta['native_type'], "\n"; +?> +--CLEAN-- +query('DROP TABLE IF EXISTS test_gh20122'); +?> +--EXPECTF-- +%r(JSON|LONGTEXT)%r diff --git a/ext/pdo_mysql/tests/pdo_mysql___construct_options.phpt b/ext/pdo_mysql/tests/pdo_mysql___construct_options.phpt index ba3054247c2b6..910afceb27f08 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 { @@ -73,7 +73,7 @@ MySQLPDOTest::skip(); } if (!is_object($db = new PDO($dsn, $user, $pass, array()))) - printf("[002] Expecting object got %s/%s¸\n", gettype($db), $db); + printf("[002] Expecting object got %s/%s\n", gettype($db), $db); $invalid = 999; if (is_object($db = new PDO($dsn, $user, $pass, array($invalid => true)))) @@ -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..20259b8d49299 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', 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..fd2b6cb5e4a77 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', 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..1d3c7f69fab96 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', 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 8e27d27173c0b..171fb7b7b1e95 100644 --- a/ext/pdo_odbc/odbc_stmt.c +++ b/ext/pdo_odbc/odbc_stmt.c @@ -803,7 +803,7 @@ static int odbc_stmt_set_param(pdo_stmt_t *stmt, zend_long attr, zval *val) return 0; case PDO_ODBC_ATTR_ASSUME_UTF8: - S->assume_utf8 = zval_is_true(val); + S->assume_utf8 = zend_is_true(val); return 0; default: strcpy(S->einfo.last_err_msg, "Unknown Attribute"); 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/pdo_odbc_arginfo.h b/ext/pdo_odbc/pdo_odbc_arginfo.h index 5b1933d7594a0..d8ee0524feb5f 100644 --- a/ext/pdo_odbc/pdo_odbc_arginfo.h +++ b/ext/pdo_odbc/pdo_odbc_arginfo.h @@ -15,33 +15,33 @@ static zend_class_entry *register_class_Pdo_Odbc(zend_class_entry *class_entry_P zval const_ATTR_USE_CURSOR_LIBRARY_value; ZVAL_LONG(&const_ATTR_USE_CURSOR_LIBRARY_value, PDO_ODBC_ATTR_USE_CURSOR_LIBRARY); - zend_string *const_ATTR_USE_CURSOR_LIBRARY_name = zend_string_init_interned("ATTR_USE_CURSOR_LIBRARY", sizeof("ATTR_USE_CURSOR_LIBRARY") - 1, 1); + zend_string *const_ATTR_USE_CURSOR_LIBRARY_name = zend_string_init_interned("ATTR_USE_CURSOR_LIBRARY", sizeof("ATTR_USE_CURSOR_LIBRARY") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_USE_CURSOR_LIBRARY_name, &const_ATTR_USE_CURSOR_LIBRARY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_USE_CURSOR_LIBRARY_name); + zend_string_release_ex(const_ATTR_USE_CURSOR_LIBRARY_name, true); zval const_ATTR_ASSUME_UTF8_value; ZVAL_LONG(&const_ATTR_ASSUME_UTF8_value, PDO_ODBC_ATTR_ASSUME_UTF8); - zend_string *const_ATTR_ASSUME_UTF8_name = zend_string_init_interned("ATTR_ASSUME_UTF8", sizeof("ATTR_ASSUME_UTF8") - 1, 1); + zend_string *const_ATTR_ASSUME_UTF8_name = zend_string_init_interned("ATTR_ASSUME_UTF8", sizeof("ATTR_ASSUME_UTF8") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_ASSUME_UTF8_name, &const_ATTR_ASSUME_UTF8_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_ASSUME_UTF8_name); + zend_string_release_ex(const_ATTR_ASSUME_UTF8_name, true); zval const_SQL_USE_IF_NEEDED_value; ZVAL_LONG(&const_SQL_USE_IF_NEEDED_value, SQL_CUR_USE_IF_NEEDED); - zend_string *const_SQL_USE_IF_NEEDED_name = zend_string_init_interned("SQL_USE_IF_NEEDED", sizeof("SQL_USE_IF_NEEDED") - 1, 1); + zend_string *const_SQL_USE_IF_NEEDED_name = zend_string_init_interned("SQL_USE_IF_NEEDED", sizeof("SQL_USE_IF_NEEDED") - 1, true); zend_declare_typed_class_constant(class_entry, const_SQL_USE_IF_NEEDED_name, &const_SQL_USE_IF_NEEDED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SQL_USE_IF_NEEDED_name); + zend_string_release_ex(const_SQL_USE_IF_NEEDED_name, true); zval const_SQL_USE_DRIVER_value; ZVAL_LONG(&const_SQL_USE_DRIVER_value, SQL_CUR_USE_DRIVER); - zend_string *const_SQL_USE_DRIVER_name = zend_string_init_interned("SQL_USE_DRIVER", sizeof("SQL_USE_DRIVER") - 1, 1); + zend_string *const_SQL_USE_DRIVER_name = zend_string_init_interned("SQL_USE_DRIVER", sizeof("SQL_USE_DRIVER") - 1, true); zend_declare_typed_class_constant(class_entry, const_SQL_USE_DRIVER_name, &const_SQL_USE_DRIVER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SQL_USE_DRIVER_name); + zend_string_release_ex(const_SQL_USE_DRIVER_name, true); zval const_SQL_USE_ODBC_value; ZVAL_LONG(&const_SQL_USE_ODBC_value, SQL_CUR_USE_ODBC); - zend_string *const_SQL_USE_ODBC_name = zend_string_init_interned("SQL_USE_ODBC", sizeof("SQL_USE_ODBC") - 1, 1); + zend_string *const_SQL_USE_ODBC_name = zend_string_init_interned("SQL_USE_ODBC", sizeof("SQL_USE_ODBC") - 1, true); zend_declare_typed_class_constant(class_entry, const_SQL_USE_ODBC_name, &const_SQL_USE_ODBC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SQL_USE_ODBC_name); + zend_string_release_ex(const_SQL_USE_ODBC_name, true); return class_entry; } 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..296207471a198 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) @@ -90,47 +90,79 @@ static zend_class_entry *register_class_Pdo_Pgsql(zend_class_entry *class_entry_ zval const_ATTR_DISABLE_PREPARES_value; ZVAL_LONG(&const_ATTR_DISABLE_PREPARES_value, PDO_PGSQL_ATTR_DISABLE_PREPARES); - zend_string *const_ATTR_DISABLE_PREPARES_name = zend_string_init_interned("ATTR_DISABLE_PREPARES", sizeof("ATTR_DISABLE_PREPARES") - 1, 1); + zend_string *const_ATTR_DISABLE_PREPARES_name = zend_string_init_interned("ATTR_DISABLE_PREPARES", sizeof("ATTR_DISABLE_PREPARES") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_DISABLE_PREPARES_name, &const_ATTR_DISABLE_PREPARES_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_DISABLE_PREPARES_name); + zend_string_release_ex(const_ATTR_DISABLE_PREPARES_name, true); #if defined(HAVE_PG_RESULT_MEMORY_SIZE) zval const_ATTR_RESULT_MEMORY_SIZE_value; ZVAL_LONG(&const_ATTR_RESULT_MEMORY_SIZE_value, PDO_PGSQL_ATTR_RESULT_MEMORY_SIZE); - zend_string *const_ATTR_RESULT_MEMORY_SIZE_name = zend_string_init_interned("ATTR_RESULT_MEMORY_SIZE", sizeof("ATTR_RESULT_MEMORY_SIZE") - 1, 1); + zend_string *const_ATTR_RESULT_MEMORY_SIZE_name = zend_string_init_interned("ATTR_RESULT_MEMORY_SIZE", sizeof("ATTR_RESULT_MEMORY_SIZE") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_RESULT_MEMORY_SIZE_name, &const_ATTR_RESULT_MEMORY_SIZE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_RESULT_MEMORY_SIZE_name); + zend_string_release_ex(const_ATTR_RESULT_MEMORY_SIZE_name, true); #endif 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_string_release(const_TRANSACTION_IDLE_name); + zend_string *const_TRANSACTION_IDLE_name = zend_string_init_interned("TRANSACTION_IDLE", sizeof("TRANSACTION_IDLE") - 1, true); + 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_ex(const_TRANSACTION_IDLE_name, true); 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_string_release(const_TRANSACTION_ACTIVE_name); + zend_string *const_TRANSACTION_ACTIVE_name = zend_string_init_interned("TRANSACTION_ACTIVE", sizeof("TRANSACTION_ACTIVE") - 1, true); + 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_ex(const_TRANSACTION_ACTIVE_name, true); 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_string_release(const_TRANSACTION_INTRANS_name); + zend_string *const_TRANSACTION_INTRANS_name = zend_string_init_interned("TRANSACTION_INTRANS", sizeof("TRANSACTION_INTRANS") - 1, true); + 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_ex(const_TRANSACTION_INTRANS_name, true); 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_string_release(const_TRANSACTION_INERROR_name); + zend_string *const_TRANSACTION_INERROR_name = zend_string_init_interned("TRANSACTION_INERROR", sizeof("TRANSACTION_INERROR") - 1, true); + 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_ex(const_TRANSACTION_INERROR_name, true); 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_string_release(const_TRANSACTION_UNKNOWN_name); + zend_string *const_TRANSACTION_UNKNOWN_name = zend_string_init_interned("TRANSACTION_UNKNOWN", sizeof("TRANSACTION_UNKNOWN") - 1, true); + 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_ex(const_TRANSACTION_UNKNOWN_name, true); + + + 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 35b86a3588fdc..44f70e00236d2 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; @@ -1334,6 +1340,20 @@ static const zend_function_entry *pdo_pgsql_get_driver_methods(pdo_dbh_t *dbh, i } } +static void pdo_pgsql_request_shutdown(pdo_dbh_t *dbh) +{ + PGresult *res; + pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; + + if(H->server) { + res = PQexec(H->server, "DISCARD ALL"); + + if(res) { + PQclear(res); + } + } +} + static bool pdo_pgsql_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val) { bool bval; @@ -1377,7 +1397,7 @@ static const struct pdo_dbh_methods pgsql_methods = { pdo_pgsql_get_attribute, pdo_pgsql_check_liveness, /* check_liveness */ pdo_pgsql_get_driver_methods, /* get_driver_methods */ - NULL, + pdo_pgsql_request_shutdown, pgsql_handle_in_transaction, NULL, /* get_gc */ pdo_pgsql_scanner diff --git a/ext/pdo_pgsql/pgsql_statement.c b/ext/pdo_pgsql/pgsql_statement.c index 3485bd8df0024..426a878d8eff7 100644 --- a/ext/pdo_pgsql/pgsql_statement.c +++ b/ext/pdo_pgsql/pgsql_statement.c @@ -219,7 +219,7 @@ static int pgsql_stmt_execute(pdo_stmt_t *stmt) PQclear(S->result); /* the cursor was declared correctly */ - S->is_prepared = 1; + S->is_prepared = true; /* fetch to be able to get the number of tuples later, but don't advance the cursor pointer */ spprintf(&q, 0, "FETCH FORWARD 0 FROM %s", S->cursor_name); @@ -240,7 +240,7 @@ static int pgsql_stmt_execute(pdo_stmt_t *stmt) case PGRES_COMMAND_OK: case PGRES_TUPLES_OK: /* it worked */ - S->is_prepared = 1; + S->is_prepared = true; PQclear(S->result); S->result = NULL; break; @@ -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-8xr5-qppj-gvwj.phpt b/ext/pdo_pgsql/tests/ghsa-8xr5-qppj-gvwj.phpt new file mode 100644 index 0000000000000..736354cab13cb --- /dev/null +++ b/ext/pdo_pgsql/tests/ghsa-8xr5-qppj-gvwj.phpt @@ -0,0 +1,28 @@ +--TEST-- +#GHSA-8xr5-qppj-gvwj: NULL Pointer Derefernce for failed user input quoting +--EXTENSIONS-- +pdo +pdo_pgsql +--SKIPIF-- + +--FILE-- +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true); + +$sql = "SELECT * FROM users where username = :username"; +$stmt = $db->prepare($sql); + +$p1 = "alice\x99"; +var_dump($stmt->execute(['username' => $p1])); + +?> +--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/session_state_reset.phpt b/ext/pdo_pgsql/tests/session_state_reset.phpt new file mode 100644 index 0000000000000..ad892bb0da52e --- /dev/null +++ b/ext/pdo_pgsql/tests/session_state_reset.phpt @@ -0,0 +1,55 @@ +--TEST-- +Persistent connections: session state reset when performing disconnect-equivalent processing (general case) +--EXTENSIONS-- +pdo_pgsql +--SKIPIF-- + +--FILE-- + true])); + +require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc'; + +$pdo1 = PDOTest::test_factory(__DIR__ . '/common.phpt'); + +$pid1 = (int)$pdo1 + ->query('select pg_backend_pid()::int;') + ->fetchColumn(0); + +$defaultValue = (int)$pdo1 + ->query('show log_min_duration_statement;') + ->fetchColumn(0); + +$setValue = $defaultValue + 1; + +$pdo1->exec("set log_min_duration_statement = {$setValue};"); + +$pdo1 = null; + +$pdo2 = PDOTest::test_factory(__DIR__ . '/common.phpt'); + +$pid2 = (int)$pdo2 + ->query('select pg_backend_pid()::int;') + ->fetchColumn(0); + +assert($pid1 === $pid2); + +$expectedValue = (int)$pdo2 + ->query('show log_min_duration_statement;') + ->fetchColumn(0); + +echo "defaultValue: {$defaultValue}\n"; +echo "setValue: {$setValue}\n"; +echo "expectedValue: {$expectedValue}\n"; +echo "expected value should be reset to default: " . (($expectedValue === $defaultValue) ? 'success' : 'failure') . "\n"; + +?> +--EXPECTF-- +defaultValue: %i +setValue: %d +expectedValue: %i +expected value should be reset to default: success diff --git a/ext/pdo_pgsql/tests/session_state_reset_advisory_lock.phpt b/ext/pdo_pgsql/tests/session_state_reset_advisory_lock.phpt new file mode 100644 index 0000000000000..3435f6b7b402f --- /dev/null +++ b/ext/pdo_pgsql/tests/session_state_reset_advisory_lock.phpt @@ -0,0 +1,51 @@ +--TEST-- +Persistent connections: session state reset when performing disconnect-equivalent processing (advisory lock case) +--EXTENSIONS-- +pdo_pgsql +--SKIPIF-- + +--FILE-- + true])); + +require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc'; + +$pdo1 = PDOTest::test_factory(__DIR__ . '/common.phpt'); + +$pid1 = (int)$pdo1 + ->query('select pg_backend_pid()::int;') + ->fetchColumn(0); + +$lockResult1 = (bool)$pdo1 + ->query('select pg_try_advisory_lock(42)::int;') + ->fetchColumn(0); + +$pdo1 = null; + +$dsn = getenv('PDO_PGSQL_TEST_DSN'); +$dsn .= ';'; +putenv('PDO_PGSQL_TEST_DSN='.$dsn); + +$pdo2 = PDOTest::test_factory(__DIR__ . '/common.phpt'); + +$pid2 = (int)$pdo2 + ->query('select pg_backend_pid()::int;') + ->fetchColumn(0); + +assert($pid1 !== $pid2); + +$lockResult2 = (bool)$pdo2 + ->query('select pg_try_advisory_lock(42)::int;') + ->fetchColumn(0); + +echo "lock1: " . ($lockResult1 ? 'success' : 'failure') . "\n"; +echo "lock2: " . ($lockResult2 ? 'success' : 'failure') . "\n"; + +?> +--EXPECT-- +lock1: success +lock2: success diff --git a/ext/pdo_pgsql/tests/session_state_reset_after_interrupted.phpt b/ext/pdo_pgsql/tests/session_state_reset_after_interrupted.phpt new file mode 100644 index 0000000000000..fdafe8a00fc39 --- /dev/null +++ b/ext/pdo_pgsql/tests/session_state_reset_after_interrupted.phpt @@ -0,0 +1,52 @@ +--TEST-- +Persistent connections: session state reset after backend termination (interrupted case) +--EXTENSIONS-- +pdo_pgsql +--SKIPIF-- + +--FILE-- + true])); + +require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc'; + +$pdo1 = PDOTest::test_factory(__DIR__ . '/common.phpt'); + +$pid1 = (int)$pdo1 + ->query('select pg_backend_pid()::int;') + ->fetchColumn(0); + +$pid1 = (int)$pdo1 + ->query('select pg_backend_pid()::int;') + ->fetchColumn(0); + +$dsn = getenv('PDO_PGSQL_TEST_DSN'); +$dsn .= ';'; +putenv('PDO_PGSQL_TEST_DSN='.$dsn); + +$pdo2 = PDOTest::test_factory(__DIR__ . '/common.phpt'); + +$pid2 = (int)$pdo2 + ->query('select pg_backend_pid()::int;') + ->fetchColumn(0); + +assert($pid1 !== $pid2); + +$terminateResult = (bool)$pdo2 + ->query("select pg_terminate_backend({$pid1})::int") + ->fetchColumn(0); + +// Disconnect after being terminated by another connection +$pdo1 = null; + +echo 'pid of pdo1: ' . $pid1 . "\n"; +echo 'terminate result of pdo1 by pdo2: ' . ($terminateResult ? 'success' : 'failure') . "\n"; + +?> +--EXPECTF-- +pid of pdo1: %d +terminate result of pdo1 by pdo2: success 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..f50cdacdc2ec6 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) @@ -69,96 +69,120 @@ static zend_class_entry *register_class_Pdo_Sqlite(zend_class_entry *class_entry zval const_DETERMINISTIC_value; ZVAL_LONG(&const_DETERMINISTIC_value, SQLITE_DETERMINISTIC); - zend_string *const_DETERMINISTIC_name = zend_string_init_interned("DETERMINISTIC", sizeof("DETERMINISTIC") - 1, 1); + zend_string *const_DETERMINISTIC_name = zend_string_init_interned("DETERMINISTIC", sizeof("DETERMINISTIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_DETERMINISTIC_name, &const_DETERMINISTIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DETERMINISTIC_name); + zend_string_release_ex(const_DETERMINISTIC_name, true); #endif zval const_OPEN_READONLY_value; ZVAL_LONG(&const_OPEN_READONLY_value, SQLITE_OPEN_READONLY); - zend_string *const_OPEN_READONLY_name = zend_string_init_interned("OPEN_READONLY", sizeof("OPEN_READONLY") - 1, 1); + zend_string *const_OPEN_READONLY_name = zend_string_init_interned("OPEN_READONLY", sizeof("OPEN_READONLY") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPEN_READONLY_name, &const_OPEN_READONLY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPEN_READONLY_name); + zend_string_release_ex(const_OPEN_READONLY_name, true); zval const_OPEN_READWRITE_value; ZVAL_LONG(&const_OPEN_READWRITE_value, SQLITE_OPEN_READWRITE); - zend_string *const_OPEN_READWRITE_name = zend_string_init_interned("OPEN_READWRITE", sizeof("OPEN_READWRITE") - 1, 1); + zend_string *const_OPEN_READWRITE_name = zend_string_init_interned("OPEN_READWRITE", sizeof("OPEN_READWRITE") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPEN_READWRITE_name, &const_OPEN_READWRITE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPEN_READWRITE_name); + zend_string_release_ex(const_OPEN_READWRITE_name, true); zval const_OPEN_CREATE_value; ZVAL_LONG(&const_OPEN_CREATE_value, SQLITE_OPEN_CREATE); - zend_string *const_OPEN_CREATE_name = zend_string_init_interned("OPEN_CREATE", sizeof("OPEN_CREATE") - 1, 1); + zend_string *const_OPEN_CREATE_name = zend_string_init_interned("OPEN_CREATE", sizeof("OPEN_CREATE") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPEN_CREATE_name, &const_OPEN_CREATE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPEN_CREATE_name); + zend_string_release_ex(const_OPEN_CREATE_name, true); zval const_ATTR_OPEN_FLAGS_value; ZVAL_LONG(&const_ATTR_OPEN_FLAGS_value, PDO_SQLITE_ATTR_OPEN_FLAGS); - zend_string *const_ATTR_OPEN_FLAGS_name = zend_string_init_interned("ATTR_OPEN_FLAGS", sizeof("ATTR_OPEN_FLAGS") - 1, 1); + zend_string *const_ATTR_OPEN_FLAGS_name = zend_string_init_interned("ATTR_OPEN_FLAGS", sizeof("ATTR_OPEN_FLAGS") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_OPEN_FLAGS_name, &const_ATTR_OPEN_FLAGS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_OPEN_FLAGS_name); + zend_string_release_ex(const_ATTR_OPEN_FLAGS_name, true); zval const_ATTR_READONLY_STATEMENT_value; ZVAL_LONG(&const_ATTR_READONLY_STATEMENT_value, PDO_SQLITE_ATTR_READONLY_STATEMENT); - zend_string *const_ATTR_READONLY_STATEMENT_name = zend_string_init_interned("ATTR_READONLY_STATEMENT", sizeof("ATTR_READONLY_STATEMENT") - 1, 1); + zend_string *const_ATTR_READONLY_STATEMENT_name = zend_string_init_interned("ATTR_READONLY_STATEMENT", sizeof("ATTR_READONLY_STATEMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_READONLY_STATEMENT_name, &const_ATTR_READONLY_STATEMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_READONLY_STATEMENT_name); + zend_string_release_ex(const_ATTR_READONLY_STATEMENT_name, true); zval const_ATTR_EXTENDED_RESULT_CODES_value; ZVAL_LONG(&const_ATTR_EXTENDED_RESULT_CODES_value, PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES); - zend_string *const_ATTR_EXTENDED_RESULT_CODES_name = zend_string_init_interned("ATTR_EXTENDED_RESULT_CODES", sizeof("ATTR_EXTENDED_RESULT_CODES") - 1, 1); + zend_string *const_ATTR_EXTENDED_RESULT_CODES_name = zend_string_init_interned("ATTR_EXTENDED_RESULT_CODES", sizeof("ATTR_EXTENDED_RESULT_CODES") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_EXTENDED_RESULT_CODES_name, &const_ATTR_EXTENDED_RESULT_CODES_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_EXTENDED_RESULT_CODES_name); + zend_string_release_ex(const_ATTR_EXTENDED_RESULT_CODES_name, true); zval const_ATTR_BUSY_STATEMENT_value; ZVAL_LONG(&const_ATTR_BUSY_STATEMENT_value, PDO_SQLITE_ATTR_BUSY_STATEMENT); - zend_string *const_ATTR_BUSY_STATEMENT_name = zend_string_init_interned("ATTR_BUSY_STATEMENT", sizeof("ATTR_BUSY_STATEMENT") - 1, 1); + zend_string *const_ATTR_BUSY_STATEMENT_name = zend_string_init_interned("ATTR_BUSY_STATEMENT", sizeof("ATTR_BUSY_STATEMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTR_BUSY_STATEMENT_name, &const_ATTR_BUSY_STATEMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTR_BUSY_STATEMENT_name); + zend_string_release_ex(const_ATTR_BUSY_STATEMENT_name, true); zval const_ATTR_EXPLAIN_STATEMENT_value; ZVAL_LONG(&const_ATTR_EXPLAIN_STATEMENT_value, PDO_SQLITE_ATTR_EXPLAIN_STATEMENT); - zend_string *const_ATTR_EXPLAIN_STATEMENT_name = zend_string_init_interned("ATTR_EXPLAIN_STATEMENT", sizeof("ATTR_EXPLAIN_STATEMENT") - 1, 1); + zend_string *const_ATTR_EXPLAIN_STATEMENT_name = zend_string_init_interned("ATTR_EXPLAIN_STATEMENT", sizeof("ATTR_EXPLAIN_STATEMENT") - 1, true); 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); + zend_string_release_ex(const_ATTR_EXPLAIN_STATEMENT_name, true); + + 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, true); + 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_ex(const_ATTR_TRANSACTION_MODE_name, true); + + 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, true); + 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_ex(const_TRANSACTION_MODE_DEFERRED_name, true); + + 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, true); + 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_ex(const_TRANSACTION_MODE_IMMEDIATE_name, true); + + 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, true); + 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_ex(const_TRANSACTION_MODE_EXCLUSIVE_name, true); #if SQLITE_VERSION_NUMBER >= 3043000 zval const_EXPLAIN_MODE_PREPARED_value; ZVAL_LONG(&const_EXPLAIN_MODE_PREPARED_value, 0); - zend_string *const_EXPLAIN_MODE_PREPARED_name = zend_string_init_interned("EXPLAIN_MODE_PREPARED", sizeof("EXPLAIN_MODE_PREPARED") - 1, 1); + zend_string *const_EXPLAIN_MODE_PREPARED_name = zend_string_init_interned("EXPLAIN_MODE_PREPARED", sizeof("EXPLAIN_MODE_PREPARED") - 1, true); zend_declare_typed_class_constant(class_entry, const_EXPLAIN_MODE_PREPARED_name, &const_EXPLAIN_MODE_PREPARED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EXPLAIN_MODE_PREPARED_name); + zend_string_release_ex(const_EXPLAIN_MODE_PREPARED_name, true); zval const_EXPLAIN_MODE_EXPLAIN_value; ZVAL_LONG(&const_EXPLAIN_MODE_EXPLAIN_value, 1); - zend_string *const_EXPLAIN_MODE_EXPLAIN_name = zend_string_init_interned("EXPLAIN_MODE_EXPLAIN", sizeof("EXPLAIN_MODE_EXPLAIN") - 1, 1); + zend_string *const_EXPLAIN_MODE_EXPLAIN_name = zend_string_init_interned("EXPLAIN_MODE_EXPLAIN", sizeof("EXPLAIN_MODE_EXPLAIN") - 1, true); zend_declare_typed_class_constant(class_entry, const_EXPLAIN_MODE_EXPLAIN_name, &const_EXPLAIN_MODE_EXPLAIN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EXPLAIN_MODE_EXPLAIN_name); + zend_string_release_ex(const_EXPLAIN_MODE_EXPLAIN_name, true); zval const_EXPLAIN_MODE_EXPLAIN_QUERY_PLAN_value; ZVAL_LONG(&const_EXPLAIN_MODE_EXPLAIN_QUERY_PLAN_value, 2); - zend_string *const_EXPLAIN_MODE_EXPLAIN_QUERY_PLAN_name = zend_string_init_interned("EXPLAIN_MODE_EXPLAIN_QUERY_PLAN", sizeof("EXPLAIN_MODE_EXPLAIN_QUERY_PLAN") - 1, 1); + zend_string *const_EXPLAIN_MODE_EXPLAIN_QUERY_PLAN_name = zend_string_init_interned("EXPLAIN_MODE_EXPLAIN_QUERY_PLAN", sizeof("EXPLAIN_MODE_EXPLAIN_QUERY_PLAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_EXPLAIN_MODE_EXPLAIN_QUERY_PLAN_name, &const_EXPLAIN_MODE_EXPLAIN_QUERY_PLAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EXPLAIN_MODE_EXPLAIN_QUERY_PLAN_name); + zend_string_release_ex(const_EXPLAIN_MODE_EXPLAIN_QUERY_PLAN_name, true); #endif zval const_OK_value; ZVAL_LONG(&const_OK_value, SQLITE_OK); - zend_string *const_OK_name = zend_string_init_interned("OK", sizeof("OK") - 1, 1); + zend_string *const_OK_name = zend_string_init_interned("OK", sizeof("OK") - 1, true); zend_declare_typed_class_constant(class_entry, const_OK_name, &const_OK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OK_name); + zend_string_release_ex(const_OK_name, true); zval const_DENY_value; ZVAL_LONG(&const_DENY_value, SQLITE_DENY); - zend_string *const_DENY_name = zend_string_init_interned("DENY", sizeof("DENY") - 1, 1); + zend_string *const_DENY_name = zend_string_init_interned("DENY", sizeof("DENY") - 1, true); zend_declare_typed_class_constant(class_entry, const_DENY_name, &const_DENY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DENY_name); + zend_string_release_ex(const_DENY_name, true); zval const_IGNORE_value; ZVAL_LONG(&const_IGNORE_value, SQLITE_IGNORE); - zend_string *const_IGNORE_name = zend_string_init_interned("IGNORE", sizeof("IGNORE") - 1, 1); + zend_string *const_IGNORE_name = zend_string_init_interned("IGNORE", sizeof("IGNORE") - 1, true); zend_declare_typed_class_constant(class_entry, const_IGNORE_name, &const_IGNORE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IGNORE_name); + zend_string_release_ex(const_IGNORE_name, true); return class_entry; } 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/sqlite_statement.c b/ext/pdo_sqlite/sqlite_statement.c index e9e7a0cc78609..ffb8c1ad4b3c8 100644 --- a/ext/pdo_sqlite/sqlite_statement.c +++ b/ext/pdo_sqlite/sqlite_statement.c @@ -335,7 +335,6 @@ static int pdo_sqlite_stmt_col_meta(pdo_stmt_t *stmt, zend_long colno, zval *ret case SQLITE_BLOB: add_next_index_string(&flags, "blob"); - /* TODO Check this is correct */ ZEND_FALLTHROUGH; case SQLITE_TEXT: add_assoc_str(return_value, "native_type", ZSTR_KNOWN(ZEND_STR_STRING)); 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/gh20095.phpt b/ext/pdo_sqlite/tests/gh20095.phpt new file mode 100644 index 0000000000000..8d691f99ee2aa --- /dev/null +++ b/ext/pdo_sqlite/tests/gh20095.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-20095: Incorrect class name in deprecation message for PDO mixins +--EXTENSIONS-- +pdo_sqlite +--FILE-- +sqliteCreateFunction('my_test', [$this, "test"]); + } +} + +$pdo = new Foo('sqlite::memory:'); +$pdo->register(); +$pdo->query("SELECT my_test()"); + +?> +--EXPECTF-- +Deprecated: Method PDO::sqliteCreateFunction() is deprecated since 8.5, use Pdo\Sqlite::createFunction() instead in %s on line %d +foo 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 3d180e3d6b9da..e3d8cb82ece91 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; @@ -1214,28 +1223,55 @@ PHP_FUNCTION(pg_query) } } -static void _php_pgsql_free_params(char **params, int num_params) +/* The char pointer MUST refer to the char* of a zend_string struct */ +static void php_pgsql_zend_string_release_from_char_pointer(char *ptr) { + zend_string_release((zend_string*) (ptr - XtOffsetOf(zend_string, val))); +} + +static void _php_pgsql_free_params(char **params, uint32_t num_params) { - if (num_params > 0) { - int i; - for (i = 0; i < num_params; i++) { - if (params[i]) { - efree(params[i]); - } + for (uint32_t i = 0; i < num_params; i++) { + if (params[i]) { + php_pgsql_zend_string_release_from_char_pointer(params[i]); } - efree(params); } + efree(params); +} + +static char **php_pgsql_make_arguments(const HashTable *param_arr, int *num_params) +{ + /* This conversion is safe because of the limit of number of elements in a table. */ + *num_params = (int) zend_hash_num_elements(param_arr); + char **params = safe_emalloc(sizeof(char *), *num_params, 0); + uint32_t i = 0; + + ZEND_HASH_FOREACH_VAL(param_arr, zval *tmp) { + ZVAL_DEREF(tmp); + if (Z_TYPE_P(tmp) == IS_NULL) { + params[i] = NULL; + } else { + zend_string *param_str = zval_try_get_string(tmp); + if (!param_str) { + _php_pgsql_free_params(params, i); + return NULL; + } + params[i] = ZSTR_VAL(param_str); + } + i++; + } ZEND_HASH_FOREACH_END(); + + return params; } /* Execute a query */ PHP_FUNCTION(pg_query_params) { zval *pgsql_link = NULL; - zval *pv_param_arr, *tmp; + zval *pv_param_arr; char *query; size_t query_len; bool leftover = false; - int num_params = 0; + int num_params; char **params = NULL; pgsql_link_handle *link; PGconn *pgsql; @@ -1279,26 +1315,9 @@ PHP_FUNCTION(pg_query_params) php_error_docref(NULL, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first"); } - num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr)); - if (num_params > 0) { - int i = 0; - params = (char **)safe_emalloc(sizeof(char *), num_params, 0); - - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pv_param_arr), tmp) { - ZVAL_DEREF(tmp); - if (Z_TYPE_P(tmp) == IS_NULL) { - params[i] = NULL; - } else { - zend_string *param_str = zval_try_get_string(tmp); - if (!param_str) { - _php_pgsql_free_params(params, i); - RETURN_THROWS(); - } - params[i] = estrndup(ZSTR_VAL(param_str), ZSTR_LEN(param_str)); - zend_string_release(param_str); - } - i++; - } ZEND_HASH_FOREACH_END(); + params = php_pgsql_make_arguments(Z_ARRVAL_P(pv_param_arr), &num_params); + if (UNEXPECTED(!params)) { + RETURN_THROWS(); } pgsql_result = PQexecParams(pgsql, query, num_params, @@ -1433,11 +1452,11 @@ PHP_FUNCTION(pg_prepare) PHP_FUNCTION(pg_execute) { zval *pgsql_link = NULL; - zval *pv_param_arr, *tmp; + zval *pv_param_arr; char *stmtname; size_t stmtname_len; bool leftover = false; - int num_params = 0; + int num_params; char **params = NULL; PGconn *pgsql; pgsql_link_handle *link; @@ -1481,25 +1500,9 @@ PHP_FUNCTION(pg_execute) php_error_docref(NULL, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first"); } - num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr)); - if (num_params > 0) { - int i = 0; - params = (char **)safe_emalloc(sizeof(char *), num_params, 0); - - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pv_param_arr), tmp) { - ZVAL_DEREF(tmp); - if (Z_TYPE_P(tmp) == IS_NULL) { - params[i] = NULL; - } else { - zend_string *tmp_str; - zend_string *str = zval_get_tmp_string(tmp, &tmp_str); - - params[i] = estrndup(ZSTR_VAL(str), ZSTR_LEN(str)); - zend_tmp_string_release(tmp_str); - } - - i++; - } ZEND_HASH_FOREACH_END(); + params = php_pgsql_make_arguments(Z_ARRVAL_P(pv_param_arr), &num_params); + if (UNEXPECTED(!params)) { + RETURN_THROWS(); } pgsql_result = PQexecPrepared(pgsql, stmtname, num_params, @@ -1974,60 +1977,37 @@ PHP_FUNCTION(pg_fetch_result) } /* }}} */ -/* {{{ void php_pgsql_fetch_hash */ -static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, zend_long result_type, int into_object) +/* Returns true when the return_value was populated with an array, + * otherwise when an error occurs false is returned, in which case the return_value is NOT initialized */ +static bool php_pgsql_fetch_hash(zval *return_value, const zval *result, zend_long row, bool row_is_null, zend_long result_type) { - zval *result; PGresult *pgsql_result; pgsql_result_handle *pg_result; int i, num_fields, pgsql_row; - zend_long row; - bool row_is_null = true; char *field_name; - HashTable *ctor_params = NULL; - zend_class_entry *ce = NULL; - - if (into_object) { - ZEND_PARSE_PARAMETERS_START(1, 4) - Z_PARAM_OBJECT_OF_CLASS(result, pgsql_result_ce) - Z_PARAM_OPTIONAL - Z_PARAM_LONG_OR_NULL(row, row_is_null) - Z_PARAM_CLASS(ce) - Z_PARAM_ARRAY_HT(ctor_params) - ZEND_PARSE_PARAMETERS_END(); - - if (!ce) { - ce = zend_standard_class_def; - } - result_type = PGSQL_ASSOC; - } else { - ZEND_PARSE_PARAMETERS_START(1, 3) - Z_PARAM_OBJECT_OF_CLASS(result, pgsql_result_ce) - Z_PARAM_OPTIONAL - Z_PARAM_LONG_OR_NULL(row, row_is_null) - Z_PARAM_LONG(result_type) - ZEND_PARSE_PARAMETERS_END(); - } if (!row_is_null && row < 0) { zend_argument_value_error(2, "must be greater than or equal to 0"); - RETURN_THROWS(); + return false; } if (!(result_type & PGSQL_BOTH)) { zend_argument_value_error(3, "must be one of PGSQL_ASSOC, PGSQL_NUM, or PGSQL_BOTH"); - RETURN_THROWS(); + return false; } pg_result = Z_PGSQL_RESULT_P(result); - CHECK_PGSQL_RESULT(pg_result); + if (UNEXPECTED(pg_result->result == NULL)) { + zend_throw_error(NULL, "PostgreSQL result has already been closed"); + return false; + } pgsql_result = pg_result->result; if (!row_is_null) { if (row >= PQntuples(pgsql_result)) { php_error_docref(NULL, E_WARNING, "Unable to jump to row " ZEND_LONG_FMT " on PostgreSQL result index " ZEND_LONG_FMT, row, Z_LVAL_P(result)); - RETURN_FALSE; + return false; } pgsql_row = (int)row; pg_result->row = pgsql_row; @@ -2035,7 +2015,7 @@ static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, zend_long result_ /* If 2nd param is NULL, use internal row counter to access next row */ pgsql_row = pg_result->row; if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) { - RETURN_FALSE; + return false; } pg_result->row++; } @@ -2051,7 +2031,7 @@ static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, zend_long result_ add_assoc_null(return_value, field_name); } } else { - char *element = PQgetvalue(pgsql_result, pgsql_row, i); + const char *element = PQgetvalue(pgsql_result, pgsql_row, i); if (element) { const size_t element_len = strlen(element); @@ -2066,63 +2046,126 @@ static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, zend_long result_ } } } - - if (into_object) { - zval dataset; - - ZVAL_COPY_VALUE(&dataset, return_value); - object_init_ex(return_value, ce); - if (!ce->default_properties_count && !ce->__set) { - Z_OBJ_P(return_value)->properties = Z_ARR(dataset); - } else { - zend_merge_properties(return_value, Z_ARRVAL(dataset)); - zval_ptr_dtor(&dataset); - } - - if (ce->constructor) { - zend_call_known_function(ce->constructor, Z_OBJ_P(return_value), Z_OBJCE_P(return_value), - /* retval */ NULL, /* argc */ 0, /* params */ NULL, ctor_params); - } else if (ctor_params && zend_hash_num_elements(ctor_params) > 0) { - zend_argument_value_error(3, - "must be empty when the specified class (%s) does not have a constructor", - ZSTR_VAL(ce->name) - ); - } - } + return true; } -/* }}} */ /* {{{ Get a row as an enumerated array */ PHP_FUNCTION(pg_fetch_row) { - php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_NUM, 0); + zval *result; + zend_long row = 0; + bool row_is_null = true; + zend_long result_type = PGSQL_NUM; + + ZEND_PARSE_PARAMETERS_START(1, 3) + Z_PARAM_OBJECT_OF_CLASS(result, pgsql_result_ce) + Z_PARAM_OPTIONAL + Z_PARAM_LONG_OR_NULL(row, row_is_null) + Z_PARAM_LONG(result_type) + ZEND_PARSE_PARAMETERS_END(); + + if (UNEXPECTED(!php_pgsql_fetch_hash(return_value, result, row, row_is_null, result_type))) { + /* Either an exception is thrown, or we return false */ + RETURN_FALSE; + } } /* }}} */ /* {{{ Fetch a row as an assoc array */ PHP_FUNCTION(pg_fetch_assoc) { - /* pg_fetch_assoc() is added from PHP 4.3.0. It should raise error, when - there is 3rd parameter */ - if (ZEND_NUM_ARGS() > 2) - WRONG_PARAM_COUNT; - php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_ASSOC, 0); + zval *result; + zend_long row = 0; + bool row_is_null = true; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_OBJECT_OF_CLASS(result, pgsql_result_ce) + Z_PARAM_OPTIONAL + Z_PARAM_LONG_OR_NULL(row, row_is_null) + ZEND_PARSE_PARAMETERS_END(); + + if (UNEXPECTED(!php_pgsql_fetch_hash(return_value, result, row, row_is_null, PGSQL_ASSOC))) { + /* Either an exception is thrown, or we return false */ + RETURN_FALSE; + } } /* }}} */ /* {{{ Fetch a row as an array */ PHP_FUNCTION(pg_fetch_array) { - php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_BOTH, 0); + zval *result; + zend_long row = 0; + bool row_is_null = true; + zend_long result_type = PGSQL_BOTH; + + ZEND_PARSE_PARAMETERS_START(1, 3) + Z_PARAM_OBJECT_OF_CLASS(result, pgsql_result_ce) + Z_PARAM_OPTIONAL + Z_PARAM_LONG_OR_NULL(row, row_is_null) + Z_PARAM_LONG(result_type) + ZEND_PARSE_PARAMETERS_END(); + + if (UNEXPECTED(!php_pgsql_fetch_hash(return_value, result, row, row_is_null, result_type))) { + /* Either an exception is thrown, or we return false */ + RETURN_FALSE; + } } /* }}} */ /* {{{ Fetch a row as an object */ PHP_FUNCTION(pg_fetch_object) { - /* pg_fetch_object() allowed result_type used to be. 3rd parameter - must be allowed for compatibility */ - php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_ASSOC, 1); + zval *result; + zend_long row = 0; + bool row_is_null = true; + zend_class_entry *ce = NULL; + HashTable *ctor_params = NULL; + + ZEND_PARSE_PARAMETERS_START(1, 4) + Z_PARAM_OBJECT_OF_CLASS(result, pgsql_result_ce) + Z_PARAM_OPTIONAL + Z_PARAM_LONG_OR_NULL(row, row_is_null) + Z_PARAM_CLASS(ce) + Z_PARAM_ARRAY_HT(ctor_params) + ZEND_PARSE_PARAMETERS_END(); + + if (!ce) { + ce = zend_standard_class_def; + } + + if (!ce->constructor && ctor_params && zend_hash_num_elements(ctor_params) > 0) { + zend_argument_value_error(3, + "must be empty when the specified class (%s) does not have a constructor", + ZSTR_VAL(ce->name) + ); + RETURN_THROWS(); + } + + zval dataset; + if (UNEXPECTED(!php_pgsql_fetch_hash(&dataset, result, row, row_is_null, PGSQL_ASSOC))) { + /* Either an exception is thrown, or we return false */ + RETURN_FALSE; + } + + // TODO: Check CE is an instantiable class earlier? + zend_result obj_initialized = object_init_ex(return_value, ce); + if (UNEXPECTED(obj_initialized == FAILURE)) { + zval_ptr_dtor(&dataset); + RETURN_THROWS(); + } + if (!ce->default_properties_count && !ce->__set) { + Z_OBJ_P(return_value)->properties = Z_ARR(dataset); + } else { + zend_merge_properties(return_value, Z_ARRVAL(dataset)); + zval_ptr_dtor(&dataset); + } + + // TODO: Need to grab constructor via object handler as this allows instantiating internal objects with overridden get_constructor + if (ce->constructor) { + zend_call_known_function(ce->constructor, Z_OBJ_P(return_value), Z_OBJCE_P(return_value), + /* retval */ NULL, /* argc */ 0, /* params */ NULL, ctor_params); + } } /* }}} */ @@ -2856,19 +2899,18 @@ PHP_FUNCTION(pg_lo_import) Oid returned_oid; pgsql_link_handle *link; - if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), - "OP|z", &pgsql_link, pgsql_link_ce, &file_in, &oid) == SUCCESS) { + /* Deprecated signature with implicit connection */ + if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "P|z", &file_in, &oid) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "OP|z", &pgsql_link, pgsql_link_ce, &file_in, &oid) == FAILURE) { + RETURN_THROWS(); + } link = Z_PGSQL_LINK_P(pgsql_link); CHECK_PGSQL_LINK(link); - } - else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), - "P|z", &file_in, &oid) == SUCCESS) { + } else { + /* Load implicit connection */ link = FETCH_DEFAULT_LINK(); CHECK_DEFAULT_LINK(link); } - else { - WRONG_PARAM_COUNT; - } if (php_check_open_basedir(ZSTR_VAL(file_in))) { RETURN_FALSE; @@ -3308,9 +3350,8 @@ PHP_FUNCTION(pg_copy_to) pgsql_link_handle *link; zend_string *table_name; zend_string *pg_delimiter = NULL; - char *pg_null_as = NULL; + char *pg_null_as = "\\\\N"; size_t pg_null_as_len = 0; - bool free_pg_null = false; char *query; PGconn *pgsql; PGresult *pgsql_result; @@ -3335,10 +3376,6 @@ PHP_FUNCTION(pg_copy_to) zend_argument_value_error(3, "must be one character"); RETURN_THROWS(); } - if (!pg_null_as) { - pg_null_as = estrdup("\\\\N"); - free_pg_null = true; - } spprintf(&query, 0, "COPY %s TO STDOUT DELIMITER E'%c' NULL AS E'%s'", ZSTR_VAL(table_name), *ZSTR_VAL(pg_delimiter), pg_null_as); @@ -3346,9 +3383,6 @@ PHP_FUNCTION(pg_copy_to) PQclear(pgsql_result); } pgsql_result = PQexec(pgsql, query); - if (free_pg_null) { - efree(pg_null_as); - } efree(query); if (pgsql_result) { @@ -3402,26 +3436,27 @@ PHP_FUNCTION(pg_copy_to) static zend_result pgsql_copy_from_query(PGconn *pgsql, PGresult *pgsql_result, zval *value) { - zend_string *tmp = zval_try_get_string(value); + zend_string *tmp_tmp; + zend_string *tmp = zval_try_get_tmp_string(value, &tmp_tmp); if (UNEXPECTED(!tmp)) { return FAILURE; } - zend_string *zquery = zend_string_alloc(ZSTR_LEN(tmp) + 2, false); - memcpy(ZSTR_VAL(zquery), ZSTR_VAL(tmp), ZSTR_LEN(tmp) + 1); - ZSTR_LEN(zquery) = ZSTR_LEN(tmp); - if (ZSTR_LEN(tmp) > 0 && ZSTR_VAL(zquery)[ZSTR_LEN(tmp) - 1] != '\n') { - ZSTR_VAL(zquery)[ZSTR_LEN(tmp)] = '\n'; - ZSTR_VAL(zquery)[ZSTR_LEN(tmp) + 1] = '\0'; - ZSTR_LEN(zquery) ++; - } - if (PQputCopyData(pgsql, ZSTR_VAL(zquery), ZSTR_LEN(zquery)) != 1) { - zend_string_release_ex(zquery, false); - zend_string_release(tmp); - return FAILURE; + + int result; + if (ZSTR_LEN(tmp) > 0 && ZSTR_VAL(tmp)[ZSTR_LEN(tmp) - 1] != '\n') { + char *zquery = emalloc(ZSTR_LEN(tmp) + 2); + memcpy(zquery, ZSTR_VAL(tmp), ZSTR_LEN(tmp) + 1); + zquery[ZSTR_LEN(tmp)] = '\n'; + zquery[ZSTR_LEN(tmp) + 1] = '\0'; + result = PQputCopyData(pgsql, zquery, ZSTR_LEN(tmp) + 1); + efree(zquery); + } else { + result = PQputCopyData(pgsql, ZSTR_VAL(tmp), ZSTR_LEN(tmp)); } - zend_string_release_ex(zquery, false); - zend_string_release(tmp); - return SUCCESS; + + zend_tmp_string_release(tmp_tmp); + + return result != 1 ? FAILURE : SUCCESS; } /* {{{ Copy table from array */ @@ -3432,9 +3467,8 @@ PHP_FUNCTION(pg_copy_from) zval *value; zend_string *table_name; zend_string *pg_delimiter = NULL; - char *pg_null_as = NULL; + char *pg_null_as = "\\\\N"; size_t pg_null_as_len; - bool pg_null_as_free = false; char *query; PGconn *pgsql; PGresult *pgsql_result; @@ -3459,10 +3493,6 @@ PHP_FUNCTION(pg_copy_from) zend_argument_value_error(4, "must be one character"); RETURN_THROWS(); } - if (!pg_null_as) { - pg_null_as = estrdup("\\\\N"); - pg_null_as_free = true; - } spprintf(&query, 0, "COPY %s FROM STDIN DELIMITER E'%c' NULL AS E'%s'", ZSTR_VAL(table_name), *ZSTR_VAL(pg_delimiter), pg_null_as); while ((pgsql_result = PQgetResult(pgsql))) { @@ -3470,9 +3500,6 @@ PHP_FUNCTION(pg_copy_from) } pgsql_result = PQexec(pgsql, query); - if (pg_null_as_free) { - efree(pg_null_as); - } efree(query); if (pgsql_result) { @@ -4026,9 +4053,9 @@ PHP_FUNCTION(pg_send_query) /* {{{ Send asynchronous parameterized query */ PHP_FUNCTION(pg_send_query_params) { - zval *pgsql_link, *pv_param_arr, *tmp; + zval *pgsql_link, *pv_param_arr; pgsql_link_handle *link; - int num_params = 0; + int num_params; char **params = NULL; char *query; size_t query_len; @@ -4058,25 +4085,9 @@ PHP_FUNCTION(pg_send_query_params) "There are results on this connection. Call pg_get_result() until it returns FALSE"); } - num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr)); - if (num_params > 0) { - int i = 0; - params = (char **)safe_emalloc(sizeof(char *), num_params, 0); - - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pv_param_arr), tmp) { - ZVAL_DEREF(tmp); - if (Z_TYPE_P(tmp) == IS_NULL) { - params[i] = NULL; - } else { - zend_string *tmp_str; - zend_string *str = zval_get_tmp_string(tmp, &tmp_str); - - params[i] = estrndup(ZSTR_VAL(str), ZSTR_LEN(str)); - zend_tmp_string_release(tmp_str); - } - - i++; - } ZEND_HASH_FOREACH_END(); + params = php_pgsql_make_arguments(Z_ARRVAL_P(pv_param_arr), &num_params); + if (UNEXPECTED(!params)) { + RETURN_THROWS(); } if (PQsendQueryParams(pgsql, query, num_params, NULL, (const char * const *)params, NULL, NULL, 0)) { @@ -4198,8 +4209,8 @@ PHP_FUNCTION(pg_send_execute) { zval *pgsql_link; pgsql_link_handle *link; - zval *pv_param_arr, *tmp; - int num_params = 0; + zval *pv_param_arr; + int num_params; char **params = NULL; char *stmtname; size_t stmtname_len; @@ -4229,27 +4240,9 @@ PHP_FUNCTION(pg_send_execute) "There are results on this connection. Call pg_get_result() until it returns FALSE"); } - num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr)); - if (num_params > 0) { - int i = 0; - params = (char **)safe_emalloc(sizeof(char *), num_params, 0); - - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pv_param_arr), tmp) { - ZVAL_DEREF(tmp); - if (Z_TYPE_P(tmp) == IS_NULL) { - params[i] = NULL; - } else { - zend_string *tmp_str = zval_try_get_string(tmp); - if (UNEXPECTED(!tmp_str)) { - _php_pgsql_free_params(params, i); - return; - } - params[i] = estrndup(ZSTR_VAL(tmp_str), ZSTR_LEN(tmp_str)); - zend_string_release(tmp_str); - } - - i++; - } ZEND_HASH_FOREACH_END(); + params = php_pgsql_make_arguments(Z_ARRVAL_P(pv_param_arr), &num_params); + if (UNEXPECTED(!params)) { + RETURN_THROWS(); } if (PQsendQueryPrepared(pgsql, stmtname, num_params, (const char * const *)params, NULL, NULL, 0)) { @@ -4913,7 +4906,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * array_init(&meta); /* table_name is escaped by php_pgsql_meta_data */ - if (php_pgsql_meta_data(pg_link, table_name, &meta, 0) == FAILURE) { + if (php_pgsql_meta_data(pg_link, table_name, &meta, false) == FAILURE) { zval_ptr_dtor(&meta); return FAILURE; } @@ -4958,7 +4951,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * break; /* break out for() */ } - if (zval_is_true(is_enum)) { + if (zend_is_true(is_enum)) { /* enums need to be treated like strings */ data_type = PG_TEXT; } else { @@ -6253,7 +6246,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) @@ -6389,7 +6381,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_arginfo.h b/ext/pgsql/pgsql_arginfo.h index 9bec05ff4c33f..2d9eec944356e 100644 --- a/ext/pgsql/pgsql_arginfo.h +++ b/ext/pgsql/pgsql_arginfo.h @@ -867,217 +867,169 @@ 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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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); @@ -1085,10 +1037,8 @@ static void register_pgsql_symbols(int module_number) 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); - zval attribute_Deprecated_const_PGSQL_LIBPQ_VERSION_STR_0_arg1; 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_arg1, attribute_Deprecated_const_PGSQL_LIBPQ_VERSION_STR_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_PGSQL_LIBPQ_VERSION_STR_0->args[1].value, &attribute_Deprecated_const_PGSQL_LIBPQ_VERSION_STR_0_arg1); + 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); } diff --git a/ext/pgsql/tests/inc/config.inc b/ext/pgsql/tests/inc/config.inc index b01b120723d9f..dc95c9eedab2f 100644 --- a/ext/pgsql/tests/inc/config.inc +++ b/ext/pgsql/tests/inc/config.inc @@ -6,4 +6,3 @@ // "test" database must exist. i.e. "createdb test" before testing $conn_str = getenv('PGSQL_TEST_CONNSTR') ?: "host=localhost dbname=test port=5432 user=postgres password=postgres"; // connection string -?> diff --git a/ext/pgsql/tests/inc/lcmess.inc b/ext/pgsql/tests/inc/lcmess.inc index 7c6e0b80ed7ba..a1bf61e6851c8 100644 --- a/ext/pgsql/tests/inc/lcmess.inc +++ b/ext/pgsql/tests/inc/lcmess.inc @@ -17,5 +17,3 @@ function _set_lc_messages($conn, $lc_messages = 'C') return true; } - -?> diff --git a/ext/pgsql/tests/inc/skipif.inc b/ext/pgsql/tests/inc/skipif.inc index 06c3ff657115b..2ce5f46e7787b 100644 --- a/ext/pgsql/tests/inc/skipif.inc +++ b/ext/pgsql/tests/inc/skipif.inc @@ -1,4 +1,3 @@ - = 9.0\n"); } } - -?> diff --git a/ext/pgsql/tests/pg_fetch_object_with_abstract_class.phpt b/ext/pgsql/tests/pg_fetch_object_with_abstract_class.phpt new file mode 100644 index 0000000000000..b3e6ea7f7b36c --- /dev/null +++ b/ext/pgsql/tests/pg_fetch_object_with_abstract_class.phpt @@ -0,0 +1,59 @@ +--TEST-- +pg_fetch_object() with abstract class name +--EXTENSIONS-- +pgsql +--SKIPIF-- + +--FILE-- +getMessage(), PHP_EOL; +} + +try { + $result = pg_query($db, $sql); + var_dump(pg_fetch_object($result, NULL, 'C')); +} catch(Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + $result = pg_query($db, $sql); + var_dump(pg_fetch_object($result, NULL, 'E')); +} catch(Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--CLEAN-- + +--EXPECT-- +Error: Cannot instantiate interface I +Error: Cannot instantiate abstract class C +Error: Cannot instantiate enum E diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c index c5aa292200e86..f37599e7db117 100644 --- a/ext/phar/dirstream.c +++ b/ext/phar/dirstream.c @@ -188,8 +188,6 @@ static php_stream *phar_make_dirstream(const char *dir, size_t dirlen, const Has entry = safe_emalloc(keylen, 1, 1); memcpy(entry, ZSTR_VAL(str_key), keylen); entry[keylen] = '\0'; - - goto PHAR_ADD_ENTRY; } else { if (0 != memcmp(ZSTR_VAL(str_key), dir, dirlen)) { /* entry in directory not found */ @@ -199,28 +197,28 @@ static php_stream *phar_make_dirstream(const char *dir, size_t dirlen, const Has continue; } } - } - const char *save = ZSTR_VAL(str_key); - save += dirlen + 1; /* seek to just past the path separator */ + const char *save = ZSTR_VAL(str_key); + save += dirlen + 1; /* seek to just past the path separator */ - const char *has_slash = memchr(save, '/', keylen - dirlen - 1); - if (has_slash) { - /* is subdirectory */ - save -= dirlen + 1; - entry = safe_emalloc(has_slash - save + dirlen, 1, 1); - memcpy(entry, save + dirlen + 1, has_slash - save - dirlen - 1); - keylen = has_slash - save - dirlen - 1; - entry[keylen] = '\0'; - } else { - /* is file */ - save -= dirlen + 1; - entry = safe_emalloc(keylen - dirlen, 1, 1); - memcpy(entry, save + dirlen + 1, keylen - dirlen - 1); - entry[keylen - dirlen - 1] = '\0'; - keylen = keylen - dirlen - 1; + const char *has_slash = memchr(save, '/', keylen - dirlen - 1); + if (has_slash) { + /* is subdirectory */ + save -= dirlen + 1; + entry = safe_emalloc(has_slash - save + dirlen, 1, 1); + memcpy(entry, save + dirlen + 1, has_slash - save - dirlen - 1); + keylen = has_slash - save - dirlen - 1; + entry[keylen] = '\0'; + } else { + /* is file */ + save -= dirlen + 1; + entry = safe_emalloc(keylen - dirlen, 1, 1); + memcpy(entry, save + dirlen + 1, keylen - dirlen - 1); + entry[keylen - dirlen - 1] = '\0'; + keylen = keylen - dirlen - 1; + } } -PHAR_ADD_ENTRY: + if (keylen) { /** * Add an empty element to avoid duplicates @@ -349,12 +347,12 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo { phar_entry_info entry, *e; phar_archive_data *phar = NULL; - char *error, *arch, *entry2; - size_t arch_len, entry_len; + char *error, *arch; + size_t arch_len; php_url *resource = NULL; /* pre-readonly check, we need to know if this is a data phar */ - if (FAILURE == phar_split_fname(url_from, strlen(url_from), &arch, &arch_len, &entry2, &entry_len, 2, 2)) { + if (FAILURE == phar_split_fname(url_from, strlen(url_from), &arch, &arch_len, NULL, NULL, 2, 2)) { php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\", no phar archive specified", url_from); return 0; } @@ -364,7 +362,6 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo } efree(arch); - efree(entry2); if (PHAR_G(readonly) && (!phar || !phar->is_data)) { php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\", write operations disabled", url_from); @@ -395,7 +392,7 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo return 0; } - if ((e = phar_get_entry_info_dir(phar, ZSTR_VAL(resource->path) + 1, ZSTR_LEN(resource->path) - 1, 2, &error, 1))) { + if ((e = phar_get_entry_info_dir(phar, ZSTR_VAL(resource->path) + 1, ZSTR_LEN(resource->path) - 1, 2, &error, true))) { /* directory exists, or is a subdirectory of an existing file */ if (e->is_temp_dir) { zend_string_efree(e->filename); @@ -413,7 +410,7 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo return 0; } - if (phar_get_entry_info_dir(phar, ZSTR_VAL(resource->path) + 1, ZSTR_LEN(resource->path) - 1, 0, &error, 1)) { + if (phar_get_entry_info_dir(phar, ZSTR_VAL(resource->path) + 1, ZSTR_LEN(resource->path) - 1, 0, &error, true)) { /* entry exists as a file */ php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\" in phar \"%s\", file already exists", ZSTR_VAL(resource->path)+1, ZSTR_VAL(resource->host)); php_url_free(resource); @@ -451,7 +448,6 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo if (NULL == zend_hash_add_mem(&phar->manifest, entry.filename, &entry, sizeof(phar_entry_info))) { php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\" in phar \"%s\", adding to manifest failed", ZSTR_VAL(entry.filename), phar->fname); - efree(error); zend_string_efree(entry.filename); return 0; } @@ -477,12 +473,12 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options { phar_entry_info *entry; phar_archive_data *phar = NULL; - char *error, *arch, *entry2; - size_t arch_len, entry_len; + char *error, *arch; + size_t arch_len; php_url *resource = NULL; /* pre-readonly check, we need to know if this is a data phar */ - if (FAILURE == phar_split_fname(url, strlen(url), &arch, &arch_len, &entry2, &entry_len, 2, 2)) { + if (FAILURE == phar_split_fname(url, strlen(url), &arch, &arch_len, NULL, NULL, 2, 2)) { php_stream_wrapper_log_error(wrapper, options, "phar error: cannot remove directory \"%s\", no phar archive specified, or phar archive does not exist", url); return 0; } @@ -492,7 +488,6 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options } efree(arch); - efree(entry2); if (PHAR_G(readonly) && (!phar || !phar->is_data)) { php_stream_wrapper_log_error(wrapper, options, "phar error: cannot rmdir directory \"%s\", write operations disabled", url); @@ -525,7 +520,7 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options size_t path_len = ZSTR_LEN(resource->path) - 1; - if (!(entry = phar_get_entry_info_dir(phar, ZSTR_VAL(resource->path) + 1, path_len, 2, &error, 1))) { + if (!(entry = phar_get_entry_info_dir(phar, ZSTR_VAL(resource->path) + 1, path_len, 2, &error, true))) { if (error) { php_stream_wrapper_log_error(wrapper, options, "phar error: cannot remove directory \"%s\" in phar \"%s\", %s", ZSTR_VAL(resource->path)+1, ZSTR_VAL(resource->host), error); efree(error); diff --git a/ext/phar/func_interceptors.c b/ext/phar/func_interceptors.c index f1b2b0eba1e63..f7e553a45ce80 100644 --- a/ext/phar/func_interceptors.c +++ b/ext/phar/func_interceptors.c @@ -50,12 +50,11 @@ PHP_FUNCTION(phar_opendir) /* {{{ */ goto skip_phar; } - if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, &entry, &entry_len, 2, 0)) { + if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, NULL, 2, 0)) { php_stream_context *context = NULL; php_stream *stream; char *name; - efree(entry); entry = estrndup(filename, filename_len); /* fopen within phar, if :// is not in the url, then prepend phar:/// */ entry_len = filename_len; @@ -89,8 +88,8 @@ PHP_FUNCTION(phar_opendir) /* {{{ */ static zend_string* phar_get_name_for_relative_paths(zend_string *filename, bool using_include_path) { - char *arch, *entry; - size_t arch_len, entry_len; + char *arch; + size_t arch_len; zend_string *fname = zend_get_executed_filename_ex(); /* we are checking for existence of a file within the relative path. Chances are good that this is @@ -99,13 +98,10 @@ static zend_string* phar_get_name_for_relative_paths(zend_string *filename, bool return NULL; } - if (FAILURE == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, &entry, &entry_len, 2, 0)) { + if (FAILURE == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, NULL, 2, 0)) { return NULL; } - efree(entry); - entry = NULL; - entry_len = 0; /* fopen within phar, if :// is not in the url, then prepend phar:/// */ /* retrieving a file defaults to within the current directory, so use this if possible */ phar_archive_data *phar; @@ -122,8 +118,8 @@ static zend_string* phar_get_name_for_relative_paths(zend_string *filename, bool return NULL; } } else { - entry_len = ZSTR_LEN(filename); - entry = phar_fix_filepath(estrndup(ZSTR_VAL(filename), ZSTR_LEN(filename)), &entry_len, 1); + size_t entry_len = ZSTR_LEN(filename); + char *entry = phar_fix_filepath(estrndup(ZSTR_VAL(filename), ZSTR_LEN(filename)), &entry_len, 1); if (entry[0] == '/') { if (!zend_hash_str_exists(&(phar->manifest), entry + 1, entry_len - 1)) { /* this file is not in the phar, use the original path */ @@ -159,10 +155,10 @@ PHP_FUNCTION(phar_file_get_contents) /* {{{ */ { zend_string *filename; zend_string *contents; - bool use_include_path = 0; + bool use_include_path = false; zend_long offset = -1; zend_long maxlen; - bool maxlen_is_null = 1; + bool maxlen_is_null = true; zval *zcontext = NULL; if (!PHAR_G(intercepted)) { @@ -235,7 +231,7 @@ PHP_FUNCTION(phar_file_get_contents) /* {{{ */ PHP_FUNCTION(phar_readfile) /* {{{ */ { zend_string *filename; - bool use_include_path = 0; + bool use_include_path = false; zval *zcontext = NULL; if (!PHAR_G(intercepted)) { @@ -281,7 +277,7 @@ PHP_FUNCTION(phar_fopen) /* {{{ */ zend_string *filename; char *mode; size_t mode_len; - bool use_include_path = 0; + bool use_include_path = false; zval *zcontext = NULL; if (!PHAR_G(intercepted)) { @@ -509,9 +505,7 @@ static void phar_file_stat(const char *filename, size_t filename_length, int typ phar = PHAR_G(last_phar); goto splitted; } - if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, &entry, &entry_len, 2, 0)) { - - efree(entry); + if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, NULL, 2, 0)) { entry = estrndup(filename, filename_length); /* fopen within phar, if :// is not in the url, then prepend phar:/// */ entry_len = filename_length; @@ -751,10 +745,9 @@ PHP_FUNCTION(phar_is_file) /* {{{ */ goto skip_phar; } - if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, &entry, &entry_len, 2, 0)) { + if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, NULL, 2, 0)) { phar_archive_data *phar; - efree(entry); entry = filename; /* fopen within phar, if :// is not in the url, then prepend phar:/// */ entry_len = filename_len; @@ -817,10 +810,9 @@ PHP_FUNCTION(phar_is_link) /* {{{ */ goto skip_phar; } - if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, &entry, &entry_len, 2, 0)) { + if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, NULL, 2, 0)) { phar_archive_data *phar; - efree(entry); entry = filename; /* fopen within phar, if :// is not in the url, then prepend phar:/// */ entry_len = filename_len; diff --git a/ext/phar/makestub.php b/ext/phar/makestub.php old mode 100644 new mode 100755 index 5808f4c38c9a0..34d270751bfb0 --- a/ext/phar/makestub.php +++ b/ext/phar/makestub.php @@ -1,3 +1,4 @@ +#!/usr/bin/env php $unused) { $stub .= ', newstub1_' . $i; diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 76a580988fb62..385e9afeda14d 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -246,7 +246,7 @@ void phar_destroy_phar_data(phar_archive_data *phar) /* {{{ */ bool phar_archive_delref(phar_archive_data *phar) /* {{{ */ { if (phar->is_persistent) { - return 0; + return false; } if (--phar->refcount < 0) { @@ -254,33 +254,39 @@ bool phar_archive_delref(phar_archive_data *phar) /* {{{ */ || zend_hash_str_del(&(PHAR_G(phar_fname_map)), phar->fname, phar->fname_len) != SUCCESS) { phar_destroy_phar_data(phar); } - return 1; + return true; } else if (!phar->refcount) { /* invalidate phar cache */ PHAR_G(last_phar) = NULL; PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL; + /* This is a new phar that has perhaps had an alias/metadata set, but has never been flushed. */ + bool remove_fname_cache = !zend_hash_num_elements(&phar->manifest); + if (phar->fp && (!(phar->flags & PHAR_FILE_COMPRESSION_MASK) || !phar->alias)) { /* close open file handle - allows removal or rename of the file on windows, which has greedy locking - only close if the archive was not already compressed. If it - was compressed, then the fp does not refer to the original file. - We're also closing compressed files to save resources, - but only if the archive isn't aliased. */ + only close if the archive was not already compressed. + We're also closing compressed files to save resources, but only if the archive isn't aliased. + If it was compressed, then the fp does not refer to the original compressed file: + it refers to the **uncompressed** filtered file stream. + Therefore, upon closing a compressed file we need to invalidate the phar archive such + that the code that reopens the phar will not try to use the **compressed** file as if it was uncompressed. + That would result in treating compressed file data as if it were compressed and using uncompressed file offsets + on the compressed file. */ php_stream_close(phar->fp); phar->fp = NULL; + remove_fname_cache |= phar->flags & PHAR_FILE_COMPRESSION_MASK; } - if (!zend_hash_num_elements(&phar->manifest)) { - /* this is a new phar that has perhaps had an alias/metadata set, but has never - been flushed */ + if (remove_fname_cache) { if (zend_hash_str_del(&(PHAR_G(phar_fname_map)), phar->fname, phar->fname_len) != SUCCESS) { phar_destroy_phar_data(phar); } - return 1; + return true; } } - return 0; + return false; } /* }}}*/ @@ -414,13 +420,13 @@ void phar_entry_delref(phar_entry_data *idata) /* {{{ */ /** * Removes an entry, either by actually removing it or by marking it. */ -void phar_entry_remove(phar_entry_data *idata, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL void phar_entry_remove(phar_entry_data *idata, char **error) /* {{{ */ { phar_archive_data *phar; phar = idata->phar; - if (idata->internal_file->fp_refcount < 2) { + if (idata->internal_file->fp_refcount < 2 && idata->internal_file->fileinfo_lock_count == 0) { if (idata->fp && idata->fp != idata->phar->fp && idata->fp != idata->phar->ufp && idata->fp != idata->internal_file->fp) { php_stream_close(idata->fp); } @@ -464,17 +470,10 @@ void phar_entry_remove(phar_entry_data *idata, char **error) /* {{{ */ | ((uint32_t)(((unsigned char*)(buffer))[1]) << 8) \ | ((uint32_t)((unsigned char*)(buffer))[0]); \ (buffer) += 4 -# define PHAR_GET_16(buffer, var) \ - var = ((uint16_t)(((unsigned char*)(buffer))[1]) << 8) \ - | ((uint16_t)((unsigned char*)(buffer))[0]); \ - (buffer) += 2 #else # define PHAR_GET_32(buffer, var) \ memcpy(&var, buffer, sizeof(var)); \ buffer += 4 -# define PHAR_GET_16(buffer, var) \ - var = *(uint16_t*)(buffer); \ - buffer += 2 #endif #define PHAR_ZIP_16(var) ((uint16_t)((((uint16_t)var[0]) & 0xff) | \ (((uint16_t)var[1]) & 0xff) << 8)) @@ -510,7 +509,6 @@ static zend_result phar_open_parsed_phar(char *fname, size_t fname_len, char *al && ((alias && fname_len == phar->fname_len && !strncmp(fname, phar->fname, fname_len)) || !alias) ) { - phar_entry_info *stub; #ifdef PHP_WIN32 if (fname != save_fname) { free_alloca(fname, fname_use_heap); @@ -526,7 +524,7 @@ static zend_result phar_open_parsed_phar(char *fname, size_t fname_len, char *al if (!is_data) { /* prevent any ".phar" without a stub getting through */ if (!phar->halt_offset && !phar->is_brandnew && (phar->is_tar || phar->is_zip)) { - if (PHAR_G(readonly) && NULL == (stub = zend_hash_str_find_ptr(&(phar->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1))) { + if (PHAR_G(readonly) && !zend_hash_str_exists(&(phar->manifest), ZEND_STRL(".phar/stub.php"))) { if (error) { spprintf(error, 0, "'%s' is not a phar archive. Use PharData::__construct() for a standard zip or tar archive", fname); } @@ -595,13 +593,9 @@ zend_result phar_metadata_tracker_unserialize_or_copy(phar_metadata_tracker *tra const bool has_unserialize_options = unserialize_options != NULL && zend_hash_num_elements(unserialize_options) > 0; /* It should be impossible to create a zval in a persistent phar/entry. */ ZEND_ASSERT(!persistent || Z_ISUNDEF(tracker->val)); + ZEND_ASSERT(!EG(exception)); if (Z_ISUNDEF(tracker->val) || has_unserialize_options) { - if (EG(exception)) { - /* Because other parts of the phar code haven't been updated to check for exceptions after doing something that may throw, - * check for exceptions before potentially serializing/unserializing instead. */ - return FAILURE; - } /* Persistent phars should always be unserialized. */ const char *start; /* Assert it should not be possible to create raw data in a persistent phar (i.e. from cache_list) */ @@ -740,7 +734,7 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname uint32_t len; zend_long offset; size_t sig_len; - int register_alias = 0, temp_alias = 0; + bool register_alias = false, temp_alias = false; char *signature = NULL; zend_string *str; @@ -1073,15 +1067,15 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname alias_len = tmp_len; alias = buffer; buffer += tmp_len; - register_alias = 1; + register_alias = true; } else if (!alias_len || !alias) { /* if we neither have an explicit nor an implicit alias, we use the filename */ alias = NULL; alias_len = 0; - register_alias = 0; + register_alias = false; } else if (alias_len) { - register_alias = 1; - temp_alias = 1; + register_alias = true; + temp_alias = true; } /* we have 5 32-bit items plus 1 byte at least */ @@ -1113,11 +1107,11 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname /* set up our manifest */ zend_hash_init(&mydata->manifest, manifest_count, - zend_get_hash_value, destroy_phar_manifest_entry, (bool)mydata->is_persistent); + zend_get_hash_value, destroy_phar_manifest_entry, mydata->is_persistent); zend_hash_init(&mydata->mounted_dirs, 5, - zend_get_hash_value, NULL, (bool)mydata->is_persistent); + zend_get_hash_value, NULL, mydata->is_persistent); zend_hash_init(&mydata->virtual_dirs, manifest_count * 2, - zend_get_hash_value, NULL, (bool)mydata->is_persistent); + zend_get_hash_value, NULL, mydata->is_persistent); mydata->fname = pestrndup(fname, fname_len, mydata->is_persistent); #ifdef PHP_WIN32 phar_unixify_path_separators(mydata->fname, fname_len); @@ -1161,15 +1155,9 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname PHAR_GET_32(buffer, entry.uncompressed_filesize); PHAR_GET_32(buffer, entry.timestamp); - if (offset == halt_offset + manifest_len + 4) { - mydata->min_timestamp = entry.timestamp; + if (offset == halt_offset + manifest_len + 4 + || mydata->max_timestamp < entry.timestamp) { mydata->max_timestamp = entry.timestamp; - } else { - if (mydata->min_timestamp > entry.timestamp) { - mydata->min_timestamp = entry.timestamp; - } else if (mydata->max_timestamp < entry.timestamp) { - mydata->max_timestamp = entry.timestamp; - } } PHAR_GET_32(buffer, entry.compressed_filesize); @@ -1315,7 +1303,7 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname /** * Create or open a phar for writing */ -zend_result phar_open_or_create_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_open_or_create_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { const char *ext_str, *z; char *my_error; @@ -1324,42 +1312,33 @@ zend_result phar_open_or_create_filename(char *fname, size_t fname_len, char *al test = &unused; - if (error) { - *error = NULL; - } + *error = NULL; /* first try to open an existing file */ - if (phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, !is_data, 0, 1) == SUCCESS) { + if (phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, !is_data, 0, true) == SUCCESS) { goto check_file; } /* next try to create a new file */ - if (FAILURE == phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, !is_data, 1, 1)) { - if (error) { - if (ext_len == -2) { - spprintf(error, 0, "Cannot create a phar archive from a URL like \"%s\". Phar objects can only be created from local files", fname); - } else { - spprintf(error, 0, "Cannot create phar '%s', file extension (or combination) not recognised or the directory does not exist", fname); - } + if (FAILURE == phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, !is_data, 1, true)) { + if (ext_len == -2) { + spprintf(error, 0, "Cannot create a phar archive from a URL like \"%s\". Phar objects can only be created from local files", fname); + } else { + spprintf(error, 0, "Cannot create phar '%s', file extension (or combination) not recognised or the directory does not exist", fname); } return FAILURE; } check_file: if (phar_open_parsed_phar(fname, fname_len, alias, alias_len, is_data, options, test, &my_error) == SUCCESS) { - if (pphar) { - *pphar = *test; - } + *pphar = *test; if ((*test)->is_data && !(*test)->is_tar && !(*test)->is_zip) { - if (error) { - spprintf(error, 0, "Cannot open '%s' as a PharData object. Use Phar::__construct() for executable archives", fname); - } + spprintf(error, 0, "Cannot open '%s' as a PharData object. Use Phar::__construct() for executable archives", fname); return FAILURE; } if (PHAR_G(readonly) && !(*test)->is_data && ((*test)->is_tar || (*test)->is_zip)) { - phar_entry_info *stub; - if (NULL == (stub = zend_hash_str_find_ptr(&((*test)->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1))) { + if (!zend_hash_str_exists(&((*test)->manifest), ZEND_STRL(".phar/stub.php"))) { spprintf(error, 0, "'%s' is not a phar archive. Use PharData::__construct() for a standard zip or tar archive", fname); return FAILURE; } @@ -1370,11 +1349,7 @@ zend_result phar_open_or_create_filename(char *fname, size_t fname_len, char *al } return SUCCESS; } else if (my_error) { - if (error) { - *error = my_error; - } else { - efree(my_error); - } + *error = my_error; return FAILURE; } @@ -1394,16 +1369,12 @@ zend_result phar_open_or_create_filename(char *fname, size_t fname_len, char *al static zend_result phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error); -zend_result phar_create_or_parse_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_create_or_parse_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { - phar_archive_data *mydata; php_stream *fp; zend_string *actual = NULL; char *p; - if (!pphar) { - pphar = &mydata; - } if (php_check_open_basedir(fname)) { return FAILURE; } @@ -1440,15 +1411,13 @@ zend_result phar_create_or_parse_filename(char *fname, size_t fname_len, char *a if (PHAR_G(readonly) && !is_data) { if (options & REPORT_ERRORS) { - if (error) { - spprintf(error, 0, "creating archive \"%s\" disabled by the php.ini setting phar.readonly", fname); - } + spprintf(error, 0, "creating archive \"%s\" disabled by the php.ini setting phar.readonly", fname); } return FAILURE; } /* set up our manifest */ - mydata = ecalloc(1, sizeof(phar_archive_data)); + phar_archive_data *mydata = ecalloc(1, sizeof(phar_archive_data)); mydata->fname = expand_filepath(fname, NULL); if (mydata->fname == NULL) { efree(mydata); @@ -1470,16 +1439,12 @@ zend_result phar_create_or_parse_filename(char *fname, size_t fname_len, char *a } } - if (pphar) { - *pphar = mydata; - } - zend_hash_init(&mydata->manifest, sizeof(phar_entry_info), zend_get_hash_value, destroy_phar_manifest_entry, 0); zend_hash_init(&mydata->mounted_dirs, sizeof(char *), zend_get_hash_value, NULL, 0); zend_hash_init(&mydata->virtual_dirs, sizeof(char *), - zend_get_hash_value, NULL, (bool)mydata->is_persistent); + zend_get_hash_value, NULL, mydata->is_persistent); mydata->fname_len = fname_len; snprintf(mydata->version, sizeof(mydata->version), "%s", PHP_PHAR_API_VERSION); mydata->is_temporary_alias = alias ? 0 : 1; @@ -1500,15 +1465,11 @@ zend_result phar_create_or_parse_filename(char *fname, size_t fname_len, char *a if (alias && NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len))) { if (SUCCESS != phar_free_alias(fd_ptr, alias, alias_len)) { - if (error) { - spprintf(error, 4096, "phar error: phar \"%s\" cannot set alias \"%s\", already in use by another phar archive", mydata->fname, alias); - } + spprintf(error, 4096, "phar error: phar \"%s\" cannot set alias \"%s\", already in use by another phar archive", mydata->fname, alias); zend_hash_str_del(&(PHAR_G(phar_fname_map)), mydata->fname, fname_len); - if (pphar) { - *pphar = NULL; - } + *pphar = NULL; return FAILURE; } @@ -1522,21 +1483,18 @@ zend_result phar_create_or_parse_filename(char *fname, size_t fname_len, char *a if (alias_len && alias) { if (NULL == zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, mydata)) { if (options & REPORT_ERRORS) { - if (error) { - spprintf(error, 0, "archive \"%s\" cannot be associated with alias \"%s\", already in use", fname, alias); - } + spprintf(error, 0, "archive \"%s\" cannot be associated with alias \"%s\", already in use", fname, alias); } zend_hash_str_del(&(PHAR_G(phar_fname_map)), mydata->fname, fname_len); - if (pphar) { - *pphar = NULL; - } + *pphar = NULL; return FAILURE; } } + *pphar = mydata; return SUCCESS; } /* }}}*/ @@ -1600,35 +1558,6 @@ zend_result phar_open_from_filename(char *fname, size_t fname_len, char *alias, } /* }}}*/ -static inline char *phar_strnstr(const char *buf, int buf_len, const char *search, int search_len) /* {{{ */ -{ - const char *c; - ptrdiff_t so_far = 0; - - if (buf_len < search_len) { - return NULL; - } - - c = buf - 1; - - do { - if (!(c = memchr(c + 1, search[0], buf_len - search_len - so_far))) { - return (char *) NULL; - } - - so_far = c - buf; - - if (so_far >= (buf_len - search_len)) { - return (char *) NULL; - } - - if (!memcmp(c, search, search_len)) { - return (char *) c; - } - } while (1); -} -/* }}} */ - /** * Scan an open fp for the required __HALT_COMPILER(); ?> token and verify * that the manifest is proper, then pass it to phar_parse_pharfile(). SUCCESS @@ -1640,14 +1569,15 @@ static zend_result phar_open_from_fp(php_stream* fp, char *fname, size_t fname_l static const char zip_magic[] = "PK\x03\x04"; static const char gz_magic[] = "\x1f\x8b\x08"; static const char bz_magic[] = "BZh"; - char *pos, test = '\0'; + const char *pos; + char test = '\0'; int recursion_count = 3; // arbitrary limit to avoid too deep or even infinite recursion const int window_size = 1024; char buffer[1024 + sizeof(token)]; /* a 1024 byte window + the size of the halt_compiler token (moving window) */ const zend_long readsize = sizeof(buffer) - sizeof(token); const zend_long tokenlen = sizeof(token) - 1; zend_long halt_offset; - size_t got; + ssize_t got; uint32_t compression = PHAR_FILE_COMPRESSED_NONE; if (error) { @@ -1665,7 +1595,7 @@ static zend_result phar_open_from_fp(php_stream* fp, char *fname, size_t fname_l /* Maybe it's better to compile the file instead of just searching, */ /* but we only want the offset. So we want a .re scanner to find it. */ while(!php_stream_eof(fp)) { - if ((got = php_stream_read(fp, buffer+tokenlen, readsize)) < (size_t) tokenlen) { + if ((got = php_stream_read(fp, buffer+tokenlen, readsize)) < tokenlen) { MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated entry)") } @@ -1682,6 +1612,12 @@ static zend_result phar_open_from_fp(php_stream* fp, char *fname, size_t fname_l if (!PHAR_G(has_zlib)) { MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\" to temporary file, enable zlib extension in php.ini") } + + /* entire file is gzip-compressed, uncompress to temporary file */ + if (!(temp = php_stream_fopen_tmpfile())) { + MAPPHAR_ALLOC_FAIL("unable to create temporary file for decompression of gzipped phar archive \"%s\"") + } + array_init(&filterparams); /* this is defined in zlib's zconf.h */ #ifndef MAX_WBITS @@ -1689,11 +1625,6 @@ static zend_result phar_open_from_fp(php_stream* fp, char *fname, size_t fname_l #endif add_assoc_long_ex(&filterparams, "window", sizeof("window") - 1, MAX_WBITS + 32); - /* entire file is gzip-compressed, uncompress to temporary file */ - if (!(temp = php_stream_fopen_tmpfile())) { - MAPPHAR_ALLOC_FAIL("unable to create temporary file for decompression of gzipped phar archive \"%s\"") - } - php_stream_rewind(fp); filter = php_stream_filter_create("zlib.inflate", &filterparams, php_stream_is_persistent(fp)); @@ -1795,7 +1726,7 @@ static zend_result phar_open_from_fp(php_stream* fp, char *fname, size_t fname_l } } - if (got > 0 && (pos = phar_strnstr(buffer, got + sizeof(token), token, sizeof(token)-1)) != NULL) { + if (got > 0 && (pos = php_memnistr(buffer, token, tokenlen, buffer + got + sizeof(token))) != NULL) { halt_offset += (pos - buffer); /* no -tokenlen+tokenlen here */ return phar_parse_pharfile(fp, fname, fname_len, alias, alias_len, halt_offset, pphar, compression, error); } @@ -1974,7 +1905,7 @@ static zend_result phar_check_str(const char *fname, const char *ext_str, size_t * the last parameter should be set to tell the thing to assume that filename is the full path, and only to check the * extension rules, not to iterate. */ -zend_result phar_detect_phar_fname_ext(const char *filename, size_t filename_len, const char **ext_str, size_t *ext_len, int executable, int for_create, int is_complete) /* {{{ */ +zend_result phar_detect_phar_fname_ext(const char *filename, size_t filename_len, const char **ext_str, size_t *ext_len, int executable, int for_create, bool is_complete) /* {{{ */ { const char *pos, *slash; @@ -2068,45 +1999,40 @@ zend_result phar_detect_phar_fname_ext(const char *filename, size_t filename_len } } - // TODO Use some sort of loop here instead of a goto pos = memchr(filename + 1, '.', filename_len); -next_extension: - if (!pos) { - return FAILURE; - } - - while (pos != filename && (*(pos - 1) == '/' || *(pos - 1) == '\0')) { - pos = memchr(pos + 1, '.', filename_len - (pos - filename) - 1); - if (!pos) { - return FAILURE; + while (pos) { + while (pos != filename && (*(pos - 1) == '/' || *(pos - 1) == '\0')) { + pos = memchr(pos + 1, '.', filename_len - (pos - filename) - 1); + if (!pos) { + return FAILURE; + } } - } - slash = memchr(pos, '/', filename_len - (pos - filename)); + slash = memchr(pos, '/', filename_len - (pos - filename)); - if (!slash) { - /* this is a url like "phar://blah.phar" with no directory */ - *ext_str = pos; - *ext_len = strlen(pos); + if (!slash) { + /* this is a url like "phar://blah.phar" with no directory */ + *ext_str = pos; + *ext_len = strlen(pos); - /* file extension must contain "phar" */ - return phar_check_str(filename, *ext_str, *ext_len, executable, for_create); - } + /* file extension must contain "phar" */ + return phar_check_str(filename, *ext_str, *ext_len, executable, for_create); + } - /* we've found an extension that ends at a directory separator */ - *ext_str = pos; - *ext_len = slash - pos; + /* we've found an extension that ends at a directory separator */ + *ext_str = pos; + *ext_len = slash - pos; - if (phar_check_str(filename, *ext_str, *ext_len, executable, for_create) == SUCCESS) { - return SUCCESS; - } + if (phar_check_str(filename, *ext_str, *ext_len, executable, for_create) == SUCCESS) { + return SUCCESS; + } - /* look for more extensions */ - pos = strchr(pos + 1, '.'); - if (pos) { - *ext_str = NULL; - *ext_len = 0; - goto next_extension; + /* look for more extensions */ + pos = strchr(pos + 1, '.'); + if (pos) { + *ext_str = NULL; + *ext_len = 0; + } } return FAILURE; @@ -2117,10 +2043,10 @@ static bool php_check_dots(const char *element, size_t n) /* {{{ */ { for(n-- ; n != SIZE_MAX; --n) { if (element[n] != '.') { - return 1; + return true; } } - return 0; + return false; } /* }}} */ @@ -2135,7 +2061,7 @@ static bool php_check_dots(const char *element, size_t n) /* {{{ */ /** * Remove .. and . references within a phar filename */ -char *phar_fix_filepath(char *path, size_t *new_len, int use_cwd) /* {{{ */ +char *phar_fix_filepath(char *path, size_t *new_len, bool use_cwd) /* {{{ */ { char *newpath; size_t newpath_len; @@ -2255,7 +2181,7 @@ zend_result phar_split_fname(const char *filename, size_t filename_len, char **a #endif size_t ext_len; - if (CHECK_NULL_PATH(filename, filename_len)) { + if (zend_char_has_nul_byte(filename, filename_len)) { return FAILURE; } @@ -2272,7 +2198,7 @@ zend_result phar_split_fname(const char *filename, size_t filename_len, char **a phar_unixify_path_separators((char *)filename, filename_len); } #endif - if (phar_detect_phar_fname_ext(filename, filename_len, &ext_str, &ext_len, executable, for_create, 0) == FAILURE) { + if (phar_detect_phar_fname_ext(filename, filename_len, &ext_str, &ext_len, executable, for_create, false) == FAILURE) { if (ext_len != -1) { if (!ext_str) { /* no / detected, restore arch for error message */ @@ -2298,16 +2224,18 @@ zend_result phar_split_fname(const char *filename, size_t filename_len, char **a *arch_len = ext_str - filename + ext_len; *arch = estrndup(filename, *arch_len); - if (ext_str[ext_len]) { - *entry_len = filename_len - *arch_len; - *entry = estrndup(ext_str+ext_len, *entry_len); -#ifdef PHP_WIN32 - phar_unixify_path_separators(*entry, *entry_len); -#endif - *entry = phar_fix_filepath(*entry, entry_len, 0); - } else { - *entry_len = 1; - *entry = estrndup("/", 1); + if (entry) { + if (ext_str[ext_len]) { + *entry_len = filename_len - *arch_len; + *entry = estrndup(ext_str+ext_len, *entry_len); + #ifdef PHP_WIN32 + phar_unixify_path_separators(*entry, *entry_len); + #endif + *entry = phar_fix_filepath(*entry, entry_len, 0); + } else { + *entry_len = 1; + *entry = estrndup("/", 1); + } } #ifdef PHP_WIN32 @@ -2324,29 +2252,23 @@ zend_result phar_split_fname(const char *filename, size_t filename_len, char **a * Invoked when a user calls Phar::mapPhar() from within an executing .phar * to set up its manifest directly */ -zend_result phar_open_executed_filename(char *alias, size_t alias_len, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL_ARGS(3) zend_result phar_open_executed_filename(char *alias, size_t alias_len, char **error) /* {{{ */ { - if (error) { - *error = NULL; - } + *error = NULL; zend_string *fname = zend_get_executed_filename_ex(); if (!fname) { - if (error) { - spprintf(error, 0, "cannot initialize a phar outside of PHP execution"); - } + *error = estrdup("cannot initialize a phar outside of PHP execution"); return FAILURE; } - if (phar_open_parsed_phar(ZSTR_VAL(fname), ZSTR_LEN(fname), alias, alias_len, 0, REPORT_ERRORS, NULL, 0) == SUCCESS) { + if (phar_open_parsed_phar(ZSTR_VAL(fname), ZSTR_LEN(fname), alias, alias_len, false, REPORT_ERRORS, NULL, NULL) == SUCCESS) { return SUCCESS; } - if (0 == zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1)) { - if (error) { - spprintf(error, 0, "__HALT_COMPILER(); must be declared in a phar"); - } + if (NULL == zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1)) { + *error = estrdup("__HALT_COMPILER(); must be declared in a phar"); return FAILURE; } @@ -2359,9 +2281,7 @@ zend_result phar_open_executed_filename(char *alias, size_t alias_len, char **er fp = php_stream_open_wrapper(ZSTR_VAL(fname), "rb", IGNORE_URL|STREAM_MUST_SEEK|REPORT_ERRORS, &actual); if (!fp) { - if (error) { - spprintf(error, 0, "unable to open phar for reading \"%s\"", ZSTR_VAL(fname)); - } + spprintf(error, 0, "unable to open phar for reading \"%s\"", ZSTR_VAL(fname)); if (actual) { zend_string_release_ex(actual, 0); } @@ -2385,42 +2305,43 @@ zend_result phar_open_executed_filename(char *alias, size_t alias_len, char **er /** * Validate the CRC32 of a file opened from within the phar */ -zend_result phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char **error, int process_zip) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL zend_result phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char **error, int process_zip) /* {{{ */ { php_stream *fp = idata->fp; phar_entry_info *entry = idata->internal_file; - if (error) { - *error = NULL; - } + *error = NULL; if (entry->is_zip && process_zip > 0) { /* verify local file header */ phar_zip_file_header local; phar_zip_data_desc desc; + php_stream *stream = phar_open_archive_fp(idata->phar); - if (SUCCESS != phar_open_archive_fp(idata->phar)) { - spprintf(error, 0, "phar error: unable to open zip-based phar archive \"%s\" to verify local file header for file \"%s\"", idata->phar->fname, ZSTR_VAL(entry->filename)); + if (!stream) { + spprintf(error, 0, "phar error: unable to open zip-based phar archive \"%s\" to verify local file header for file \"%s\"", + idata->phar->fname, ZSTR_VAL(entry->filename)); return FAILURE; } - php_stream_seek(phar_get_entrypfp(idata->internal_file), entry->header_offset, SEEK_SET); - - if (sizeof(local) != php_stream_read(phar_get_entrypfp(idata->internal_file), (char *) &local, sizeof(local))) { + php_stream_seek(stream, entry->header_offset, SEEK_SET); - spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (cannot read local file header for file \"%s\")", idata->phar->fname, ZSTR_VAL(entry->filename)); + if (sizeof(local) != php_stream_read(stream, (char *) &local, sizeof(local))) { + spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (cannot read local file header for file \"%s\")", + idata->phar->fname, ZSTR_VAL(entry->filename)); return FAILURE; } /* check for data descriptor */ if (((PHAR_ZIP_16(local.flags)) & 0x8) == 0x8) { - php_stream_seek(phar_get_entrypfp(idata->internal_file), + php_stream_seek(stream, entry->header_offset + sizeof(local) + PHAR_ZIP_16(local.filename_len) + PHAR_ZIP_16(local.extra_len) + entry->compressed_filesize, SEEK_SET); - if (sizeof(desc) != php_stream_read(phar_get_entrypfp(idata->internal_file), + if (sizeof(desc) != php_stream_read(stream, (char *) &desc, sizeof(desc))) { - spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (cannot read local data descriptor for file \"%s\")", idata->phar->fname, ZSTR_VAL(entry->filename)); + spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (cannot read local data descriptor for file \"%s\")", + idata->phar->fname, ZSTR_VAL(entry->filename)); return FAILURE; } if (desc.signature[0] == 'P' && desc.signature[1] == 'K') { @@ -2432,7 +2353,8 @@ zend_result phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char * } /* verify local header */ if (ZSTR_LEN(entry->filename) != PHAR_ZIP_16(local.filename_len) || entry->crc32 != PHAR_ZIP_32(local.crc32) || entry->uncompressed_filesize != PHAR_ZIP_32(local.uncompsize) || entry->compressed_filesize != PHAR_ZIP_32(local.compsize)) { - spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (local header of file \"%s\" does not match central directory)", idata->phar->fname, ZSTR_VAL(entry->filename)); + spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (local header of file \"%s\" does not match central directory)", + idata->phar->fname, ZSTR_VAL(entry->filename)); return FAILURE; } @@ -2460,7 +2382,8 @@ zend_result phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char * entry->is_crc_checked = 1; return SUCCESS; } else { - spprintf(error, 0, "phar error: internal corruption of phar \"%s\" (crc32 mismatch on file \"%s\")", idata->phar->fname, ZSTR_VAL(entry->filename)); + spprintf(error, 0, "phar error: internal corruption of phar \"%s\" (crc32 mismatch on file \"%s\")", + idata->phar->fname, ZSTR_VAL(entry->filename)); return FAILURE; } } @@ -2492,47 +2415,53 @@ static int phar_flush_clean_deleted_apply(zval *zv) /* {{{ */ #include "stub.h" /* Generated phar_get_stub() function from makestub.php script */ -zend_string *phar_create_default_stub(const char *index_php, const char *web_index, char **error) /* {{{ */ +zend_string *phar_create_default_stub(const zend_string *php_index_str, const zend_string *web_index_str, char **error) /* {{{ */ { - size_t index_len, web_len; + const char *php_index; + const char *web_index; + size_t php_len, web_len; if (error) { *error = NULL; } - if (!index_php) { - index_php = "index.php"; - } - - if (!web_index) { - web_index = "index.php"; - } - - index_len = strlen(index_php); - web_len = strlen(web_index); - - if (index_len > 400) { - /* ridiculous size not allowed for index.php startup filename */ - if (error) { - spprintf(error, 0, "Illegal filename passed in for stub creation, was %zd characters long, and only 400 or less is allowed", index_len); + if (!php_index_str) { + php_index = "index.php"; + php_len = strlen("index.php"); + } else { + php_index = ZSTR_VAL(php_index_str); + php_len = ZSTR_LEN(php_index_str); + if (php_len > 400) { + /* ridiculous size not allowed for index.php startup filename */ + if (error) { + spprintf(error, 0, "Illegal filename passed in for stub creation, was %zd characters long, and only 400 or less is allowed", php_len); + } return NULL; } } - if (web_len > 400) { - /* ridiculous size not allowed for index.php startup filename */ - if (error) { - spprintf(error, 0, "Illegal web filename passed in for stub creation, was %zd characters long, and only 400 or less is allowed", web_len); + if (!web_index_str) { + web_index = "index.php"; + web_len = strlen("index.php"); + } else { + web_index = ZSTR_VAL(web_index_str); + web_len = ZSTR_LEN(web_index_str); + + if (web_len > 400) { + /* ridiculous size not allowed for index.php startup filename */ + if (error) { + spprintf(error, 0, "Illegal web filename passed in for stub creation, was %zd characters long, and only 400 or less is allowed", web_len); + } return NULL; } } - return phar_get_stub(index_php, web_index, index_len+1, web_len+1); + return phar_get_stub(php_index, web_index, php_len+1, web_len+1); } /* }}} */ -void phar_flush(phar_archive_data *phar, char **error) { - phar_flush_ex(phar, NULL, false, error); +ZEND_ATTRIBUTE_NONNULL int phar_flush(phar_archive_data *phar, char **error) { + return phar_flush_ex(phar, NULL, false, error); } /** @@ -2540,13 +2469,14 @@ void phar_flush(phar_archive_data *phar, char **error) { * * if user_stub is NULL the default or existing stub should be used */ -void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_default_stub, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_default_stub, char **error) /* {{{ */ { static const char halt_stub[] = "__HALT_COMPILER();"; phar_entry_info *entry, *newentry; size_t halt_offset; - int restore_alias_len, global_flags = 0; + uint32_t restore_alias_len; + uint32_t global_flags = 0; bool must_close_old_file = false; bool has_dirs = false; char manifest[18], entry_buffer[24]; @@ -2565,34 +2495,28 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa php_stream *shared_cfp = NULL; if (phar->is_persistent) { - if (error) { - spprintf(error, 0, "internal error: attempt to flush cached zip-based phar \"%s\"", phar->fname); - } - return; + spprintf(error, 0, "internal error: attempt to flush cached zip-based phar \"%s\"", phar->fname); + return EOF; } - if (error) { - *error = NULL; - } + *error = NULL; if (!zend_hash_num_elements(&phar->manifest) && !user_stub) { - return; + return EOF; } zend_hash_clean(&phar->virtual_dirs); if (phar->is_zip) { - phar_zip_flush(phar, user_stub, is_default_stub, error); - return; + return phar_zip_flush(phar, user_stub, is_default_stub, error); } if (phar->is_tar) { - phar_tar_flush(phar, user_stub, is_default_stub, error); - return; + return phar_tar_flush(phar, user_stub, is_default_stub, error); } if (PHAR_G(readonly)) { - return; + return EOF; } if (phar->fp && !phar->is_brandnew) { @@ -2605,13 +2529,11 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa } newfile = php_stream_fopen_tmpfile(); if (!newfile) { - if (error) { - spprintf(error, 0, "unable to create temporary file"); - } + *error = estrdup("unable to create temporary file"); if (must_close_old_file) { php_stream_close(oldfile); } - return; + return EOF; } if (user_stub) { @@ -2622,10 +2544,8 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa php_stream_close(oldfile); } php_stream_close(newfile); - if (error) { - spprintf(error, 0, "illegal stub for phar \"%s\" (__HALT_COMPILER(); is missing)", phar->fname); - } - return; + spprintf(error, 0, "illegal stub for phar \"%s\" (__HALT_COMPILER(); is missing)", phar->fname); + return EOF; } size_t len = pos - ZSTR_VAL(user_stub) + strlen(halt_stub); @@ -2640,10 +2560,8 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa php_stream_close(oldfile); } php_stream_close(newfile); - if (error) { - spprintf(error, 0, "unable to create stub from string in new phar \"%s\"", phar->fname); - } - return; + spprintf(error, 0, "unable to create stub from string in new phar \"%s\"", phar->fname); + return EOF; } phar->halt_offset = len + end_sequence_len; } else { @@ -2663,17 +2581,15 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa php_stream_close(oldfile); } php_stream_close(newfile); - if (error) { - if (new_stub) { - spprintf(error, 0, "unable to create stub in new phar \"%s\"", phar->fname); - } else { - spprintf(error, 0, "unable to copy stub of old phar to new phar \"%s\"", phar->fname); - } + if (new_stub) { + spprintf(error, 0, "unable to create stub in new phar \"%s\"", phar->fname); + } else { + spprintf(error, 0, "unable to copy stub of old phar to new phar \"%s\"", phar->fname); } if (new_stub) { zend_string_free(new_stub); } - return; + return EOF; } if (new_stub) { zend_string_free(new_stub); @@ -2749,7 +2665,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa } continue; } - if (!phar_get_efp(entry, 0)) { + if (!phar_get_efp(entry, false)) { /* re-open internal file pointer just-in-time */ newentry = phar_open_jit(phar, entry, error); if (!newentry) { @@ -2760,16 +2676,14 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa } entry = newentry; } - file = phar_get_efp(entry, 0); - if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 1)) { + file = phar_get_efp(entry, false); + if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, true)) { if (must_close_old_file) { php_stream_close(oldfile); } php_stream_close(newfile); - if (error) { - spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); - } - return; + spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); + return EOF; } newcrc32 = php_crc32_bulk_init(); php_crc32_stream_bulk_update(&newcrc32, file, entry->uncompressed_filesize); @@ -2780,22 +2694,17 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa entry->compressed_filesize = entry->uncompressed_filesize; continue; } - filter = php_stream_filter_create(phar_compress_filter(entry, 0), NULL, 0); + filter = php_stream_filter_create(phar_compress_filter(entry, false), NULL, 0); if (!filter) { if (must_close_old_file) { php_stream_close(oldfile); } php_stream_close(newfile); - if (entry->flags & PHAR_ENT_COMPRESSED_GZ) { - if (error) { - spprintf(error, 0, "unable to gzip compress file \"%s\" to new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); - } - } else { - if (error) { - spprintf(error, 0, "unable to bzip2 compress file \"%s\" to new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); - } - } - return; + spprintf(error, 0, "unable to %s compress file \"%s\" to new phar \"%s\"", + entry->flags & PHAR_ENT_COMPRESSED_GZ ? "gzip" : "bzip2", + ZSTR_VAL(entry->filename), + phar->fname); + return EOF; } /* create new file that holds the compressed versions */ @@ -2807,9 +2716,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa entry->cfp = shared_cfp; if (!entry->cfp) { php_stream_filter_free(filter); - if (error) { - spprintf(error, 0, "unable to create temporary file"); - } + *error = estrdup("unable to create temporary file"); if (must_close_old_file) { php_stream_close(oldfile); } @@ -2820,15 +2727,14 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa ZEND_ASSERT(entry->header_offset == 0); entry->header_offset = php_stream_tell(entry->cfp); php_stream_flush(file); - if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 0)) { + if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, false)) { php_stream_filter_free(filter); if (must_close_old_file) { php_stream_close(oldfile); } php_stream_close(newfile); - if (error) { - spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); - } + spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", + ZSTR_VAL(entry->filename), phar->fname); goto cleanup; } php_stream_filter_append((&entry->cfp->writefilters), filter); @@ -2838,9 +2744,8 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa php_stream_close(oldfile); } php_stream_close(newfile); - if (error) { - spprintf(error, 0, "unable to copy compressed file contents of file \"%s\" while creating new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); - } + spprintf(error, 0, "unable to copy compressed file contents of file \"%s\" while creating new phar \"%s\"", + ZSTR_VAL(entry->filename), phar->fname); goto cleanup; } php_stream_filter_flush(filter, 1); @@ -2900,9 +2805,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa php_stream_close(newfile); phar->alias_len = restore_alias_len; - if (error) { - spprintf(error, 0, "unable to write manifest header of new phar \"%s\"", phar->fname); - } + spprintf(error, 0, "unable to write manifest header of new phar \"%s\"", phar->fname); goto cleanup; } @@ -2921,9 +2824,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa php_stream_close(newfile); phar->alias_len = restore_alias_len; - if (error) { - spprintf(error, 0, "unable to write manifest meta-data of new phar \"%s\"", phar->fname); - } + spprintf(error, 0, "unable to write manifest meta-data of new phar \"%s\"", phar->fname); goto cleanup; } @@ -2954,12 +2855,10 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa php_stream_close(oldfile); } php_stream_close(newfile); - if (error) { - if (entry->is_dir) { - spprintf(error, 0, "unable to write filename of directory \"%s\" to manifest of new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); - } else { - spprintf(error, 0, "unable to write filename of file \"%s\" to manifest of new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); - } + if (entry->is_dir) { + spprintf(error, 0, "unable to write filename of directory \"%s\" to manifest of new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); + } else { + spprintf(error, 0, "unable to write filename of file \"%s\" to manifest of new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); } goto cleanup; } @@ -2991,9 +2890,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa php_stream_close(newfile); - if (error) { - spprintf(error, 0, "unable to write temporary manifest of file \"%s\" to manifest of new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); - } + spprintf(error, 0, "unable to write temporary manifest of file \"%s\" to manifest of new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); goto cleanup; } @@ -3007,9 +2904,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa php_stream_close(newfile); - if (error) { - spprintf(error, 0, "unable to write manifest padding byte"); - } + *error = estrdup("unable to write manifest padding byte"); goto cleanup; } @@ -3026,15 +2921,13 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa file = entry->cfp; php_stream_seek(file, entry->header_offset, SEEK_SET); } else { - file = phar_get_efp(entry, 0); - if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 0)) { + file = phar_get_efp(entry, false); + if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, false)) { if (must_close_old_file) { php_stream_close(oldfile); } php_stream_close(newfile); - if (error) { - spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); - } + spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); goto cleanup; } } @@ -3044,9 +2937,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa php_stream_close(oldfile); } php_stream_close(newfile); - if (error) { - spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); - } + spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); goto cleanup; } @@ -3060,9 +2951,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa php_stream_close(newfile); - if (error) { - spprintf(error, 0, "unable to write contents of file \"%s\" to new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); - } + spprintf(error, 0, "unable to write contents of file \"%s\" to new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); goto cleanup; } @@ -3108,12 +2997,11 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa char *digest = NULL; size_t digest_len; - if (FAILURE == phar_create_signature(phar, newfile, &digest, &digest_len, error)) { - if (error) { - char *save = *error; - spprintf(error, 0, "phar error: unable to write signature: %s", save); - efree(save); - } + char *signature_error = NULL; + if (FAILURE == phar_create_signature(phar, newfile, &digest, &digest_len, &signature_error)) { + spprintf(error, 0, "phar error: unable to write signature: %s", signature_error); + efree(signature_error); + if (digest) { efree(digest); } @@ -3121,7 +3009,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa php_stream_close(oldfile); } php_stream_close(newfile); - return; + return EOF; } php_stream_write(newfile, digest, digest_len); @@ -3170,10 +3058,8 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa phar->fp = php_stream_open_wrapper(phar->fname, "w+b", IGNORE_URL|STREAM_MUST_SEEK|REPORT_ERRORS, NULL); if (!phar->fp) { phar->fp = newfile; - if (error) { - spprintf(error, 4096, "unable to open new phar \"%s\" for writing", phar->fname); - } - return; + spprintf(error, 4096, "unable to open new phar \"%s\" for writing", phar->fname); + return EOF; } if (phar->flags & PHAR_FILE_COMPRESSED_GZ) { @@ -3186,10 +3072,8 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa zend_array_destroy(Z_ARR(filterparams)); if (!filter) { - if (error) { - spprintf(error, 4096, "unable to compress all contents of phar \"%s\" using zlib, PHP versions older than 5.2.6 have a buggy zlib", phar->fname); - } - return; + spprintf(error, 4096, "unable to compress all contents of phar \"%s\" using zlib, PHP versions older than 5.2.6 have a buggy zlib", phar->fname); + return EOF; } php_stream_filter_append(&phar->fp->writefilters, filter); @@ -3216,12 +3100,11 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa } if (-1 == php_stream_seek(phar->fp, phar->halt_offset, SEEK_SET)) { - if (error) { - spprintf(error, 0, "unable to seek to __HALT_COMPILER(); in new phar \"%s\"", phar->fname); - } + spprintf(error, 0, "unable to seek to __HALT_COMPILER(); in new phar \"%s\"", phar->fname); + return EOF; } - return; + return 0; cleanup: if (shared_cfp != NULL) { @@ -3233,6 +3116,8 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa entry->header_offset = 0; } } ZEND_HASH_FOREACH_END(); + + return EOF; } /* }}} */ @@ -3269,7 +3154,7 @@ static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type) { zend_op_array *res; zend_string *name = NULL; - int failed; + bool failed; phar_archive_data *phar; if (!file_handle || !file_handle->filename) { @@ -3320,11 +3205,11 @@ static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type) } zend_try { - failed = 0; + failed = false; CG(zend_lineno) = 0; res = phar_orig_compile_file(file_handle, type); } zend_catch { - failed = 1; + failed = true; res = NULL; } zend_end_try(); 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_internal.h b/ext/phar/phar_internal.h index 736226783bef1..5ed213fb03e16 100644 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -105,8 +105,8 @@ ZEND_BEGIN_MODULE_GLOBALS(phar) /* for cached phars, this is a per-process store of fp/ufp */ phar_entry_fp *cached_fp; HashTable phar_alias_map; - int phar_SERVER_mung_list; char* cache_list; + int phar_SERVER_mung_list; bool readonly; bool manifest_cached; bool persist; @@ -150,8 +150,8 @@ ZEND_BEGIN_MODULE_GLOBALS(phar) /* phar_get_archive cache */ char* last_phar_name; uint32_t last_phar_name_len; - char* last_alias; uint32_t last_alias_len; + char* last_alias; phar_archive_data* last_phar; HashTable mime_types; ZEND_END_MODULE_GLOBALS(phar) @@ -196,6 +196,7 @@ typedef struct _phar_metadata_tracker { typedef struct _phar_entry_info { /* first bytes are exactly as in file */ uint32_t uncompressed_filesize; + /* modification time */ uint32_t timestamp; uint32_t compressed_filesize; uint32_t crc32; @@ -205,7 +206,6 @@ typedef struct _phar_entry_info { uint32_t old_flags; phar_metadata_tracker metadata_tracker; zend_string *filename; - enum phar_fp_type fp_type; /* offset within original phar file of the file contents */ zend_long offset_abs; /* offset within fp of the file contents */ @@ -214,7 +214,9 @@ typedef struct _phar_entry_info { zend_long header_offset; php_stream *fp; php_stream *cfp; + enum phar_fp_type fp_type; int fp_refcount; + unsigned int fileinfo_lock_count; char *tmp; phar_archive_data *phar; char *link; /* symbolic link to another file */ @@ -224,21 +226,21 @@ typedef struct _phar_entry_info { /* for stat */ unsigned short inode; - uint32_t is_crc_checked:1; - uint32_t is_modified:1; - uint32_t is_deleted:1; - uint32_t is_dir:1; + bool is_crc_checked:1; + bool is_modified:1; + bool is_deleted:1; + bool is_dir:1; /* this flag is used for mounted entries (external files mapped to location inside a phar */ - uint32_t is_mounted:1; + bool is_mounted:1; /* used when iterating */ - uint32_t is_temp_dir:1; + bool is_temp_dir:1; /* tar-based phar file stuff */ - uint32_t is_tar:1; + bool is_tar:1; /* zip-based phar file stuff */ - uint32_t is_zip:1; + bool is_zip:1; /* for cached phar entries */ - uint32_t is_persistent:1; + bool is_persistent:1; } phar_entry_info; /* information about a phar file (the archive itself) */ @@ -246,10 +248,10 @@ struct _phar_archive_data { char *fname; uint32_t fname_len; /* for phar_detect_fname_ext, this stores the location of the file extension within fname */ - char *ext; uint32_t ext_len; + char *ext; char *alias; - uint32_t alias_len; + uint32_t alias_len; char version[12]; size_t halt_offset; HashTable manifest; @@ -258,32 +260,31 @@ struct _phar_archive_data { /* hash of mounted directory paths */ HashTable mounted_dirs; uint32_t flags; - uint32_t min_timestamp; uint32_t max_timestamp; + int refcount; php_stream *fp; /* decompressed file contents are stored here */ php_stream *ufp; - int refcount; uint32_t sig_flags; uint32_t sig_len; char *signature; phar_metadata_tracker metadata_tracker; uint32_t phar_pos; /* if 1, then this alias was manually specified by the user and is not a permanent alias */ - uint32_t is_temporary_alias:1; - uint32_t is_modified:1; - uint32_t is_writeable:1; - uint32_t is_brandnew:1; + bool is_temporary_alias:1; + bool is_modified:1; + bool is_writeable:1; + bool is_brandnew:1; /* defer phar creation */ - uint32_t donotflush:1; + bool donotflush:1; /* zip-based phar variables */ - uint32_t is_zip:1; + bool is_zip:1; /* tar-based phar variables */ - uint32_t is_tar:1; + bool is_tar:1; /* PharData variables */ - uint32_t is_data:1; + bool is_data:1; /* for cached phar manifests */ - uint32_t is_persistent:1; + bool is_persistent:1; }; typedef struct _phar_entry_fp_info { @@ -404,27 +405,27 @@ void phar_request_initialize(void); void phar_object_init(void); void phar_destroy_phar_data(phar_archive_data *phar); -zend_result phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char **error, int process_zip); +ZEND_ATTRIBUTE_NONNULL zend_result phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char **error, int process_zip); zend_result phar_open_from_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error); -zend_result phar_open_or_create_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); -zend_result phar_create_or_parse_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); -zend_result phar_open_executed_filename(char *alias, size_t alias_len, char **error); +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_open_or_create_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_create_or_parse_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); +ZEND_ATTRIBUTE_NONNULL_ARGS(3) zend_result phar_open_executed_filename(char *alias, size_t alias_len, char **error); zend_result phar_free_alias(phar_archive_data *phar, char *alias, size_t alias_len); zend_result phar_get_archive(phar_archive_data **archive, char *fname, size_t fname_len, char *alias, size_t alias_len, char **error); zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t sig_type, char *sig, size_t sig_len, char *fname, char **signature, size_t *signature_len, char **error); -zend_result phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, size_t *signature_length, char **error); +ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, size_t *signature_length, char **error); /* utility functions */ -zend_string *phar_create_default_stub(const char *index_php, const char *web_index, char **error); -char *phar_decompress_filter(phar_entry_info * entry, int return_unknown); -char *phar_compress_filter(phar_entry_info * entry, int return_unknown); +zend_string *phar_create_default_stub(const zend_string *php_index_str, const zend_string *web_index_str, char **error); +const char *phar_decompress_filter(const phar_entry_info *entry, bool return_unknown); +const char *phar_compress_filter(const phar_entry_info *entry, bool return_unknown); /* void phar_remove_virtual_dirs(phar_archive_data *phar, char *filename, size_t filename_len); */ void phar_add_virtual_dirs(phar_archive_data *phar, char *filename, size_t filename_len); zend_result phar_mount_entry(phar_archive_data *phar, char *filename, size_t filename_len, char *path, size_t path_len); zend_string *phar_find_in_include_path(zend_string *file, phar_archive_data **pphar); -char *phar_fix_filepath(char *path, size_t *new_len, int use_cwd); -phar_entry_info * phar_open_jit(phar_archive_data *phar, phar_entry_info *entry, char **error); +char *phar_fix_filepath(char *path, size_t *new_len, bool use_cwd); +ZEND_ATTRIBUTE_NONNULL phar_entry_info * phar_open_jit(const phar_archive_data *phar, phar_entry_info *entry, char **error); void phar_parse_metadata_lazy(const char *buffer, phar_metadata_tracker *tracker, uint32_t zip_metadata_len, bool persistent); bool phar_metadata_tracker_has_data(const phar_metadata_tracker* tracker, bool persistent); /* If this has data, free it and set all values to undefined. */ @@ -434,24 +435,24 @@ void phar_metadata_tracker_clone(phar_metadata_tracker* tracker); void phar_metadata_tracker_try_ensure_has_serialized_data(phar_metadata_tracker* tracker, bool persistent); zend_result phar_metadata_tracker_unserialize_or_copy(phar_metadata_tracker* tracker, zval *value, bool persistent, HashTable *unserialize_options, const char* method_name); void destroy_phar_manifest_entry(zval *zv); -int phar_seek_efp(phar_entry_info *entry, zend_off_t offset, int whence, zend_off_t position, int follow_links); -php_stream *phar_get_efp(phar_entry_info *entry, int follow_links); -zend_result phar_copy_entry_fp(phar_entry_info *source, phar_entry_info *dest, char **error); -zend_result phar_open_entry_fp(phar_entry_info *entry, char **error, int follow_links); +int phar_seek_efp(phar_entry_info *entry, zend_off_t offset, int whence, zend_off_t position, bool follow_links); +php_stream *phar_get_efp(phar_entry_info *entry, bool follow_links); +ZEND_ATTRIBUTE_NONNULL zend_result phar_copy_entry_fp(phar_entry_info *source, phar_entry_info *dest, char **error); +ZEND_ATTRIBUTE_NONNULL zend_result phar_open_entry_fp(phar_entry_info *entry, char **error, bool follow_links); phar_entry_info *phar_get_link_source(phar_entry_info *entry); -zend_result phar_open_archive_fp(phar_archive_data *phar); +php_stream *phar_open_archive_fp(phar_archive_data *phar); zend_result phar_copy_on_write(phar_archive_data **pphar); /* tar functions in tar.c */ -bool phar_is_tar(char *buf, char *fname); +bool phar_is_tar(const char *buf, const char *fname); zend_result phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, char *alias, size_t alias_len, phar_archive_data** pphar, uint32_t compression, char **error); -zend_result phar_open_or_create_tar(char *fname, size_t fname_len, char *alias, size_t alias_len, int is_data, uint32_t options, phar_archive_data** pphar, char **error); -void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_default_stub, char **error); +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_open_or_create_tar(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_default_stub, char **error); /* zip functions in zip.c */ -int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alias, size_t alias_len, phar_archive_data** pphar, char **error); -int phar_open_or_create_zip(char *fname, size_t fname_len, char *alias, size_t alias_len, int is_data, uint32_t options, phar_archive_data** pphar, char **error); -void phar_zip_flush(phar_archive_data *archive, zend_string *user_stub, bool is_default_stub, char **error); +zend_result phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alias, size_t alias_len, phar_archive_data** pphar, char **error); +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_open_or_create_zip(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_zip_flush(phar_archive_data *archive, zend_string *user_stub, bool is_default_stub, char **error); #ifdef PHAR_MAIN extern const php_stream_wrapper php_stream_phar_wrapper; @@ -463,13 +464,13 @@ extern HashTable cached_alias; bool phar_archive_delref(phar_archive_data *phar); void phar_entry_delref(phar_entry_data *idata); -phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, size_t path_len, char **error, int security); -phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, size_t path_len, char dir, char **error, int security); -phar_entry_data *phar_get_or_create_entry_data(char *fname, size_t fname_len, char *path, size_t path_len, const char *mode, char allow_dir, char **error, int security); -zend_result phar_get_entry_data(phar_entry_data **ret, char *fname, size_t fname_len, char *path, size_t path_len, const char *mode, char allow_dir, char **error, int security); -void phar_flush_ex(phar_archive_data *archive, zend_string *user_stub, bool is_default_stub, char **error); -void phar_flush(phar_archive_data *archive, char **error); -zend_result phar_detect_phar_fname_ext(const char *filename, size_t filename_len, const char **ext_str, size_t *ext_len, int executable, int for_create, int is_complete); +phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, size_t path_len, char **error, bool security); +phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, size_t path_len, char dir, char **error, bool security); +ZEND_ATTRIBUTE_NONNULL phar_entry_data *phar_get_or_create_entry_data(char *fname, size_t fname_len, char *path, size_t path_len, const char *mode, char allow_dir, char **error, bool security, uint32_t timestamp); +ZEND_ATTRIBUTE_NONNULL zend_result phar_get_entry_data(phar_entry_data **ret, char *fname, size_t fname_len, char *path, size_t path_len, const char *mode, char allow_dir, char **error, bool security); +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_flush_ex(phar_archive_data *archive, zend_string *user_stub, bool is_default_stub, char **error); +ZEND_ATTRIBUTE_NONNULL int phar_flush(phar_archive_data *archive, char **error); +zend_result phar_detect_phar_fname_ext(const char *filename, size_t filename_len, const char **ext_str, size_t *ext_len, int executable, int for_create, bool is_complete); zend_result phar_split_fname(const char *filename, size_t filename_len, char **arch, size_t *arch_len, char **entry, size_t *entry_len, int executable, int for_create); typedef enum { @@ -484,6 +485,6 @@ typedef enum { pcr_err_empty_entry } phar_path_check_result; -phar_path_check_result phar_path_check(char **p, size_t *len, const char **error); +ZEND_ATTRIBUTE_NONNULL phar_path_check_result phar_path_check(char **p, size_t *len, const char **error); END_EXTERN_C() diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 9982074f73a81..17000ca3c0f17 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -34,7 +34,18 @@ static zend_class_entry *phar_ce_data; static zend_class_entry *phar_ce_PharException; static zend_class_entry *phar_ce_entry; -static int phar_file_type(HashTable *mimes, char *file, char **mime_type) /* {{{ */ +#define PHAR_FETCH_INTERNAL_EX(zv) (void *)((char *) Z_OBJ_P(zv) - Z_OBJ_P(zv)->handlers->offset); +#define PHAR_FETCH_INTERNAL() PHAR_FETCH_INTERNAL_EX(ZEND_THIS) + +#define PHAR_ARCHIVE_OBJECT() \ + phar_archive_object *phar_obj = PHAR_FETCH_INTERNAL(); \ + if (!phar_obj->archive) { \ + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \ + "Cannot call method on an uninitialized Phar object"); \ + RETURN_THROWS(); \ + } + +static int phar_file_type(const HashTable *mimes, const char *file, char **mime_type) /* {{{ */ { char *ext; phar_mime_type *mime; @@ -54,7 +65,7 @@ static int phar_file_type(HashTable *mimes, char *file, char **mime_type) /* {{{ } /* }}} */ -static void phar_mung_server_vars(char *fname, char *entry, size_t entry_len, char *basename, size_t request_uri_len) /* {{{ */ +static void phar_mung_server_vars(char *fname, char *entry, size_t entry_len, const char *basename, size_t request_uri_len) /* {{{ */ { HashTable *_SERVER; zval *stuff; @@ -140,7 +151,12 @@ static void phar_mung_server_vars(char *fname, char *entry, size_t entry_len, ch } /* }}} */ -static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char *mime_type, int code, char *entry, size_t entry_len, char *arch, char *basename, char *ru, size_t ru_len) /* {{{ */ +typedef enum { + PHAR_ACT_DO_EXIT, + PHAR_ACT_GRACEFULLY_RETURN, +} phar_action_status; + +static phar_action_status phar_file_action(phar_archive_data *phar, phar_entry_info *info, char *mime_type, int code, char *entry, size_t entry_len, char *arch, const char *basename, char *ru, size_t ru_len) /* {{{ */ { char *name = NULL, buf[8192]; const char *cwd; @@ -157,7 +173,6 @@ static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char switch (code) { case PHAR_MIME_PHPS: - efree(basename); /* highlight source */ if (entry[0] == '/') { spprintf(&name, 4096, "phar://%s%s", arch, entry); @@ -169,13 +184,9 @@ static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char highlight_file(name, &syntax_highlighter_ini); efree(name); -#ifdef PHP_WIN32 - efree(arch); -#endif - zend_bailout(); + return PHAR_ACT_DO_EXIT; case PHAR_MIME_OTHER: /* send headers, output file contents */ - efree(basename); ctr.line_len = spprintf((char **) &(ctr.line), 0, "Content-type: %s", mime_type); sapi_header_op(SAPI_HEADER_REPLACE, &ctr); efree((void *) ctr.line); @@ -184,11 +195,11 @@ static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char efree((void *) ctr.line); if (FAILURE == sapi_send_headers()) { - zend_bailout(); + return PHAR_ACT_DO_EXIT; } /* prepare to output */ - fp = phar_get_efp(info, 1); + fp = phar_get_efp(info, true); if (!fp) { char *error; @@ -197,12 +208,12 @@ static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error); efree(error); } - return -1; + return PHAR_ACT_GRACEFULLY_RETURN; } - fp = phar_get_efp(info, 1); + fp = phar_get_efp(info, true); } position = 0; - phar_seek_efp(info, 0, SEEK_SET, 0, 1); + phar_seek_efp(info, 0, SEEK_SET, 0, true); do { got = php_stream_read(fp, buf, MIN(8192, info->uncompressed_filesize - position)); @@ -215,11 +226,10 @@ static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char } } while (1); - zend_bailout(); + return PHAR_ACT_DO_EXIT; case PHAR_MIME_PHP: if (basename) { phar_mung_server_vars(arch, entry, entry_len, basename, ru_len); - efree(basename); } if (entry[0] == '/') { @@ -261,9 +271,6 @@ static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char } zend_destroy_file_handle(&file_handle); -#ifdef PHP_WIN32 - efree(arch); -#endif if (new_op_array) { ZVAL_UNDEF(&result); @@ -291,16 +298,15 @@ static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char efree(name); } zend_end_try(); - zend_bailout(); + return PHAR_ACT_DO_EXIT; } - - return PHAR_MIME_PHP; } - return -1; + + return PHAR_ACT_GRACEFULLY_RETURN; } /* }}} */ -static void phar_do_403(char *entry, size_t entry_len) /* {{{ */ +static void phar_do_403(void) /* {{{ */ { sapi_header_line ctr = {0}; @@ -314,16 +320,17 @@ static void phar_do_403(char *entry, size_t entry_len) /* {{{ */ } /* }}} */ -static void phar_do_404(phar_archive_data *phar, char *fname, size_t fname_len, char *f404, size_t f404_len, char *entry, size_t entry_len) /* {{{ */ +static void phar_do_404(phar_archive_data *phar, char *fname, size_t fname_len, zend_string *f404) /* {{{ */ { sapi_header_line ctr = {0}; phar_entry_info *info; - if (phar && f404_len) { - info = phar_get_entry_info(phar, f404, f404_len, NULL, 1); + if (phar && f404 && ZSTR_LEN(f404)) { + info = phar_get_entry_info(phar, ZSTR_VAL(f404), ZSTR_LEN(f404), NULL, true); if (info) { - phar_file_action(phar, info, "text/html", PHAR_MIME_PHP, f404, f404_len, fname, NULL, NULL, 0); + /* Status doesn't matter, we're exiting anyway. */ + phar_file_action(phar, info, "text/html", PHAR_MIME_PHP, ZSTR_VAL(f404), ZSTR_LEN(f404), fname, NULL, NULL, 0); return; } } @@ -341,9 +348,10 @@ static void phar_do_404(phar_archive_data *phar, char *fname, size_t fname_len, /* post-process REQUEST_URI and retrieve the actual request URI. This is for cases like http://localhost/blah.phar/path/to/file.php/extra/stuff which calls "blah.phar" file "path/to/file.php" with PATH_INFO "/extra/stuff" */ -static void phar_postprocess_ru_web(char *fname, size_t fname_len, char **entry, size_t *entry_len, char **ru, size_t *ru_len) /* {{{ */ +static void phar_postprocess_ru_web(const char *fname, size_t fname_len, const char *entry, size_t *entry_len, char **ru, size_t *ru_len) /* {{{ */ { - char *e = *entry + 1, *u = NULL, *u1 = NULL, *saveu = NULL; + const char *e = entry + 1; + char *u = NULL, *u1 = NULL, *saveu = NULL; size_t e_len = *entry_len - 1, u_len = 0; phar_archive_data *pphar; @@ -401,9 +409,9 @@ static void phar_postprocess_ru_web(char *fname, size_t fname_len, char **entry, PHP_METHOD(Phar, running) { zend_string *fname; - char *arch, *entry; - size_t arch_len, entry_len; - bool retphar = 1; + char *arch; + size_t arch_len; + bool retphar = true; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &retphar) == FAILURE) { RETURN_THROWS(); @@ -416,9 +424,8 @@ PHP_METHOD(Phar, running) if ( zend_string_starts_with_literal_ci(fname, "phar://") - && SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, &entry, &entry_len, 2, 0) + && SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, NULL, 2, 0) ) { - efree(entry); if (retphar) { RETVAL_STRINGL(ZSTR_VAL(fname), arch_len + 7); efree(arch); @@ -474,8 +481,7 @@ PHP_METHOD(Phar, mount) } #endif - if (fname_len > 7 && !memcmp(fname, "phar://", 7) && SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) { - efree(entry); + if (fname_len > 7 && !memcmp(fname, "phar://", 7) && SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, NULL, NULL, 2, 0)) { entry = NULL; if (path_len > 7 && !memcmp(path, "phar://", 7)) { @@ -550,8 +556,9 @@ PHP_METHOD(Phar, webPhar) zval *mimeoverride = NULL; zend_fcall_info rewrite_fci = {0}; zend_fcall_info_cache rewrite_fcc; - char *alias = NULL, *error, *index_php = NULL, *f404 = NULL, *ru = NULL; - size_t alias_len = 0, f404_len = 0, free_pathinfo = 0; + char *alias = NULL, *error, *index_php = NULL, *ru = NULL; + size_t alias_len = 0, free_pathinfo = 0; + zend_string *f404 = NULL; size_t ru_len = 0; char *fname, *path_info, *mime_type = NULL, *entry, *pt; const char *basename; @@ -561,8 +568,9 @@ PHP_METHOD(Phar, webPhar) phar_archive_data *phar = NULL; phar_entry_info *info = NULL; size_t sapi_mod_name_len = strlen(sapi_module.name); + phar_action_status status = PHAR_ACT_DO_EXIT; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!s!s!af!", &alias, &alias_len, &index_php, &index_php_len, &f404, &f404_len, &mimeoverride, &rewrite_fci, &rewrite_fcc) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!s!S!af!", &alias, &alias_len, &index_php, &index_php_len, &f404, &mimeoverride, &rewrite_fci, &rewrite_fcc) == FAILURE) { RETURN_THROWS(); } @@ -601,10 +609,8 @@ PHP_METHOD(Phar, webPhar) fname_len = ZSTR_LEN(zend_file_name); #ifdef PHP_WIN32 - if (memchr(fname, '\\', fname_len)) { - fname = estrndup(fname, fname_len); - phar_unixify_path_separators(fname, fname_len); - } + fname = estrndup(fname, fname_len); + phar_unixify_path_separators(fname, fname_len); #endif basename = zend_memrchr(fname, '/', fname_len); @@ -620,7 +626,7 @@ PHP_METHOD(Phar, webPhar) || (sapi_mod_name_len == sizeof("litespeed") - 1 && !strncmp(sapi_module.name, "litespeed", sizeof("litespeed") - 1))) { if (Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) != IS_UNDEF) { - HashTable *_server = Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]); + const HashTable *_server = Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]); zval *z_script_name, *z_path_info; if (NULL == (z_script_name = zend_hash_str_find(_server, "SCRIPT_NAME", sizeof("SCRIPT_NAME")-1)) || @@ -646,9 +652,7 @@ PHP_METHOD(Phar, webPhar) pt = estrndup(Z_STRVAL_P(z_script_name), Z_STRLEN_P(z_script_name)); } else { - char *testit; - - testit = sapi_getenv("SCRIPT_NAME", sizeof("SCRIPT_NAME")-1); + char *testit = sapi_getenv("SCRIPT_NAME", sizeof("SCRIPT_NAME")-1); if (!(pt = strstr(testit, basename))) { efree(testit); goto finish; @@ -669,6 +673,7 @@ PHP_METHOD(Phar, webPhar) } pt = estrndup(testit, (pt - testit) + (fname_len - (basename - fname))); + efree(testit); } not_cgi = 0; } else { @@ -691,62 +696,49 @@ PHP_METHOD(Phar, webPhar) zval params, retval; ZVAL_STRINGL(¶ms, entry, entry_len); + efree(entry); rewrite_fci.param_count = 1; rewrite_fci.params = ¶ms; rewrite_fci.retval = &retval; if (FAILURE == zend_call_function(&rewrite_fci, &rewrite_fcc)) { + zval_ptr_dtor_str(¶ms); if (!EG(exception)) { zend_throw_exception_ex(phar_ce_PharException, 0, "phar error: failed to call rewrite callback"); } - goto cleanup_fail; + goto cleanup_skip_entry; } - if (Z_TYPE_P(rewrite_fci.retval) == IS_UNDEF || Z_TYPE(retval) == IS_UNDEF) { - zend_throw_exception_ex(phar_ce_PharException, 0, "phar error: rewrite callback must return a string or false"); - goto cleanup_fail; - } + zval_ptr_dtor_str(¶ms); switch (Z_TYPE(retval)) { case IS_STRING: - efree(entry); + /* TODO: avoid relocation??? */ entry = estrndup(Z_STRVAL_P(rewrite_fci.retval), Z_STRLEN_P(rewrite_fci.retval)); entry_len = Z_STRLEN_P(rewrite_fci.retval); + zval_ptr_dtor_str(&retval); break; case IS_TRUE: case IS_FALSE: - phar_do_403(entry, entry_len); - - if (free_pathinfo) { - efree(path_info); - } - efree(pt); - - zend_bailout(); + phar_do_403(); + goto cleanup_skip_entry; default: + zval_ptr_dtor(&retval); zend_throw_exception_ex(phar_ce_PharException, 0, "phar error: rewrite callback must return a string or false"); - -cleanup_fail: - zval_ptr_dtor(¶ms); - if (free_pathinfo) { - efree(path_info); - } - efree(entry); - efree(pt); -#ifdef PHP_WIN32 - efree(fname); -#endif - RETURN_THROWS(); + goto cleanup_skip_entry; } } if (entry_len) { - phar_postprocess_ru_web(fname, fname_len, &entry, &entry_len, &ru, &ru_len); + phar_postprocess_ru_web(fname, fname_len, entry, &entry_len, &ru, &ru_len); } if (!entry_len || (entry_len == 1 && entry[0] == '/')) { efree(entry); + + bool is_entry_allocated = false; + /* direct request */ if (index_php_len) { entry = index_php; @@ -754,22 +746,17 @@ PHP_METHOD(Phar, webPhar) if (entry[0] != '/') { spprintf(&entry, 0, "/%s", index_php); ++entry_len; + is_entry_allocated = true; } } else { /* assume "index.php" is starting point */ - entry = estrndup("/index.php", sizeof("/index.php")); + entry = "/index.php"; entry_len = sizeof("/index.php")-1; } if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, NULL) || - (info = phar_get_entry_info(phar, entry, entry_len, NULL, 0)) == NULL) { - phar_do_404(phar, fname, fname_len, f404, f404_len, entry, entry_len); - - if (free_pathinfo) { - efree(path_info); - } - - zend_bailout(); + (info = phar_get_entry_info(phar, entry, entry_len, NULL, false)) == NULL) { + phar_do_404(phar, fname, fname_len, f404); } else { char *tmp = NULL, sa = '\0'; sapi_header_line ctr = {0}; @@ -796,21 +783,22 @@ PHP_METHOD(Phar, webPhar) *tmp = sa; } - if (free_pathinfo) { - efree(path_info); - } - sapi_header_op(SAPI_HEADER_REPLACE, &ctr); sapi_send_headers(); efree((void *) ctr.line); - zend_bailout(); } + + if (is_entry_allocated) { + efree(entry); + } + + goto cleanup_skip_entry; } if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, NULL) || - (info = phar_get_entry_info(phar, entry, entry_len, NULL, 0)) == NULL) { - phar_do_404(phar, fname, fname_len, f404, f404_len, entry, entry_len); - zend_bailout(); + (info = phar_get_entry_info(phar, entry, entry_len, NULL, false)) == NULL) { + phar_do_404(phar, fname, fname_len, f404); + goto cleanup; } if (mimeoverride && zend_hash_num_elements(Z_ARRVAL_P(mimeoverride))) { @@ -828,15 +816,7 @@ PHP_METHOD(Phar, webPhar) code = Z_LVAL_P(val); } else { zend_throw_exception_ex(phar_ce_PharException, 0, "Unknown mime type specifier used, only Phar::PHP, Phar::PHPS and a mime type string are allowed"); - if (free_pathinfo) { - efree(path_info); - } - efree(pt); - efree(entry); -#ifdef PHP_WIN32 - efree(fname); -#endif - RETURN_THROWS(); + goto cleanup; } break; case IS_STRING: @@ -845,15 +825,7 @@ PHP_METHOD(Phar, webPhar) break; default: zend_throw_exception_ex(phar_ce_PharException, 0, "Unknown mime type specifier used (not a string or int), only Phar::PHP, Phar::PHPS and a mime type string are allowed"); - if (free_pathinfo) { - efree(path_info); - } - efree(pt); - efree(entry); -#ifdef PHP_WIN32 - efree(fname); -#endif - RETURN_THROWS(); + goto cleanup; } } } @@ -862,7 +834,22 @@ PHP_METHOD(Phar, webPhar) if (!mime_type) { code = phar_file_type(&PHAR_G(mime_types), entry, &mime_type); } - phar_file_action(phar, info, mime_type, code, entry, entry_len, fname, pt, ru, ru_len); + status = phar_file_action(phar, info, mime_type, code, entry, entry_len, fname, pt, ru, ru_len); + +cleanup: + efree(entry); +cleanup_skip_entry: + if (free_pathinfo) { + efree(path_info); + } + efree(pt); + efree(ru); + + if (status == PHAR_ACT_DO_EXIT) { + if (!EG(exception)) { + zend_throw_unwind_exit(); + } + } finish: ; #ifdef PHP_WIN32 @@ -897,7 +884,7 @@ PHP_METHOD(Phar, mungServer) phar_request_initialize(); ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(mungvalues), data) { - + ZVAL_DEREF(data); if (Z_TYPE_P(data) != IS_STRING) { zend_throw_exception_ex(phar_ce_PharException, 0, "Non-string value passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME"); RETURN_THROWS(); @@ -911,8 +898,10 @@ PHP_METHOD(Phar, mungServer) PHAR_G(phar_SERVER_mung_list) |= PHAR_MUNG_SCRIPT_NAME; } else if (zend_string_equals_literal(Z_STR_P(data), "SCRIPT_FILENAME")) { PHAR_G(phar_SERVER_mung_list) |= PHAR_MUNG_SCRIPT_FILENAME; + } else { + zend_throw_exception_ex(phar_ce_PharException, 0, "Invalid value passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME"); + RETURN_THROWS(); } - // TODO Warning for invalid value? } ZEND_HASH_FOREACH_END(); } /* }}} */ @@ -926,9 +915,7 @@ PHP_METHOD(Phar, mungServer) */ PHP_METHOD(Phar, interceptFileFuncs) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); phar_intercept_functions(); } /* }}} */ @@ -939,11 +926,11 @@ PHP_METHOD(Phar, interceptFileFuncs) */ PHP_METHOD(Phar, createDefaultStub) { - char *index = NULL, *webindex = NULL, *error; + zend_string *index = NULL, *webindex = NULL; + char *error; zend_string *stub; - size_t index_len = 0, webindex_len = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|p!p!", &index, &index_len, &webindex, &webindex_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|P!P!", &index, &webindex) == FAILURE) { RETURN_THROWS(); } @@ -1002,9 +989,7 @@ PHP_METHOD(Phar, loadPhar) /* {{{ Returns the api version */ PHP_METHOD(Phar, apiVersion) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_STRINGL(PHP_PHAR_API_VERSION, sizeof(PHP_PHAR_API_VERSION)-1); } /* }}}*/ @@ -1021,23 +1006,11 @@ PHP_METHOD(Phar, canCompress) phar_request_initialize(); switch (method) { case PHAR_ENT_COMPRESSED_GZ: - if (PHAR_G(has_zlib)) { - RETURN_TRUE; - } else { - RETURN_FALSE; - } + RETURN_BOOL(PHAR_G(has_zlib)); case PHAR_ENT_COMPRESSED_BZ2: - if (PHAR_G(has_bz2)) { - RETURN_TRUE; - } else { - RETURN_FALSE; - } + RETURN_BOOL(PHAR_G(has_bz2)); default: - if (PHAR_G(has_zlib) || PHAR_G(has_bz2)) { - RETURN_TRUE; - } else { - RETURN_FALSE; - } + RETURN_BOOL(PHAR_G(has_zlib) || PHAR_G(has_bz2)); } } /* }}} */ @@ -1045,9 +1018,7 @@ PHP_METHOD(Phar, canCompress) /* {{{ Returns whether phar extension supports writing and creating phars */ PHP_METHOD(Phar, canWrite) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_BOOL(!PHAR_G(readonly)); } /* }}} */ @@ -1059,15 +1030,13 @@ PHP_METHOD(Phar, isValidPharFilename) const char *ext_str; size_t fname_len; size_t ext_len; - int is_executable; - bool executable = 1; + bool is_executable = true; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|b", &fname, &fname_len, &executable) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|b", &fname, &fname_len, &is_executable) == FAILURE) { RETURN_THROWS(); } - is_executable = executable; - RETVAL_BOOL(phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, is_executable, 2, 1) == SUCCESS); + RETURN_BOOL(phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, is_executable, 2, true) == SUCCESS); } /* }}} */ @@ -1122,11 +1091,11 @@ PHP_METHOD(Phar, __construct) zend_long format = 0; phar_archive_object *phar_obj; phar_archive_data *phar_data; - zval *zobj = ZEND_THIS, arg1, arg2; + zval arg1, arg2; - phar_obj = (phar_archive_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset); + phar_obj = PHAR_FETCH_INTERNAL(); - is_data = instanceof_function(Z_OBJCE_P(zobj), phar_ce_data); + is_data = instanceof_function(Z_OBJCE_P(ZEND_THIS), phar_ce_data); if (is_data) { if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|ls!l", &fname, &fname_len, &flags, &alias, &alias_len, &format) == FAILURE) { @@ -1185,8 +1154,8 @@ PHP_METHOD(Phar, __construct) } if (is_data && phar_data->is_tar && phar_data->is_brandnew && format == PHAR_FORMAT_ZIP) { - phar_data->is_zip = 1; - phar_data->is_tar = 0; + phar_data->is_zip = true; + phar_data->is_tar = false; } if (fname == arch) { @@ -1226,7 +1195,7 @@ PHP_METHOD(Phar, __construct) ZVAL_LONG(&arg2, flags); zend_call_known_instance_method_with_2_params(spl_ce_RecursiveDirectoryIterator->constructor, - Z_OBJ_P(zobj), NULL, &arg1, &arg2); + Z_OBJ_P(ZEND_THIS), NULL, &arg1, &arg2); zval_ptr_dtor(&arg1); @@ -1245,9 +1214,7 @@ PHP_METHOD(Phar, __construct) /* {{{ Return array of supported signature types */ PHP_METHOD(Phar, getSupportedSignatures) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); array_init(return_value); @@ -1272,9 +1239,7 @@ PHP_METHOD(Phar, getSupportedSignatures) /* {{{ Return array of supported comparession algorithms */ PHP_METHOD(Phar, getSupportedCompression) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); array_init(return_value); phar_request_initialize(); @@ -1292,9 +1257,9 @@ PHP_METHOD(Phar, getSupportedCompression) /* {{{ Completely remove a phar archive from memory and disk */ PHP_METHOD(Phar, unlinkArchive) { - char *fname, *error, *arch, *entry; + char *fname, *error, *arch; size_t fname_len; - size_t arch_len, entry_len; + size_t arch_len; phar_archive_data *phar; if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) { @@ -1321,16 +1286,14 @@ PHP_METHOD(Phar, unlinkArchive) if ( zend_file_name && zend_string_starts_with_literal_ci(zend_file_name, "phar://") - && SUCCESS == phar_split_fname(ZSTR_VAL(zend_file_name), ZSTR_LEN(zend_file_name), &arch, &arch_len, &entry, &entry_len, 2, 0) + && SUCCESS == phar_split_fname(ZSTR_VAL(zend_file_name), ZSTR_LEN(zend_file_name), &arch, &arch_len, NULL, NULL, 2, 0) ) { if (arch_len == fname_len && !memcmp(arch, fname, arch_len)) { zend_throw_exception_ex(phar_ce_PharException, 0, "phar archive \"%s\" cannot be unlinked from within itself", fname); efree(arch); - efree(entry); RETURN_THROWS(); } efree(arch); - efree(entry); } if (phar->is_persistent) { @@ -1356,24 +1319,12 @@ PHP_METHOD(Phar, unlinkArchive) } /* }}} */ -#define PHAR_ARCHIVE_OBJECT() \ - zval *zobj = ZEND_THIS; \ - phar_archive_object *phar_obj = (phar_archive_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset); \ - if (!phar_obj->archive) { \ - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \ - "Cannot call method on an uninitialized Phar object"); \ - RETURN_THROWS(); \ - } - /* {{{ if persistent, remove from the cache */ PHP_METHOD(Phar, __destruct) { - zval *zobj = ZEND_THIS; - phar_archive_object *phar_obj = (phar_archive_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset); + phar_archive_object *phar_obj = PHAR_FETCH_INTERNAL(); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); if (phar_obj->archive && phar_obj->archive->is_persistent) { zend_hash_str_del(&PHAR_G(phar_persist_map), (const char *) phar_obj->archive, sizeof(phar_obj->archive)); @@ -1390,17 +1341,55 @@ struct _phar_t { int count; }; +static zend_always_inline void phar_call_method_with_unwrap(zend_object *obj, const char *name, zval *rv) +{ + zend_call_method_with_0_params(obj, obj->ce, NULL, name, rv); + if (Z_ISREF_P(rv)) { + zend_unwrap_reference(rv); + } +} + +/* This is the same as phar_get_or_create_entry_data(), but allows overriding metadata via SplFileInfo. */ +static phar_entry_data *phar_build_entry_data(char *fname, size_t fname_len, char *path, size_t path_len, char **error, zval *file_info) +{ + uint32_t timestamp; + + /* Expects an instance of SplFileInfo if it is an object, which is verified in phar_build(). */ + if (Z_TYPE_P(file_info) == IS_OBJECT && Z_OBJCE_P(file_info)->type == ZEND_USER_CLASS) { + zval rv; + phar_call_method_with_unwrap(Z_OBJ_P(file_info), "getMTime", &rv); + + if (UNEXPECTED(Z_TYPE(rv) != IS_LONG)) { + /* Either it's a tentative type failure, an exception happened, or the function returned false to indicate failure. */ + *error = estrdup("getMTime() must return an int"); + return NULL; + } + + /* Sanity check bounds. See GH-14141. */ + if (ZEND_LONG_UINT_OVFL(Z_LVAL(rv))) { + *error = estrdup("timestamp is limited to 32-bit"); + return NULL; + } + + timestamp = Z_LVAL(rv); + } else { + timestamp = time(NULL); + } + + return phar_get_or_create_entry_data(fname, fname_len, path, path_len, "w+b", 0, error, true, timestamp); +} + static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */ { zval *value; - bool close_fp = 1; + bool close_fp = true; struct _phar_t *p_obj = (struct _phar_t*) puser; size_t str_key_len, base_len = ZSTR_LEN(p_obj->base); phar_entry_data *data; php_stream *fp; size_t fname_len; size_t contents_len; - char *fname, *error = NULL, *base = ZSTR_VAL(p_obj->base), *save = NULL, *temp = NULL; + char *fname = NULL, *error = NULL, *base = ZSTR_VAL(p_obj->base), *save = NULL, *temp = NULL; zend_string *opened; char *str_key; zend_class_entry *ce = p_obj->c; @@ -1455,56 +1444,71 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */ return ZEND_HASH_APPLY_STOP; } - close_fp = 0; + close_fp = false; opened = ZSTR_INIT_LITERAL("[stream]", 0); goto after_open_fp; case IS_OBJECT: if (instanceof_function(Z_OBJCE_P(value), spl_ce_SplFileInfo)) { - char *test = NULL; - spl_filesystem_object *intern = (spl_filesystem_object*)((char*)Z_OBJ_P(value) - Z_OBJ_P(value)->handlers->offset); + spl_filesystem_object *intern = PHAR_FETCH_INTERNAL_EX(value); if (!base_len) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Iterator %s returns an SplFileInfo object, so base directory must be specified", ZSTR_VAL(ce->name)); return ZEND_HASH_APPLY_STOP; } - switch (intern->type) { - case SPL_FS_DIR: { - zend_string *test_str = spl_filesystem_object_get_path(intern); - fname_len = spprintf(&fname, 0, "%s%c%s", ZSTR_VAL(test_str), DEFAULT_SLASH, intern->u.dir.entry.d_name); - zend_string_release_ex(test_str, /* persistent */ false); - if (php_stream_stat_path(fname, &ssb) == 0 && S_ISDIR(ssb.sb.st_mode)) { - /* ignore directories */ - efree(fname); - return ZEND_HASH_APPLY_KEEP; - } + zend_string *tmp_dir_str = NULL; - test = expand_filepath(fname, NULL); - efree(fname); + /* Take into account that SplFileObject may be overridden. + * The purpose here is to grab the path name of the file to add. */ + if (Z_OBJCE_P(value)->type == ZEND_USER_CLASS) { + zval rv; + phar_call_method_with_unwrap(Z_OBJ_P(value), "getPathname", &rv); - if (test) { - fname = test; - fname_len = strlen(fname); - } else { - zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Could not resolve file path"); - return ZEND_HASH_APPLY_STOP; + if (UNEXPECTED(Z_TYPE(rv) != IS_STRING)) { + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "getPathname() must return a string"); + return ZEND_HASH_APPLY_STOP; + } + tmp_dir_str = Z_STR(rv); + } else { + /* Not a user class, so we can grab the data internally quickly. */ + switch (intern->type) { + case SPL_FS_DIR: { + zend_string *test_str = spl_filesystem_object_get_path(intern); + const char slash = DEFAULT_SLASH; + tmp_dir_str = zend_string_concat3( + ZSTR_VAL(test_str), ZSTR_LEN(test_str), + &slash, 1, + intern->u.dir.entry.d_name, strlen(intern->u.dir.entry.d_name) + ); + zend_string_release_ex(test_str, /* persistent */ false); + break; } + case SPL_FS_INFO: + case SPL_FS_FILE: + fname = expand_filepath(ZSTR_VAL(intern->file_name), NULL); + break; + } + } - save = fname; - goto phar_spl_fileinfo; + if (tmp_dir_str) { + if (php_stream_stat_path(ZSTR_VAL(tmp_dir_str), &ssb) == 0 && S_ISDIR(ssb.sb.st_mode)) { + /* ignore directories */ + zend_string_release_ex(tmp_dir_str, /* persistent */ false); + return ZEND_HASH_APPLY_KEEP; } - case SPL_FS_INFO: - case SPL_FS_FILE: - fname = expand_filepath(ZSTR_VAL(intern->file_name), NULL); - if (!fname) { - zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Could not resolve file path"); - return ZEND_HASH_APPLY_STOP; - } - fname_len = strlen(fname); - save = fname; - goto phar_spl_fileinfo; + fname = expand_filepath(ZSTR_VAL(tmp_dir_str), NULL); + zend_string_release_ex(tmp_dir_str, /* persistent */ false); + } + + if (!fname) { + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Could not resolve file path"); + return ZEND_HASH_APPLY_STOP; } + + fname_len = strlen(fname); + save = fname; + goto phar_spl_fileinfo; } ZEND_FALLTHROUGH; default: @@ -1635,7 +1639,7 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */ return ZEND_HASH_APPLY_KEEP; } - if (!(data = phar_get_or_create_entry_data(phar_obj->archive->fname, phar_obj->archive->fname_len, str_key, str_key_len, "w+b", 0, &error, 1))) { + if (!(data = phar_build_entry_data(phar_obj->archive->fname, phar_obj->archive->fname_len, str_key, str_key_len, &error, value))) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s cannot be created: %s", str_key, error); efree(error); @@ -1671,8 +1675,6 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */ data->internal_file->offset_abs = data->internal_file->offset = php_stream_tell(p_obj->fp); data->fp = NULL; php_stream_copy_to_stream_ex(fp, p_obj->fp, PHP_STREAM_COPY_ALL, &contents_len); - data->internal_file->uncompressed_filesize = data->internal_file->compressed_filesize = - php_stream_tell(p_obj->fp) - data->internal_file->offset; if (php_stream_stat(fp, &ssb) != -1) { data->internal_file->flags = ssb.sb.st_mode & PHAR_ENT_PERM_MASK ; } else { @@ -1714,8 +1716,8 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */ PHP_METHOD(Phar, buildFromDirectory) { char *error; - bool apply_reg = 0; - zval arg, arg2, iter, iteriter, regexiter; + bool apply_reg = false; + zval iter, iteriter, regexiter; struct _phar_t pass; zend_string *dir, *regex = NULL; @@ -1731,54 +1733,31 @@ PHP_METHOD(Phar, buildFromDirectory) RETURN_THROWS(); } - if (SUCCESS != object_init_ex(&iter, spl_ce_RecursiveDirectoryIterator)) { - zval_ptr_dtor(&iter); - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to instantiate directory iterator for %s", phar_obj->archive->fname); - RETURN_THROWS(); - } - - ZVAL_STR(&arg, dir); - ZVAL_LONG(&arg2, SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS); - - zend_call_known_instance_method_with_2_params(spl_ce_RecursiveDirectoryIterator->constructor, - Z_OBJ(iter), NULL, &arg, &arg2); + zval args[2]; + ZVAL_STR(&args[0], dir); + ZVAL_LONG(&args[1], SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS); - if (EG(exception)) { - zval_ptr_dtor(&iter); + if (SUCCESS != object_init_with_constructor(&iter, spl_ce_RecursiveDirectoryIterator, 2, args, NULL)) { RETURN_THROWS(); } - if (SUCCESS != object_init_ex(&iteriter, spl_ce_RecursiveIteratorIterator)) { + if (SUCCESS != object_init_with_constructor(&iteriter, spl_ce_RecursiveIteratorIterator, 1, &iter, NULL)) { zval_ptr_dtor(&iter); - zval_ptr_dtor(&iteriter); - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to instantiate directory iterator for %s", phar_obj->archive->fname); - RETURN_THROWS(); - } - - zend_call_known_instance_method_with_1_params(spl_ce_RecursiveIteratorIterator->constructor, - Z_OBJ(iteriter), NULL, &iter); - - if (EG(exception)) { - zval_ptr_dtor(&iter); - zval_ptr_dtor(&iteriter); RETURN_THROWS(); } zval_ptr_dtor(&iter); if (regex && ZSTR_LEN(regex) > 0) { - apply_reg = 1; + apply_reg = true; + + ZVAL_COPY_VALUE(&args[0], &iteriter); + ZVAL_STR(&args[1], regex); - if (SUCCESS != object_init_ex(®exiter, spl_ce_RegexIterator)) { + if (SUCCESS != object_init_with_constructor(®exiter, spl_ce_RegexIterator, 2, args, NULL)) { zval_ptr_dtor(&iteriter); - zval_ptr_dtor(®exiter); - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to instantiate regex iterator for %s", phar_obj->archive->fname); RETURN_THROWS(); } - - ZVAL_STR(&arg2, regex); - zend_call_known_instance_method_with_2_params(spl_ce_RegexIterator->constructor, - Z_OBJ(regexiter), NULL, &iteriter, &arg2); } array_init(return_value); @@ -1790,6 +1769,10 @@ PHP_METHOD(Phar, buildFromDirectory) pass.ret = return_value; pass.fp = php_stream_fopen_tmpfile(); if (pass.fp == NULL) { + zval_ptr_dtor(&iteriter); + if (apply_reg) { + zval_ptr_dtor(®exiter); + } zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" unable to create temporary file", phar_obj->archive->fname); RETURN_THROWS(); } @@ -1937,7 +1920,7 @@ static zend_result phar_copy_file_contents(phar_entry_info *entry, php_stream *f ZEND_ASSERT(!entry->link); - if (FAILURE == phar_open_entry_fp(entry, &error, 1)) { + if (FAILURE == phar_open_entry_fp(entry, &error, true)) { if (error) { zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Cannot convert phar archive \"%s\", unable to open entry \"%s\" contents: %s", entry->phar->fname, ZSTR_VAL(entry->filename), error); @@ -1950,9 +1933,9 @@ 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, 0); + phar_seek_efp(entry, 0, SEEK_SET, 0, false); offset = php_stream_tell(fp); - if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(entry, 0), fp, entry->uncompressed_filesize, NULL)) { + if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(entry, false), 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; @@ -2143,7 +2126,7 @@ static zend_object *phar_rename_archive(phar_archive_data **sphar, char *ext) /* goto err_reused_oldpath; } if (!phar->is_data) { - if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &(phar->ext), &ext_len, 1, 1, 1)) { + if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &(phar->ext), &ext_len, 1, 1, true)) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "phar \"%s\" has invalid extension %s", phar->fname, ext); goto err_reused_oldpath; } @@ -2166,7 +2149,7 @@ static zend_object *phar_rename_archive(phar_archive_data **sphar, char *ext) /* } else { - if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &(phar->ext), &ext_len, 0, 1, 1)) { + if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &(phar->ext), &ext_len, 0, 1, true)) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "data phar \"%s\" has invalid extension %s", phar->fname, ext); goto err_reused_oldpath; } @@ -2184,7 +2167,7 @@ static zend_object *phar_rename_archive(phar_archive_data **sphar, char *ext) /* goto err_oldpath; } - phar_flush_ex(phar, NULL, 1, &error); + phar_flush_ex(phar, NULL, true, &error); if (error) { zend_hash_str_del(&(PHAR_G(phar_fname_map)), newpath, phar->fname_len); @@ -2202,17 +2185,12 @@ static zend_object *phar_rename_archive(phar_archive_data **sphar, char *ext) /* ce = phar_ce_archive; } - ZVAL_NULL(&ret); - if (SUCCESS != object_init_ex(&ret, ce)) { - zval_ptr_dtor(&ret); - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to instantiate phar object when converting archive \"%s\"", phar->fname); + ZVAL_STRINGL(&arg1, phar->fname, phar->fname_len); + zend_result result = object_init_with_constructor(&ret, ce, 1, &arg1, NULL); + zval_ptr_dtor_str(&arg1); + if (SUCCESS != result) { return NULL; } - - ZVAL_STRINGL(&arg1, phar->fname, phar->fname_len); - - zend_call_known_instance_method_with_1_params(ce->constructor, Z_OBJ(ret), NULL, &arg1); - zval_ptr_dtor(&arg1); return Z_OBJ(ret); err_reused_oldpath: @@ -2237,6 +2215,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; @@ -2244,13 +2228,13 @@ static zend_object *phar_convert_to_other(phar_archive_data *source, int convert switch (convert) { case PHAR_FORMAT_TAR: - phar->is_tar = 1; + phar->is_tar = true; break; case PHAR_FORMAT_ZIP: - phar->is_zip = 1; + phar->is_zip = true; break; default: - phar->is_data = 0; + phar->is_data = false; break; } @@ -2261,11 +2245,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; @@ -2289,6 +2269,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); @@ -2326,13 +2307,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; @@ -2347,12 +2333,11 @@ static zend_object *phar_convert_to_other(phar_archive_data *source, int convert PHP_METHOD(Phar, convertToExecutable) { char *ext = NULL; - int is_data; size_t ext_len = 0; uint32_t flags; zend_object *ret; zend_long format, method; - bool format_is_null = 1, method_is_null = 1; + bool format_is_null = true, method_is_null = true; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!l!s!", &format, &format_is_null, &method, &method_is_null, &ext, &ext_len) == FAILURE) { RETURN_THROWS(); @@ -2438,8 +2423,8 @@ PHP_METHOD(Phar, convertToExecutable) } } - is_data = phar_obj->archive->is_data; - phar_obj->archive->is_data = 0; + bool is_data = phar_obj->archive->is_data; + phar_obj->archive->is_data = false; ret = phar_convert_to_other(phar_obj->archive, format, ext, flags); phar_obj->archive->is_data = is_data; @@ -2458,12 +2443,11 @@ PHP_METHOD(Phar, convertToExecutable) PHP_METHOD(Phar, convertToData) { char *ext = NULL; - int is_data; size_t ext_len = 0; uint32_t flags; zend_object *ret; zend_long format, method; - bool format_is_null = 1, method_is_null = 1; + bool format_is_null = true, method_is_null = true; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!l!s!", &format, &format_is_null, &method, &method_is_null, &ext, &ext_len) == FAILURE) { RETURN_THROWS(); @@ -2548,8 +2532,8 @@ PHP_METHOD(Phar, convertToData) } } - is_data = phar_obj->archive->is_data; - phar_obj->archive->is_data = 1; + bool is_data = phar_obj->archive->is_data; + phar_obj->archive->is_data = true; ret = phar_convert_to_other(phar_obj->archive, (int)format, ext, flags); phar_obj->archive->is_data = is_data; @@ -2566,9 +2550,7 @@ PHP_METHOD(Phar, convertToData) */ PHP_METHOD(Phar, isCompressed) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHAR_ARCHIVE_OBJECT(); @@ -2589,9 +2571,7 @@ PHP_METHOD(Phar, isWritable) { php_stream_statbuf ssb; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHAR_ARCHIVE_OBJECT(); @@ -2600,11 +2580,8 @@ PHP_METHOD(Phar, isWritable) } if (SUCCESS != php_stream_stat_path(phar_obj->archive->fname, &ssb)) { - if (phar_obj->archive->is_brandnew) { - /* assume it works if the file doesn't exist yet */ - RETURN_TRUE; - } - RETURN_FALSE; + /* assume it works if the file doesn't exist yet */ + RETURN_BOOL(phar_obj->archive->is_brandnew); } RETURN_BOOL((ssb.sb.st_mode & (S_IWOTH | S_IWGRP | S_IWUSR)) != 0); @@ -2662,9 +2639,7 @@ PHP_METHOD(Phar, delete) /* {{{ Returns the alias for the Phar or NULL. */ PHP_METHOD(Phar, getAlias) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHAR_ARCHIVE_OBJECT(); @@ -2677,9 +2652,7 @@ PHP_METHOD(Phar, getAlias) /* {{{ Returns the real path to the phar archive on disk */ PHP_METHOD(Phar, getPath) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHAR_ARCHIVE_OBJECT(); @@ -2696,7 +2669,7 @@ PHP_METHOD(Phar, setAlias) char *error, *oldalias; phar_archive_data *fd_ptr; size_t oldalias_len; - int old_temp, readd = 0; + bool old_temp, readd = false; if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &new_alias) == FAILURE) { RETURN_THROWS(); @@ -2729,37 +2702,33 @@ PHP_METHOD(Phar, setAlias) RETURN_TRUE; } if (NULL != (fd_ptr = zend_hash_find_ptr(&(PHAR_G(phar_alias_map)), new_alias))) { - spprintf(&error, 0, "alias \"%s\" is already used for archive \"%s\" and cannot be used for other archives", ZSTR_VAL(new_alias), fd_ptr->fname); - if (SUCCESS == phar_free_alias(fd_ptr, ZSTR_VAL(new_alias), ZSTR_LEN(new_alias))) { - efree(error); - goto valid_alias; + if (SUCCESS != phar_free_alias(fd_ptr, ZSTR_VAL(new_alias), ZSTR_LEN(new_alias))) { + zend_throw_exception_ex(phar_ce_PharException, 0, "alias \"%s\" is already used for archive \"%s\" and cannot be used for other archives", ZSTR_VAL(new_alias), fd_ptr->fname); + RETURN_THROWS(); } - zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error); - efree(error); - RETURN_THROWS(); - } - if (!phar_validate_alias(ZSTR_VAL(new_alias), ZSTR_LEN(new_alias))) { + } else if (!phar_validate_alias(ZSTR_VAL(new_alias), ZSTR_LEN(new_alias))) { zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Invalid alias \"%s\" specified for phar \"%s\"", ZSTR_VAL(new_alias), phar_obj->archive->fname); RETURN_THROWS(); } -valid_alias: if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) { zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname); RETURN_THROWS(); } if (phar_obj->archive->alias_len && NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), phar_obj->archive->alias, phar_obj->archive->alias_len))) { zend_hash_str_del(&(PHAR_G(phar_alias_map)), phar_obj->archive->alias, phar_obj->archive->alias_len); - readd = 1; + readd = true; } + ZEND_ASSERT(!phar_obj->archive->is_persistent); + oldalias = phar_obj->archive->alias; oldalias_len = phar_obj->archive->alias_len; old_temp = phar_obj->archive->is_temporary_alias; phar_obj->archive->alias_len = ZSTR_LEN(new_alias); if (phar_obj->archive->alias_len) { - phar_obj->archive->alias = pestrndup(ZSTR_VAL(new_alias), ZSTR_LEN(new_alias), phar_obj->archive->is_persistent); + phar_obj->archive->alias = estrndup(ZSTR_VAL(new_alias), ZSTR_LEN(new_alias)); } else { phar_obj->archive->alias = NULL; } @@ -2768,6 +2737,7 @@ PHP_METHOD(Phar, setAlias) phar_flush(phar_obj->archive, &error); if (error) { + efree(phar_obj->archive->alias); phar_obj->archive->alias = oldalias; phar_obj->archive->alias_len = oldalias_len; phar_obj->archive->is_temporary_alias = old_temp; @@ -2792,9 +2762,7 @@ PHP_METHOD(Phar, setAlias) /* {{{ Return version info of Phar archive */ PHP_METHOD(Phar, getVersion) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHAR_ARCHIVE_OBJECT(); @@ -2805,9 +2773,7 @@ PHP_METHOD(Phar, getVersion) /* {{{ Do not flush a writeable phar (save its contents) until explicitly requested */ PHP_METHOD(Phar, startBuffering) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHAR_ARCHIVE_OBJECT(); @@ -2818,9 +2784,7 @@ PHP_METHOD(Phar, startBuffering) /* {{{ Returns whether write operations are flushing to disk immediately. */ PHP_METHOD(Phar, isBuffering) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHAR_ARCHIVE_OBJECT(); @@ -2833,9 +2797,7 @@ PHP_METHOD(Phar, stopBuffering) { char *error; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHAR_ARCHIVE_OBJECT(); @@ -2957,12 +2919,11 @@ PHP_METHOD(Phar, setStub) */ PHP_METHOD(Phar, setDefaultStub) { - char *index = NULL, *webindex = NULL, *error = NULL; + zend_string *index = NULL, *webindex = NULL; zend_string *stub = NULL; - size_t index_len = 0, webindex_len = 0; - int created_stub = 0; + bool created_stub = false; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!s!", &index, &index_len, &webindex, &webindex_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|P!P!", &index, &webindex) == FAILURE) { RETURN_THROWS(); } @@ -2990,6 +2951,7 @@ PHP_METHOD(Phar, setDefaultStub) RETURN_THROWS(); } + char *error = NULL; if (!phar_obj->archive->is_tar && !phar_obj->archive->is_zip) { stub = phar_create_default_stub(index, webindex, &error); @@ -3081,9 +3043,7 @@ PHP_METHOD(Phar, setSignatureAlgorithm) /* {{{ Returns a hash signature, or FALSE if the archive is unsigned. */ PHP_METHOD(Phar, getSignature) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHAR_ARCHIVE_OBJECT(); @@ -3128,9 +3088,7 @@ PHP_METHOD(Phar, getSignature) /* {{{ Return whether phar was modified */ PHP_METHOD(Phar, getModified) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHAR_ARCHIVE_OBJECT(); @@ -3157,7 +3115,7 @@ static int phar_set_compression(zval *zv, void *argument) /* {{{ */ static int phar_test_compression(zval *zv, void *argument) /* {{{ */ { - phar_entry_info *entry = (phar_entry_info *)Z_PTR_P(zv); + const phar_entry_info *entry = Z_PTR_P(zv); if (entry->is_deleted) { return ZEND_HASH_APPLY_KEEP; @@ -3166,12 +3124,14 @@ static int phar_test_compression(zval *zv, void *argument) /* {{{ */ if (!PHAR_G(has_bz2)) { if (entry->flags & PHAR_ENT_COMPRESSED_BZ2) { *(int *) argument = 0; + return ZEND_HASH_APPLY_STOP; } } if (!PHAR_G(has_zlib)) { if (entry->flags & PHAR_ENT_COMPRESSED_GZ) { *(int *) argument = 0; + return ZEND_HASH_APPLY_STOP; } } @@ -3388,10 +3348,7 @@ PHP_METHOD(Phar, decompressFiles) { char *error; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - - } + ZEND_PARSE_PARAMETERS_NONE(); PHAR_ARCHIVE_OBJECT(); @@ -3527,7 +3484,6 @@ PHP_METHOD(Phar, copy) PHP_METHOD(Phar, offsetExists) { zend_string *file_name; - phar_entry_info *entry; if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &file_name) == FAILURE) { RETURN_THROWS(); @@ -3535,19 +3491,15 @@ PHP_METHOD(Phar, offsetExists) PHAR_ARCHIVE_OBJECT(); - if (zend_hash_exists(&phar_obj->archive->manifest, file_name)) { - if (NULL != (entry = zend_hash_find_ptr(&phar_obj->archive->manifest, file_name))) { - if (entry->is_deleted) { - /* entry is deleted, but has not been flushed to disk yet */ - RETURN_FALSE; - } - } - - if (zend_string_starts_with_literal(file_name, ".phar")) { - /* none of these are real files, so they don't exist */ + const phar_entry_info *entry = zend_hash_find_ptr(&phar_obj->archive->manifest, file_name); + if (entry != NULL) { + if (entry->is_deleted) { + /* entry is deleted, but has not been flushed to disk yet */ RETURN_FALSE; } - RETURN_TRUE; + + /* none of these are real files, so they don't exist */ + RETURN_BOOL(!zend_string_starts_with_literal(file_name, ".phar")); } else { /* If the info class is not based on PharFileInfo, directories are not directly instantiable */ if (UNEXPECTED(!instanceof_function(phar_obj->spl.info_class, phar_ce_entry))) { @@ -3572,7 +3524,7 @@ PHP_METHOD(Phar, offsetGet) PHAR_ARCHIVE_OBJECT(); /* security is 0 here so that we can get a better error message than "entry doesn't exist" */ - if (!(entry = phar_get_entry_info_dir(phar_obj->archive, ZSTR_VAL(file_name), ZSTR_LEN(file_name), 1, &error, 0))) { + if (!(entry = phar_get_entry_info_dir(phar_obj->archive, ZSTR_VAL(file_name), ZSTR_LEN(file_name), 1, &error, false))) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s does not exist%s%s", ZSTR_VAL(file_name), error?", ":"", error?error:""); } else { if (zend_string_equals_literal(file_name, ".phar/stub.php")) { @@ -3645,7 +3597,7 @@ static void phar_add_file(phar_archive_data **pphar, zend_string *file_name, con } #endif - if (!(data = phar_get_or_create_entry_data((*pphar)->fname, (*pphar)->fname_len, filename, filename_len, "w+b", 0, &error, 1))) { + if (!(data = phar_get_or_create_entry_data((*pphar)->fname, (*pphar)->fname_len, filename, filename_len, "w+b", 0, &error, true, time(NULL)))) { if (error) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s does not exist and cannot be created: %s", filename, error); efree(error); @@ -3717,7 +3669,7 @@ static void phar_mkdir(phar_archive_data **pphar, zend_string *dir_name) char *error; phar_entry_data *data; - if (!(data = phar_get_or_create_entry_data((*pphar)->fname, (*pphar)->fname_len, ZSTR_VAL(dir_name), ZSTR_LEN(dir_name), "w+b", 2, &error, 1))) { + if (!(data = phar_get_or_create_entry_data((*pphar)->fname, (*pphar)->fname_len, ZSTR_VAL(dir_name), ZSTR_LEN(dir_name), "w+b", 2, &error, true, time(NULL)))) { if (error) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Directory %s does not exist and cannot be created: %s", ZSTR_VAL(dir_name), error); efree(error); @@ -3910,9 +3862,7 @@ PHP_METHOD(Phar, getStub) php_stream_filter *filter = NULL; phar_entry_info *stub; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHAR_ARCHIVE_OBJECT(); @@ -3927,15 +3877,15 @@ PHP_METHOD(Phar, getStub) RETURN_THROWS(); } if (stub->flags & PHAR_ENT_COMPRESSION_MASK) { - char *filter_name; + const char *filter_name = phar_decompress_filter(stub, false); - if ((filter_name = phar_decompress_filter(stub, 0)) != NULL) { + if (filter_name != NULL) { filter = php_stream_filter_create(filter_name, NULL, php_stream_is_persistent(fp)); } else { filter = NULL; } if (!filter) { - zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "phar error: unable to read stub of phar \"%s\" (cannot create %s filter)", phar_obj->archive->fname, phar_decompress_filter(stub, 1)); + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "phar error: unable to read stub of phar \"%s\" (cannot create %s filter)", phar_obj->archive->fname, phar_decompress_filter(stub, true)); RETURN_THROWS(); } php_stream_filter_append(&fp->readfilters, filter); @@ -4001,9 +3951,7 @@ PHP_METHOD(Phar, getStub) /* {{{ Returns TRUE if the phar has global metadata, FALSE otherwise. */ PHP_METHOD(Phar, hasMetadata) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHAR_ARCHIVE_OBJECT(); @@ -4032,7 +3980,7 @@ PHP_METHOD(Phar, getMetadata) /* }}} */ /* {{{ Modifies the phar metadata or throws */ -static zend_result serialize_metadata_or_throw(phar_metadata_tracker *tracker, int persistent, zval *metadata) +static zend_result serialize_metadata_or_throw(phar_metadata_tracker *tracker, bool persistent, zval *metadata) { php_serialize_data_t metadata_hash; smart_str main_metadata_str = {0}; @@ -4104,9 +4052,7 @@ PHP_METHOD(Phar, delMetadata) { char *error; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHAR_ARCHIVE_OBJECT(); @@ -4133,7 +4079,7 @@ PHP_METHOD(Phar, delMetadata) } /* }}} */ -static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, char *dest, size_t dest_len, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, const zend_string *path, char **error) /* {{{ */ { php_stream_statbuf ssb; size_t len; @@ -4161,7 +4107,7 @@ static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, cha if (virtual_file_ex(&new_state, ZSTR_VAL(entry->filename), NULL, CWD_EXPAND) != 0 || new_state.cwd_length <= 1) { if (EINVAL == errno && ZSTR_LEN(entry->filename) > 50) { - spprintf(error, 4096, "Cannot extract \"%.50s...\" to \"%s...\", extracted filename is too long for filesystem", ZSTR_VAL(entry->filename), dest); + spprintf(error, 4096, "Cannot extract \"%.50s...\" to \"%s...\", extracted filename is too long for filesystem", ZSTR_VAL(entry->filename), ZSTR_VAL(path)); } else { spprintf(error, 4096, "Cannot extract \"%s\", internal error", ZSTR_VAL(entry->filename)); } @@ -4183,7 +4129,7 @@ static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, cha } #endif - len = spprintf(&fullpath, 0, "%s/%s", dest, filename); + len = spprintf(&fullpath, 0, "%s/%s", ZSTR_VAL(path), filename); if (len >= MAXPATHLEN) { /* truncate for error message */ @@ -4224,9 +4170,9 @@ static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, cha slash = zend_memrchr(filename, '/', filename_len); if (slash) { - fullpath[dest_len + (slash - filename) + 1] = '\0'; + fullpath[ZSTR_LEN(path) + (slash - filename) + 1] = '\0'; } else { - fullpath[dest_len] = '\0'; + fullpath[ZSTR_LEN(path)] = '\0'; } if (FAILURE == php_stream_stat_path(fullpath, &ssb)) { @@ -4248,9 +4194,9 @@ static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, cha } if (slash) { - fullpath[dest_len + (slash - filename) + 1] = '/'; + fullpath[ZSTR_LEN(path) + (slash - filename) + 1] = '/'; } else { - fullpath[dest_len] = '/'; + fullpath[ZSTR_LEN(path)] = '/'; } filename = NULL; @@ -4269,10 +4215,11 @@ static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, cha return FAILURE; } - if ((phar_get_fp_type(entry) == PHAR_FP && (entry->flags & PHAR_ENT_COMPRESSION_MASK)) || !phar_get_efp(entry, 0)) { - if (FAILURE == phar_open_entry_fp(entry, error, 1)) { - if (error) { - spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to open internal file pointer: %s", ZSTR_VAL(entry->filename), fullpath, *error); + if ((phar_get_fp_type(entry) == PHAR_FP && (entry->flags & PHAR_ENT_COMPRESSION_MASK)) || !phar_get_efp(entry, false)) { + char *open_entry_error = NULL; + if (FAILURE == phar_open_entry_fp(entry, &open_entry_error, true)) { + if (open_entry_error) { + spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to open internal file pointer: %s", ZSTR_VAL(entry->filename), fullpath, open_entry_error); } else { spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to open internal file pointer", ZSTR_VAL(entry->filename), fullpath); } @@ -4282,14 +4229,14 @@ static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, cha } } - if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 0)) { + if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, false)) { spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to seek internal file pointer", ZSTR_VAL(entry->filename), fullpath); efree(fullpath); php_stream_close(fp); return FAILURE; } - if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(entry, 0), fp, entry->uncompressed_filesize, NULL)) { + if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(entry, false), fp, entry->uncompressed_filesize, NULL)) { spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", copying contents failed", ZSTR_VAL(entry->filename), fullpath); efree(fullpath); php_stream_close(fp); @@ -4310,28 +4257,28 @@ static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, cha } /* }}} */ -static int extract_helper(phar_archive_data *archive, zend_string *search, char *pathto, size_t pathto_len, bool overwrite, char **error) { /* {{{ */ +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 3, 5) static int extract_helper(const phar_archive_data *archive, zend_string *search, const zend_string *path_to, bool overwrite, char **error) { /* {{{ */ int extracted = 0; phar_entry_info *entry; if (!search) { /* nothing to match -- extract all files */ ZEND_HASH_MAP_FOREACH_PTR(&archive->manifest, entry) { - if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, error)) return -1; + if (FAILURE == phar_extract_file(overwrite, entry, path_to, error)) return -1; extracted++; } ZEND_HASH_FOREACH_END(); } else if (ZSTR_LEN(search) > 0 && '/' == ZSTR_VAL(search)[ZSTR_LEN(search) - 1]) { /* ends in "/" -- extract all entries having that prefix */ ZEND_HASH_MAP_FOREACH_PTR(&archive->manifest, entry) { if (!zend_string_starts_with(entry->filename, search)) continue; - if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, error)) return -1; + if (FAILURE == phar_extract_file(overwrite, entry, path_to, error)) return -1; extracted++; } ZEND_HASH_FOREACH_END(); } else { /* otherwise, looking for an exact match */ entry = zend_hash_find_ptr(&archive->manifest, search); if (NULL == entry) return 0; - if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, error)) return -1; + if (FAILURE == phar_extract_file(overwrite, entry, path_to, error)) return -1; return 1; } @@ -4344,9 +4291,8 @@ PHP_METHOD(Phar, extractTo) { php_stream *fp; php_stream_statbuf ssb; - char *pathto; + zend_string *path_to; zend_string *filename = NULL; - size_t pathto_len; int ret; zval *zval_file; HashTable *files_ht = NULL; @@ -4354,7 +4300,7 @@ PHP_METHOD(Phar, extractTo) char *error = NULL; ZEND_PARSE_PARAMETERS_START(1, 3) - Z_PARAM_PATH(pathto, pathto_len) + Z_PARAM_PATH_STR(path_to) Z_PARAM_OPTIONAL Z_PARAM_ARRAY_HT_OR_STR_OR_NULL(files_ht, filename) Z_PARAM_BOOL(overwrite) @@ -4372,30 +4318,27 @@ PHP_METHOD(Phar, extractTo) php_stream_close(fp); - if (pathto_len < 1) { + if (ZSTR_LEN(path_to) == 0) { zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "Invalid argument, extraction path must be non-zero length"); RETURN_THROWS(); } - if (pathto_len >= MAXPATHLEN) { - char *tmp = estrndup(pathto, 50); - /* truncate for error message */ - zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "Cannot extract to \"%s...\", destination directory is too long for filesystem", tmp); - efree(tmp); + if (ZSTR_LEN(path_to) >= MAXPATHLEN) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "Cannot extract to \"%.50s...\", destination directory is too long for filesystem", ZSTR_VAL(path_to)); RETURN_THROWS(); } - if (php_stream_stat_path(pathto, &ssb) < 0) { - ret = php_stream_mkdir(pathto, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL); + if (php_stream_stat_path(ZSTR_VAL(path_to), &ssb) < 0) { + ret = php_stream_mkdir(ZSTR_VAL(path_to), 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL); if (!ret) { zend_throw_exception_ex(spl_ce_RuntimeException, 0, - "Unable to create path \"%s\" for extraction", pathto); + "Unable to create path \"%s\" for extraction", ZSTR_VAL(path_to)); RETURN_THROWS(); } } else if (!(ssb.sb.st_mode & S_IFDIR)) { zend_throw_exception_ex(spl_ce_RuntimeException, 0, - "Unable to use path \"%s\" for extraction, it is a file, must be a directory", pathto); + "Unable to use path \"%s\" for extraction, it is a file, must be a directory", ZSTR_VAL(path_to)); RETURN_THROWS(); } @@ -4411,7 +4354,7 @@ PHP_METHOD(Phar, extractTo) "Invalid argument, array of filenames to extract contains non-string value"); RETURN_THROWS(); } - switch (extract_helper(phar_obj->archive, Z_STR_P(zval_file), pathto, pathto_len, overwrite, &error)) { + switch (extract_helper(phar_obj->archive, Z_STR_P(zval_file), path_to, overwrite, &error)) { case -1: zend_throw_exception_ex(phar_ce_PharException, 0, "Extraction from phar \"%s\" failed: %s", phar_obj->archive->fname, error); @@ -4427,7 +4370,7 @@ PHP_METHOD(Phar, extractTo) RETURN_TRUE; } - ret = extract_helper(phar_obj->archive, filename, pathto, pathto_len, overwrite, &error); + ret = extract_helper(phar_obj->archive, filename, path_to, overwrite, &error); if (-1 == ret) { zend_throw_exception_ex(phar_ce_PharException, 0, "Extraction from phar \"%s\" failed: %s", phar_obj->archive->fname, error); @@ -4452,13 +4395,13 @@ PHP_METHOD(PharFileInfo, __construct) phar_entry_object *entry_obj; phar_entry_info *entry_info; phar_archive_data *phar_data; - zval *zobj = ZEND_THIS, arg1; + zval arg1; if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) { RETURN_THROWS(); } - entry_obj = (phar_entry_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset); + entry_obj = PHAR_FETCH_INTERNAL(); if (entry_obj->entry) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot call constructor twice"); @@ -4485,7 +4428,7 @@ PHP_METHOD(PharFileInfo, __construct) RETURN_THROWS(); } - if ((entry_info = phar_get_entry_info_dir(phar_data, entry, entry_len, 1, &error, 1)) == NULL) { + if ((entry_info = phar_get_entry_info_dir(phar_data, entry, entry_len, 1, &error, true)) == NULL) { zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot access phar file entry '%s' in archive '%s'%s%s", entry, arch, error ? ", " : "", error ? error : ""); efree(arch); @@ -4498,63 +4441,64 @@ PHP_METHOD(PharFileInfo, __construct) entry_obj->entry = entry_info; if (!entry_info->is_persistent && !entry_info->is_temp_dir) { - ++entry_info->fp_refcount; + ++entry_info->fileinfo_lock_count; + /* The phar data must exist to keep the alias locked. */ + ZEND_ASSERT(!phar_data->is_persistent); + ++phar_data->refcount; } ZVAL_STRINGL(&arg1, fname, fname_len); zend_call_known_instance_method_with_1_params(spl_ce_SplFileInfo->constructor, - Z_OBJ_P(zobj), NULL, &arg1); + Z_OBJ_P(ZEND_THIS), NULL, &arg1); zval_ptr_dtor(&arg1); } /* }}} */ -#define PHAR_ENTRY_OBJECT() \ - zval *zobj = ZEND_THIS; \ - phar_entry_object *entry_obj = (phar_entry_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset); \ +#define PHAR_ENTRY_OBJECT_EX(throw) \ + phar_entry_object *entry_obj = PHAR_FETCH_INTERNAL(); \ if (!entry_obj->entry) { \ - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \ - "Cannot call method on an uninitialized PharFileInfo object"); \ - RETURN_THROWS(); \ + if (throw) { \ + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \ + "Cannot call method on an uninitialized PharFileInfo object"); \ + } \ + return; \ } +#define PHAR_ENTRY_OBJECT() PHAR_ENTRY_OBJECT_EX(true) + /* {{{ clean up directory-based entry objects */ PHP_METHOD(PharFileInfo, __destruct) { - zval *zobj = ZEND_THIS; - phar_entry_object *entry_obj = (phar_entry_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset); + ZEND_PARSE_PARAMETERS_NONE(); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + PHAR_ENTRY_OBJECT_EX(false); - if (!entry_obj->entry) { - return; - } + phar_entry_info *entry = entry_obj->entry; - if (entry_obj->entry->is_temp_dir) { - if (entry_obj->entry->filename) { - zend_string_efree(entry_obj->entry->filename); - entry_obj->entry->filename = NULL; + if (entry->is_temp_dir) { + if (entry->filename) { + zend_string_release_ex(entry->filename, false); + entry->filename = NULL; } - efree(entry_obj->entry); - } else if (!entry_obj->entry->is_persistent) { - --entry_obj->entry->fp_refcount; - /* It is necessarily still in the manifest, which will ultimately free this. */ + efree(entry); + entry_obj->entry = NULL; + } else if (!entry->is_persistent) { + --entry->fileinfo_lock_count; + /* The entry itself still lives in the manifest, + * which will either be freed here if the file info was the last reference; or freed later. */ + entry_obj->entry = NULL; + phar_archive_delref(entry->phar); } - - entry_obj->entry = NULL; } /* }}} */ /* {{{ Returns the compressed size */ PHP_METHOD(PharFileInfo, getCompressedSize) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHAR_ENTRY_OBJECT(); @@ -4566,7 +4510,7 @@ PHP_METHOD(PharFileInfo, getCompressedSize) PHP_METHOD(PharFileInfo, isCompressed) { zend_long method; - bool method_is_null = 1; + bool method_is_null = true; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &method, &method_is_null) == FAILURE) { RETURN_THROWS(); @@ -4595,9 +4539,7 @@ PHP_METHOD(PharFileInfo, isCompressed) /* {{{ Returns CRC32 code or throws an exception if not CRC checked */ PHP_METHOD(PharFileInfo, getCRC32) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHAR_ENTRY_OBJECT(); @@ -4619,9 +4561,7 @@ PHP_METHOD(PharFileInfo, getCRC32) /* {{{ Returns whether file entry is CRC checked */ PHP_METHOD(PharFileInfo, isCRCChecked) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHAR_ENTRY_OBJECT(); @@ -4632,9 +4572,7 @@ PHP_METHOD(PharFileInfo, isCRCChecked) /* {{{ Returns the Phar file entry flags */ PHP_METHOD(PharFileInfo, getPharFlags) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHAR_ENTRY_OBJECT(); @@ -4707,9 +4645,7 @@ PHP_METHOD(PharFileInfo, chmod) /* {{{ Returns the metadata of the entry */ PHP_METHOD(PharFileInfo, hasMetadata) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHAR_ENTRY_OBJECT(); @@ -4792,9 +4728,7 @@ PHP_METHOD(PharFileInfo, delMetadata) { char *error; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHAR_ENTRY_OBJECT(); @@ -4849,9 +4783,7 @@ PHP_METHOD(PharFileInfo, getContent) phar_entry_info *link; zend_string *str; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHAR_ENTRY_OBJECT(); @@ -4867,20 +4799,20 @@ PHP_METHOD(PharFileInfo, getContent) link = entry_obj->entry; } - if (SUCCESS != phar_open_entry_fp(link, &error, 0)) { + if (SUCCESS != phar_open_entry_fp(link, &error, false)) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "phar error: Cannot retrieve contents, \"%s\" in phar \"%s\": %s", ZSTR_VAL(entry_obj->entry->filename), entry_obj->entry->phar->fname, error); efree(error); RETURN_THROWS(); } - if (!(fp = phar_get_efp(link, 0))) { + if (!(fp = phar_get_efp(link, false))) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "phar error: Cannot retrieve contents of \"%s\" in phar \"%s\"", ZSTR_VAL(entry_obj->entry->filename), entry_obj->entry->phar->fname); RETURN_THROWS(); } - phar_seek_efp(link, 0, SEEK_SET, 0, 0); + phar_seek_efp(link, 0, SEEK_SET, 0, false); str = php_stream_copy_to_mem(fp, link->uncompressed_filesize, 0); if (str) { RETURN_STR(str); @@ -4950,7 +4882,7 @@ PHP_METHOD(PharFileInfo, compress) } /* decompress this file indirectly */ - if (SUCCESS != phar_open_entry_fp(entry_obj->entry, &error, 1)) { + if (SUCCESS != phar_open_entry_fp(entry_obj->entry, &error, true)) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "phar error: Cannot decompress bzip2-compressed file \"%s\" in phar \"%s\" in order to compress with gzip: %s", ZSTR_VAL(entry_obj->entry->filename), entry_obj->entry->phar->fname, error); efree(error); @@ -4981,7 +4913,7 @@ PHP_METHOD(PharFileInfo, compress) } /* decompress this file indirectly */ - if (SUCCESS != phar_open_entry_fp(entry_obj->entry, &error, 1)) { + if (SUCCESS != phar_open_entry_fp(entry_obj->entry, &error, true)) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "phar error: Cannot decompress gzip-compressed file \"%s\" in phar \"%s\" in order to compress with bzip2: %s", ZSTR_VAL(entry_obj->entry->filename), entry_obj->entry->phar->fname, error); efree(error); @@ -5023,9 +4955,7 @@ PHP_METHOD(PharFileInfo, decompress) char *error; char *compression_type; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHAR_ENTRY_OBJECT(); @@ -5086,7 +5016,7 @@ PHP_METHOD(PharFileInfo, decompress) RETURN_THROWS(); } /* decompress this file indirectly */ - if (SUCCESS != phar_open_entry_fp(entry_obj->entry, &error, 1)) { + if (SUCCESS != phar_open_entry_fp(entry_obj->entry, &error, true)) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Phar error: Cannot decompress %s-compressed file \"%s\" in phar \"%s\": %s", compression_type, ZSTR_VAL(entry_obj->entry->filename), entry_obj->entry->phar->fname, error); efree(error); diff --git a/ext/phar/phar_object_arginfo.h b/ext/phar/phar_object_arginfo.h index e6c5ac75e9e7a..c77876fc3647f 100644 --- a/ext/phar/phar_object_arginfo.h +++ b/ext/phar/phar_object_arginfo.h @@ -624,99 +624,99 @@ static zend_class_entry *register_class_Phar(zend_class_entry *class_entry_Recur zval const_BZ2_value; ZVAL_LONG(&const_BZ2_value, PHAR_ENT_COMPRESSED_BZ2); - zend_string *const_BZ2_name = zend_string_init_interned("BZ2", sizeof("BZ2") - 1, 1); + zend_string *const_BZ2_name = zend_string_init_interned("BZ2", sizeof("BZ2") - 1, true); zend_declare_typed_class_constant(class_entry, const_BZ2_name, &const_BZ2_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BZ2_name); + zend_string_release_ex(const_BZ2_name, true); zval const_GZ_value; ZVAL_LONG(&const_GZ_value, PHAR_ENT_COMPRESSED_GZ); - zend_string *const_GZ_name = zend_string_init_interned("GZ", sizeof("GZ") - 1, 1); + zend_string *const_GZ_name = zend_string_init_interned("GZ", sizeof("GZ") - 1, true); zend_declare_typed_class_constant(class_entry, const_GZ_name, &const_GZ_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_GZ_name); + zend_string_release_ex(const_GZ_name, true); zval const_NONE_value; ZVAL_LONG(&const_NONE_value, PHAR_ENT_COMPRESSED_NONE); - zend_string *const_NONE_name = zend_string_init_interned("NONE", sizeof("NONE") - 1, 1); + zend_string *const_NONE_name = zend_string_init_interned("NONE", sizeof("NONE") - 1, true); zend_declare_typed_class_constant(class_entry, const_NONE_name, &const_NONE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NONE_name); + zend_string_release_ex(const_NONE_name, true); zval const_PHAR_value; ZVAL_LONG(&const_PHAR_value, PHAR_FORMAT_PHAR); - zend_string *const_PHAR_name = zend_string_init_interned("PHAR", sizeof("PHAR") - 1, 1); + zend_string *const_PHAR_name = zend_string_init_interned("PHAR", sizeof("PHAR") - 1, true); zend_declare_typed_class_constant(class_entry, const_PHAR_name, &const_PHAR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PHAR_name); + zend_string_release_ex(const_PHAR_name, true); zval const_TAR_value; ZVAL_LONG(&const_TAR_value, PHAR_FORMAT_TAR); - zend_string *const_TAR_name = zend_string_init_interned("TAR", sizeof("TAR") - 1, 1); + zend_string *const_TAR_name = zend_string_init_interned("TAR", sizeof("TAR") - 1, true); zend_declare_typed_class_constant(class_entry, const_TAR_name, &const_TAR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TAR_name); + zend_string_release_ex(const_TAR_name, true); zval const_ZIP_value; ZVAL_LONG(&const_ZIP_value, PHAR_FORMAT_ZIP); - zend_string *const_ZIP_name = zend_string_init_interned("ZIP", sizeof("ZIP") - 1, 1); + zend_string *const_ZIP_name = zend_string_init_interned("ZIP", sizeof("ZIP") - 1, true); zend_declare_typed_class_constant(class_entry, const_ZIP_name, &const_ZIP_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ZIP_name); + zend_string_release_ex(const_ZIP_name, true); zval const_COMPRESSED_value; ZVAL_LONG(&const_COMPRESSED_value, PHAR_ENT_COMPRESSION_MASK); - zend_string *const_COMPRESSED_name = zend_string_init_interned("COMPRESSED", sizeof("COMPRESSED") - 1, 1); + zend_string *const_COMPRESSED_name = zend_string_init_interned("COMPRESSED", sizeof("COMPRESSED") - 1, true); zend_declare_typed_class_constant(class_entry, const_COMPRESSED_name, &const_COMPRESSED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_COMPRESSED_name); + zend_string_release_ex(const_COMPRESSED_name, true); zval const_PHP_value; ZVAL_LONG(&const_PHP_value, PHAR_MIME_PHP); - zend_string *const_PHP_name = zend_string_init_interned("PHP", sizeof("PHP") - 1, 1); + zend_string *const_PHP_name = zend_string_init_interned("PHP", sizeof("PHP") - 1, true); zend_declare_typed_class_constant(class_entry, const_PHP_name, &const_PHP_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PHP_name); + zend_string_release_ex(const_PHP_name, true); zval const_PHPS_value; ZVAL_LONG(&const_PHPS_value, PHAR_MIME_PHPS); - zend_string *const_PHPS_name = zend_string_init_interned("PHPS", sizeof("PHPS") - 1, 1); + zend_string *const_PHPS_name = zend_string_init_interned("PHPS", sizeof("PHPS") - 1, true); zend_declare_typed_class_constant(class_entry, const_PHPS_name, &const_PHPS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PHPS_name); + zend_string_release_ex(const_PHPS_name, true); zval const_MD5_value; ZVAL_LONG(&const_MD5_value, PHAR_SIG_MD5); - zend_string *const_MD5_name = zend_string_init_interned("MD5", sizeof("MD5") - 1, 1); + zend_string *const_MD5_name = zend_string_init_interned("MD5", sizeof("MD5") - 1, true); zend_declare_typed_class_constant(class_entry, const_MD5_name, &const_MD5_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_MD5_name); + zend_string_release_ex(const_MD5_name, true); zval const_OPENSSL_value; ZVAL_LONG(&const_OPENSSL_value, PHAR_SIG_OPENSSL); - zend_string *const_OPENSSL_name = zend_string_init_interned("OPENSSL", sizeof("OPENSSL") - 1, 1); + zend_string *const_OPENSSL_name = zend_string_init_interned("OPENSSL", sizeof("OPENSSL") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPENSSL_name, &const_OPENSSL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPENSSL_name); + zend_string_release_ex(const_OPENSSL_name, true); zval const_OPENSSL_SHA256_value; ZVAL_LONG(&const_OPENSSL_SHA256_value, PHAR_SIG_OPENSSL_SHA256); - zend_string *const_OPENSSL_SHA256_name = zend_string_init_interned("OPENSSL_SHA256", sizeof("OPENSSL_SHA256") - 1, 1); + zend_string *const_OPENSSL_SHA256_name = zend_string_init_interned("OPENSSL_SHA256", sizeof("OPENSSL_SHA256") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPENSSL_SHA256_name, &const_OPENSSL_SHA256_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPENSSL_SHA256_name); + zend_string_release_ex(const_OPENSSL_SHA256_name, true); zval const_OPENSSL_SHA512_value; ZVAL_LONG(&const_OPENSSL_SHA512_value, PHAR_SIG_OPENSSL_SHA512); - zend_string *const_OPENSSL_SHA512_name = zend_string_init_interned("OPENSSL_SHA512", sizeof("OPENSSL_SHA512") - 1, 1); + zend_string *const_OPENSSL_SHA512_name = zend_string_init_interned("OPENSSL_SHA512", sizeof("OPENSSL_SHA512") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPENSSL_SHA512_name, &const_OPENSSL_SHA512_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPENSSL_SHA512_name); + zend_string_release_ex(const_OPENSSL_SHA512_name, true); zval const_SHA1_value; ZVAL_LONG(&const_SHA1_value, PHAR_SIG_SHA1); - zend_string *const_SHA1_name = zend_string_init_interned("SHA1", sizeof("SHA1") - 1, 1); + zend_string *const_SHA1_name = zend_string_init_interned("SHA1", sizeof("SHA1") - 1, true); zend_declare_typed_class_constant(class_entry, const_SHA1_name, &const_SHA1_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SHA1_name); + zend_string_release_ex(const_SHA1_name, true); zval const_SHA256_value; ZVAL_LONG(&const_SHA256_value, PHAR_SIG_SHA256); - zend_string *const_SHA256_name = zend_string_init_interned("SHA256", sizeof("SHA256") - 1, 1); + zend_string *const_SHA256_name = zend_string_init_interned("SHA256", sizeof("SHA256") - 1, true); zend_declare_typed_class_constant(class_entry, const_SHA256_name, &const_SHA256_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SHA256_name); + zend_string_release_ex(const_SHA256_name, true); zval const_SHA512_value; ZVAL_LONG(&const_SHA512_value, PHAR_SIG_SHA512); - zend_string *const_SHA512_name = zend_string_init_interned("SHA512", sizeof("SHA512") - 1, 1); + zend_string *const_SHA512_name = zend_string_init_interned("SHA512", sizeof("SHA512") - 1, true); zend_declare_typed_class_constant(class_entry, const_SHA512_name, &const_SHA512_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SHA512_name); + zend_string_release_ex(const_SHA512_name, true); return class_entry; } diff --git a/ext/phar/phar_path_check.re b/ext/phar/phar_path_check.re index 77aa0b1953d3c..689ffaa512442 100644 --- a/ext/phar/phar_path_check.re +++ b/ext/phar/phar_path_check.re @@ -18,7 +18,7 @@ #include "phar_internal.h" -phar_path_check_result phar_path_check(char **s, size_t *len, const char **error) +ZEND_ATTRIBUTE_NONNULL phar_path_check_result phar_path_check(char **s, size_t *len, const char **error) { const unsigned char *p = (const unsigned char*)*s; const unsigned char *m; diff --git a/ext/phar/shortarc.php b/ext/phar/shortarc.php index 2d0d37d0dcc56..c85e08439e761 100644 --- a/ext/phar/shortarc.php +++ b/ext/phar/shortarc.php @@ -74,7 +74,7 @@ $a = realpath(Extract_Phar::$temp . DIRECTORY_SEPARATOR . $pt); if (!$a || strlen(dirname($a)) < strlen(Extract_Phar::$temp)) { header('HTTP/1.0 404 Not Found'); - echo "\n \n File Not Found<title>\n </head>\n <body>\n <h1>404 - File Not Found</h1>\n </body>\n</html>"; + echo "<html>\n <head>\n <title>File Not Found\n \n \n

404 - File Not Found

\n \n"; exit; } $b = pathinfo($a); @@ -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 2ac8e79c4c0bd..4bd1e85666b85 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -191,7 +191,7 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const cha /* strip leading "/" */ internal_file = estrndup(ZSTR_VAL(resource->path) + 1, ZSTR_LEN(resource->path) - 1); if (mode[0] == 'w' || (mode[0] == 'r' && mode[1] == '+')) { - if (NULL == (idata = phar_get_or_create_entry_data(ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), internal_file, strlen(internal_file), mode, 0, &error, 1))) { + if (NULL == (idata = phar_get_or_create_entry_data(ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), internal_file, strlen(internal_file), mode, 0, &error, true, time(NULL)))) { if (error) { php_stream_wrapper_log_error(wrapper, options, "%s", error); efree(error); @@ -209,23 +209,23 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const cha php_url_free(resource); efree(internal_file); - if (context && Z_TYPE(context->options) != IS_UNDEF && (pzoption = zend_hash_str_find(HASH_OF(&context->options), "phar", sizeof("phar")-1)) != NULL) { + if (context && Z_TYPE(context->options) != IS_UNDEF && (pzoption = zend_hash_str_find_ind(HASH_OF(&context->options), "phar", sizeof("phar")-1)) != NULL) { pharcontext = HASH_OF(pzoption); if (idata->internal_file->uncompressed_filesize == 0 && idata->internal_file->compressed_filesize == 0 - && (pzoption = zend_hash_str_find(pharcontext, "compress", sizeof("compress")-1)) != NULL + && (pzoption = zend_hash_str_find_ind(pharcontext, "compress", sizeof("compress")-1)) != NULL && Z_TYPE_P(pzoption) == IS_LONG && (Z_LVAL_P(pzoption) & ~PHAR_ENT_COMPRESSION_MASK) == 0 ) { idata->internal_file->flags &= ~PHAR_ENT_COMPRESSION_MASK; idata->internal_file->flags |= Z_LVAL_P(pzoption); } - if ((pzoption = zend_hash_str_find(pharcontext, "metadata", sizeof("metadata")-1)) != NULL) { + if ((pzoption = zend_hash_str_find_ind(pharcontext, "metadata", sizeof("metadata")-1)) != NULL) { phar_metadata_tracker_free(&idata->internal_file->metadata_tracker, idata->internal_file->is_persistent); metadata = pzoption; ZVAL_COPY_DEREF(&idata->internal_file->metadata_tracker.val, metadata); - idata->phar->is_modified = 1; + idata->phar->is_modified = true; } } if (opened_path) { @@ -242,7 +242,7 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const cha return NULL; } if (phar->is_tar || phar->is_zip) { - if ((FAILURE == phar_get_entry_data(&idata, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), ".phar/stub.php", sizeof(".phar/stub.php")-1, "r", 0, &error, 0)) || !idata) { + if ((FAILURE == phar_get_entry_data(&idata, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), ".phar/stub.php", sizeof(".phar/stub.php")-1, "r", 0, &error, false)) || !idata) { goto idata_error; } efree(internal_file); @@ -254,13 +254,13 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const cha } else { php_stream *stream = phar_get_pharfp(phar); if (stream == NULL) { - if (UNEXPECTED(FAILURE == phar_open_archive_fp(phar))) { + stream = phar_open_archive_fp(phar); + if (UNEXPECTED(!stream)) { php_stream_wrapper_log_error(wrapper, options, "phar error: could not reopen phar \"%s\"", ZSTR_VAL(resource->host)); efree(internal_file); php_url_free(resource); return NULL; } - stream = phar_get_pharfp(phar); } phar_entry_info *entry; @@ -290,7 +290,7 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const cha } } /* read-only access is allowed to magic files in .phar directory */ - if ((FAILURE == phar_get_entry_data(&idata, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), internal_file, strlen(internal_file), "r", 0, &error, 0)) || !idata) { + if ((FAILURE == phar_get_entry_data(&idata, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), internal_file, strlen(internal_file), "r", 0, &error, false)) || !idata) { idata_error: if (error) { php_stream_wrapper_log_error(wrapper, options, "%s", error); @@ -424,11 +424,9 @@ static int phar_stream_seek(php_stream *stream, zend_off_t offset, int whence, z zend_off_t temp_signed = (zend_off_t) temp; if (temp_signed > data->zero + (zend_off_t) entry->uncompressed_filesize) { - *newoffset = -1; /* FIXME: this will invalidate the ZEND_ASSERT(stream->position >= 0); assertion in streams.c */ return -1; } if (temp_signed < data->zero) { - *newoffset = -1; /* FIXME: this will invalidate the ZEND_ASSERT(stream->position >= 0); assertion in streams.c */ return -1; } res = php_stream_seek(data->fp, temp_signed, SEEK_SET); @@ -447,7 +445,7 @@ static ssize_t phar_stream_write(php_stream *stream, const char *buf, size_t cou 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); + php_stream_wrapper_log_error(stream->wrapper, stream->flags, "phar error: Could not write %zu characters to \"%s\" in phar \"%s\"", count, ZSTR_VAL(data->internal_file->filename), data->phar->fname); return -1; } data->position = php_stream_tell(data->fp) - data->zero; @@ -456,7 +454,7 @@ static ssize_t phar_stream_write(php_stream *stream, const char *buf, size_t cou } data->internal_file->compressed_filesize = data->internal_file->uncompressed_filesize; data->internal_file->old_flags = data->internal_file->flags; - data->internal_file->is_modified = 1; + data->internal_file->is_modified = true; return count; } /* }}} */ @@ -467,16 +465,17 @@ static ssize_t phar_stream_write(php_stream *stream, const char *buf, size_t cou static int phar_stream_flush(php_stream *stream) /* {{{ */ { char *error; + int ret; phar_entry_data *data = (phar_entry_data *) stream->abstract; if (data->internal_file->is_modified) { data->internal_file->timestamp = time(0); - phar_flush(data->phar, &error); + ret = phar_flush(data->phar, &error); if (error) { php_stream_wrapper_log_error(stream->wrapper, REPORT_ERRORS, "%s", error); efree(error); } - return EOF; + return ret; } else { return EOF; } @@ -546,7 +545,7 @@ static int phar_stream_stat(php_stream *stream, php_stream_statbuf *ssb) /* {{{ return -1; } - phar_dostat(data->phar, data->internal_file, ssb, 0); + phar_dostat(data->phar, data->internal_file, ssb, false); return 0; } /* }}} */ @@ -558,7 +557,7 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, const char *url, int f php_stream_statbuf *ssb, php_stream_context *context) /* {{{ */ { php_url *resource = NULL; - char *internal_file, *error; + char *internal_file; phar_archive_data *phar; phar_entry_info *entry; size_t internal_file_len; @@ -582,19 +581,13 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, const char *url, int f internal_file = ZSTR_VAL(resource->path) + 1; /* strip leading "/" */ /* find the phar in our trusty global hash indexed by alias (host of phar://blah.phar/file.whatever) */ - if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, &error)) { + if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, NULL)) { php_url_free(resource); - if (error) { - efree(error); - } return FAILURE; } - if (error) { - efree(error); - } if (*internal_file == '\0') { /* root directory requested */ - phar_dostat(phar, NULL, ssb, 1); + phar_dostat(phar, NULL, ssb, true); php_url_free(resource); return SUCCESS; } @@ -605,12 +598,12 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, const char *url, int f internal_file_len = strlen(internal_file); /* search through the manifest of files, and if we have an exact match, it's a file */ if (NULL != (entry = zend_hash_str_find_ptr(&phar->manifest, internal_file, internal_file_len))) { - phar_dostat(phar, entry, ssb, 0); + phar_dostat(phar, entry, ssb, false); php_url_free(resource); return SUCCESS; } if (zend_hash_str_exists(&(phar->virtual_dirs), internal_file, internal_file_len)) { - phar_dostat(phar, NULL, ssb, 1); + phar_dostat(phar, NULL, ssb, true); php_url_free(resource); return SUCCESS; } @@ -646,7 +639,7 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, const char *url, int f if (NULL == (entry = zend_hash_str_find_ptr(&phar->manifest, internal_file, internal_file_len))) { goto free_resource; } - phar_dostat(phar, entry, ssb, 0); + phar_dostat(phar, entry, ssb, false); php_url_free(resource); return SUCCESS; } @@ -665,7 +658,7 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int { php_url *resource; char *internal_file, *error; - int internal_file_len; + size_t internal_file_len; phar_entry_data *idata; phar_archive_data *pphar; @@ -699,7 +692,7 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int /* need to copy to strip leading "/", will get touched again */ internal_file = estrndup(ZSTR_VAL(resource->path) + 1, ZSTR_LEN(resource->path) - 1); internal_file_len = ZSTR_LEN(resource->path) - 1; - if (FAILURE == phar_get_entry_data(&idata, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), internal_file, internal_file_len, "r", 0, &error, 1)) { + if (FAILURE == phar_get_entry_data(&idata, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), internal_file, internal_file_len, "r", 0, &error, true)) { /* constraints of fp refcount were not met */ if (error) { php_stream_wrapper_log_error(wrapper, options, "unlink of \"%s\" failed: %s", url, error); @@ -739,8 +732,8 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from char *error; phar_archive_data *phar, *pfrom, *pto; phar_entry_info *entry; - int is_dir = 0; - int is_modified = 0; + bool is_dir = false; + bool is_modified = false; error = NULL; @@ -861,8 +854,8 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from zend_hash_del(&phar->manifest, entry->filename); return 0; } - is_modified = 1; - entry->is_modified = 1; + is_modified = true; + entry->is_modified = true; is_dir = entry->is_dir; } else { is_dir = zend_hash_str_exists(&(phar->virtual_dirs), ZSTR_VAL(resource_from->path)+1, ZSTR_LEN(resource_from->path)-1); @@ -897,8 +890,8 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from memcpy(ZSTR_VAL(new_str_key) + to_len, ZSTR_VAL(str_key) + from_len, ZSTR_LEN(str_key) - from_len); ZSTR_VAL(new_str_key)[ZSTR_LEN(new_str_key)] = 0; - is_modified = 1; - entry->is_modified = 1; + is_modified = true; + entry->is_modified = true; zend_string_release(entry->filename); entry->filename = zend_string_copy(new_str_key); diff --git a/ext/phar/stream.h b/ext/phar/stream.h index ce75b70dcba00..83b395b4cfca3 100644 --- a/ext/phar/stream.h +++ b/ext/phar/stream.h @@ -21,7 +21,7 @@ BEGIN_EXTERN_C() #include "ext/standard/url.h" php_url* phar_parse_url(http://github.com/php_stream_wrapper%20*wrapper,%20const%20char%20*filename,%20const%20char%20*mode,%20int%20options); -void phar_entry_remove(phar_entry_data *idata, char **error); +ZEND_ATTRIBUTE_NONNULL void phar_entry_remove(phar_entry_data *idata, char **error); static php_stream* phar_wrapper_open_url(http://github.com/php_stream_wrapper%20*wrapper,%20const%20char%20*path,%20const%20char%20*mode,%20int%20options,%20zend_string%20**opened_path,%20php_stream_context%20*context%20STREAMS_DC); static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from, const char *url_to, int options, php_stream_context *context); diff --git a/ext/phar/stub.h b/ext/phar/stub.h index aa70e703b79b7..2c62e05900ace 100644 --- a/ext/phar/stub.h +++ b/ext/phar/stub.h @@ -16,16 +16,18 @@ +----------------------------------------------------------------------+ */ -static inline zend_string* phar_get_stub(const char *index_php, const char *web, const int name_len, const int web_len) +static inline zend_string *phar_get_stub(const char *index_php, const char *web, size_t name_len, size_t web_len) { + /* Do NOT modify this file directly! + * Instead modify shortarc.php to change PHP code or makestub.php to change C code and then use makestub.php to generate this file. */ static const char newstub0[] = " 2,\n'c' => 'text/plain',\n'cc' => 'text/plain',\n'cpp' => 'text/plain',\n'c++' => 'text/plain',\n'dtd' => 'text/plain',\n'h' => 'text/plain',\n'log' => 'text/plain',\n'rng' => 'text/plain',\n'txt' => 'text/plain',\n'xsd' => 'text/plain',\n'php' => 1,\n'inc' => 1,\n'avi' => 'video/avi',\n'bmp' => 'image/bmp',\n'css' => 'text/css',\n'gif' => 'image/gif',\n'htm' => 'text/html',\n'html' => 'text/html',\n'htmls' => 'text/html',\n'ico' => 'image/x-ico',\n'jpe' => 'image/jpeg',\n'jpg' => 'image/jpeg',\n'jpeg' => 'image/jpeg',\n'js' => 'application/x-javascript',\n'midi' => 'audio/midi',\n'mid' => 'audio/midi',\n'mod' => 'audio/mod',\n'mov' => 'movie/quicktime',\n'mp3' => 'audio/mp3',\n'mpg' => 'video/mpeg',\n'mpeg' => 'video/mpeg',\n'pdf' => 'application/pdf',\n'png' => 'image/png',\n'swf' => 'application/shockwave-flash',\n'tif' => 'image/tiff',\n'tiff' => 'image/tiff',\n'wav' => 'audio/wav',\n'xbm' => 'image/xbm',\n'xml' => 'text/xml',\n);\n\nheader(\"Cache-Control: no-cache, must-revalidate\");\nheader(\"Pragma: no-cache\");\n\n$basename = basename(__FILE__);\nif (!strpos($_SERVER['REQUEST_URI'], $basename)) {\nchdir(Extract_Phar::$temp);\ninclude $web;\nreturn;\n}\n$pt = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], $basename) + strlen($basename));\nif (!$pt || $pt == '/') {\n$pt = $web;\nheader('HTTP/1.1 301 Moved Permanently');\nheader('Location: ' . $_SERVER['REQUEST_URI'] . '/' . $pt);\nexit;\n}\n$a = realpath(Extract_Phar::$temp . DIRECTORY_SEPARATOR . $pt);\nif (!$a || strlen(dirname($a)) < strlen("; - static const char newstub1_1[] = "Extract_Phar::$temp)) {\nheader('HTTP/1.0 404 Not Found');\necho \"\\n \\n File Not Found<title>\\n </head>\\n <body>\\n <h1>404 - File Not Found</h1>\\n </body>\\n</html>\";\nexit;\n}\n$b = pathinfo($a);\nif (!isset($b['extension'])) {\nheader('Content-Type: text/plain');\nheader('Content-Length: ' . filesize($a));\nreadfile($a);\nexit;\n}\nif (isset($mimes[$b['extension']])) {\nif ($mimes[$b['extension']] === 1) {\ninclude $a;\nexit;\n}\nif ($mimes[$b['extension']] === 2) {\nhighlight_file($a);\nexit;\n}\nheader('Content-Type: ' .$mimes[$b['extension']]);\nheader('Content-Length: ' . filesize($a));\nreadfile($a);\nexit;\n}\n}\n\nclass Extract_Phar\n{\nstatic $temp;\nstatic $origdir;\nconst GZ = 0x1000;\nconst BZ2 = 0x2000;\nconst MASK = 0x3000;\nconst START = '"; + static const char newstub1_1[] = "Extract_Phar::$temp)) {\nheader('HTTP/1.0 404 Not Found');\necho \"<html>\\n <head>\\n <title>File Not Found\\n \\n \\n

404 - File Not Found

\\n \\n\";\nexit;\n}\n$b = pathinfo($a);\nif (!isset($b['extension'])) {\nheader('Content-Type: text/plain');\nheader('Content-Length: ' . filesize($a));\nreadfile($a);\nexit;\n}\nif (isset($mimes[$b['extension']])) {\nif ($mimes[$b['extension']] === 1) {\ninclude $a;\nexit;\n}\nif ($mimes[$b['extension']] === 2) {\nhighlight_file($a);\nexit;\n}\nheader('Content-Type: ' .$mimes[$b['extension']]);\nheader('Content-Length: ' . filesize($a));\nreadfile($a);\nexit;\n}\n}\n\nclass Extract_Phar\n{\nstatic $temp;\nstatic $origdir;\nconst GZ = 0x1000;\nconst BZ2 = 0x2000;\nconst MASK = 0x3000;\nconst START = '"; static const char newstub2[] = "';\nconst LEN = "; - static const char newstub3_0[] = ";\n\nstatic function go($return = false)\n{\n$fp = fopen(__FILE__, 'rb');\nfseek($fp, self::LEN);\n$L = unpack('V', $a = fread($fp, 4));\n$m = '';\n\ndo {\n$read = 8192;\nif ($L[1] - strlen($m) < 8192) {\n$read = $L[1] - strlen($m);\n}\n$last = fread($fp, $read);\n$m .= $last;\n} while (strlen($last) && strlen($m) < $L[1]);\n\nif (strlen($m) < $L[1]) {\ndie('ERROR: manifest length read was \"' .\nstrlen($m) .'\" should be \"' .\n$L[1] . '\"');\n}\n\n$info = self::_unpack($m);\n$f = $info['c'];\n\nif ($f & self::GZ) {\nif (!function_exists('gzinflate')) {\ndie('Error: zlib extension is not enabled -' .\n' gzinflate() function needed for zlib-compressed .phars');\n}\n}\n\nif ($f & self::BZ2) {\nif (!function_exists('bzdecompress')) {\ndie('Error: bzip2 extension is not enabled -' .\n' bzdecompress() function needed for bz2-compressed .phars');\n}\n}\n\n$temp = self::tmpdir();\n\nif (!$temp || !is_writable($temp)) {\n$sessionpath = session_save_path();\nif (strpos ($sessionpath, \";\") !== false)\n$sessionpath = substr ($sessionpath, strpos ($sessionpath, \";\")+1);\nif (!file_exists($sessionpath) || !is_dir($sessionpath)) {\ndie('Could not locate temporary directory to extract phar');\n}\n$temp = $sessionpath;\n}\n\n$temp .= '/pharextract/'.basename(__FILE__, '.phar');\nself::$temp = $temp;\nself::$origdir = getcwd();\n@mkdir($temp, 0777, true);\n$temp = realpath($temp);\n\nif (!file_exists($temp . DIRECTORY_SEPARATOR . md5_file(__FILE__))) {\nself::_removeTmpFiles($temp, getcwd());\n@mkdir($temp, 0777, true);\n@file_put_contents($temp . '/' . md5_file(__FILE__), '');\n\nforeach ($info['m'] as $path => $file) {\n$a = !file_exists(dirname($temp . '/' . $path));\n@mkdir(dirname($temp . '/' . $path), 0777, true);\nclearstatcache();\n\nif ($path[strlen($path) - 1] == '/') {\n@mkdir($temp . '/' . $path, 0777);\n} else {\nfile_put_contents($temp . '/' . $path, self::extractFile($path, $file, $fp));\n@chmod($temp . '/' . $path, 0666);\n}\n}\n}\n\nchdir($temp);\n\nif (!$return) {\ninclude self::START;\n}\n}\n\nstatic fun"; - static const char newstub3_1[] = "ction tmpdir()\n{\nif (strpos(PHP_OS, 'WIN') !== false) {\nif ($var = getenv('TMP') ? getenv('TMP') : getenv('TEMP')) {\nreturn $var;\n}\nif (is_dir('/temp') || mkdir('/temp')) {\nreturn realpath('/temp');\n}\nreturn false;\n}\nif ($var = getenv('TMPDIR')) {\nreturn $var;\n}\nreturn realpath('/tmp');\n}\n\nstatic function _unpack($m)\n{\n$info = unpack('V', substr($m, 0, 4));\n $l = unpack('V', substr($m, 10, 4));\n$m = substr($m, 14 + $l[1]);\n$s = unpack('V', substr($m, 0, 4));\n$o = 0;\n$start = 4 + $s[1];\n$ret['c'] = 0;\n\nfor ($i = 0; $i < $info[1]; $i++) {\n $len = unpack('V', substr($m, $start, 4));\n$start += 4;\n $savepath = substr($m, $start, $len[1]);\n$start += $len[1];\n $ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24)));\n$ret['m'][$savepath][3] = sprintf('%u', $ret['m'][$savepath][3]\n& 0xffffffff);\n$ret['m'][$savepath][7] = $o;\n$o += $ret['m'][$savepath][2];\n$start += 24 + $ret['m'][$savepath][5];\n$ret['c'] |= $ret['m'][$savepath][4] & self::MASK;\n}\nreturn $ret;\n}\n\nstatic function extractFile($path, $entry, $fp)\n{\n$data = '';\n$c = $entry[2];\n\nwhile ($c) {\nif ($c < 8192) {\n$data .= @fread($fp, $c);\n$c = 0;\n} else {\n$c -= 8192;\n$data .= @fread($fp, 8192);\n}\n}\n\nif ($entry[4] & self::GZ) {\n$data = gzinflate($data);\n} elseif ($entry[4] & self::BZ2) {\n$data = bzdecompress($data);\n}\n\nif (strlen($data) != $entry[0]) {\ndie(\"Invalid internal .phar file (size error \" . strlen($data) . \" != \" .\n$stat[7] . \")\");\n}\n\nif ($entry[3] != sprintf(\"%u\", crc32($data) & 0xffffffff)) {\ndie(\"Invalid internal .phar file (checksum error)\");\n}\n\nreturn $data;\n}\n\nstatic function _removeTmpFiles($temp, $origdir)\n{\nchdir($temp);\n\nforeach (glob('*') as $f) {\nif (file_exists($f)) {\nis_dir($f) ? @rmdir($f) : @unlink($f);\nif (file_exists($f) && is_dir($f)) {\nself::_removeTmpFiles($f, getcwd());\n}\n}\n}\n\n@rmdir($temp);\nclearstatcache();\nchdir($origdir);\n}\n}\n\nExtract_Phar::go();\n__HALT_COMPILER(); ?>"; + static const char newstub3_0[] = ";\n\nstatic function go($return = false)\n{\n$fp = fopen(__FILE__, 'rb');\nfseek($fp, self::LEN);\n$L = unpack('V', $a = (string)fread($fp, 4));\n$m = '';\n\ndo {\n$read = 8192;\nif ($L[1] - strlen($m) < 8192) {\n$read = $L[1] - strlen($m);\n}\n$last = (string)fread($fp, $read);\n$m .= $last;\n} while (strlen($last) && strlen($m) < $L[1]);\n\nif (strlen($m) < $L[1]) {\ndie('ERROR: manifest length read was \"' .\nstrlen($m) .'\" should be \"' .\n$L[1] . '\"');\n}\n\n$info = self::_unpack($m);\n$f = $info['c'];\n\nif ($f & self::GZ) {\nif (!function_exists('gzinflate')) {\ndie('Error: zlib extension is not enabled -' .\n' gzinflate() function needed for zlib-compressed .phars');\n}\n}\n\nif ($f & self::BZ2) {\nif (!function_exists('bzdecompress')) {\ndie('Error: bzip2 extension is not enabled -' .\n' bzdecompress() function needed for bz2-compressed .phars');\n}\n}\n\n$temp = self::tmpdir();\n\nif (!$temp || !is_writable($temp)) {\n$sessionpath = session_save_path();\nif (strpos ($sessionpath, \";\") !== false)\n$sessionpath = substr ($sessionpath, strpos ($sessionpath, \";\")+1);\nif (!file_exists($sessionpath) || !is_dir($sessionpath)) {\ndie('Could not locate temporary directory to extract phar');\n}\n$temp = $sessionpath;\n}\n\n$temp .= '/pharextract/'.basename(__FILE__, '.phar');\nself::$temp = $temp;\nself::$origdir = getcwd();\n@mkdir($temp, 0777, true);\n$temp = realpath($temp);\n\nif (!file_exists($temp . DIRECTORY_SEPARATOR . md5_file(__FILE__))) {\nself::_removeTmpFiles($temp, getcwd());\n@mkdir($temp, 0777, true);\n@file_put_contents($temp . '/' . md5_file(__FILE__), '');\n\nforeach ($info['m'] as $path => $file) {\n$a = !file_exists(dirname($temp . '/' . $path));\n@mkdir(dirname($temp . '/' . $path), 0777, true);\nclearstatcache();\n\nif ($path[strlen($path) - 1] == '/') {\n@mkdir($temp . '/' . $path, 0777);\n} else {\nfile_put_contents($temp . '/' . $path, self::extractFile($path, $file, $fp));\n@chmod($temp . '/' . $path, 0666);\n}\n}\n}\n\nchdir($temp);\n\nif (!$return) {\ninclude self::START;\n}\n"; + static const char newstub3_1[] = "}\n\nstatic function tmpdir()\n{\nif (strpos(PHP_OS, 'WIN') !== false) {\nif ($var = getenv('TMP') ? getenv('TMP') : getenv('TEMP')) {\nreturn $var;\n}\nif (is_dir('/temp') || mkdir('/temp')) {\nreturn realpath('/temp');\n}\nreturn false;\n}\nif ($var = getenv('TMPDIR')) {\nreturn $var;\n}\nreturn realpath('/tmp');\n}\n\nstatic function _unpack($m)\n{\n$info = unpack('V', substr($m, 0, 4));\n\n$l = unpack('V', substr($m, 10, 4));\n$m = substr($m, 14 + $l[1]);\n$s = unpack('V', substr($m, 0, 4));\n$o = 0;\n$start = 4 + $s[1];\n$ret['c'] = 0;\n\nfor ($i = 0; $i < $info[1]; $i++) {\n\n$len = unpack('V', substr($m, $start, 4));\n$start += 4;\n\n$savepath = substr($m, $start, $len[1]);\n$start += $len[1];\n\n\n\n$ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24)));\n$ret['m'][$savepath][3] = sprintf('%u', $ret['m'][$savepath][3]\n& 0xffffffff);\n$ret['m'][$savepath][7] = $o;\n$o += $ret['m'][$savepath][2];\n$start += 24 + $ret['m'][$savepath][5];\n$ret['c'] |= $ret['m'][$savepath][4] & self::MASK;\n}\nreturn $ret;\n}\n\nstatic function extractFile($path, $entry, $fp)\n{\n$data = '';\n$c = $entry[2];\n\nwhile ($c) {\nif ($c < 8192) {\n$data .= @fread($fp, $c);\n$c = 0;\n} else {\n$c -= 8192;\n$data .= @fread($fp, 8192);\n}\n}\n\nif ($entry[4] & self::GZ) {\n$data = gzinflate($data);\n} elseif ($entry[4] & self::BZ2) {\n$data = bzdecompress($data);\n}\n\nif (strlen($data) != $entry[0]) {\ndie(\"Invalid internal .phar file (size error \" . strlen($data) . \" != \" .\n$entry[0] . \")\");\n}\n\nif ($entry[3] != sprintf(\"%u\", crc32($data) & 0xffffffff)) {\ndie(\"Invalid internal .phar file (checksum error)\");\n}\n\nreturn $data;\n}\n\nstatic function _removeTmpFiles($temp, $origdir)\n{\nchdir($temp);\n\nforeach (glob('*') as $f) {\nif (file_exists($f)) {\nis_dir($f) ? @rmdir($f) : @unlink($f);\nif (file_exists($f) && is_dir($f)) {\nself::_removeTmpFiles($f, getcwd());\n}\n}\n}\n\n@rmdir($temp);\nclearstatcache();\nchdir($origdir);\n}\n}\n\nExtract_Phar::go();\n__HALT_COMPILER(); ?>"; - static const int newstub_len = 6623; + static const size_t newstub_len = 6641; - return strpprintf(name_len + web_len + newstub_len, "%s%s%s%s%s%s%d%s%s", newstub0, web, newstub1_0, newstub1_1, index_php, newstub2, name_len + web_len + newstub_len, newstub3_0, newstub3_1); + return strpprintf(name_len + web_len + newstub_len, "%s%s%s%s%s%s%zu%s%s", newstub0, web, newstub1_0, newstub1_1, index_php, newstub2, name_len + web_len + newstub_len, newstub3_0, newstub3_1); } diff --git a/ext/phar/tar.c b/ext/phar/tar.c index 7316e67ebb35f..91b6b04996d67 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -87,10 +87,10 @@ static zend_result phar_tar_octal(char *buf, uint32_t val, size_t len) /* {{{ */ } /* }}} */ -static uint32_t phar_tar_checksum(char *buf, size_t len) /* {{{ */ +static uint32_t phar_tar_checksum(const char *buf, size_t len) /* {{{ */ { uint32_t sum = 0; - char *end = buf + len; + const char *end = buf + len; while (buf != end) { sum += (unsigned char)*buf; @@ -100,7 +100,7 @@ static uint32_t phar_tar_checksum(char *buf, size_t len) /* {{{ */ } /* }}} */ -bool phar_is_tar(char *buf, char *fname) /* {{{ */ +bool phar_is_tar(const char *buf, const char *fname) /* {{{ */ { tar_header *header = (tar_header *) buf; uint32_t checksum = phar_tar_number(header->checksum, sizeof(header->checksum)); @@ -127,7 +127,7 @@ bool phar_is_tar(char *buf, char *fname) /* {{{ */ } /* }}} */ -zend_result phar_open_or_create_tar(char *fname, size_t fname_len, char *alias, size_t alias_len, int is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_open_or_create_tar(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { phar_archive_data *phar; zend_result ret = phar_create_or_parse_filename(fname, fname_len, alias, alias_len, is_data, options, &phar, error); @@ -136,9 +136,7 @@ zend_result phar_open_or_create_tar(char *fname, size_t fname_len, char *alias, return FAILURE; } - if (pphar) { - *pphar = phar; - } + *pphar = phar; phar->is_data = is_data; @@ -153,9 +151,7 @@ zend_result phar_open_or_create_tar(char *fname, size_t fname_len, char *alias, } /* we've reached here - the phar exists and is a regular phar */ - if (error) { - spprintf(error, 4096, "phar tar error: \"%s\" already exists as a regular phar and must be deleted from disk prior to creating as a tar-based phar", fname); - } + spprintf(error, 4096, "phar tar error: \"%s\" already exists as a regular phar and must be deleted from disk prior to creating as a tar-based phar", fname); return FAILURE; } /* }}} */ @@ -210,7 +206,7 @@ zend_result phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, ch tar_header *hdr; uint32_t sum1, sum2, size, old; phar_archive_data *myphar, *actual; - int last_was_longlink = 0; + bool last_was_longlink = false; size_t linkname_len; if (error) { @@ -237,11 +233,11 @@ zend_result phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, ch myphar->is_persistent = PHAR_G(persist); /* estimate number of entries, can't be certain with tar files */ zend_hash_init(&myphar->manifest, 2 + (totalsize >> 12), - zend_get_hash_value, destroy_phar_manifest_entry, (bool)myphar->is_persistent); + zend_get_hash_value, destroy_phar_manifest_entry, myphar->is_persistent); zend_hash_init(&myphar->mounted_dirs, 5, - zend_get_hash_value, NULL, (bool)myphar->is_persistent); + zend_get_hash_value, NULL, myphar->is_persistent); zend_hash_init(&myphar->virtual_dirs, 4 + (totalsize >> 11), - zend_get_hash_value, NULL, (bool)myphar->is_persistent); + zend_get_hash_value, NULL, myphar->is_persistent); myphar->is_tar = 1; /* remember whether this entire phar was compressed with gz/bzip2 */ myphar->flags = compression; @@ -361,7 +357,7 @@ zend_result phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, ch } if (!last_was_longlink && hdr->typeflag == 'L') { - last_was_longlink = 1; + last_was_longlink = true; /* support the ././@LongLink system for storing long filenames */ /* Check for overflow - bug 61065 */ @@ -465,7 +461,7 @@ zend_result phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, ch GC_MAKE_PERSISTENT_LOCAL(entry.filename); } } - last_was_longlink = 0; + last_was_longlink = false; phar_add_virtual_dirs(myphar, ZSTR_VAL(entry.filename), ZSTR_LEN(entry.filename)); @@ -730,7 +726,7 @@ static int phar_tar_writeheaders_int(phar_entry_info *entry, void *argument) /* } if (entry->is_deleted) { - if (entry->fp_refcount <= 0) { + if (entry->fp_refcount <= 0 && entry->fileinfo_lock_count == 0) { return ZEND_HASH_APPLY_REMOVE; } else { /* we can't delete this in-memory until it is closed */ @@ -819,18 +815,18 @@ static int phar_tar_writeheaders_int(phar_entry_info *entry, void *argument) /* /* write contents */ if (entry->uncompressed_filesize) { - if (FAILURE == phar_open_entry_fp(entry, fp->error, 0)) { + if (FAILURE == phar_open_entry_fp(entry, fp->error, false)) { return ZEND_HASH_APPLY_STOP; } - if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 0)) { + if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, false)) { if (fp->error) { spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, contents of file \"%s\" could not be written, seek failed", entry->phar->fname, ZSTR_VAL(entry->filename)); } return ZEND_HASH_APPLY_STOP; } - if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(entry, 0), fp->new, entry->uncompressed_filesize, NULL)) { + if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(entry, false), fp->new, entry->uncompressed_filesize, NULL)) { if (fp->error) { spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, contents of file \"%s\" could not be written", entry->phar->fname, ZSTR_VAL(entry->filename)); } @@ -845,10 +841,10 @@ static int phar_tar_writeheaders_int(phar_entry_info *entry, void *argument) /* /* open file pointers refer to this fp, do not free the stream */ switch (entry->fp_type) { case PHAR_FP: - fp->free_fp = 0; + fp->free_fp = false; break; case PHAR_UFP: - fp->free_ufp = 0; + fp->free_ufp = false; default: break; } @@ -877,7 +873,7 @@ static int phar_tar_writeheaders(zval *zv, void *argument) /* {{{ */ } /* }}} */ -static int phar_tar_setmetadata(const phar_metadata_tracker *tracker, phar_entry_info *entry, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL static int phar_tar_setmetadata(const phar_metadata_tracker *tracker, phar_entry_info *entry, char **error) /* {{{ */ { /* Copy the metadata from tracker to the new entry being written out to temporary files */ const zend_string *serialized_str; @@ -897,7 +893,7 @@ static int phar_tar_setmetadata(const phar_metadata_tracker *tracker, phar_entry entry->fp = php_stream_fopen_tmpfile(); entry->offset = entry->offset_abs = 0; if (entry->fp == NULL) { - spprintf(error, 0, "phar error: unable to create temporary file"); + *error = estrdup("phar error: unable to create temporary file"); return -1; } if (serialized_str && ZSTR_LEN(serialized_str) != php_stream_write(entry->fp, ZSTR_VAL(serialized_str), ZSTR_LEN(serialized_str))) { @@ -910,7 +906,7 @@ static int phar_tar_setmetadata(const phar_metadata_tracker *tracker, phar_entry } /* }}} */ -static int phar_tar_setupmetadata(zval *zv, void *argument) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL static int phar_tar_setupmetadata(zval *zv, void *argument) /* {{{ */ { struct _phar_pass_tar_info *i = (struct _phar_pass_tar_info *)argument; char **error = i->error; @@ -964,7 +960,7 @@ static int phar_tar_setupmetadata(zval *zv, void *argument) /* {{{ */ } /* }}} */ -void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_default_stub, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_default_stub, char **error) /* {{{ */ { static const char newstub[] = "is_persistent) { - if (error) { - spprintf(error, 0, "internal error: attempt to flush cached tar-based phar \"%s\"", phar->fname); - } - return; + spprintf(error, 0, "internal error: attempt to flush cached tar-based phar \"%s\"", phar->fname); + return EOF; } if (phar->is_data) { @@ -1002,15 +996,13 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def if (!phar->is_temporary_alias && phar->alias_len) { entry.fp = php_stream_fopen_tmpfile(); if (entry.fp == NULL) { - spprintf(error, 0, "phar error: unable to create temporary file"); - return; + *error = estrdup("phar error: unable to create temporary file"); + return EOF; } if (phar->alias_len != php_stream_write(entry.fp, phar->alias, phar->alias_len)) { - if (error) { - spprintf(error, 0, "unable to set alias in tar-based phar \"%s\"", phar->fname); - } + spprintf(error, 0, "unable to set alias in tar-based phar \"%s\"", phar->fname); php_stream_close(entry.fp); - return; + return EOF; } entry.uncompressed_filesize = phar->alias_len; @@ -1028,10 +1020,8 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def char *pos = php_stristr(ZSTR_VAL(user_stub), halt_stub, ZSTR_LEN(user_stub), sizeof(halt_stub) - 1); if (pos == NULL) { - if (error) { - spprintf(error, 0, "illegal stub for tar-based phar \"%s\"", phar->fname); - } - return; + spprintf(error, 0, "illegal stub for tar-based phar \"%s\"", phar->fname); + return EOF; } size_t len = pos - ZSTR_VAL(user_stub) + strlen(halt_stub); @@ -1040,8 +1030,8 @@ 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"); - return; + *error = estrdup("phar error: unable to create temporary file"); + return EOF; } entry.uncompressed_filesize = len + end_sequence_len; @@ -1049,11 +1039,9 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def len != php_stream_write(entry.fp, ZSTR_VAL(user_stub), len) || end_sequence_len != php_stream_write(entry.fp, end_sequence, end_sequence_len) ) { - if (error) { - spprintf(error, 0, "unable to create stub from string in new tar-based phar \"%s\"", phar->fname); - } + spprintf(error, 0, "unable to create stub from string in new tar-based phar \"%s\"", phar->fname); php_stream_close(entry.fp); - return; + return EOF; } entry.filename = ZSTR_INIT_LITERAL(".phar/stub.php", false); @@ -1062,15 +1050,14 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def /* Either this is a brand new phar (add the stub), or the default stub is required (overwrite the stub) */ entry.fp = php_stream_fopen_tmpfile(); if (entry.fp == NULL) { - spprintf(error, 0, "phar error: unable to create temporary file"); - return; + *error = estrdup("phar error: unable to create temporary file"); + return EOF; } if (sizeof(newstub)-1 != php_stream_write(entry.fp, newstub, sizeof(newstub)-1)) { php_stream_close(entry.fp); - if (error) { - spprintf(error, 0, "unable to %s stub in%star-based phar \"%s\", failed", user_stub ? "overwrite" : "create", user_stub ? " " : " new ", phar->fname); - } - return; + spprintf(error, 0, "unable to %s stub in%star-based phar \"%s\", failed", + user_stub ? "overwrite" : "create", user_stub ? " " : " new ", phar->fname); + return EOF; } entry.uncompressed_filesize = entry.compressed_filesize = sizeof(newstub) - 1; @@ -1081,10 +1068,8 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def if (NULL == zend_hash_add_mem(&phar->manifest, entry.filename, &entry, sizeof(phar_entry_info))) { php_stream_close(entry.fp); zend_string_efree(entry.filename); - if (error) { - spprintf(error, 0, "unable to create stub in tar-based phar \"%s\"", phar->fname); - } - return; + spprintf(error, 0, "unable to create stub in tar-based phar \"%s\"", phar->fname); + return EOF; } } else { php_stream_close(entry.fp); @@ -1106,20 +1091,18 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def newfile = php_stream_fopen_tmpfile(); if (!newfile) { - if (error) { - spprintf(error, 0, "unable to create temporary file"); - } + *error = estrdup("unable to create temporary file"); if (must_close_old_file) { php_stream_close(oldfile); } - return; + return EOF; } pass.old = oldfile; pass.new = newfile; pass.error = error; - pass.free_fp = 1; - pass.free_ufp = 1; + pass.free_fp = true; + pass.free_ufp = true; if (phar_metadata_tracker_has_data(&phar->metadata_tracker, phar->is_persistent)) { phar_entry_info *mentry; @@ -1128,7 +1111,7 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def if (must_close_old_file) { php_stream_close(oldfile); } - return; + return EOF; } } else { phar_entry_info newentry = {0}; @@ -1144,7 +1127,7 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def if (must_close_old_file) { php_stream_close(oldfile); } - return; + return EOF; } if (ZEND_HASH_APPLY_KEEP != phar_tar_setmetadata(&phar->metadata_tracker, mentry, error)) { @@ -1152,46 +1135,60 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def if (must_close_old_file) { php_stream_close(oldfile); } - return; + return EOF; } } } zend_hash_apply_with_argument(&phar->manifest, phar_tar_setupmetadata, (void *) &pass); - if (error && *error) { + if (*error) { if (must_close_old_file) { php_stream_close(oldfile); } /* on error in the hash iterator above, error is set */ php_stream_close(newfile); - return; + return EOF; } zend_hash_apply_with_argument(&phar->manifest, phar_tar_writeheaders, (void *) &pass); + if (*error) { + if (must_close_old_file) { + php_stream_close(oldfile); + } + + /* on error in the hash iterator above, error is set */ + php_stream_close(newfile); + return EOF; + } + /* add signature for executable tars or tars explicitly set with setSignatureAlgorithm */ if (!phar->is_data || phar->sig_flags) { - if (FAILURE == phar_create_signature(phar, newfile, &signature, &signature_length, error)) { - if (error) { - char *save = *error; - spprintf(error, 0, "phar error: unable to write signature to tar-based phar: %s", save); - efree(save); - } + char *signature_error = NULL; + if (FAILURE == phar_create_signature(phar, newfile, &signature, &signature_length, &signature_error)) { + spprintf(error, 0, "phar error: unable to write signature to tar-based phar: %s", signature_error); + efree(signature_error); if (must_close_old_file) { php_stream_close(oldfile); } php_stream_close(newfile); - return; + return EOF; } entry.fp = php_stream_fopen_tmpfile(); if (entry.fp == NULL) { - spprintf(error, 0, "phar error: unable to create temporary file"); - return; + *error = estrdup("phar error: unable to create temporary file"); + + efree(signature); + if (must_close_old_file) { + php_stream_close(oldfile); + } + php_stream_close(newfile); + return EOF; } #ifdef WORDS_BIGENDIAN # define PHAR_SET_32(destination, source) do { \ @@ -1209,15 +1206,13 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def if (8 != php_stream_write(entry.fp, sigbuf, 8) || signature_length != php_stream_write(entry.fp, signature, signature_length)) { efree(signature); - if (error) { - spprintf(error, 0, "phar error: unable to write signature to tar-based phar %s", phar->fname); - } + spprintf(error, 0, "phar error: unable to write signature to tar-based phar %s", phar->fname); if (must_close_old_file) { php_stream_close(oldfile); } php_stream_close(newfile); - return; + return EOF; } ALLOCA_FLAG(use_heap); @@ -1228,13 +1223,13 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def phar_tar_writeheaders_int(&entry, &pass); ZSTR_ALLOCA_FREE(entry.filename, use_heap); - if (error && *error) { + if (*error) { if (must_close_old_file) { php_stream_close(oldfile); } /* error is set by writeheaders */ php_stream_close(newfile); - return; + return EOF; } } /* signature */ @@ -1247,12 +1242,6 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def php_stream_close(oldfile); } - /* on error in the hash iterator above, error is set */ - if (error && *error) { - php_stream_close(newfile); - return; - } - if (phar->fp && pass.free_fp) { php_stream_close(phar->fp); } @@ -1274,10 +1263,8 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def phar->fp = php_stream_open_wrapper(phar->fname, "w+b", IGNORE_URL|STREAM_MUST_SEEK|REPORT_ERRORS, NULL); if (!phar->fp) { phar->fp = newfile; - if (error) { - spprintf(error, 0, "unable to open new phar \"%s\" for writing", phar->fname); - } - return; + spprintf(error, 0, "unable to open new phar \"%s\" for writing", phar->fname); + return EOF; } if (phar->flags & PHAR_FILE_COMPRESSED_GZ) { @@ -1298,10 +1285,8 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def /* copy contents uncompressed rather than lose them */ php_stream_copy_to_stream_ex(newfile, phar->fp, PHP_STREAM_COPY_ALL, NULL); php_stream_close(newfile); - if (error) { - spprintf(error, 4096, "unable to compress all contents of phar \"%s\" using zlib, PHP versions older than 5.2.6 have a buggy zlib", phar->fname); - } - return; + spprintf(error, 4096, "unable to compress all contents of phar \"%s\" using zlib, PHP versions older than 5.2.6 have a buggy zlib", phar->fname); + return EOF; } php_stream_filter_append(&phar->fp->writefilters, filter); @@ -1328,5 +1313,6 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def php_stream_close(newfile); } } + return 0; } /* }}} */ diff --git a/ext/phar/tests/022.phpt b/ext/phar/tests/022.phpt index 5363a65be9423..c484c4d3c06dc 100644 --- a/ext/phar/tests/022.phpt +++ b/ext/phar/tests/022.phpt @@ -80,28 +80,28 @@ int(1) fseek($fp, -1, SEEK_END)int(0) int(6) fseek($fp, -8, SEEK_END)int(-1) -bool(false) +int(6) fseek($fp, -7, SEEK_END)int(0) int(0) fseek($fp, 0, SEEK_END)int(0) int(7) fseek($fp, 1, SEEK_END)int(-1) -bool(false) +int(7) fseek($fp, -8, SEEK_END)int(-1) -bool(false) +int(7) fseek($fp, 6)int(0) int(6) fseek($fp, 8)int(-1) -bool(false) +int(6) fseek($fp, -1)int(-1) -bool(false) +int(6) next int(4) fseek($fp, -5, SEEK_CUR)int(-1) -bool(false) +int(4) int(4) fseek($fp, 5, SEEK_CUR)int(-1) -bool(false) +int(4) int(4) fseek($fp, -4, SEEK_CUR)int(0) int(0) diff --git a/ext/phar/tests/SplFileInfo_openFile_write.phpt b/ext/phar/tests/SplFileInfo_openFile_write.phpt new file mode 100644 index 0000000000000..f63baf5c7ad10 --- /dev/null +++ b/ext/phar/tests/SplFileInfo_openFile_write.phpt @@ -0,0 +1,31 @@ +--TEST-- +SplFileInfo::openFile() in write mode +--EXTENSIONS-- +phar +--INI-- +phar.readonly=0 +--FILE-- +addFromString('test', 'contents'); +var_dump($phar['test']->openFile('w')); + +?> +--CLEAN-- + +--EXPECTF-- +object(SplFileObject)#%d (%d) { + ["pathName":"SplFileInfo":private]=> + string(%d) "phar://%stest" + ["fileName":"SplFileInfo":private]=> + string(4) "test" + ["openMode":"SplFileObject":private]=> + string(1) "w" + ["delimiter":"SplFileObject":private]=> + string(1) "," + ["enclosure":"SplFileObject":private]=> + string(1) """ +} diff --git a/ext/phar/tests/bug74154.phpt b/ext/phar/tests/bug74154.phpt new file mode 100644 index 0000000000000..ab3836ce87d46 --- /dev/null +++ b/ext/phar/tests/bug74154.phpt @@ -0,0 +1,41 @@ +--TEST-- +Bug #74154 (Phar extractTo creates empty files) +--EXTENSIONS-- +phar +zlib +--FILE-- +buildFromDirectory($dir); + +$compPhar = $phar->compress(Phar::GZ); +unset($phar); //make sure that test.tar is closed +unlink(__DIR__.'/bug74154.tar'); +unset($compPhar); //make sure that test.tar.gz is closed +$extractingPhar = new PharData(__DIR__.'/bug74154.tar.gz'); +$extractingPhar->extractTo($dir.'_out'); + +var_dump(file_get_contents($dir.'_out/1.txt')); +var_dump(file_get_contents($dir.'_out/2.txt')); + +?> +--CLEAN-- + +--EXPECT-- +string(64) "hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh" +string(64) "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" 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/buildFromIterator_user_overrides/getMTime.phpt b/ext/phar/tests/buildFromIterator_user_overrides/getMTime.phpt new file mode 100644 index 0000000000000..eefe352a0cbb6 --- /dev/null +++ b/ext/phar/tests/buildFromIterator_user_overrides/getMTime.phpt @@ -0,0 +1,81 @@ +--TEST-- +buildFromIterator with user overrides - getMTime() +--EXTENSIONS-- +phar +--INI-- +phar.readonly=0 +phar.require_hash=0 +--CREDITS-- +Arne Blankerts +N. Dossche +--FILE-- +getPathname() . " ]\n"; + return new MySplFileInfo(parent::current()->getPathname()); + } +} + +$workdir = __DIR__.'/getMTime'; +mkdir($workdir . '/content', recursive: true); +file_put_contents($workdir . '/content/hello.txt', "Hello world."); + +$phar = new \Phar($workdir . '/test.phar'); +$phar->startBuffering(); +$phar->buildFromIterator( + new RecursiveIteratorIterator( + new MyIterator($workdir . '/content', FilesystemIterator::SKIP_DOTS) + ), + $workdir +); +$phar->stopBuffering(); + + +$result = new \Phar($workdir . '/test.phar', 0, 'test.phar'); +var_dump($result['content/hello.txt']); +var_dump($result['content/hello.txt']->getATime()); +var_dump($result['content/hello.txt']->getMTime()); +var_dump($result['content/hello.txt']->getCTime()); + +?> +--CLEAN-- + +--EXPECTF-- +[ Found: %shello.txt ] +[MTime] +object(PharFileInfo)#%d (2) { + ["pathName":"SplFileInfo":private]=> + string(%d) "phar://%shello.txt" + ["fileName":"SplFileInfo":private]=> + string(%d) "hello.txt" +} +int(123) +int(123) +int(123) diff --git a/ext/phar/tests/buildFromIterator_user_overrides/getMTime_byRef.phpt b/ext/phar/tests/buildFromIterator_user_overrides/getMTime_byRef.phpt new file mode 100644 index 0000000000000..a7f81709a34e3 --- /dev/null +++ b/ext/phar/tests/buildFromIterator_user_overrides/getMTime_byRef.phpt @@ -0,0 +1,70 @@ +--TEST-- +buildFromIterator with user overrides - getMTime() by ref +--EXTENSIONS-- +phar +--INI-- +phar.readonly=0 +phar.require_hash=0 +--CREDITS-- +Arne Blankerts +N. Dossche +--FILE-- +getPathname() . " ]\n"; + return new MySplFileInfo(parent::current()->getPathname()); + } +} + +$workdir = __DIR__.'/getMTime_byRef'; +mkdir($workdir . '/content', recursive: true); +file_put_contents($workdir . '/content/hello.txt', "Hello world."); + +$phar = new \Phar($workdir . '/test.phar'); +$phar->startBuffering(); +$phar->buildFromIterator( + new RecursiveIteratorIterator( + new MyIterator($workdir . '/content', FilesystemIterator::SKIP_DOTS) + ), + $workdir +); +$phar->stopBuffering(); + + +$result = new \Phar($workdir . '/test.phar', 0, 'test.phar'); +var_dump($result['content/hello.txt']); +var_dump($result['content/hello.txt']->getATime()); +var_dump($result['content/hello.txt']->getMTime()); +var_dump($result['content/hello.txt']->getCTime()); + +?> +--CLEAN-- + +--EXPECTF-- +[ Found: %shello.txt ] +[MTime] +object(PharFileInfo)#%d (2) { + ["pathName":"SplFileInfo":private]=> + string(%d) "phar://%shello.txt" + ["fileName":"SplFileInfo":private]=> + string(%d) "hello.txt" +} +int(123) +int(123) +int(123) diff --git a/ext/phar/tests/buildFromIterator_user_overrides/getMTime_errors.phpt b/ext/phar/tests/buildFromIterator_user_overrides/getMTime_errors.phpt new file mode 100644 index 0000000000000..f43a7a496a762 --- /dev/null +++ b/ext/phar/tests/buildFromIterator_user_overrides/getMTime_errors.phpt @@ -0,0 +1,117 @@ +--TEST-- +buildFromIterator with user overrides - errors in getMTime() +--EXTENSIONS-- +phar +--SKIPIF-- + +--INI-- +phar.readonly=0 +phar.require_hash=0 +--CREDITS-- +Arne Blankerts +N. Dossche +--FILE-- +getPathname() . " ]\n"; + if ($counter === 1) { + return new MySplFileInfo1(parent::current()->getPathname()); + } else if ($counter === 2) { + return new MySplFileInfo2(parent::current()->getPathname()); + } else if ($counter === 3) { + return new MySplFileInfo3(parent::current()->getPathname()); + } else if ($counter === 4) { + return new MySplFileInfo4(parent::current()->getPathname()); + } + } +} + +$workdir = __DIR__.'/getMTime_errors'; +mkdir($workdir . '/content', recursive: true); +file_put_contents($workdir . '/content/hello.txt', "Hello world."); + +for ($i = 0; $i < 4; $i++) { + echo "--- Iteration $i ---\n"; + try { + $phar = new \Phar($workdir . "/test$i.phar"); + $phar->startBuffering(); + $phar->buildFromIterator( + new RecursiveIteratorIterator( + new MyIterator($workdir . '/content', FilesystemIterator::SKIP_DOTS) + ), + $workdir + ); + $phar->stopBuffering(); + } catch (Throwable $e) { + echo $e->getMessage(), "\n"; + if ($previous = $e->getPrevious()) { + echo "Previous: ", $previous->getMessage(), "\n"; + } + } +} + +?> +--CLEAN-- + +--EXPECTF-- +--- Iteration 0 --- +[ Found: %shello.txt ] +[MTime] +Entry content%chello.txt cannot be created: timestamp is limited to 32-bit +--- Iteration 1 --- +[ Found: %shello.txt ] +[MTime] +Entry content%chello.txt cannot be created: getMTime() must return an int +--- Iteration 2 --- +[ Found: %shello.txt ] +[MTime] +Entry content%chello.txt cannot be created: getMTime() must return an int +Previous: Throwing an exception inside getMTime() +--- Iteration 3 --- +[ Found: %shello.txt ] +[MTime] +Entry content%chello.txt cannot be created: getMTime() must return an int diff --git a/ext/phar/tests/buildFromIterator_user_overrides/getPathname.phpt b/ext/phar/tests/buildFromIterator_user_overrides/getPathname.phpt new file mode 100644 index 0000000000000..144eed1d874a6 --- /dev/null +++ b/ext/phar/tests/buildFromIterator_user_overrides/getPathname.phpt @@ -0,0 +1,67 @@ +--TEST-- +buildFromIterator with user overrides - getPathname() +--EXTENSIONS-- +phar +--INI-- +phar.readonly=0 +phar.require_hash=0 +--CREDITS-- +Arne Blankerts +N. Dossche +--FILE-- +getPathname() . " ]\n"; + return new MyGlobIterator(parent::current()->getPath() . '/*'); + } +} + +$workdir = __DIR__.'/getPathname'; +mkdir($workdir . '/content', recursive: true); +file_put_contents($workdir . '/content/hello1.txt', "Hello world 1."); +file_put_contents($workdir . '/content/hello2.txt', "Hello world 2."); + +$phar = new \Phar($workdir . "/test.phar"); +$phar->startBuffering(); +$phar->buildFromIterator( + new RecursiveIteratorIterator( + new MyIterator($workdir . '/content', FilesystemIterator::SKIP_DOTS) + ), + $workdir +); +$phar->stopBuffering(); + +$result = new \Phar($workdir . '/test.phar', 0, 'test.phar'); +var_dump(isset($result['content/hello1.txt'])); +var_dump(isset($result['content/hello2.txt'])); + +?> +--CLEAN-- + +--EXPECTF-- +[ Found: %shello%d.txt ] +[getPathname] +string(%d) "%shello1.txt" +[ Found: %shello%d.txt ] +[getPathname] +string(%d) "%shello1.txt" +bool(false) +bool(true) diff --git a/ext/phar/tests/buildFromIterator_user_overrides/getPathname_byRef.phpt b/ext/phar/tests/buildFromIterator_user_overrides/getPathname_byRef.phpt new file mode 100644 index 0000000000000..0ae2946ce1ade --- /dev/null +++ b/ext/phar/tests/buildFromIterator_user_overrides/getPathname_byRef.phpt @@ -0,0 +1,58 @@ +--TEST-- +buildFromIterator with user overrides - getPathname() by ref +--EXTENSIONS-- +phar +--INI-- +phar.readonly=0 +phar.require_hash=0 +--CREDITS-- +Arne Blankerts +N. Dossche +--FILE-- +getPathname() . " ]\n"; + return new MyGlobIterator(parent::current()->getPath() . '/*'); + } +} + +$workdir = __DIR__.'/getPathname_byRef'; +mkdir($workdir . '/content', recursive: true); +file_put_contents($workdir . '/content/hello.txt', "Hello world 1."); + +$phar = new \Phar($workdir . "/test.phar"); +$phar->startBuffering(); +$phar->buildFromIterator( + new RecursiveIteratorIterator( + new MyIterator($workdir . '/content', FilesystemIterator::SKIP_DOTS) + ), + $workdir +); +$phar->stopBuffering(); + +$result = new \Phar($workdir . '/test.phar', 0, 'test.phar'); +var_dump(isset($result['content/hello.txt'])); + +?> +--CLEAN-- + +--EXPECTF-- +[ Found: %scontent%chello.txt ] +[getPathname] +bool(true) diff --git a/ext/phar/tests/buildFromIterator_user_overrides/getPathname_exception.phpt b/ext/phar/tests/buildFromIterator_user_overrides/getPathname_exception.phpt new file mode 100644 index 0000000000000..86b66050a973f --- /dev/null +++ b/ext/phar/tests/buildFromIterator_user_overrides/getPathname_exception.phpt @@ -0,0 +1,63 @@ +--TEST-- +buildFromIterator with user overrides - exception in getPathname() +--EXTENSIONS-- +phar +--INI-- +phar.readonly=0 +phar.require_hash=0 +--CREDITS-- +Arne Blankerts +N. Dossche +--FILE-- +getPathname() . " ]\n"; + return new MyGlobIterator(parent::current()->getPath() . '/*'); + } +} + +$workdir = __DIR__.'/getPathname_exception'; +mkdir($workdir . '/content', recursive: true); +file_put_contents($workdir . '/content/hello.txt', "Hello world."); + +$phar = new \Phar($workdir . "/test.phar"); +$phar->startBuffering(); +try { + $phar->buildFromIterator( + new RecursiveIteratorIterator( + new MyIterator($workdir . '/content', FilesystemIterator::SKIP_DOTS) + ), + $workdir + ); +} catch (Throwable $e) { + echo $e->getMessage(), "\n"; + if ($previous = $e->getPrevious()) { + echo "Previous: ", $previous->getMessage(), "\n"; + } +} +$phar->stopBuffering(); + +?> +--CLEAN-- + +--EXPECTF-- +[ Found: %shello.txt ] +[getPathname] +string(%d) "%shello.txt" +getPathname() must return a string +Previous: exception in getPathname() diff --git a/ext/phar/tests/buildFromIterator_user_overrides/getPathname_wrong_type.phpt b/ext/phar/tests/buildFromIterator_user_overrides/getPathname_wrong_type.phpt new file mode 100644 index 0000000000000..dfb3fb5f2c550 --- /dev/null +++ b/ext/phar/tests/buildFromIterator_user_overrides/getPathname_wrong_type.phpt @@ -0,0 +1,58 @@ +--TEST-- +buildFromIterator with user overrides - wrong return type in getPathname() +--EXTENSIONS-- +phar +--INI-- +phar.readonly=0 +phar.require_hash=0 +--CREDITS-- +Arne Blankerts +N. Dossche +--FILE-- +getPathname() . " ]\n"; + return new MyGlobIterator(parent::current()->getPath() . '/*'); + } +} + +$workdir = __DIR__.'/getPathname_wrong_type'; +mkdir($workdir . '/content', recursive: true); +file_put_contents($workdir . '/content/hello.txt', "Hello world."); + +$phar = new \Phar($workdir . "/test.phar"); +$phar->startBuffering(); +try { + $phar->buildFromIterator( + new RecursiveIteratorIterator( + new MyIterator($workdir . '/content', FilesystemIterator::SKIP_DOTS) + ), + $workdir + ); +} catch (Throwable $e) { + echo $e->getMessage(), "\n"; +} +$phar->stopBuffering(); + +?> +--CLEAN-- + +--EXPECTF-- +[ Found: %scontent%chello.txt ] +[getPathname] +getPathname() must return a string diff --git a/ext/phar/tests/cache_list/copyonwrite11.phar.phpt b/ext/phar/tests/cache_list/copyonwrite11.phar.phpt index a52b8e5fed3f5..d51135894494f 100644 --- a/ext/phar/tests/cache_list/copyonwrite11.phar.phpt +++ b/ext/phar/tests/cache_list/copyonwrite11.phar.phpt @@ -18,5 +18,5 @@ echo strlen($p2->getStub()),"\n"; echo "ok\n"; __HALT_COMPILER(); ?> " -6643 +6661 ok 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/fflush_phar_file_report_success.phpt b/ext/phar/tests/fflush_phar_file_report_success.phpt new file mode 100644 index 0000000000000..615f4e58e5678 --- /dev/null +++ b/ext/phar/tests/fflush_phar_file_report_success.phpt @@ -0,0 +1,25 @@ +--TEST-- +fflush() on phar file should report success +--EXTENSIONS-- +phar +--INI-- +phar.readonly=0 +--FILE-- +addFromString('test', 'contents'); +unset($phar); + +$f = fopen('phar://' . __DIR__.'/fflush_phar_file_report_success.phar/test', 'w'); +var_dump(fflush($f)); +var_dump(fclose($f)); + +?> +--CLEAN-- + +--EXPECT-- +bool(true) +bool(true) diff --git a/ext/phar/tests/files/gh20442.phar b/ext/phar/tests/files/gh20442.phar new file mode 100644 index 0000000000000..26fac67ede587 Binary files /dev/null and b/ext/phar/tests/files/gh20442.phar differ 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/fseek_outside_bounds.phpt b/ext/phar/tests/fseek_outside_bounds.phpt new file mode 100644 index 0000000000000..0a35abb360d5f --- /dev/null +++ b/ext/phar/tests/fseek_outside_bounds.phpt @@ -0,0 +1,26 @@ +--TEST-- +Assertion failure when fseeking outside of bounds of phar file +--EXTENSIONS-- +phar +--INI-- +phar.require_hash=0 +--FILE-- +setInfoClass('SplFileObject'); +$f = $phar['a.php']; +var_dump($f->fseek(1, SEEK_SET)); +var_dump($f->fseek(999999, SEEK_SET)); +var_dump($f->fseek(999999, SEEK_CUR)); +var_dump($f->ftell()); +var_dump($f->fseek(1, SEEK_CUR)); +var_dump($f->fread(3)); +?> +--EXPECT-- +int(0) +int(-1) +int(-1) +int(1) +int(0) +string(3) "php" diff --git a/ext/phar/tests/gh17808.phpt b/ext/phar/tests/gh17808.phpt index 03e54ff264bfa..a5c13a5405e24 100644 --- a/ext/phar/tests/gh17808.phpt +++ b/ext/phar/tests/gh17808.phpt @@ -5,18 +5,26 @@ phar zlib --FILE-- getContent())); -unlink("$file"); +unlink($file); var_dump($file->getATime()); ?> +--CLEAN-- + --EXPECTF-- -string(%d) "phar://%spackage.xml" +object(PharFileInfo)#%d (%d) { + ["pathName":"SplFileInfo":private]=> + string(%d) "phar://%spackage.xml" + ["fileName":"SplFileInfo":private]=> + string(11) "package.xml" +} int(6747) - -Warning: unlink(): phar error: "package.xml" in phar %s, has open file pointers, cannot unlink in %s on line %d int(33188) 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/gh20302.phpt b/ext/phar/tests/gh20302.phpt new file mode 100644 index 0000000000000..0cbd253d54fc3 --- /dev/null +++ b/ext/phar/tests/gh20302.phpt @@ -0,0 +1,36 @@ +--TEST-- +GH-20302 (Freeing a phar alias may invalidate PharFileInfo objects) +--EXTENSIONS-- +phar +--INI-- +phar.require_hash=0 +--FILE-- +"; +$files = array(); +$files['here'] = 'a'; +include __DIR__.'/files/phar_test.inc'; +$b = new PharFileInfo($pname . '/here'); + +// Create new phar with same alias and open it +@mkdir(__DIR__.'/gh20302'); +$fname = __DIR__.'/gh20302/gh20302.phar'; +$pname = 'phar://' . $fname; +include __DIR__.'/files/phar_test.inc'; +try { + new Phar($fname); +} catch (UnexpectedValueException $e) { + echo $e->getMessage(), "\n"; +} +?> +--CLEAN-- + +--EXPECTF-- +Cannot open archive "%sgh20302.phar", alias is already in use by existing archive diff --git a/ext/phar/tests/gh20442.phpt b/ext/phar/tests/gh20442.phpt new file mode 100644 index 0000000000000..e6862f3d33dbc --- /dev/null +++ b/ext/phar/tests/gh20442.phpt @@ -0,0 +1,18 @@ +--TEST-- +GH-20442 (Phar does not respect case-insensitiveness of __halt_compiler() when reading stub) +--EXTENSIONS-- +phar +--FILE-- +count()); +var_dump($phar->getStub()); + +?> +--EXPECT-- +int(1) +string(50) " +" diff --git a/ext/phar/tests/gh20732.phpt b/ext/phar/tests/gh20732.phpt new file mode 100644 index 0000000000000..b938d16d42caf --- /dev/null +++ b/ext/phar/tests/gh20732.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-20732 (Phar::LoadPhar undefined behavior when loading directory) +--EXTENSIONS-- +phar +--FILE-- +getMessage(), "\n"; +} +?> +--EXPECTF-- +%r(internal corruption of phar "%s" \(truncated entry\)|unable to open phar for reading ".")%r diff --git a/ext/phar/tests/invalid_string_phar_mungserver.phpt b/ext/phar/tests/invalid_string_phar_mungserver.phpt new file mode 100644 index 0000000000000..46de113f6c087 --- /dev/null +++ b/ext/phar/tests/invalid_string_phar_mungserver.phpt @@ -0,0 +1,15 @@ +--TEST-- +Passing invalid string to Phar::mungServer() +--FILE-- +getMessage(), "\n"; +} + +?> +--EXPECT-- +Invalid value passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME diff --git a/ext/phar/tests/openssl_sign_invalid_polyfill_return_value.phpt b/ext/phar/tests/openssl_sign_invalid_polyfill_return_value.phpt new file mode 100644 index 0000000000000..37c14188edf98 --- /dev/null +++ b/ext/phar/tests/openssl_sign_invalid_polyfill_return_value.phpt @@ -0,0 +1,34 @@ +--TEST-- +openssl_sign() polyfill with wrong return value +--EXTENSIONS-- +phar +--SKIPIF-- + +--INI-- +phar.require_hash=0 +--FILE-- +setSignatureAlgorithm(Phar::OPENSSL, "randomcrap"); +try { + $phar->addEmptyDir('blah'); +} catch (PharException $e) { + echo $e->getMessage(); +} + +?> +--CLEAN-- + +--EXPECTF-- +phar error: unable to write signature to tar-based phar: unable to write phar "%s" with requested openssl signature diff --git a/ext/phar/tests/phar_commitwrite.phpt b/ext/phar/tests/phar_commitwrite.phpt index 80c35cb784364..951506aff0f00 100644 --- a/ext/phar/tests/phar_commitwrite.phpt +++ b/ext/phar/tests/phar_commitwrite.phpt @@ -27,7 +27,7 @@ unlink(__DIR__ . '/phar_commitwrite.phar'); __HALT_COMPILER(); ?> --EXPECTF-- -int(6641) +int(6659) string(%d) "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_convert_repeated.phpt b/ext/phar/tests/phar_convert_repeated.phpt index 8f8b6361362fc..09026f0d947fb 100644 --- a/ext/phar/tests/phar_convert_repeated.phpt +++ b/ext/phar/tests/phar_convert_repeated.phpt @@ -120,7 +120,7 @@ NULL bool(true) bool(false) bool(false) -int(6641) +int(6659) NULL ================= convertToZip() ===================== bool(false) diff --git a/ext/phar/tests/phar_create_in_cwd.phpt b/ext/phar/tests/phar_create_in_cwd.phpt index c6245c295e651..7aed3a5d59038 100644 --- a/ext/phar/tests/phar_create_in_cwd.phpt +++ b/ext/phar/tests/phar_create_in_cwd.phpt @@ -30,7 +30,7 @@ __HALT_COMPILER(); unlink(__DIR__ . '/phar_create_in_cwd.phar'); ?> --EXPECTF-- -int(6641) +int(6659) string(%d) "getMessage() . "\n"; } ?> --EXPECT-- -string(6641) "\n \n File Not Found<title>\n </head>\n <body>\n <h1>404 - File Not Found</h1>\n </body>\n</html>"; +echo "<html>\n <head>\n <title>File Not Found\n \n \n

404 - File Not Found

\n \n"; exit; } $b = pathinfo($a); @@ -143,13 +143,13 @@ const GZ = 0x1000; const BZ2 = 0x2000; const MASK = 0x3000; const START = 'index.php'; -const LEN = 6643; +const LEN = 6661; static function go($return = false) { $fp = fopen(__FILE__, 'rb'); fseek($fp, self::LEN); -$L = unpack('V', $a = fread($fp, 4)); +$L = unpack('V', $a = (string)fread($fp, 4)); $m = ''; do { @@ -157,7 +157,7 @@ $read = 8192; if ($L[1] - strlen($m) < 8192) { $read = $L[1] - strlen($m); } -$last = fread($fp, $read); +$last = (string)fread($fp, $read); $m .= $last; } while (strlen($last) && strlen($m) < $L[1]); @@ -248,7 +248,8 @@ return realpath('/tmp'); static function _unpack($m) { $info = unpack('V', substr($m, 0, 4)); - $l = unpack('V', substr($m, 10, 4)); + +$l = unpack('V', substr($m, 10, 4)); $m = substr($m, 14 + $l[1]); $s = unpack('V', substr($m, 0, 4)); $o = 0; @@ -256,11 +257,16 @@ $start = 4 + $s[1]; $ret['c'] = 0; for ($i = 0; $i < $info[1]; $i++) { - $len = unpack('V', substr($m, $start, 4)); + +$len = unpack('V', substr($m, $start, 4)); $start += 4; - $savepath = substr($m, $start, $len[1]); + +$savepath = substr($m, $start, $len[1]); $start += $len[1]; - $ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24))); + + + +$ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24))); $ret['m'][$savepath][3] = sprintf('%u', $ret['m'][$savepath][3] & 0xffffffff); $ret['m'][$savepath][7] = $o; @@ -294,7 +300,7 @@ $data = bzdecompress($data); if (strlen($data) != $entry[0]) { die("Invalid internal .phar file (size error " . strlen($data) . " != " . -$stat[7] . ")"); +$entry[0] . ")"); } if ($entry[3] != sprintf("%u", crc32($data) & 0xffffffff)) { @@ -327,7 +333,7 @@ Extract_Phar::go(); __HALT_COMPILER(); ?>" ============================================================================ ============================================================================ -string(6652) "\n \n File Not Found<title>\n </head>\n <body>\n <h1>404 - File Not Found</h1>\n </body>\n</html>"; +echo "<html>\n <head>\n <title>File Not Found\n \n \n

404 - File Not Found

\n \n"; exit; } $b = pathinfo($a); @@ -437,13 +443,13 @@ const GZ = 0x1000; const BZ2 = 0x2000; const MASK = 0x3000; const START = 'my/custom/thingy.php'; -const LEN = 6654; +const LEN = 6672; static function go($return = false) { $fp = fopen(__FILE__, 'rb'); fseek($fp, self::LEN); -$L = unpack('V', $a = fread($fp, 4)); +$L = unpack('V', $a = (string)fread($fp, 4)); $m = ''; do { @@ -451,7 +457,7 @@ $read = 8192; if ($L[1] - strlen($m) < 8192) { $read = $L[1] - strlen($m); } -$last = fread($fp, $read); +$last = (string)fread($fp, $read); $m .= $last; } while (strlen($last) && strlen($m) < $L[1]); @@ -542,7 +548,8 @@ return realpath('/tmp'); static function _unpack($m) { $info = unpack('V', substr($m, 0, 4)); - $l = unpack('V', substr($m, 10, 4)); + +$l = unpack('V', substr($m, 10, 4)); $m = substr($m, 14 + $l[1]); $s = unpack('V', substr($m, 0, 4)); $o = 0; @@ -550,11 +557,16 @@ $start = 4 + $s[1]; $ret['c'] = 0; for ($i = 0; $i < $info[1]; $i++) { - $len = unpack('V', substr($m, $start, 4)); + +$len = unpack('V', substr($m, $start, 4)); $start += 4; - $savepath = substr($m, $start, $len[1]); + +$savepath = substr($m, $start, $len[1]); $start += $len[1]; - $ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24))); + + + +$ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24))); $ret['m'][$savepath][3] = sprintf('%u', $ret['m'][$savepath][3] & 0xffffffff); $ret['m'][$savepath][7] = $o; @@ -588,7 +600,7 @@ $data = bzdecompress($data); if (strlen($data) != $entry[0]) { die("Invalid internal .phar file (size error " . strlen($data) . " != " . -$stat[7] . ")"); +$entry[0] . ")"); } if ($entry[3] != sprintf("%u", crc32($data) & 0xffffffff)) { @@ -621,7 +633,7 @@ Extract_Phar::go(); __HALT_COMPILER(); ?>" ============================================================================ ============================================================================ -int(7032) +int(7050) ============================================================================ ============================================================================ Illegal filename passed in for stub creation, was 401 characters long, and only 400 or less is allowed @@ -629,7 +641,7 @@ Illegal filename passed in for stub creation, was 401 characters long, and only ============================================================================ ============================================================================ ============================================================================ -string(6654) "\n \n File Not Found<title>\n </head>\n <body>\n <h1>404 - File Not Found</h1>\n </body>\n</html>"; +echo "<html>\n <head>\n <title>File Not Found\n \n \n

404 - File Not Found

\n \n"; exit; } $b = pathinfo($a); @@ -739,13 +751,13 @@ const GZ = 0x1000; const BZ2 = 0x2000; const MASK = 0x3000; const START = 'my/custom/thingy.php'; -const LEN = 6656; +const LEN = 6674; static function go($return = false) { $fp = fopen(__FILE__, 'rb'); fseek($fp, self::LEN); -$L = unpack('V', $a = fread($fp, 4)); +$L = unpack('V', $a = (string)fread($fp, 4)); $m = ''; do { @@ -753,7 +765,7 @@ $read = 8192; if ($L[1] - strlen($m) < 8192) { $read = $L[1] - strlen($m); } -$last = fread($fp, $read); +$last = (string)fread($fp, $read); $m .= $last; } while (strlen($last) && strlen($m) < $L[1]); @@ -844,7 +856,8 @@ return realpath('/tmp'); static function _unpack($m) { $info = unpack('V', substr($m, 0, 4)); - $l = unpack('V', substr($m, 10, 4)); + +$l = unpack('V', substr($m, 10, 4)); $m = substr($m, 14 + $l[1]); $s = unpack('V', substr($m, 0, 4)); $o = 0; @@ -852,11 +865,16 @@ $start = 4 + $s[1]; $ret['c'] = 0; for ($i = 0; $i < $info[1]; $i++) { - $len = unpack('V', substr($m, $start, 4)); + +$len = unpack('V', substr($m, $start, 4)); $start += 4; - $savepath = substr($m, $start, $len[1]); + +$savepath = substr($m, $start, $len[1]); $start += $len[1]; - $ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24))); + + + +$ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24))); $ret['m'][$savepath][3] = sprintf('%u', $ret['m'][$savepath][3] & 0xffffffff); $ret['m'][$savepath][7] = $o; @@ -890,7 +908,7 @@ $data = bzdecompress($data); if (strlen($data) != $entry[0]) { die("Invalid internal .phar file (size error " . strlen($data) . " != " . -$stat[7] . ")"); +$entry[0] . ")"); } if ($entry[3] != sprintf("%u", crc32($data) & 0xffffffff)) { @@ -923,5 +941,5 @@ Extract_Phar::go(); __HALT_COMPILER(); ?>" ============================================================================ ============================================================================ -int(7032) +int(7050) Illegal web filename passed in for stub creation, was 401 characters long, and only 400 or less is allowed diff --git a/ext/phar/tests/phar_offset_check.phpt b/ext/phar/tests/phar_offset_check.phpt index c1a8d201c8bc7..5a039d2d89346 100644 --- a/ext/phar/tests/phar_offset_check.phpt +++ b/ext/phar/tests/phar_offset_check.phpt @@ -68,8 +68,8 @@ var_dump($phar->getAlias()); Entry .phar/stub.php does not exist Entry .phar/alias.txt does not exist Cannot set stub ".phar/stub.php" directly in phar "%sphar_offset_check.phar.php", use setStub -int(6643) -int(6643) +int(6661) +int(6661) Cannot set alias ".phar/alias.txt" directly in phar "%sphar_offset_check.phar.php", use setAlias string(5) "susan" string(5) "susan" diff --git a/ext/phar/tests/phar_setdefaultstub.phpt b/ext/phar/tests/phar_setdefaultstub.phpt index c5db64a308e6f..ea05a03bc1a7f 100644 --- a/ext/phar/tests/phar_setdefaultstub.phpt +++ b/ext/phar/tests/phar_setdefaultstub.phpt @@ -53,7 +53,7 @@ try { unlink(__DIR__ . '/' . basename(__FILE__, '.clean.php') . '.phar'); ?> --EXPECT-- -string(6643) "\n \n File Not Found<title>\n </head>\n <body>\n <h1>404 - File Not Found</h1>\n </body>\n</html>"; +echo "<html>\n <head>\n <title>File Not Found\n \n \n

404 - File Not Found

\n \n"; exit; } $b = pathinfo($a); @@ -163,13 +163,13 @@ const GZ = 0x1000; const BZ2 = 0x2000; const MASK = 0x3000; const START = 'index.php'; -const LEN = 6643; +const LEN = 6661; static function go($return = false) { $fp = fopen(__FILE__, 'rb'); fseek($fp, self::LEN); -$L = unpack('V', $a = fread($fp, 4)); +$L = unpack('V', $a = (string)fread($fp, 4)); $m = ''; do { @@ -177,7 +177,7 @@ $read = 8192; if ($L[1] - strlen($m) < 8192) { $read = $L[1] - strlen($m); } -$last = fread($fp, $read); +$last = (string)fread($fp, $read); $m .= $last; } while (strlen($last) && strlen($m) < $L[1]); @@ -268,7 +268,8 @@ return realpath('/tmp'); static function _unpack($m) { $info = unpack('V', substr($m, 0, 4)); - $l = unpack('V', substr($m, 10, 4)); + +$l = unpack('V', substr($m, 10, 4)); $m = substr($m, 14 + $l[1]); $s = unpack('V', substr($m, 0, 4)); $o = 0; @@ -276,11 +277,16 @@ $start = 4 + $s[1]; $ret['c'] = 0; for ($i = 0; $i < $info[1]; $i++) { - $len = unpack('V', substr($m, $start, 4)); + +$len = unpack('V', substr($m, $start, 4)); $start += 4; - $savepath = substr($m, $start, $len[1]); + +$savepath = substr($m, $start, $len[1]); $start += $len[1]; - $ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24))); + + + +$ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24))); $ret['m'][$savepath][3] = sprintf('%u', $ret['m'][$savepath][3] & 0xffffffff); $ret['m'][$savepath][7] = $o; @@ -314,7 +320,7 @@ $data = bzdecompress($data); if (strlen($data) != $entry[0]) { die("Invalid internal .phar file (size error " . strlen($data) . " != " . -$stat[7] . ")"); +$entry[0] . ")"); } if ($entry[3] != sprintf("%u", crc32($data) & 0xffffffff)) { @@ -348,7 +354,7 @@ __HALT_COMPILER(); ?> " ============================================================================ ============================================================================ -string(6654) "\n \n File Not Found<title>\n </head>\n <body>\n <h1>404 - File Not Found</h1>\n </body>\n</html>"; +echo "<html>\n <head>\n <title>File Not Found\n \n \n

404 - File Not Found

\n \n"; exit; } $b = pathinfo($a); @@ -458,13 +464,13 @@ const GZ = 0x1000; const BZ2 = 0x2000; const MASK = 0x3000; const START = 'my/custom/thingy.php'; -const LEN = 6654; +const LEN = 6672; static function go($return = false) { $fp = fopen(__FILE__, 'rb'); fseek($fp, self::LEN); -$L = unpack('V', $a = fread($fp, 4)); +$L = unpack('V', $a = (string)fread($fp, 4)); $m = ''; do { @@ -472,7 +478,7 @@ $read = 8192; if ($L[1] - strlen($m) < 8192) { $read = $L[1] - strlen($m); } -$last = fread($fp, $read); +$last = (string)fread($fp, $read); $m .= $last; } while (strlen($last) && strlen($m) < $L[1]); @@ -563,7 +569,8 @@ return realpath('/tmp'); static function _unpack($m) { $info = unpack('V', substr($m, 0, 4)); - $l = unpack('V', substr($m, 10, 4)); + +$l = unpack('V', substr($m, 10, 4)); $m = substr($m, 14 + $l[1]); $s = unpack('V', substr($m, 0, 4)); $o = 0; @@ -571,11 +578,16 @@ $start = 4 + $s[1]; $ret['c'] = 0; for ($i = 0; $i < $info[1]; $i++) { - $len = unpack('V', substr($m, $start, 4)); + +$len = unpack('V', substr($m, $start, 4)); $start += 4; - $savepath = substr($m, $start, $len[1]); + +$savepath = substr($m, $start, $len[1]); $start += $len[1]; - $ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24))); + + + +$ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24))); $ret['m'][$savepath][3] = sprintf('%u', $ret['m'][$savepath][3] & 0xffffffff); $ret['m'][$savepath][7] = $o; @@ -609,7 +621,7 @@ $data = bzdecompress($data); if (strlen($data) != $entry[0]) { die("Invalid internal .phar file (size error " . strlen($data) . " != " . -$stat[7] . ")"); +$entry[0] . ")"); } if ($entry[3] != sprintf("%u", crc32($data) & 0xffffffff)) { @@ -643,7 +655,7 @@ __HALT_COMPILER(); ?> " ============================================================================ ============================================================================ -string(6656) "\n \n File Not Found<title>\n </head>\n <body>\n <h1>404 - File Not Found</h1>\n </body>\n</html>"; +echo "<html>\n <head>\n <title>File Not Found\n \n \n

404 - File Not Found

\n \n"; exit; } $b = pathinfo($a); @@ -753,13 +765,13 @@ const GZ = 0x1000; const BZ2 = 0x2000; const MASK = 0x3000; const START = 'my/custom/thingy.php'; -const LEN = 6656; +const LEN = 6674; static function go($return = false) { $fp = fopen(__FILE__, 'rb'); fseek($fp, self::LEN); -$L = unpack('V', $a = fread($fp, 4)); +$L = unpack('V', $a = (string)fread($fp, 4)); $m = ''; do { @@ -767,7 +779,7 @@ $read = 8192; if ($L[1] - strlen($m) < 8192) { $read = $L[1] - strlen($m); } -$last = fread($fp, $read); +$last = (string)fread($fp, $read); $m .= $last; } while (strlen($last) && strlen($m) < $L[1]); @@ -858,7 +870,8 @@ return realpath('/tmp'); static function _unpack($m) { $info = unpack('V', substr($m, 0, 4)); - $l = unpack('V', substr($m, 10, 4)); + +$l = unpack('V', substr($m, 10, 4)); $m = substr($m, 14 + $l[1]); $s = unpack('V', substr($m, 0, 4)); $o = 0; @@ -866,11 +879,16 @@ $start = 4 + $s[1]; $ret['c'] = 0; for ($i = 0; $i < $info[1]; $i++) { - $len = unpack('V', substr($m, $start, 4)); + +$len = unpack('V', substr($m, $start, 4)); $start += 4; - $savepath = substr($m, $start, $len[1]); + +$savepath = substr($m, $start, $len[1]); $start += $len[1]; - $ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24))); + + + +$ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24))); $ret['m'][$savepath][3] = sprintf('%u', $ret['m'][$savepath][3] & 0xffffffff); $ret['m'][$savepath][7] = $o; @@ -904,7 +922,7 @@ $data = bzdecompress($data); if (strlen($data) != $entry[0]) { die("Invalid internal .phar file (size error " . strlen($data) . " != " . -$stat[7] . ")"); +$entry[0] . ")"); } if ($entry[3] != sprintf("%u", crc32($data) & 0xffffffff)) { @@ -938,5 +956,5 @@ __HALT_COMPILER(); ?> " ============================================================================ ============================================================================ -int(7034) +int(7052) Illegal filename passed in for stub creation, was 401 characters long, and only 400 or less is allowed diff --git a/ext/phar/tests/phar_setsignaturealgo2.phpt b/ext/phar/tests/phar_setsignaturealgo2.phpt index 4f31836fbbbcc..82615a13da478 100644 --- a/ext/phar/tests/phar_setsignaturealgo2.phpt +++ b/ext/phar/tests/phar_setsignaturealgo2.phpt @@ -2,6 +2,7 @@ Phar::setSupportedSignatures() with hash --EXTENSIONS-- phar +openssl --SKIPIF-- getSignature()); + +echo "Set MD5:\n"; $p->setSignatureAlgorithm(Phar::MD5); var_dump($p->getSignature()); + +echo "Set SHA1:\n"; $p->setSignatureAlgorithm(Phar::SHA1); var_dump($p->getSignature()); + +echo "Set SHA256:\n"; try { -$p->setSignatureAlgorithm(Phar::SHA256); -var_dump($p->getSignature()); -} catch (Exception $e) { -echo $e->getMessage(); + $p->setSignatureAlgorithm(Phar::SHA256); + var_dump($p->getSignature()); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } + +echo "Set SHA512:\n"; try { -$p->setSignatureAlgorithm(Phar::SHA512); -var_dump($p->getSignature()); -} catch (Exception $e) { -echo $e->getMessage(); + $p->setSignatureAlgorithm(Phar::SHA512); + var_dump($p->getSignature()); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } + +echo "Set OPENSSL:\n"; try { -$config = __DIR__ . '/files/openssl.cnf'; -$config_arg = array('config' => $config); -$private = openssl_get_privatekey(file_get_contents(__DIR__ . '/files/private.pem')); -$pkey = ''; -openssl_pkey_export($private, $pkey, NULL, $config_arg); -$p->setSignatureAlgorithm(Phar::OPENSSL, $pkey); -var_dump($p->getSignature()); -} catch (Exception $e) { -echo $e->getMessage(); + $config = __DIR__ . '/files/openssl.cnf'; + $config_arg = array('config' => $config); + $private = openssl_get_privatekey(file_get_contents(__DIR__ . '/files/private.pem')); + $pkey = ''; + openssl_pkey_export($private, $pkey, NULL, $config_arg); + $p->setSignatureAlgorithm(Phar::OPENSSL, $pkey); + var_dump($p->getSignature()); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } + ?> --CLEAN-- --EXPECTF-- +Default: array(2) { ["hash"]=> string(%d) "%s" ["hash_type"]=> string(7) "SHA-256" } +Set MD5: array(2) { ["hash"]=> string(%d) "%s" ["hash_type"]=> string(3) "MD5" } +Set SHA1: array(2) { ["hash"]=> string(%d) "%s" ["hash_type"]=> string(5) "SHA-1" } +Set SHA256: array(2) { ["hash"]=> string(%d) "%s" ["hash_type"]=> string(7) "SHA-256" } +Set SHA512: array(2) { ["hash"]=> string(%d) "%s" ["hash_type"]=> string(7) "SHA-512" } +Set OPENSSL: array(2) { ["hash"]=> string(%d) "%s" diff --git a/ext/phar/tests/tar/bug70417.phpt b/ext/phar/tests/tar/bug70417.phpt index 4d98a18954cc3..7bb6bbafbcfa4 100644 --- a/ext/phar/tests/tar/bug70417.phpt +++ b/ext/phar/tests/tar/bug70417.phpt @@ -3,32 +3,18 @@ Bug #70417 (PharData::compress() doesn't close temp file) --EXTENSIONS-- phar zlib ---SKIPIF-- - --FILE-- /dev/null', $out); // Note: valgrind can produce false positives for /usr/bin/lsof - return count($out); -} $filename = __DIR__ . '/bug70417.tar'; @unlink("$filename.gz"); -$openFiles1 = countOpenFiles(); +$resBefore = count(get_resources()); $arch = new PharData($filename); $arch->addFromString('foo', 'bar'); +$arch->addFromString('foo2', 'baz'); $arch->compress(Phar::GZ); unset($arch); -$openFiles2 = countOpenFiles(); -var_dump($openFiles1 === $openFiles2); +$resAfter = count(get_resources()); +var_dump($resAfter - $resBefore); ?> --CLEAN-- --EXPECT-- -bool(true) +int(0) 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/tests/tar/phar_convert_phar.phpt b/ext/phar/tests/tar/phar_convert_phar.phpt index c25ed7c556bf7..3247550431d44 100644 --- a/ext/phar/tests/tar/phar_convert_phar.phpt +++ b/ext/phar/tests/tar/phar_convert_phar.phpt @@ -45,11 +45,11 @@ __HALT_COMPILER(); ?> --EXPECT-- bool(false) -int(6641) +int(6659) bool(true) string(60) " --EXPECT-- bool(false) -int(6641) +int(6659) bool(true) string(60) " --EXPECT-- bool(false) -int(6641) +int(6659) bool(true) string(60) " --EXPECT-- bool(false) -int(6641) +int(6659) string(2) "hi" bool(true) string(60) "getSignature()); + +echo "Set MD5:\n"; $p->setSignatureAlgorithm(Phar::MD5); var_dump($p->getSignature()); + +echo "Set SHA1:\n"; $p->setSignatureAlgorithm(Phar::SHA1); var_dump($p->getSignature()); + +echo "Set SHA256:\n"; try { -$p->setSignatureAlgorithm(Phar::SHA256); -var_dump($p->getSignature()); -} catch (Exception $e) { -echo $e->getMessage(); + $p->setSignatureAlgorithm(Phar::SHA256); + var_dump($p->getSignature()); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } + +echo "Set SHA512:\n"; try { -$p->setSignatureAlgorithm(Phar::SHA512); -var_dump($p->getSignature()); -} catch (Exception $e) { -echo $e->getMessage(); + $p->setSignatureAlgorithm(Phar::SHA512); + var_dump($p->getSignature()); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } + +echo "Set OPENSSL:\n"; try { -$config = __DIR__ . '/../files/openssl.cnf'; -$config_arg = array('config' => $config); -$private = openssl_get_privatekey(file_get_contents(dirname(__DIR__) . '/files/private.pem')); -$pkey = ''; -openssl_pkey_export($private, $pkey, NULL, $config_arg); -$p->setSignatureAlgorithm(Phar::OPENSSL, $pkey); -var_dump($p->getSignature()); -$p->setSignatureAlgorithm(Phar::OPENSSL_SHA512, $pkey); -var_dump($p->getSignature()); -$p->setSignatureAlgorithm(Phar::OPENSSL_SHA256, $pkey); -var_dump($p->getSignature()); -} catch (Exception $e) { -echo $e->getMessage(); + $config = __DIR__ . '/../files/openssl.cnf'; + $config_arg = array('config' => $config); + $private = openssl_get_privatekey(file_get_contents(dirname(__DIR__) . '/files/private.pem')); + $pkey = ''; + openssl_pkey_export($private, $pkey, NULL, $config_arg); + $p->setSignatureAlgorithm(Phar::OPENSSL, $pkey); + var_dump($p->getSignature()); + echo "Set OPENSSL_SHA512:\n"; + $p->setSignatureAlgorithm(Phar::OPENSSL_SHA512, $pkey); + var_dump($p->getSignature()); + echo "Set OPENSSL_SHA256:\n"; + $p->setSignatureAlgorithm(Phar::OPENSSL_SHA256, $pkey); + var_dump($p->getSignature()); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } + ?> --CLEAN-- --EXPECTF-- +Default: array(2) { ["hash"]=> string(%d) "%s" ["hash_type"]=> string(7) "SHA-256" } +Set MD5: array(2) { ["hash"]=> string(%d) "%s" ["hash_type"]=> string(3) "MD5" } +Set SHA1: array(2) { ["hash"]=> string(%d) "%s" ["hash_type"]=> string(5) "SHA-1" } +Set SHA256: array(2) { ["hash"]=> string(%d) "%s" ["hash_type"]=> string(7) "SHA-256" } +Set SHA512: array(2) { ["hash"]=> string(%d) "%s" ["hash_type"]=> string(7) "SHA-512" } +Set OPENSSL: array(2) { ["hash"]=> string(%d) "%s" ["hash_type"]=> string(7) "OpenSSL" } +Set OPENSSL_SHA512: array(2) { ["hash"]=> string(%d) "%s" ["hash_type"]=> string(14) "OpenSSL_SHA512" } +Set OPENSSL_SHA256: array(2) { ["hash"]=> string(%d) "%s" diff --git a/ext/phar/tests/tar_flush_too_long_filename.phpt b/ext/phar/tests/tar_flush_too_long_filename.phpt new file mode 100644 index 0000000000000..be18f5e481688 --- /dev/null +++ b/ext/phar/tests/tar_flush_too_long_filename.phpt @@ -0,0 +1,41 @@ +--TEST-- +Tar flush with too long file name +--EXTENSIONS-- +phar +--SKIPIF-- + +--INI-- +phar.require_hash=0 +--FILE-- +addEmptyDir('blah1/'); +$phar->setSignatureAlgorithm(Phar::OPENSSL, "randomcrap"); +try { + $phar->addEmptyDir('blah2/' . str_repeat('X', 1000)); +} catch (PharException $e) { + echo $e->getMessage(); +} + +?> +--CLEAN-- + +--EXPECTF-- +tar-based phar "%s" cannot be created, filename "%s" is too long for tar file format diff --git a/ext/phar/tests/zip/phar_convert_phar.phpt b/ext/phar/tests/zip/phar_convert_phar.phpt index f05a1cabaa6b7..18eab01c10f0d 100644 --- a/ext/phar/tests/zip/phar_convert_phar.phpt +++ b/ext/phar/tests/zip/phar_convert_phar.phpt @@ -45,11 +45,11 @@ __HALT_COMPILER(); ?> --EXPECT-- bool(false) -int(6641) +int(6659) bool(true) string(60) "getSignature()); + +echo "Set MD5:\n"; $p->setSignatureAlgorithm(Phar::MD5); copy($fname, $fname2); $p = new Phar($fname2); var_dump($p->getSignature()); +echo "Set SHA1:\n"; $p->setSignatureAlgorithm(Phar::SHA1); copy($fname2, $fname3); $p = new Phar($fname3); var_dump($p->getSignature()); +echo "Set SHA256:\n"; try { -$p->setSignatureAlgorithm(Phar::SHA256); -copy($fname3, $fname4); -$p = new Phar($fname4); -var_dump($p->getSignature()); -} catch (Exception $e) { -echo $e->getMessage(); + $p->setSignatureAlgorithm(Phar::SHA256); + copy($fname3, $fname4); + $p = new Phar($fname4); + var_dump($p->getSignature()); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } + +echo "Set SHA512:\n"; try { -$p->setSignatureAlgorithm(Phar::SHA512); -copy($fname4, $fname5); -$p = new Phar($fname5); -var_dump($p->getSignature()); -} catch (Exception $e) { -echo $e->getMessage(); + $p->setSignatureAlgorithm(Phar::SHA512); + copy($fname4, $fname5); + $p = new Phar($fname5); + var_dump($p->getSignature()); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } + +echo "Set OPENSSL:\n"; try { -$config = __DIR__ . '/../files/openssl.cnf'; -$config_arg = array('config' => $config); -$keys=openssl_pkey_new($config_arg); -openssl_pkey_export($keys, $privkey, NULL, $config_arg); -$pubkey=openssl_pkey_get_details($keys); -$p->setSignatureAlgorithm(Phar::OPENSSL, $privkey); + $config = __DIR__ . '/../files/openssl.cnf'; + $config_arg = array('config' => $config); + $keys=openssl_pkey_new($config_arg); + openssl_pkey_export($keys, $privkey, NULL, $config_arg); + $pubkey=openssl_pkey_get_details($keys); + $p->setSignatureAlgorithm(Phar::OPENSSL, $privkey); -copy($fname5, $fname6); -file_put_contents($fname6 . '.pubkey', $pubkey['key']); -$p = new Phar($fname6); -var_dump($p->getSignature()); -} catch (Exception $e) { -echo $e->getMessage(); + copy($fname5, $fname6); + file_put_contents($fname6 . '.pubkey', $pubkey['key']); + $p = new Phar($fname6); + var_dump($p->getSignature()); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } ?> --CLEAN-- @@ -76,36 +86,42 @@ unlink(__DIR__ . '/' . basename(__FILE__, '.clean.php') . '.6.phar.zip'); unlink(__DIR__ . '/' . basename(__FILE__, '.clean.php') . '.6.phar.zip.pubkey'); ?> --EXPECTF-- +Default: array(2) { ["hash"]=> string(%d) "%s" ["hash_type"]=> string(7) "SHA-256" } +Set MD5: array(2) { ["hash"]=> string(%d) "%s" ["hash_type"]=> string(3) "MD5" } +Set SHA1: array(2) { ["hash"]=> string(%d) "%s" ["hash_type"]=> string(5) "SHA-1" } +Set SHA256: array(2) { ["hash"]=> string(%d) "%s" ["hash_type"]=> string(7) "SHA-256" } +Set SHA512: array(2) { ["hash"]=> string(%d) "%s" ["hash_type"]=> string(7) "SHA-512" } +Set OPENSSL: array(2) { ["hash"]=> string(%d) "%s" diff --git a/ext/phar/util.c b/ext/phar/util.c index 06394813574b7..fdadc4d9b6bf7 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -96,22 +96,23 @@ static php_stream *phar_get_entrypufp(const phar_entry_info *entry) } /* retrieve a phar_entry_info's current file pointer for reading contents */ -php_stream *phar_get_efp(phar_entry_info *entry, int follow_links) /* {{{ */ +php_stream *phar_get_efp(phar_entry_info *entry, bool follow_links) /* {{{ */ { if (follow_links && entry->link) { phar_entry_info *link_entry = phar_get_link_source(entry); if (link_entry && link_entry != entry) { - return phar_get_efp(link_entry, 1); + return phar_get_efp(link_entry, true); } } if (phar_get_fp_type(entry) == PHAR_FP) { - if (!phar_get_entrypfp(entry)) { + php_stream *stream = phar_get_entrypfp(entry); + if (!stream) { /* re-open just in time for cases where our refcount reached 0 on the phar archive */ - phar_open_archive_fp(entry->phar); + stream = phar_open_archive_fp(entry->phar); } - return phar_get_entrypfp(entry); + return stream; } else if (phar_get_fp_type(entry) == PHAR_UFP) { return phar_get_entrypufp(entry); } else if (entry->fp_type == PHAR_MOD) { @@ -139,7 +140,7 @@ static zend_off_t phar_get_fp_offset(const phar_entry_info *entry) return PHAR_G(cached_fp)[entry->phar->phar_pos].manifest[entry->manifest_pos].offset; } -int phar_seek_efp(phar_entry_info *entry, zend_off_t offset, int whence, zend_off_t position, int follow_links) /* {{{ */ +int phar_seek_efp(phar_entry_info *entry, zend_off_t offset, int whence, zend_off_t position, bool follow_links) /* {{{ */ { php_stream *fp = phar_get_efp(entry, follow_links); zend_off_t temp, eoffset; @@ -193,7 +194,7 @@ zend_result phar_mount_entry(phar_archive_data *phar, char *filename, size_t fil { phar_entry_info entry = {0}; php_stream_statbuf ssb; - int is_phar; + bool is_phar; const char *err; if (phar_path_check(&path, &path_len, &err) > pcr_is_ok) { @@ -225,8 +226,8 @@ zend_result phar_mount_entry(phar_archive_data *phar, char *filename, size_t fil return FAILURE; } - entry.is_mounted = 1; - entry.is_crc_checked = 1; + entry.is_mounted = true; + entry.is_crc_checked = true; entry.fp_type = PHAR_TMP; if (SUCCESS != php_stream_stat_path(filename, &ssb)) { @@ -240,7 +241,7 @@ zend_result phar_mount_entry(phar_archive_data *phar, char *filename, size_t fil #endif if (ssb.sb.st_mode & S_IFDIR) { - entry.is_dir = 1; + entry.is_dir = true; if (NULL == zend_hash_add_ptr(&phar->mounted_dirs, entry.filename, entry.filename)) { /* directory already mounted */ efree(entry.tmp); @@ -248,7 +249,7 @@ zend_result phar_mount_entry(phar_archive_data *phar, char *filename, size_t fil return FAILURE; } } else { - entry.is_dir = 0; + entry.is_dir = false; entry.uncompressed_filesize = entry.compressed_filesize = ssb.sb.st_size; } @@ -267,8 +268,8 @@ zend_result phar_mount_entry(phar_archive_data *phar, char *filename, size_t fil zend_string *phar_find_in_include_path(zend_string *filename, phar_archive_data **pphar) /* {{{ */ { zend_string *ret; - char *path, *arch, *entry, *test; - size_t arch_len, entry_len; + char *path, *arch, *test; + size_t arch_len; phar_archive_data *phar; if (pphar) { @@ -301,12 +302,10 @@ zend_string *phar_find_in_include_path(zend_string *filename, phar_archive_data goto splitted; } - if (!is_file_a_phar_wrapper || SUCCESS != phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, &entry, &entry_len, 1, 0)) { + if (!is_file_a_phar_wrapper || SUCCESS != phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, NULL, 1, 0)) { return NULL; } - efree(entry); - if (*ZSTR_VAL(filename) == '.') { size_t try_len; @@ -347,7 +346,7 @@ zend_string *phar_find_in_include_path(zend_string *filename, phar_archive_data if (ret && zend_string_starts_with_literal_ci(ret, "phar://")) { /* found phar:// */ - if (SUCCESS != phar_split_fname(ZSTR_VAL(ret), ZSTR_LEN(ret), &arch, &arch_len, &entry, &entry_len, 1, 0)) { + if (SUCCESS != phar_split_fname(ZSTR_VAL(ret), ZSTR_LEN(ret), &arch, &arch_len, NULL, NULL, 1, 0)) { return ret; } @@ -358,15 +357,16 @@ zend_string *phar_find_in_include_path(zend_string *filename, phar_archive_data } efree(arch); - efree(entry); } return ret; } /* }}} */ -static zend_result phar_create_writeable_entry(phar_archive_data *phar, phar_entry_info *entry, char **error) /* {{{ */ +static ZEND_ATTRIBUTE_NONNULL zend_result phar_create_writeable_entry(phar_archive_data *phar, phar_entry_info *entry, char **error) /* {{{ */ { + *error = NULL; + if (entry->fp_type == PHAR_MOD) { /* already newly created, truncate */ php_stream_truncate_set_size(entry->fp, 0); @@ -384,10 +384,6 @@ static zend_result phar_create_writeable_entry(phar_archive_data *phar, phar_ent return SUCCESS; } - if (error) { - *error = NULL; - } - /* open a new temp file for writing */ if (entry->link) { efree(entry->link); @@ -398,9 +394,7 @@ static zend_result phar_create_writeable_entry(phar_archive_data *phar, phar_ent entry->fp = php_stream_fopen_tmpfile(); if (!entry->fp) { - if (error) { - spprintf(error, 0, "phar error: unable to create temporary file"); - } + *error = estrdup("phar error: unable to create temporary file"); return FAILURE; } @@ -418,12 +412,12 @@ static zend_result phar_create_writeable_entry(phar_archive_data *phar, phar_ent } /* }}} */ -static zend_result phar_separate_entry_fp(phar_entry_info *entry, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL static zend_result phar_separate_entry_fp(phar_entry_info *entry, char **error) /* {{{ */ { php_stream *fp; phar_entry_info *link; - if (FAILURE == phar_open_entry_fp(entry, error, 1)) { + if (FAILURE == phar_open_entry_fp(entry, error, true)) { return FAILURE; } @@ -433,20 +427,18 @@ static zend_result phar_separate_entry_fp(phar_entry_info *entry, char **error) fp = php_stream_fopen_tmpfile(); if (fp == NULL) { - spprintf(error, 0, "phar error: unable to create temporary file"); + *error = estrdup("phar error: unable to create temporary file"); return FAILURE; } - phar_seek_efp(entry, 0, SEEK_SET, 0, 1); + phar_seek_efp(entry, 0, SEEK_SET, 0, true); 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 (error) { - spprintf(error, 4096, "phar error: cannot separate entry file \"%s\" contents in phar archive \"%s\" for write access", ZSTR_VAL(entry->filename), entry->phar->fname); - } + if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(link, false), fp, link->uncompressed_filesize, NULL)) { + spprintf(error, 4096, "phar error: cannot separate entry file \"%s\" contents in phar archive \"%s\" for write access", ZSTR_VAL(entry->filename), entry->phar->fname); return FAILURE; } @@ -472,7 +464,7 @@ static zend_result phar_separate_entry_fp(phar_entry_info *entry, char **error) * appended, truncated, or read. For read, if the entry is marked unmodified, it is * assumed that the file pointer, if present, is opened for reading */ -zend_result phar_get_entry_data(phar_entry_data **ret, char *fname, size_t fname_len, char *path, size_t path_len, const char *mode, char allow_dir, char **error, int security) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL zend_result phar_get_entry_data(phar_entry_data **ret, char *fname, size_t fname_len, char *path, size_t path_len, const char *mode, char allow_dir, char **error, bool security) /* {{{ */ { phar_archive_data *phar; phar_entry_info *entry; @@ -481,31 +473,20 @@ zend_result phar_get_entry_data(phar_entry_data **ret, char *fname, size_t fname bool for_create = mode[0] != 'r'; bool for_trunc = mode[0] == 'w'; - if (!ret) { - return FAILURE; - } - *ret = NULL; - - if (error) { - *error = NULL; - } + *error = NULL; if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, error)) { return FAILURE; } if (for_write && PHAR_G(readonly) && !phar->is_data) { - if (error) { - spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, disabled by ini setting", path, fname); - } + spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, disabled by ini setting", path, fname); return FAILURE; } if (!path_len) { - if (error) { - spprintf(error, 4096, "phar error: file \"\" in phar \"%s\" must not be empty", fname); - } + spprintf(error, 4096, "phar error: file \"\" in phar \"%s\" must not be empty", fname); return FAILURE; } really_get_entry: @@ -527,9 +508,7 @@ zend_result phar_get_entry_data(phar_entry_data **ret, char *fname, size_t fname if (for_write && phar->is_persistent) { if (FAILURE == phar_copy_on_write(&phar)) { - if (error) { - spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, could not make cached phar writeable", path, fname); - } + spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, could not make cached phar writeable", path, fname); return FAILURE; } else { goto really_get_entry; @@ -537,16 +516,12 @@ zend_result phar_get_entry_data(phar_entry_data **ret, char *fname, size_t fname } if (entry->is_modified && !for_write) { - if (error) { - spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for reading, writable file pointers are open", path, fname); - } + spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for reading, writable file pointers are open", path, fname); return FAILURE; } if (entry->fp_refcount && for_write) { - if (error) { - spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, readable file pointers are open", path, fname); - } + spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, readable file pointers are open", path, fname); return FAILURE; } @@ -578,7 +553,7 @@ zend_result phar_get_entry_data(phar_entry_data **ret, char *fname, size_t fname return FAILURE; } } else if (for_append) { - phar_seek_efp(entry, 0, SEEK_END, 0, 0); + phar_seek_efp(entry, 0, SEEK_END, 0, false); } } else { if (for_write) { @@ -598,7 +573,7 @@ zend_result phar_get_entry_data(phar_entry_data **ret, char *fname, size_t fname } } } else { - if (FAILURE == phar_open_entry_fp(entry, error, 1)) { + if (FAILURE == phar_open_entry_fp(entry, error, true)) { return FAILURE; } } @@ -608,7 +583,7 @@ zend_result phar_get_entry_data(phar_entry_data **ret, char *fname, size_t fname (*ret)->position = 0; (*ret)->phar = phar; (*ret)->internal_file = entry; - (*ret)->fp = phar_get_efp(entry, 1); + (*ret)->fp = phar_get_efp(entry, true); if (entry->link) { phar_entry_info *link = phar_get_link_source(entry); if(!link) { @@ -632,7 +607,7 @@ zend_result phar_get_entry_data(phar_entry_data **ret, char *fname, size_t fname /** * Create a new dummy file slot within a writeable phar for a newly created file */ -phar_entry_data *phar_get_or_create_entry_data(char *fname, size_t fname_len, char *path, size_t path_len, const char *mode, char allow_dir, char **error, int security) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL phar_entry_data *phar_get_or_create_entry_data(char *fname, size_t fname_len, char *path, size_t path_len, const char *mode, char allow_dir, char **error, bool security, uint32_t timestamp) /* {{{ */ { phar_archive_data *phar; phar_entry_info *entry, etemp; @@ -657,16 +632,12 @@ phar_entry_data *phar_get_or_create_entry_data(char *fname, size_t fname_len, ch } if (phar_path_check(&path, &path_len, &pcr_error) > pcr_is_ok) { - if (error) { - spprintf(error, 0, "phar error: invalid path \"%s\" contains %s", path, pcr_error); - } + spprintf(error, 0, "phar error: invalid path \"%s\" contains %s", path, pcr_error); return NULL; } if (phar->is_persistent && FAILURE == phar_copy_on_write(&phar)) { - if (error) { - spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be created, could not make cached phar writeable", path, fname); - } + spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be created, could not make cached phar writeable", path, fname); return NULL; } @@ -679,9 +650,7 @@ phar_entry_data *phar_get_or_create_entry_data(char *fname, size_t fname_len, ch etemp.fp = php_stream_fopen_tmpfile(); if (!etemp.fp) { - if (error) { - spprintf(error, 0, "phar error: unable to create temporary file"); - } + *error = estrdup("phar error: unable to create temporary file"); efree(ret); return NULL; } @@ -700,7 +669,7 @@ phar_entry_data *phar_get_or_create_entry_data(char *fname, size_t fname_len, ch phar_add_virtual_dirs(phar, path, path_len); etemp.is_modified = 1; - etemp.timestamp = time(0); + etemp.timestamp = timestamp; etemp.is_crc_checked = 1; etemp.phar = phar; etemp.filename = zend_string_init(path, path_len, false); @@ -713,9 +682,8 @@ phar_entry_data *phar_get_or_create_entry_data(char *fname, size_t fname_len, ch if (NULL == (entry = zend_hash_add_mem(&phar->manifest, etemp.filename, &etemp, sizeof(phar_entry_info)))) { php_stream_close(etemp.fp); - if (error) { - spprintf(error, 0, "phar error: unable to add new entry \"%s\" to phar \"%s\"", ZSTR_VAL(etemp.filename), phar->fname); - } + spprintf(error, 0, "phar error: unable to add new entry \"%s\" to phar \"%s\"", + ZSTR_VAL(etemp.filename), phar->fname); efree(ret); zend_string_efree(etemp.filename); return NULL; @@ -741,33 +709,32 @@ static inline void phar_set_pharfp(phar_archive_data *phar, php_stream *fp) PHAR_G(cached_fp)[phar->phar_pos].fp = fp; } -/* initialize a phar_archive_data's read-only fp for existing phar data */ -zend_result phar_open_archive_fp(phar_archive_data *phar) /* {{{ */ +/* Initialize a phar_archive_data's read-only fp for existing phar data. + * The stream is owned by the `phar` object and must not be closed manually. */ +php_stream *phar_open_archive_fp(phar_archive_data *phar) /* {{{ */ { - if (phar_get_pharfp(phar)) { - return SUCCESS; + php_stream *stream = phar_get_pharfp(phar); + if (stream) { + return stream; } if (php_check_open_basedir(phar->fname)) { - return FAILURE; + return NULL; } - phar_set_pharfp(phar, php_stream_open_wrapper(phar->fname, "rb", IGNORE_URL|STREAM_MUST_SEEK|0, NULL)); + stream = php_stream_open_wrapper(phar->fname, "rb", IGNORE_URL|STREAM_MUST_SEEK, NULL); + phar_set_pharfp(phar, stream); - if (!phar_get_pharfp(phar)) { - return FAILURE; - } - - return SUCCESS; + return stream; } /* }}} */ /* copy file data from an existing to a new phar_entry_info that is not in the manifest */ -zend_result phar_copy_entry_fp(phar_entry_info *source, phar_entry_info *dest, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL zend_result phar_copy_entry_fp(phar_entry_info *source, phar_entry_info *dest, char **error) /* {{{ */ { phar_entry_info *link; - if (FAILURE == phar_open_entry_fp(source, error, 1)) { + if (FAILURE == phar_open_entry_fp(source, error, true)) { return FAILURE; } @@ -782,22 +749,21 @@ zend_result phar_copy_entry_fp(phar_entry_info *source, phar_entry_info *dest, c dest->is_modified = 1; dest->fp = php_stream_fopen_tmpfile(); if (dest->fp == NULL) { - spprintf(error, 0, "phar error: unable to create temporary file"); + *error = estrdup("phar error: unable to create temporary file"); return EOF; } - phar_seek_efp(source, 0, SEEK_SET, 0, 1); + phar_seek_efp(source, 0, SEEK_SET, 0, true); link = phar_get_link_source(source); if (!link) { link = source; } - if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(link, 0), dest->fp, link->uncompressed_filesize, NULL)) { + if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(link, false), dest->fp, link->uncompressed_filesize, NULL)) { php_stream_close(dest->fp); dest->fp_type = PHAR_FP; - if (error) { - spprintf(error, 4096, "phar error: unable to copy contents of file \"%s\" to \"%s\" in phar archive \"%s\"", ZSTR_VAL(source->filename), ZSTR_VAL(dest->filename), source->phar->fname); - } + spprintf(error, 4096, "phar error: unable to copy contents of file \"%s\" to \"%s\" in phar archive \"%s\"", + ZSTR_VAL(source->filename), ZSTR_VAL(dest->filename), source->phar->fname); return FAILURE; } @@ -831,11 +797,10 @@ static void phar_set_fp_type(phar_entry_info *entry, enum phar_fp_type type, zen /* open and decompress a compressed phar entry */ -zend_result phar_open_entry_fp(phar_entry_info *entry, char **error, int follow_links) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL zend_result phar_open_entry_fp(phar_entry_info *entry, char **error, bool follow_links) /* {{{ */ { php_stream_filter *filter; phar_archive_data *phar = entry->phar; - char *filtername; zend_off_t loc; php_stream *ufp; phar_entry_data dummy; @@ -843,7 +808,7 @@ zend_result phar_open_entry_fp(phar_entry_info *entry, char **error, int follow_ if (follow_links && entry->link) { phar_entry_info *link_entry = phar_get_link_source(entry); if (link_entry && link_entry != entry) { - return phar_open_entry_fp(link_entry, error, 1); + return phar_open_entry_fp(link_entry, error, true); } } @@ -864,7 +829,7 @@ zend_result phar_open_entry_fp(phar_entry_info *entry, char **error, int follow_ } if (!phar_get_pharfp(phar)) { - if (FAILURE == phar_open_archive_fp(phar)) { + if (!phar_open_archive_fp(phar)) { spprintf(error, 4096, "phar error: Cannot open phar archive \"%s\" for reading", phar->fname); return FAILURE; } @@ -899,14 +864,15 @@ zend_result phar_open_entry_fp(phar_entry_info *entry, char **error, int follow_ ufp = phar_get_entrypufp(entry); - if ((filtername = phar_decompress_filter(entry, 0)) != NULL) { - filter = php_stream_filter_create(filtername, NULL, 0); + const char *filter_name = phar_decompress_filter(entry, false); + if (filter_name != NULL) { + filter = php_stream_filter_create(filter_name, NULL, 0); } else { filter = NULL; } if (!filter) { - spprintf(error, 4096, "phar error: unable to read phar \"%s\" (cannot create %s filter while decompressing file \"%s\")", phar->fname, phar_decompress_filter(entry, 1), ZSTR_VAL(entry->filename)); + spprintf(error, 4096, "phar error: unable to read phar \"%s\" (cannot create %s filter while decompressing file \"%s\")", phar->fname, phar_decompress_filter(entry, true), ZSTR_VAL(entry->filename)); return FAILURE; } @@ -950,16 +916,14 @@ zend_result phar_open_entry_fp(phar_entry_info *entry, char **error, int follow_ /** * helper function to open an internal file's fp just-in-time */ -phar_entry_info * phar_open_jit(phar_archive_data *phar, phar_entry_info *entry, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL phar_entry_info * phar_open_jit(const phar_archive_data *phar, phar_entry_info *entry, char **error) /* {{{ */ { - if (error) { - *error = NULL; - } + *error = NULL; /* seek to start of internal file and read it */ - if (FAILURE == phar_open_entry_fp(entry, error, 1)) { + if (FAILURE == phar_open_entry_fp(entry, error, true)) { return NULL; } - if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 1)) { + if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, true)) { spprintf(error, 4096, "phar error: cannot seek to start of file \"%s\" in phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); return NULL; } @@ -1194,7 +1158,7 @@ zend_result phar_get_archive(phar_archive_data **archive, char *fname, size_t fn /** * Determine which stream compression filter (if any) we need to read this file */ -char * phar_compress_filter(phar_entry_info * entry, int return_unknown) /* {{{ */ +const char * phar_compress_filter(const phar_entry_info *entry, bool return_unknown) /* {{{ */ { switch (entry->flags & PHAR_ENT_COMPRESSION_MASK) { case PHAR_ENT_COMPRESSED_GZ: @@ -1210,7 +1174,7 @@ char * phar_compress_filter(phar_entry_info * entry, int return_unknown) /* {{{ /** * Determine which stream decompression filter (if any) we need to read this file */ -char * phar_decompress_filter(phar_entry_info * entry, int return_unknown) /* {{{ */ +const char * phar_decompress_filter(const phar_entry_info *entry, bool return_unknown) /* {{{ */ { uint32_t flags; @@ -1234,7 +1198,7 @@ char * phar_decompress_filter(phar_entry_info * entry, int return_unknown) /* {{ /** * retrieve information on a file contained within a phar, or null if it ain't there */ -phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, size_t path_len, char **error, int security) /* {{{ */ +phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, size_t path_len, char **error, bool security) /* {{{ */ { return phar_get_entry_info_dir(phar, path, path_len, 0, error, security); } @@ -1245,17 +1209,17 @@ phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, size_t * valid pre-existing empty directory entries */ // TODO: convert this to use zend_string too -phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, size_t path_len, char dir, char **error, int security) /* {{{ */ +phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, size_t path_len, char dir, char **error, bool security) /* {{{ */ { const char *pcr_error; phar_entry_info *entry; - int is_dir; + bool is_dir; #ifdef PHP_WIN32 phar_unixify_path_separators(path, path_len); #endif - is_dir = (path_len && (path[path_len - 1] == '/')) ? 1 : 0; + is_dir = path_len && (path[path_len - 1] == '/'); if (error) { *error = NULL; @@ -1500,8 +1464,10 @@ static zend_result phar_call_openssl_signverify(bool is_sign, php_stream *fp, ze *signature_len = Z_STRLEN(zp[1]); zval_ptr_dtor(&zp[1]); return SUCCESS; - case IS_FALSE: default: + zval_ptr_dtor(&retval); + ZEND_FALLTHROUGH; + case IS_FALSE: zval_ptr_dtor(&zp[1]); return FAILURE; } @@ -1543,7 +1509,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s #ifndef PHAR_HAVE_OPENSSL if (!zend_hash_str_exists(&module_registry, "openssl", sizeof("openssl")-1)) { if (error) { - spprintf(error, 0, "openssl not loaded"); + *error = estrdup("openssl not loaded"); } return FAILURE; } @@ -1558,7 +1524,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s php_stream_close(pfp); } if (error) { - spprintf(error, 0, "openssl public key could not be read"); + *error = estrdup("openssl public key could not be read"); } return FAILURE; } @@ -1571,7 +1537,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s zend_string_release_ex(pubkey, 0); if (error) { - spprintf(error, 0, "openssl signature could not be verified"); + *error = estrdup("openssl signature could not be verified"); } return FAILURE; @@ -1586,7 +1552,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s if (NULL == in) { zend_string_release_ex(pubkey, 0); if (error) { - spprintf(error, 0, "openssl signature could not be processed"); + *error = estrdup("openssl signature could not be processed"); } return FAILURE; } @@ -1597,7 +1563,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s if (NULL == key) { if (error) { - spprintf(error, 0, "openssl signature could not be processed"); + *error = estrdup("openssl signature could not be processed"); } return FAILURE; } @@ -1608,7 +1574,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s EVP_MD_CTX_destroy(md_ctx); } if (error) { - spprintf(error, 0, "openssl signature could not be verified"); + *error = estrdup("openssl signature could not be verified"); } return FAILURE; } @@ -1640,7 +1606,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s EVP_MD_CTX_destroy(md_ctx); if (error) { - spprintf(error, 0, "broken openssl signature"); + *error = estrdup("broken openssl signature"); } return FAILURE; @@ -1659,7 +1625,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s if (sig_len < sizeof(digest)) { if (error) { - spprintf(error, 0, "broken signature"); + *error = estrdup("broken openssl signature"); } return FAILURE; } @@ -1685,7 +1651,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s if (memcmp(digest, sig, sizeof(digest))) { if (error) { - spprintf(error, 0, "broken signature"); + *error = estrdup("broken openssl signature"); } return FAILURE; } @@ -1699,7 +1665,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s if (sig_len < sizeof(digest)) { if (error) { - spprintf(error, 0, "broken signature"); + *error = estrdup("broken openssl signature"); } return FAILURE; } @@ -1725,7 +1691,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s if (memcmp(digest, sig, sizeof(digest))) { if (error) { - spprintf(error, 0, "broken signature"); + *error = estrdup("broken signature"); } return FAILURE; } @@ -1739,7 +1705,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s if (sig_len < sizeof(digest)) { if (error) { - spprintf(error, 0, "broken signature"); + *error = estrdup("broken signature"); } return FAILURE; } @@ -1765,7 +1731,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s if (memcmp(digest, sig, sizeof(digest))) { if (error) { - spprintf(error, 0, "broken signature"); + *error = estrdup("broken signature"); } return FAILURE; } @@ -1779,7 +1745,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s if (sig_len < sizeof(digest)) { if (error) { - spprintf(error, 0, "broken signature"); + *error = estrdup("broken signature"); } return FAILURE; } @@ -1805,7 +1771,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s if (memcmp(digest, sig, sizeof(digest))) { if (error) { - spprintf(error, 0, "broken signature"); + *error = estrdup("broken signature"); } return FAILURE; } @@ -1815,7 +1781,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s } default: if (error) { - spprintf(error, 0, "broken or unsupported signature"); + *error = estrdup("broken or unsupported signature"); } return FAILURE; } @@ -1823,7 +1789,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s } /* }}} */ -zend_result phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, size_t *signature_length, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, size_t *signature_length, char **error) /* {{{ */ { unsigned char buf[1024]; size_t sig_len; @@ -1891,9 +1857,7 @@ zend_result phar_create_signature(phar_archive_data *phar, php_stream *fp, char in = BIO_new_mem_buf(PHAR_G(openssl_privatekey), PHAR_G(openssl_privatekey_len)); if (in == NULL) { - if (error) { - spprintf(error, 0, "unable to write to phar \"%s\" with requested openssl signature", phar->fname); - } + spprintf(error, 0, "unable to write to phar \"%s\" with requested openssl signature", phar->fname); return FAILURE; } @@ -1901,18 +1865,14 @@ zend_result phar_create_signature(phar_archive_data *phar, php_stream *fp, char BIO_free(in); if (!key) { - if (error) { - spprintf(error, 0, "unable to process private key"); - } + *error = estrdup("unable to process private key"); return FAILURE; } md_ctx = EVP_MD_CTX_create(); if (md_ctx == NULL) { EVP_PKEY_free(key); - if (error) { - spprintf(error, 0, "unable to initialize openssl signature for phar \"%s\"", phar->fname); - } + spprintf(error, 0, "unable to initialize openssl signature for phar \"%s\"", phar->fname); return FAILURE; } @@ -1921,30 +1881,27 @@ 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_destroy(md_ctx); efree(sigbuf); - if (error) { - spprintf(error, 0, "unable to initialize openssl signature for phar \"%s\"", phar->fname); - } + spprintf(error, 0, "unable to initialize openssl signature for phar \"%s\"", phar->fname); return FAILURE; } 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_destroy(md_ctx); efree(sigbuf); - if (error) { - spprintf(error, 0, "unable to update the openssl signature for phar \"%s\"", phar->fname); - } + spprintf(error, 0, "unable to update the openssl signature for phar \"%s\"", phar->fname); return FAILURE; } } if (!EVP_SignFinal (md_ctx, sigbuf, &siglen, key)) { EVP_PKEY_free(key); + EVP_MD_CTX_destroy(md_ctx); efree(sigbuf); - if (error) { - spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", phar->fname); - } + spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", phar->fname); return FAILURE; } @@ -1958,9 +1915,7 @@ zend_result phar_create_signature(phar_archive_data *phar, php_stream *fp, char php_stream_seek(fp, 0, SEEK_END); if (FAILURE == phar_call_openssl_signverify(true, fp, php_stream_tell(fp), PHAR_G(openssl_privatekey), PHAR_G(openssl_privatekey_len), (char **)&sigbuf, &siglen, phar->sig_flags)) { - if (error) { - spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", phar->fname); - } + spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", phar->fname); return FAILURE; } #endif diff --git a/ext/phar/zip.c b/ext/phar/zip.c index 0ee958bda24fb..9e71a33ccf98a 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -41,7 +41,7 @@ static inline void phar_write_16(char buffer[2], uint32_t value) # define PHAR_SET_32(var, value) phar_write_32(var, (uint32_t) (value)); # define PHAR_SET_16(var, value) phar_write_16(var, (uint16_t) (value)); -static int phar_zip_process_extra(php_stream *fp, phar_entry_info *entry, uint16_t len) /* {{{ */ +static zend_result phar_zip_process_extra(php_stream *fp, phar_entry_info *entry, uint16_t len) /* {{{ */ { union { phar_zip_extra_field_header header; @@ -226,7 +226,7 @@ static char *phar_find_eocd(const char *s, size_t n) * This is used by phar_open_from_fp to process a zip-based phar, but can be called * directly. */ -int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alias, size_t alias_len, phar_archive_data** pphar, char **error) /* {{{ */ +zend_result phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alias, size_t alias_len, phar_archive_data** pphar, char **error) /* {{{ */ { phar_zip_dir_end locator; char buf[sizeof(locator) + 65536]; @@ -234,7 +234,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia uint16_t i; phar_archive_data *mydata = NULL; phar_entry_info entry = {0}; - char *p = buf, *ext, *actual_alias = NULL; + char *ext, *actual_alias = NULL; char *metadata = NULL; size = php_stream_tell(fp); @@ -261,58 +261,55 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia return FAILURE; } - if ((p = phar_find_eocd(buf, size)) != NULL) { - memcpy((void *)&locator, (void *) p, sizeof(locator)); - if (PHAR_GET_16(locator.centraldisk) != 0 || PHAR_GET_16(locator.disknumber) != 0) { - /* split archives not handled */ - php_stream_close(fp); - if (error) { - spprintf(error, 4096, "phar error: split archives spanning multiple zips cannot be processed in zip-based phar \"%s\"", fname); - } - return FAILURE; + char *p = phar_find_eocd(buf, size); + if (!p) { + php_stream_close(fp); + if (error) { + spprintf(error, 4096, "phar error: end of central directory not found in zip-based phar \"%s\"", fname); } + return FAILURE; + } - if (PHAR_GET_16(locator.counthere) != PHAR_GET_16(locator.count)) { - if (error) { - spprintf(error, 4096, "phar error: corrupt zip archive, conflicting file count in end of central directory record in zip-based phar \"%s\"", fname); - } - php_stream_close(fp); - return FAILURE; + memcpy((void *)&locator, (void *) p, sizeof(locator)); + if (PHAR_GET_16(locator.centraldisk) != 0 || PHAR_GET_16(locator.disknumber) != 0) { + /* split archives not handled */ + php_stream_close(fp); + if (error) { + spprintf(error, 4096, "phar error: split archives spanning multiple zips cannot be processed in zip-based phar \"%s\"", fname); } + return FAILURE; + } - mydata = pecalloc(1, sizeof(phar_archive_data), PHAR_G(persist)); - mydata->is_persistent = PHAR_G(persist); + if (PHAR_GET_16(locator.counthere) != PHAR_GET_16(locator.count)) { + if (error) { + spprintf(error, 4096, "phar error: corrupt zip archive, conflicting file count in end of central directory record in zip-based phar \"%s\"", fname); + } + php_stream_close(fp); + return FAILURE; + } - /* read in archive comment, if any */ - if (PHAR_GET_16(locator.comment_len)) { + mydata = pecalloc(1, sizeof(phar_archive_data), PHAR_G(persist)); + mydata->is_persistent = PHAR_G(persist); - metadata = p + sizeof(locator); + /* read in archive comment, if any */ + if (PHAR_GET_16(locator.comment_len)) { - if (PHAR_GET_16(locator.comment_len) != size - (metadata - buf)) { - if (error) { - spprintf(error, 4096, "phar error: corrupt zip archive, zip file comment truncated in zip-based phar \"%s\"", fname); - } - php_stream_close(fp); - pefree(mydata, mydata->is_persistent); - return FAILURE; - } + metadata = p + sizeof(locator); - phar_parse_metadata_lazy(metadata, &mydata->metadata_tracker, PHAR_GET_16(locator.comment_len), mydata->is_persistent); - } else { - ZVAL_UNDEF(&mydata->metadata_tracker.val); + if (PHAR_GET_16(locator.comment_len) != size - (metadata - buf)) { + if (error) { + spprintf(error, 4096, "phar error: corrupt zip archive, zip file comment truncated in zip-based phar \"%s\"", fname); + } + php_stream_close(fp); + pefree(mydata, mydata->is_persistent); + return FAILURE; } - goto foundit; - } - - php_stream_close(fp); - - if (error) { - spprintf(error, 4096, "phar error: end of central directory not found in zip-based phar \"%s\"", fname); + phar_parse_metadata_lazy(metadata, &mydata->metadata_tracker, PHAR_GET_16(locator.comment_len), mydata->is_persistent); + } else { + ZVAL_UNDEF(&mydata->metadata_tracker.val); } - return FAILURE; -foundit: mydata->fname = pestrndup(fname, fname_len, mydata->is_persistent); #ifdef PHP_WIN32 phar_unixify_path_separators(mydata->fname, fname_len); @@ -336,38 +333,17 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia php_stream_seek(fp, PHAR_GET_32(locator.cdir_offset), SEEK_SET); /* read in central directory */ zend_hash_init(&mydata->manifest, PHAR_GET_16(locator.count), - zend_get_hash_value, destroy_phar_manifest_entry, (bool)mydata->is_persistent); + zend_get_hash_value, destroy_phar_manifest_entry, mydata->is_persistent); zend_hash_init(&mydata->mounted_dirs, 5, - zend_get_hash_value, NULL, (bool)mydata->is_persistent); + zend_get_hash_value, NULL, mydata->is_persistent); zend_hash_init(&mydata->virtual_dirs, PHAR_GET_16(locator.count) * 2, - zend_get_hash_value, NULL, (bool)mydata->is_persistent); + zend_get_hash_value, NULL, mydata->is_persistent); entry.phar = mydata; entry.is_zip = 1; entry.fp_type = PHAR_FP; entry.is_persistent = mydata->is_persistent; -#define PHAR_ZIP_FAIL_FREE(errmsg, save) \ - zend_hash_destroy(&mydata->manifest); \ - HT_INVALIDATE(&mydata->manifest); \ - zend_hash_destroy(&mydata->mounted_dirs); \ - HT_INVALIDATE(&mydata->mounted_dirs); \ - zend_hash_destroy(&mydata->virtual_dirs); \ - HT_INVALIDATE(&mydata->virtual_dirs); \ - php_stream_close(fp); \ - phar_metadata_tracker_free(&mydata->metadata_tracker, mydata->is_persistent); \ - if (mydata->signature) { \ - efree(mydata->signature); \ - } \ - if (error) { \ - spprintf(error, 4096, "phar error: %s in zip-based phar \"%s\"", errmsg, mydata->fname); \ - } \ - pefree(mydata->fname, mydata->is_persistent); \ - if (mydata->alias) { \ - pefree(mydata->alias, mydata->is_persistent); \ - } \ - pefree(mydata, mydata->is_persistent); \ - efree(save); \ - return FAILURE; #define PHAR_ZIP_FAIL(errmsg) \ + efree(actual_alias); \ zend_hash_destroy(&mydata->manifest); \ HT_INVALIDATE(&mydata->manifest); \ zend_hash_destroy(&mydata->mounted_dirs); \ @@ -522,14 +498,13 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia mydata->sig_flags = PHAR_GET_32(sig); if (FAILURE == phar_verify_signature(sigfile, php_stream_tell(sigfile), mydata->sig_flags, sig + 8, entry.uncompressed_filesize - 8, fname, &mydata->signature, &sig_len, error)) { efree(sig); + php_stream_close(sigfile); if (error) { - char *save; - php_stream_close(sigfile); - spprintf(&save, 4096, "signature cannot be verified: %s", *error); + char errmsg[128]; + snprintf(errmsg, sizeof(errmsg), "signature cannot be verified: %s", *error); efree(*error); - PHAR_ZIP_FAIL_FREE(save, save); + PHAR_ZIP_FAIL(errmsg); } else { - php_stream_close(sigfile); PHAR_ZIP_FAIL("signature cannot be verified"); } } @@ -641,13 +616,6 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia zend_off_t restore_pos = php_stream_tell(fp); php_stream_seek(fp, entry.offset, SEEK_SET); - /* these next lines should be for php < 5.2.6 after 5.3 filters are fixed */ - fp->writepos = 0; - fp->readpos = 0; - php_stream_seek(fp, entry.offset, SEEK_SET); - fp->writepos = 0; - fp->readpos = 0; - /* the above lines should be for php < 5.2.6 after 5.3 filters are fixed */ mydata->alias_len = entry.uncompressed_filesize; if (entry.flags & PHAR_ENT_COMPRESSED_GZ) { @@ -674,7 +642,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia } } - if (!entry.uncompressed_filesize || !actual_alias) { + if (!entry.uncompressed_filesize) { php_stream_filter_remove(filter, 1); zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unable to read in alias, truncated"); @@ -707,7 +675,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia } } - if (!entry.uncompressed_filesize || !actual_alias) { + if (!entry.uncompressed_filesize) { php_stream_filter_remove(filter, 1); zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unable to read in alias, truncated"); @@ -730,7 +698,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia } } - if (!entry.uncompressed_filesize || !actual_alias) { + if (!entry.uncompressed_filesize) { zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unable to read in alias, truncated"); } @@ -827,18 +795,16 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia /** * Create or open a zip-based phar for writing */ -int phar_open_or_create_zip(char *fname, size_t fname_len, char *alias, size_t alias_len, int is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_open_or_create_zip(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { phar_archive_data *phar; - int ret = phar_create_or_parse_filename(fname, fname_len, alias, alias_len, is_data, options, &phar, error); + zend_result ret = phar_create_or_parse_filename(fname, fname_len, alias, alias_len, is_data, options, &phar, error); if (FAILURE == ret) { return FAILURE; } - if (pphar) { - *pphar = phar; - } + *pphar = phar; phar->is_data = is_data; @@ -853,9 +819,7 @@ int phar_open_or_create_zip(char *fname, size_t fname_len, char *alias, size_t a } /* we've reached here - the phar exists and is a regular phar */ - if (error) { - spprintf(error, 4096, "phar zip error: phar \"%s\" already exists as a regular phar and must be deleted from disk prior to creating as a zip-based phar", fname); - } + spprintf(error, 4096, "phar zip error: phar \"%s\" already exists as a regular phar and must be deleted from disk prior to creating as a zip-based phar", fname); return FAILURE; } @@ -878,7 +842,7 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ struct _phar_zip_pass *p; uint32_t newcrc32; zend_off_t offset; - int not_really_modified = 0; + bool not_really_modified = false; p = (struct _phar_zip_pass*) arg; uint16_t general_purpose_flags; @@ -887,7 +851,7 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ } if (entry->is_deleted) { - if (entry->fp_refcount <= 0) { + if (entry->fp_refcount <= 0 && entry->fileinfo_lock_count == 0) { return ZEND_HASH_APPLY_REMOVE; } else { /* we can't delete this in-memory until it is closed */ @@ -952,23 +916,23 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ goto continue_dir; } - if (FAILURE == phar_open_entry_fp(entry, p->error, 0)) { + if (FAILURE == phar_open_entry_fp(entry, p->error, false)) { spprintf(p->error, 0, "unable to open file contents of file \"%s\" in zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } /* we can be modified and already be compressed, such as when chmod() is executed */ if (entry->flags & PHAR_ENT_COMPRESSION_MASK && (entry->old_flags == entry->flags || !entry->old_flags)) { - not_really_modified = 1; + not_really_modified = true; goto is_compressed; } - if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 0)) { + if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, false)) { spprintf(p->error, 0, "unable to seek to start of file \"%s\" to zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } - efp = phar_get_efp(entry, 0); + efp = phar_get_efp(entry, false); newcrc32 = php_crc32_bulk_init(); php_crc32_stream_bulk_update(&newcrc32, efp, entry->uncompressed_filesize); @@ -985,7 +949,7 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ goto not_compressed; } - filter = php_stream_filter_create(phar_compress_filter(entry, 0), NULL, 0); + filter = php_stream_filter_create(phar_compress_filter(entry, false), NULL, 0); if (!filter) { if (entry->flags & PHAR_ENT_COMPRESSED_GZ) { @@ -1009,7 +973,7 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ php_stream_flush(efp); - if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 0)) { + if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, false)) { php_stream_filter_free(filter); spprintf(p->error, 0, "unable to seek to start of file \"%s\" to zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; @@ -1122,13 +1086,13 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ php_stream_close(entry->cfp); entry->cfp = NULL; } else { - if (FAILURE == phar_open_entry_fp(entry, p->error, 0)) { + if (FAILURE == phar_open_entry_fp(entry, p->error, false)) { return ZEND_HASH_APPLY_STOP; } - phar_seek_efp(entry, 0, SEEK_SET, 0, 0); + phar_seek_efp(entry, 0, SEEK_SET, 0, false); - if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(entry, 0), p->filefp, entry->uncompressed_filesize, NULL)) { + if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(entry, false), p->filefp, entry->uncompressed_filesize, NULL)) { spprintf(p->error, 0, "unable to write contents of file \"%s\" in zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } @@ -1145,10 +1109,10 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ /* open file pointers refer to this fp, do not free the stream */ switch (entry->fp_type) { case PHAR_FP: - p->free_fp = 0; + p->free_fp = false; break; case PHAR_UFP: - p->free_ufp = 0; + p->free_ufp = false; default: break; } @@ -1181,7 +1145,7 @@ static int phar_zip_changed_apply(zval *zv, void *arg) /* {{{ */ } /* }}} */ -static int phar_zip_applysignature(phar_archive_data *phar, struct _phar_zip_pass *pass) /* {{{ */ +static zend_result phar_zip_applysignature(phar_archive_data *phar, struct _phar_zip_pass *pass) /* {{{ */ { /* add signature for executable tars or tars explicitly set with setSignatureAlgorithm */ if (!phar->is_data || phar->sig_flags) { @@ -1207,11 +1171,11 @@ static int phar_zip_applysignature(phar_archive_data *phar, struct _phar_zip_pas php_stream_write(newfile, ZSTR_VAL(phar->metadata_tracker.str), ZSTR_LEN(phar->metadata_tracker.str)); } - if (FAILURE == phar_create_signature(phar, newfile, &signature, &signature_length, pass->error)) { - if (pass->error) { - char *save = *(pass->error); - spprintf(pass->error, 0, "phar error: unable to write signature to zip-based phar: %s", save); - efree(save); + char *signature_error = NULL; + if (FAILURE == phar_create_signature(phar, newfile, &signature, &signature_length, &signature_error)) { + if (signature_error) { + spprintf(pass->error, 0, "phar error: unable to write signature to zip-based phar: %s", signature_error); + efree(signature_error); } php_stream_close(newfile); @@ -1222,7 +1186,9 @@ static int phar_zip_applysignature(phar_archive_data *phar, struct _phar_zip_pas entry.fp_type = PHAR_MOD; entry.is_modified = 1; if (entry.fp == NULL) { + efree(signature); spprintf(pass->error, 0, "phar error: unable to create temporary file for signature"); + php_stream_close(newfile); return FAILURE; } @@ -1258,7 +1224,7 @@ static int phar_zip_applysignature(phar_archive_data *phar, struct _phar_zip_pas } /* }}} */ -void phar_zip_flush(phar_archive_data *phar, zend_string *user_stub, bool is_default_stub, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_zip_flush(phar_archive_data *phar, zend_string *user_stub, bool is_default_stub, char **error) /* {{{ */ { static const char newstub[] = "is_persistent) { - if (error) { - spprintf(error, 0, "internal error: attempt to flush cached zip-based phar \"%s\"", phar->fname); - } - return; + spprintf(error, 0, "internal error: attempt to flush cached zip-based phar \"%s\"", phar->fname); + return EOF; } if (phar->is_data) { @@ -1294,14 +1255,13 @@ void phar_zip_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def if (!phar->is_temporary_alias && phar->alias_len) { entry.fp = php_stream_fopen_tmpfile(); if (entry.fp == NULL) { - spprintf(error, 0, "phar error: unable to create temporary file"); - return; + *error = estrdup("phar error: unable to create temporary file"); + return EOF; } if (phar->alias_len != php_stream_write(entry.fp, phar->alias, phar->alias_len)) { - if (error) { - spprintf(error, 0, "unable to set alias in zip-based phar \"%s\"", phar->fname); - } - return; + php_stream_close(entry.fp); + spprintf(error, 0, "unable to set alias in zip-based phar \"%s\"", phar->fname); + return EOF; } entry.uncompressed_filesize = entry.compressed_filesize = phar->alias_len; @@ -1315,7 +1275,7 @@ void phar_zip_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def /* register alias */ if (phar->alias_len) { if (FAILURE == phar_get_archive(&phar, phar->fname, phar->fname_len, phar->alias, phar->alias_len, error)) { - return; + return EOF; } } @@ -1324,10 +1284,8 @@ void phar_zip_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def char *pos = php_stristr(ZSTR_VAL(user_stub), halt_stub, ZSTR_LEN(user_stub), strlen(halt_stub)); if (pos == NULL) { - if (error) { - spprintf(error, 0, "illegal stub for zip-based phar \"%s\"", phar->fname); - } - return; + spprintf(error, 0, "illegal stub for zip-based phar \"%s\"", phar->fname); + return EOF; } size_t len = pos - ZSTR_VAL(user_stub) + strlen(halt_stub); @@ -1336,8 +1294,8 @@ void phar_zip_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"); - return; + *error = estrdup("phar error: unable to create temporary file"); + return EOF; } entry.uncompressed_filesize = len + end_sequence_len; @@ -1345,11 +1303,9 @@ void phar_zip_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def len != php_stream_write(entry.fp, ZSTR_VAL(user_stub), len) || end_sequence_len != php_stream_write(entry.fp, end_sequence, end_sequence_len) ) { - if (error) { - spprintf(error, 0, "unable to create stub from string in new zip-based phar \"%s\"", phar->fname); - } + spprintf(error, 0, "unable to create stub from string in new zip-based phar \"%s\"", phar->fname); php_stream_close(entry.fp); - return; + return EOF; } entry.filename = ZSTR_INIT_LITERAL(".phar/stub.php", false); @@ -1359,15 +1315,13 @@ void phar_zip_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def /* Either this is a brand new phar (add the stub), or the default stub is required (overwrite the stub) */ entry.fp = php_stream_fopen_tmpfile(); if (entry.fp == NULL) { - spprintf(error, 0, "phar error: unable to create temporary file"); - return; + *error = estrdup("phar error: unable to create temporary file"); + return EOF; } if (sizeof(newstub)-1 != php_stream_write(entry.fp, newstub, sizeof(newstub)-1)) { php_stream_close(entry.fp); - if (error) { - spprintf(error, 0, "unable to %s stub in%szip-based phar \"%s\", failed", user_stub ? "overwrite" : "create", user_stub ? " " : " new ", phar->fname); - } - return; + spprintf(error, 0, "unable to %s stub in%szip-based phar \"%s\", failed", user_stub ? "overwrite" : "create", user_stub ? " " : " new ", phar->fname); + return EOF; } entry.uncompressed_filesize = entry.compressed_filesize = sizeof(newstub) - 1; @@ -1378,10 +1332,8 @@ void phar_zip_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def if (NULL == zend_hash_add_mem(&phar->manifest, entry.filename, &entry, sizeof(phar_entry_info))) { php_stream_close(entry.fp); zend_string_efree(entry.filename); - if (error) { - spprintf(error, 0, "unable to create stub in zip-based phar \"%s\"", phar->fname); - } - return; + spprintf(error, 0, "unable to create stub in zip-based phar \"%s\"", phar->fname); + return EOF; } } else { php_stream_close(entry.fp); @@ -1402,6 +1354,9 @@ void phar_zip_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def } /* save modified files to the zip */ + char *pass_error = NULL; + struct _phar_zip_pass pass; + pass.error = &pass_error; pass.old = oldfile; pass.filefp = php_stream_fopen_tmpfile(); @@ -1410,19 +1365,18 @@ void phar_zip_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def if (must_close_old_file) { php_stream_close(oldfile); } - if (error) { - spprintf(error, 4096, "phar zip flush of \"%s\" failed: unable to open temporary file", phar->fname); - } - return; + spprintf(error, 4096, "phar zip flush of \"%s\" failed: unable to open temporary file", phar->fname); + return EOF; } pass.centralfp = php_stream_fopen_tmpfile(); if (!pass.centralfp) { + php_stream_close(pass.filefp); goto fperror; } - pass.free_fp = pass.free_ufp = 1; + pass.free_fp = pass.free_ufp = true; memset(&eocd, 0, sizeof(eocd)); memcpy(eocd.signature, "PK\5\6", 4); @@ -1439,23 +1393,18 @@ void phar_zip_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def zend_hash_apply_with_argument(&phar->manifest, phar_zip_changed_apply, (void *) &pass); phar_metadata_tracker_try_ensure_has_serialized_data(&phar->metadata_tracker, phar->is_persistent); - if (temperr) { - if (error) { - spprintf(error, 4096, "phar zip flush of \"%s\" failed: %s", phar->fname, temperr); - } - efree(temperr); -temperror: + if (pass_error + || FAILURE == phar_zip_applysignature(phar, &pass)) { + spprintf(error, 4096, "phar zip flush of \"%s\" failed: %s", phar->fname, pass_error); + efree(pass_error); +nopasserror: php_stream_close(pass.centralfp); nocentralerror: php_stream_close(pass.filefp); if (must_close_old_file) { php_stream_close(oldfile); } - return; - } - - if (FAILURE == phar_zip_applysignature(phar, &pass)) { - goto temperror; + return EOF; } /* save zip */ @@ -1467,12 +1416,10 @@ void phar_zip_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def { size_t clen; - int ret = php_stream_copy_to_stream_ex(pass.centralfp, pass.filefp, PHP_STREAM_COPY_ALL, &clen); + zend_result ret = php_stream_copy_to_stream_ex(pass.centralfp, pass.filefp, PHP_STREAM_COPY_ALL, &clen); if (SUCCESS != ret || clen != cdir_size) { - if (error) { - spprintf(error, 4096, "phar zip flush of \"%s\" failed: unable to write central-directory", phar->fname); - } - goto temperror; + spprintf(error, 4096, "phar zip flush of \"%s\" failed: unable to write central-directory", phar->fname); + goto nopasserror; } } @@ -1484,23 +1431,17 @@ void phar_zip_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def PHAR_SET_16(eocd.comment_len, ZSTR_LEN(phar->metadata_tracker.str)); if (sizeof(eocd) != php_stream_write(pass.filefp, (char *)&eocd, sizeof(eocd))) { - if (error) { - spprintf(error, 4096, "phar zip flush of \"%s\" failed: unable to write end of central-directory", phar->fname); - } + spprintf(error, 4096, "phar zip flush of \"%s\" failed: unable to write end of central-directory", phar->fname); goto nocentralerror; } if (ZSTR_LEN(phar->metadata_tracker.str) != php_stream_write(pass.filefp, ZSTR_VAL(phar->metadata_tracker.str), ZSTR_LEN(phar->metadata_tracker.str))) { - if (error) { - spprintf(error, 4096, "phar zip flush of \"%s\" failed: unable to write metadata to zip comment", phar->fname); - } + spprintf(error, 4096, "phar zip flush of \"%s\" failed: unable to write metadata to zip comment", phar->fname); goto nocentralerror; } } else { if (sizeof(eocd) != php_stream_write(pass.filefp, (char *)&eocd, sizeof(eocd))) { - if (error) { - spprintf(error, 4096, "phar zip flush of \"%s\" failed: unable to write end of central-directory", phar->fname); - } + spprintf(error, 4096, "phar zip flush of \"%s\" failed: unable to write end of central-directory", phar->fname); goto nocentralerror; } } @@ -1529,10 +1470,8 @@ void phar_zip_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def php_stream_close(oldfile); } phar->fp = pass.filefp; - if (error) { - spprintf(error, 4096, "unable to open new phar \"%s\" for writing", phar->fname); - } - return; + spprintf(error, 4096, "unable to open new phar \"%s\" for writing", phar->fname); + return EOF; } php_stream_rewind(pass.filefp); php_stream_copy_to_stream_ex(pass.filefp, phar->fp, PHP_STREAM_COPY_ALL, NULL); @@ -1543,5 +1482,6 @@ void phar_zip_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def if (must_close_old_file) { php_stream_close(oldfile); } + return 0; } /* }}} */ diff --git a/ext/posix/config.m4 b/ext/posix/config.m4 index 8960979065f98..8655463569536 100644 --- a/ext/posix/config.m4 +++ b/ext/posix/config.m4 @@ -44,7 +44,8 @@ if test "$PHP_POSIX" = "yes"; then dnl Skip pathconf and fpathconf check on musl libc due to limited implementation dnl (first argument is not validated and has different error). - AS_IF([command -v ldd >/dev/null && ldd --version 2>&1 | grep ^musl >/dev/null 2>&1], + PHP_C_STANDARD_LIBRARY + AS_VAR_IF([php_cv_c_standard_library], [musl], [], [AC_CHECK_FUNCS([pathconf fpathconf])]) diff --git a/ext/posix/posix.c b/ext/posix/posix.c index 512776d3ced20..b7acf8c751270 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; @@ -678,7 +699,8 @@ static void php_posix_group_to_array(struct group *g, zval *array_group) /* {{{ for (count = 0;; count++) { /* gr_mem entries may be misaligned on macos. */ char *gr_mem; - memcpy(&gr_mem, &g->gr_mem[count], sizeof(char *)); + char *entry = (char *)g->gr_mem + (count * sizeof (char *)); + memcpy(&gr_mem, entry, sizeof(char *)); if (!gr_mem) { break; } @@ -1183,6 +1205,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/engine_mt19937.c b/ext/random/engine_mt19937.c index 7c9d1741d81f1..f2cb2fd7e9bcb 100644 --- a/ext/random/engine_mt19937.c +++ b/ext/random/engine_mt19937.c @@ -324,17 +324,16 @@ PHP_METHOD(Random_Engine_Mt19937, __serialize) array_init(return_value); /* members */ - ZVAL_ARR(&t, zend_std_get_properties(&engine->std)); - Z_TRY_ADDREF(t); + ZVAL_EMPTY_ARRAY(&t); zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &t); /* state */ array_init(&t); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &t); if (!engine->engine.algo->serialize(engine->engine.state, Z_ARRVAL(t))) { zend_throw_exception(NULL, "Engine serialize failed", 0); RETURN_THROWS(); } - zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &t); } /* }}} */ 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_arginfo.h b/ext/random/random_arginfo.h index 0cda5467deba7..94c024b122369 100644 --- a/ext/random/random_arginfo.h +++ b/ext/random/random_arginfo.h @@ -232,19 +232,15 @@ static void register_random_symbols(int module_number) 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_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); - zval attribute_Deprecated_const_MT_RAND_PHP_0_arg1; 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_arg1, attribute_Deprecated_const_MT_RAND_PHP_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_MT_RAND_PHP_0->args[1].value, &attribute_Deprecated_const_MT_RAND_PHP_0_arg1); + 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); } @@ -322,10 +318,10 @@ static zend_class_entry *register_class_Random_Randomizer(void) zval property_engine_default_value; ZVAL_UNDEF(&property_engine_default_value); - zend_string *property_engine_name = zend_string_init("engine", sizeof("engine") - 1, 1); + zend_string *property_engine_name = zend_string_init("engine", sizeof("engine") - 1, true); zend_string *property_engine_class_Random_Engine = zend_string_init("Random\\Engine", sizeof("Random\\Engine")-1, 1); zend_declare_typed_property(class_entry, property_engine_name, &property_engine_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_engine_class_Random_Engine, 0, 0)); - zend_string_release(property_engine_name); + zend_string_release_ex(property_engine_name, true); return class_entry; } diff --git a/ext/random/randomizer.c b/ext/random/randomizer.c index fc3c93fc2b053..2daf98661099a 100644 --- a/ext/random/randomizer.c +++ b/ext/random/randomizer.c @@ -509,8 +509,7 @@ PHP_METHOD(Random_Randomizer, __serialize) ZEND_PARSE_PARAMETERS_NONE(); array_init(return_value); - ZVAL_ARR(&t, zend_std_get_properties(&randomizer->std)); - Z_TRY_ADDREF(t); + ZVAL_ARR(&t, zend_array_dup(zend_std_get_properties(&randomizer->std))); zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &t); } /* }}} */ 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-- __serialize()); + +?> +--EXPECT-- +array(1) { + [0]=> + array(1) { + ["engine"]=> + object(Random\Engine\Secure)#2 (0) { + } + } +} diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 74dcd772dc716..64e79651913fb 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,12 +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) { - return fptr->type == ZEND_INTERNAL_FUNCTION - && !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO); } /* {{{ _parameter_string */ @@ -790,17 +784,15 @@ static void _parameter_string(smart_str *str, zend_function *fptr, struct _zend_ if (ZEND_ARG_IS_VARIADIC(arg_info)) { smart_str_appends(str, "..."); } - smart_str_append_printf(str, "$%s", has_internal_arg_info(fptr) - ? ((zend_internal_arg_info*)arg_info)->name : ZSTR_VAL(arg_info->name)); + smart_str_append_printf(str, "$%s", ZSTR_VAL(arg_info->name)); if (!required && !ZEND_ARG_IS_VARIADIC(arg_info)) { if (fptr->type == ZEND_INTERNAL_FUNCTION) { smart_str_appends(str, " = "); /* TODO: We don't have a way to fetch the default value for an internal function * with userland arg info. */ - if (has_internal_arg_info(fptr) - && ((zend_internal_arg_info*)arg_info)->default_value) { - smart_str_appends(str, ((zend_internal_arg_info*)arg_info)->default_value); + if (arg_info->default_value) { + smart_str_append(str, arg_info->default_value); } else { smart_str_appends(str, ""); } @@ -808,9 +800,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 +1030,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 +1048,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 +1266,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); @@ -1414,13 +1425,7 @@ static void reflection_extension_factory_ex(zval *object, zend_module_entry *mod static void reflection_extension_factory(zval *object, const char *name_str) { size_t name_len = strlen(name_str); - zend_string *lcname; - struct _zend_module_entry *module; - - lcname = zend_string_alloc(name_len, 0); - zend_str_tolower_copy(ZSTR_VAL(lcname), name_str, name_len); - module = zend_hash_find_ptr(&module_registry, lcname); - zend_string_efree(lcname); + struct _zend_module_entry *module = zend_hash_str_find_ptr_lc(&module_registry, name_str, name_len); if (!module) { return; } @@ -1451,11 +1456,7 @@ static void reflection_parameter_factory(zend_function *fptr, zval *closure_obje } prop_name = reflection_prop_name(object); - if (has_internal_arg_info(fptr)) { - ZVAL_STRING(prop_name, ((zend_internal_arg_info*)arg_info)->name); - } else { - ZVAL_STR_COPY(prop_name, arg_info->name); - } + ZVAL_STR_COPY(prop_name, arg_info->name); } /* }}} */ @@ -1635,14 +1636,13 @@ 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. */ return FAILURE; } - return zend_get_default_from_internal_arg_info( - result, (zend_internal_arg_info *) param->arg_info); + return zend_get_default_from_internal_arg_info(result, param->arg_info); } else { zval *default_value = get_default_from_recv((zend_op_array *) param->fptr, param->offset); if (!default_value) { @@ -1695,6 +1695,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)); @@ -2114,16 +2123,10 @@ ZEND_METHOD(ReflectionFunction, invoke) zend_call_known_fcc(&fcc, &retval, num_args, params, named_params); - if (Z_TYPE(retval) == IS_UNDEF && !EG(exception)) { - zend_throw_exception_ex(reflection_exception_ptr, 0, - "Invocation of function %s() failed", ZSTR_VAL(fptr->common.function_name)); - RETURN_THROWS(); - } - if (Z_ISREF(retval)) { zend_unwrap_reference(&retval); } - ZVAL_COPY_VALUE(return_value, &retval); + RETURN_COPY_VALUE(&retval); } /* }}} */ @@ -2153,16 +2156,10 @@ ZEND_METHOD(ReflectionFunction, invokeArgs) zend_call_known_fcc(&fcc, &retval, /* num_params */ 0, /* params */ NULL, params); - if (Z_TYPE(retval) == IS_UNDEF && !EG(exception)) { - zend_throw_exception_ex(reflection_exception_ptr, 0, - "Invocation of function %s() failed", ZSTR_VAL(fptr->common.function_name)); - RETURN_THROWS(); - } - if (Z_ISREF(retval)) { zend_unwrap_reference(&retval); } - ZVAL_COPY_VALUE(return_value, &retval); + RETURN_COPY_VALUE(&retval); } /* }}} */ @@ -2581,22 +2578,11 @@ ZEND_METHOD(ReflectionParameter, __construct) uint32_t i; position = -1; - if (has_internal_arg_info(fptr)) { - for (i = 0; i < num_args; i++) { - if (arg_info[i].name) { - if (strcmp(((zend_internal_arg_info*)arg_info)[i].name, ZSTR_VAL(arg_name)) == 0) { - position = i; - break; - } - } - } - } else { - for (i = 0; i < num_args; i++) { - if (arg_info[i].name) { - if (zend_string_equals(arg_name, arg_info[i].name)) { - position = i; - break; - } + for (i = 0; i < num_args; i++) { + if (arg_info[i].name) { + if (zend_string_equals(arg_name, arg_info[i].name)) { + position = i; + break; } } } @@ -2637,11 +2623,7 @@ ZEND_METHOD(ReflectionParameter, __construct) prop_name = reflection_prop_name(object); zval_ptr_dtor(prop_name); - if (has_internal_arg_info(fptr)) { - ZVAL_STRING(prop_name, ((zend_internal_arg_info*)arg_info)[position].name); - } else { - ZVAL_STR_COPY(prop_name, arg_info[position].name); - } + ZVAL_STR_COPY(prop_name, arg_info[position].name); return; failure: @@ -2680,11 +2662,7 @@ ZEND_METHOD(ReflectionParameter, getName) ZEND_PARSE_PARAMETERS_NONE(); GET_REFLECTION_OBJECT_PTR(param); - if (has_internal_arg_info(param->fptr)) { - RETURN_STRING(((zend_internal_arg_info *) param->arg_info)->name); - } else { - RETURN_STR_COPY(param->arg_info->name); - } + RETURN_STR_COPY(param->arg_info->name); } /* }}} */ @@ -2805,7 +2783,7 @@ ZEND_METHOD(ReflectionParameter, getType) if (!ZEND_TYPE_IS_SET(param->arg_info->type)) { RETURN_NULL(); } - reflection_type_factory(param->arg_info->type, return_value, 1); + reflection_type_factory(param->arg_info->type, return_value, true); } /* }}} */ @@ -2938,8 +2916,7 @@ ZEND_METHOD(ReflectionParameter, isDefaultValueAvailable) GET_REFLECTION_OBJECT_PTR(param); if (param->fptr->type == ZEND_INTERNAL_FUNCTION) { - RETURN_BOOL(!(param->fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO) - && ((zend_internal_arg_info*) (param->arg_info))->default_value); + RETURN_BOOL(param->arg_info->default_value); } else { zval *default_value = get_default_from_recv((zend_op_array *)param->fptr, param->offset); RETURN_BOOL(default_value != NULL); @@ -3150,7 +3127,7 @@ static void append_type(zval *return_value, zend_type type) { ZEND_TYPE_FULL_MASK(type) &= ~_ZEND_TYPE_ITERABLE_BIT; } - reflection_type_factory(type, &reflection_type, 0); + reflection_type_factory(type, &reflection_type, false); zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &reflection_type); } @@ -3469,16 +3446,10 @@ static void reflection_method_invoke(INTERNAL_FUNCTION_PARAMETERS, int variadic) callback = _copy_function(mptr); zend_call_known_function(callback, (object ? Z_OBJ_P(object) : NULL), intern->ce, &retval, argc, params, named_params); - if (Z_TYPE(retval) == IS_UNDEF && !EG(exception)) { - zend_throw_exception_ex(reflection_exception_ptr, 0, - "Invocation of method %s::%s() failed", ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name)); - RETURN_THROWS(); - } - if (Z_ISREF(retval)) { zend_unwrap_reference(&retval); } - ZVAL_COPY_VALUE(return_value, &retval); + RETURN_COPY_VALUE(&retval); } /* }}} */ @@ -3652,7 +3623,7 @@ ZEND_METHOD(ReflectionFunctionAbstract, getReturnType) RETURN_NULL(); } - reflection_type_factory(fptr->common.arg_info[-1].type, return_value, 1); + reflection_type_factory(fptr->common.arg_info[-1].type, return_value, true); } /* }}} */ @@ -3684,7 +3655,7 @@ ZEND_METHOD(ReflectionFunctionAbstract, getTentativeReturnType) RETURN_NULL(); } - reflection_type_factory(fptr->common.arg_info[-1].type, return_value, 1); + reflection_type_factory(fptr->common.arg_info[-1].type, return_value, true); } /* }}} */ @@ -3887,7 +3858,7 @@ ZEND_METHOD(ReflectionClassConstant, getType) RETURN_NULL(); } - reflection_type_factory(ref->type, return_value, 1); + reflection_type_factory(ref->type, return_value, true); } /* Returns whether class constant has a type */ @@ -4287,8 +4258,8 @@ ZEND_METHOD(ReflectionClass, getDefaultProperties) if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) { RETURN_THROWS(); } - add_class_vars(ce, 1, return_value); - add_class_vars(ce, 0, return_value); + add_class_vars(ce, true, return_value); + add_class_vars(ce, false, return_value); } /* }}} */ @@ -4505,16 +4476,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; } /* }}} */ @@ -4525,7 +4496,7 @@ ZEND_METHOD(ReflectionClass, getMethods) zend_class_entry *ce; zend_function *mptr; zend_long filter; - bool filter_is_null = 1; + bool filter_is_null = true; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &filter, &filter_is_null) == FAILURE) { RETURN_THROWS(); @@ -4703,7 +4674,7 @@ ZEND_METHOD(ReflectionClass, getProperties) zend_string *key; zend_property_info *prop_info; zend_long filter; - bool filter_is_null = 1; + bool filter_is_null = true; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &filter, &filter_is_null) == FAILURE) { RETURN_THROWS(); @@ -4759,7 +4730,7 @@ ZEND_METHOD(ReflectionClass, getConstants) zend_class_constant *constant; zval val; zend_long filter; - bool filter_is_null = 1; + bool filter_is_null = true; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &filter, &filter_is_null) == FAILURE) { RETURN_THROWS(); @@ -4793,7 +4764,7 @@ ZEND_METHOD(ReflectionClass, getReflectionConstants) zend_string *name; zend_class_constant *constant; zend_long filter; - bool filter_is_null = 1; + bool filter_is_null = true; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &filter, &filter_is_null) == FAILURE) { RETURN_THROWS(); @@ -4837,6 +4808,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); @@ -5557,7 +5533,8 @@ ZEND_METHOD(ReflectionClass, isIterable) RETURN_FALSE; } - RETURN_BOOL(ce->get_iterator || instanceof_function(ce, zend_ce_traversable)); + RETURN_BOOL((ce->get_iterator && ce->get_iterator != zend_hooked_object_get_iterator) + || instanceof_function(ce, zend_ce_traversable)); } /* }}} */ @@ -5753,6 +5730,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; @@ -6381,7 +6373,7 @@ ZEND_METHOD(ReflectionProperty, getType) RETURN_NULL(); } - reflection_type_factory(ref->prop->type, return_value, 1); + reflection_type_factory(ref->prop->type, return_value, true); } /* }}} */ @@ -6403,7 +6395,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, true); return; } @@ -6413,7 +6405,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, true); return; } @@ -6421,7 +6413,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, true); } /* {{{ Returns whether property has a type */ @@ -6476,11 +6468,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; } @@ -6602,28 +6605,21 @@ ZEND_METHOD(ReflectionProperty, isFinal) ZEND_METHOD(ReflectionExtension, __construct) { zval *object; - char *lcname; reflection_object *intern; zend_module_entry *module; - char *name_str; - size_t name_len; - ALLOCA_FLAG(use_heap) + zend_string *name_str; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name_str, &name_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name_str) == FAILURE) { RETURN_THROWS(); } object = ZEND_THIS; intern = Z_REFLECTION_P(object); - lcname = do_alloca(name_len + 1, use_heap); - zend_str_tolower_copy(lcname, name_str, name_len); - if ((module = zend_hash_str_find_ptr(&module_registry, lcname, name_len)) == NULL) { - free_alloca(lcname, use_heap); + if ((module = zend_hash_find_ptr_lc(&module_registry, name_str)) == NULL) { zend_throw_exception_ex(reflection_exception_ptr, 0, - "Extension \"%s\" does not exist", name_str); + "Extension \"%s\" does not exist", ZSTR_VAL(name_str)); RETURN_THROWS(); } - free_alloca(lcname, use_heap); zval *prop_name = reflection_prop_name(object); zval_ptr_dtor(prop_name); ZVAL_STRING(prop_name, module->name); @@ -6790,7 +6786,7 @@ ZEND_METHOD(ReflectionExtension, getClasses) array_init(return_value); ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) { - add_extension_class(ce, key, return_value, module, 1); + add_extension_class(ce, key, return_value, module, true); } ZEND_HASH_FOREACH_END(); } /* }}} */ @@ -6808,7 +6804,7 @@ ZEND_METHOD(ReflectionExtension, getClassNames) array_init(return_value); ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) { - add_extension_class(ce, key, return_value, module, 0); + add_extension_class(ce, key, return_value, module, false); } ZEND_HASH_FOREACH_END(); } /* }}} */ @@ -7051,7 +7047,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 @@ -7116,7 +7112,7 @@ ZEND_METHOD(ReflectionReference, getId) RETURN_THROWS(); } - REFLECTION_G(key_initialized) = 1; + REFLECTION_G(key_initialized) = true; } /* SHA1(ref || key) to avoid directly exposing memory addresses. */ @@ -7166,10 +7162,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"); } @@ -7275,26 +7268,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(); + } + + /* 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); - 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)); @@ -7419,7 +7447,7 @@ ZEND_METHOD(ReflectionEnum, getBackingType) RETURN_NULL(); } else { zend_type type = ZEND_TYPE_INIT_CODE(ce->enum_backing_type, 0, 0); - reflection_type_factory(type, return_value, 0); + reflection_type_factory(type, return_value, false); } } @@ -7942,7 +7970,7 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */ reflection_property_hook_type_ptr = register_class_PropertyHookType(); - REFLECTION_G(key_initialized) = 0; + REFLECTION_G(key_initialized) = false; return SUCCESS; } /* }}} */ diff --git a/ext/reflection/php_reflection.stub.php b/ext/reflection/php_reflection.stub.php index 63518b446ad86..91c70d6ffdb1a 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 since PHP 8.1")] 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 since PHP 8.1")] public function setAccessible(bool $accessible): void {} /** @tentative-return-type */ @@ -900,7 +904,7 @@ public function getTrace(int $options = DEBUG_BACKTRACE_PROVIDE_OBJECT): array { * @strict-properties * @not-serializable */ -final class ReflectionConstant implements Reflector +class ReflectionConstant implements Reflector { public string $name; diff --git a/ext/reflection/php_reflection_arginfo.h b/ext/reflection/php_reflection_arginfo.h index b1d310c2a0ca3..62275423b3caf 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: fd645a0b0db39d94ca25b39ffe64d7f05bad6bea */ 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) @@ -1417,18 +1421,16 @@ static zend_class_entry *register_class_ReflectionFunction(zend_class_entry *cla zval const_IS_DEPRECATED_value; ZVAL_LONG(&const_IS_DEPRECATED_value, ZEND_ACC_DEPRECATED); - zend_string *const_IS_DEPRECATED_name = zend_string_init_interned("IS_DEPRECATED", sizeof("IS_DEPRECATED") - 1, 1); + zend_string *const_IS_DEPRECATED_name = zend_string_init_interned("IS_DEPRECATED", sizeof("IS_DEPRECATED") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_DEPRECATED_name, &const_IS_DEPRECATED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_DEPRECATED_name); + zend_string_release_ex(const_IS_DEPRECATED_name, true); 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_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; @@ -1453,44 +1455,52 @@ static zend_class_entry *register_class_ReflectionMethod(zend_class_entry *class zval const_IS_STATIC_value; ZVAL_LONG(&const_IS_STATIC_value, ZEND_ACC_STATIC); - zend_string *const_IS_STATIC_name = zend_string_init_interned("IS_STATIC", sizeof("IS_STATIC") - 1, 1); + zend_string *const_IS_STATIC_name = zend_string_init_interned("IS_STATIC", sizeof("IS_STATIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_STATIC_name, &const_IS_STATIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_STATIC_name); + zend_string_release_ex(const_IS_STATIC_name, true); zval const_IS_PUBLIC_value; ZVAL_LONG(&const_IS_PUBLIC_value, ZEND_ACC_PUBLIC); - zend_string *const_IS_PUBLIC_name = zend_string_init_interned("IS_PUBLIC", sizeof("IS_PUBLIC") - 1, 1); + zend_string *const_IS_PUBLIC_name = zend_string_init_interned("IS_PUBLIC", sizeof("IS_PUBLIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_PUBLIC_name, &const_IS_PUBLIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_PUBLIC_name); + zend_string_release_ex(const_IS_PUBLIC_name, true); zval const_IS_PROTECTED_value; ZVAL_LONG(&const_IS_PROTECTED_value, ZEND_ACC_PROTECTED); - zend_string *const_IS_PROTECTED_name = zend_string_init_interned("IS_PROTECTED", sizeof("IS_PROTECTED") - 1, 1); + zend_string *const_IS_PROTECTED_name = zend_string_init_interned("IS_PROTECTED", sizeof("IS_PROTECTED") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_PROTECTED_name, &const_IS_PROTECTED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_PROTECTED_name); + zend_string_release_ex(const_IS_PROTECTED_name, true); zval const_IS_PRIVATE_value; ZVAL_LONG(&const_IS_PRIVATE_value, ZEND_ACC_PRIVATE); - zend_string *const_IS_PRIVATE_name = zend_string_init_interned("IS_PRIVATE", sizeof("IS_PRIVATE") - 1, 1); + zend_string *const_IS_PRIVATE_name = zend_string_init_interned("IS_PRIVATE", sizeof("IS_PRIVATE") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_PRIVATE_name, &const_IS_PRIVATE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_PRIVATE_name); + zend_string_release_ex(const_IS_PRIVATE_name, true); zval const_IS_ABSTRACT_value; ZVAL_LONG(&const_IS_ABSTRACT_value, ZEND_ACC_ABSTRACT); - zend_string *const_IS_ABSTRACT_name = zend_string_init_interned("IS_ABSTRACT", sizeof("IS_ABSTRACT") - 1, 1); + zend_string *const_IS_ABSTRACT_name = zend_string_init_interned("IS_ABSTRACT", sizeof("IS_ABSTRACT") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_ABSTRACT_name, &const_IS_ABSTRACT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_ABSTRACT_name); + zend_string_release_ex(const_IS_ABSTRACT_name, true); zval const_IS_FINAL_value; ZVAL_LONG(&const_IS_FINAL_value, ZEND_ACC_FINAL); - zend_string *const_IS_FINAL_name = zend_string_init_interned("IS_FINAL", sizeof("IS_FINAL") - 1, 1); + zend_string *const_IS_FINAL_name = zend_string_init_interned("IS_FINAL", sizeof("IS_FINAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_FINAL_name, &const_IS_FINAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_FINAL_name); + zend_string_release_ex(const_IS_FINAL_name, true); zval property_class_default_value; 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 since PHP 8.1", strlen("as it has no effect since PHP 8.1"), 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; } @@ -1504,39 +1514,39 @@ static zend_class_entry *register_class_ReflectionClass(zend_class_entry *class_ zval const_IS_IMPLICIT_ABSTRACT_value; ZVAL_LONG(&const_IS_IMPLICIT_ABSTRACT_value, ZEND_ACC_IMPLICIT_ABSTRACT_CLASS); - zend_string *const_IS_IMPLICIT_ABSTRACT_name = zend_string_init_interned("IS_IMPLICIT_ABSTRACT", sizeof("IS_IMPLICIT_ABSTRACT") - 1, 1); + zend_string *const_IS_IMPLICIT_ABSTRACT_name = zend_string_init_interned("IS_IMPLICIT_ABSTRACT", sizeof("IS_IMPLICIT_ABSTRACT") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_IMPLICIT_ABSTRACT_name, &const_IS_IMPLICIT_ABSTRACT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_IMPLICIT_ABSTRACT_name); + zend_string_release_ex(const_IS_IMPLICIT_ABSTRACT_name, true); zval const_IS_EXPLICIT_ABSTRACT_value; ZVAL_LONG(&const_IS_EXPLICIT_ABSTRACT_value, ZEND_ACC_EXPLICIT_ABSTRACT_CLASS); - zend_string *const_IS_EXPLICIT_ABSTRACT_name = zend_string_init_interned("IS_EXPLICIT_ABSTRACT", sizeof("IS_EXPLICIT_ABSTRACT") - 1, 1); + zend_string *const_IS_EXPLICIT_ABSTRACT_name = zend_string_init_interned("IS_EXPLICIT_ABSTRACT", sizeof("IS_EXPLICIT_ABSTRACT") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_EXPLICIT_ABSTRACT_name, &const_IS_EXPLICIT_ABSTRACT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_EXPLICIT_ABSTRACT_name); + zend_string_release_ex(const_IS_EXPLICIT_ABSTRACT_name, true); zval const_IS_FINAL_value; ZVAL_LONG(&const_IS_FINAL_value, ZEND_ACC_FINAL); - zend_string *const_IS_FINAL_name = zend_string_init_interned("IS_FINAL", sizeof("IS_FINAL") - 1, 1); + zend_string *const_IS_FINAL_name = zend_string_init_interned("IS_FINAL", sizeof("IS_FINAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_FINAL_name, &const_IS_FINAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_FINAL_name); + zend_string_release_ex(const_IS_FINAL_name, true); zval const_IS_READONLY_value; ZVAL_LONG(&const_IS_READONLY_value, ZEND_ACC_READONLY_CLASS); - zend_string *const_IS_READONLY_name = zend_string_init_interned("IS_READONLY", sizeof("IS_READONLY") - 1, 1); + zend_string *const_IS_READONLY_name = zend_string_init_interned("IS_READONLY", sizeof("IS_READONLY") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_READONLY_name, &const_IS_READONLY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_READONLY_name); + zend_string_release_ex(const_IS_READONLY_name, true); zval const_SKIP_INITIALIZATION_ON_SERIALIZE_value; ZVAL_LONG(&const_SKIP_INITIALIZATION_ON_SERIALIZE_value, ZEND_LAZY_OBJECT_SKIP_INITIALIZATION_ON_SERIALIZE); - zend_string *const_SKIP_INITIALIZATION_ON_SERIALIZE_name = zend_string_init_interned("SKIP_INITIALIZATION_ON_SERIALIZE", sizeof("SKIP_INITIALIZATION_ON_SERIALIZE") - 1, 1); + zend_string *const_SKIP_INITIALIZATION_ON_SERIALIZE_name = zend_string_init_interned("SKIP_INITIALIZATION_ON_SERIALIZE", sizeof("SKIP_INITIALIZATION_ON_SERIALIZE") - 1, true); zend_declare_typed_class_constant(class_entry, const_SKIP_INITIALIZATION_ON_SERIALIZE_name, &const_SKIP_INITIALIZATION_ON_SERIALIZE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SKIP_INITIALIZATION_ON_SERIALIZE_name); + zend_string_release_ex(const_SKIP_INITIALIZATION_ON_SERIALIZE_name, true); zval const_SKIP_DESTRUCTOR_value; ZVAL_LONG(&const_SKIP_DESTRUCTOR_value, ZEND_LAZY_OBJECT_SKIP_DESTRUCTOR); - zend_string *const_SKIP_DESTRUCTOR_name = zend_string_init_interned("SKIP_DESTRUCTOR", sizeof("SKIP_DESTRUCTOR") - 1, 1); + zend_string *const_SKIP_DESTRUCTOR_name = zend_string_init_interned("SKIP_DESTRUCTOR", sizeof("SKIP_DESTRUCTOR") - 1, true); zend_declare_typed_class_constant(class_entry, const_SKIP_DESTRUCTOR_name, &const_SKIP_DESTRUCTOR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SKIP_DESTRUCTOR_name); + zend_string_release_ex(const_SKIP_DESTRUCTOR_name, true); zval property_name_default_value; ZVAL_UNDEF(&property_name_default_value); @@ -1582,63 +1592,63 @@ static zend_class_entry *register_class_ReflectionProperty(zend_class_entry *cla zval const_IS_STATIC_value; ZVAL_LONG(&const_IS_STATIC_value, ZEND_ACC_STATIC); - zend_string *const_IS_STATIC_name = zend_string_init_interned("IS_STATIC", sizeof("IS_STATIC") - 1, 1); + zend_string *const_IS_STATIC_name = zend_string_init_interned("IS_STATIC", sizeof("IS_STATIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_STATIC_name, &const_IS_STATIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_STATIC_name); + zend_string_release_ex(const_IS_STATIC_name, true); zval const_IS_READONLY_value; ZVAL_LONG(&const_IS_READONLY_value, ZEND_ACC_READONLY); - zend_string *const_IS_READONLY_name = zend_string_init_interned("IS_READONLY", sizeof("IS_READONLY") - 1, 1); + zend_string *const_IS_READONLY_name = zend_string_init_interned("IS_READONLY", sizeof("IS_READONLY") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_READONLY_name, &const_IS_READONLY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_READONLY_name); + zend_string_release_ex(const_IS_READONLY_name, true); zval const_IS_PUBLIC_value; ZVAL_LONG(&const_IS_PUBLIC_value, ZEND_ACC_PUBLIC); - zend_string *const_IS_PUBLIC_name = zend_string_init_interned("IS_PUBLIC", sizeof("IS_PUBLIC") - 1, 1); + zend_string *const_IS_PUBLIC_name = zend_string_init_interned("IS_PUBLIC", sizeof("IS_PUBLIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_PUBLIC_name, &const_IS_PUBLIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_PUBLIC_name); + zend_string_release_ex(const_IS_PUBLIC_name, true); zval const_IS_PROTECTED_value; ZVAL_LONG(&const_IS_PROTECTED_value, ZEND_ACC_PROTECTED); - zend_string *const_IS_PROTECTED_name = zend_string_init_interned("IS_PROTECTED", sizeof("IS_PROTECTED") - 1, 1); + zend_string *const_IS_PROTECTED_name = zend_string_init_interned("IS_PROTECTED", sizeof("IS_PROTECTED") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_PROTECTED_name, &const_IS_PROTECTED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_PROTECTED_name); + zend_string_release_ex(const_IS_PROTECTED_name, true); zval const_IS_PRIVATE_value; ZVAL_LONG(&const_IS_PRIVATE_value, ZEND_ACC_PRIVATE); - zend_string *const_IS_PRIVATE_name = zend_string_init_interned("IS_PRIVATE", sizeof("IS_PRIVATE") - 1, 1); + zend_string *const_IS_PRIVATE_name = zend_string_init_interned("IS_PRIVATE", sizeof("IS_PRIVATE") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_PRIVATE_name, &const_IS_PRIVATE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_PRIVATE_name); + zend_string_release_ex(const_IS_PRIVATE_name, true); zval const_IS_ABSTRACT_value; ZVAL_LONG(&const_IS_ABSTRACT_value, ZEND_ACC_ABSTRACT); - zend_string *const_IS_ABSTRACT_name = zend_string_init_interned("IS_ABSTRACT", sizeof("IS_ABSTRACT") - 1, 1); + zend_string *const_IS_ABSTRACT_name = zend_string_init_interned("IS_ABSTRACT", sizeof("IS_ABSTRACT") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_ABSTRACT_name, &const_IS_ABSTRACT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_ABSTRACT_name); + zend_string_release_ex(const_IS_ABSTRACT_name, true); zval const_IS_PROTECTED_SET_value; ZVAL_LONG(&const_IS_PROTECTED_SET_value, ZEND_ACC_PROTECTED_SET); - zend_string *const_IS_PROTECTED_SET_name = zend_string_init_interned("IS_PROTECTED_SET", sizeof("IS_PROTECTED_SET") - 1, 1); + zend_string *const_IS_PROTECTED_SET_name = zend_string_init_interned("IS_PROTECTED_SET", sizeof("IS_PROTECTED_SET") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_PROTECTED_SET_name, &const_IS_PROTECTED_SET_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_PROTECTED_SET_name); + zend_string_release_ex(const_IS_PROTECTED_SET_name, true); zval const_IS_PRIVATE_SET_value; ZVAL_LONG(&const_IS_PRIVATE_SET_value, ZEND_ACC_PRIVATE_SET); - zend_string *const_IS_PRIVATE_SET_name = zend_string_init_interned("IS_PRIVATE_SET", sizeof("IS_PRIVATE_SET") - 1, 1); + zend_string *const_IS_PRIVATE_SET_name = zend_string_init_interned("IS_PRIVATE_SET", sizeof("IS_PRIVATE_SET") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_PRIVATE_SET_name, &const_IS_PRIVATE_SET_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_PRIVATE_SET_name); + zend_string_release_ex(const_IS_PRIVATE_SET_name, true); zval const_IS_VIRTUAL_value; ZVAL_LONG(&const_IS_VIRTUAL_value, ZEND_ACC_VIRTUAL); - zend_string *const_IS_VIRTUAL_name = zend_string_init_interned("IS_VIRTUAL", sizeof("IS_VIRTUAL") - 1, 1); + zend_string *const_IS_VIRTUAL_name = zend_string_init_interned("IS_VIRTUAL", sizeof("IS_VIRTUAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_VIRTUAL_name, &const_IS_VIRTUAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_VIRTUAL_name); + zend_string_release_ex(const_IS_VIRTUAL_name, true); zval const_IS_FINAL_value; ZVAL_LONG(&const_IS_FINAL_value, ZEND_ACC_FINAL); - zend_string *const_IS_FINAL_name = zend_string_init_interned("IS_FINAL", sizeof("IS_FINAL") - 1, 1); + zend_string *const_IS_FINAL_name = zend_string_init_interned("IS_FINAL", sizeof("IS_FINAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_FINAL_name, &const_IS_FINAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_FINAL_name); + zend_string_release_ex(const_IS_FINAL_name, true); zval property_name_default_value; ZVAL_UNDEF(&property_name_default_value); @@ -1648,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 since PHP 8.1", strlen("as it has no effect since PHP 8.1"), 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; } @@ -1661,27 +1679,27 @@ static zend_class_entry *register_class_ReflectionClassConstant(zend_class_entry zval const_IS_PUBLIC_value; ZVAL_LONG(&const_IS_PUBLIC_value, ZEND_ACC_PUBLIC); - zend_string *const_IS_PUBLIC_name = zend_string_init_interned("IS_PUBLIC", sizeof("IS_PUBLIC") - 1, 1); + zend_string *const_IS_PUBLIC_name = zend_string_init_interned("IS_PUBLIC", sizeof("IS_PUBLIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_PUBLIC_name, &const_IS_PUBLIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_PUBLIC_name); + zend_string_release_ex(const_IS_PUBLIC_name, true); zval const_IS_PROTECTED_value; ZVAL_LONG(&const_IS_PROTECTED_value, ZEND_ACC_PROTECTED); - zend_string *const_IS_PROTECTED_name = zend_string_init_interned("IS_PROTECTED", sizeof("IS_PROTECTED") - 1, 1); + zend_string *const_IS_PROTECTED_name = zend_string_init_interned("IS_PROTECTED", sizeof("IS_PROTECTED") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_PROTECTED_name, &const_IS_PROTECTED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_PROTECTED_name); + zend_string_release_ex(const_IS_PROTECTED_name, true); zval const_IS_PRIVATE_value; ZVAL_LONG(&const_IS_PRIVATE_value, ZEND_ACC_PRIVATE); - zend_string *const_IS_PRIVATE_name = zend_string_init_interned("IS_PRIVATE", sizeof("IS_PRIVATE") - 1, 1); + zend_string *const_IS_PRIVATE_name = zend_string_init_interned("IS_PRIVATE", sizeof("IS_PRIVATE") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_PRIVATE_name, &const_IS_PRIVATE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_PRIVATE_name); + zend_string_release_ex(const_IS_PRIVATE_name, true); zval const_IS_FINAL_value; ZVAL_LONG(&const_IS_FINAL_value, ZEND_ACC_FINAL); - zend_string *const_IS_FINAL_name = zend_string_init_interned("IS_FINAL", sizeof("IS_FINAL") - 1, 1); + zend_string *const_IS_FINAL_name = zend_string_init_interned("IS_FINAL", sizeof("IS_FINAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_FINAL_name, &const_IS_FINAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_FINAL_name); + zend_string_release_ex(const_IS_FINAL_name, true); zval property_name_default_value; ZVAL_UNDEF(&property_name_default_value); @@ -1710,28 +1728,20 @@ 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_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_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_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; @@ -1828,9 +1838,9 @@ static zend_class_entry *register_class_ReflectionAttribute(zend_class_entry *cl zval const_IS_INSTANCEOF_value; ZVAL_LONG(&const_IS_INSTANCEOF_value, REFLECTION_ATTRIBUTE_IS_INSTANCEOF); - zend_string *const_IS_INSTANCEOF_name = zend_string_init_interned("IS_INSTANCEOF", sizeof("IS_INSTANCEOF") - 1, 1); + zend_string *const_IS_INSTANCEOF_name = zend_string_init_interned("IS_INSTANCEOF", sizeof("IS_INSTANCEOF") - 1, true); zend_declare_typed_class_constant(class_entry, const_IS_INSTANCEOF_name, &const_IS_INSTANCEOF_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IS_INSTANCEOF_name); + zend_string_release_ex(const_IS_INSTANCEOF_name, true); zval property_name_default_value; ZVAL_UNDEF(&property_name_default_value); @@ -1884,7 +1894,7 @@ static zend_class_entry *register_class_ReflectionConstant(zend_class_entry *cla zend_class_entry ce, *class_entry; INIT_CLASS_ENTRY(ce, "ReflectionConstant", class_ReflectionConstant_methods); - class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES|ZEND_ACC_NOT_SERIALIZABLE); + class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_NO_DYNAMIC_PROPERTIES|ZEND_ACC_NOT_SERIALIZABLE); zend_class_implements(class_entry, 1, class_entry_Reflector); zval property_name_default_value; 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_isIterable_gh20217.phpt b/ext/reflection/tests/ReflectionClass_isIterable_gh20217.phpt new file mode 100644 index 0000000000000..f64fc1efcd414 --- /dev/null +++ b/ext/reflection/tests/ReflectionClass_isIterable_gh20217.phpt @@ -0,0 +1,38 @@ +--TEST-- +GH-20217 (ReflectionClass::isIterable() should return false for classes with property hooks) +--FILE-- + 'virtual'; + } +} + +class IterableClassWithPropertyHooks implements IteratorAggregate +{ + public string $name { + get => 'virtual'; + } + + public function getIterator(): Traversable + { + return new ArrayIterator([]); + } +} + +$classes = [ + 'ClassWithPropertyHooks' => false, + 'IterableClassWithPropertyHooks' => true, +]; + +foreach ($classes as $className => $expected) { + $status = (new ReflectionClass($className)->isIterable() === $expected) ? 'PASS' : 'FAIL'; + echo "$className: $status\n"; +} + +?> +--EXPECT-- +ClassWithPropertyHooks: PASS +IterableClassWithPropertyHooks: PASS 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/ReflectionFunction__toString_bound_variables.phpt b/ext/reflection/tests/ReflectionFunction__toString_bound_variables.phpt new file mode 100644 index 0000000000000..142e661361496 --- /dev/null +++ b/ext/reflection/tests/ReflectionFunction__toString_bound_variables.phpt @@ -0,0 +1,32 @@ +--TEST-- +ReflectionFunction::__toString() with bound variables +--FILE-- + 0; + +$rf = new ReflectionFunction($closure_without_bounds); +echo (string) $rf; + +$global = ""; +$closure_with_bounds = function() use($global) { + static $counter = 0; + return $counter++; +}; + +$rf = new ReflectionFunction($closure_with_bounds); +echo (string) $rf; + +?> +--EXPECTF-- +Closure [ function {closure:%s:%d} ] { + @@ %sReflectionFunction__toString_bound_variables.php 3 - 3 +} +Closure [ function {closure:%s:%d} ] { + @@ %sReflectionFunction__toString_bound_variables.php 9 - 12 + + - Bound Variables [2] { + Variable #0 [ $global ] + Variable #1 [ $counter ] + } +} diff --git a/ext/reflection/tests/ReflectionMethod_setAccessible.phpt b/ext/reflection/tests/ReflectionMethod_setAccessible.phpt index 92312528a0419..be720a4044c78 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 since PHP 8.1 in %s on line %d + +Deprecated: Method ReflectionMethod::setAccessible() is deprecated since 8.5, as it has no effect since PHP 8.1 in %s on line %d + +Deprecated: Method ReflectionMethod::setAccessible() is deprecated since 8.5, as it has no effect since PHP 8.1 in %s on line %d + +Deprecated: Method ReflectionMethod::setAccessible() is deprecated since 8.5, as it has no effect since PHP 8.1 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..5ccc1366060b0 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 since PHP 8.1 in %s on line %d + +Deprecated: Method ReflectionProperty::setAccessible() is deprecated since 8.5, as it has no effect since PHP 8.1 in %s on line %d + +Deprecated: Method ReflectionProperty::setAccessible() is deprecated since 8.5, as it has no effect since PHP 8.1 in %s on line %d + +Deprecated: Method ReflectionProperty::setAccessible() is deprecated since 8.5, as it has no effect since PHP 8.1 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 since PHP 8.1 in %s on line %d + +Deprecated: Method ReflectionProperty::setAccessible() is deprecated since 8.5, as it has no effect since PHP 8.1 in %s on line %d + +Deprecated: Method ReflectionProperty::setAccessible() is deprecated since 8.5, as it has no effect since PHP 8.1 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/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/config.w32 b/ext/session/config.w32 index 825bc8b61d291..40f9f78a313ed 100644 --- a/ext/session/config.w32 +++ b/ext/session/config.w32 @@ -3,10 +3,10 @@ ARG_ENABLE("session", "session support", "yes"); if (PHP_SESSION == "yes") { - EXTENSION("session", "mod_user_class.c session.c mod_files.c mod_mm.c mod_user.c", false /* never shared */, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); + EXTENSION("session", "mod_user_class.c session.c mod_files.c mod_user.c", false /* never shared */, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); ADD_EXTENSION_DEP('session', 'date'); // https://bugs.php.net/53141 ADD_EXTENSION_DEP('session', 'spl', true); AC_DEFINE("HAVE_PHP_SESSION", 1, "Define to 1 if the PHP extension 'session' is available."); - PHP_INSTALL_HEADERS("ext/session", "mod_mm.h php_session.h mod_files.h mod_user.h"); + PHP_INSTALL_HEADERS("ext/session", "php_session.h mod_files.h mod_user.h"); } diff --git a/ext/session/mod_mm.c b/ext/session/mod_mm.c index b997a2bdcff54..962e19666a2a3 100644 --- a/ext/session/mod_mm.c +++ b/ext/session/mod_mm.c @@ -207,7 +207,7 @@ static zend_result ps_mm_key_exists(ps_mm *data, const zend_string *key) if (!key) { return FAILURE; } - sd = ps_sd_lookup(data, key, 0); + sd = ps_sd_lookup(data, key, false); if (sd) { return SUCCESS; } @@ -365,7 +365,7 @@ PS_READ_FUNC(mm) PS(session_status) = php_session_active; } - sd = ps_sd_lookup(data, PS(id), 0); + sd = ps_sd_lookup(data, PS(id), false); if (sd) { *val = zend_string_init(sd->data, sd->datalen, 0); ret = SUCCESS; @@ -383,7 +383,7 @@ PS_WRITE_FUNC(mm) mm_lock(data->mm, MM_LOCK_RW); - sd = ps_sd_lookup(data, key, 1); + sd = ps_sd_lookup(data, key, true); if (!sd) { sd = ps_sd_new(data, key); ps_mm_debug(("new entry for %s\n", ZSTR_VAL(key))); @@ -422,7 +422,7 @@ PS_DESTROY_FUNC(mm) mm_lock(data->mm, MM_LOCK_RW); - sd = ps_sd_lookup(data, key, 0); + sd = ps_sd_lookup(data, key, false); if (sd) { ps_sd_destroy(data, sd); } diff --git a/ext/session/php_session.h b/ext/session/php_session.h index 8a0d2ed27b868..e48ed4615297f 100644 --- a/ext/session/php_session.h +++ b/ext/session/php_session.h @@ -149,6 +149,7 @@ typedef struct _php_ps_globals { 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; diff --git a/ext/session/session.c b/ext/session/session.c index 33cc6cd4b7d16..8796005e9232f 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) @@ -483,7 +487,7 @@ static zend_result php_session_initialize(void) } /* GC must be done after read */ - php_session_gc(0); + php_session_gc(false); if (PS(session_vars)) { zend_string_release_ex(PS(session_vars), 0); @@ -649,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; @@ -886,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, 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_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) + 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", @@ -1246,7 +1251,7 @@ static inline void last_modified(void) } #define LAST_MODIFIED "Last-Modified: " - memcpy(buf, ZEND_STRL(LAST_MODIFIED)); + memcpy(buf, LAST_MODIFIED, sizeof(LAST_MODIFIED) - 1); strcpy_gmt(buf + sizeof(LAST_MODIFIED) - 1, &sb.st_mtime); ADD_HEADER(buf); } @@ -1261,7 +1266,7 @@ CACHE_LIMITER_FUNC(public) gettimeofday(&tv, NULL); now = tv.tv_sec + PS(cache_expire) * 60; - memcpy(buf, ZEND_STRL(EXPIRES)); + memcpy(buf, EXPIRES, sizeof(EXPIRES) - 1); strcpy_gmt(buf + sizeof(EXPIRES) - 1, &now); ADD_HEADER(buf); @@ -1335,45 +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; + 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))); - 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; - } + 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); } @@ -1388,6 +1367,12 @@ static zend_result php_session_send_cookie(void) return FAILURE; } + /* 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 */ @@ -1432,6 +1417,10 @@ static zend_result php_session_send_cookie(void) 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); } @@ -1454,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 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 ppid2sid(zval *ppid) { - ZVAL_DEREF(ppid); - if (Z_TYPE_P(ppid) == IS_STRING) { - PS(id) = zend_string_copy(Z_STR_P(ppid)); +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; @@ -1496,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)) { @@ -1517,6 +1601,8 @@ PHPAPI zend_result php_session_reset_id(void) /* 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}; @@ -1528,7 +1614,7 @@ PHPAPI zend_result php_session_reset_id(void) 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 { @@ -1536,21 +1622,29 @@ 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; + apply_trans_sid = false; if (APPLY_TRANS_SID) { - apply_trans_sid = 1; + apply_trans_sid = true; if (PS(use_cookies) && (data = zend_hash_str_find(&EG(symbol_table), ZEND_STRL("_COOKIE")))) { ZVAL_DEREF(data); if (Z_TYPE_P(data) == IS_ARRAY && - (ppid = zend_hash_find(Z_ARRVAL_P(data), PS(session_name)))) { - ZVAL_DEREF(ppid); - apply_trans_sid = 0; + (potential_session_id = zend_hash_find(Z_ARRVAL_P(data), PS(session_name)))) { + ZVAL_DEREF(potential_session_id); + apply_trans_sid = false; } } } @@ -1564,8 +1658,6 @@ PHPAPI zend_result php_session_reset_id(void) PHPAPI zend_result php_session_start(void) { - zval *ppid; - zval *data; char *value; switch (PS(session_status)) { @@ -1610,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), ZEND_STRL("_COOKIE")))) { - ZVAL_DEREF(data); - if (Z_TYPE_P(data) == IS_ARRAY && (ppid = zend_hash_find(Z_ARRVAL_P(data), PS(session_name)))) { - 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), ZEND_STRL("_GET")))) { - ZVAL_DEREF(data); - if (Z_TYPE_P(data) == IS_ARRAY && (ppid = zend_hash_find(Z_ARRVAL_P(data), PS(session_name)))) { - ppid2sid(ppid); - } - } - if (!PS(id) && (data = zend_hash_str_find(&EG(symbol_table), ZEND_STRL("_POST")))) { - ZVAL_DEREF(data); - if (Z_TYPE_P(data) == IS_ARRAY && (ppid = zend_hash_find(Z_ARRVAL_P(data), PS(session_name)))) { - 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]), ZEND_STRL("HTTP_REFERER"))) && - 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; } @@ -1725,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; @@ -1789,11 +1858,15 @@ PHP_FUNCTION(session_set_cookie_params) domain = zval_get_string(value); found++; } else if (zend_string_equals_literal_ci(key, "secure")) { - secure = zval_is_true(value); + secure = zend_is_true(value); secure_null = 0; found++; + } else if (zend_string_equals_literal_ci(key, "partitioned")) { + partitioned = zend_is_true(value); + partitioned_null = 0; + found++; } else if (zend_string_equals_literal_ci(key, "httponly")) { - httponly = zval_is_true(value); + httponly = zend_is_true(value); httponly_null = 0; found++; } else if (zend_string_equals_literal_ci(key, "samesite")) { @@ -1856,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); @@ -1898,6 +1980,7 @@ PHP_FUNCTION(session_get_cookie_params) 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_str(return_value, "samesite", zend_string_dup(PS(cookie_samesite), false)); } @@ -1911,13 +1994,7 @@ PHP_FUNCTION(session_name) 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"); - 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"); + if (name && !php_can_change_session_setting("name", false)) { RETURN_FALSE; } @@ -1940,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; } @@ -2042,7 +2113,7 @@ PHP_FUNCTION(session_set_save_handler) /* OOP Version */ if (ZEND_NUM_ARGS() <= 2) { zval *obj = NULL; - bool register_shutdown = 1; + bool register_shutdown = true; if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|b", &obj, php_session_iface_entry, ®ister_shutdown) == FAILURE) { RETURN_THROWS(); @@ -2215,13 +2286,7 @@ PHP_FUNCTION(session_save_path) 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"); - 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"); + if (name && !php_can_change_session_setting("save path", false)) { RETURN_FALSE; } @@ -2243,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; } @@ -2277,7 +2336,7 @@ PHP_FUNCTION(session_id) /* Update the current session id with a newly generated one. If delete_old_session is set to true, remove the old session. */ PHP_FUNCTION(session_regenerate_id) { - bool del_ses = 0; + bool del_ses = false; zend_string *data; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &del_ses) == FAILURE) { @@ -2476,7 +2535,7 @@ PHP_FUNCTION(session_cache_limiter) PHP_FUNCTION(session_cache_expire) { zend_long expires; - bool expires_is_null = 1; + bool expires_is_null = true; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &expires, &expires_is_null) == FAILURE) { RETURN_THROWS(); @@ -2682,7 +2741,7 @@ PHP_FUNCTION(session_gc) RETURN_FALSE; } - num = php_session_gc(1); + num = php_session_gc(true); if (num < 0) { RETURN_FALSE; } @@ -2950,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, ' '); } } @@ -3007,20 +3066,20 @@ 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; + return false; } - if ((ppid = zend_hash_find(Z_ARRVAL(PG(http_globals)[where]), PS(session_name))) - && 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); - return 1; + ZVAL_COPY_DEREF(dest, potential_session_id); + return true; } - return 0; + return false; } static void php_session_rfc1867_early_find_sid(php_session_rfc1867_progress *progress) @@ -3029,7 +3088,7 @@ static void php_session_rfc1867_early_find_sid(php_session_rfc1867_progress *pro if (PS(use_cookies)) { sapi_module.treat_data(PARSE_COOKIE, NULL, NULL); if (early_find_sid_in(&progress->sid, TRACK_VARS_COOKIE, progress)) { - progress->apply_trans_sid = 0; + progress->apply_trans_sid = false; return; } } @@ -3045,13 +3104,13 @@ static bool php_check_cancel_upload(php_session_rfc1867_progress *progress) zval *progress_ary, *cancel_upload; if ((progress_ary = zend_symtable_find(Z_ARRVAL_P(Z_REFVAL(PS(http_session_vars))), progress->key.s)) == NULL) { - return 0; + return false; } if (Z_TYPE_P(progress_ary) != IS_ARRAY) { - return 0; + return false; } if ((cancel_upload = zend_hash_str_find(Z_ARRVAL_P(progress_ary), ZEND_STRL("cancel_upload"))) == NULL) { - return 0; + return false; } return Z_TYPE_P(cancel_upload) == IS_TRUE; } @@ -3188,7 +3247,7 @@ static zend_result php_session_rfc1867_callback(unsigned int event, void *event_ progress->post_bytes_processed = zend_hash_str_find(Z_ARRVAL(progress->data), ZEND_STRL("bytes_processed")); - php_rinit_session(0); + php_rinit_session(false); PS(id) = zend_string_copy(Z_STR(progress->sid)); if (progress->apply_trans_sid) { /* Enable trans sid by modifying flags */ @@ -3215,7 +3274,7 @@ static zend_result php_session_rfc1867_callback(unsigned int event, void *event_ 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); + php_session_rfc1867_update(progress, false); } break; case MULTIPART_EVENT_FILE_DATA: { @@ -3228,7 +3287,7 @@ static zend_result php_session_rfc1867_callback(unsigned int event, void *event_ Z_LVAL_P(progress->current_file_bytes_processed) = data->offset + data->length; Z_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed; - php_session_rfc1867_update(progress, 0); + php_session_rfc1867_update(progress, false); } break; case MULTIPART_EVENT_FILE_END: { @@ -3247,7 +3306,7 @@ static zend_result php_session_rfc1867_callback(unsigned int event, void *event_ Z_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed; - php_session_rfc1867_update(progress, 0); + php_session_rfc1867_update(progress, false); } break; case MULTIPART_EVENT_END: { @@ -3261,7 +3320,7 @@ static zend_result php_session_rfc1867_callback(unsigned int event, void *event_ SEPARATE_ARRAY(&progress->data); 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); + php_session_rfc1867_update(progress, true); } } php_rshutdown_session_globals(); 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/shmop/shmop_arginfo.h b/ext/shmop/shmop_arginfo.h index 8e763ac87f764..f376b8556d930 100644 --- a/ext/shmop/shmop_arginfo.h +++ b/ext/shmop/shmop_arginfo.h @@ -55,10 +55,8 @@ static void register_shmop_symbols(int module_number) zend_attribute *attribute_Deprecated_func_shmop_close_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "shmop_close", sizeof("shmop_close") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); 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..16a8aaa22fc3a 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -1179,12 +1179,12 @@ static HashTable *sxe_get_properties(zend_object *object) /* {{{ */ } /* }}} */ -static HashTable * sxe_get_debug_info(zend_object *object, int *is_temp) /* {{{ */ +/* This custom handler exists because the var_dump adds a pseudo "@attributes" key. */ +PHP_METHOD(SimpleXMLElement, __debugInfo) { - *is_temp = 1; - return sxe_get_prop_hash(object, 1); + ZEND_PARSE_PARAMETERS_NONE(); + RETURN_ARR(sxe_get_prop_hash(Z_OBJ_P(ZEND_THIS), 1)); } -/* }}} */ static int sxe_objects_compare(zval *object1, zval *object2) /* {{{ */ { @@ -1413,14 +1413,10 @@ PHP_METHOD(SimpleXMLElement, asXML) static inline void sxe_add_namespace_name_raw(zval *return_value, const char *prefix, const char *href) { - zend_string *key = zend_string_init(prefix, strlen(prefix), 0); - zval zv; - - if (!zend_hash_exists(Z_ARRVAL_P(return_value), key)) { - ZVAL_STRING(&zv, href); - zend_hash_add_new(Z_ARRVAL_P(return_value), key, &zv); + zval *zv = zend_hash_str_lookup(Z_ARRVAL_P(return_value), prefix, strlen(prefix)); + if (Z_ISNULL_P(zv)) { + ZVAL_STRING(zv, href); } - zend_string_release_ex(key, 0); } static inline void sxe_add_namespace_name(zval *return_value, xmlNsPtr ns) /* {{{ */ @@ -1489,7 +1485,7 @@ static inline void sxe_object_free_iterxpath(php_sxe_object *sxe) /* {{{ Return all namespaces in use */ PHP_METHOD(SimpleXMLElement, getNamespaces) { - bool recursive = 0; + bool recursive = false; php_sxe_object *sxe; xmlNodePtr node; @@ -1528,10 +1524,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); } } @@ -1551,7 +1547,7 @@ static void sxe_add_registered_namespaces(php_sxe_object *sxe, xmlNodePtr node, /* {{{ Return all namespaces registered with document */ PHP_METHOD(SimpleXMLElement, getDocNamespaces) { - bool recursive = 0, from_root = 1; + bool recursive = false, from_root = true; php_sxe_object *sxe; xmlNodePtr node; @@ -1589,7 +1585,7 @@ PHP_METHOD(SimpleXMLElement, children) php_sxe_object *sxe; zend_string *nsprefix = NULL; xmlNodePtr node; - bool isprefix = 0; + bool isprefix = false; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!b", &nsprefix, &isprefix) == FAILURE) { RETURN_THROWS(); @@ -1628,7 +1624,7 @@ PHP_METHOD(SimpleXMLElement, getName) node = php_sxe_get_first_node_non_destructive(sxe, node); if (node) { namelen = xmlStrlen(node->name); - RETURN_STRINGL((char*)node->name, namelen); + RETURN_STRINGL_FAST((const char *) node->name, namelen); } else { RETURN_EMPTY_STRING(); } @@ -1641,7 +1637,7 @@ PHP_METHOD(SimpleXMLElement, attributes) php_sxe_object *sxe; zend_string *nsprefix = NULL; xmlNodePtr node; - bool isprefix = 0; + bool isprefix = false; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!b", &nsprefix, &isprefix) == FAILURE) { RETURN_THROWS(); @@ -2028,7 +2024,7 @@ PHP_METHOD(SimpleXMLElement, key) } curnode = intern->node->node; - RETURN_STRINGL((char*)curnode->name, xmlStrlen(curnode->name)); + RETURN_STRINGL_FAST((char*)curnode->name, xmlStrlen(curnode->name)); } /* }}} */ @@ -2208,7 +2204,7 @@ PHP_FUNCTION(simplexml_load_file) zend_long options = 0; zend_class_entry *ce= ce_SimpleXMLElement; zend_function *fptr_count; - bool isprefix = 0; + bool isprefix = false; if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|C!lSb", &filename, &filename_len, &ce, &options, &ns, &isprefix) == FAILURE) { RETURN_THROWS(); @@ -2254,7 +2250,7 @@ PHP_FUNCTION(simplexml_load_string) zend_long options = 0; zend_class_entry *ce= ce_SimpleXMLElement; zend_function *fptr_count; - bool isprefix = 0; + bool isprefix = false; if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|C!lSb", &data, &data_len, &ce, &options, &ns, &isprefix) == FAILURE) { RETURN_THROWS(); @@ -2306,7 +2302,7 @@ PHP_METHOD(SimpleXMLElement, __construct) size_t data_len; xmlDocPtr docp; zend_long options = 0; - bool is_url = 0, isprefix = 0; + bool is_url = false, isprefix = false; if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|lbSb", &data, &data_len, &options, &is_url, &ns, &isprefix) == FAILURE) { RETURN_THROWS(); @@ -2673,7 +2669,6 @@ PHP_MINIT_FUNCTION(simplexml) sxe_object_handlers.compare = sxe_objects_compare; sxe_object_handlers.cast_object = sxe_object_cast; sxe_object_handlers.count_elements = sxe_count_elements; - sxe_object_handlers.get_debug_info = sxe_get_debug_info; sxe_object_handlers.get_closure = NULL; sxe_object_handlers.get_gc = sxe_get_gc; diff --git a/ext/simplexml/simplexml.stub.php b/ext/simplexml/simplexml.stub.php index 2053fec6fdd2e..935af16621e9d 100644 --- a/ext/simplexml/simplexml.stub.php +++ b/ext/simplexml/simplexml.stub.php @@ -51,6 +51,8 @@ public function getName(): string {} public function __toString(): string {} + public function __debugInfo(): ?array {} + /** @tentative-return-type */ public function count(): int {} diff --git a/ext/simplexml/simplexml_arginfo.h b/ext/simplexml/simplexml_arginfo.h index 379307f953a10..90831f54c46e9 100644 --- a/ext/simplexml/simplexml_arginfo.h +++ b/ext/simplexml/simplexml_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 36eac2dee86bcc386c24e2cc14caa7bd3d709e82 */ + * Stub hash: cee51320f0f09f14962fb72125ef8ff6073a642a */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_simplexml_load_file, 0, 1, SimpleXMLElement, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0) @@ -79,6 +79,9 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_SimpleXMLElement___toString, 0, 0, IS_STRING, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_SimpleXMLElement___debugInfo, 0, 0, IS_ARRAY, 1) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SimpleXMLElement_count, 0, 0, IS_LONG, 0) ZEND_END_ARG_INFO() @@ -115,6 +118,7 @@ ZEND_METHOD(SimpleXMLElement, addChild); ZEND_METHOD(SimpleXMLElement, addAttribute); ZEND_METHOD(SimpleXMLElement, getName); ZEND_METHOD(SimpleXMLElement, __toString); +ZEND_METHOD(SimpleXMLElement, __debugInfo); ZEND_METHOD(SimpleXMLElement, count); ZEND_METHOD(SimpleXMLElement, rewind); ZEND_METHOD(SimpleXMLElement, valid); @@ -145,6 +149,7 @@ static const zend_function_entry class_SimpleXMLElement_methods[] = { ZEND_ME(SimpleXMLElement, addAttribute, arginfo_class_SimpleXMLElement_addAttribute, ZEND_ACC_PUBLIC) ZEND_ME(SimpleXMLElement, getName, arginfo_class_SimpleXMLElement_getName, ZEND_ACC_PUBLIC) ZEND_ME(SimpleXMLElement, __toString, arginfo_class_SimpleXMLElement___toString, ZEND_ACC_PUBLIC) + ZEND_ME(SimpleXMLElement, __debugInfo, arginfo_class_SimpleXMLElement___debugInfo, ZEND_ACC_PUBLIC) ZEND_ME(SimpleXMLElement, count, arginfo_class_SimpleXMLElement_count, ZEND_ACC_PUBLIC) ZEND_ME(SimpleXMLElement, rewind, arginfo_class_SimpleXMLElement_rewind, ZEND_ACC_PUBLIC) ZEND_ME(SimpleXMLElement, valid, arginfo_class_SimpleXMLElement_valid, ZEND_ACC_PUBLIC) 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-- 1]; + } +} + +$sxe = simplexml_load_string('', MySXE::class); +var_dump($sxe); + +?> +--EXPECT-- +invoked +object(MySXE)#1 (1) { + ["x"]=> + int(1) +} diff --git a/ext/skeleton/composer.json.in b/ext/skeleton/composer.json.in new file mode 100644 index 0000000000000..8f12bdee475ba --- /dev/null +++ b/ext/skeleton/composer.json.in @@ -0,0 +1,19 @@ +{ + "name": "%VENDORNAME%/%EXTNAME%", + "type": "php-ext", + "license": "BSD-3-Clause", + "description": "Describe your extension here", + "require": { + "php": "^8.3" + }, + "php-ext": { + "extension-name": "%EXTNAME%", + "configure-options": [ + { + "name": "enable-%EXTNAME%", + "needs-value": false, + "description": "whether to enable %EXTNAME% support" + } + ] + } +} diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c index 915c4a46e1b12..0ff8d41c1e6ce 100644 --- a/ext/snmp/snmp.c +++ b/ext/snmp/snmp.c @@ -34,7 +34,6 @@ #include "php_snmp.h" #include "zend_exceptions.h" -#include "zend_smart_string.h" #include "ext/spl/spl_exceptions.h" #ifdef HAVE_SNMP @@ -1038,21 +1037,18 @@ static bool snmp_session_set_auth_protocol(struct snmp_session *s, zend_string * } #endif - smart_string err = {0}; - - smart_string_appends(&err, "Authentication protocol must be \"SHA\""); + zend_value_error( + "Authentication protocol must be \"SHA\"" #ifdef HAVE_SNMP_SHA256 - smart_string_appends(&err, " or \"SHA256\""); + " or \"SHA256\"" #endif #ifdef HAVE_SNMP_SHA512 - smart_string_appends(&err, " or \"SHA512\""); + " or \"SHA512\"" #endif #ifndef DISABLE_MD5 - smart_string_appends(&err, " or \"MD5\""); + " or \"MD5\"" #endif - smart_string_0(&err); - zend_value_error("%s", err.c); - smart_string_free(&err); + ); return false; } /* }}} */ diff --git a/ext/snmp/snmp_arginfo.h b/ext/snmp/snmp_arginfo.h index 18ed9c7356634..dd0fdee92969d 100644 --- a/ext/snmp/snmp_arginfo.h +++ b/ext/snmp/snmp_arginfo.h @@ -270,123 +270,123 @@ static zend_class_entry *register_class_SNMP(void) zval const_VERSION_1_value; ZVAL_LONG(&const_VERSION_1_value, SNMP_VERSION_1); - zend_string *const_VERSION_1_name = zend_string_init_interned("VERSION_1", sizeof("VERSION_1") - 1, 1); + zend_string *const_VERSION_1_name = zend_string_init_interned("VERSION_1", sizeof("VERSION_1") - 1, true); zend_declare_typed_class_constant(class_entry, const_VERSION_1_name, &const_VERSION_1_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_VERSION_1_name); + zend_string_release_ex(const_VERSION_1_name, true); zval const_VERSION_2c_value; ZVAL_LONG(&const_VERSION_2c_value, SNMP_VERSION_2c); - zend_string *const_VERSION_2c_name = zend_string_init_interned("VERSION_2c", sizeof("VERSION_2c") - 1, 1); + zend_string *const_VERSION_2c_name = zend_string_init_interned("VERSION_2c", sizeof("VERSION_2c") - 1, true); zend_declare_typed_class_constant(class_entry, const_VERSION_2c_name, &const_VERSION_2c_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_VERSION_2c_name); + zend_string_release_ex(const_VERSION_2c_name, true); zval const_VERSION_2C_value; ZVAL_LONG(&const_VERSION_2C_value, SNMP_VERSION_2c); - zend_string *const_VERSION_2C_name = zend_string_init_interned("VERSION_2C", sizeof("VERSION_2C") - 1, 1); + zend_string *const_VERSION_2C_name = zend_string_init_interned("VERSION_2C", sizeof("VERSION_2C") - 1, true); zend_declare_typed_class_constant(class_entry, const_VERSION_2C_name, &const_VERSION_2C_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_VERSION_2C_name); + zend_string_release_ex(const_VERSION_2C_name, true); zval const_VERSION_3_value; ZVAL_LONG(&const_VERSION_3_value, SNMP_VERSION_3); - zend_string *const_VERSION_3_name = zend_string_init_interned("VERSION_3", sizeof("VERSION_3") - 1, 1); + zend_string *const_VERSION_3_name = zend_string_init_interned("VERSION_3", sizeof("VERSION_3") - 1, true); zend_declare_typed_class_constant(class_entry, const_VERSION_3_name, &const_VERSION_3_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_VERSION_3_name); + zend_string_release_ex(const_VERSION_3_name, true); zval const_ERRNO_NOERROR_value; ZVAL_LONG(&const_ERRNO_NOERROR_value, PHP_SNMP_ERRNO_NOERROR); - zend_string *const_ERRNO_NOERROR_name = zend_string_init_interned("ERRNO_NOERROR", sizeof("ERRNO_NOERROR") - 1, 1); + zend_string *const_ERRNO_NOERROR_name = zend_string_init_interned("ERRNO_NOERROR", sizeof("ERRNO_NOERROR") - 1, true); zend_declare_typed_class_constant(class_entry, const_ERRNO_NOERROR_name, &const_ERRNO_NOERROR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ERRNO_NOERROR_name); + zend_string_release_ex(const_ERRNO_NOERROR_name, true); zval const_ERRNO_ANY_value; ZVAL_LONG(&const_ERRNO_ANY_value, PHP_SNMP_ERRNO_ANY); - zend_string *const_ERRNO_ANY_name = zend_string_init_interned("ERRNO_ANY", sizeof("ERRNO_ANY") - 1, 1); + zend_string *const_ERRNO_ANY_name = zend_string_init_interned("ERRNO_ANY", sizeof("ERRNO_ANY") - 1, true); zend_declare_typed_class_constant(class_entry, const_ERRNO_ANY_name, &const_ERRNO_ANY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ERRNO_ANY_name); + zend_string_release_ex(const_ERRNO_ANY_name, true); zval const_ERRNO_GENERIC_value; ZVAL_LONG(&const_ERRNO_GENERIC_value, PHP_SNMP_ERRNO_GENERIC); - zend_string *const_ERRNO_GENERIC_name = zend_string_init_interned("ERRNO_GENERIC", sizeof("ERRNO_GENERIC") - 1, 1); + zend_string *const_ERRNO_GENERIC_name = zend_string_init_interned("ERRNO_GENERIC", sizeof("ERRNO_GENERIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_ERRNO_GENERIC_name, &const_ERRNO_GENERIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ERRNO_GENERIC_name); + zend_string_release_ex(const_ERRNO_GENERIC_name, true); zval const_ERRNO_TIMEOUT_value; ZVAL_LONG(&const_ERRNO_TIMEOUT_value, PHP_SNMP_ERRNO_TIMEOUT); - zend_string *const_ERRNO_TIMEOUT_name = zend_string_init_interned("ERRNO_TIMEOUT", sizeof("ERRNO_TIMEOUT") - 1, 1); + zend_string *const_ERRNO_TIMEOUT_name = zend_string_init_interned("ERRNO_TIMEOUT", sizeof("ERRNO_TIMEOUT") - 1, true); zend_declare_typed_class_constant(class_entry, const_ERRNO_TIMEOUT_name, &const_ERRNO_TIMEOUT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ERRNO_TIMEOUT_name); + zend_string_release_ex(const_ERRNO_TIMEOUT_name, true); zval const_ERRNO_ERROR_IN_REPLY_value; ZVAL_LONG(&const_ERRNO_ERROR_IN_REPLY_value, PHP_SNMP_ERRNO_ERROR_IN_REPLY); - zend_string *const_ERRNO_ERROR_IN_REPLY_name = zend_string_init_interned("ERRNO_ERROR_IN_REPLY", sizeof("ERRNO_ERROR_IN_REPLY") - 1, 1); + zend_string *const_ERRNO_ERROR_IN_REPLY_name = zend_string_init_interned("ERRNO_ERROR_IN_REPLY", sizeof("ERRNO_ERROR_IN_REPLY") - 1, true); zend_declare_typed_class_constant(class_entry, const_ERRNO_ERROR_IN_REPLY_name, &const_ERRNO_ERROR_IN_REPLY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ERRNO_ERROR_IN_REPLY_name); + zend_string_release_ex(const_ERRNO_ERROR_IN_REPLY_name, true); zval const_ERRNO_OID_NOT_INCREASING_value; ZVAL_LONG(&const_ERRNO_OID_NOT_INCREASING_value, PHP_SNMP_ERRNO_OID_NOT_INCREASING); - zend_string *const_ERRNO_OID_NOT_INCREASING_name = zend_string_init_interned("ERRNO_OID_NOT_INCREASING", sizeof("ERRNO_OID_NOT_INCREASING") - 1, 1); + zend_string *const_ERRNO_OID_NOT_INCREASING_name = zend_string_init_interned("ERRNO_OID_NOT_INCREASING", sizeof("ERRNO_OID_NOT_INCREASING") - 1, true); zend_declare_typed_class_constant(class_entry, const_ERRNO_OID_NOT_INCREASING_name, &const_ERRNO_OID_NOT_INCREASING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ERRNO_OID_NOT_INCREASING_name); + zend_string_release_ex(const_ERRNO_OID_NOT_INCREASING_name, true); zval const_ERRNO_OID_PARSING_ERROR_value; ZVAL_LONG(&const_ERRNO_OID_PARSING_ERROR_value, PHP_SNMP_ERRNO_OID_PARSING_ERROR); - zend_string *const_ERRNO_OID_PARSING_ERROR_name = zend_string_init_interned("ERRNO_OID_PARSING_ERROR", sizeof("ERRNO_OID_PARSING_ERROR") - 1, 1); + zend_string *const_ERRNO_OID_PARSING_ERROR_name = zend_string_init_interned("ERRNO_OID_PARSING_ERROR", sizeof("ERRNO_OID_PARSING_ERROR") - 1, true); zend_declare_typed_class_constant(class_entry, const_ERRNO_OID_PARSING_ERROR_name, &const_ERRNO_OID_PARSING_ERROR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ERRNO_OID_PARSING_ERROR_name); + zend_string_release_ex(const_ERRNO_OID_PARSING_ERROR_name, true); zval const_ERRNO_MULTIPLE_SET_QUERIES_value; ZVAL_LONG(&const_ERRNO_MULTIPLE_SET_QUERIES_value, PHP_SNMP_ERRNO_MULTIPLE_SET_QUERIES); - zend_string *const_ERRNO_MULTIPLE_SET_QUERIES_name = zend_string_init_interned("ERRNO_MULTIPLE_SET_QUERIES", sizeof("ERRNO_MULTIPLE_SET_QUERIES") - 1, 1); + zend_string *const_ERRNO_MULTIPLE_SET_QUERIES_name = zend_string_init_interned("ERRNO_MULTIPLE_SET_QUERIES", sizeof("ERRNO_MULTIPLE_SET_QUERIES") - 1, true); zend_declare_typed_class_constant(class_entry, const_ERRNO_MULTIPLE_SET_QUERIES_name, &const_ERRNO_MULTIPLE_SET_QUERIES_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ERRNO_MULTIPLE_SET_QUERIES_name); + zend_string_release_ex(const_ERRNO_MULTIPLE_SET_QUERIES_name, true); zval property_info_default_value; ZVAL_UNDEF(&property_info_default_value); - zend_string *property_info_name = zend_string_init("info", sizeof("info") - 1, 1); + zend_string *property_info_name = zend_string_init("info", sizeof("info") - 1, true); zend_declare_typed_property(class_entry, property_info_name, &property_info_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ARRAY)); - zend_string_release(property_info_name); + zend_string_release_ex(property_info_name, true); zval property_max_oids_default_value; ZVAL_UNDEF(&property_max_oids_default_value); - zend_string *property_max_oids_name = zend_string_init("max_oids", sizeof("max_oids") - 1, 1); + zend_string *property_max_oids_name = zend_string_init("max_oids", sizeof("max_oids") - 1, true); zend_declare_typed_property(class_entry, property_max_oids_name, &property_max_oids_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG|MAY_BE_NULL)); - zend_string_release(property_max_oids_name); + zend_string_release_ex(property_max_oids_name, true); zval property_valueretrieval_default_value; ZVAL_UNDEF(&property_valueretrieval_default_value); - zend_string *property_valueretrieval_name = zend_string_init("valueretrieval", sizeof("valueretrieval") - 1, 1); + zend_string *property_valueretrieval_name = zend_string_init("valueretrieval", sizeof("valueretrieval") - 1, true); zend_declare_typed_property(class_entry, property_valueretrieval_name, &property_valueretrieval_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_valueretrieval_name); + zend_string_release_ex(property_valueretrieval_name, true); zval property_quick_print_default_value; ZVAL_UNDEF(&property_quick_print_default_value); - zend_string *property_quick_print_name = zend_string_init("quick_print", sizeof("quick_print") - 1, 1); + zend_string *property_quick_print_name = zend_string_init("quick_print", sizeof("quick_print") - 1, true); zend_declare_typed_property(class_entry, property_quick_print_name, &property_quick_print_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_quick_print_name); + zend_string_release_ex(property_quick_print_name, true); zval property_enum_print_default_value; ZVAL_UNDEF(&property_enum_print_default_value); - zend_string *property_enum_print_name = zend_string_init("enum_print", sizeof("enum_print") - 1, 1); + zend_string *property_enum_print_name = zend_string_init("enum_print", sizeof("enum_print") - 1, true); zend_declare_typed_property(class_entry, property_enum_print_name, &property_enum_print_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_enum_print_name); + zend_string_release_ex(property_enum_print_name, true); zval property_oid_output_format_default_value; ZVAL_UNDEF(&property_oid_output_format_default_value); - zend_string *property_oid_output_format_name = zend_string_init("oid_output_format", sizeof("oid_output_format") - 1, 1); + zend_string *property_oid_output_format_name = zend_string_init("oid_output_format", sizeof("oid_output_format") - 1, true); zend_declare_typed_property(class_entry, property_oid_output_format_name, &property_oid_output_format_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_oid_output_format_name); + zend_string_release_ex(property_oid_output_format_name, true); zval property_oid_increasing_check_default_value; ZVAL_UNDEF(&property_oid_increasing_check_default_value); - zend_string *property_oid_increasing_check_name = zend_string_init("oid_increasing_check", sizeof("oid_increasing_check") - 1, 1); + zend_string *property_oid_increasing_check_name = zend_string_init("oid_increasing_check", sizeof("oid_increasing_check") - 1, true); zend_declare_typed_property(class_entry, property_oid_increasing_check_name, &property_oid_increasing_check_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_oid_increasing_check_name); + zend_string_release_ex(property_oid_increasing_check_name, true); zval property_exceptions_enabled_default_value; ZVAL_UNDEF(&property_exceptions_enabled_default_value); - zend_string *property_exceptions_enabled_name = zend_string_init("exceptions_enabled", sizeof("exceptions_enabled") - 1, 1); + zend_string *property_exceptions_enabled_name = zend_string_init("exceptions_enabled", sizeof("exceptions_enabled") - 1, true); zend_declare_typed_property(class_entry, property_exceptions_enabled_name, &property_exceptions_enabled_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_exceptions_enabled_name); + zend_string_release_ex(property_exceptions_enabled_name, true); return class_entry; } diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index 8423f50fd4b8e..77d97b566fc19 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -284,7 +284,7 @@ static bool soap_check_zval_ref(zval *data, xmlNodePtr node) { smart_str prefix = {0}; if (node_ptr == node) { - return 0; + return false; } if (SOAP_GLOBAL(soap_version) == SOAP_1_1) { attr = get_attribute(attr, "id"); @@ -322,12 +322,12 @@ static bool soap_check_zval_ref(zval *data, xmlNodePtr node) { set_ns_prop(node, SOAP_1_2_ENC_NAMESPACE, "ref", id); } smart_str_free(&prefix); - return 1; + return true; } else { zend_hash_index_update_ptr(SOAP_GLOBAL(ref_map), (zend_ulong)data, node); } } - return 0; + return false; } static bool soap_check_xml_ref(zval *data, xmlNodePtr node) @@ -341,11 +341,11 @@ static bool soap_check_xml_ref(zval *data, xmlNodePtr node) Z_COUNTED_P(data) != Z_COUNTED_P(data_ptr)) { zval_ptr_dtor(data); ZVAL_COPY(data, data_ptr); - return 1; + return true; } } } - return 0; + return false; } static void soap_add_xml_ref(zval *data, xmlNodePtr node) @@ -598,7 +598,7 @@ xmlNodePtr to_xml_user(encodeTypePtr type, zval *data, int style, xmlNodePtr par zval_ptr_dtor(&return_value); } if (!ret) { - ret = xmlNewNode(NULL, BAD_CAST("BOGUS")); + ret = xmlNewDocNode(parent->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 && @@ -1797,9 +1797,9 @@ static sdlTypePtr model_array_element(sdlContentModelPtr model) ZEND_HASH_FOREACH_PTR(model->u.content, tmp) { return model_array_element(tmp); } ZEND_HASH_FOREACH_END(); + + break; } - /* TODO Check this is correct */ - ZEND_FALLTHROUGH; case XSD_CONTENT_GROUP: { return model_array_element(model->u.group->model); } @@ -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; } @@ -3565,6 +3579,11 @@ static encodePtr get_array_type(xmlNodePtr node, zval *array, smart_str *type) soap_error0(E_ERROR, "Encoding: SoapVar has no 'enc_type' property"); } cur_type = Z_LVAL_P(ztype); + if (cur_type == UNKNOWN_TYPE) { + /* Mimic guess_xml_convert() where we use the type of the data. + * UNDEFs are handled transparently as it will error out upon encoding the data. */ + cur_type = Z_TYPE_P(Z_VAR_ENC_VALUE_P(tmp)); + } zval *zstype = Z_VAR_ENC_STYPE_P(tmp); if (Z_TYPE_P(zstype) == IS_STRING) { diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c index 71f32d4b9d107..63c0093eb05c8 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); @@ -328,25 +329,22 @@ static bool in_domain(const zend_string *host, const zend_string *domain) if (ZSTR_LEN(host) > ZSTR_LEN(domain)) { return strcmp(ZSTR_VAL(host)+ZSTR_LEN(host)-ZSTR_LEN(domain), ZSTR_VAL(domain)) == 0; } else { - return 0; + return false; } } else { return zend_string_equals(host,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; @@ -365,9 +363,9 @@ int make_http_soap_request(zval *this_ptr, char *http_msg = NULL; bool old_allow_url_fopen; php_stream_context *context = NULL; - bool has_authorization = 0; - bool has_proxy_authorization = 0; - bool has_cookies = 0; + bool has_authorization = false; + bool has_proxy_authorization = false; + bool has_cookies = false; if (this_ptr == NULL || Z_TYPE_P(this_ptr) != IS_OBJECT) { return FALSE; @@ -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,26 +453,28 @@ 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); } - add_soap_fault(this_ptr, "HTTP", "Unable to parse URL", NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "HTTP", "Unable to parse URL", NULL, NULL, soap_lang_en); smart_str_free(&soap_headers_z); efree(http_msg); return FALSE; } 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); } - add_soap_fault(this_ptr, "HTTP", "Unknown protocol. Only http and https are allowed.", NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "HTTP", "Unknown protocol. Only http and https are allowed.", NULL, NULL, soap_lang_en); smart_str_free(&soap_headers_z); efree(http_msg); return FALSE; @@ -478,33 +483,33 @@ 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); } - add_soap_fault(this_ptr, "HTTP", "SSL support is not available in this build", NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "HTTP", "SSL support is not available in this build", NULL, NULL, soap_lang_en); PG(allow_url_fopen) = old_allow_url_fopen; smart_str_free(&soap_headers_z); efree(http_msg); 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); @@ -526,16 +531,16 @@ int make_http_soap_request(zval *this_ptr, } 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_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); } - add_soap_fault(this_ptr, "HTTP", "Could not connect to host", NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "HTTP", "Could not connect to host", NULL, NULL, soap_lang_en); PG(allow_url_fopen) = old_allow_url_fopen; smart_str_free(&soap_headers_z); efree(http_msg); @@ -556,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 && @@ -569,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"); @@ -594,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" @@ -675,7 +680,7 @@ int make_http_soap_request(zval *this_ptr, if (Z_TYPE_P(login) == IS_STRING) { zval *digest = Z_CLIENT_DIGEST_P(this_ptr); - has_authorization = 1; + has_authorization = true; if (Z_TYPE_P(digest) == IS_ARRAY) { char HA1[33], HA2[33], response[33], cnonce[33], nc[9]; unsigned char nonce[16]; @@ -739,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); @@ -787,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) { @@ -853,7 +858,7 @@ int make_http_soap_request(zval *this_ptr, if (zend_hash_num_elements(Z_ARRVAL_P(cookies)) != 0 && !HT_IS_PACKED(Z_ARRVAL_P(cookies))) { zval *data; zend_string *key; - has_cookies = 1; + has_cookies = true; bool first_cookie = true; smart_str_append_const(&soap_headers, "Cookie: "); ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(cookies), key, data) { @@ -865,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, "; "); @@ -906,14 +911,14 @@ int make_http_soap_request(zval *this_ptr, php_stream_close(stream); convert_to_null(Z_CLIENT_HTTPURL_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)); + add_soap_fault(this_ptr, "HTTP", "Failed Sending HTTP SOAP request", NULL, NULL, soap_lang_en); smart_str_free(&soap_headers_z); efree(http_msg); return FALSE; } smart_str_free(&soap_headers); } else { - add_soap_fault(this_ptr, "HTTP", "Failed to create stream??", NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "HTTP", "Failed to create stream??", NULL, NULL, soap_lang_en); smart_str_free(&soap_headers_z); efree(http_msg); return FALSE; @@ -930,7 +935,7 @@ int make_http_soap_request(zval *this_ptr, ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr)); php_stream_close(stream); 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)); + add_soap_fault(this_ptr, "HTTP", "Error Fetching http headers", NULL, NULL, soap_lang_en); smart_str_free(&soap_headers_z); efree(http_msg); return FALSE; @@ -1009,8 +1014,7 @@ int make_http_soap_request(zval *this_ptr, char *eqpos = strstr(cookie, "="); char *sempos = strstr(cookie, ";"); if (eqpos != NULL && (sempos == NULL || sempos > eqpos)) { - smart_str name = {0}; - int cookie_len; + size_t cookie_len; zval zcookie; if (sempos != NULL) { @@ -1019,8 +1023,7 @@ int make_http_soap_request(zval *this_ptr, cookie_len = strlen(cookie)-(eqpos-cookie)-1; } - smart_str_appendl(&name, cookie, eqpos - cookie); - smart_str_0(&name); + zend_string *name = zend_string_init(cookie, eqpos - cookie, false); array_init(&zcookie); add_index_stringl(&zcookie, 0, eqpos + 1, cookie_len); @@ -1047,19 +1050,19 @@ 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); - smart_str_free(&name); + zend_symtable_update(Z_ARRVAL_P(cookies), name, &zcookie); + zend_string_release_ex(name, false); } cookie_itt = cookie_itt + cookie_len; @@ -1119,7 +1122,7 @@ int make_http_soap_request(zval *this_ptr, php_stream_close(stream); zend_string_release_ex(http_headers, 0); 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)); + add_soap_fault(this_ptr, "HTTP", "Error Fetching http body, No Content-Length, connection closed or chunked data", NULL, NULL, soap_lang_en); if (http_msg) { efree(http_msg); } @@ -1143,42 +1146,49 @@ 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; + } + + 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_url != NULL) { + if (new_uri != NULL) { zend_string_release_ex(http_headers, 0); zend_string_release_ex(http_body, 0); - 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)); + add_soap_fault(this_ptr, "HTTP", "Redirection limit reached, aborting", NULL, NULL, soap_lang_en); smart_str_free(&soap_headers_z); efree(http_msg); return FALSE; @@ -1235,20 +1245,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); @@ -1314,7 +1324,7 @@ int make_http_soap_request(zval *this_ptr, if (http_msg) { efree(http_msg); } - add_soap_fault(this_ptr, "HTTP", "Unknown Content-Encoding", NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "HTTP", "Unknown Content-Encoding", NULL, NULL, soap_lang_en); return FALSE; } zend_call_known_function(decompression_fn, NULL, NULL, &retval, 1, params, NULL); @@ -1326,7 +1336,7 @@ int make_http_soap_request(zval *this_ptr, efree(content_encoding); zend_string_release_ex(http_headers, 0); zend_string_release_ex(http_body, 0); - add_soap_fault(this_ptr, "HTTP", "Can't uncompress compressed response", NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "HTTP", "Can't uncompress compressed response", NULL, NULL, soap_lang_en); if (http_msg) { efree(http_msg); } @@ -1360,7 +1370,7 @@ int make_http_soap_request(zval *this_ptr, if (error) { zval_ptr_dtor(return_value); ZVAL_UNDEF(return_value); - add_soap_fault(this_ptr, "HTTP", http_msg, NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "HTTP", http_msg, NULL, NULL, soap_lang_en); efree(http_msg); return FALSE; } 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_packet_soap.c b/ext/soap/php_packet_soap.c index 31ed094ef2fc7..1019949093f0e 100644 --- a/ext/soap/php_packet_soap.c +++ b/ext/soap/php_packet_soap.c @@ -40,11 +40,11 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio response = soap_xmlParseMemory(buffer, buffer_size); if (!response) { - add_soap_fault(this_ptr, "Client", "looks like we got no XML document", NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "Client", "looks like we got no XML document", NULL, NULL, soap_lang_en); return false; } if (xmlGetIntSubset(response) != NULL) { - add_soap_fault(this_ptr, "Client", "DTD are not supported by SOAP", NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "Client", "DTD are not supported by SOAP", NULL, NULL, soap_lang_en); xmlFreeDoc(response); return false; } @@ -63,7 +63,7 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio envelope_ns = SOAP_1_2_ENV_NAMESPACE; soap_version = SOAP_1_2; } else { - add_soap_fault(this_ptr, "VersionMismatch", "Wrong Version", NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "VersionMismatch", "Wrong Version", NULL, NULL, soap_lang_en); xmlFreeDoc(response); return false; } @@ -71,7 +71,7 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio trav = trav->next; } if (env == NULL) { - add_soap_fault(this_ptr, "Client", "looks like we got XML without \"Envelope\" element", NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "Client", "looks like we got XML without \"Envelope\" element", NULL, NULL, soap_lang_en); xmlFreeDoc(response); return false; } @@ -79,16 +79,16 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio attr = env->properties; while (attr != NULL) { if (attr->ns == NULL) { - add_soap_fault(this_ptr, "Client", "A SOAP Envelope element cannot have non Namespace qualified attributes", NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "Client", "A SOAP Envelope element cannot have non Namespace qualified attributes", NULL, NULL, soap_lang_en); xmlFreeDoc(response); return false; } else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) { if (soap_version == SOAP_1_2) { - add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Envelope", NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Envelope", NULL, NULL, soap_lang_en); xmlFreeDoc(response); return false; } else if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE) != 0) { - add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL, soap_lang_en); xmlFreeDoc(response); return false; } @@ -120,7 +120,7 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio trav = trav->next; } if (body == NULL) { - add_soap_fault(this_ptr, "Client", "Body must be present in a SOAP envelope", NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "Client", "Body must be present in a SOAP envelope", NULL, NULL, soap_lang_en); xmlFreeDoc(response); return false; } @@ -128,17 +128,17 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio while (attr != NULL) { if (attr->ns == NULL) { if (soap_version == SOAP_1_2) { - add_soap_fault(this_ptr, "Client", "A SOAP Body element cannot have non Namespace qualified attributes", NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "Client", "A SOAP Body element cannot have non Namespace qualified attributes", NULL, NULL, soap_lang_en); xmlFreeDoc(response); return false; } } else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) { if (soap_version == SOAP_1_2) { - add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Body", NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Body", NULL, NULL, soap_lang_en); xmlFreeDoc(response); return false; } else if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE) != 0) { - add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL, soap_lang_en); xmlFreeDoc(response); return false; } @@ -146,7 +146,7 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio attr = attr->next; } if (trav != NULL && soap_version == SOAP_1_2) { - add_soap_fault(this_ptr, "Client", "A SOAP 1.2 envelope can contain only Header and Body", NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "Client", "A SOAP 1.2 envelope can contain only Header and Body", NULL, NULL, soap_lang_en); xmlFreeDoc(response); return false; } @@ -155,16 +155,16 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio attr = head->properties; while (attr != NULL) { if (attr->ns == NULL) { - add_soap_fault(this_ptr, "Client", "A SOAP Header element cannot have non Namespace qualified attributes", NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "Client", "A SOAP Header element cannot have non Namespace qualified attributes", NULL, NULL, soap_lang_en); xmlFreeDoc(response); return false; } else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) { if (soap_version == SOAP_1_2) { - add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Header", NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Header", NULL, NULL, soap_lang_en); xmlFreeDoc(response); return false; } else if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE) != 0) { - add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL, SOAP_GLOBAL(lang_en)); + add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL, soap_lang_en); xmlFreeDoc(response); return false; } diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c index cc01b598bd9c3..e6871cd6e9b31 100644 --- a/ext/soap/php_sdl.c +++ b/ext/soap/php_sdl.c @@ -3157,8 +3157,8 @@ sdlPtr get_sdl(zval *this_ptr, char *uri, zend_long cache_wsdl) smart_str headers = {0}; char* key = NULL; time_t t = time(0); - bool has_proxy_authorization = 0; - bool has_authorization = 0; + bool has_proxy_authorization = false; + bool has_authorization = false; ZVAL_UNDEF(&orig_context); ZVAL_UNDEF(&new_context); @@ -3312,7 +3312,7 @@ sdlPtr get_sdl(zval *this_ptr, char *uri, zend_long cache_wsdl) sdl = load_wsdl(this_ptr, uri); if (sdl) { - sdl->is_persistent = 0; + sdl->is_persistent = false; } SOAP_GLOBAL(error_code) = old_error_code; @@ -3359,7 +3359,7 @@ sdlPtr get_sdl(zval *this_ptr, char *uri, zend_long cache_wsdl) } psdl = make_persistent_sdl(sdl); - psdl->is_persistent = 1; + psdl->is_persistent = true; p.time = t; p.sdl = psdl; diff --git a/ext/soap/php_soap.h b/ext/soap/php_soap.h index 1eea30c62e905..aa3fb79e57095 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 @@ -170,9 +171,10 @@ ZEND_BEGIN_MODULE_GLOBALS(soap) HashTable wsdl_cache; int cur_uniq_ref; HashTable *ref_map; - zend_string *lang_en; ZEND_END_MODULE_GLOBALS(soap) +extern zend_string *soap_lang_en; + #ifdef ZTS #include "TSRM.h" #endif @@ -255,7 +257,7 @@ static zend_always_inline zval *php_soap_deref(zval *zv) { #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/php_xml.c b/ext/soap/php_xml.c index b6b0c09b9d48b..a2536b98f39bb 100644 --- a/ext/soap/php_xml.c +++ b/ext/soap/php_xml.c @@ -79,12 +79,15 @@ static xmlDocPtr soap_xmlParse_ex(xmlParserCtxtPtr ctxt) { xmlDocPtr ret; if (ctxt) { +#if LIBXML_VERSION >= 21300 + xmlCtxtSetOptions(ctxt, XML_PARSE_HUGE | XML_PARSE_NO_XXE | XML_PARSE_NONET | XML_PARSE_NOBLANKS); +#else php_libxml_sanitize_parse_ctxt_options(ctxt); - /* TODO: In libxml2 2.14.0 change this to the new options API so we don't rely on deprecated APIs. */ ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations") ctxt->keepBlanks = 0; ctxt->options |= XML_PARSE_HUGE; ZEND_DIAGNOSTIC_IGNORED_END +#endif ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace; ctxt->sax->comment = soap_Comment; ctxt->sax->warning = NULL; diff --git a/ext/soap/soap.c b/ext/soap/soap.c index 0786ac811059e..471b2d622d98a 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -194,6 +194,8 @@ static zend_object_handlers soap_server_object_handlers; static zend_object_handlers soap_url_object_handlers; static zend_object_handlers soap_sdl_object_handlers; +zend_string *soap_lang_en; + typedef struct { soapServicePtr service; zend_object std; @@ -233,9 +235,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); @@ -453,7 +455,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) @@ -473,7 +474,7 @@ PHP_MSHUTDOWN_FUNCTION(soap) zend_hash_destroy(SOAP_GLOBAL(mem_cache)); free(SOAP_GLOBAL(mem_cache)); } - zend_string_release_ex(SOAP_GLOBAL(lang_en), true); + zend_string_release_ex(soap_lang_en, true); UNREGISTER_INI_ENTRIES(); return SUCCESS; } @@ -553,6 +554,8 @@ PHP_MINIT_FUNCTION(soap) old_error_handler = zend_error_cb; zend_error_cb = soap_error_handler; + soap_lang_en = zend_string_init_interned(ZEND_STRL("en"), true); + return SUCCESS; } @@ -711,7 +714,7 @@ PHP_METHOD(SoapFault, __construct) } this_ptr = ZEND_THIS; - set_soap_fault(this_ptr, fault_code_ns, fault_code, fault_string, fault_actor, details, name, lang); + set_soap_fault(this_ptr, fault_code_ns, fault_code, fault_string, fault_actor, details, name, soap_lang_en); if (headerfault != NULL) { ZVAL_COPY(Z_FAULT_HEADERFAULT_P(this_ptr), headerfault); } @@ -764,7 +767,7 @@ PHP_METHOD(SoapVar, __construct) { zval *data, *this_ptr; zend_long type; - bool type_is_null = 1; + bool type_is_null = true; zend_string *stype = NULL, *ns = NULL, *name = NULL, *namens = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS(), "z!l!|S!S!S!S!", &data, &type, &type_is_null, &stype, &ns, &name, &namens) == FAILURE) { @@ -1012,7 +1015,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); @@ -1852,7 +1861,7 @@ static ZEND_NORETURN void soap_server_fault(char* code, char* string, char *acto static ZEND_NORETURN void soap_server_fault_en(char* code, char* string, char *actor, zval* details, zend_string* name) { - soap_server_fault(code, string, actor, details, name, SOAP_GLOBAL(lang_en)); + soap_server_fault(code, string, actor, details, name, soap_lang_en); } static zend_never_inline ZEND_COLD void soap_real_error_handler(int error_num, zend_string *error_filename, const uint32_t error_lineno, zend_string *message) /* {{{ */ @@ -1921,7 +1930,7 @@ static zend_never_inline ZEND_COLD void soap_real_error_handler(int error_num, z } ZVAL_NULL(&fault_obj); - set_soap_fault(&fault_obj, NULL, code, ZSTR_VAL(buffer), NULL, &outbuf, NULL, SOAP_GLOBAL(lang_en)); + set_soap_fault(&fault_obj, NULL, code, ZSTR_VAL(buffer), NULL, &outbuf, NULL, soap_lang_en); zend_string_release(buffer); fault = 1; } @@ -1962,7 +1971,7 @@ static void soap_error_handler(int error_num, zend_string *error_filename, const /* {{{ */ PHP_FUNCTION(use_soap_error_handler) { - bool handler = 1; + bool handler = true; ZVAL_BOOL(return_value, SOAP_GLOBAL(use_soap_error_handler)); if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &handler) == SUCCESS) { @@ -2544,7 +2553,7 @@ static void soap_client_call_common( if (soap_headers) { if (!free_soap_headers) { soap_headers = zend_array_dup(soap_headers); - free_soap_headers = 1; + free_soap_headers = true; } ZEND_HASH_FOREACH_VAL(default_headers, tmp) { if(Z_TYPE_P(tmp) == IS_OBJECT) { @@ -2554,7 +2563,7 @@ static void soap_client_call_common( } ZEND_HASH_FOREACH_END(); } else { soap_headers = Z_ARRVAL_P(tmp); - free_soap_headers = 0; + free_soap_headers = false; } } @@ -2783,28 +2792,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; + bool one_way = false; 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; + one_way = false; } 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; } @@ -2826,12 +2835,12 @@ PHP_METHOD(SoapClient, __setCookie) zval *cookies = Z_CLIENT_COOKIES_P(ZEND_THIS); SEPARATE_ARRAY(cookies); if (val == NULL) { - zend_hash_del(Z_ARRVAL_P(cookies), name); + zend_symtable_del(Z_ARRVAL_P(cookies), name); } else { zval zcookie; array_init(&zcookie); add_index_str(&zcookie, 0, zend_string_copy(val)); - zend_hash_update(Z_ARRVAL_P(cookies), name, &zcookie); + zend_symtable_update(Z_ARRVAL_P(cookies), name, &zcookie); } } /* }}} */ @@ -2934,7 +2943,7 @@ static void add_soap_fault_ex(zval *fault, zval *obj, char *fault_code, char *fa static void add_soap_fault_ex_en(zval *fault, zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail) { - add_soap_fault_ex(fault, obj, fault_code, fault_string, fault_actor, fault_detail, SOAP_GLOBAL(lang_en)); + add_soap_fault_ex(fault, obj, fault_code, fault_string, fault_actor, fault_detail, soap_lang_en); } void add_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail, zend_string *lang) /* {{{ */ @@ -2946,7 +2955,7 @@ void add_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault static void add_soap_fault_en(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail) { - add_soap_fault(obj, fault_code, fault_string, fault_actor, fault_detail, SOAP_GLOBAL(lang_en)); + add_soap_fault(obj, fault_code, fault_string, fault_actor, fault_detail, soap_lang_en); } static void set_soap_fault(zval *obj, const char *fault_code_ns, const char *fault_code, const char *fault_string, const char *fault_actor, zval *fault_detail, zend_string *name, zend_string *lang) /* {{{ */ @@ -3716,7 +3725,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) { @@ -3780,7 +3789,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); @@ -4112,7 +4121,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)); @@ -4205,7 +4214,7 @@ static xmlNodePtr serialize_zval(zval *val, sdlParamPtr param, const char *param } xmlParam = master_to_xml(enc, val, style, parent); zval_ptr_dtor(&defval); - if (xmlParam != NULL) { + if (xmlParam != NULL) { if (xmlParam->name == NULL || strcmp((char*)xmlParam->name, "BOGUS") == 0) { xmlNodeSetName(xmlParam, BAD_CAST(paramName)); } diff --git a/ext/soap/soap.stub.php b/ext/soap/soap.stub.php index 15d4ef1e6bd3e..851b32042bd19 100644 --- a/ext/soap/soap.stub.php +++ b/ext/soap/soap.stub.php @@ -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 f69659b4b0f84..7efa15cde2f9d 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: 4277993645a3f560c7a9971466fabf2d451bc92d */ + * 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) @@ -320,10 +321,8 @@ static void register_soap_symbols(int module_number) 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); - zval attribute_Deprecated_const_SOAP_FUNCTIONS_ALL_0_arg1; 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_arg1, attribute_Deprecated_const_SOAP_FUNCTIONS_ALL_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_SOAP_FUNCTIONS_ALL_0->args[1].value, &attribute_Deprecated_const_SOAP_FUNCTIONS_ALL_0_arg1); + 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); } @@ -356,15 +355,15 @@ static zend_class_entry *register_class_SoapParam(void) zval property_param_name_default_value; ZVAL_UNDEF(&property_param_name_default_value); - zend_string *property_param_name_name = zend_string_init("param_name", sizeof("param_name") - 1, 1); + zend_string *property_param_name_name = zend_string_init("param_name", sizeof("param_name") - 1, true); zend_declare_typed_property(class_entry, property_param_name_name, &property_param_name_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_param_name_name); + zend_string_release_ex(property_param_name_name, true); zval property_param_data_default_value; ZVAL_UNDEF(&property_param_data_default_value); - zend_string *property_param_data_name = zend_string_init("param_data", sizeof("param_data") - 1, 1); + zend_string *property_param_data_name = zend_string_init("param_data", sizeof("param_data") - 1, true); zend_declare_typed_property(class_entry, property_param_data_name, &property_param_data_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ANY)); - zend_string_release(property_param_data_name); + zend_string_release_ex(property_param_data_name, true); return class_entry; } @@ -378,9 +377,9 @@ static zend_class_entry *register_class_SoapHeader(void) zval property_namespace_default_value; ZVAL_UNDEF(&property_namespace_default_value); - zend_string *property_namespace_name = zend_string_init("namespace", sizeof("namespace") - 1, 1); + zend_string *property_namespace_name = zend_string_init("namespace", sizeof("namespace") - 1, true); zend_declare_typed_property(class_entry, property_namespace_name, &property_namespace_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_namespace_name); + zend_string_release_ex(property_namespace_name, true); zval property_name_default_value; ZVAL_UNDEF(&property_name_default_value); @@ -388,21 +387,21 @@ static zend_class_entry *register_class_SoapHeader(void) zval property_data_default_value; ZVAL_NULL(&property_data_default_value); - zend_string *property_data_name = zend_string_init("data", sizeof("data") - 1, 1); + zend_string *property_data_name = zend_string_init("data", sizeof("data") - 1, true); zend_declare_typed_property(class_entry, property_data_name, &property_data_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ANY)); - zend_string_release(property_data_name); + zend_string_release_ex(property_data_name, true); zval property_mustUnderstand_default_value; ZVAL_UNDEF(&property_mustUnderstand_default_value); - zend_string *property_mustUnderstand_name = zend_string_init("mustUnderstand", sizeof("mustUnderstand") - 1, 1); + zend_string *property_mustUnderstand_name = zend_string_init("mustUnderstand", sizeof("mustUnderstand") - 1, true); zend_declare_typed_property(class_entry, property_mustUnderstand_name, &property_mustUnderstand_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_mustUnderstand_name); + zend_string_release_ex(property_mustUnderstand_name, true); zval property_actor_default_value; ZVAL_UNDEF(&property_actor_default_value); - zend_string *property_actor_name = zend_string_init("actor", sizeof("actor") - 1, 1); + zend_string *property_actor_name = zend_string_init("actor", sizeof("actor") - 1, true); zend_declare_typed_property(class_entry, property_actor_name, &property_actor_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_LONG|MAY_BE_NULL)); - zend_string_release(property_actor_name); + zend_string_release_ex(property_actor_name, true); return class_entry; } @@ -416,51 +415,51 @@ static zend_class_entry *register_class_SoapFault(zend_class_entry *class_entry_ zval property_faultstring_default_value; ZVAL_UNDEF(&property_faultstring_default_value); - zend_string *property_faultstring_name = zend_string_init("faultstring", sizeof("faultstring") - 1, 1); + zend_string *property_faultstring_name = zend_string_init("faultstring", sizeof("faultstring") - 1, true); zend_declare_typed_property(class_entry, property_faultstring_name, &property_faultstring_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_faultstring_name); + zend_string_release_ex(property_faultstring_name, true); zval property_faultcode_default_value; ZVAL_NULL(&property_faultcode_default_value); - zend_string *property_faultcode_name = zend_string_init("faultcode", sizeof("faultcode") - 1, 1); + zend_string *property_faultcode_name = zend_string_init("faultcode", sizeof("faultcode") - 1, true); zend_declare_typed_property(class_entry, property_faultcode_name, &property_faultcode_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_faultcode_name); + zend_string_release_ex(property_faultcode_name, true); zval property_faultcodens_default_value; ZVAL_NULL(&property_faultcodens_default_value); - zend_string *property_faultcodens_name = zend_string_init("faultcodens", sizeof("faultcodens") - 1, 1); + zend_string *property_faultcodens_name = zend_string_init("faultcodens", sizeof("faultcodens") - 1, true); zend_declare_typed_property(class_entry, property_faultcodens_name, &property_faultcodens_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_faultcodens_name); + zend_string_release_ex(property_faultcodens_name, true); zval property_faultactor_default_value; ZVAL_NULL(&property_faultactor_default_value); - zend_string *property_faultactor_name = zend_string_init("faultactor", sizeof("faultactor") - 1, 1); + zend_string *property_faultactor_name = zend_string_init("faultactor", sizeof("faultactor") - 1, true); zend_declare_typed_property(class_entry, property_faultactor_name, &property_faultactor_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_faultactor_name); + zend_string_release_ex(property_faultactor_name, true); zval property_detail_default_value; ZVAL_NULL(&property_detail_default_value); - zend_string *property_detail_name = zend_string_init("detail", sizeof("detail") - 1, 1); + zend_string *property_detail_name = zend_string_init("detail", sizeof("detail") - 1, true); zend_declare_typed_property(class_entry, property_detail_name, &property_detail_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ANY)); - zend_string_release(property_detail_name); + zend_string_release_ex(property_detail_name, true); zval property__name_default_value; ZVAL_NULL(&property__name_default_value); - zend_string *property__name_name = zend_string_init("_name", sizeof("_name") - 1, 1); + zend_string *property__name_name = zend_string_init("_name", sizeof("_name") - 1, true); zend_declare_typed_property(class_entry, property__name_name, &property__name_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property__name_name); + zend_string_release_ex(property__name_name, true); zval property_headerfault_default_value; ZVAL_NULL(&property_headerfault_default_value); - zend_string *property_headerfault_name = zend_string_init("headerfault", sizeof("headerfault") - 1, 1); + zend_string *property_headerfault_name = zend_string_init("headerfault", sizeof("headerfault") - 1, true); zend_declare_typed_property(class_entry, property_headerfault_name, &property_headerfault_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ANY)); - zend_string_release(property_headerfault_name); + zend_string_release_ex(property_headerfault_name, true); zval property_lang_default_value; ZVAL_EMPTY_STRING(&property_lang_default_value); - zend_string *property_lang_name = zend_string_init("lang", sizeof("lang") - 1, 1); + zend_string *property_lang_name = zend_string_init("lang", sizeof("lang") - 1, true); zend_declare_typed_property(class_entry, property_lang_name, &property_lang_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_lang_name); + zend_string_release_ex(property_lang_name, true); return class_entry; } @@ -474,39 +473,39 @@ static zend_class_entry *register_class_SoapVar(void) zval property_enc_type_default_value; ZVAL_UNDEF(&property_enc_type_default_value); - zend_string *property_enc_type_name = zend_string_init("enc_type", sizeof("enc_type") - 1, 1); + zend_string *property_enc_type_name = zend_string_init("enc_type", sizeof("enc_type") - 1, true); zend_declare_typed_property(class_entry, property_enc_type_name, &property_enc_type_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_enc_type_name); + zend_string_release_ex(property_enc_type_name, true); zval property_enc_value_default_value; ZVAL_NULL(&property_enc_value_default_value); - zend_string *property_enc_value_name = zend_string_init("enc_value", sizeof("enc_value") - 1, 1); + zend_string *property_enc_value_name = zend_string_init("enc_value", sizeof("enc_value") - 1, true); zend_declare_typed_property(class_entry, property_enc_value_name, &property_enc_value_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ANY)); - zend_string_release(property_enc_value_name); + zend_string_release_ex(property_enc_value_name, true); zval property_enc_stype_default_value; ZVAL_NULL(&property_enc_stype_default_value); - zend_string *property_enc_stype_name = zend_string_init("enc_stype", sizeof("enc_stype") - 1, 1); + zend_string *property_enc_stype_name = zend_string_init("enc_stype", sizeof("enc_stype") - 1, true); zend_declare_typed_property(class_entry, property_enc_stype_name, &property_enc_stype_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_enc_stype_name); + zend_string_release_ex(property_enc_stype_name, true); zval property_enc_ns_default_value; ZVAL_NULL(&property_enc_ns_default_value); - zend_string *property_enc_ns_name = zend_string_init("enc_ns", sizeof("enc_ns") - 1, 1); + zend_string *property_enc_ns_name = zend_string_init("enc_ns", sizeof("enc_ns") - 1, true); zend_declare_typed_property(class_entry, property_enc_ns_name, &property_enc_ns_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_enc_ns_name); + zend_string_release_ex(property_enc_ns_name, true); zval property_enc_name_default_value; ZVAL_NULL(&property_enc_name_default_value); - zend_string *property_enc_name_name = zend_string_init("enc_name", sizeof("enc_name") - 1, 1); + zend_string *property_enc_name_name = zend_string_init("enc_name", sizeof("enc_name") - 1, true); zend_declare_typed_property(class_entry, property_enc_name_name, &property_enc_name_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_enc_name_name); + zend_string_release_ex(property_enc_name_name, true); zval property_enc_namens_default_value; ZVAL_NULL(&property_enc_namens_default_value); - zend_string *property_enc_namens_name = zend_string_init("enc_namens", sizeof("enc_namens") - 1, 1); + zend_string *property_enc_namens_name = zend_string_init("enc_namens", sizeof("enc_namens") - 1, true); zend_declare_typed_property(class_entry, property_enc_namens_name, &property_enc_namens_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_enc_namens_name); + zend_string_release_ex(property_enc_namens_name, true); return class_entry; } @@ -520,10 +519,10 @@ static zend_class_entry *register_class_SoapServer(void) zval property___soap_fault_default_value; ZVAL_NULL(&property___soap_fault_default_value); - zend_string *property___soap_fault_name = zend_string_init("__soap_fault", sizeof("__soap_fault") - 1, 1); + zend_string *property___soap_fault_name = zend_string_init("__soap_fault", sizeof("__soap_fault") - 1, true); zend_string *property___soap_fault_class_SoapFault = zend_string_init("SoapFault", sizeof("SoapFault")-1, 1); zend_declare_typed_property(class_entry, property___soap_fault_name, &property___soap_fault_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property___soap_fault_class_SoapFault, 0, MAY_BE_NULL)); - zend_string_release(property___soap_fault_name); + zend_string_release_ex(property___soap_fault_name, true); return class_entry; } @@ -537,27 +536,27 @@ static zend_class_entry *register_class_SoapClient(void) zval property_uri_default_value; ZVAL_NULL(&property_uri_default_value); - zend_string *property_uri_name = zend_string_init("uri", sizeof("uri") - 1, 1); + zend_string *property_uri_name = zend_string_init("uri", sizeof("uri") - 1, true); zend_declare_typed_property(class_entry, property_uri_name, &property_uri_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_uri_name); + zend_string_release_ex(property_uri_name, true); zval property_style_default_value; ZVAL_NULL(&property_style_default_value); - zend_string *property_style_name = zend_string_init("style", sizeof("style") - 1, 1); + zend_string *property_style_name = zend_string_init("style", sizeof("style") - 1, true); zend_declare_typed_property(class_entry, property_style_name, &property_style_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG|MAY_BE_NULL)); - zend_string_release(property_style_name); + zend_string_release_ex(property_style_name, true); zval property_use_default_value; ZVAL_NULL(&property_use_default_value); - zend_string *property_use_name = zend_string_init("use", sizeof("use") - 1, 1); + zend_string *property_use_name = zend_string_init("use", sizeof("use") - 1, true); zend_declare_typed_property(class_entry, property_use_name, &property_use_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG|MAY_BE_NULL)); - zend_string_release(property_use_name); + zend_string_release_ex(property_use_name, true); zval property_location_default_value; ZVAL_NULL(&property_location_default_value); - zend_string *property_location_name = zend_string_init("location", sizeof("location") - 1, 1); + zend_string *property_location_name = zend_string_init("location", sizeof("location") - 1, true); zend_declare_typed_property(class_entry, property_location_name, &property_location_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_location_name); + zend_string_release_ex(property_location_name, true); zval property_trace_default_value; ZVAL_FALSE(&property_trace_default_value); @@ -565,192 +564,192 @@ static zend_class_entry *register_class_SoapClient(void) zval property_compression_default_value; ZVAL_NULL(&property_compression_default_value); - zend_string *property_compression_name = zend_string_init("compression", sizeof("compression") - 1, 1); + zend_string *property_compression_name = zend_string_init("compression", sizeof("compression") - 1, true); zend_declare_typed_property(class_entry, property_compression_name, &property_compression_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG|MAY_BE_NULL)); - zend_string_release(property_compression_name); + zend_string_release_ex(property_compression_name, true); zval property_sdl_default_value; ZVAL_NULL(&property_sdl_default_value); - zend_string *property_sdl_name = zend_string_init("sdl", sizeof("sdl") - 1, 1); + zend_string *property_sdl_name = zend_string_init("sdl", sizeof("sdl") - 1, true); zend_string *property_sdl_class_Soap_Sdl = zend_string_init("Soap\\Sdl", sizeof("Soap\\Sdl")-1, 1); zend_declare_typed_property(class_entry, property_sdl_name, &property_sdl_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_sdl_class_Soap_Sdl, 0, MAY_BE_NULL)); - zend_string_release(property_sdl_name); + zend_string_release_ex(property_sdl_name, true); zval property_typemap_default_value; ZVAL_NULL(&property_typemap_default_value); - zend_string *property_typemap_name = zend_string_init("typemap", sizeof("typemap") - 1, 1); + zend_string *property_typemap_name = zend_string_init("typemap", sizeof("typemap") - 1, true); zend_declare_typed_property(class_entry, property_typemap_name, &property_typemap_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ARRAY|MAY_BE_NULL)); - zend_string_release(property_typemap_name); + zend_string_release_ex(property_typemap_name, true); zval property_httpsocket_default_value; ZVAL_NULL(&property_httpsocket_default_value); - zend_string *property_httpsocket_name = zend_string_init("httpsocket", sizeof("httpsocket") - 1, 1); + zend_string *property_httpsocket_name = zend_string_init("httpsocket", sizeof("httpsocket") - 1, true); zend_declare_typed_property(class_entry, property_httpsocket_name, &property_httpsocket_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0)); - zend_string_release(property_httpsocket_name); + zend_string_release_ex(property_httpsocket_name, true); zval property_httpurl_default_value; ZVAL_NULL(&property_httpurl_default_value); - zend_string *property_httpurl_name = zend_string_init("httpurl", sizeof("httpurl") - 1, 1); + zend_string *property_httpurl_name = zend_string_init("httpurl", sizeof("httpurl") - 1, true); zend_string *property_httpurl_class_Soap_Url = zend_string_init("Soap\\\125rl", sizeof("Soap\\\125rl")-1, 1); zend_declare_typed_property(class_entry, property_httpurl_name, &property_httpurl_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_httpurl_class_Soap_Url, 0, MAY_BE_NULL)); - zend_string_release(property_httpurl_name); + zend_string_release_ex(property_httpurl_name, true); zval property__login_default_value; ZVAL_NULL(&property__login_default_value); - zend_string *property__login_name = zend_string_init("_login", sizeof("_login") - 1, 1); + zend_string *property__login_name = zend_string_init("_login", sizeof("_login") - 1, true); zend_declare_typed_property(class_entry, property__login_name, &property__login_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property__login_name); + zend_string_release_ex(property__login_name, true); zval property__password_default_value; ZVAL_NULL(&property__password_default_value); - zend_string *property__password_name = zend_string_init("_password", sizeof("_password") - 1, 1); + zend_string *property__password_name = zend_string_init("_password", sizeof("_password") - 1, true); zend_declare_typed_property(class_entry, property__password_name, &property__password_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property__password_name); + zend_string_release_ex(property__password_name, true); zval property__use_digest_default_value; ZVAL_FALSE(&property__use_digest_default_value); - zend_string *property__use_digest_name = zend_string_init("_use_digest", sizeof("_use_digest") - 1, 1); + zend_string *property__use_digest_name = zend_string_init("_use_digest", sizeof("_use_digest") - 1, true); zend_declare_typed_property(class_entry, property__use_digest_name, &property__use_digest_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property__use_digest_name); + zend_string_release_ex(property__use_digest_name, true); zval property__digest_default_value; ZVAL_NULL(&property__digest_default_value); - zend_string *property__digest_name = zend_string_init("_digest", sizeof("_digest") - 1, 1); + zend_string *property__digest_name = zend_string_init("_digest", sizeof("_digest") - 1, true); zend_declare_typed_property(class_entry, property__digest_name, &property__digest_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property__digest_name); + zend_string_release_ex(property__digest_name, true); zval property__proxy_host_default_value; ZVAL_NULL(&property__proxy_host_default_value); - zend_string *property__proxy_host_name = zend_string_init("_proxy_host", sizeof("_proxy_host") - 1, 1); + zend_string *property__proxy_host_name = zend_string_init("_proxy_host", sizeof("_proxy_host") - 1, true); zend_declare_typed_property(class_entry, property__proxy_host_name, &property__proxy_host_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property__proxy_host_name); + zend_string_release_ex(property__proxy_host_name, true); zval property__proxy_port_default_value; ZVAL_NULL(&property__proxy_port_default_value); - zend_string *property__proxy_port_name = zend_string_init("_proxy_port", sizeof("_proxy_port") - 1, 1); + zend_string *property__proxy_port_name = zend_string_init("_proxy_port", sizeof("_proxy_port") - 1, true); zend_declare_typed_property(class_entry, property__proxy_port_name, &property__proxy_port_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG|MAY_BE_NULL)); - zend_string_release(property__proxy_port_name); + zend_string_release_ex(property__proxy_port_name, true); zval property__proxy_login_default_value; ZVAL_NULL(&property__proxy_login_default_value); - zend_string *property__proxy_login_name = zend_string_init("_proxy_login", sizeof("_proxy_login") - 1, 1); + zend_string *property__proxy_login_name = zend_string_init("_proxy_login", sizeof("_proxy_login") - 1, true); zend_declare_typed_property(class_entry, property__proxy_login_name, &property__proxy_login_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property__proxy_login_name); + zend_string_release_ex(property__proxy_login_name, true); zval property__proxy_password_default_value; ZVAL_NULL(&property__proxy_password_default_value); - zend_string *property__proxy_password_name = zend_string_init("_proxy_password", sizeof("_proxy_password") - 1, 1); + zend_string *property__proxy_password_name = zend_string_init("_proxy_password", sizeof("_proxy_password") - 1, true); zend_declare_typed_property(class_entry, property__proxy_password_name, &property__proxy_password_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property__proxy_password_name); + zend_string_release_ex(property__proxy_password_name, true); zval property__exceptions_default_value; ZVAL_TRUE(&property__exceptions_default_value); - zend_string *property__exceptions_name = zend_string_init("_exceptions", sizeof("_exceptions") - 1, 1); + zend_string *property__exceptions_name = zend_string_init("_exceptions", sizeof("_exceptions") - 1, true); zend_declare_typed_property(class_entry, property__exceptions_name, &property__exceptions_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property__exceptions_name); + zend_string_release_ex(property__exceptions_name, true); zval property__encoding_default_value; ZVAL_NULL(&property__encoding_default_value); - zend_string *property__encoding_name = zend_string_init("_encoding", sizeof("_encoding") - 1, 1); + zend_string *property__encoding_name = zend_string_init("_encoding", sizeof("_encoding") - 1, true); zend_declare_typed_property(class_entry, property__encoding_name, &property__encoding_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property__encoding_name); + zend_string_release_ex(property__encoding_name, true); zval property__classmap_default_value; ZVAL_NULL(&property__classmap_default_value); - zend_string *property__classmap_name = zend_string_init("_classmap", sizeof("_classmap") - 1, 1); + zend_string *property__classmap_name = zend_string_init("_classmap", sizeof("_classmap") - 1, true); zend_declare_typed_property(class_entry, property__classmap_name, &property__classmap_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ARRAY|MAY_BE_NULL)); - zend_string_release(property__classmap_name); + zend_string_release_ex(property__classmap_name, true); zval property__features_default_value; ZVAL_NULL(&property__features_default_value); - zend_string *property__features_name = zend_string_init("_features", sizeof("_features") - 1, 1); + zend_string *property__features_name = zend_string_init("_features", sizeof("_features") - 1, true); zend_declare_typed_property(class_entry, property__features_name, &property__features_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG|MAY_BE_NULL)); - zend_string_release(property__features_name); + zend_string_release_ex(property__features_name, true); zval property__connection_timeout_default_value; ZVAL_LONG(&property__connection_timeout_default_value, 0); - zend_string *property__connection_timeout_name = zend_string_init("_connection_timeout", sizeof("_connection_timeout") - 1, 1); + zend_string *property__connection_timeout_name = zend_string_init("_connection_timeout", sizeof("_connection_timeout") - 1, true); zend_declare_typed_property(class_entry, property__connection_timeout_name, &property__connection_timeout_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property__connection_timeout_name); + zend_string_release_ex(property__connection_timeout_name, true); zval property__stream_context_default_value; ZVAL_NULL(&property__stream_context_default_value); - zend_string *property__stream_context_name = zend_string_init("_stream_context", sizeof("_stream_context") - 1, 1); + zend_string *property__stream_context_name = zend_string_init("_stream_context", sizeof("_stream_context") - 1, true); zend_declare_typed_property(class_entry, property__stream_context_name, &property__stream_context_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0)); - zend_string_release(property__stream_context_name); + zend_string_release_ex(property__stream_context_name, true); zval property__user_agent_default_value; ZVAL_NULL(&property__user_agent_default_value); - zend_string *property__user_agent_name = zend_string_init("_user_agent", sizeof("_user_agent") - 1, 1); + zend_string *property__user_agent_name = zend_string_init("_user_agent", sizeof("_user_agent") - 1, true); zend_declare_typed_property(class_entry, property__user_agent_name, &property__user_agent_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property__user_agent_name); + zend_string_release_ex(property__user_agent_name, true); zval property__keep_alive_default_value; ZVAL_TRUE(&property__keep_alive_default_value); - zend_string *property__keep_alive_name = zend_string_init("_keep_alive", sizeof("_keep_alive") - 1, 1); + zend_string *property__keep_alive_name = zend_string_init("_keep_alive", sizeof("_keep_alive") - 1, true); zend_declare_typed_property(class_entry, property__keep_alive_name, &property__keep_alive_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property__keep_alive_name); + zend_string_release_ex(property__keep_alive_name, true); zval property__ssl_method_default_value; ZVAL_NULL(&property__ssl_method_default_value); - zend_string *property__ssl_method_name = zend_string_init("_ssl_method", sizeof("_ssl_method") - 1, 1); + zend_string *property__ssl_method_name = zend_string_init("_ssl_method", sizeof("_ssl_method") - 1, true); zend_declare_typed_property(class_entry, property__ssl_method_name, &property__ssl_method_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG|MAY_BE_NULL)); - zend_string_release(property__ssl_method_name); + zend_string_release_ex(property__ssl_method_name, true); zval property__soap_version_default_value; ZVAL_UNDEF(&property__soap_version_default_value); - zend_string *property__soap_version_name = zend_string_init("_soap_version", sizeof("_soap_version") - 1, 1); + zend_string *property__soap_version_name = zend_string_init("_soap_version", sizeof("_soap_version") - 1, true); zend_declare_typed_property(class_entry, property__soap_version_name, &property__soap_version_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property__soap_version_name); + zend_string_release_ex(property__soap_version_name, true); zval property__use_proxy_default_value; ZVAL_NULL(&property__use_proxy_default_value); - zend_string *property__use_proxy_name = zend_string_init("_use_proxy", sizeof("_use_proxy") - 1, 1); + zend_string *property__use_proxy_name = zend_string_init("_use_proxy", sizeof("_use_proxy") - 1, true); zend_declare_typed_property(class_entry, property__use_proxy_name, &property__use_proxy_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG|MAY_BE_NULL)); - zend_string_release(property__use_proxy_name); + zend_string_release_ex(property__use_proxy_name, true); zval property__cookies_default_value; ZVAL_EMPTY_ARRAY(&property__cookies_default_value); - zend_string *property__cookies_name = zend_string_init("_cookies", sizeof("_cookies") - 1, 1); + zend_string *property__cookies_name = zend_string_init("_cookies", sizeof("_cookies") - 1, true); zend_declare_typed_property(class_entry, property__cookies_name, &property__cookies_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ARRAY)); - zend_string_release(property__cookies_name); + zend_string_release_ex(property__cookies_name, true); zval property___default_headers_default_value; ZVAL_NULL(&property___default_headers_default_value); - zend_string *property___default_headers_name = zend_string_init("__default_headers", sizeof("__default_headers") - 1, 1); + zend_string *property___default_headers_name = zend_string_init("__default_headers", sizeof("__default_headers") - 1, true); zend_declare_typed_property(class_entry, property___default_headers_name, &property___default_headers_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ARRAY|MAY_BE_NULL)); - zend_string_release(property___default_headers_name); + zend_string_release_ex(property___default_headers_name, true); zval property___soap_fault_default_value; ZVAL_NULL(&property___soap_fault_default_value); - zend_string *property___soap_fault_name = zend_string_init("__soap_fault", sizeof("__soap_fault") - 1, 1); + zend_string *property___soap_fault_name = zend_string_init("__soap_fault", sizeof("__soap_fault") - 1, true); zend_string *property___soap_fault_class_SoapFault = zend_string_init("SoapFault", sizeof("SoapFault")-1, 1); zend_declare_typed_property(class_entry, property___soap_fault_name, &property___soap_fault_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property___soap_fault_class_SoapFault, 0, MAY_BE_NULL)); - zend_string_release(property___soap_fault_name); + zend_string_release_ex(property___soap_fault_name, true); zval property___last_request_default_value; ZVAL_NULL(&property___last_request_default_value); - zend_string *property___last_request_name = zend_string_init("__last_request", sizeof("__last_request") - 1, 1); + zend_string *property___last_request_name = zend_string_init("__last_request", sizeof("__last_request") - 1, true); zend_declare_typed_property(class_entry, property___last_request_name, &property___last_request_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property___last_request_name); + zend_string_release_ex(property___last_request_name, true); zval property___last_response_default_value; ZVAL_NULL(&property___last_response_default_value); - zend_string *property___last_response_name = zend_string_init("__last_response", sizeof("__last_response") - 1, 1); + zend_string *property___last_response_name = zend_string_init("__last_response", sizeof("__last_response") - 1, true); zend_declare_typed_property(class_entry, property___last_response_name, &property___last_response_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property___last_response_name); + zend_string_release_ex(property___last_response_name, true); zval property___last_request_headers_default_value; ZVAL_NULL(&property___last_request_headers_default_value); - zend_string *property___last_request_headers_name = zend_string_init("__last_request_headers", sizeof("__last_request_headers") - 1, 1); + zend_string *property___last_request_headers_name = zend_string_init("__last_request_headers", sizeof("__last_request_headers") - 1, true); zend_declare_typed_property(class_entry, property___last_request_headers_name, &property___last_request_headers_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property___last_request_headers_name); + zend_string_release_ex(property___last_request_headers_name, true); zval property___last_response_headers_default_value; ZVAL_NULL(&property___last_response_headers_default_value); - zend_string *property___last_response_headers_name = zend_string_init("__last_response_headers", sizeof("__last_response_headers") - 1, 1); + zend_string *property___last_response_headers_name = zend_string_init("__last_response_headers", sizeof("__last_response_headers") - 1, true); zend_declare_typed_property(class_entry, property___last_response_headers_name, &property___last_response_headers_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property___last_response_headers_name); + zend_string_release_ex(property___last_response_headers_name, true); return class_entry; } 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..dc2437baa9e1f 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(); @@ -42,4 +42,4 @@ echo($client->__getLastResponse()); --EXPECT-- This is our fault: � -TestThis is our fault: Ä +TestThis is our fault: Ä 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/bug68996.phpt b/ext/soap/tests/bugs/bug68996.phpt index bcc0e66cbebf9..8aa858e6545ec 100644 --- a/ext/soap/tests/bugs/bug68996.phpt +++ b/ext/soap/tests/bugs/bug68996.phpt @@ -56,4 +56,4 @@ handleFormatted($s, $HTTP_RAW_POST_DATA); some msg -some msg +some msg 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/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/gh20011.phpt b/ext/soap/tests/bugs/gh20011.phpt new file mode 100644 index 0000000000000..7cccc76192128 --- /dev/null +++ b/ext/soap/tests/bugs/gh20011.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-20011 (Array of SoapVar of unknown type causes crash) +--EXTENSIONS-- +soap +--FILE-- + 'test://', 'uri' => 'http://soapinterop.org/']); +$client->echoStringArray($array); +?> +--EXPECT-- + +test string 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/soap12/T63.phpt b/ext/soap/tests/soap12/T63.phpt index a8cf3c431b24b..810207e50ee50 100644 --- a/ext/soap/tests/soap12/T63.phpt +++ b/ext/soap/tests/soap12/T63.phpt @@ -21,5 +21,5 @@ include "soap12-test.inc"; ?> --EXPECT-- -Country code must be 2 letters.env:SenderNot a valid country code +Country code must be 2 letters.env:SenderNot a valid country code ok diff --git a/ext/soap/tests/soap_qname_crash.phpt b/ext/soap/tests/soap_qname_crash.phpt index bcf01d574fab4..53d6904db1c95 100644 --- a/ext/soap/tests/soap_qname_crash.phpt +++ b/ext/soap/tests/soap_qname_crash.phpt @@ -18,6 +18,7 @@ class TestSoapClient extends SoapClient { $action, $version, $one_way = false, + ?string $uriParserClass = null, ): ?string { die($request); } diff --git a/ext/soap/tests/soap_set_cookie.phpt b/ext/soap/tests/soap_set_cookie.phpt new file mode 100644 index 0000000000000..a23aa18bb4b75 --- /dev/null +++ b/ext/soap/tests/soap_set_cookie.phpt @@ -0,0 +1,22 @@ +--TEST-- +SoapClient::__setCookie with numeric keys +--EXTENSIONS-- +soap +--FILE-- + 'mo:http://www.w3.org/', 'location' => 'http://example.com/')); +$client->__setCookie("123", "456"); +var_dump($client->__getCookies()); +$client->__setCookie("123", NULL); +var_dump($client->__getCookies()); +?> +--EXPECT-- +array(1) { + [123]=> + array(1) { + [0]=> + string(3) "456" + } +} +array(0) { +} 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-- #endif @@ -109,7 +110,9 @@ ZEND_DECLARE_MODULE_GLOBALS(sockets) } \ } while (0) #else -#define PHP_ETH_PROTO_CHECK(protocol, family) (0) +#define PHP_ETH_PROTO_CHECK(protocol, family) \ + (void)protocol; \ + (void)family #endif static PHP_GINIT_FUNCTION(sockets); @@ -248,7 +251,7 @@ static bool php_open_listen_sock(php_socket *sock, unsigned short port, int back #else if ((hp = php_network_gethostbyname("localhost")) == NULL) { #endif - return 0; + return false; } memcpy((char *) &la.sin_addr, hp->h_addr, hp->h_length); @@ -260,7 +263,7 @@ static bool php_open_listen_sock(php_socket *sock, unsigned short port, int back if (IS_INVALID_SOCKET(sock)) { PHP_SOCKET_ERROR(sock, "unable to create listening socket", errno); - return 0; + return false; } sock->type = PF_INET; @@ -268,38 +271,51 @@ static bool php_open_listen_sock(php_socket *sock, unsigned short port, int back if (bind(sock->bsd_socket, (struct sockaddr *)&la, sizeof(la)) != 0) { PHP_SOCKET_ERROR(sock, "unable to bind to given address", errno); close(sock->bsd_socket); - return 0; + return false; } if (listen(sock->bsd_socket, backlog) != 0) { PHP_SOCKET_ERROR(sock, "unable to listen on socket", errno); close(sock->bsd_socket); - return 0; + return false; } - return 1; + return true; } /* }}} */ static bool php_accept_connect(php_socket *in_sock, php_socket *out_sock, struct sockaddr *la, socklen_t *la_len) /* {{{ */ { +#if defined(HAVE_ACCEPT4) + int flags = SOCK_CLOEXEC; + if (!in_sock->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 false; + } +#else out_sock->bsd_socket = accept(in_sock->bsd_socket, la, la_len); if (IS_INVALID_SOCKET(out_sock)) { PHP_SOCKET_ERROR(out_sock, "unable to accept incoming connection", errno); - return 0; + return false; } #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; if ((mode = fcntl(out_sock->bsd_socket, F_GETFD)) < 0) { PHP_SOCKET_ERROR(out_sock, "unable to get fcntl mode on the socket", errno); - return 0; + return false; } int cloexec = (mode | FD_CLOEXEC); @@ -307,16 +323,17 @@ static bool php_accept_connect(php_socket *in_sock, php_socket *out_sock, struct if (mode != cloexec) { if (fcntl(out_sock->bsd_socket, F_SETFD, cloexec) < 0) { PHP_SOCKET_ERROR(out_sock, "unable to set cloexec mode on the socket", errno); - return 0; + return false; } } +#endif #endif out_sock->error = 0; out_sock->blocking = 1; out_sock->type = la->sa_family; - return 1; + return true; } /* }}} */ @@ -1564,7 +1581,11 @@ PHP_FUNCTION(socket_recvfrom) if (arg6 == NULL) { zend_string_efree(recv_buf); - WRONG_PARAM_COUNT; + zend_throw_exception( + zend_ce_argument_count_error, + "socket_recvfrom() expects exactly 6 arguments when argument #1 ($socket) is of type AF_INET or AF_INET6", + 0); + RETURN_THROWS(); } retval = recvfrom(php_sock->bsd_socket, ZSTR_VAL(recv_buf), arg3, arg4, (struct sockaddr *)&sin, (socklen_t *)&slen); @@ -1591,7 +1612,11 @@ PHP_FUNCTION(socket_recvfrom) if (arg6 == NULL) { zend_string_efree(recv_buf); - WRONG_PARAM_COUNT; + zend_throw_exception( + zend_ce_argument_count_error, + "socket_recvfrom() expects exactly 6 arguments when argument #1 ($socket) is of type AF_INET or AF_INET6", + 0); + RETURN_THROWS(); } retval = recvfrom(php_sock->bsd_socket, ZSTR_VAL(recv_buf), arg3, arg4, (struct sockaddr *)&sin6, (socklen_t *)&slen); @@ -1748,7 +1773,7 @@ PHP_FUNCTION(socket_sendto) RETURN_THROWS(); } - memset(&sll, 0, sizeof(sll)); + memset(&sll, 0, sizeof(sll)); sll.sll_family = AF_PACKET; sll.sll_ifindex = port; @@ -2105,6 +2130,28 @@ PHP_FUNCTION(socket_set_option) } #endif +#if defined(TCP_USER_TIMEOUT) + case TCP_USER_TIMEOUT: { + zend_long timeout = zval_get_long(arg4); + + // TCP_USER_TIMEOUT unsigned int + if (timeout < 0 || timeout > UINT_MAX) { + zend_argument_value_error(4, "must be of between 0 and %u", UINT_MAX); + RETURN_THROWS(); + } + + unsigned int val = (unsigned int)timeout; + optlen = sizeof(val); + opt_ptr = &val; + if (setsockopt(php_sock->bsd_socket, level, optname, opt_ptr, optlen) != 0) { + PHP_SOCKET_ERROR(php_sock, "Unable to set socket option", errno); + RETURN_FALSE; + } + + RETURN_TRUE; + } +#endif + } } @@ -2541,7 +2588,7 @@ bool socket_import_file_descriptor(PHP_SOCKET socket, php_socket *retsock) retsock->type = addr.ss_family; } else { PHP_SOCKET_ERROR(retsock, "Unable to obtain socket family", errno); - return 0; + return false; } /* determine blocking mode */ @@ -2549,13 +2596,13 @@ bool socket_import_file_descriptor(PHP_SOCKET socket, php_socket *retsock) t = fcntl(socket, F_GETFL); if (t == -1) { PHP_SOCKET_ERROR(retsock, "Unable to obtain blocking state", errno); - return 0; + return false; } else { retsock->blocking = !(t & O_NONBLOCK); } #endif - return 1; + return true; } /* {{{ Imports a stream that encapsulates a socket into a socket extension resource. */ @@ -2571,7 +2618,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; } diff --git a/ext/sockets/sockets.stub.php b/ext/sockets/sockets.stub.php index 6050a89414565..04fb702807e0a 100644 --- a/ext/sockets/sockets.stub.php +++ b/ext/sockets/sockets.stub.php @@ -602,6 +602,13 @@ */ const TCP_SYNCNT = UNKNOWN; #endif +#ifdef TCP_USER_TIMEOUT +/** + * @var int + * @cvalue TCP_USER_TIMEOUT + */ +const TCP_USER_TIMEOUT = UNKNOWN; +#endif #ifdef SO_ZEROCOPY /** * @var int @@ -643,11 +650,15 @@ * @cvalue TCP_KEEPIDLE */ const TCP_KEEPIDLE = UNKNOWN; +#endif +#ifdef TCP_KEEPINTVL /** * @var int * @cvalue TCP_KEEPINTVL */ const TCP_KEEPINTVL = UNKNOWN; +#endif +#ifdef TCP_KEEPCNT /** * @var int * @cvalue TCP_KEEPCNT diff --git a/ext/sockets/sockets_arginfo.h b/ext/sockets/sockets_arginfo.h index b7af6eb6b89ac..0145d01252881 100644 --- a/ext/sockets/sockets_arginfo.h +++ b/ext/sockets/sockets_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 7b1baf47dce2fb08faa5616068238ea078d1609b */ + * Stub hash: 038081ca7bb98076d4b559d93b4c9300acc47160 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_select, 0, 4, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(1, read, IS_ARRAY, 1) @@ -527,6 +527,9 @@ static void register_sockets_symbols(int module_number) #if defined(TCP_SYNCNT) REGISTER_LONG_CONSTANT("TCP_SYNCNT", TCP_SYNCNT, CONST_PERSISTENT); #endif +#if defined(TCP_USER_TIMEOUT) + REGISTER_LONG_CONSTANT("TCP_USER_TIMEOUT", TCP_USER_TIMEOUT, CONST_PERSISTENT); +#endif #if defined(SO_ZEROCOPY) REGISTER_LONG_CONSTANT("SO_ZEROCOPY", SO_ZEROCOPY, CONST_PERSISTENT); #endif @@ -544,7 +547,11 @@ static void register_sockets_symbols(int module_number) #endif #if defined(TCP_KEEPIDLE) REGISTER_LONG_CONSTANT("TCP_KEEPIDLE", TCP_KEEPIDLE, CONST_PERSISTENT); +#endif +#if defined(TCP_KEEPINTVL) REGISTER_LONG_CONSTANT("TCP_KEEPINTVL", TCP_KEEPINTVL, CONST_PERSISTENT); +#endif +#if defined(TCP_KEEPCNT) REGISTER_LONG_CONSTANT("TCP_KEEPCNT", TCP_KEEPCNT, CONST_PERSISTENT); #endif #if defined(TCP_FUNCTION_BLK) 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_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/sockets/tests/socket_recvfrom_ipv4_missing_port_arg.phpt b/ext/sockets/tests/socket_recvfrom_ipv4_missing_port_arg.phpt new file mode 100644 index 0000000000000..0554818fb67c8 --- /dev/null +++ b/ext/sockets/tests/socket_recvfrom_ipv4_missing_port_arg.phpt @@ -0,0 +1,17 @@ +--TEST-- +socket_recvfrom() with IPv4 socket missing port argument +--EXTENSIONS-- +sockets +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +ArgumentCountError: socket_recvfrom() expects exactly 6 arguments when argument #1 ($socket) is of type AF_INET or AF_INET6 diff --git a/ext/sockets/tests/socket_recvfrom_ipv6_missing_port_arg.phpt b/ext/sockets/tests/socket_recvfrom_ipv6_missing_port_arg.phpt new file mode 100644 index 0000000000000..957751a949763 --- /dev/null +++ b/ext/sockets/tests/socket_recvfrom_ipv6_missing_port_arg.phpt @@ -0,0 +1,21 @@ +--TEST-- +socket_recvfrom() with IPv6 socket missing port argument +--EXTENSIONS-- +sockets +--SKIPIF-- + +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +ArgumentCountError: socket_recvfrom() expects exactly 6 arguments when argument #1 ($socket) is of type AF_INET or AF_INET6 diff --git a/ext/sockets/tests/socket_setoption_tcpusertimeout_32bit.phpt b/ext/sockets/tests/socket_setoption_tcpusertimeout_32bit.phpt new file mode 100644 index 0000000000000..3f12120e54d89 --- /dev/null +++ b/ext/sockets/tests/socket_setoption_tcpusertimeout_32bit.phpt @@ -0,0 +1,34 @@ +--TEST-- +Test if socket_set_option() works, option:TCP_USER_TIMEOUT +--EXTENSIONS-- +sockets +--SKIPIF-- + +--FILE-- +getMessage(), PHP_EOL; +} + +$timeout = 200; +$retval_2 = socket_set_option($socket, SOL_TCP, TCP_USER_TIMEOUT, $timeout); +$retval_3 = socket_get_option($socket, SOL_TCP, TCP_USER_TIMEOUT); +var_dump($retval_2); +var_dump($retval_3 === $timeout); +socket_close($socket); +?> +--EXPECTF-- +socket_setopt(): Argument #4 ($value) must be of between 0 and %d +bool(true) +bool(true) diff --git a/ext/sockets/tests/socket_setoption_tcpusertimeout_64bit.phpt b/ext/sockets/tests/socket_setoption_tcpusertimeout_64bit.phpt new file mode 100644 index 0000000000000..8dbb7f80e48b1 --- /dev/null +++ b/ext/sockets/tests/socket_setoption_tcpusertimeout_64bit.phpt @@ -0,0 +1,41 @@ +--TEST-- +Test if socket_set_option() works, option:TCP_USER_TIMEOUT +--EXTENSIONS-- +sockets +--SKIPIF-- + +--FILE-- +getMessage(), PHP_EOL; +} + +try { + socket_setopt($socket, SOL_TCP, TCP_USER_TIMEOUT, PHP_INT_MAX); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} + +$timeout = 200; +$retval_2 = socket_set_option($socket, SOL_TCP, TCP_USER_TIMEOUT, $timeout); +$retval_3 = socket_get_option($socket, SOL_TCP, TCP_USER_TIMEOUT); +var_dump($retval_2); +var_dump($retval_3 === $timeout); +socket_close($socket); +?> +--EXPECTF-- +socket_setopt(): Argument #4 ($value) must be of between 0 and %d +socket_setopt(): Argument #4 ($value) must be of between 0 and %d +bool(true) +bool(true) diff --git a/ext/sockets/tests/socket_tcp_keepalive.phpt b/ext/sockets/tests/socket_tcp_keepalive.phpt new file mode 100644 index 0000000000000..cef570dc62b2b --- /dev/null +++ b/ext/sockets/tests/socket_tcp_keepalive.phpt @@ -0,0 +1,52 @@ +--TEST-- +Test SO_KEEPALIVE and TCP keepalive constants +--EXTENSIONS-- +sockets +--SKIPIF-- + +--FILE-- + +--EXPECT-- +SO_KEEPALIVE: enabled +TCP_KEEPIDLE: 60 +TCP_KEEPINTVL: 10 +TCP_KEEPCNT: 5 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.c b/ext/sodium/sodium_pwhash.c index eea7fe9eb0f1d..32e4f72634c38 100644 --- a/ext/sodium/sodium_pwhash.c +++ b/ext/sodium/sodium_pwhash.c @@ -87,7 +87,7 @@ static zend_string *php_sodium_argon2_hash(const zend_string *password, zend_arr static bool php_sodium_argon2_verify(const zend_string *password, const zend_string *hash) { if ((ZSTR_LEN(password) >= 0xffffffff) || (ZSTR_LEN(hash) >= 0xffffffff)) { - return 0; + return false; } return crypto_pwhash_str_verify(ZSTR_VAL(hash), ZSTR_VAL(password), ZSTR_LEN(password)) == 0; } @@ -96,7 +96,7 @@ static bool php_sodium_argon2_needs_rehash(const zend_string *hash, zend_array * size_t opslimit, memlimit; if (get_options(options, &memlimit, &opslimit) == FAILURE) { - return 1; + return true; } return crypto_pwhash_str_needs_rehash(ZSTR_VAL(hash), opslimit, memlimit); } 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 e6134c94b721d..0acfcbc5c16d0 100644 --- a/ext/spl/php_spl.c +++ b/ext/spl/php_spl.c @@ -66,7 +66,7 @@ PHP_FUNCTION(class_parents) { zval *obj; zend_class_entry *parent_class, *ce; - bool autoload = 1; + bool autoload = true; /* We do not use Z_PARAM_OBJ_OR_STR here to be able to exclude int, float, and bool which are bogus class names */ if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|b", &obj, &autoload) == FAILURE) { @@ -99,7 +99,7 @@ PHP_FUNCTION(class_parents) PHP_FUNCTION(class_implements) { zval *obj; - bool autoload = 1; + bool autoload = true; zend_class_entry *ce; /* We do not use Z_PARAM_OBJ_OR_STR here to be able to exclude int, float, and bool which are bogus class names */ @@ -128,7 +128,7 @@ PHP_FUNCTION(class_implements) PHP_FUNCTION(class_uses) { zval *obj; - bool autoload = 1; + bool autoload = true; zend_class_entry *ce; /* We do not use Z_PARAM_OBJ_OR_STR here to be able to exclude int, float, and bool which are bogus class names */ @@ -216,9 +216,7 @@ PHP_FUNCTION(class_uses) /* {{{ Return an array containing the names of all classes and interfaces defined in SPL */ PHP_FUNCTION(spl_classes) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); array_init(return_value); @@ -582,6 +580,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); @@ -612,9 +617,7 @@ PHP_FUNCTION(spl_autoload_functions) { autoload_func_info *alfi; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); array_init(return_value); if (spl_autoload_functions) { diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 5cb3e27bbb861..3d6870a7ee953 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: @@ -620,13 +621,13 @@ static bool spl_array_has_dimension_ex(bool check_inherited, zend_object *object if (!zend_is_true(&rv)) { zval_ptr_dtor(&rv); - return 0; + return false; } zval_ptr_dtor(&rv); /* For isset calls we don't need to check the value, so return early */ if (!check_empty) { - return 1; + return true; } else if (intern->fptr_offset_get) { value = spl_array_read_dimension_ex(1, object, offset, BP_VAR_R, &rv); } @@ -638,7 +639,7 @@ static bool spl_array_has_dimension_ex(bool check_inherited, zend_object *object if (get_hash_key(&key, intern, offset) == FAILURE) { zend_illegal_container_offset(object->ce->name, offset, BP_VAR_IS); - return 0; + return false; } if (key.key) { @@ -649,13 +650,13 @@ static bool spl_array_has_dimension_ex(bool check_inherited, zend_object *object } if (!tmp) { - return 0; + return false; } /* check_empty is only equal to 2 if it is called from offsetExists on this class, * where it needs to report an offset exists even if the value is null */ if (check_empty == 2) { - return 1; + return true; } if (check_empty && check_inherited && intern->fptr_offset_get) { @@ -752,9 +753,7 @@ PHP_METHOD(ArrayObject, getArrayCopy) zval *object = ZEND_THIS; spl_array_object *intern = Z_SPLARRAY_P(object); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_ARR(zend_array_dup(spl_array_get_hash_table(intern))); } /* }}} */ @@ -776,11 +775,11 @@ static HashTable *spl_array_get_properties_for(zend_object *object, zend_prop_pu * meantime. */ switch (purpose) { case ZEND_PROP_PURPOSE_ARRAY_CAST: - dup = 1; + dup = true; break; case ZEND_PROP_PURPOSE_VAR_EXPORT: case ZEND_PROP_PURPOSE_JSON: - dup = 0; + dup = false; break; default: return zend_std_get_properties_for(object, purpose); @@ -874,7 +873,7 @@ static zval *spl_array_get_property_ptr_ptr(zend_object *object, zend_string *na return NULL; } ZVAL_STR(&member, name); - return spl_array_get_dimension_ptr(1, intern, object->ce->name, &member, type); + return spl_array_get_dimension_ptr(true, intern, object->ce->name, &member, type); } return zend_std_get_property_ptr_ptr(object, name, type, cache_slot); } /* }}} */ @@ -984,6 +983,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) { @@ -1079,9 +1084,7 @@ PHP_METHOD(ArrayObject, getIteratorClass) zval *object = ZEND_THIS; spl_array_object *intern = Z_SPLARRAY_P(object); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); zend_string_addref(intern->ce_get_iterator->name); RETURN_STR(intern->ce_get_iterator->name); @@ -1094,9 +1097,7 @@ PHP_METHOD(ArrayObject, getFlags) zval *object = ZEND_THIS; spl_array_object *intern = Z_SPLARRAY_P(object); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_LONG(intern->ar_flags & ~SPL_ARRAY_INT_MASK); } @@ -1133,7 +1134,7 @@ PHP_METHOD(ArrayObject, exchangeArray) } RETVAL_ARR(zend_array_dup(spl_array_get_hash_table(intern))); - spl_array_set_array(object, intern, array, 0L, 1); + spl_array_set_array(object, intern, array, 0L, true); } /* }}} */ @@ -1143,9 +1144,7 @@ PHP_METHOD(ArrayObject, getIterator) zval *object = ZEND_THIS; spl_array_object *intern = Z_SPLARRAY_P(object); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_OBJ(spl_array_object_new_ex(intern->ce_get_iterator, Z_OBJ_P(object), 0)); } @@ -1196,9 +1195,7 @@ PHP_METHOD(ArrayObject, count) { spl_array_object *intern = Z_SPLARRAY_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_LONG(spl_array_object_count_elements_helper(intern)); } /* }}} */ @@ -1298,9 +1295,7 @@ PHP_METHOD(ArrayObject, serialize) php_serialize_data_t var_hash; smart_str buf = {0}; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHP_VAR_SERIALIZE_INIT(var_hash); @@ -1406,7 +1401,7 @@ PHP_METHOD(ArrayObject, unserialize) ZVAL_NULL(array); SEPARATE_ARRAY(&intern->array); } else { - spl_array_set_array(object, intern, array, 0L, 1); + spl_array_set_array(object, intern, array, 0L, true); } if (*p != ';') { @@ -1446,9 +1441,7 @@ PHP_METHOD(ArrayObject, __serialize) spl_array_object *intern = Z_SPLARRAY_P(ZEND_THIS); zval tmp; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); array_init(return_value); @@ -1519,7 +1512,7 @@ PHP_METHOD(ArrayObject, __unserialize) zend_throw_exception(spl_ce_InvalidArgumentException, "Passed variable is not an array or object", 0); RETURN_THROWS(); } - spl_array_set_array(ZEND_THIS, intern, storage_zv, 0L, 1); + spl_array_set_array(ZEND_THIS, intern, storage_zv, 0L, true); } object_properties_load(&intern->std, Z_ARRVAL_P(members_zv)); @@ -1552,9 +1545,7 @@ PHP_METHOD(ArrayObject, __unserialize) /* {{{ */ PHP_METHOD(ArrayObject, __debugInfo) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_ARR(spl_array_get_debug_info(Z_OBJ_P(ZEND_THIS))); } /* }}} */ @@ -1732,9 +1723,7 @@ PHP_METHOD(ArrayIterator, rewind) zval *object = ZEND_THIS; spl_array_object *intern = Z_SPLARRAY_P(object); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); spl_array_rewind(intern); } @@ -1776,9 +1765,7 @@ PHP_METHOD(ArrayIterator, current) zval *entry; HashTable *aht = spl_array_get_hash_table(intern); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); if ((entry = zend_hash_get_current_data_ex(aht, spl_array_get_pos_ptr(aht, intern))) == NULL) { RETURN_NULL(); @@ -1805,9 +1792,7 @@ void spl_array_iterator_key(zval *object, zval *return_value) /* {{{ */ /* {{{ Return current array key */ PHP_METHOD(ArrayIterator, key) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); spl_array_iterator_key(ZEND_THIS, return_value); } /* }}} */ @@ -1819,9 +1804,7 @@ PHP_METHOD(ArrayIterator, next) spl_array_object *intern = Z_SPLARRAY_P(object); HashTable *aht = spl_array_get_hash_table(intern); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); spl_array_next_ex(intern, aht); } @@ -1834,9 +1817,7 @@ PHP_METHOD(ArrayIterator, valid) spl_array_object *intern = Z_SPLARRAY_P(object); HashTable *aht = spl_array_get_hash_table(intern); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_BOOL(zend_hash_has_more_elements_ex(aht, spl_array_get_pos_ptr(aht, intern)) == SUCCESS); } @@ -1851,9 +1832,7 @@ PHP_METHOD(RecursiveArrayIterator, hasChildren) spl_array_object *intern = Z_SPLARRAY_P(object); HashTable *aht = spl_array_get_hash_table(intern); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); if ((entry = zend_hash_get_current_data_ex(aht, spl_array_get_pos_ptr(aht, intern))) == NULL) { RETURN_FALSE; @@ -1891,9 +1870,7 @@ PHP_METHOD(RecursiveArrayIterator, getChildren) spl_array_object *intern = Z_SPLARRAY_P(object); HashTable *aht = spl_array_get_hash_table(intern); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); if ((entry = zend_hash_get_current_data_ex(aht, spl_array_get_pos_ptr(aht, intern))) == NULL) { RETURN_NULL(); diff --git a/ext/spl/spl_array_arginfo.h b/ext/spl/spl_array_arginfo.h index 24dcadac661c8..da3b7ddb8c909 100644 --- a/ext/spl/spl_array_arginfo.h +++ b/ext/spl/spl_array_arginfo.h @@ -264,15 +264,15 @@ static zend_class_entry *register_class_ArrayObject(zend_class_entry *class_entr zval const_STD_PROP_LIST_value; ZVAL_LONG(&const_STD_PROP_LIST_value, SPL_ARRAY_STD_PROP_LIST); - zend_string *const_STD_PROP_LIST_name = zend_string_init_interned("STD_PROP_LIST", sizeof("STD_PROP_LIST") - 1, 1); + zend_string *const_STD_PROP_LIST_name = zend_string_init_interned("STD_PROP_LIST", sizeof("STD_PROP_LIST") - 1, true); zend_declare_typed_class_constant(class_entry, const_STD_PROP_LIST_name, &const_STD_PROP_LIST_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_STD_PROP_LIST_name); + zend_string_release_ex(const_STD_PROP_LIST_name, true); zval const_ARRAY_AS_PROPS_value; ZVAL_LONG(&const_ARRAY_AS_PROPS_value, SPL_ARRAY_ARRAY_AS_PROPS); - zend_string *const_ARRAY_AS_PROPS_name = zend_string_init_interned("ARRAY_AS_PROPS", sizeof("ARRAY_AS_PROPS") - 1, 1); + zend_string *const_ARRAY_AS_PROPS_name = zend_string_init_interned("ARRAY_AS_PROPS", sizeof("ARRAY_AS_PROPS") - 1, true); zend_declare_typed_class_constant(class_entry, const_ARRAY_AS_PROPS_name, &const_ARRAY_AS_PROPS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ARRAY_AS_PROPS_name); + zend_string_release_ex(const_ARRAY_AS_PROPS_name, true); return class_entry; } @@ -287,15 +287,15 @@ static zend_class_entry *register_class_ArrayIterator(zend_class_entry *class_en zval const_STD_PROP_LIST_value; ZVAL_LONG(&const_STD_PROP_LIST_value, SPL_ARRAY_STD_PROP_LIST); - zend_string *const_STD_PROP_LIST_name = zend_string_init_interned("STD_PROP_LIST", sizeof("STD_PROP_LIST") - 1, 1); + zend_string *const_STD_PROP_LIST_name = zend_string_init_interned("STD_PROP_LIST", sizeof("STD_PROP_LIST") - 1, true); zend_declare_typed_class_constant(class_entry, const_STD_PROP_LIST_name, &const_STD_PROP_LIST_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_STD_PROP_LIST_name); + zend_string_release_ex(const_STD_PROP_LIST_name, true); zval const_ARRAY_AS_PROPS_value; ZVAL_LONG(&const_ARRAY_AS_PROPS_value, SPL_ARRAY_ARRAY_AS_PROPS); - zend_string *const_ARRAY_AS_PROPS_name = zend_string_init_interned("ARRAY_AS_PROPS", sizeof("ARRAY_AS_PROPS") - 1, 1); + zend_string *const_ARRAY_AS_PROPS_name = zend_string_init_interned("ARRAY_AS_PROPS", sizeof("ARRAY_AS_PROPS") - 1, true); zend_declare_typed_class_constant(class_entry, const_ARRAY_AS_PROPS_name, &const_ARRAY_AS_PROPS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ARRAY_AS_PROPS_name); + zend_string_release_ex(const_ARRAY_AS_PROPS_name, true); return class_entry; } @@ -310,9 +310,9 @@ static zend_class_entry *register_class_RecursiveArrayIterator(zend_class_entry zval const_CHILD_ARRAYS_ONLY_value; ZVAL_LONG(&const_CHILD_ARRAYS_ONLY_value, SPL_ARRAY_CHILD_ARRAYS_ONLY); - zend_string *const_CHILD_ARRAYS_ONLY_name = zend_string_init_interned("CHILD_ARRAYS_ONLY", sizeof("CHILD_ARRAYS_ONLY") - 1, 1); + zend_string *const_CHILD_ARRAYS_ONLY_name = zend_string_init_interned("CHILD_ARRAYS_ONLY", sizeof("CHILD_ARRAYS_ONLY") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHILD_ARRAYS_ONLY_name, &const_CHILD_ARRAYS_ONLY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHILD_ARRAYS_ONLY_name); + zend_string_release_ex(const_CHILD_ARRAYS_ONLY_name, true); return class_entry; } diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 8c59e9624a332..86e4b11334c81 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; } } /* }}} */ @@ -295,6 +292,11 @@ static void spl_filesystem_dir_open(spl_filesystem_object* intern, zend_string * intern->type = SPL_FS_DIR; intern->u.dir.dirp = php_stream_opendir(ZSTR_VAL(path), REPORT_ERRORS, FG(default_context)); + if (intern->u.dir.dirp) { + /* we prevent potential UAF with conflicting explicit fclose(), relying on the object destructor for this */ + intern->u.dir.dirp->flags |= PHP_STREAM_FLAG_NO_FCLOSE; + } + if (ZSTR_LEN(path) > 1 && IS_SLASH_AT(ZSTR_VAL(path), ZSTR_LEN(path)-1)) { intern->path = zend_string_init(ZSTR_VAL(path), ZSTR_LEN(path)-1, 0); } else { @@ -412,7 +414,7 @@ static zend_object *spl_filesystem_object_clone(zend_object *old_object) spl_filesystem_dir_open(intern, source->path); /* read until we hit the position in which we were before */ bool skip_dots = SPL_HAS_FLAG(source->flags, SPL_FILE_DIR_SKIPDOTS); - int index; + zend_long index; for (index = 0; index < source->u.dir.index; ++index) { do { spl_filesystem_dir_read(intern); @@ -483,9 +485,8 @@ static spl_filesystem_object *spl_filesystem_object_create_info(zend_string *fil RETVAL_OBJ(&intern->std); if (ce->constructor->common.scope != spl_ce_SplFileInfo) { - ZVAL_STR_COPY(&arg1, file_path); + ZVAL_STR(&arg1, file_path); zend_call_method_with_1_params(Z_OBJ_P(return_value), ce, &ce->constructor, "__construct", NULL, &arg1); - zval_ptr_dtor(&arg1); } else { spl_filesystem_info_set_filename(intern, file_path); } @@ -496,7 +497,7 @@ static spl_filesystem_object *spl_filesystem_object_create_info(zend_string *fil static spl_filesystem_object *spl_filesystem_object_create_type(int num_args, spl_filesystem_object *source, int type, zend_class_entry *ce, zval *return_value) /* {{{ */ { spl_filesystem_object *intern; - bool use_include_path = 0; + bool use_include_path = false; zval arg1, arg2; zend_error_handling error_handling; @@ -523,9 +524,8 @@ static spl_filesystem_object *spl_filesystem_object_create_type(int num_args, sp } if (ce->constructor->common.scope != spl_ce_SplFileInfo) { - ZVAL_STR_COPY(&arg1, source->file_name); + ZVAL_STR(&arg1, source->file_name); zend_call_method_with_1_params(Z_OBJ_P(return_value), ce, &ce->constructor, "__construct", NULL, &arg1); - zval_ptr_dtor(&arg1); } else { intern->file_name = zend_string_copy(source->file_name); intern->path = spl_filesystem_object_get_path(source); @@ -552,11 +552,9 @@ static spl_filesystem_object *spl_filesystem_object_create_type(int num_args, sp } if (ce->constructor->common.scope != spl_ce_SplFileObject) { - ZVAL_STR_COPY(&arg1, source->file_name); - ZVAL_STR_COPY(&arg2, open_mode); + ZVAL_STR(&arg1, source->file_name); + ZVAL_STR(&arg2, open_mode); zend_call_method_with_2_params(Z_OBJ_P(return_value), ce, &ce->constructor, "__construct", NULL, &arg1, &arg2); - zval_ptr_dtor(&arg1); - zval_ptr_dtor(&arg2); } else { intern->file_name = source->file_name; intern->path = spl_filesystem_object_get_path(source); @@ -740,9 +738,7 @@ PHP_METHOD(DirectoryIterator, rewind) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(intern); intern->u.dir.index = 0; @@ -756,9 +752,7 @@ PHP_METHOD(DirectoryIterator, key) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(intern); RETURN_LONG(intern->u.dir.index); @@ -768,9 +762,7 @@ PHP_METHOD(DirectoryIterator, key) /* {{{ Return this (needed for Iterator interface) */ PHP_METHOD(DirectoryIterator, current) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS))); RETURN_OBJ_COPY(Z_OBJ_P(ZEND_THIS)); @@ -783,9 +775,7 @@ PHP_METHOD(DirectoryIterator, next) spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); bool skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(intern); intern->u.dir.index++; @@ -834,9 +824,7 @@ PHP_METHOD(DirectoryIterator, valid) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(intern); RETURN_BOOL(intern->u.dir.entry.d_name[0] != '\0'); @@ -849,9 +837,7 @@ PHP_METHOD(SplFileInfo, getPath) spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); zend_string *path; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); path = spl_filesystem_object_get_path(intern); if (path) { @@ -868,9 +854,7 @@ PHP_METHOD(SplFileInfo, getFilename) spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); zend_string *path; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); if (!intern->file_name) { zend_throw_error(NULL, "Object not initialized"); @@ -897,9 +881,7 @@ PHP_METHOD(DirectoryIterator, getFilename) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(intern); RETURN_STRING(intern->u.dir.entry.d_name); @@ -917,9 +899,7 @@ PHP_METHOD(SplFileInfo, getExtension) size_t idx; zend_string *ret; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); if (!intern->file_name) { zend_throw_error(NULL, "Object not initialized"); @@ -962,9 +942,7 @@ PHP_METHOD(DirectoryIterator, getExtension) size_t idx; zend_string *fname; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(intern); fname = php_basename(intern->u.dir.entry.d_name, strlen(intern->u.dir.entry.d_name), NULL, 0); @@ -1042,9 +1020,7 @@ PHP_METHOD(SplFileInfo, getPathname) spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); zend_string *path; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); path = spl_filesystem_object_get_pathname(intern); if (path) { RETURN_STR_COPY(path); @@ -1059,9 +1035,7 @@ PHP_METHOD(FilesystemIterator, key) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); if (SPL_FILE_DIR_KEY(intern, SPL_FILE_DIR_KEY_AS_FILENAME)) { RETURN_STRING(intern->u.dir.entry.d_name); @@ -1079,9 +1053,7 @@ PHP_METHOD(FilesystemIterator, current) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); if (SPL_FILE_DIR_CURRENT(intern, SPL_FILE_DIR_CURRENT_AS_PATHNAME)) { if (spl_filesystem_object_get_file_name(intern) == FAILURE) { @@ -1104,9 +1076,7 @@ PHP_METHOD(DirectoryIterator, isDot) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(intern); RETURN_BOOL(spl_filesystem_is_dot(intern->u.dir.entry.d_name)); @@ -1140,9 +1110,7 @@ PHP_METHOD(SplFileInfo, func_name) \ { \ spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); \ zend_error_handling error_handling; \ - if (zend_parse_parameters_none() == FAILURE) { \ - RETURN_THROWS(); \ - } \ + ZEND_PARSE_PARAMETERS_NONE(); \ if (spl_filesystem_object_get_file_name(intern) == FAILURE) { \ RETURN_THROWS(); \ } \ @@ -1219,9 +1187,7 @@ PHP_METHOD(SplFileInfo, getLinkTarget) ssize_t ret; char buff[MAXPATHLEN]; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); if (intern->file_name == NULL) { if (spl_filesystem_object_get_file_name(intern) == FAILURE) { @@ -1266,9 +1232,7 @@ PHP_METHOD(SplFileInfo, getRealPath) char buff[MAXPATHLEN]; char *filename; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); if (intern->type == SPL_FS_DIR && !intern->file_name && intern->u.dir.entry.d_name[0]) { if (spl_filesystem_object_get_file_name(intern) == FAILURE) { @@ -1378,9 +1342,7 @@ PHP_METHOD(SplFileInfo, getPathInfo) /* {{{ */ PHP_METHOD(SplFileInfo, __debugInfo) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_ARR(spl_filesystem_object_get_debug_info(Z_OBJ_P(ZEND_THIS))); } /* }}} */ @@ -1388,9 +1350,7 @@ PHP_METHOD(SplFileInfo, __debugInfo) /* {{{ */ PHP_METHOD(SplFileInfo, _bad_state_ex) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); zend_throw_error(NULL, "The parent constructor was not called: the object is in an invalid state"); RETURN_THROWS(); } @@ -1409,9 +1369,7 @@ PHP_METHOD(FilesystemIterator, rewind) spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); bool skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); intern->u.dir.index = 0; if (intern->u.dir.dirp) { @@ -1428,9 +1386,7 @@ PHP_METHOD(FilesystemIterator, getFlags) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_LONG(intern->flags & (SPL_FILE_DIR_KEY_MODE_MASK | SPL_FILE_DIR_CURRENT_MODE_MASK | SPL_FILE_DIR_OTHERS_MASK)); } /* }}} */ @@ -1494,9 +1450,7 @@ PHP_METHOD(RecursiveDirectoryIterator, getChildren) spl_filesystem_object *subdir; char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); if (spl_filesystem_object_get_file_name(intern) == FAILURE) { RETURN_THROWS(); @@ -1537,9 +1491,7 @@ PHP_METHOD(RecursiveDirectoryIterator, getSubPath) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); if (intern->u.dir.sub_path) { RETURN_STR_COPY(intern->u.dir.sub_path); @@ -1555,9 +1507,7 @@ PHP_METHOD(RecursiveDirectoryIterator, getSubPathname) spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); if (intern->u.dir.sub_path) { RETURN_NEW_STR(strpprintf(0, "%s%c%s", ZSTR_VAL(intern->u.dir.sub_path), slash, intern->u.dir.entry.d_name)); @@ -1586,9 +1536,7 @@ PHP_METHOD(GlobIterator, count) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); if (EXPECTED(spl_intern_is_glob(intern))) { RETURN_LONG(php_glob_stream_get_count(intern->u.dir.dirp, NULL)); @@ -2017,7 +1965,7 @@ PHP_METHOD(SplFileObject, __construct) zend_string *file_name = NULL; zend_string *open_mode = ZSTR_CHAR('r'); zval *stream_context = NULL; - bool use_include_path = 0; + bool use_include_path = false; size_t path_len; zend_error_handling error_handling; @@ -2103,9 +2051,7 @@ PHP_METHOD(SplFileObject, rewind) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); spl_filesystem_file_rewind(ZEND_THIS, intern); } /* }}} */ @@ -2115,9 +2061,7 @@ PHP_METHOD(SplFileObject, eof) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); @@ -2129,9 +2073,7 @@ PHP_METHOD(SplFileObject, valid) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) { RETURN_BOOL(intern->u.file.current_line || !Z_ISUNDEF(intern->u.file.current_zval)); @@ -2147,9 +2089,7 @@ PHP_METHOD(SplFileObject, fgets) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); @@ -2164,9 +2104,7 @@ PHP_METHOD(SplFileObject, current) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); @@ -2188,9 +2126,7 @@ PHP_METHOD(SplFileObject, key) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); /* Do not read the next line to support correct counting with fgetc() if (!intern->u.file.current_line) { @@ -2204,9 +2140,7 @@ PHP_METHOD(SplFileObject, next) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); spl_filesystem_file_free_line(intern); if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) { @@ -2230,9 +2164,7 @@ PHP_METHOD(SplFileObject, getFlags) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_LONG(intern->flags & SPL_FILE_OBJECT_MASK); } /* }}} */ @@ -2261,9 +2193,7 @@ PHP_METHOD(SplFileObject, getMaxLineLen) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_LONG((zend_long)intern->u.file.max_line_len); } /* }}} */ @@ -2271,9 +2201,7 @@ PHP_METHOD(SplFileObject, getMaxLineLen) /* {{{ Return false */ PHP_METHOD(SplFileObject, hasChildren) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_FALSE; } /* }}} */ @@ -2281,9 +2209,7 @@ PHP_METHOD(SplFileObject, hasChildren) /* {{{ Read NULL */ PHP_METHOD(SplFileObject, getChildren) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); /* return NULL */ } /* }}} */ @@ -2434,9 +2360,7 @@ PHP_METHOD(SplFileObject, getCsvControl) spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); char delimiter[2], enclosure[2], escape[2]; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); array_init(return_value); @@ -2479,9 +2403,7 @@ PHP_METHOD(SplFileObject, fflush) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); @@ -2494,9 +2416,7 @@ PHP_METHOD(SplFileObject, ftell) spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); zend_long ret; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); @@ -2530,9 +2450,7 @@ PHP_METHOD(SplFileObject, fgetc) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); @@ -2555,9 +2473,7 @@ PHP_METHOD(SplFileObject, fpassthru) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); @@ -2586,7 +2502,8 @@ PHP_METHOD(SplFileObject, fscanf) int result = php_sscanf_internal(ZSTR_VAL(intern->u.file.current_line), ZSTR_VAL(format_str), (int)num_varargs, varargs, 0, return_value); if (SCAN_ERROR_WRONG_PARAM_COUNT == result) { - WRONG_PARAM_COUNT; + zend_wrong_param_count(); + RETURN_THROWS(); } } /* }}} */ @@ -2657,9 +2574,7 @@ PHP_METHOD(SplFileObject, fstat) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); @@ -2725,9 +2640,7 @@ PHP_METHOD(SplFileObject, seek) PHP_METHOD(SplFileObject, __toString) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); diff --git a/ext/spl/spl_directory.h b/ext/spl/spl_directory.h index 549dfb1dc4d0f..a2d1d8d854750 100644 --- a/ext/spl/spl_directory.h +++ b/ext/spl/spl_directory.h @@ -62,7 +62,7 @@ struct _spl_filesystem_object { struct { php_stream *dirp; zend_string *sub_path; - int index; + zend_long index; zend_function *func_rewind; zend_function *func_next; zend_function *func_valid; diff --git a/ext/spl/spl_directory_arginfo.h b/ext/spl/spl_directory_arginfo.h index 434abefef4c68..3b37c1ed6fd0e 100644 --- a/ext/spl/spl_directory_arginfo.h +++ b/ext/spl/spl_directory_arginfo.h @@ -508,75 +508,75 @@ static zend_class_entry *register_class_FilesystemIterator(zend_class_entry *cla zval const_CURRENT_MODE_MASK_value; ZVAL_LONG(&const_CURRENT_MODE_MASK_value, SPL_FILE_DIR_CURRENT_MODE_MASK); - zend_string *const_CURRENT_MODE_MASK_name = zend_string_init_interned("CURRENT_MODE_MASK", sizeof("CURRENT_MODE_MASK") - 1, 1); + zend_string *const_CURRENT_MODE_MASK_name = zend_string_init_interned("CURRENT_MODE_MASK", sizeof("CURRENT_MODE_MASK") - 1, true); zend_declare_typed_class_constant(class_entry, const_CURRENT_MODE_MASK_name, &const_CURRENT_MODE_MASK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CURRENT_MODE_MASK_name); + zend_string_release_ex(const_CURRENT_MODE_MASK_name, true); zval const_CURRENT_AS_PATHNAME_value; ZVAL_LONG(&const_CURRENT_AS_PATHNAME_value, SPL_FILE_DIR_CURRENT_AS_PATHNAME); - zend_string *const_CURRENT_AS_PATHNAME_name = zend_string_init_interned("CURRENT_AS_PATHNAME", sizeof("CURRENT_AS_PATHNAME") - 1, 1); + zend_string *const_CURRENT_AS_PATHNAME_name = zend_string_init_interned("CURRENT_AS_PATHNAME", sizeof("CURRENT_AS_PATHNAME") - 1, true); zend_declare_typed_class_constant(class_entry, const_CURRENT_AS_PATHNAME_name, &const_CURRENT_AS_PATHNAME_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CURRENT_AS_PATHNAME_name); + zend_string_release_ex(const_CURRENT_AS_PATHNAME_name, true); zval const_CURRENT_AS_FILEINFO_value; ZVAL_LONG(&const_CURRENT_AS_FILEINFO_value, SPL_FILE_DIR_CURRENT_AS_FILEINFO); - zend_string *const_CURRENT_AS_FILEINFO_name = zend_string_init_interned("CURRENT_AS_FILEINFO", sizeof("CURRENT_AS_FILEINFO") - 1, 1); + zend_string *const_CURRENT_AS_FILEINFO_name = zend_string_init_interned("CURRENT_AS_FILEINFO", sizeof("CURRENT_AS_FILEINFO") - 1, true); zend_declare_typed_class_constant(class_entry, const_CURRENT_AS_FILEINFO_name, &const_CURRENT_AS_FILEINFO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CURRENT_AS_FILEINFO_name); + zend_string_release_ex(const_CURRENT_AS_FILEINFO_name, true); zval const_CURRENT_AS_SELF_value; ZVAL_LONG(&const_CURRENT_AS_SELF_value, SPL_FILE_DIR_CURRENT_AS_SELF); - zend_string *const_CURRENT_AS_SELF_name = zend_string_init_interned("CURRENT_AS_SELF", sizeof("CURRENT_AS_SELF") - 1, 1); + zend_string *const_CURRENT_AS_SELF_name = zend_string_init_interned("CURRENT_AS_SELF", sizeof("CURRENT_AS_SELF") - 1, true); zend_declare_typed_class_constant(class_entry, const_CURRENT_AS_SELF_name, &const_CURRENT_AS_SELF_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CURRENT_AS_SELF_name); + zend_string_release_ex(const_CURRENT_AS_SELF_name, true); zval const_KEY_MODE_MASK_value; ZVAL_LONG(&const_KEY_MODE_MASK_value, SPL_FILE_DIR_KEY_MODE_MASK); - zend_string *const_KEY_MODE_MASK_name = zend_string_init_interned("KEY_MODE_MASK", sizeof("KEY_MODE_MASK") - 1, 1); + zend_string *const_KEY_MODE_MASK_name = zend_string_init_interned("KEY_MODE_MASK", sizeof("KEY_MODE_MASK") - 1, true); zend_declare_typed_class_constant(class_entry, const_KEY_MODE_MASK_name, &const_KEY_MODE_MASK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_KEY_MODE_MASK_name); + zend_string_release_ex(const_KEY_MODE_MASK_name, true); zval const_KEY_AS_PATHNAME_value; ZVAL_LONG(&const_KEY_AS_PATHNAME_value, SPL_FILE_DIR_KEY_AS_PATHNAME); - zend_string *const_KEY_AS_PATHNAME_name = zend_string_init_interned("KEY_AS_PATHNAME", sizeof("KEY_AS_PATHNAME") - 1, 1); + zend_string *const_KEY_AS_PATHNAME_name = zend_string_init_interned("KEY_AS_PATHNAME", sizeof("KEY_AS_PATHNAME") - 1, true); zend_declare_typed_class_constant(class_entry, const_KEY_AS_PATHNAME_name, &const_KEY_AS_PATHNAME_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_KEY_AS_PATHNAME_name); + zend_string_release_ex(const_KEY_AS_PATHNAME_name, true); zval const_FOLLOW_SYMLINKS_value; ZVAL_LONG(&const_FOLLOW_SYMLINKS_value, SPL_FILE_DIR_FOLLOW_SYMLINKS); - zend_string *const_FOLLOW_SYMLINKS_name = zend_string_init_interned("FOLLOW_SYMLINKS", sizeof("FOLLOW_SYMLINKS") - 1, 1); + zend_string *const_FOLLOW_SYMLINKS_name = zend_string_init_interned("FOLLOW_SYMLINKS", sizeof("FOLLOW_SYMLINKS") - 1, true); zend_declare_typed_class_constant(class_entry, const_FOLLOW_SYMLINKS_name, &const_FOLLOW_SYMLINKS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FOLLOW_SYMLINKS_name); + zend_string_release_ex(const_FOLLOW_SYMLINKS_name, true); zval const_KEY_AS_FILENAME_value; ZVAL_LONG(&const_KEY_AS_FILENAME_value, SPL_FILE_DIR_KEY_AS_FILENAME); - zend_string *const_KEY_AS_FILENAME_name = zend_string_init_interned("KEY_AS_FILENAME", sizeof("KEY_AS_FILENAME") - 1, 1); + zend_string *const_KEY_AS_FILENAME_name = zend_string_init_interned("KEY_AS_FILENAME", sizeof("KEY_AS_FILENAME") - 1, true); zend_declare_typed_class_constant(class_entry, const_KEY_AS_FILENAME_name, &const_KEY_AS_FILENAME_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_KEY_AS_FILENAME_name); + zend_string_release_ex(const_KEY_AS_FILENAME_name, true); zval const_NEW_CURRENT_AND_KEY_value; ZVAL_LONG(&const_NEW_CURRENT_AND_KEY_value, SPL_FILE_NEW_CURRENT_AND_KEY); - zend_string *const_NEW_CURRENT_AND_KEY_name = zend_string_init_interned("NEW_CURRENT_AND_KEY", sizeof("NEW_CURRENT_AND_KEY") - 1, 1); + zend_string *const_NEW_CURRENT_AND_KEY_name = zend_string_init_interned("NEW_CURRENT_AND_KEY", sizeof("NEW_CURRENT_AND_KEY") - 1, true); zend_declare_typed_class_constant(class_entry, const_NEW_CURRENT_AND_KEY_name, &const_NEW_CURRENT_AND_KEY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NEW_CURRENT_AND_KEY_name); + zend_string_release_ex(const_NEW_CURRENT_AND_KEY_name, true); zval const_OTHER_MODE_MASK_value; ZVAL_LONG(&const_OTHER_MODE_MASK_value, SPL_FILE_DIR_OTHERS_MASK); - zend_string *const_OTHER_MODE_MASK_name = zend_string_init_interned("OTHER_MODE_MASK", sizeof("OTHER_MODE_MASK") - 1, 1); + zend_string *const_OTHER_MODE_MASK_name = zend_string_init_interned("OTHER_MODE_MASK", sizeof("OTHER_MODE_MASK") - 1, true); zend_declare_typed_class_constant(class_entry, const_OTHER_MODE_MASK_name, &const_OTHER_MODE_MASK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OTHER_MODE_MASK_name); + zend_string_release_ex(const_OTHER_MODE_MASK_name, true); zval const_SKIP_DOTS_value; ZVAL_LONG(&const_SKIP_DOTS_value, SPL_FILE_DIR_SKIPDOTS); - zend_string *const_SKIP_DOTS_name = zend_string_init_interned("SKIP_DOTS", sizeof("SKIP_DOTS") - 1, 1); + zend_string *const_SKIP_DOTS_name = zend_string_init_interned("SKIP_DOTS", sizeof("SKIP_DOTS") - 1, true); zend_declare_typed_class_constant(class_entry, const_SKIP_DOTS_name, &const_SKIP_DOTS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SKIP_DOTS_name); + zend_string_release_ex(const_SKIP_DOTS_name, true); zval const_UNIX_PATHS_value; ZVAL_LONG(&const_UNIX_PATHS_value, SPL_FILE_DIR_UNIXPATHS); - zend_string *const_UNIX_PATHS_name = zend_string_init_interned("UNIX_PATHS", sizeof("UNIX_PATHS") - 1, 1); + zend_string *const_UNIX_PATHS_name = zend_string_init_interned("UNIX_PATHS", sizeof("UNIX_PATHS") - 1, true); zend_declare_typed_class_constant(class_entry, const_UNIX_PATHS_name, &const_UNIX_PATHS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_UNIX_PATHS_name); + zend_string_release_ex(const_UNIX_PATHS_name, true); return class_entry; } @@ -613,27 +613,27 @@ static zend_class_entry *register_class_SplFileObject(zend_class_entry *class_en zval const_DROP_NEW_LINE_value; ZVAL_LONG(&const_DROP_NEW_LINE_value, SPL_FILE_OBJECT_DROP_NEW_LINE); - zend_string *const_DROP_NEW_LINE_name = zend_string_init_interned("DROP_NEW_LINE", sizeof("DROP_NEW_LINE") - 1, 1); + zend_string *const_DROP_NEW_LINE_name = zend_string_init_interned("DROP_NEW_LINE", sizeof("DROP_NEW_LINE") - 1, true); zend_declare_typed_class_constant(class_entry, const_DROP_NEW_LINE_name, &const_DROP_NEW_LINE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DROP_NEW_LINE_name); + zend_string_release_ex(const_DROP_NEW_LINE_name, true); zval const_READ_AHEAD_value; ZVAL_LONG(&const_READ_AHEAD_value, SPL_FILE_OBJECT_READ_AHEAD); - zend_string *const_READ_AHEAD_name = zend_string_init_interned("READ_AHEAD", sizeof("READ_AHEAD") - 1, 1); + zend_string *const_READ_AHEAD_name = zend_string_init_interned("READ_AHEAD", sizeof("READ_AHEAD") - 1, true); zend_declare_typed_class_constant(class_entry, const_READ_AHEAD_name, &const_READ_AHEAD_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_READ_AHEAD_name); + zend_string_release_ex(const_READ_AHEAD_name, true); zval const_SKIP_EMPTY_value; ZVAL_LONG(&const_SKIP_EMPTY_value, SPL_FILE_OBJECT_SKIP_EMPTY); - zend_string *const_SKIP_EMPTY_name = zend_string_init_interned("SKIP_EMPTY", sizeof("SKIP_EMPTY") - 1, 1); + zend_string *const_SKIP_EMPTY_name = zend_string_init_interned("SKIP_EMPTY", sizeof("SKIP_EMPTY") - 1, true); zend_declare_typed_class_constant(class_entry, const_SKIP_EMPTY_name, &const_SKIP_EMPTY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SKIP_EMPTY_name); + zend_string_release_ex(const_SKIP_EMPTY_name, true); zval const_READ_CSV_value; ZVAL_LONG(&const_READ_CSV_value, SPL_FILE_OBJECT_READ_CSV); - zend_string *const_READ_CSV_name = zend_string_init_interned("READ_CSV", sizeof("READ_CSV") - 1, 1); + zend_string *const_READ_CSV_name = zend_string_init_interned("READ_CSV", sizeof("READ_CSV") - 1, true); zend_declare_typed_class_constant(class_entry, const_READ_CSV_name, &const_READ_CSV_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_READ_CSV_name); + zend_string_release_ex(const_READ_CSV_name, true); return class_entry; } diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c index 0f525e627d305..867f492fab16d 100644 --- a/ext/spl/spl_dllist.c +++ b/ext/spl/spl_dllist.c @@ -511,9 +511,7 @@ PHP_METHOD(SplDoublyLinkedList, pop) { spl_dllist_object *intern; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); intern = Z_SPLDLLIST_P(ZEND_THIS); spl_ptr_llist_pop(intern->llist, return_value); @@ -530,9 +528,7 @@ PHP_METHOD(SplDoublyLinkedList, shift) { spl_dllist_object *intern; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); intern = Z_SPLDLLIST_P(ZEND_THIS); spl_ptr_llist_shift(intern->llist, return_value); @@ -550,9 +546,7 @@ PHP_METHOD(SplDoublyLinkedList, top) zval *value; spl_dllist_object *intern; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); intern = Z_SPLDLLIST_P(ZEND_THIS); value = spl_ptr_llist_last(intern->llist); @@ -572,9 +566,7 @@ PHP_METHOD(SplDoublyLinkedList, bottom) zval *value; spl_dllist_object *intern; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); intern = Z_SPLDLLIST_P(ZEND_THIS); value = spl_ptr_llist_first(intern->llist); @@ -594,9 +586,7 @@ PHP_METHOD(SplDoublyLinkedList, count) zend_long count; spl_dllist_object *intern = Z_SPLDLLIST_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); count = spl_ptr_llist_count(intern->llist); RETURN_LONG(count); @@ -608,9 +598,7 @@ PHP_METHOD(SplDoublyLinkedList, isEmpty) { zend_long count; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); spl_dllist_object_count_elements(Z_OBJ_P(ZEND_THIS), &count); RETURN_BOOL(count == 0); @@ -646,9 +634,7 @@ PHP_METHOD(SplDoublyLinkedList, getIteratorMode) { spl_dllist_object *intern; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); intern = Z_SPLDLLIST_P(ZEND_THIS); @@ -702,7 +688,7 @@ PHP_METHOD(SplDoublyLinkedList, offsetGet) PHP_METHOD(SplDoublyLinkedList, offsetSet) { zend_long index; - bool index_is_null = 1; + bool index_is_null = true; zval *value; spl_dllist_object *intern; @@ -914,9 +900,7 @@ PHP_METHOD(SplDoublyLinkedList, key) { spl_dllist_object *intern = Z_SPLDLLIST_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_LONG(intern->traverse_position); } @@ -927,9 +911,7 @@ PHP_METHOD(SplDoublyLinkedList, prev) { spl_dllist_object *intern = Z_SPLDLLIST_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); spl_dllist_it_helper_move_forward(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags ^ SPL_DLLIST_IT_LIFO); } @@ -940,9 +922,7 @@ PHP_METHOD(SplDoublyLinkedList, next) { spl_dllist_object *intern = Z_SPLDLLIST_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); spl_dllist_it_helper_move_forward(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags); } @@ -953,9 +933,7 @@ PHP_METHOD(SplDoublyLinkedList, valid) { spl_dllist_object *intern = Z_SPLDLLIST_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_BOOL(intern->traverse_pointer != NULL); } @@ -966,9 +944,7 @@ PHP_METHOD(SplDoublyLinkedList, rewind) { spl_dllist_object *intern = Z_SPLDLLIST_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); spl_dllist_it_helper_rewind(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags); } @@ -980,9 +956,7 @@ PHP_METHOD(SplDoublyLinkedList, current) spl_dllist_object *intern = Z_SPLDLLIST_P(ZEND_THIS); spl_ptr_llist_element *element = intern->traverse_pointer; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); if (element == NULL || Z_ISUNDEF(element->data)) { RETURN_NULL(); @@ -1001,9 +975,7 @@ PHP_METHOD(SplDoublyLinkedList, serialize) zval flags; php_serialize_data_t var_hash; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHP_VAR_SERIALIZE_INIT(var_hash); @@ -1099,9 +1071,7 @@ PHP_METHOD(SplDoublyLinkedList, __serialize) spl_ptr_llist_element *current = intern->llist->head; zval tmp; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); array_init(return_value); @@ -1205,9 +1175,7 @@ PHP_METHOD(SplDoublyLinkedList, add) /* {{{ */ PHP_METHOD(SplDoublyLinkedList, __debugInfo) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_ARR(spl_dllist_object_get_debug_info(Z_OBJ_P(ZEND_THIS))); } /* }}} */ diff --git a/ext/spl/spl_dllist_arginfo.h b/ext/spl/spl_dllist_arginfo.h index a5b1510655138..e6ceb3dca42de 100644 --- a/ext/spl/spl_dllist_arginfo.h +++ b/ext/spl/spl_dllist_arginfo.h @@ -156,27 +156,27 @@ static zend_class_entry *register_class_SplDoublyLinkedList(zend_class_entry *cl zval const_IT_MODE_LIFO_value; ZVAL_LONG(&const_IT_MODE_LIFO_value, SPL_DLLIST_IT_LIFO); - zend_string *const_IT_MODE_LIFO_name = zend_string_init_interned("IT_MODE_LIFO", sizeof("IT_MODE_LIFO") - 1, 1); + zend_string *const_IT_MODE_LIFO_name = zend_string_init_interned("IT_MODE_LIFO", sizeof("IT_MODE_LIFO") - 1, true); zend_declare_typed_class_constant(class_entry, const_IT_MODE_LIFO_name, &const_IT_MODE_LIFO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IT_MODE_LIFO_name); + zend_string_release_ex(const_IT_MODE_LIFO_name, true); zval const_IT_MODE_FIFO_value; ZVAL_LONG(&const_IT_MODE_FIFO_value, SPL_DLLIST_IT_FIFO); - zend_string *const_IT_MODE_FIFO_name = zend_string_init_interned("IT_MODE_FIFO", sizeof("IT_MODE_FIFO") - 1, 1); + zend_string *const_IT_MODE_FIFO_name = zend_string_init_interned("IT_MODE_FIFO", sizeof("IT_MODE_FIFO") - 1, true); zend_declare_typed_class_constant(class_entry, const_IT_MODE_FIFO_name, &const_IT_MODE_FIFO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IT_MODE_FIFO_name); + zend_string_release_ex(const_IT_MODE_FIFO_name, true); zval const_IT_MODE_DELETE_value; ZVAL_LONG(&const_IT_MODE_DELETE_value, SPL_DLLIST_IT_DELETE); - zend_string *const_IT_MODE_DELETE_name = zend_string_init_interned("IT_MODE_DELETE", sizeof("IT_MODE_DELETE") - 1, 1); + zend_string *const_IT_MODE_DELETE_name = zend_string_init_interned("IT_MODE_DELETE", sizeof("IT_MODE_DELETE") - 1, true); zend_declare_typed_class_constant(class_entry, const_IT_MODE_DELETE_name, &const_IT_MODE_DELETE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IT_MODE_DELETE_name); + zend_string_release_ex(const_IT_MODE_DELETE_name, true); zval const_IT_MODE_KEEP_value; ZVAL_LONG(&const_IT_MODE_KEEP_value, SPL_DLLIST_IT_KEEP); - zend_string *const_IT_MODE_KEEP_name = zend_string_init_interned("IT_MODE_KEEP", sizeof("IT_MODE_KEEP") - 1, 1); + zend_string *const_IT_MODE_KEEP_name = zend_string_init_interned("IT_MODE_KEEP", sizeof("IT_MODE_KEEP") - 1, true); zend_declare_typed_class_constant(class_entry, const_IT_MODE_KEEP_name, &const_IT_MODE_KEEP_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IT_MODE_KEEP_name); + zend_string_release_ex(const_IT_MODE_KEEP_name, true); return class_entry; } diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index dc32045ba0ff9..6f976923341bc 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -303,12 +303,12 @@ static zend_object *spl_fixedarray_object_new_ex(zend_class_entry *class_type, z static zend_object *spl_fixedarray_new(zend_class_entry *class_type) { - return spl_fixedarray_object_new_ex(class_type, NULL, 0); + return spl_fixedarray_object_new_ex(class_type, NULL, false); } static zend_object *spl_fixedarray_object_clone(zend_object *old_object) { - zend_object *new_object = spl_fixedarray_object_new_ex(old_object->ce, old_object, 1); + zend_object *new_object = spl_fixedarray_object_new_ex(old_object->ce, old_object, true); zend_objects_clone_members(new_object, old_object); @@ -562,9 +562,7 @@ PHP_METHOD(SplFixedArray, __wakeup) HashTable *intern_ht = zend_std_get_properties(Z_OBJ_P(ZEND_THIS)); zval *data; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); if (intern->array.size == 0) { int index = 0; @@ -589,9 +587,7 @@ PHP_METHOD(SplFixedArray, __serialize) zval *current; zend_string *key; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); HashTable *ht = zend_std_get_properties(&intern->std); uint32_t num_properties = zend_hash_num_elements(ht); @@ -639,7 +635,7 @@ PHP_METHOD(SplFixedArray, __unserialize) intern->array.size = 0; ZEND_HASH_FOREACH_STR_KEY_VAL(data, key, elem) { if (key == NULL) { - ZVAL_COPY(&intern->array.elements[intern->array.size], elem); + ZVAL_COPY_DEREF(&intern->array.elements[intern->array.size], elem); intern->array.size++; } else { Z_TRY_ADDREF_P(elem); @@ -666,9 +662,7 @@ PHP_METHOD(SplFixedArray, count) zval *object = ZEND_THIS; spl_fixedarray_object *intern; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); intern = Z_SPLFIXEDARRAY_P(object); RETURN_LONG(intern->array.size); @@ -678,9 +672,7 @@ PHP_METHOD(SplFixedArray, toArray) { spl_fixedarray_object *intern; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); intern = Z_SPLFIXEDARRAY_P(ZEND_THIS); @@ -706,7 +698,7 @@ PHP_METHOD(SplFixedArray, fromArray) spl_fixedarray array; spl_fixedarray_object *intern; int num; - bool save_indexes = 1; + bool save_indexes = true; if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|b", &data, &save_indexes) == FAILURE) { RETURN_THROWS(); @@ -774,9 +766,7 @@ PHP_METHOD(SplFixedArray, getSize) zval *object = ZEND_THIS; spl_fixedarray_object *intern; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); intern = Z_SPLFIXEDARRAY_P(object); RETURN_LONG(intern->array.size); @@ -815,7 +805,7 @@ PHP_METHOD(SplFixedArray, offsetExists) intern = Z_SPLFIXEDARRAY_P(ZEND_THIS); - RETURN_BOOL(spl_fixedarray_object_has_dimension_helper(intern, zindex, 0)); + RETURN_BOOL(spl_fixedarray_object_has_dimension_helper(intern, zindex, false)); } /* Returns the value at the specified $index. */ @@ -832,7 +822,7 @@ PHP_METHOD(SplFixedArray, offsetGet) value = spl_fixedarray_object_read_dimension_helper(intern, zindex); if (value) { - RETURN_COPY_DEREF(value); + RETURN_COPY(value); } else { RETURN_NULL(); } @@ -871,9 +861,7 @@ PHP_METHOD(SplFixedArray, offsetUnset) /* Create a new iterator from a SplFixedArray instance. */ PHP_METHOD(SplFixedArray, getIterator) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); zend_create_internal_iterator_zval(return_value, ZEND_THIS); } diff --git a/ext/spl/spl_fixedarray_arginfo.h b/ext/spl/spl_fixedarray_arginfo.h index 333ef5c3a690f..d3d84deabe6ec 100644 --- a/ext/spl/spl_fixedarray_arginfo.h +++ b/ext/spl/spl_fixedarray_arginfo.h @@ -100,10 +100,8 @@ 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_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..85fc5f8bb698b 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; @@ -580,9 +575,7 @@ PHP_METHOD(SplHeap, count) zend_long count; spl_heap_object *intern = Z_SPLHEAP_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); count = spl_ptr_heap_count(intern->heap); RETURN_LONG(count); @@ -594,9 +587,7 @@ PHP_METHOD(SplHeap, isEmpty) { spl_heap_object *intern = Z_SPLHEAP_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_BOOL(spl_ptr_heap_count(intern->heap) == 0); } @@ -645,9 +636,7 @@ PHP_METHOD(SplHeap, extract) { spl_heap_object *intern; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); intern = Z_SPLHEAP_P(ZEND_THIS); @@ -710,9 +699,7 @@ PHP_METHOD(SplPriorityQueue, extract) spl_pqueue_elem elem; spl_heap_object *intern; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); intern = Z_SPLHEAP_P(ZEND_THIS); @@ -736,9 +723,7 @@ PHP_METHOD(SplPriorityQueue, top) spl_heap_object *intern; spl_pqueue_elem *elem; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); intern = Z_SPLHEAP_P(ZEND_THIS); @@ -785,9 +770,7 @@ PHP_METHOD(SplPriorityQueue, getExtractFlags) { spl_heap_object *intern; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); intern = Z_SPLHEAP_P(ZEND_THIS); @@ -800,9 +783,7 @@ PHP_METHOD(SplHeap, recoverFromCorruption) { spl_heap_object *intern; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); intern = Z_SPLHEAP_P(ZEND_THIS); @@ -817,9 +798,7 @@ PHP_METHOD(SplHeap, isCorrupted) { spl_heap_object *intern; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); intern = Z_SPLHEAP_P(ZEND_THIS); @@ -846,9 +825,7 @@ PHP_METHOD(SplHeap, top) zval *value; spl_heap_object *intern; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); intern = Z_SPLHEAP_P(ZEND_THIS); @@ -975,9 +952,7 @@ PHP_METHOD(SplHeap, key) { spl_heap_object *intern = Z_SPLHEAP_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_LONG(intern->heap->count - 1); } @@ -988,9 +963,7 @@ PHP_METHOD(SplHeap, next) { spl_heap_object *intern = Z_SPLHEAP_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); spl_ptr_heap_delete_top(intern->heap, NULL, ZEND_THIS); } @@ -1001,9 +974,7 @@ PHP_METHOD(SplHeap, valid) { spl_heap_object *intern = Z_SPLHEAP_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_BOOL(intern->heap->count != 0); } @@ -1012,9 +983,7 @@ PHP_METHOD(SplHeap, valid) /* {{{ Rewind the datastructure back to the start */ PHP_METHOD(SplHeap, rewind) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); /* do nothing, the iterator always points to the top element */ } /* }}} */ @@ -1024,9 +993,7 @@ PHP_METHOD(SplHeap, current) { spl_heap_object *intern = Z_SPLHEAP_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); if (!intern->heap->count) { RETURN_NULL(); @@ -1042,9 +1009,7 @@ PHP_METHOD(SplPriorityQueue, current) { spl_heap_object *intern = Z_SPLHEAP_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); if (!intern->heap->count) { RETURN_NULL(); @@ -1058,9 +1023,7 @@ PHP_METHOD(SplPriorityQueue, current) /* {{{ */ PHP_METHOD(SplHeap, __debugInfo) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_ARR(spl_heap_object_get_debug_info(spl_ce_SplHeap, Z_OBJ_P(ZEND_THIS))); } /* }}} */ @@ -1068,13 +1031,235 @@ PHP_METHOD(SplHeap, __debugInfo) /* {{{ */ PHP_METHOD(SplPriorityQueue, __debugInfo) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_ARR(spl_heap_object_get_debug_info(spl_ce_SplPriorityQueue, Z_OBJ_P(ZEND_THIS))); } /* }}} */ +static void spl_heap_serialize_internal_state(zval *return_value, spl_heap_object *intern, bool is_pqueue) +{ + zval heap_elements; + int heap_count = intern->heap->count; + + array_init(return_value); + add_assoc_long(return_value, "flags", intern->flags); + + array_init_size(&heap_elements, heap_count); + + if (heap_count == 0) { + add_assoc_zval(return_value, "heap_elements", &heap_elements); + return; + } + + for (int heap_idx = 0; heap_idx < heap_count; ++heap_idx) { + if (is_pqueue) { + spl_pqueue_elem *elem = spl_heap_elem(intern->heap, heap_idx); + zval entry; + array_init(&entry); + add_assoc_zval_ex(&entry, "data", strlen("data"), &elem->data); + Z_TRY_ADDREF(elem->data); + add_assoc_zval_ex(&entry, "priority", strlen("priority"), &elem->priority); + Z_TRY_ADDREF(elem->priority); + zend_hash_next_index_insert(Z_ARRVAL(heap_elements), &entry); + } else { + zval *elem = spl_heap_elem(intern->heap, heap_idx); + zend_hash_next_index_insert(Z_ARRVAL(heap_elements), elem); + Z_TRY_ADDREF_P(elem); + } + } + + add_assoc_zval(return_value, "heap_elements", &heap_elements); +} + +static zend_result spl_heap_unserialize_internal_state(HashTable *state_ht, spl_heap_object *intern, zval *this_ptr, bool is_pqueue) +{ + zval *flags_val = zend_hash_str_find(state_ht, "flags", strlen("flags")); + if (!flags_val || Z_TYPE_P(flags_val) != IS_LONG) { + return FAILURE; + } + + zend_long flags_value = Z_LVAL_P(flags_val); + + if (is_pqueue) { + flags_value &= SPL_PQUEUE_EXTR_MASK; + if (!flags_value) { + return FAILURE; + } + } else if (flags_value != 0) { /* Regular heaps should not have user-visible flags */ + return FAILURE; + } + + intern->flags = (int) flags_value; + + zval *heap_elements = zend_hash_str_find(state_ht, "heap_elements", strlen("heap_elements")); + if (!heap_elements) { + return FAILURE; + } + + if (Z_TYPE_P(heap_elements) != IS_ARRAY) { + return FAILURE; + } + + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(heap_elements), zval *val) { + if (is_pqueue) { + /* PriorityQueue elements are serialized as arrays with 'data' and 'priority' keys */ + if (Z_TYPE_P(val) != IS_ARRAY || zend_hash_num_elements(Z_ARRVAL_P(val)) != 2) { + return FAILURE; + } + + zval *data_val = zend_hash_str_find(Z_ARRVAL_P(val), "data", strlen("data") ); + zval *priority_val = zend_hash_str_find(Z_ARRVAL_P(val), "priority", strlen("priority")); + + if (!data_val || !priority_val) { + return FAILURE; + } + + spl_pqueue_elem elem; + ZVAL_COPY(&elem.data, data_val); + ZVAL_COPY(&elem.priority, priority_val); + spl_ptr_heap_insert(intern->heap, &elem, this_ptr); + if (EG(exception)) { + return FAILURE; + } + } else { + Z_TRY_ADDREF_P(val); + spl_ptr_heap_insert(intern->heap, val, this_ptr); + if (EG(exception)) { + return FAILURE; + } + } + } ZEND_HASH_FOREACH_END(); + + return SUCCESS; +} + +static void spl_heap_serialize_internal(INTERNAL_FUNCTION_PARAMETERS, bool is_pqueue) +{ + spl_heap_object *intern = Z_SPLHEAP_P(ZEND_THIS); + zval props, state; + + ZEND_PARSE_PARAMETERS_NONE(); + + if (UNEXPECTED(spl_heap_consistency_validations(intern, false) != SUCCESS)) { + RETURN_THROWS(); + } + + if (intern->heap->flags & SPL_HEAP_WRITE_LOCKED) { + zend_throw_exception(spl_ce_RuntimeException, "Cannot serialize heap while it is being modified.", 0); + RETURN_THROWS(); + } + + array_init(return_value); + + ZVAL_ARR(&props, zend_array_dup(zend_std_get_properties(&intern->std))); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &props); + + spl_heap_serialize_internal_state(&state, intern, is_pqueue); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &state); +} + +PHP_METHOD(SplPriorityQueue, __serialize) +{ + spl_heap_serialize_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, true); +} + +PHP_METHOD(SplPriorityQueue, __unserialize) +{ + HashTable *data; + spl_heap_object *intern = Z_SPLHEAP_P(ZEND_THIS); + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ARRAY_HT(data) + ZEND_PARSE_PARAMETERS_END(); + + if (zend_hash_num_elements(data) != 2) { + zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(intern->std.ce->name)); + RETURN_THROWS(); + } + + zval *props = zend_hash_index_find(data, 0); + if (!props || Z_TYPE_P(props) != IS_ARRAY) { + zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(intern->std.ce->name)); + RETURN_THROWS(); + } + + object_properties_load(&intern->std, Z_ARRVAL_P(props)); + if (EG(exception)) { + zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(intern->std.ce->name)); + RETURN_THROWS(); + } + + zval *state = zend_hash_index_find(data, 1); + if (!state || Z_TYPE_P(state) != IS_ARRAY) { + zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(intern->std.ce->name)); + RETURN_THROWS(); + } + + if (spl_heap_unserialize_internal_state(Z_ARRVAL_P(state), intern, ZEND_THIS, true) != SUCCESS) { + zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(intern->std.ce->name)); + RETURN_THROWS(); + } + + if (EG(exception)) { + RETURN_THROWS(); + } + + if (UNEXPECTED(spl_heap_consistency_validations(intern, false) != SUCCESS)) { + RETURN_THROWS(); + } +} + +PHP_METHOD(SplHeap, __serialize) +{ + spl_heap_serialize_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, false); +} + +PHP_METHOD(SplHeap, __unserialize) +{ + HashTable *data; + spl_heap_object *intern = Z_SPLHEAP_P(ZEND_THIS); + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ARRAY_HT(data) + ZEND_PARSE_PARAMETERS_END(); + + if (UNEXPECTED(spl_heap_consistency_validations(intern, true) != SUCCESS)) { + RETURN_THROWS(); + } + + if (zend_hash_num_elements(data) != 2) { + zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(intern->std.ce->name)); + RETURN_THROWS(); + } + + zval *props = zend_hash_index_find(data, 0); + if (!props || Z_TYPE_P(props) != IS_ARRAY) { + zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(intern->std.ce->name)); + RETURN_THROWS(); + } + + object_properties_load(&intern->std, Z_ARRVAL_P(props)); + if (EG(exception)) { + zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(intern->std.ce->name)); + RETURN_THROWS(); + } + + zval *state = zend_hash_index_find(data, 1); + if (!state || Z_TYPE_P(state) != IS_ARRAY) { + zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(intern->std.ce->name)); + RETURN_THROWS(); + } + + if (spl_heap_unserialize_internal_state(Z_ARRVAL_P(state), intern, ZEND_THIS, false) != SUCCESS) { + zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(intern->std.ce->name)); + RETURN_THROWS(); + } + + if (UNEXPECTED(spl_heap_consistency_validations(intern, false) != SUCCESS)) { + RETURN_THROWS(); + } +} + /* iterator handler table */ static const zend_object_iterator_funcs spl_heap_it_funcs = { spl_heap_it_dtor, diff --git a/ext/spl/spl_heap.stub.php b/ext/spl/spl_heap.stub.php index c545d27dfc0f9..dd38cfb983432 100644 --- a/ext/spl/spl_heap.stub.php +++ b/ext/spl/spl_heap.stub.php @@ -82,6 +82,12 @@ public function getExtractFlags(): int {} /** @tentative-return-type */ public function __debugInfo(): array {} + + /** @tentative-return-type */ + public function __serialize(): array {} + + /** @tentative-return-type */ + public function __unserialize(array $data): void {} } abstract class SplHeap implements Iterator, Countable @@ -127,6 +133,12 @@ public function isCorrupted(): bool {} /** @tentative-return-type */ public function __debugInfo(): array {} + + /** @tentative-return-type */ + public function __serialize(): array {} + + /** @tentative-return-type */ + public function __unserialize(array $data): void {} } class SplMinHeap extends SplHeap diff --git a/ext/spl/spl_heap_arginfo.h b/ext/spl/spl_heap_arginfo.h index 31a3f79fe2c75..8b79ee0902ddf 100644 --- a/ext/spl/spl_heap_arginfo.h +++ b/ext/spl/spl_heap_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 47273e114c9c7089bf708a2f18f2e9e522abceb6 */ + * Stub hash: 3256398ed9e798f141fd3cb73370c0d8b2dbd0f1 */ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SplPriorityQueue_compare, 0, 2, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, priority1, IS_MIXED, 0) @@ -47,6 +47,12 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SplPriorityQueue___debugInfo, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() +#define arginfo_class_SplPriorityQueue___serialize arginfo_class_SplPriorityQueue___debugInfo + +ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SplPriorityQueue___unserialize, 0, 1, IS_VOID, 0) + ZEND_ARG_TYPE_INFO(0, data, IS_ARRAY, 0) +ZEND_END_ARG_INFO() + #define arginfo_class_SplHeap_extract arginfo_class_SplPriorityQueue_top ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SplHeap_insert, 0, 1, IS_TRUE, 0) @@ -80,6 +86,10 @@ ZEND_END_ARG_INFO() #define arginfo_class_SplHeap___debugInfo arginfo_class_SplPriorityQueue___debugInfo +#define arginfo_class_SplHeap___serialize arginfo_class_SplPriorityQueue___debugInfo + +#define arginfo_class_SplHeap___unserialize arginfo_class_SplPriorityQueue___unserialize + #define arginfo_class_SplMinHeap_compare arginfo_class_SplHeap_compare #define arginfo_class_SplMaxHeap_compare arginfo_class_SplHeap_compare @@ -100,11 +110,15 @@ ZEND_METHOD(SplHeap, recoverFromCorruption); ZEND_METHOD(SplHeap, isCorrupted); ZEND_METHOD(SplPriorityQueue, getExtractFlags); ZEND_METHOD(SplPriorityQueue, __debugInfo); +ZEND_METHOD(SplPriorityQueue, __serialize); +ZEND_METHOD(SplPriorityQueue, __unserialize); ZEND_METHOD(SplHeap, extract); ZEND_METHOD(SplHeap, insert); ZEND_METHOD(SplHeap, top); ZEND_METHOD(SplHeap, current); ZEND_METHOD(SplHeap, __debugInfo); +ZEND_METHOD(SplHeap, __serialize); +ZEND_METHOD(SplHeap, __unserialize); ZEND_METHOD(SplMinHeap, compare); ZEND_METHOD(SplMaxHeap, compare); @@ -125,6 +139,8 @@ static const zend_function_entry class_SplPriorityQueue_methods[] = { ZEND_RAW_FENTRY("isCorrupted", zim_SplHeap_isCorrupted, arginfo_class_SplPriorityQueue_isCorrupted, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_ME(SplPriorityQueue, getExtractFlags, arginfo_class_SplPriorityQueue_getExtractFlags, ZEND_ACC_PUBLIC) ZEND_ME(SplPriorityQueue, __debugInfo, arginfo_class_SplPriorityQueue___debugInfo, ZEND_ACC_PUBLIC) + ZEND_ME(SplPriorityQueue, __serialize, arginfo_class_SplPriorityQueue___serialize, ZEND_ACC_PUBLIC) + ZEND_ME(SplPriorityQueue, __unserialize, arginfo_class_SplPriorityQueue___unserialize, ZEND_ACC_PUBLIC) ZEND_FE_END }; @@ -143,6 +159,8 @@ static const zend_function_entry class_SplHeap_methods[] = { ZEND_RAW_FENTRY("compare", NULL, arginfo_class_SplHeap_compare, ZEND_ACC_PROTECTED|ZEND_ACC_ABSTRACT, NULL, NULL) ZEND_ME(SplHeap, isCorrupted, arginfo_class_SplHeap_isCorrupted, ZEND_ACC_PUBLIC) ZEND_ME(SplHeap, __debugInfo, arginfo_class_SplHeap___debugInfo, ZEND_ACC_PUBLIC) + ZEND_ME(SplHeap, __serialize, arginfo_class_SplHeap___serialize, ZEND_ACC_PUBLIC) + ZEND_ME(SplHeap, __unserialize, arginfo_class_SplHeap___unserialize, ZEND_ACC_PUBLIC) ZEND_FE_END }; @@ -166,21 +184,21 @@ static zend_class_entry *register_class_SplPriorityQueue(zend_class_entry *class zval const_EXTR_BOTH_value; ZVAL_LONG(&const_EXTR_BOTH_value, SPL_PQUEUE_EXTR_BOTH); - zend_string *const_EXTR_BOTH_name = zend_string_init_interned("EXTR_BOTH", sizeof("EXTR_BOTH") - 1, 1); + zend_string *const_EXTR_BOTH_name = zend_string_init_interned("EXTR_BOTH", sizeof("EXTR_BOTH") - 1, true); zend_declare_typed_class_constant(class_entry, const_EXTR_BOTH_name, &const_EXTR_BOTH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EXTR_BOTH_name); + zend_string_release_ex(const_EXTR_BOTH_name, true); zval const_EXTR_PRIORITY_value; ZVAL_LONG(&const_EXTR_PRIORITY_value, SPL_PQUEUE_EXTR_PRIORITY); - zend_string *const_EXTR_PRIORITY_name = zend_string_init_interned("EXTR_PRIORITY", sizeof("EXTR_PRIORITY") - 1, 1); + zend_string *const_EXTR_PRIORITY_name = zend_string_init_interned("EXTR_PRIORITY", sizeof("EXTR_PRIORITY") - 1, true); zend_declare_typed_class_constant(class_entry, const_EXTR_PRIORITY_name, &const_EXTR_PRIORITY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EXTR_PRIORITY_name); + zend_string_release_ex(const_EXTR_PRIORITY_name, true); zval const_EXTR_DATA_value; ZVAL_LONG(&const_EXTR_DATA_value, SPL_PQUEUE_EXTR_DATA); - zend_string *const_EXTR_DATA_name = zend_string_init_interned("EXTR_DATA", sizeof("EXTR_DATA") - 1, 1); + zend_string *const_EXTR_DATA_name = zend_string_init_interned("EXTR_DATA", sizeof("EXTR_DATA") - 1, true); zend_declare_typed_class_constant(class_entry, const_EXTR_DATA_name, &const_EXTR_DATA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EXTR_DATA_name); + zend_string_release_ex(const_EXTR_DATA_name, true); return class_entry; } diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index 677590cc89514..a73e69519db51 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -222,7 +222,7 @@ static zend_result spl_recursive_it_valid_ex(spl_recursive_it_object *object, zv if (object->endIteration && object->in_iteration) { zend_call_method_with_0_params(Z_OBJ_P(zthis), object->ce, &object->endIteration, "endIteration", NULL); } - object->in_iteration = 0; + object->in_iteration = false; return FAILURE; } @@ -460,7 +460,7 @@ static void spl_recursive_it_rewind_ex(spl_recursive_it_object *object, zval *zt if (!EG(exception) && object->beginIteration && !object->in_iteration) { zend_call_method_with_0_params(Z_OBJ_P(zthis), object->ce, &object->beginIteration, "beginIteration", NULL); } - object->in_iteration = 1; + object->in_iteration = true; spl_recursive_it_move_forward_ex(object, zthis); } @@ -614,7 +614,7 @@ static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_cla intern->mode = mode; intern->flags = (int)flags; intern->max_depth = -1; - intern->in_iteration = 0; + intern->in_iteration = false; intern->ce = Z_OBJCE_P(object); intern->beginIteration = zend_hash_str_find_ptr(&intern->ce->function_table, "beginiteration", sizeof("beginiteration") - 1); @@ -740,7 +740,7 @@ PHP_METHOD(RecursiveIteratorIterator, getSubIterator) { spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(ZEND_THIS); zend_long level; - bool level_is_null = 1; + bool level_is_null = true; zval *value; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &level, &level_is_null) == FAILURE) { @@ -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_iterators_arginfo.h b/ext/spl/spl_iterators_arginfo.h index 439236643471e..ebd57693632d9 100644 --- a/ext/spl/spl_iterators_arginfo.h +++ b/ext/spl/spl_iterators_arginfo.h @@ -653,27 +653,27 @@ static zend_class_entry *register_class_RecursiveIteratorIterator(zend_class_ent zval const_LEAVES_ONLY_value; ZVAL_LONG(&const_LEAVES_ONLY_value, RIT_LEAVES_ONLY); - zend_string *const_LEAVES_ONLY_name = zend_string_init_interned("LEAVES_ONLY", sizeof("LEAVES_ONLY") - 1, 1); + zend_string *const_LEAVES_ONLY_name = zend_string_init_interned("LEAVES_ONLY", sizeof("LEAVES_ONLY") - 1, true); zend_declare_typed_class_constant(class_entry, const_LEAVES_ONLY_name, &const_LEAVES_ONLY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LEAVES_ONLY_name); + zend_string_release_ex(const_LEAVES_ONLY_name, true); zval const_SELF_FIRST_value; ZVAL_LONG(&const_SELF_FIRST_value, RIT_SELF_FIRST); - zend_string *const_SELF_FIRST_name = zend_string_init_interned("SELF_FIRST", sizeof("SELF_FIRST") - 1, 1); + zend_string *const_SELF_FIRST_name = zend_string_init_interned("SELF_FIRST", sizeof("SELF_FIRST") - 1, true); zend_declare_typed_class_constant(class_entry, const_SELF_FIRST_name, &const_SELF_FIRST_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SELF_FIRST_name); + zend_string_release_ex(const_SELF_FIRST_name, true); zval const_CHILD_FIRST_value; ZVAL_LONG(&const_CHILD_FIRST_value, RIT_CHILD_FIRST); - zend_string *const_CHILD_FIRST_name = zend_string_init_interned("CHILD_FIRST", sizeof("CHILD_FIRST") - 1, 1); + zend_string *const_CHILD_FIRST_name = zend_string_init_interned("CHILD_FIRST", sizeof("CHILD_FIRST") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHILD_FIRST_name, &const_CHILD_FIRST_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHILD_FIRST_name); + zend_string_release_ex(const_CHILD_FIRST_name, true); zval const_CATCH_GET_CHILD_value; ZVAL_LONG(&const_CATCH_GET_CHILD_value, RIT_CATCH_GET_CHILD); - zend_string *const_CATCH_GET_CHILD_name = zend_string_init_interned("CATCH_GET_CHILD", sizeof("CATCH_GET_CHILD") - 1, 1); + zend_string *const_CATCH_GET_CHILD_name = zend_string_init_interned("CATCH_GET_CHILD", sizeof("CATCH_GET_CHILD") - 1, true); zend_declare_typed_class_constant(class_entry, const_CATCH_GET_CHILD_name, &const_CATCH_GET_CHILD_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CATCH_GET_CHILD_name); + zend_string_release_ex(const_CATCH_GET_CHILD_name, true); return class_entry; } @@ -762,39 +762,39 @@ static zend_class_entry *register_class_CachingIterator(zend_class_entry *class_ zval const_CALL_TOSTRING_value; ZVAL_LONG(&const_CALL_TOSTRING_value, CIT_CALL_TOSTRING); - zend_string *const_CALL_TOSTRING_name = zend_string_init_interned("CALL_TOSTRING", sizeof("CALL_TOSTRING") - 1, 1); + zend_string *const_CALL_TOSTRING_name = zend_string_init_interned("CALL_TOSTRING", sizeof("CALL_TOSTRING") - 1, true); zend_declare_typed_class_constant(class_entry, const_CALL_TOSTRING_name, &const_CALL_TOSTRING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CALL_TOSTRING_name); + zend_string_release_ex(const_CALL_TOSTRING_name, true); zval const_CATCH_GET_CHILD_value; ZVAL_LONG(&const_CATCH_GET_CHILD_value, CIT_CATCH_GET_CHILD); - zend_string *const_CATCH_GET_CHILD_name = zend_string_init_interned("CATCH_GET_CHILD", sizeof("CATCH_GET_CHILD") - 1, 1); + zend_string *const_CATCH_GET_CHILD_name = zend_string_init_interned("CATCH_GET_CHILD", sizeof("CATCH_GET_CHILD") - 1, true); zend_declare_typed_class_constant(class_entry, const_CATCH_GET_CHILD_name, &const_CATCH_GET_CHILD_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CATCH_GET_CHILD_name); + zend_string_release_ex(const_CATCH_GET_CHILD_name, true); zval const_TOSTRING_USE_KEY_value; ZVAL_LONG(&const_TOSTRING_USE_KEY_value, CIT_TOSTRING_USE_KEY); - zend_string *const_TOSTRING_USE_KEY_name = zend_string_init_interned("TOSTRING_USE_KEY", sizeof("TOSTRING_USE_KEY") - 1, 1); + zend_string *const_TOSTRING_USE_KEY_name = zend_string_init_interned("TOSTRING_USE_KEY", sizeof("TOSTRING_USE_KEY") - 1, true); zend_declare_typed_class_constant(class_entry, const_TOSTRING_USE_KEY_name, &const_TOSTRING_USE_KEY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TOSTRING_USE_KEY_name); + zend_string_release_ex(const_TOSTRING_USE_KEY_name, true); zval const_TOSTRING_USE_CURRENT_value; ZVAL_LONG(&const_TOSTRING_USE_CURRENT_value, CIT_TOSTRING_USE_CURRENT); - zend_string *const_TOSTRING_USE_CURRENT_name = zend_string_init_interned("TOSTRING_USE_CURRENT", sizeof("TOSTRING_USE_CURRENT") - 1, 1); + zend_string *const_TOSTRING_USE_CURRENT_name = zend_string_init_interned("TOSTRING_USE_CURRENT", sizeof("TOSTRING_USE_CURRENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_TOSTRING_USE_CURRENT_name, &const_TOSTRING_USE_CURRENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TOSTRING_USE_CURRENT_name); + zend_string_release_ex(const_TOSTRING_USE_CURRENT_name, true); zval const_TOSTRING_USE_INNER_value; ZVAL_LONG(&const_TOSTRING_USE_INNER_value, CIT_TOSTRING_USE_INNER); - zend_string *const_TOSTRING_USE_INNER_name = zend_string_init_interned("TOSTRING_USE_INNER", sizeof("TOSTRING_USE_INNER") - 1, 1); + zend_string *const_TOSTRING_USE_INNER_name = zend_string_init_interned("TOSTRING_USE_INNER", sizeof("TOSTRING_USE_INNER") - 1, true); zend_declare_typed_class_constant(class_entry, const_TOSTRING_USE_INNER_name, &const_TOSTRING_USE_INNER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TOSTRING_USE_INNER_name); + zend_string_release_ex(const_TOSTRING_USE_INNER_name, true); zval const_FULL_CACHE_value; ZVAL_LONG(&const_FULL_CACHE_value, CIT_FULL_CACHE); - zend_string *const_FULL_CACHE_name = zend_string_init_interned("FULL_CACHE", sizeof("FULL_CACHE") - 1, 1); + zend_string *const_FULL_CACHE_name = zend_string_init_interned("FULL_CACHE", sizeof("FULL_CACHE") - 1, true); zend_declare_typed_class_constant(class_entry, const_FULL_CACHE_name, &const_FULL_CACHE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FULL_CACHE_name); + zend_string_release_ex(const_FULL_CACHE_name, true); return class_entry; } @@ -849,51 +849,51 @@ static zend_class_entry *register_class_RegexIterator(zend_class_entry *class_en zval const_USE_KEY_value; ZVAL_LONG(&const_USE_KEY_value, REGIT_USE_KEY); - zend_string *const_USE_KEY_name = zend_string_init_interned("USE_KEY", sizeof("USE_KEY") - 1, 1); + zend_string *const_USE_KEY_name = zend_string_init_interned("USE_KEY", sizeof("USE_KEY") - 1, true); zend_declare_typed_class_constant(class_entry, const_USE_KEY_name, &const_USE_KEY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_USE_KEY_name); + zend_string_release_ex(const_USE_KEY_name, true); zval const_INVERT_MATCH_value; ZVAL_LONG(&const_INVERT_MATCH_value, REGIT_INVERTED); - zend_string *const_INVERT_MATCH_name = zend_string_init_interned("INVERT_MATCH", sizeof("INVERT_MATCH") - 1, 1); + zend_string *const_INVERT_MATCH_name = zend_string_init_interned("INVERT_MATCH", sizeof("INVERT_MATCH") - 1, true); zend_declare_typed_class_constant(class_entry, const_INVERT_MATCH_name, &const_INVERT_MATCH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_INVERT_MATCH_name); + zend_string_release_ex(const_INVERT_MATCH_name, true); zval const_MATCH_value; ZVAL_LONG(&const_MATCH_value, REGIT_MODE_MATCH); - zend_string *const_MATCH_name = zend_string_init_interned("MATCH", sizeof("MATCH") - 1, 1); + zend_string *const_MATCH_name = zend_string_init_interned("MATCH", sizeof("MATCH") - 1, true); zend_declare_typed_class_constant(class_entry, const_MATCH_name, &const_MATCH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_MATCH_name); + zend_string_release_ex(const_MATCH_name, true); zval const_GET_MATCH_value; ZVAL_LONG(&const_GET_MATCH_value, REGIT_MODE_GET_MATCH); - zend_string *const_GET_MATCH_name = zend_string_init_interned("GET_MATCH", sizeof("GET_MATCH") - 1, 1); + zend_string *const_GET_MATCH_name = zend_string_init_interned("GET_MATCH", sizeof("GET_MATCH") - 1, true); zend_declare_typed_class_constant(class_entry, const_GET_MATCH_name, &const_GET_MATCH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_GET_MATCH_name); + zend_string_release_ex(const_GET_MATCH_name, true); zval const_ALL_MATCHES_value; ZVAL_LONG(&const_ALL_MATCHES_value, REGIT_MODE_ALL_MATCHES); - zend_string *const_ALL_MATCHES_name = zend_string_init_interned("ALL_MATCHES", sizeof("ALL_MATCHES") - 1, 1); + zend_string *const_ALL_MATCHES_name = zend_string_init_interned("ALL_MATCHES", sizeof("ALL_MATCHES") - 1, true); zend_declare_typed_class_constant(class_entry, const_ALL_MATCHES_name, &const_ALL_MATCHES_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ALL_MATCHES_name); + zend_string_release_ex(const_ALL_MATCHES_name, true); zval const_SPLIT_value; ZVAL_LONG(&const_SPLIT_value, REGIT_MODE_SPLIT); - zend_string *const_SPLIT_name = zend_string_init_interned("SPLIT", sizeof("SPLIT") - 1, 1); + zend_string *const_SPLIT_name = zend_string_init_interned("SPLIT", sizeof("SPLIT") - 1, true); zend_declare_typed_class_constant(class_entry, const_SPLIT_name, &const_SPLIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SPLIT_name); + zend_string_release_ex(const_SPLIT_name, true); zval const_REPLACE_value; ZVAL_LONG(&const_REPLACE_value, REGIT_MODE_REPLACE); - zend_string *const_REPLACE_name = zend_string_init_interned("REPLACE", sizeof("REPLACE") - 1, 1); + zend_string *const_REPLACE_name = zend_string_init_interned("REPLACE", sizeof("REPLACE") - 1, true); zend_declare_typed_class_constant(class_entry, const_REPLACE_name, &const_REPLACE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_REPLACE_name); + zend_string_release_ex(const_REPLACE_name, true); zval property_replacement_default_value; ZVAL_NULL(&property_replacement_default_value); - zend_string *property_replacement_name = zend_string_init("replacement", sizeof("replacement") - 1, 1); + zend_string *property_replacement_name = zend_string_init("replacement", sizeof("replacement") - 1, true); zend_declare_typed_property(class_entry, property_replacement_name, &property_replacement_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_replacement_name); + zend_string_release_ex(property_replacement_name, true); return class_entry; } @@ -918,51 +918,51 @@ static zend_class_entry *register_class_RecursiveTreeIterator(zend_class_entry * zval const_BYPASS_CURRENT_value; ZVAL_LONG(&const_BYPASS_CURRENT_value, RTIT_BYPASS_CURRENT); - zend_string *const_BYPASS_CURRENT_name = zend_string_init_interned("BYPASS_CURRENT", sizeof("BYPASS_CURRENT") - 1, 1); + zend_string *const_BYPASS_CURRENT_name = zend_string_init_interned("BYPASS_CURRENT", sizeof("BYPASS_CURRENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_BYPASS_CURRENT_name, &const_BYPASS_CURRENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BYPASS_CURRENT_name); + zend_string_release_ex(const_BYPASS_CURRENT_name, true); zval const_BYPASS_KEY_value; ZVAL_LONG(&const_BYPASS_KEY_value, RTIT_BYPASS_KEY); - zend_string *const_BYPASS_KEY_name = zend_string_init_interned("BYPASS_KEY", sizeof("BYPASS_KEY") - 1, 1); + zend_string *const_BYPASS_KEY_name = zend_string_init_interned("BYPASS_KEY", sizeof("BYPASS_KEY") - 1, true); zend_declare_typed_class_constant(class_entry, const_BYPASS_KEY_name, &const_BYPASS_KEY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_BYPASS_KEY_name); + zend_string_release_ex(const_BYPASS_KEY_name, true); zval const_PREFIX_LEFT_value; ZVAL_LONG(&const_PREFIX_LEFT_value, 0); - zend_string *const_PREFIX_LEFT_name = zend_string_init_interned("PREFIX_LEFT", sizeof("PREFIX_LEFT") - 1, 1); + zend_string *const_PREFIX_LEFT_name = zend_string_init_interned("PREFIX_LEFT", sizeof("PREFIX_LEFT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PREFIX_LEFT_name, &const_PREFIX_LEFT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PREFIX_LEFT_name); + zend_string_release_ex(const_PREFIX_LEFT_name, true); zval const_PREFIX_MID_HAS_NEXT_value; ZVAL_LONG(&const_PREFIX_MID_HAS_NEXT_value, 1); - zend_string *const_PREFIX_MID_HAS_NEXT_name = zend_string_init_interned("PREFIX_MID_HAS_NEXT", sizeof("PREFIX_MID_HAS_NEXT") - 1, 1); + zend_string *const_PREFIX_MID_HAS_NEXT_name = zend_string_init_interned("PREFIX_MID_HAS_NEXT", sizeof("PREFIX_MID_HAS_NEXT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PREFIX_MID_HAS_NEXT_name, &const_PREFIX_MID_HAS_NEXT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PREFIX_MID_HAS_NEXT_name); + zend_string_release_ex(const_PREFIX_MID_HAS_NEXT_name, true); zval const_PREFIX_MID_LAST_value; ZVAL_LONG(&const_PREFIX_MID_LAST_value, 2); - zend_string *const_PREFIX_MID_LAST_name = zend_string_init_interned("PREFIX_MID_LAST", sizeof("PREFIX_MID_LAST") - 1, 1); + zend_string *const_PREFIX_MID_LAST_name = zend_string_init_interned("PREFIX_MID_LAST", sizeof("PREFIX_MID_LAST") - 1, true); zend_declare_typed_class_constant(class_entry, const_PREFIX_MID_LAST_name, &const_PREFIX_MID_LAST_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PREFIX_MID_LAST_name); + zend_string_release_ex(const_PREFIX_MID_LAST_name, true); zval const_PREFIX_END_HAS_NEXT_value; ZVAL_LONG(&const_PREFIX_END_HAS_NEXT_value, 3); - zend_string *const_PREFIX_END_HAS_NEXT_name = zend_string_init_interned("PREFIX_END_HAS_NEXT", sizeof("PREFIX_END_HAS_NEXT") - 1, 1); + zend_string *const_PREFIX_END_HAS_NEXT_name = zend_string_init_interned("PREFIX_END_HAS_NEXT", sizeof("PREFIX_END_HAS_NEXT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PREFIX_END_HAS_NEXT_name, &const_PREFIX_END_HAS_NEXT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PREFIX_END_HAS_NEXT_name); + zend_string_release_ex(const_PREFIX_END_HAS_NEXT_name, true); zval const_PREFIX_END_LAST_value; ZVAL_LONG(&const_PREFIX_END_LAST_value, 4); - zend_string *const_PREFIX_END_LAST_name = zend_string_init_interned("PREFIX_END_LAST", sizeof("PREFIX_END_LAST") - 1, 1); + zend_string *const_PREFIX_END_LAST_name = zend_string_init_interned("PREFIX_END_LAST", sizeof("PREFIX_END_LAST") - 1, true); zend_declare_typed_class_constant(class_entry, const_PREFIX_END_LAST_name, &const_PREFIX_END_LAST_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PREFIX_END_LAST_name); + zend_string_release_ex(const_PREFIX_END_LAST_name, true); zval const_PREFIX_RIGHT_value; ZVAL_LONG(&const_PREFIX_RIGHT_value, 5); - zend_string *const_PREFIX_RIGHT_name = zend_string_init_interned("PREFIX_RIGHT", sizeof("PREFIX_RIGHT") - 1, 1); + zend_string *const_PREFIX_RIGHT_name = zend_string_init_interned("PREFIX_RIGHT", sizeof("PREFIX_RIGHT") - 1, true); zend_declare_typed_class_constant(class_entry, const_PREFIX_RIGHT_name, &const_PREFIX_RIGHT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PREFIX_RIGHT_name); + zend_string_release_ex(const_PREFIX_RIGHT_name, true); return class_entry; } diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index 4eeb33710276e..801c091fbb42d 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" @@ -672,9 +673,7 @@ PHP_METHOD(SplObjectStorage, rewind) { spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); intern->index = 0; @@ -685,9 +684,7 @@ PHP_METHOD(SplObjectStorage, valid) { spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_BOOL(zend_hash_has_more_elements_ex(&intern->storage, &intern->pos) == SUCCESS); } /* }}} */ @@ -697,9 +694,7 @@ PHP_METHOD(SplObjectStorage, key) { spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_LONG(intern->index); } /* }}} */ @@ -710,9 +705,7 @@ PHP_METHOD(SplObjectStorage, current) spl_SplObjectStorageElement *element; spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); if ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) == NULL) { zend_throw_exception(spl_ce_RuntimeException, "Called current() on invalid iterator", 0); @@ -727,9 +720,7 @@ PHP_METHOD(SplObjectStorage, getInfo) spl_SplObjectStorageElement *element; spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); if ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) == NULL) { RETURN_NULL(); @@ -762,9 +753,7 @@ PHP_METHOD(SplObjectStorage, next) { spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); zend_hash_move_forward_ex(&intern->storage, &intern->pos); intern->index++; @@ -824,9 +813,7 @@ PHP_METHOD(SplObjectStorage, serialize) php_serialize_data_t var_hash; smart_str buf = {0}; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); PHP_VAR_SERIALIZE_INIT(var_hash); @@ -998,9 +985,7 @@ PHP_METHOD(SplObjectStorage, __serialize) spl_SplObjectStorageElement *elem; zval tmp; - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); array_init(return_value); @@ -1068,9 +1053,7 @@ PHP_METHOD(SplObjectStorage, __unserialize) /* {{{ */ PHP_METHOD(SplObjectStorage, __debugInfo) { - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_ARR(spl_object_storage_debug_info(Z_OBJ_P(ZEND_THIS))); } @@ -1099,9 +1082,7 @@ PHP_METHOD(MultipleIterator, getFlags) { spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_LONG(intern->flags); } /* }}} */ @@ -1192,9 +1173,7 @@ PHP_METHOD(MultipleIterator, countIterators) { spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_LONG(zend_hash_num_elements(&intern->storage)); } @@ -1207,9 +1186,7 @@ PHP_METHOD(MultipleIterator, rewind) intern = Z_SPLOBJSTORAGE_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL && !EG(exception)) { @@ -1228,9 +1205,7 @@ PHP_METHOD(MultipleIterator, next) intern = Z_SPLOBJSTORAGE_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL && !EG(exception)) { @@ -1251,9 +1226,7 @@ PHP_METHOD(MultipleIterator, valid) intern = Z_SPLOBJSTORAGE_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); if (!zend_hash_num_elements(&intern->storage)) { RETURN_FALSE; @@ -1360,9 +1333,7 @@ PHP_METHOD(MultipleIterator, current) spl_SplObjectStorage *intern; intern = Z_SPLOBJSTORAGE_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); spl_multiple_iterator_get_all(intern, SPL_MULTIPLE_ITERATOR_GET_ALL_CURRENT, return_value); } @@ -1374,9 +1345,7 @@ PHP_METHOD(MultipleIterator, key) spl_SplObjectStorage *intern; intern = Z_SPLOBJSTORAGE_P(ZEND_THIS); - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_NONE(); spl_multiple_iterator_get_all(intern, SPL_MULTIPLE_ITERATOR_GET_ALL_KEY, return_value); } 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..fec3ccb84203d 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; } @@ -271,27 +293,27 @@ static zend_class_entry *register_class_MultipleIterator(zend_class_entry *class zval const_MIT_NEED_ANY_value; ZVAL_LONG(&const_MIT_NEED_ANY_value, MIT_NEED_ANY); - zend_string *const_MIT_NEED_ANY_name = zend_string_init_interned("MIT_NEED_ANY", sizeof("MIT_NEED_ANY") - 1, 1); + zend_string *const_MIT_NEED_ANY_name = zend_string_init_interned("MIT_NEED_ANY", sizeof("MIT_NEED_ANY") - 1, true); zend_declare_typed_class_constant(class_entry, const_MIT_NEED_ANY_name, &const_MIT_NEED_ANY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_MIT_NEED_ANY_name); + zend_string_release_ex(const_MIT_NEED_ANY_name, true); zval const_MIT_NEED_ALL_value; ZVAL_LONG(&const_MIT_NEED_ALL_value, MIT_NEED_ALL); - zend_string *const_MIT_NEED_ALL_name = zend_string_init_interned("MIT_NEED_ALL", sizeof("MIT_NEED_ALL") - 1, 1); + zend_string *const_MIT_NEED_ALL_name = zend_string_init_interned("MIT_NEED_ALL", sizeof("MIT_NEED_ALL") - 1, true); zend_declare_typed_class_constant(class_entry, const_MIT_NEED_ALL_name, &const_MIT_NEED_ALL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_MIT_NEED_ALL_name); + zend_string_release_ex(const_MIT_NEED_ALL_name, true); zval const_MIT_KEYS_NUMERIC_value; ZVAL_LONG(&const_MIT_KEYS_NUMERIC_value, MIT_KEYS_NUMERIC); - zend_string *const_MIT_KEYS_NUMERIC_name = zend_string_init_interned("MIT_KEYS_NUMERIC", sizeof("MIT_KEYS_NUMERIC") - 1, 1); + zend_string *const_MIT_KEYS_NUMERIC_name = zend_string_init_interned("MIT_KEYS_NUMERIC", sizeof("MIT_KEYS_NUMERIC") - 1, true); zend_declare_typed_class_constant(class_entry, const_MIT_KEYS_NUMERIC_name, &const_MIT_KEYS_NUMERIC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_MIT_KEYS_NUMERIC_name); + zend_string_release_ex(const_MIT_KEYS_NUMERIC_name, true); zval const_MIT_KEYS_ASSOC_value; ZVAL_LONG(&const_MIT_KEYS_ASSOC_value, MIT_KEYS_ASSOC); - zend_string *const_MIT_KEYS_ASSOC_name = zend_string_init_interned("MIT_KEYS_ASSOC", sizeof("MIT_KEYS_ASSOC") - 1, 1); + zend_string *const_MIT_KEYS_ASSOC_name = zend_string_init_interned("MIT_KEYS_ASSOC", sizeof("MIT_KEYS_ASSOC") - 1, true); zend_declare_typed_class_constant(class_entry, const_MIT_KEYS_ASSOC_name, &const_MIT_KEYS_ASSOC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_MIT_KEYS_ASSOC_name); + zend_string_release_ex(const_MIT_KEYS_ASSOC_name, true); 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/ArrayObject_clone_other_std_props.phpt b/ext/spl/tests/ArrayObject/ArrayObject_clone_other_std_props.phpt new file mode 100644 index 0000000000000..f527f5b664586 --- /dev/null +++ b/ext/spl/tests/ArrayObject/ArrayObject_clone_other_std_props.phpt @@ -0,0 +1,24 @@ +--TEST-- +Clone ArrayObject using other with STD_PROP_LIST +--FILE-- + +--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) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(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/ArrayObject_enum.phpt b/ext/spl/tests/ArrayObject/ArrayObject_enum.phpt new file mode 100644 index 0000000000000..a88da8fc5539c --- /dev/null +++ b/ext/spl/tests/ArrayObject/ArrayObject_enum.phpt @@ -0,0 +1,17 @@ +--TEST-- +Enums are not compatible with ArrayObject +--FILE-- + +--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/ArrayObject_get_object_vars.phpt b/ext/spl/tests/ArrayObject/ArrayObject_get_object_vars.phpt new file mode 100644 index 0000000000000..2e6b3d27f1566 --- /dev/null +++ b/ext/spl/tests/ArrayObject/ArrayObject_get_object_vars.phpt @@ -0,0 +1,31 @@ +--TEST-- +get_object_vars() on ArrayObject works on the properties of the ArrayObject itself +--FILE-- +getObjectVars()); + +?> +--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) { + ["test"]=> + NULL +} 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/ArrayObject_modify_shared_object_properties.phpt b/ext/spl/tests/ArrayObject/ArrayObject_modify_shared_object_properties.phpt new file mode 100644 index 0000000000000..69424204456b4 --- /dev/null +++ b/ext/spl/tests/ArrayObject/ArrayObject_modify_shared_object_properties.phpt @@ -0,0 +1,20 @@ +--TEST-- +Modifications to ArrayObjects should not affect shared properties tables +--FILE-- + 1, 'b' => 2]; +$ao = new ArrayObject($obj); +$arr = (array) $obj; +$ao['a'] = 42; +var_dump($arr); + +?> +--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) + ["b"]=> + int(2) +} diff --git a/ext/spl/tests/ArrayObject/ArrayObject_overloaded_SplFixedArray.phpt b/ext/spl/tests/ArrayObject/ArrayObject_overloaded_SplFixedArray.phpt new file mode 100644 index 0000000000000..13065b4ac38a9 --- /dev/null +++ b/ext/spl/tests/ArrayObject/ArrayObject_overloaded_SplFixedArray.phpt @@ -0,0 +1,17 @@ +--TEST-- +SplFixedArray properties is incompatible with ArrayObject +--FILE-- +exchangeArray($fixedArray); +} catch (InvalidArgumentException $e) { + echo $e->getMessage(), "\n"; +} +?> +--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/ArrayObject_overloaded_object_incompatible.phpt b/ext/spl/tests/ArrayObject/ArrayObject_overloaded_object_incompatible.phpt new file mode 100644 index 0000000000000..8cc66facc0053 --- /dev/null +++ b/ext/spl/tests/ArrayObject/ArrayObject_overloaded_object_incompatible.phpt @@ -0,0 +1,28 @@ +--TEST-- +Objects with overloaded get_properties are incompatible with ArrayObject +--FILE-- +exchangeArray(new DateInterval('P1D')); +} catch (Exception $e) { + echo $e->getMessage(), "\n"; +} +var_dump($ao); + +?> +--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]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} diff --git a/ext/spl/tests/ArrayObject/ArrayObject_proptable_canonicalization.phpt b/ext/spl/tests/ArrayObject/ArrayObject_proptable_canonicalization.phpt new file mode 100644 index 0000000000000..fd10797f72b06 --- /dev/null +++ b/ext/spl/tests/ArrayObject/ArrayObject_proptable_canonicalization.phpt @@ -0,0 +1,34 @@ +--TEST-- +When ArrayObject wraps an object, we should use prop table canonicalization +--FILE-- + +--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) +} +object(stdClass)#1 (1) { + ["0"]=> + int(2) +} +bool(true) +array(1) { + [0]=> + int(2) +} +object(stdClass)#1 (0) { +} diff --git a/ext/spl/tests/ArrayObject/ArrayObject_sort_different_backing_storage.phpt b/ext/spl/tests/ArrayObject/ArrayObject_sort_different_backing_storage.phpt new file mode 100644 index 0000000000000..34ecc1018c065 --- /dev/null +++ b/ext/spl/tests/ArrayObject/ArrayObject_sort_different_backing_storage.phpt @@ -0,0 +1,81 @@ +--TEST-- +Test sorting of various ArrayObject backing storage +--FILE-- + 2, 'b' => 1]; +$ao = new ArrayObject($obj); +$ao->uasort(function($a, $b) { return $a <=> $b; }); +var_dump($ao); + +$ao2 = new ArrayObject($ao); +$ao2->uasort(function($a, $b) { return $b <=> $a; }); +var_dump($ao2); + +$ao3 = new ArrayObject(); +$ao3->exchangeArray($ao3); +$ao3->a = 2; +$ao3->b = 1; +$ao3->uasort(function($a, $b) { return $a <=> $b; }); +var_dump($ao3); + +$ao4 = new ArrayObject([]); +$ao4->uasort(function($a, $b) { return $a <=> $b; }); +var_dump($ao4); + +$ao5 = new ArrayObject(['a' => 2, 'b' => 1]); +$ao5->uasort(function($a, $b) { return $a <=> $b; }); +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) { + ["b"]=> + int(1) + ["a"]=> + 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) { + ["storage":"ArrayObject":private]=> + object(stdClass)#1 (2) { + ["a"]=> + int(2) + ["b"]=> + int(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 +object(ArrayObject)#4 (2) { + ["b"]=> + int(1) + ["a"]=> + int(2) +} +object(ArrayObject)#5 (1) { + ["storage":"ArrayObject":private]=> + array(0) { + } +} +object(ArrayObject)#6 (1) { + ["storage":"ArrayObject":private]=> + array(2) { + ["b"]=> + int(1) + ["a"]=> + int(2) + } +} diff --git a/ext/spl/tests/ArrayObject/ArrayObject_std_props_no_recursion.phpt b/ext/spl/tests/ArrayObject/ArrayObject_std_props_no_recursion.phpt new file mode 100644 index 0000000000000..56f54844580d9 --- /dev/null +++ b/ext/spl/tests/ArrayObject/ArrayObject_std_props_no_recursion.phpt @@ -0,0 +1,37 @@ +--TEST-- +Don't recurse into USE_OTHER when checking for STD_PROP_LIST +--FILE-- +prop = 'a'; +$b = new ArrayObject($a, 0); +$b->prop = 'b'; +var_dump((array) $b); +$c = new ArrayObject($a); +$c->prop = 'c'; +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]=> + int(1) + [1]=> + int(2) + [2]=> + 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"]=> + string(1) "c" +} 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/arrayObject___construct_basic1.phpt b/ext/spl/tests/ArrayObject/arrayObject___construct_basic1.phpt new file mode 100644 index 0000000000000..744a936276bdc --- /dev/null +++ b/ext/spl/tests/ArrayObject/arrayObject___construct_basic1.phpt @@ -0,0 +1,58 @@ +--TEST-- +SPL: ArrayObject::__construct basic usage. +--FILE-- + No arguments:\n"; +var_dump(new ArrayObject()); + +echo "--> Object argument:\n"; +$a = new stdClass; +$a->p = 'hello'; +var_dump(new ArrayObject($a)); + +echo "--> Array argument:\n"; +var_dump(new ArrayObject(array('key1' => 'val1'))); + +echo "--> Nested ArrayObject argument:\n"; +var_dump(new ArrayObject(new ArrayObject($a))); +?> +--EXPECTF-- +--> No arguments: +object(ArrayObject)#1 (1) { + ["storage":"ArrayObject":private]=> + array(0) { + } +} +--> 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) { + ["p"]=> + string(5) "hello" + } +} +--> Array argument: +object(ArrayObject)#2 (1) { + ["storage":"ArrayObject":private]=> + array(1) { + ["key1"]=> + string(4) "val1" + } +} +--> 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) { + ["storage":"ArrayObject":private]=> + object(stdClass)#1 (1) { + ["p"]=> + string(5) "hello" + } + } +} 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/arrayObject___construct_basic7.phpt b/ext/spl/tests/ArrayObject/arrayObject___construct_basic7.phpt new file mode 100644 index 0000000000000..98131c8c6b4da --- /dev/null +++ b/ext/spl/tests/ArrayObject/arrayObject___construct_basic7.phpt @@ -0,0 +1,35 @@ +--TEST-- +SPL: ArrayObject::__construct: Using object with shared properties +--FILE-- +asort(); +var_dump($a, $o, $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 +array(2) { + [0]=> + int(2) + [1]=> + int(1) +} +object(stdClass)#1 (2) { + ["1"]=> + int(1) + ["0"]=> + int(2) +} +object(ArrayObject)#2 (1) { + ["storage":"ArrayObject":private]=> + object(stdClass)#1 (2) { + ["1"]=> + int(1) + ["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/arrayObject_exchangeArray_basic2.phpt b/ext/spl/tests/ArrayObject/arrayObject_exchangeArray_basic2.phpt new file mode 100644 index 0000000000000..4ba09cd388f28 --- /dev/null +++ b/ext/spl/tests/ArrayObject/arrayObject_exchangeArray_basic2.phpt @@ -0,0 +1,107 @@ +--TEST-- +SPL: ArrayObject::exchangeArray() with various object arguments +--FILE-- + exchangeArray(array):\n"; +$ao = new ArrayObject(); +$ao->exchangeArray(array('key'=>'original')); +var_dump($ao['key']); +var_dump($ao); + +echo "\n--> exchangeArray(normal object):\n"; +$obj = new stdClass; +$obj->key = 'normal object prop'; +$ao->exchangeArray($obj); +var_dump($ao['key']); +var_dump($ao); + +echo "\n--> exchangeArray(ArrayObject):\n"; +$obj = new ArrayObject(array('key'=>'ArrayObject element')); +$ao->exchangeArray($obj); +var_dump($ao['key']); +var_dump($ao); + +echo "\n--> exchangeArray(ArrayIterator):\n"; +$obj = new ArrayIterator(array('key'=>'ArrayIterator element')); +$ao->exchangeArray($obj); +var_dump($ao['key']); +var_dump($ao); + +echo "\n--> exchangeArray(nested ArrayObject):\n"; +$obj = new ArrayObject(new ArrayObject(array('key'=>'nested ArrayObject element'))); +$ao->exchangeArray($obj); +var_dump($ao['key']); +var_dump($ao); +?> +--EXPECTF-- +--> exchangeArray(array): +string(8) "original" +object(ArrayObject)#%d (1) { + ["storage":"ArrayObject":private]=> + array(1) { + ["key"]=> + string(8) "original" + } +} + +--> 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]=> + object(stdClass)#%d (1) { + ["key"]=> + string(18) "normal object prop" + } +} + +--> 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]=> + object(ArrayObject)#%d (1) { + ["storage":"ArrayObject":private]=> + array(1) { + ["key"]=> + string(19) "ArrayObject element" + } + } +} + +--> 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]=> + object(ArrayIterator)#%d (1) { + ["storage":"ArrayIterator":private]=> + array(1) { + ["key"]=> + string(21) "ArrayIterator element" + } + } +} + +--> 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]=> + object(ArrayObject)#%d (1) { + ["storage":"ArrayObject":private]=> + object(ArrayObject)#%d (1) { + ["storage":"ArrayObject":private]=> + array(1) { + ["key"]=> + string(26) "nested ArrayObject element" + } + } + } +} \ No newline at end of file diff --git a/ext/spl/tests/ArrayObject/arrayObject_exchangeArray_basic3.phpt b/ext/spl/tests/ArrayObject/arrayObject_exchangeArray_basic3.phpt new file mode 100644 index 0000000000000..8db9b016fda86 --- /dev/null +++ b/ext/spl/tests/ArrayObject/arrayObject_exchangeArray_basic3.phpt @@ -0,0 +1,141 @@ +--TEST-- +SPL: ArrayObject::exchangeArray() basic usage with object as underlying data store. +--FILE-- + exchangeArray() with objects:\n"; +$original = new C; +$ao = new ArrayObject($original); +$swapIn = new C; +try { + $copy = $ao->exchangeArray($swapIn); + $copy['addedToCopy'] = 'added To Copy'; +} catch (Exception $e) { + echo "Exception:" . $e->getMessage() . "\n"; +} +$swapIn->addedToSwapIn = 'added To Swap-In'; +$original->addedToOriginal = 'added To Original'; +var_dump($ao, $original, $swapIn, $copy); + + +echo "\n\n--> exchangeArray() with no arg:\n"; +unset($original, $ao, $swapIn, $copy); +$original = new C; +$ao = new ArrayObject($original); +try { + $copy = $ao->exchangeArray(); + $copy['addedToCopy'] = 'added To Copy'; +} catch (TypeError $e) { + echo "Exception: " . $e->getMessage() . "\n"; +} +$original->addedToOriginal = 'added To Original'; +var_dump($ao, $original, $copy); + +echo "\n\n--> exchangeArray() with bad arg type:\n"; +unset($original, $ao, $swapIn, $copy); +$original = new C; +$ao = new ArrayObject($original); +try { + $copy = $ao->exchangeArray(null); + $copy['addedToCopy'] = 'added To Copy'; +} catch (TypeError $e) { + echo $e->getMessage() . "\n"; +} +$original->addedToOriginal = 'added To Original'; +var_dump($ao, $original, $copy); + +?> +--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) { + ["pub1"]=> + string(7) "public1" + ["addedToSwapIn"]=> + string(16) "added To Swap-In" + } +} +object(C)#1 (2) { + ["pub1"]=> + string(7) "public1" + ["addedToOriginal"]=> + string(17) "added To Original" +} +object(C)#3 (2) { + ["pub1"]=> + string(7) "public1" + ["addedToSwapIn"]=> + string(16) "added To Swap-In" +} +array(2) { + ["pub1"]=> + string(7) "public1" + ["addedToCopy"]=> + string(13) "added To Copy" +} + + +--> 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]=> + object(C)#3 (2) { + ["pub1"]=> + string(7) "public1" + ["addedToOriginal"]=> + string(17) "added To Original" + } +} +object(C)#3 (2) { + ["pub1"]=> + string(7) "public1" + ["addedToOriginal"]=> + string(17) "added To Original" +} +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]=> + object(C)#2 (2) { + ["pub1"]=> + string(7) "public1" + ["addedToOriginal"]=> + string(17) "added To Original" + } +} +object(C)#2 (2) { + ["pub1"]=> + string(7) "public1" + ["addedToOriginal"]=> + string(17) "added To Original" +} +NULL 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/ArrayObject/array_022.phpt b/ext/spl/tests/ArrayObject/array_022.phpt new file mode 100644 index 0000000000000..4e8c94fd11815 --- /dev/null +++ b/ext/spl/tests/ArrayObject/array_022.phpt @@ -0,0 +1,72 @@ +--TEST-- +SPL: ArrayObject/Iterator and reference to self +--FILE-- +==ArrayObject=== + +==ArrayIterator=== + +--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" +} +object(MyArrayObject)#%d (2) { + ["bar"]=> + string(3) "baz" + ["baz"]=> + 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" +} +object(MyArrayIterator)#%d (2) { + ["bar"]=> + string(3) "baz" + ["baz"]=> + string(3) "Foo" +} 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/ArrayObject/array_025.phpt b/ext/spl/tests/ArrayObject/array_025.phpt new file mode 100644 index 0000000000000..4bd4c434f4804 --- /dev/null +++ b/ext/spl/tests/ArrayObject/array_025.phpt @@ -0,0 +1,43 @@ +--TEST-- +SPL: ArrayObject serialize with an object as storage +--FILE-- + +--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 + ( + [storage:ArrayObject:private] => Array + ( + [0] => 1 + [1] => 2 + ) + + ) + +) +O:11:"ArrayObject":4:{i:0;i:0;i:1;O:11:"ArrayObject":4:{i:0;i:0;i:1;a:2:{i:0;i:1;i:1;i:2;}i:2;a:0:{}i:3;N;}i:2;a:0:{}i:3;N;} +ArrayObject Object +( + [storage:ArrayObject:private] => ArrayObject Object + ( + [storage:ArrayObject:private] => Array + ( + [0] => 1 + [1] => 2 + ) + + ) + +) 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/ArrayObject/array_028.phpt b/ext/spl/tests/ArrayObject/array_028.phpt new file mode 100644 index 0000000000000..1e422fe2f990b --- /dev/null +++ b/ext/spl/tests/ArrayObject/array_028.phpt @@ -0,0 +1,29 @@ +--TEST-- +ArrayObject/Iterator on array with NUL bytes +--FILE-- + "bar", +]; + +$it = new ArrayIterator($array); +foreach ($it as $v) { + var_dump($v); +} + +$obj = new ArrayObject($array); +foreach ($obj as $v) { + var_dump($v); +} + +$obj = new ArrayObject($it); +foreach ($obj as $v) { + var_dump($v); +} +?> +--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/bug31346.phpt b/ext/spl/tests/ArrayObject/bug31346.phpt new file mode 100644 index 0000000000000..a1088dfd013e8 --- /dev/null +++ b/ext/spl/tests/ArrayObject/bug31346.phpt @@ -0,0 +1,19 @@ +--TEST-- +Bug #31486 (ArrayIterator::next segfaults) +--FILE-- +var1=1; + +$ao = new ArrayObject($obj); + +$i = $ao->getIterator(); + +$ao->offsetUnset($i->key()); +$i->next(); + +?> +===DONE=== +--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/ArrayObject/bug38618.phpt b/ext/spl/tests/ArrayObject/bug38618.phpt new file mode 100644 index 0000000000000..5a865f12d636e --- /dev/null +++ b/ext/spl/tests/ArrayObject/bug38618.phpt @@ -0,0 +1,108 @@ +--TEST-- +Bug #38618 (RecursiveArrayIterator::hasChildren() follows objects) +--FILE-- +title = $title; + } + + public function __toString() + { + return $this->title; + } +} + +class FruitProtected +{ + protected $title; + + public function __construct($title) + { + $this->title = $title; + } + + public function __toString() + { + return $this->title; + } +} + +function test_array($array, $which, $flags = 0) +{ + echo "===$which===\n"; + $it = new RecursiveArrayIterator($array, $flags); + foreach (new RecursiveIteratorIterator($it) as $k => $fruit) { + echo $k , ' => ', $fruit, "\n"; + } +} + +$array = array( + 1 => array( + 1 => array( + 1 => 'apple', + ), + 2 => array( + 1 => 'grape', + ), + ), +); + +test_array($array, 'Default with array'); + +$array = array( + 1 => array( + 1 => array( + 1 => new FruitPublic('apple'), + ), + 2 => array( + 1 => new FruitPublic('grape'), + ), + ), +); + +test_array($array, 'Public Property'); + +$array = array( + 1 => array( + 1 => array( + 1 => new FruitProtected('apple'), + ), + 2 => array( + 1 => new FruitProtected('grape'), + ), + ), +); + +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); +?> +--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 +===Protected Property New=== +1 => apple +1 => grape diff --git a/ext/spl/tests/ArrayObject/bug41691.phpt b/ext/spl/tests/ArrayObject/bug41691.phpt new file mode 100644 index 0000000000000..c808d59c2022f --- /dev/null +++ b/ext/spl/tests/ArrayObject/bug41691.phpt @@ -0,0 +1,30 @@ +--TEST-- +Bug #41691 (ArrayObject::exchangeArray hangs Apache) +--FILE-- +exchangeArray(array('a'=>1,'b'=>1,'c'=>1))); + +echo "Done\n"; +?> +--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 + ["b"]=> + NULL + ["c"]=> + NULL +} +Done 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/ArrayObject/bug54323.phpt b/ext/spl/tests/ArrayObject/bug54323.phpt new file mode 100644 index 0000000000000..fa1e64f4947c2 --- /dev/null +++ b/ext/spl/tests/ArrayObject/bug54323.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #54323 (Accessing unset()'ed ArrayObject's property causes crash) +--FILE-- +$value) { + } + unset($ao['prop']); + var_dump($c->prop, $ao['prop']); +} +?> +--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 +NULL +NULL diff --git a/ext/spl/tests/ArrayObject/bug62672.phpt b/ext/spl/tests/ArrayObject/bug62672.phpt new file mode 100644 index 0000000000000..2d70ca71a1bd4 --- /dev/null +++ b/ext/spl/tests/ArrayObject/bug62672.phpt @@ -0,0 +1,33 @@ +--TEST-- +Bug #62672 (Error on serialize of ArrayObject) +--FILE-- +_varA = $source; + } +} + +class ObjB extends ObjA +{ + private $_varB; + + public function __construct(ArrayObject $keys) + { + $this->_varB = $keys; + parent::__construct($keys->getIterator()); + } +} + +$obj = new ObjB(new ArrayObject()); + +var_dump($obj == unserialize(serialize($obj))); +?> +--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/ArrayObject/bug73209.phpt b/ext/spl/tests/ArrayObject/bug73209.phpt new file mode 100644 index 0000000000000..7da582b13523a --- /dev/null +++ b/ext/spl/tests/ArrayObject/bug73209.phpt @@ -0,0 +1,29 @@ +--TEST-- +Bug #73209: RecursiveArrayIterator does not iterate object properties +--FILE-- +props = ['hello' => 5, 'props' => ['keyme' => ['test' => 5]]]; + } +} +$data = new hello(); + +$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($data), RecursiveIteratorIterator::SELF_FIRST); +echo "Expect to see all keys in ->props here: \n"; + +foreach($iterator as $k=>$v) { + echo $k . "\n"; +} + +?> +--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 +props +keyme +test 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/ArrayObject/gh11178.phpt b/ext/spl/tests/ArrayObject/gh11178.phpt new file mode 100644 index 0000000000000..91ac55d6f814a --- /dev/null +++ b/ext/spl/tests/ArrayObject/gh11178.phpt @@ -0,0 +1,29 @@ +--TEST-- +GH-11178 (Segmentation fault in spl_array_it_get_current_data (PHP 8.1.18)) +--FILE-- +{'x'} = 1; + } + + function getIterator(): Traversable { + return new ArrayIterator($this); + } +} + +$obj = new A; + +foreach ($obj as $k => &$v) { + $v = 3; +} + +var_dump($obj); +?> +--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/ArrayObject/gh15833_1.phpt b/ext/spl/tests/ArrayObject/gh15833_1.phpt new file mode 100644 index 0000000000000..5ee4b69e32560 --- /dev/null +++ b/ext/spl/tests/ArrayObject/gh15833_1.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-15833 (Segmentation fault (access null pointer) in ext/spl/spl_array.c) +--CREDITS-- +YuanchengJiang +--FILE-- +newLazyProxy(function ($obj) { + $obj = new C(); + return $obj; +}); +$recursiveArrayIterator = new RecursiveArrayIterator($obj); +var_dump($recursiveArrayIterator->current()); +$recursiveArrayIterator->next(); +var_dump($recursiveArrayIterator->current()); +?> +--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/ArrayObject/gh15918.phpt b/ext/spl/tests/ArrayObject/gh15918.phpt new file mode 100644 index 0000000000000..5efdb887f9b56 --- /dev/null +++ b/ext/spl/tests/ArrayObject/gh15918.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-15918 (Assertion failure in ext/spl/spl_fixedarray.c) +--FILE-- +getMessage(), "\n"; +} +?> +--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/ArrayObject/gh16646.phpt b/ext/spl/tests/ArrayObject/gh16646.phpt new file mode 100644 index 0000000000000..f572346ea5dfa --- /dev/null +++ b/ext/spl/tests/ArrayObject/gh16646.phpt @@ -0,0 +1,33 @@ +--TEST-- +GH-16646: Use-after-free in ArrayObject::unset() with destructor +--FILE-- +b = $arg; + } +} + +class C { + function __destruct() { + global $arr; + echo __METHOD__, "\n"; + $arr->exchangeArray([]); + } +} + +$arr = new ArrayObject(new B(new C)); +unset($arr["b"]); +var_dump($arr); + +?> +--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]=> + array(0) { + } +} diff --git a/ext/spl/tests/ArrayObject/gh16646_2.phpt b/ext/spl/tests/ArrayObject/gh16646_2.phpt new file mode 100644 index 0000000000000..035087fbe22bb --- /dev/null +++ b/ext/spl/tests/ArrayObject/gh16646_2.phpt @@ -0,0 +1,26 @@ +--TEST-- +GH-16646: Use-after-free in ArrayObject::exchangeArray() with destructor +--FILE-- +exchangeArray([]); + } +} + +$arr = new ArrayObject(new C); +$arr->exchangeArray([]); +var_dump($arr); + +?> +--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]=> + array(0) { + } +} 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_clone_other_std_props.phpt b/ext/spl/tests/ArrayObject_clone_other_std_props.phpt deleted file mode 100644 index 688954c3d7b13..0000000000000 --- a/ext/spl/tests/ArrayObject_clone_other_std_props.phpt +++ /dev/null @@ -1,23 +0,0 @@ ---TEST-- -Clone ArrayObject using other with STD_PROP_LIST ---FILE-- - ---EXPECT-- -object(ArrayObject)#3 (1) { - ["storage":"ArrayObject":private]=> - array(3) { - [0]=> - int(1) - [1]=> - int(2) - [2]=> - int(3) - } -} diff --git a/ext/spl/tests/ArrayObject_enum.phpt b/ext/spl/tests/ArrayObject_enum.phpt deleted file mode 100644 index 906c89b54dff1..0000000000000 --- a/ext/spl/tests/ArrayObject_enum.phpt +++ /dev/null @@ -1,15 +0,0 @@ ---TEST-- -Enums are not compatible with ArrayObject ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught InvalidArgumentException: Enums are not compatible with ArrayObject in %s:%d -%a diff --git a/ext/spl/tests/ArrayObject_get_object_vars.phpt b/ext/spl/tests/ArrayObject_get_object_vars.phpt deleted file mode 100644 index a80add6b95ad7..0000000000000 --- a/ext/spl/tests/ArrayObject_get_object_vars.phpt +++ /dev/null @@ -1,30 +0,0 @@ ---TEST-- -get_object_vars() on ArrayObject works on the properties of the ArrayObject itself ---FILE-- -getObjectVars()); - -?> ---EXPECT-- -array(0) { -} -array(1) { - ["test"]=> - NULL -} diff --git a/ext/spl/tests/ArrayObject_modify_shared_object_properties.phpt b/ext/spl/tests/ArrayObject_modify_shared_object_properties.phpt deleted file mode 100644 index 24c247cabd9d0..0000000000000 --- a/ext/spl/tests/ArrayObject_modify_shared_object_properties.phpt +++ /dev/null @@ -1,19 +0,0 @@ ---TEST-- -Modifications to ArrayObjects should not affect shared properties tables ---FILE-- - 1, 'b' => 2]; -$ao = new ArrayObject($obj); -$arr = (array) $obj; -$ao['a'] = 42; -var_dump($arr); - -?> ---EXPECT-- -array(2) { - ["a"]=> - int(1) - ["b"]=> - int(2) -} diff --git a/ext/spl/tests/ArrayObject_overloaded_SplFixedArray.phpt b/ext/spl/tests/ArrayObject_overloaded_SplFixedArray.phpt deleted file mode 100644 index f46e4cc1c9aa4..0000000000000 --- a/ext/spl/tests/ArrayObject_overloaded_SplFixedArray.phpt +++ /dev/null @@ -1,16 +0,0 @@ ---TEST-- -SplFixedArray properties is incompatible with ArrayObject ---FILE-- -exchangeArray($fixedArray); -} catch (InvalidArgumentException $e) { - echo $e->getMessage(), "\n"; -} -?> ---EXPECT-- -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_overloaded_object_incompatible.phpt deleted file mode 100644 index 67267f0ec6a12..0000000000000 --- a/ext/spl/tests/ArrayObject_overloaded_object_incompatible.phpt +++ /dev/null @@ -1,27 +0,0 @@ ---TEST-- -Objects with overloaded get_properties are incompatible with ArrayObject ---FILE-- -exchangeArray(new DateInterval('P1D')); -} catch (Exception $e) { - echo $e->getMessage(), "\n"; -} -var_dump($ao); - -?> ---EXPECT-- -Overloaded object of type DateInterval is not compatible with ArrayObject -object(ArrayObject)#1 (1) { - ["storage":"ArrayObject":private]=> - array(3) { - [0]=> - int(1) - [1]=> - int(2) - [2]=> - int(3) - } -} diff --git a/ext/spl/tests/ArrayObject_proptable_canonicalization.phpt b/ext/spl/tests/ArrayObject_proptable_canonicalization.phpt deleted file mode 100644 index 006a152602682..0000000000000 --- a/ext/spl/tests/ArrayObject_proptable_canonicalization.phpt +++ /dev/null @@ -1,33 +0,0 @@ ---TEST-- -When ArrayObject wraps an object, we should use proptable canonicalization ---FILE-- - ---EXPECT-- -object(stdClass)#1 (1) { - ["0"]=> - int(1) -} -object(stdClass)#1 (1) { - ["0"]=> - int(2) -} -bool(true) -array(1) { - [0]=> - int(2) -} -object(stdClass)#1 (0) { -} diff --git a/ext/spl/tests/ArrayObject_sort_different_backing_storage.phpt b/ext/spl/tests/ArrayObject_sort_different_backing_storage.phpt deleted file mode 100644 index 93dd6570791c7..0000000000000 --- a/ext/spl/tests/ArrayObject_sort_different_backing_storage.phpt +++ /dev/null @@ -1,76 +0,0 @@ ---TEST-- -Test sorting of various ArrayObject backing storage ---FILE-- - 2, 'b' => 1]; -$ao = new ArrayObject($obj); -$ao->uasort(function($a, $b) { return $a <=> $b; }); -var_dump($ao); - -$ao2 = new ArrayObject($ao); -$ao2->uasort(function($a, $b) { return $b <=> $a; }); -var_dump($ao2); - -$ao3 = new ArrayObject(); -$ao3->exchangeArray($ao3); -$ao3->a = 2; -$ao3->b = 1; -$ao3->uasort(function($a, $b) { return $a <=> $b; }); -var_dump($ao3); - -$ao4 = new ArrayObject([]); -$ao4->uasort(function($a, $b) { return $a <=> $b; }); -var_dump($ao4); - -$ao5 = new ArrayObject(['a' => 2, 'b' => 1]); -$ao5->uasort(function($a, $b) { return $a <=> $b; }); -var_dump($ao5); - -?> ---EXPECTF-- -object(ArrayObject)#2 (1) { - ["storage":"ArrayObject":private]=> - object(stdClass)#1 (2) { - ["b"]=> - int(1) - ["a"]=> - int(2) - } -} -object(ArrayObject)#3 (1) { - ["storage":"ArrayObject":private]=> - object(ArrayObject)#2 (1) { - ["storage":"ArrayObject":private]=> - object(stdClass)#1 (2) { - ["a"]=> - int(2) - ["b"]=> - int(1) - } - } -} - -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 -object(ArrayObject)#4 (2) { - ["b"]=> - int(1) - ["a"]=> - int(2) -} -object(ArrayObject)#5 (1) { - ["storage":"ArrayObject":private]=> - array(0) { - } -} -object(ArrayObject)#6 (1) { - ["storage":"ArrayObject":private]=> - array(2) { - ["b"]=> - int(1) - ["a"]=> - int(2) - } -} diff --git a/ext/spl/tests/ArrayObject_std_props_no_recursion.phpt b/ext/spl/tests/ArrayObject_std_props_no_recursion.phpt deleted file mode 100644 index 55ec57762fa4e..0000000000000 --- a/ext/spl/tests/ArrayObject_std_props_no_recursion.phpt +++ /dev/null @@ -1,33 +0,0 @@ ---TEST-- -Don't recurse into USE_OTHER when checking for STD_PROP_LIST ---FILE-- -prop = 'a'; -$b = new ArrayObject($a, 0); -$b->prop = 'b'; -var_dump((array) $b); -$c = new ArrayObject($a); -$c->prop = 'c'; -var_dump((array) $c); - -?> ---EXPECTF-- -Deprecated: Creation of dynamic property ArrayObject::$prop is deprecated in %s on line %d - -Deprecated: Creation of dynamic property ArrayObject::$prop is deprecated in %s on line %d -array(3) { - [0]=> - int(1) - [1]=> - int(2) - [2]=> - int(3) -} - -Deprecated: Creation of dynamic property ArrayObject::$prop is deprecated in %s on line %d -array(1) { - ["prop"]=> - string(1) "c" -} diff --git a/ext/spl/tests/SplHeap_serialize_corrupted.phpt b/ext/spl/tests/SplHeap_serialize_corrupted.phpt new file mode 100644 index 0000000000000..8763a4c082937 --- /dev/null +++ b/ext/spl/tests/SplHeap_serialize_corrupted.phpt @@ -0,0 +1,67 @@ +--TEST-- +SplHeap and SplPriorityQueue serialization fails when corrupted +--FILE-- +insert(1); +$heap->insert(2); + +try { + $heap->insert('throw'); +} catch (Exception $e) { + // no-op, heap should now be corrupted +} + +echo "Heap is corrupted: " . ($heap->isCorrupted() ? 'YES' : 'NO') . "\n"; + +try { + serialize($heap); + echo "FAIL: Serialization should have thrown\n"; +} catch (Exception $e) { + echo "Serialization failed: " . $e->getMessage() . "\n"; +} + +class ThrowingPQ extends SplPriorityQueue { + public function compare($priority1, $priority2): int { + if ($priority1 === 'throw' || $priority2 === 'throw') { + throw new Exception('Priority comparison failed'); + } + return parent::compare($priority1, $priority2); + } +} + +$pq = new ThrowingPQ(); +$pq->insert('data1', 1); +$pq->insert('data2', 2); + +try { + $pq->insert('data3', 'throw'); +} catch (Exception $e) { + // no-op, queue is corrupted +} + +echo "PriorityQueue is corrupted: " . ($pq->isCorrupted() ? 'YES' : 'NO') . "\n"; + +try { + serialize($pq); + echo "FAIL: PQ Serialization should have thrown\n"; +} catch (Exception $e) { + echo "PQ Serialization failed: " . $e->getMessage() . "\n"; +} + +?> +--EXPECT-- +Heap is corrupted: YES +Serialization failed: Heap is corrupted, heap properties are no longer ensured. +PriorityQueue is corrupted: YES +PQ Serialization failed: Heap is corrupted, heap properties are no longer ensured. diff --git a/ext/spl/tests/SplHeap_serialize_error_handling.phpt b/ext/spl/tests/SplHeap_serialize_error_handling.phpt new file mode 100644 index 0000000000000..458f27db5ce03 --- /dev/null +++ b/ext/spl/tests/SplHeap_serialize_error_handling.phpt @@ -0,0 +1,84 @@ +--TEST-- +SplHeap and SplPriorityQueue unserialization error handling +--FILE-- + 'not_int']], + + // Missing heap_elements + [[], ['flags' => 0]], + + // Invalid heap_elements type + [[], ['flags' => 0, 'heap_elements' => 'not_array']], + [[], ['flags' => 0, 'heap_elements' => 123]], +]; + +foreach ($invalid_cases as $i => $case) { + try { + $heap = new SplMaxHeap(); + $heap->__unserialize($case); + echo "Case $i: UNEXPECTED SUCCESS\n"; + } catch (Exception $e) { + echo "Case $i: " . $e->getMessage() . "\n"; + } +} + +$pq_invalid_cases = [ + // Invalid flags for PQ + [[], ['flags' => 0]], + + // Invalid element structure + [[], ['flags' => 1, 'heap_elements' => ['not_array']]], + + // Missing data/priority keys + [[], ['flags' => 1, 'heap_elements' => [['data' => 'test']]]], + [[], ['flags' => 1, 'heap_elements' => [['priority' => 1]]]], + [[], ['flags' => 1, 'heap_elements' => [[]]]], +]; + +foreach ($pq_invalid_cases as $i => $case) { + try { + $pq = new SplPriorityQueue(); + $pq->__unserialize($case); + echo "PQ Case $i: UNEXPECTED SUCCESS\n"; + } catch (Exception $e) { + echo "PQ Case $i: " . $e->getMessage() . "\n"; + } +} + +?> +--EXPECT-- +Case 0: Invalid serialization data for SplMaxHeap object +Case 1: Invalid serialization data for SplMaxHeap object +Case 2: Invalid serialization data for SplMaxHeap object +Case 3: Invalid serialization data for SplMaxHeap object +Case 4: Invalid serialization data for SplMaxHeap object +Case 5: Invalid serialization data for SplMaxHeap object +Case 6: Invalid serialization data for SplMaxHeap object +Case 7: Invalid serialization data for SplMaxHeap object +Case 8: Invalid serialization data for SplMaxHeap object +Case 9: Invalid serialization data for SplMaxHeap object +Case 10: Invalid serialization data for SplMaxHeap object +PQ Case 0: Invalid serialization data for SplPriorityQueue object +PQ Case 1: Invalid serialization data for SplPriorityQueue object +PQ Case 2: Invalid serialization data for SplPriorityQueue object +PQ Case 3: Invalid serialization data for SplPriorityQueue object +PQ Case 4: Invalid serialization data for SplPriorityQueue object diff --git a/ext/spl/tests/SplHeap_serialize_format.phpt b/ext/spl/tests/SplHeap_serialize_format.phpt new file mode 100644 index 0000000000000..aaa1b56e2695a --- /dev/null +++ b/ext/spl/tests/SplHeap_serialize_format.phpt @@ -0,0 +1,131 @@ +--TEST-- +SplHeap serialization binary format +--FILE-- +insert(100); +$heap->insert(50); +$heap->insert(200); +$s = serialize($heap); +echo $s . "\n"; +$unserialized = unserialize($s); +var_dump($unserialized); + +// Test SplMinHeap +$min = new SplMinHeap(); +$min->insert(30); +$min->insert(10); +$min->insert(20); +$s = serialize($min); +echo $s . "\n"; +var_dump(unserialize($s)); + +// Test SplPriorityQueue empty +$pq = new SplPriorityQueue(); +$s = serialize($pq); +echo $s . "\n"; +var_dump(unserialize($s)); + +// Test SplPriorityQueue with data +$pq = new SplPriorityQueue(); +$pq->insert('low', 1); +$pq->insert('high', 10); +$pq->insert('medium', 5); +$pq->setExtractFlags(SplPriorityQueue::EXTR_BOTH); +$s = serialize($pq); +echo $s . "\n"; +var_dump(unserialize($s)); + +?> +--EXPECT-- +O:10:"SplMaxHeap":2:{i:0;a:0:{}i:1;a:2:{s:5:"flags";i:0;s:13:"heap_elements";a:0:{}}} +object(SplMaxHeap)#2 (3) { + ["flags":"SplHeap":private]=> + int(0) + ["isCorrupted":"SplHeap":private]=> + bool(false) + ["heap":"SplHeap":private]=> + array(0) { + } +} +O:10:"SplMaxHeap":2:{i:0;a:0:{}i:1;a:2:{s:5:"flags";i:0;s:13:"heap_elements";a:3:{i:0;i:200;i:1;i:50;i:2;i:100;}}} +object(SplMaxHeap)#1 (3) { + ["flags":"SplHeap":private]=> + int(0) + ["isCorrupted":"SplHeap":private]=> + bool(false) + ["heap":"SplHeap":private]=> + array(3) { + [0]=> + int(200) + [1]=> + int(50) + [2]=> + int(100) + } +} +O:10:"SplMinHeap":2:{i:0;a:0:{}i:1;a:2:{s:5:"flags";i:0;s:13:"heap_elements";a:3:{i:0;i:10;i:1;i:30;i:2;i:20;}}} +object(SplMinHeap)#4 (3) { + ["flags":"SplHeap":private]=> + int(0) + ["isCorrupted":"SplHeap":private]=> + bool(false) + ["heap":"SplHeap":private]=> + array(3) { + [0]=> + int(10) + [1]=> + int(30) + [2]=> + int(20) + } +} +O:16:"SplPriorityQueue":2:{i:0;a:0:{}i:1;a:2:{s:5:"flags";i:1;s:13:"heap_elements";a:0:{}}} +object(SplPriorityQueue)#5 (3) { + ["flags":"SplPriorityQueue":private]=> + int(1) + ["isCorrupted":"SplPriorityQueue":private]=> + bool(false) + ["heap":"SplPriorityQueue":private]=> + array(0) { + } +} +O:16:"SplPriorityQueue":2:{i:0;a:0:{}i:1;a:2:{s:5:"flags";i:3;s:13:"heap_elements";a:3:{i:0;a:2:{s:4:"data";s:4:"high";s:8:"priority";i:10;}i:1;a:2:{s:4:"data";s:3:"low";s:8:"priority";i:1;}i:2;a:2:{s:4:"data";s:6:"medium";s:8:"priority";i:5;}}}} +object(SplPriorityQueue)#4 (3) { + ["flags":"SplPriorityQueue":private]=> + int(3) + ["isCorrupted":"SplPriorityQueue":private]=> + bool(false) + ["heap":"SplPriorityQueue":private]=> + array(3) { + [0]=> + array(2) { + ["data"]=> + string(4) "high" + ["priority"]=> + int(10) + } + [1]=> + array(2) { + ["data"]=> + string(3) "low" + ["priority"]=> + int(1) + } + [2]=> + array(2) { + ["data"]=> + string(6) "medium" + ["priority"]=> + int(5) + } + } +} diff --git a/ext/spl/tests/SplHeap_serialize_indexed_format.phpt b/ext/spl/tests/SplHeap_serialize_indexed_format.phpt new file mode 100644 index 0000000000000..21ea74c6bff9b --- /dev/null +++ b/ext/spl/tests/SplHeap_serialize_indexed_format.phpt @@ -0,0 +1,91 @@ +--TEST-- +SplHeap serialization format - indexed array format prevents conflicts +--FILE-- +insert(100); +$heap->insert(50); +$heap->insert(200); + +$serialized_data = $heap->__serialize(); +var_dump($serialized_data); + +$pq = new SplPriorityQueue(); +$pq->insert('data', 10); +$pq->setExtractFlags(SplPriorityQueue::EXTR_DATA); + +$pq_data = $pq->__serialize(); +var_dump($pq_data); + +class CustomHeap extends SplMaxHeap { + public $flags = 'user_property'; + public $heap_elements = 'user_property'; +} + +$custom = new CustomHeap(); +$custom->insert(42); + +$custom_data = $custom->__serialize(); +var_dump($custom_data); + +?> +--EXPECT-- +array(2) { + [0]=> + array(0) { + } + [1]=> + array(2) { + ["flags"]=> + int(0) + ["heap_elements"]=> + array(3) { + [0]=> + int(200) + [1]=> + int(50) + [2]=> + int(100) + } + } +} +array(2) { + [0]=> + array(0) { + } + [1]=> + array(2) { + ["flags"]=> + int(1) + ["heap_elements"]=> + array(1) { + [0]=> + array(2) { + ["data"]=> + string(4) "data" + ["priority"]=> + int(10) + } + } + } +} +array(2) { + [0]=> + array(2) { + ["flags"]=> + string(13) "user_property" + ["heap_elements"]=> + string(13) "user_property" + } + [1]=> + array(2) { + ["flags"]=> + int(0) + ["heap_elements"]=> + array(1) { + [0]=> + int(42) + } + } +} diff --git a/ext/spl/tests/SplHeap_serialize_inheritance_safety.phpt b/ext/spl/tests/SplHeap_serialize_inheritance_safety.phpt new file mode 100644 index 0000000000000..c90b278e45b62 --- /dev/null +++ b/ext/spl/tests/SplHeap_serialize_inheritance_safety.phpt @@ -0,0 +1,117 @@ +--TEST-- +SplHeap and SplPriorityQueue inheritance safety with conflicting property names +--FILE-- +flags = 'modified_user_flags'; +$heap->heap_elements = 'modified_user_elements'; +$heap->custom_prop = 'modified_custom'; + +$heap->insert(100); +$heap->insert(50); +$heap->insert(200); + +$serialized = serialize($heap); +echo $serialized . "\n"; +$unserialized = unserialize($serialized); +var_dump($unserialized); + +class CustomPriorityQueue extends SplPriorityQueue { + public $flags = 'user_flags_property'; + public $heap_elements = 'user_heap_elements_property'; + public $custom_data = 'custom_data_value'; + protected $protected_priority = 'protected_priority_value'; +} + +$pq = new CustomPriorityQueue(); +$pq->flags = 'modified_user_flags'; +$pq->heap_elements = 'modified_user_elements'; +$pq->custom_data = 'modified_custom_data'; + +$pq->insert('low_priority', 1); +$pq->insert('high_priority', 10); +$pq->insert('medium_priority', 5); + +$pq->setExtractFlags(SplPriorityQueue::EXTR_BOTH); + +$serialized_pq = serialize($pq); +echo $serialized_pq . "\n"; +$unserialized_pq = unserialize($serialized_pq); +var_dump($unserialized_pq); + +?> +--EXPECTF-- +O:10:"CustomHeap":2:{i:0;a:5:{s:5:"flags";s:19:"modified_user_flags";s:13:"heap_elements";s:22:"modified_user_elements";s:11:"custom_prop";s:15:"modified_custom";s:17:"%0*%0protected_prop";s:15:"protected_value";s:24:"%0CustomHeap%0private_prop";s:13:"private_value";}i:1;a:2:{s:5:"flags";i:0;s:13:"heap_elements";a:3:{i:0;i:200;i:1;i:50;i:2;i:100;}}} +object(CustomHeap)#2 (8) { + ["flags"]=> + string(19) "modified_user_flags" + ["heap_elements"]=> + string(22) "modified_user_elements" + ["custom_prop"]=> + string(15) "modified_custom" + ["protected_prop":protected]=> + string(15) "protected_value" + ["private_prop":"CustomHeap":private]=> + string(13) "private_value" + ["flags":"SplHeap":private]=> + int(0) + ["isCorrupted":"SplHeap":private]=> + bool(false) + ["heap":"SplHeap":private]=> + array(3) { + [0]=> + int(200) + [1]=> + int(50) + [2]=> + int(100) + } +} +O:19:"CustomPriorityQueue":2:{i:0;a:4:{s:5:"flags";s:19:"modified_user_flags";s:13:"heap_elements";s:22:"modified_user_elements";s:11:"custom_data";s:20:"modified_custom_data";s:21:"%0*%0protected_priority";s:24:"protected_priority_value";}i:1;a:2:{s:5:"flags";i:3;s:13:"heap_elements";a:3:{i:0;a:2:{s:4:"data";s:13:"high_priority";s:8:"priority";i:10;}i:1;a:2:{s:4:"data";s:12:"low_priority";s:8:"priority";i:1;}i:2;a:2:{s:4:"data";s:15:"medium_priority";s:8:"priority";i:5;}}}} +object(CustomPriorityQueue)#4 (7) { + ["flags"]=> + string(19) "modified_user_flags" + ["heap_elements"]=> + string(22) "modified_user_elements" + ["custom_data"]=> + string(20) "modified_custom_data" + ["protected_priority":protected]=> + string(24) "protected_priority_value" + ["flags":"SplPriorityQueue":private]=> + int(3) + ["isCorrupted":"SplPriorityQueue":private]=> + bool(false) + ["heap":"SplPriorityQueue":private]=> + array(3) { + [0]=> + array(2) { + ["data"]=> + string(13) "high_priority" + ["priority"]=> + int(10) + } + [1]=> + array(2) { + ["data"]=> + string(12) "low_priority" + ["priority"]=> + int(1) + } + [2]=> + array(2) { + ["data"]=> + string(15) "medium_priority" + ["priority"]=> + int(5) + } + } +} diff --git a/ext/spl/tests/SplMaxHeap_serialize_complex.phpt b/ext/spl/tests/SplMaxHeap_serialize_complex.phpt new file mode 100644 index 0000000000000..9e83d779c416a --- /dev/null +++ b/ext/spl/tests/SplMaxHeap_serialize_complex.phpt @@ -0,0 +1,89 @@ +--TEST-- +SplMaxHeap serialization with complex data types +--FILE-- +insert(['type' => 'array1', 'value' => 10]); +$heap->insert(['type' => 'array2', 'value' => 20]); +$heap->insert(['type' => 'array3', 'value' => 5]); + +$serialized = serialize($heap); +echo $serialized . "\n"; + +$unserialized = unserialize($serialized); +var_dump($unserialized); + +class TestObj { + public $val; + public function __construct($v) { $this->val = $v; } +} + +$heap2 = new SplMaxHeap(); +$heap2->insert(new TestObj(30)); +$heap2->insert(new TestObj(10)); +$heap2->insert(new TestObj(20)); + +$serialized2 = serialize($heap2); +echo $serialized2 . "\n"; + +$unserialized2 = unserialize($serialized2); +var_dump($unserialized2); + +?> +--EXPECT-- +O:10:"SplMaxHeap":2:{i:0;a:0:{}i:1;a:2:{s:5:"flags";i:0;s:13:"heap_elements";a:3:{i:0;a:2:{s:4:"type";s:6:"array3";s:5:"value";i:5;}i:1;a:2:{s:4:"type";s:6:"array1";s:5:"value";i:10;}i:2;a:2:{s:4:"type";s:6:"array2";s:5:"value";i:20;}}}} +object(SplMaxHeap)#2 (3) { + ["flags":"SplHeap":private]=> + int(0) + ["isCorrupted":"SplHeap":private]=> + bool(false) + ["heap":"SplHeap":private]=> + array(3) { + [0]=> + array(2) { + ["type"]=> + string(6) "array3" + ["value"]=> + int(5) + } + [1]=> + array(2) { + ["type"]=> + string(6) "array1" + ["value"]=> + int(10) + } + [2]=> + array(2) { + ["type"]=> + string(6) "array2" + ["value"]=> + int(20) + } + } +} +O:10:"SplMaxHeap":2:{i:0;a:0:{}i:1;a:2:{s:5:"flags";i:0;s:13:"heap_elements";a:3:{i:0;O:7:"TestObj":1:{s:3:"val";i:30;}i:1;O:7:"TestObj":1:{s:3:"val";i:10;}i:2;O:7:"TestObj":1:{s:3:"val";i:20;}}}} +object(SplMaxHeap)#7 (3) { + ["flags":"SplHeap":private]=> + int(0) + ["isCorrupted":"SplHeap":private]=> + bool(false) + ["heap":"SplHeap":private]=> + array(3) { + [0]=> + object(TestObj)#8 (1) { + ["val"]=> + int(30) + } + [1]=> + object(TestObj)#9 (1) { + ["val"]=> + int(10) + } + [2]=> + object(TestObj)#10 (1) { + ["val"]=> + int(20) + } + } +} diff --git a/ext/spl/tests/SplMinHeap_serialize_complex.phpt b/ext/spl/tests/SplMinHeap_serialize_complex.phpt new file mode 100644 index 0000000000000..0f33fa3ae700b --- /dev/null +++ b/ext/spl/tests/SplMinHeap_serialize_complex.phpt @@ -0,0 +1,63 @@ +--TEST-- +SplMinHeap serialization with nested arrays +--FILE-- +insert(['name' => 'Alice', 'nested' => ['age' => 25, 'city' => 'NYC']]); +$heap->insert(['name' => 'Bob', 'nested' => ['age' => 30, 'city' => 'LA']]); +$heap->insert(['name' => 'Charlie', 'nested' => ['age' => 35, 'city' => 'SF']]); + +$serialized = serialize($heap); +echo $serialized . "\n"; + +$unserialized = unserialize($serialized); +var_dump($unserialized); + +?> +--EXPECT-- +O:10:"SplMinHeap":2:{i:0;a:0:{}i:1;a:2:{s:5:"flags";i:0;s:13:"heap_elements";a:3:{i:0;a:2:{s:4:"name";s:5:"Alice";s:6:"nested";a:2:{s:3:"age";i:25;s:4:"city";s:3:"NYC";}}i:1;a:2:{s:4:"name";s:3:"Bob";s:6:"nested";a:2:{s:3:"age";i:30;s:4:"city";s:2:"LA";}}i:2;a:2:{s:4:"name";s:7:"Charlie";s:6:"nested";a:2:{s:3:"age";i:35;s:4:"city";s:2:"SF";}}}}} +object(SplMinHeap)#2 (3) { + ["flags":"SplHeap":private]=> + int(0) + ["isCorrupted":"SplHeap":private]=> + bool(false) + ["heap":"SplHeap":private]=> + array(3) { + [0]=> + array(2) { + ["name"]=> + string(5) "Alice" + ["nested"]=> + array(2) { + ["age"]=> + int(25) + ["city"]=> + string(3) "NYC" + } + } + [1]=> + array(2) { + ["name"]=> + string(3) "Bob" + ["nested"]=> + array(2) { + ["age"]=> + int(30) + ["city"]=> + string(2) "LA" + } + } + [2]=> + array(2) { + ["name"]=> + string(7) "Charlie" + ["nested"]=> + array(2) { + ["age"]=> + int(35) + ["city"]=> + string(2) "SF" + } + } + } +} 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/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/SplObjectStorage/observer_008.phpt b/ext/spl/tests/SplObjectStorage/observer_008.phpt new file mode 100644 index 0000000000000..36769c57d5243 --- /dev/null +++ b/ext/spl/tests/SplObjectStorage/observer_008.phpt @@ -0,0 +1,32 @@ +--TEST-- +SPL: SplObjectStorage addAll/removeAll +--FILE-- +offsetSet($o1); +$a->offsetSet($o2); + +$b = new SplObjectStorage(); +$b->offsetSet($o2); +$b->offsetSet($o3); + +$a->offsetUnset($b); + +var_dump($a->count()); + +$a->offsetUnset($o3); +var_dump($a->count()); + +$a->removeAll($b); +var_dump($a->count()); +?> +--EXPECT-- +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/SplPriorityQueue_serialize_complex.phpt b/ext/spl/tests/SplPriorityQueue_serialize_complex.phpt new file mode 100644 index 0000000000000..61a3cb1aa8699 --- /dev/null +++ b/ext/spl/tests/SplPriorityQueue_serialize_complex.phpt @@ -0,0 +1,113 @@ +--TEST-- +SplPriorityQueue serialization with mixed data types and extract flags +--FILE-- +setExtractFlags(SplPriorityQueue::EXTR_BOTH); + +$array1 = ['name' => 'John', 'hobbies' => ['reading', 'gaming']]; +$queue->insert($array1, 10); + +class TestClass { + public $prop = 'test'; +} +$obj1 = new TestClass(); +$queue->insert($obj1, 15); + +$queue->insert(3.14159, 12); +$queue->insert(true, 20); +$queue->insert(null, 3); + +$serialized = serialize($queue); +echo $serialized . "\n"; + +$unserialized = unserialize($serialized); +var_dump($unserialized); + +$queue2 = new SplPriorityQueue(); +$queue2->setExtractFlags(SplPriorityQueue::EXTR_PRIORITY); +$queue2->insert("data", 42); + +$serialized2 = serialize($queue2); +echo $serialized2 . "\n"; + +$unserialized2 = unserialize($serialized2); +var_dump($unserialized2); + +?> +--EXPECT-- +O:16:"SplPriorityQueue":2:{i:0;a:0:{}i:1;a:2:{s:5:"flags";i:3;s:13:"heap_elements";a:5:{i:0;a:2:{s:4:"data";b:1;s:8:"priority";i:20;}i:1;a:2:{s:4:"data";O:9:"TestClass":1:{s:4:"prop";s:4:"test";}s:8:"priority";i:15;}i:2;a:2:{s:4:"data";d:3.14159;s:8:"priority";i:12;}i:3;a:2:{s:4:"data";a:2:{s:4:"name";s:4:"John";s:7:"hobbies";a:2:{i:0;s:7:"reading";i:1;s:6:"gaming";}}s:8:"priority";i:10;}i:4;a:2:{s:4:"data";N;s:8:"priority";i:3;}}}} +object(SplPriorityQueue)#3 (3) { + ["flags":"SplPriorityQueue":private]=> + int(3) + ["isCorrupted":"SplPriorityQueue":private]=> + bool(false) + ["heap":"SplPriorityQueue":private]=> + array(5) { + [0]=> + array(2) { + ["data"]=> + bool(true) + ["priority"]=> + int(20) + } + [1]=> + array(2) { + ["data"]=> + object(TestClass)#4 (1) { + ["prop"]=> + string(4) "test" + } + ["priority"]=> + int(15) + } + [2]=> + array(2) { + ["data"]=> + float(3.14159) + ["priority"]=> + int(12) + } + [3]=> + array(2) { + ["data"]=> + array(2) { + ["name"]=> + string(4) "John" + ["hobbies"]=> + array(2) { + [0]=> + string(7) "reading" + [1]=> + string(6) "gaming" + } + } + ["priority"]=> + int(10) + } + [4]=> + array(2) { + ["data"]=> + NULL + ["priority"]=> + int(3) + } + } +} +O:16:"SplPriorityQueue":2:{i:0;a:0:{}i:1;a:2:{s:5:"flags";i:2;s:13:"heap_elements";a:1:{i:0;a:2:{s:4:"data";s:4:"data";s:8:"priority";i:42;}}}} +object(SplPriorityQueue)#6 (3) { + ["flags":"SplPriorityQueue":private]=> + int(2) + ["isCorrupted":"SplPriorityQueue":private]=> + bool(false) + ["heap":"SplPriorityQueue":private]=> + array(1) { + [0]=> + array(2) { + ["data"]=> + string(4) "data" + ["priority"]=> + int(42) + } + } +} diff --git a/ext/spl/tests/SplPriorityQueue_unserialize_invalid_flags.phpt b/ext/spl/tests/SplPriorityQueue_unserialize_invalid_flags.phpt new file mode 100644 index 0000000000000..8c785606c7fe7 --- /dev/null +++ b/ext/spl/tests/SplPriorityQueue_unserialize_invalid_flags.phpt @@ -0,0 +1,80 @@ +--TEST-- +SplPriorityQueue unserialization with invalid flags should throw exception +--FILE-- + 4, // invalid flag value (4 & 3 = 0) + 'heap_elements' => [] + ] + ]; + + $queue = new SplPriorityQueue(); + $queue->__unserialize($data); + echo "Should have thrown exception for invalid flags\n"; +} catch (Exception $e) { + echo "Exception thrown for invalid flags: " . $e->getMessage() . "\n"; +} + +try { + $data = [ + [], + [ + 'flags' => 0, + 'heap_elements' => [] + ] + ]; + + $queue = new SplPriorityQueue(); + $queue->__unserialize($data); + echo "Should have thrown exception for zero flags\n"; +} catch (Exception $e) { + echo "Exception thrown for zero flags: " . $e->getMessage() . "\n"; +} + +try { + $data = [ + [], + [ + 'flags' => SplPriorityQueue::EXTR_DATA, + 'heap_elements' => [] + ] + ]; + + $queue = new SplPriorityQueue(); + $queue->__unserialize($data); + echo "Valid flags accepted\n"; +} catch (Exception $e) { + echo "Valid flags rejected: " . $e->getMessage() . "\n"; +} + +try { + $data = [ + [], + [ + 'flags' => 999, // extra bits that should be masked to 3 (EXTR_BOTH) + 'heap_elements' => [] + ] + ]; + + $queue = new SplPriorityQueue(); + $queue->__unserialize($data); + + if ($queue->getExtractFlags() === SplPriorityQueue::EXTR_BOTH) { + echo "Flags properly masked\n"; + } else { + echo "Flags not properly masked, got: " . $queue->getExtractFlags() . "\n"; + } +} catch (Exception $e) { + echo "Flags with extra bits should be masked: " . $e->getMessage() . "\n"; +} + +?> +--EXPECT-- +Exception thrown for invalid flags: Invalid serialization data for SplPriorityQueue object +Exception thrown for zero flags: Invalid serialization data for SplPriorityQueue object +Valid flags accepted +Flags properly masked diff --git a/ext/spl/tests/arrayObject___construct_basic1.phpt b/ext/spl/tests/arrayObject___construct_basic1.phpt deleted file mode 100644 index a14166c35e306..0000000000000 --- a/ext/spl/tests/arrayObject___construct_basic1.phpt +++ /dev/null @@ -1,52 +0,0 @@ ---TEST-- -SPL: ArrayObject::__construct basic usage. ---FILE-- - No arguments:\n"; -var_dump(new ArrayObject()); - -echo "--> Object argument:\n"; -$a = new stdClass; -$a->p = 'hello'; -var_dump(new ArrayObject($a)); - -echo "--> Array argument:\n"; -var_dump(new ArrayObject(array('key1' => 'val1'))); - -echo "--> Nested ArrayObject argument:\n"; -var_dump(new ArrayObject(new ArrayObject($a))); -?> ---EXPECT-- ---> No arguments: -object(ArrayObject)#1 (1) { - ["storage":"ArrayObject":private]=> - array(0) { - } -} ---> Object argument: -object(ArrayObject)#2 (1) { - ["storage":"ArrayObject":private]=> - object(stdClass)#1 (1) { - ["p"]=> - string(5) "hello" - } -} ---> Array argument: -object(ArrayObject)#2 (1) { - ["storage":"ArrayObject":private]=> - array(1) { - ["key1"]=> - string(4) "val1" - } -} ---> Nested ArrayObject argument: -object(ArrayObject)#2 (1) { - ["storage":"ArrayObject":private]=> - object(ArrayObject)#3 (1) { - ["storage":"ArrayObject":private]=> - object(stdClass)#1 (1) { - ["p"]=> - string(5) "hello" - } - } -} diff --git a/ext/spl/tests/arrayObject___construct_basic7.phpt b/ext/spl/tests/arrayObject___construct_basic7.phpt deleted file mode 100644 index dd10b5fb6b996..0000000000000 --- a/ext/spl/tests/arrayObject___construct_basic7.phpt +++ /dev/null @@ -1,34 +0,0 @@ ---TEST-- -SPL: ArrayObject::__construct: Using object with shared properties ---FILE-- -asort(); -var_dump($a, $o, $ao); -?> ---EXPECT-- -array(2) { - [0]=> - int(2) - [1]=> - int(1) -} -object(stdClass)#1 (2) { - ["1"]=> - int(1) - ["0"]=> - int(2) -} -object(ArrayObject)#2 (1) { - ["storage":"ArrayObject":private]=> - object(stdClass)#1 (2) { - ["1"]=> - int(1) - ["0"]=> - int(2) - } -} diff --git a/ext/spl/tests/arrayObject_exchangeArray_basic2.phpt b/ext/spl/tests/arrayObject_exchangeArray_basic2.phpt deleted file mode 100644 index 1f037e90735b7..0000000000000 --- a/ext/spl/tests/arrayObject_exchangeArray_basic2.phpt +++ /dev/null @@ -1,97 +0,0 @@ ---TEST-- -SPL: ArrayObject::exchangeArray() with various object arguments ---FILE-- - exchangeArray(array):\n"; -$ao = new ArrayObject(); -$ao->exchangeArray(array('key'=>'original')); -var_dump($ao['key']); -var_dump($ao); - -echo "\n--> exchangeArray(normal object):\n"; -$obj = new stdClass; -$obj->key = 'normal object prop'; -$ao->exchangeArray($obj); -var_dump($ao['key']); -var_dump($ao); - -echo "\n--> exchangeArray(ArrayObject):\n"; -$obj = new ArrayObject(array('key'=>'ArrayObject element')); -$ao->exchangeArray($obj); -var_dump($ao['key']); -var_dump($ao); - -echo "\n--> exchangeArray(ArrayIterator):\n"; -$obj = new ArrayIterator(array('key'=>'ArrayIterator element')); -$ao->exchangeArray($obj); -var_dump($ao['key']); -var_dump($ao); - -echo "\n--> exchangeArray(nested ArrayObject):\n"; -$obj = new ArrayObject(new ArrayObject(array('key'=>'nested ArrayObject element'))); -$ao->exchangeArray($obj); -var_dump($ao['key']); -var_dump($ao); -?> ---EXPECTF-- ---> exchangeArray(array): -string(8) "original" -object(ArrayObject)#%d (1) { - ["storage":"ArrayObject":private]=> - array(1) { - ["key"]=> - string(8) "original" - } -} - ---> exchangeArray(normal object): -string(18) "normal object prop" -object(ArrayObject)#%d (1) { - ["storage":"ArrayObject":private]=> - object(stdClass)#%d (1) { - ["key"]=> - string(18) "normal object prop" - } -} - ---> exchangeArray(ArrayObject): -string(19) "ArrayObject element" -object(ArrayObject)#%d (1) { - ["storage":"ArrayObject":private]=> - object(ArrayObject)#%d (1) { - ["storage":"ArrayObject":private]=> - array(1) { - ["key"]=> - string(19) "ArrayObject element" - } - } -} - ---> exchangeArray(ArrayIterator): -string(21) "ArrayIterator element" -object(ArrayObject)#%d (1) { - ["storage":"ArrayObject":private]=> - object(ArrayIterator)#%d (1) { - ["storage":"ArrayIterator":private]=> - array(1) { - ["key"]=> - string(21) "ArrayIterator element" - } - } -} - ---> exchangeArray(nested ArrayObject): -string(26) "nested ArrayObject element" -object(ArrayObject)#%d (1) { - ["storage":"ArrayObject":private]=> - object(ArrayObject)#%d (1) { - ["storage":"ArrayObject":private]=> - object(ArrayObject)#%d (1) { - ["storage":"ArrayObject":private]=> - array(1) { - ["key"]=> - string(26) "nested ArrayObject element" - } - } - } -} diff --git a/ext/spl/tests/arrayObject_exchangeArray_basic3.phpt b/ext/spl/tests/arrayObject_exchangeArray_basic3.phpt deleted file mode 100644 index 49b990be8bdf2..0000000000000 --- a/ext/spl/tests/arrayObject_exchangeArray_basic3.phpt +++ /dev/null @@ -1,125 +0,0 @@ ---TEST-- -SPL: ArrayObject::exchangeArray() basic usage with object as underlying data store. ---FILE-- - exchangeArray() with objects:\n"; -$original = new C; -$ao = new ArrayObject($original); -$swapIn = new C; -try { - $copy = $ao->exchangeArray($swapIn); - $copy['addedToCopy'] = 'added To Copy'; -} catch (Exception $e) { - echo "Exception:" . $e->getMessage() . "\n"; -} -$swapIn->addedToSwapIn = 'added To Swap-In'; -$original->addedToOriginal = 'added To Original'; -var_dump($ao, $original, $swapIn, $copy); - - -echo "\n\n--> exchangeArray() with no arg:\n"; -unset($original, $ao, $swapIn, $copy); -$original = new C; -$ao = new ArrayObject($original); -try { - $copy = $ao->exchangeArray(); - $copy['addedToCopy'] = 'added To Copy'; -} catch (TypeError $e) { - echo "Exception: " . $e->getMessage() . "\n"; -} -$original->addedToOriginal = 'added To Original'; -var_dump($ao, $original, $copy); - -echo "\n\n--> exchangeArray() with bad arg type:\n"; -unset($original, $ao, $swapIn, $copy); -$original = new C; -$ao = new ArrayObject($original); -try { - $copy = $ao->exchangeArray(null); - $copy['addedToCopy'] = 'added To Copy'; -} catch (TypeError $e) { - echo $e->getMessage() . "\n"; -} -$original->addedToOriginal = 'added To Original'; -var_dump($ao, $original, $copy); - -?> ---EXPECTF-- ---> exchangeArray() with objects: -object(ArrayObject)#2 (1) { - ["storage":"ArrayObject":private]=> - object(C)#3 (2) { - ["pub1"]=> - string(7) "public1" - ["addedToSwapIn"]=> - string(16) "added To Swap-In" - } -} -object(C)#1 (2) { - ["pub1"]=> - string(7) "public1" - ["addedToOriginal"]=> - string(17) "added To Original" -} -object(C)#3 (2) { - ["pub1"]=> - string(7) "public1" - ["addedToSwapIn"]=> - string(16) "added To Swap-In" -} -array(2) { - ["pub1"]=> - string(7) "public1" - ["addedToCopy"]=> - string(13) "added To Copy" -} - - ---> exchangeArray() with no arg: -Exception: ArrayObject::exchangeArray() expects exactly 1 argument, 0 given - -Warning: Undefined variable $copy in %s on line %d -object(ArrayObject)#2 (1) { - ["storage":"ArrayObject":private]=> - object(C)#3 (2) { - ["pub1"]=> - string(7) "public1" - ["addedToOriginal"]=> - string(17) "added To Original" - } -} -object(C)#3 (2) { - ["pub1"]=> - string(7) "public1" - ["addedToOriginal"]=> - string(17) "added To Original" -} -NULL - - ---> exchangeArray() with bad arg type: -ArrayObject::exchangeArray(): Argument #1 ($array) must be of type array, null given - -Warning: Undefined variable $copy in %s on line %d -object(ArrayObject)#3 (1) { - ["storage":"ArrayObject":private]=> - object(C)#2 (2) { - ["pub1"]=> - string(7) "public1" - ["addedToOriginal"]=> - string(17) "added To Original" - } -} -object(C)#2 (2) { - ["pub1"]=> - string(7) "public1" - ["addedToOriginal"]=> - string(17) "added To Original" -} -NULL 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/array_022.phpt b/ext/spl/tests/array_022.phpt deleted file mode 100644 index f7407bf602c75..0000000000000 --- a/ext/spl/tests/array_022.phpt +++ /dev/null @@ -1,68 +0,0 @@ ---TEST-- -SPL: ArrayObject/Iterator and reference to self ---FILE-- -==ArrayObject=== - -==ArrayIterator=== - ---EXPECTF-- -==ArrayObject=== -object(MyArrayObject)#%d (1) { - ["bar"]=> - string(3) "baz" -} -object(MyArrayObject)#%d (2) { - ["bar"]=> - string(3) "baz" - ["baz"]=> - string(3) "Foo" -} -==ArrayIterator=== -object(MyArrayIterator)#%d (1) { - ["bar"]=> - string(3) "baz" -} -object(MyArrayIterator)#%d (2) { - ["bar"]=> - string(3) "baz" - ["baz"]=> - string(3) "Foo" -} diff --git a/ext/spl/tests/array_025.phpt b/ext/spl/tests/array_025.phpt deleted file mode 100644 index d64f8f04c1e14..0000000000000 --- a/ext/spl/tests/array_025.phpt +++ /dev/null @@ -1,40 +0,0 @@ ---TEST-- -SPL: ArrayObject serialize with an object as storage ---FILE-- - ---EXPECT-- -ArrayObject Object -( - [storage:ArrayObject:private] => ArrayObject Object - ( - [storage:ArrayObject:private] => Array - ( - [0] => 1 - [1] => 2 - ) - - ) - -) -O:11:"ArrayObject":4:{i:0;i:0;i:1;O:11:"ArrayObject":4:{i:0;i:0;i:1;a:2:{i:0;i:1;i:1;i:2;}i:2;a:0:{}i:3;N;}i:2;a:0:{}i:3;N;} -ArrayObject Object -( - [storage:ArrayObject:private] => ArrayObject Object - ( - [storage:ArrayObject:private] => Array - ( - [0] => 1 - [1] => 2 - ) - - ) - -) diff --git a/ext/spl/tests/array_028.phpt b/ext/spl/tests/array_028.phpt deleted file mode 100644 index 1adcdd3f90714..0000000000000 --- a/ext/spl/tests/array_028.phpt +++ /dev/null @@ -1,27 +0,0 @@ ---TEST-- -ArrayObject/Iterator on array with NUL bytes ---FILE-- - "bar", -]; - -$it = new ArrayIterator($array); -foreach ($it as $v) { - var_dump($v); -} - -$obj = new ArrayObject($array); -foreach ($obj as $v) { - var_dump($v); -} - -$obj = new ArrayObject($it); -foreach ($obj as $v) { - var_dump($v); -} -?> ---EXPECT-- -string(3) "bar" -string(3) "bar" -string(3) "bar" diff --git a/ext/spl/tests/bug31346.phpt b/ext/spl/tests/bug31346.phpt deleted file mode 100644 index b2d29905ac767..0000000000000 --- a/ext/spl/tests/bug31346.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -Bug #31486 (ArrayIterator::next segfaults) ---FILE-- -var1=1; - -$ao = new ArrayObject($obj); - -$i = $ao->getIterator(); - -$ao->offsetUnset($i->key()); -$i->next(); - -?> -===DONE=== ---EXPECT-- -===DONE=== diff --git a/ext/spl/tests/bug38618.phpt b/ext/spl/tests/bug38618.phpt deleted file mode 100644 index 71a09111a4b8b..0000000000000 --- a/ext/spl/tests/bug38618.phpt +++ /dev/null @@ -1,100 +0,0 @@ ---TEST-- -Bug #38618 (RecursiveArrayIterator::hasChildren() follows objects) ---FILE-- -title = $title; - } - - public function __toString() - { - return $this->title; - } -} - -class FruitProtected -{ - protected $title; - - public function __construct($title) - { - $this->title = $title; - } - - public function __toString() - { - return $this->title; - } -} - -function test_array($array, $which, $flags = 0) -{ - echo "===$which===\n"; - $it = new RecursiveArrayIterator($array, $flags); - foreach (new RecursiveIteratorIterator($it) as $k => $fruit) { - echo $k , ' => ', $fruit, "\n"; - } -} - -$array = array( - 1 => array( - 1 => array( - 1 => 'apple', - ), - 2 => array( - 1 => 'grape', - ), - ), -); - -test_array($array, 'Default with array'); - -$array = array( - 1 => array( - 1 => array( - 1 => new FruitPublic('apple'), - ), - 2 => array( - 1 => new FruitPublic('grape'), - ), - ), -); - -test_array($array, 'Public Property'); - -$array = array( - 1 => array( - 1 => array( - 1 => new FruitProtected('apple'), - ), - 2 => array( - 1 => new FruitProtected('grape'), - ), - ), -); - -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-- -===Default with array=== -1 => apple -1 => grape -===Public Property=== -title => apple -title => grape -===Protected Property=== -===Public Property New=== -1 => apple -1 => grape -===Protected Property New=== -1 => apple -1 => grape diff --git a/ext/spl/tests/bug41691.phpt b/ext/spl/tests/bug41691.phpt deleted file mode 100644 index 93af430b4884a..0000000000000 --- a/ext/spl/tests/bug41691.phpt +++ /dev/null @@ -1,29 +0,0 @@ ---TEST-- -Bug #41691 (ArrayObject::exchangeArray hangs Apache) ---FILE-- -exchangeArray(array('a'=>1,'b'=>1,'c'=>1))); - -echo "Done\n"; -?> ---EXPECT-- -array(3) { - ["a"]=> - NULL - ["b"]=> - NULL - ["c"]=> - NULL -} -Done diff --git a/ext/spl/tests/bug54323.phpt b/ext/spl/tests/bug54323.phpt deleted file mode 100644 index 7431c9c47348a..0000000000000 --- a/ext/spl/tests/bug54323.phpt +++ /dev/null @@ -1,25 +0,0 @@ ---TEST-- -Bug #54323 (Accessing unset()'ed ArrayObject's property causes crash) ---FILE-- -$value) { - } - unset($ao['prop']); - var_dump($c->prop, $ao['prop']); -} -?> ---EXPECTF-- -Warning: Undefined property: C::$prop in %s on line %d - -Warning: Undefined array key "prop" in %s on line %d -NULL -NULL diff --git a/ext/spl/tests/bug62672.phpt b/ext/spl/tests/bug62672.phpt deleted file mode 100644 index ec40ee695504b..0000000000000 --- a/ext/spl/tests/bug62672.phpt +++ /dev/null @@ -1,32 +0,0 @@ ---TEST-- -Bug #62672 (Error on serialize of ArrayObject) ---FILE-- -_varA = $source; - } -} - -class ObjB extends ObjA -{ - private $_varB; - - public function __construct(ArrayObject $keys) - { - $this->_varB = $keys; - parent::__construct($keys->getIterator()); - } -} - -$obj = new ObjB(new ArrayObject()); - -var_dump($obj == unserialize(serialize($obj))); -?> ---EXPECT-- -bool(true) 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/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/bug73209.phpt b/ext/spl/tests/bug73209.phpt deleted file mode 100644 index 7383940936689..0000000000000 --- a/ext/spl/tests/bug73209.phpt +++ /dev/null @@ -1,28 +0,0 @@ ---TEST-- -Bug #73209: RecursiveArrayIterator does not iterate object properties ---FILE-- -props = ['hello' => 5, 'props' => ['keyme' => ['test' => 5]]]; - } -} -$data = new hello(); - -$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($data), RecursiveIteratorIterator::SELF_FIRST); -echo "Expect to see all keys in ->props here: \n"; - -foreach($iterator as $k=>$v) { - echo $k . "\n"; -} - -?> ---EXPECT-- -Expect to see all keys in ->props here: -props -hello -props -keyme -test diff --git a/ext/spl/tests/gh11178.phpt b/ext/spl/tests/gh11178.phpt deleted file mode 100644 index 3732c57a59d19..0000000000000 --- a/ext/spl/tests/gh11178.phpt +++ /dev/null @@ -1,28 +0,0 @@ ---TEST-- -GH-11178 (Segmentation fault in spl_array_it_get_current_data (PHP 8.1.18)) ---FILE-- -{'x'} = 1; - } - - function getIterator(): Traversable { - return new ArrayIterator($this); - } -} - -$obj = new A; - -foreach ($obj as $k => &$v) { - $v = 3; -} - -var_dump($obj); -?> ---EXPECT-- -object(A)#1 (1) { - ["x"]=> - &int(3) -} diff --git a/ext/spl/tests/gh15833_1.phpt b/ext/spl/tests/gh15833_1.phpt deleted file mode 100644 index d658a770e80f5..0000000000000 --- a/ext/spl/tests/gh15833_1.phpt +++ /dev/null @@ -1,22 +0,0 @@ ---TEST-- -GH-15833 (Segmentation fault (access null pointer) in ext/spl/spl_array.c) ---CREDITS-- -YuanchengJiang ---FILE-- -newLazyProxy(function ($obj) { - $obj = new C(); - return $obj; -}); -$recursiveArrayIterator = new RecursiveArrayIterator($obj); -var_dump($recursiveArrayIterator->current()); -$recursiveArrayIterator->next(); -var_dump($recursiveArrayIterator->current()); -?> ---EXPECT-- -int(1) -NULL diff --git a/ext/spl/tests/gh15918.phpt b/ext/spl/tests/gh15918.phpt deleted file mode 100644 index b26ff8adfc140..0000000000000 --- a/ext/spl/tests/gh15918.phpt +++ /dev/null @@ -1,13 +0,0 @@ ---TEST-- -GH-15918 (Assertion failure in ext/spl/spl_fixedarray.c) ---FILE-- -getMessage(), "\n"; -} -?> ---EXPECT-- -Overloaded object of type SplFixedArray is not compatible with ArrayObject diff --git a/ext/spl/tests/gh16646.phpt b/ext/spl/tests/gh16646.phpt deleted file mode 100644 index b6cb503d8ed05..0000000000000 --- a/ext/spl/tests/gh16646.phpt +++ /dev/null @@ -1,32 +0,0 @@ ---TEST-- -GH-16646: Use-after-free in ArrayObject::unset() with destructor ---FILE-- -b = $arg; - } -} - -class C { - function __destruct() { - global $arr; - echo __METHOD__, "\n"; - $arr->exchangeArray([]); - } -} - -$arr = new ArrayObject(new B(new C)); -unset($arr["b"]); -var_dump($arr); - -?> ---EXPECT-- -C::__destruct -object(ArrayObject)#1 (1) { - ["storage":"ArrayObject":private]=> - array(0) { - } -} diff --git a/ext/spl/tests/gh16646_2.phpt b/ext/spl/tests/gh16646_2.phpt deleted file mode 100644 index d006583500811..0000000000000 --- a/ext/spl/tests/gh16646_2.phpt +++ /dev/null @@ -1,25 +0,0 @@ ---TEST-- -GH-16646: Use-after-free in ArrayObject::exchangeArray() with destructor ---FILE-- -exchangeArray([]); - } -} - -$arr = new ArrayObject(new C); -$arr->exchangeArray([]); -var_dump($arr); - -?> ---EXPECT-- -C::__destruct -object(ArrayObject)#1 (1) { - ["storage":"ArrayObject":private]=> - array(0) { - } -} 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/gh20101.phpt b/ext/spl/tests/gh20101.phpt new file mode 100644 index 0000000000000..ad2399d76c8e6 --- /dev/null +++ b/ext/spl/tests/gh20101.phpt @@ -0,0 +1,49 @@ +--TEST-- +GH-20101 (SplHeap/SplPriorityQueue serialization exposes INDIRECTs) +--FILE-- +__serialize(); +var_dump($data); + +class CustomPriorityQueue extends SplPriorityQueue { + public $field = 0; +} +$pqueue = new CustomPriorityQueue(); +$data = $pqueue->__serialize(); +var_dump($data); +?> +--EXPECT-- +array(2) { + [0]=> + array(1) { + ["field"]=> + int(0) + } + [1]=> + array(2) { + ["flags"]=> + int(0) + ["heap_elements"]=> + array(0) { + } + } +} +array(2) { + [0]=> + array(1) { + ["field"]=> + int(0) + } + [1]=> + array(2) { + ["flags"]=> + int(1) + ["heap_elements"]=> + array(0) { + } + } +} diff --git a/ext/spl/tests/gh20614.phpt b/ext/spl/tests/gh20614.phpt new file mode 100644 index 0000000000000..c13630d76469b --- /dev/null +++ b/ext/spl/tests/gh20614.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-20614 (SplFixedArray incorrectly handles references in deserialization) +--FILE-- +__unserialize($array); +var_dump($fa); +unset($fa[0]); +var_dump($fa); + +?> +--EXPECT-- +object(SplFixedArray)#1 (1) { + [0]=> + int(1) +} +object(SplFixedArray)#1 (1) { + [0]=> + NULL +} diff --git a/ext/spl/tests/gh20678.phpt b/ext/spl/tests/gh20678.phpt new file mode 100644 index 0000000000000..00364db7f8044 --- /dev/null +++ b/ext/spl/tests/gh20678.phpt @@ -0,0 +1,13 @@ +--TEST-- +GH-20678 (resource created by GlobalIterator crashes when it is called with fclose()) +--CREDITS-- +chongwick +--FILE-- + +--EXPECTF-- +Warning: fclose(): cannot close the provided stream, as it must not be manually closed in %s on line %d diff --git a/ext/spl/tests/heap_unserialize_under_corruption_or_modification.phpt b/ext/spl/tests/heap_unserialize_under_corruption_or_modification.phpt new file mode 100644 index 0000000000000..2e54be09ad1a7 --- /dev/null +++ b/ext/spl/tests/heap_unserialize_under_corruption_or_modification.phpt @@ -0,0 +1,30 @@ +--TEST-- +SplHeap should not accept unserialize data when it is corrupted or under modification +--FILE-- +__unserialize($array); + return $a < $b ? -1 : ($a == $b ? 0 : 1); + } +} + +$heap = new SplMaxHeap; +$heap->insert(1); +$array = $heap->__serialize(); + +$heap = new MyHeap; +$heap->insert(0); +try { + $heap->insert(2); +} catch (RuntimeException $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Heap cannot be changed when it is already being modified. 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_049.phpt b/ext/spl/tests/iterator_049.phpt index e9b81fbff39be..6fccbd5911623 100644 --- a/ext/spl/tests/iterator_049.phpt +++ b/ext/spl/tests/iterator_049.phpt @@ -1,10 +1,10 @@ --TEST-- -SPL: ArrayIterator with NULL key +SPL: ArrayIterator with empty string key --FILE-- NULL)); -@var_dump($ar); +$ar = new ArrayIterator(array(''=>NULL)); +var_dump($ar); var_dump($ar->getArrayCopy()); ?> diff --git a/ext/spl/tests/iterator_049b.phpt b/ext/spl/tests/iterator_049b.phpt index 1e1176c7169fc..7a957aa70c5cf 100644 --- a/ext/spl/tests/iterator_049b.phpt +++ b/ext/spl/tests/iterator_049b.phpt @@ -1,17 +1,17 @@ --TEST-- -SPL: ArrayIterator with NULL key +SPL: ArrayIterator with empty string key --FILE-- 1, + ''=>1, "\0"=>2, "\0\0"=>3, "\0\0\0"=>4, "\0*"=>5, "\0*\0"=>6, )); -@var_dump($ar); +var_dump($ar); var_dump($ar->getArrayCopy()); ?> 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/iterator_to_array_nonscalar_keys.phpt b/ext/spl/tests/iterator_to_array_nonscalar_keys.phpt index 44b4e2a0ebcbb..c5fc21ea8bc76 100644 --- a/ext/spl/tests/iterator_to_array_nonscalar_keys.phpt +++ b/ext/spl/tests/iterator_to_array_nonscalar_keys.phpt @@ -21,4 +21,6 @@ try { ?> --EXPECTF-- Deprecated: Implicit conversion from float 2.5 to int loses precision in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d Cannot access offset of type array on array diff --git a/ext/spl/tests/observer_008.phpt b/ext/spl/tests/observer_008.phpt deleted file mode 100644 index 0f6f0d263b9e8..0000000000000 --- a/ext/spl/tests/observer_008.phpt +++ /dev/null @@ -1,32 +0,0 @@ ---TEST-- -SPL: SplObjectStorage addAll/removeAll ---FILE-- -attach($o1); -$a->attach($o2); - -$b = new SplObjectStorage(); -$b->attach($o2); -$b->attach($o3); - -$a->addAll($b); - -var_dump($a->count()); - -$a->detach($o3); -var_dump($a->count()); - -$a->removeAll($b); -var_dump($a->count()); -?> ---EXPECT-- -int(3) -int(2) -int(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/spl/tests/spl_recursive_iterator_iterator_key_case.phpt b/ext/spl/tests/spl_recursive_iterator_iterator_key_case.phpt index 4b8cfaa53d819..257a961cee80f 100644 --- a/ext/spl/tests/spl_recursive_iterator_iterator_key_case.phpt +++ b/ext/spl/tests/spl_recursive_iterator_iterator_key_case.phpt @@ -5,7 +5,7 @@ Rohan Abraham (rohanabrahams@gmail.com) TestFest London May 2009 --FILE-- 1, "two"=>2, "three"=>array("four"=>4, "five"=>5, "six"=>array("seven"=>7)), "eight"=>8, -100 => 10, NULL => "null"); + $ar = array("one"=>1, "two"=>2, "three"=>array("four"=>4, "five"=>5, "six"=>array("seven"=>7)), "eight"=>8, -100 => 10, '' => "null"); $it = new RecursiveArrayIterator($ar); $it = new RecursiveIteratorIterator($it); foreach($it as $k=>$v) diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c index 21b6840a8d1b2..da24b037861a8 100644 --- a/ext/sqlite3/sqlite3.c +++ b/ext/sqlite3/sqlite3.c @@ -318,7 +318,7 @@ PHP_METHOD(SQLite3, enableExtendedResultCodes) { php_sqlite3_db_object *db_obj; zval *object = ZEND_THIS; - bool enable = 1; + bool enable = true; db_obj = Z_SQLITE3_DB_P(object); int ret; @@ -648,7 +648,7 @@ static void sqlite_value_to_zval(sqlite3_stmt *stmt, int column, zval *data) /* break; case SQLITE3_TEXT: - ZVAL_STRING(data, (char*)sqlite3_column_text(stmt, column)); + ZVAL_STRINGL(data, (const char *) sqlite3_column_text(stmt, column), sqlite3_column_bytes(stmt, column)); break; case SQLITE_BLOB: @@ -666,7 +666,7 @@ PHP_METHOD(SQLite3, querySingle) zend_string *sql; char *errtext = NULL; int return_code; - bool entire_row = 0; + bool entire_row = false; sqlite3_stmt *stmt; db_obj = Z_SQLITE3_DB_P(object); @@ -1285,7 +1285,7 @@ PHP_METHOD(SQLite3, enableExceptions) { php_sqlite3_db_object *db_obj; zval *object = ZEND_THIS; - bool enableExceptions = 0; + bool enableExceptions = false; db_obj = Z_SQLITE3_DB_P(object); @@ -1916,7 +1916,6 @@ PHP_METHOD(SQLite3Stmt, __construct) errcode = sqlite3_prepare_v2(db_obj->db, ZSTR_VAL(sql), ZSTR_LEN(sql), &(stmt_obj->stmt), NULL); if (errcode != SQLITE_OK) { php_sqlite3_error(db_obj, errcode, "Unable to prepare statement: %s", sqlite3_errmsg(db_obj->db)); - zval_ptr_dtor(return_value); RETURN_FALSE; } stmt_obj->initialised = true; @@ -2044,6 +2043,7 @@ PHP_METHOD(SQLite3Result, fetchArray) default: php_sqlite3_error(result_obj->db_obj, sqlite3_errcode(sqlite3_db_handle(result_obj->stmt_obj->stmt)), "Unable to execute statement: %s", sqlite3_errmsg(sqlite3_db_handle(result_obj->stmt_obj->stmt))); + RETURN_FALSE; } } /* }}} */ diff --git a/ext/sqlite3/sqlite3_arginfo.h b/ext/sqlite3/sqlite3_arginfo.h index 54ca70cad5c53..12c1c7d0ce961 100644 --- a/ext/sqlite3/sqlite3_arginfo.h +++ b/ext/sqlite3/sqlite3_arginfo.h @@ -332,226 +332,226 @@ static zend_class_entry *register_class_SQLite3(void) zval const_OK_value; ZVAL_LONG(&const_OK_value, SQLITE_OK); - zend_string *const_OK_name = zend_string_init_interned("OK", sizeof("OK") - 1, 1); + zend_string *const_OK_name = zend_string_init_interned("OK", sizeof("OK") - 1, true); zend_declare_typed_class_constant(class_entry, const_OK_name, &const_OK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OK_name); + zend_string_release_ex(const_OK_name, true); zval const_DENY_value; ZVAL_LONG(&const_DENY_value, SQLITE_DENY); - zend_string *const_DENY_name = zend_string_init_interned("DENY", sizeof("DENY") - 1, 1); + zend_string *const_DENY_name = zend_string_init_interned("DENY", sizeof("DENY") - 1, true); zend_declare_typed_class_constant(class_entry, const_DENY_name, &const_DENY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DENY_name); + zend_string_release_ex(const_DENY_name, true); zval const_IGNORE_value; ZVAL_LONG(&const_IGNORE_value, SQLITE_IGNORE); - zend_string *const_IGNORE_name = zend_string_init_interned("IGNORE", sizeof("IGNORE") - 1, 1); + zend_string *const_IGNORE_name = zend_string_init_interned("IGNORE", sizeof("IGNORE") - 1, true); zend_declare_typed_class_constant(class_entry, const_IGNORE_name, &const_IGNORE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_IGNORE_name); + zend_string_release_ex(const_IGNORE_name, true); zval const_CREATE_INDEX_value; ZVAL_LONG(&const_CREATE_INDEX_value, SQLITE_CREATE_INDEX); - zend_string *const_CREATE_INDEX_name = zend_string_init_interned("CREATE_INDEX", sizeof("CREATE_INDEX") - 1, 1); + zend_string *const_CREATE_INDEX_name = zend_string_init_interned("CREATE_INDEX", sizeof("CREATE_INDEX") - 1, true); zend_declare_typed_class_constant(class_entry, const_CREATE_INDEX_name, &const_CREATE_INDEX_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CREATE_INDEX_name); + zend_string_release_ex(const_CREATE_INDEX_name, true); zval const_CREATE_TABLE_value; ZVAL_LONG(&const_CREATE_TABLE_value, SQLITE_CREATE_TABLE); - zend_string *const_CREATE_TABLE_name = zend_string_init_interned("CREATE_TABLE", sizeof("CREATE_TABLE") - 1, 1); + zend_string *const_CREATE_TABLE_name = zend_string_init_interned("CREATE_TABLE", sizeof("CREATE_TABLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_CREATE_TABLE_name, &const_CREATE_TABLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CREATE_TABLE_name); + zend_string_release_ex(const_CREATE_TABLE_name, true); zval const_CREATE_TEMP_INDEX_value; ZVAL_LONG(&const_CREATE_TEMP_INDEX_value, SQLITE_CREATE_TEMP_INDEX); - zend_string *const_CREATE_TEMP_INDEX_name = zend_string_init_interned("CREATE_TEMP_INDEX", sizeof("CREATE_TEMP_INDEX") - 1, 1); + zend_string *const_CREATE_TEMP_INDEX_name = zend_string_init_interned("CREATE_TEMP_INDEX", sizeof("CREATE_TEMP_INDEX") - 1, true); zend_declare_typed_class_constant(class_entry, const_CREATE_TEMP_INDEX_name, &const_CREATE_TEMP_INDEX_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CREATE_TEMP_INDEX_name); + zend_string_release_ex(const_CREATE_TEMP_INDEX_name, true); zval const_CREATE_TEMP_TABLE_value; ZVAL_LONG(&const_CREATE_TEMP_TABLE_value, SQLITE_CREATE_TEMP_TABLE); - zend_string *const_CREATE_TEMP_TABLE_name = zend_string_init_interned("CREATE_TEMP_TABLE", sizeof("CREATE_TEMP_TABLE") - 1, 1); + zend_string *const_CREATE_TEMP_TABLE_name = zend_string_init_interned("CREATE_TEMP_TABLE", sizeof("CREATE_TEMP_TABLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_CREATE_TEMP_TABLE_name, &const_CREATE_TEMP_TABLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CREATE_TEMP_TABLE_name); + zend_string_release_ex(const_CREATE_TEMP_TABLE_name, true); zval const_CREATE_TEMP_TRIGGER_value; ZVAL_LONG(&const_CREATE_TEMP_TRIGGER_value, SQLITE_CREATE_TEMP_TRIGGER); - zend_string *const_CREATE_TEMP_TRIGGER_name = zend_string_init_interned("CREATE_TEMP_TRIGGER", sizeof("CREATE_TEMP_TRIGGER") - 1, 1); + zend_string *const_CREATE_TEMP_TRIGGER_name = zend_string_init_interned("CREATE_TEMP_TRIGGER", sizeof("CREATE_TEMP_TRIGGER") - 1, true); zend_declare_typed_class_constant(class_entry, const_CREATE_TEMP_TRIGGER_name, &const_CREATE_TEMP_TRIGGER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CREATE_TEMP_TRIGGER_name); + zend_string_release_ex(const_CREATE_TEMP_TRIGGER_name, true); zval const_CREATE_TEMP_VIEW_value; ZVAL_LONG(&const_CREATE_TEMP_VIEW_value, SQLITE_CREATE_TEMP_VIEW); - zend_string *const_CREATE_TEMP_VIEW_name = zend_string_init_interned("CREATE_TEMP_VIEW", sizeof("CREATE_TEMP_VIEW") - 1, 1); + zend_string *const_CREATE_TEMP_VIEW_name = zend_string_init_interned("CREATE_TEMP_VIEW", sizeof("CREATE_TEMP_VIEW") - 1, true); zend_declare_typed_class_constant(class_entry, const_CREATE_TEMP_VIEW_name, &const_CREATE_TEMP_VIEW_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CREATE_TEMP_VIEW_name); + zend_string_release_ex(const_CREATE_TEMP_VIEW_name, true); zval const_CREATE_TRIGGER_value; ZVAL_LONG(&const_CREATE_TRIGGER_value, SQLITE_CREATE_TRIGGER); - zend_string *const_CREATE_TRIGGER_name = zend_string_init_interned("CREATE_TRIGGER", sizeof("CREATE_TRIGGER") - 1, 1); + zend_string *const_CREATE_TRIGGER_name = zend_string_init_interned("CREATE_TRIGGER", sizeof("CREATE_TRIGGER") - 1, true); zend_declare_typed_class_constant(class_entry, const_CREATE_TRIGGER_name, &const_CREATE_TRIGGER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CREATE_TRIGGER_name); + zend_string_release_ex(const_CREATE_TRIGGER_name, true); zval const_CREATE_VIEW_value; ZVAL_LONG(&const_CREATE_VIEW_value, SQLITE_CREATE_VIEW); - zend_string *const_CREATE_VIEW_name = zend_string_init_interned("CREATE_VIEW", sizeof("CREATE_VIEW") - 1, 1); + zend_string *const_CREATE_VIEW_name = zend_string_init_interned("CREATE_VIEW", sizeof("CREATE_VIEW") - 1, true); zend_declare_typed_class_constant(class_entry, const_CREATE_VIEW_name, &const_CREATE_VIEW_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CREATE_VIEW_name); + zend_string_release_ex(const_CREATE_VIEW_name, true); zval const_DELETE_value; ZVAL_LONG(&const_DELETE_value, SQLITE_DELETE); - zend_string *const_DELETE_name = zend_string_init_interned("DELETE", sizeof("DELETE") - 1, 1); + zend_string *const_DELETE_name = zend_string_init_interned("DELETE", sizeof("DELETE") - 1, true); zend_declare_typed_class_constant(class_entry, const_DELETE_name, &const_DELETE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DELETE_name); + zend_string_release_ex(const_DELETE_name, true); zval const_DROP_INDEX_value; ZVAL_LONG(&const_DROP_INDEX_value, SQLITE_DROP_INDEX); - zend_string *const_DROP_INDEX_name = zend_string_init_interned("DROP_INDEX", sizeof("DROP_INDEX") - 1, 1); + zend_string *const_DROP_INDEX_name = zend_string_init_interned("DROP_INDEX", sizeof("DROP_INDEX") - 1, true); zend_declare_typed_class_constant(class_entry, const_DROP_INDEX_name, &const_DROP_INDEX_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DROP_INDEX_name); + zend_string_release_ex(const_DROP_INDEX_name, true); zval const_DROP_TABLE_value; ZVAL_LONG(&const_DROP_TABLE_value, SQLITE_DROP_TABLE); - zend_string *const_DROP_TABLE_name = zend_string_init_interned("DROP_TABLE", sizeof("DROP_TABLE") - 1, 1); + zend_string *const_DROP_TABLE_name = zend_string_init_interned("DROP_TABLE", sizeof("DROP_TABLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_DROP_TABLE_name, &const_DROP_TABLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DROP_TABLE_name); + zend_string_release_ex(const_DROP_TABLE_name, true); zval const_DROP_TEMP_INDEX_value; ZVAL_LONG(&const_DROP_TEMP_INDEX_value, SQLITE_DROP_TEMP_INDEX); - zend_string *const_DROP_TEMP_INDEX_name = zend_string_init_interned("DROP_TEMP_INDEX", sizeof("DROP_TEMP_INDEX") - 1, 1); + zend_string *const_DROP_TEMP_INDEX_name = zend_string_init_interned("DROP_TEMP_INDEX", sizeof("DROP_TEMP_INDEX") - 1, true); zend_declare_typed_class_constant(class_entry, const_DROP_TEMP_INDEX_name, &const_DROP_TEMP_INDEX_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DROP_TEMP_INDEX_name); + zend_string_release_ex(const_DROP_TEMP_INDEX_name, true); zval const_DROP_TEMP_TABLE_value; ZVAL_LONG(&const_DROP_TEMP_TABLE_value, SQLITE_DROP_TEMP_TABLE); - zend_string *const_DROP_TEMP_TABLE_name = zend_string_init_interned("DROP_TEMP_TABLE", sizeof("DROP_TEMP_TABLE") - 1, 1); + zend_string *const_DROP_TEMP_TABLE_name = zend_string_init_interned("DROP_TEMP_TABLE", sizeof("DROP_TEMP_TABLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_DROP_TEMP_TABLE_name, &const_DROP_TEMP_TABLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DROP_TEMP_TABLE_name); + zend_string_release_ex(const_DROP_TEMP_TABLE_name, true); zval const_DROP_TEMP_TRIGGER_value; ZVAL_LONG(&const_DROP_TEMP_TRIGGER_value, SQLITE_DROP_TEMP_TRIGGER); - zend_string *const_DROP_TEMP_TRIGGER_name = zend_string_init_interned("DROP_TEMP_TRIGGER", sizeof("DROP_TEMP_TRIGGER") - 1, 1); + zend_string *const_DROP_TEMP_TRIGGER_name = zend_string_init_interned("DROP_TEMP_TRIGGER", sizeof("DROP_TEMP_TRIGGER") - 1, true); zend_declare_typed_class_constant(class_entry, const_DROP_TEMP_TRIGGER_name, &const_DROP_TEMP_TRIGGER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DROP_TEMP_TRIGGER_name); + zend_string_release_ex(const_DROP_TEMP_TRIGGER_name, true); zval const_DROP_TEMP_VIEW_value; ZVAL_LONG(&const_DROP_TEMP_VIEW_value, SQLITE_DROP_TEMP_VIEW); - zend_string *const_DROP_TEMP_VIEW_name = zend_string_init_interned("DROP_TEMP_VIEW", sizeof("DROP_TEMP_VIEW") - 1, 1); + zend_string *const_DROP_TEMP_VIEW_name = zend_string_init_interned("DROP_TEMP_VIEW", sizeof("DROP_TEMP_VIEW") - 1, true); zend_declare_typed_class_constant(class_entry, const_DROP_TEMP_VIEW_name, &const_DROP_TEMP_VIEW_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DROP_TEMP_VIEW_name); + zend_string_release_ex(const_DROP_TEMP_VIEW_name, true); zval const_DROP_TRIGGER_value; ZVAL_LONG(&const_DROP_TRIGGER_value, SQLITE_DROP_TRIGGER); - zend_string *const_DROP_TRIGGER_name = zend_string_init_interned("DROP_TRIGGER", sizeof("DROP_TRIGGER") - 1, 1); + zend_string *const_DROP_TRIGGER_name = zend_string_init_interned("DROP_TRIGGER", sizeof("DROP_TRIGGER") - 1, true); zend_declare_typed_class_constant(class_entry, const_DROP_TRIGGER_name, &const_DROP_TRIGGER_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DROP_TRIGGER_name); + zend_string_release_ex(const_DROP_TRIGGER_name, true); zval const_DROP_VIEW_value; ZVAL_LONG(&const_DROP_VIEW_value, SQLITE_DROP_VIEW); - zend_string *const_DROP_VIEW_name = zend_string_init_interned("DROP_VIEW", sizeof("DROP_VIEW") - 1, 1); + zend_string *const_DROP_VIEW_name = zend_string_init_interned("DROP_VIEW", sizeof("DROP_VIEW") - 1, true); zend_declare_typed_class_constant(class_entry, const_DROP_VIEW_name, &const_DROP_VIEW_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DROP_VIEW_name); + zend_string_release_ex(const_DROP_VIEW_name, true); zval const_INSERT_value; ZVAL_LONG(&const_INSERT_value, SQLITE_INSERT); - zend_string *const_INSERT_name = zend_string_init_interned("INSERT", sizeof("INSERT") - 1, 1); + zend_string *const_INSERT_name = zend_string_init_interned("INSERT", sizeof("INSERT") - 1, true); zend_declare_typed_class_constant(class_entry, const_INSERT_name, &const_INSERT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_INSERT_name); + zend_string_release_ex(const_INSERT_name, true); zval const_PRAGMA_value; ZVAL_LONG(&const_PRAGMA_value, SQLITE_PRAGMA); - zend_string *const_PRAGMA_name = zend_string_init_interned("PRAGMA", sizeof("PRAGMA") - 1, 1); + zend_string *const_PRAGMA_name = zend_string_init_interned("PRAGMA", sizeof("PRAGMA") - 1, true); zend_declare_typed_class_constant(class_entry, const_PRAGMA_name, &const_PRAGMA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PRAGMA_name); + zend_string_release_ex(const_PRAGMA_name, true); zval const_READ_value; ZVAL_LONG(&const_READ_value, SQLITE_READ); - zend_string *const_READ_name = zend_string_init_interned("READ", sizeof("READ") - 1, 1); + zend_string *const_READ_name = zend_string_init_interned("READ", sizeof("READ") - 1, true); zend_declare_typed_class_constant(class_entry, const_READ_name, &const_READ_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_READ_name); + zend_string_release_ex(const_READ_name, true); zval const_SELECT_value; ZVAL_LONG(&const_SELECT_value, SQLITE_SELECT); - zend_string *const_SELECT_name = zend_string_init_interned("SELECT", sizeof("SELECT") - 1, 1); + zend_string *const_SELECT_name = zend_string_init_interned("SELECT", sizeof("SELECT") - 1, true); zend_declare_typed_class_constant(class_entry, const_SELECT_name, &const_SELECT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SELECT_name); + zend_string_release_ex(const_SELECT_name, true); zval const_TRANSACTION_value; ZVAL_LONG(&const_TRANSACTION_value, SQLITE_TRANSACTION); - zend_string *const_TRANSACTION_name = zend_string_init_interned("TRANSACTION", sizeof("TRANSACTION") - 1, 1); + zend_string *const_TRANSACTION_name = zend_string_init_interned("TRANSACTION", sizeof("TRANSACTION") - 1, true); zend_declare_typed_class_constant(class_entry, const_TRANSACTION_name, &const_TRANSACTION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TRANSACTION_name); + zend_string_release_ex(const_TRANSACTION_name, true); zval const_UPDATE_value; ZVAL_LONG(&const_UPDATE_value, SQLITE_UPDATE); - zend_string *const_UPDATE_name = zend_string_init_interned("UPDATE", sizeof("UPDATE") - 1, 1); + zend_string *const_UPDATE_name = zend_string_init_interned("UPDATE", sizeof("UPDATE") - 1, true); zend_declare_typed_class_constant(class_entry, const_UPDATE_name, &const_UPDATE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_UPDATE_name); + zend_string_release_ex(const_UPDATE_name, true); zval const_ATTACH_value; ZVAL_LONG(&const_ATTACH_value, SQLITE_ATTACH); - zend_string *const_ATTACH_name = zend_string_init_interned("ATTACH", sizeof("ATTACH") - 1, 1); + zend_string *const_ATTACH_name = zend_string_init_interned("ATTACH", sizeof("ATTACH") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTACH_name, &const_ATTACH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTACH_name); + zend_string_release_ex(const_ATTACH_name, true); zval const_DETACH_value; ZVAL_LONG(&const_DETACH_value, SQLITE_DETACH); - zend_string *const_DETACH_name = zend_string_init_interned("DETACH", sizeof("DETACH") - 1, 1); + zend_string *const_DETACH_name = zend_string_init_interned("DETACH", sizeof("DETACH") - 1, true); zend_declare_typed_class_constant(class_entry, const_DETACH_name, &const_DETACH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DETACH_name); + zend_string_release_ex(const_DETACH_name, true); zval const_ALTER_TABLE_value; ZVAL_LONG(&const_ALTER_TABLE_value, SQLITE_ALTER_TABLE); - zend_string *const_ALTER_TABLE_name = zend_string_init_interned("ALTER_TABLE", sizeof("ALTER_TABLE") - 1, 1); + zend_string *const_ALTER_TABLE_name = zend_string_init_interned("ALTER_TABLE", sizeof("ALTER_TABLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_ALTER_TABLE_name, &const_ALTER_TABLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ALTER_TABLE_name); + zend_string_release_ex(const_ALTER_TABLE_name, true); zval const_REINDEX_value; ZVAL_LONG(&const_REINDEX_value, SQLITE_REINDEX); - zend_string *const_REINDEX_name = zend_string_init_interned("REINDEX", sizeof("REINDEX") - 1, 1); + zend_string *const_REINDEX_name = zend_string_init_interned("REINDEX", sizeof("REINDEX") - 1, true); zend_declare_typed_class_constant(class_entry, const_REINDEX_name, &const_REINDEX_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_REINDEX_name); + zend_string_release_ex(const_REINDEX_name, true); zval const_ANALYZE_value; ZVAL_LONG(&const_ANALYZE_value, SQLITE_ANALYZE); - zend_string *const_ANALYZE_name = zend_string_init_interned("ANALYZE", sizeof("ANALYZE") - 1, 1); + zend_string *const_ANALYZE_name = zend_string_init_interned("ANALYZE", sizeof("ANALYZE") - 1, true); zend_declare_typed_class_constant(class_entry, const_ANALYZE_name, &const_ANALYZE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ANALYZE_name); + zend_string_release_ex(const_ANALYZE_name, true); zval const_CREATE_VTABLE_value; ZVAL_LONG(&const_CREATE_VTABLE_value, SQLITE_CREATE_VTABLE); - zend_string *const_CREATE_VTABLE_name = zend_string_init_interned("CREATE_VTABLE", sizeof("CREATE_VTABLE") - 1, 1); + zend_string *const_CREATE_VTABLE_name = zend_string_init_interned("CREATE_VTABLE", sizeof("CREATE_VTABLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_CREATE_VTABLE_name, &const_CREATE_VTABLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CREATE_VTABLE_name); + zend_string_release_ex(const_CREATE_VTABLE_name, true); zval const_DROP_VTABLE_value; ZVAL_LONG(&const_DROP_VTABLE_value, SQLITE_DROP_VTABLE); - zend_string *const_DROP_VTABLE_name = zend_string_init_interned("DROP_VTABLE", sizeof("DROP_VTABLE") - 1, 1); + zend_string *const_DROP_VTABLE_name = zend_string_init_interned("DROP_VTABLE", sizeof("DROP_VTABLE") - 1, true); zend_declare_typed_class_constant(class_entry, const_DROP_VTABLE_name, &const_DROP_VTABLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DROP_VTABLE_name); + zend_string_release_ex(const_DROP_VTABLE_name, true); zval const_FUNCTION_value; ZVAL_LONG(&const_FUNCTION_value, SQLITE_FUNCTION); - zend_string *const_FUNCTION_name = zend_string_init_interned("FUNCTION", sizeof("FUNCTION") - 1, 1); + zend_string *const_FUNCTION_name = zend_string_init_interned("FUNCTION", sizeof("FUNCTION") - 1, true); zend_declare_typed_class_constant(class_entry, const_FUNCTION_name, &const_FUNCTION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FUNCTION_name); + zend_string_release_ex(const_FUNCTION_name, true); zval const_SAVEPOINT_value; ZVAL_LONG(&const_SAVEPOINT_value, SQLITE_SAVEPOINT); - zend_string *const_SAVEPOINT_name = zend_string_init_interned("SAVEPOINT", sizeof("SAVEPOINT") - 1, 1); + zend_string *const_SAVEPOINT_name = zend_string_init_interned("SAVEPOINT", sizeof("SAVEPOINT") - 1, true); zend_declare_typed_class_constant(class_entry, const_SAVEPOINT_name, &const_SAVEPOINT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SAVEPOINT_name); + zend_string_release_ex(const_SAVEPOINT_name, true); zval const_COPY_value; ZVAL_LONG(&const_COPY_value, SQLITE_COPY); - zend_string *const_COPY_name = zend_string_init_interned("COPY", sizeof("COPY") - 1, 1); + zend_string *const_COPY_name = zend_string_init_interned("COPY", sizeof("COPY") - 1, true); zend_declare_typed_class_constant(class_entry, const_COPY_name, &const_COPY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_COPY_name); + zend_string_release_ex(const_COPY_name, true); #if defined(SQLITE_RECURSIVE) zval const_RECURSIVE_value; ZVAL_LONG(&const_RECURSIVE_value, SQLITE_RECURSIVE); - zend_string *const_RECURSIVE_name = zend_string_init_interned("RECURSIVE", sizeof("RECURSIVE") - 1, 1); + zend_string *const_RECURSIVE_name = zend_string_init_interned("RECURSIVE", sizeof("RECURSIVE") - 1, true); zend_declare_typed_class_constant(class_entry, const_RECURSIVE_name, &const_RECURSIVE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_RECURSIVE_name); + zend_string_release_ex(const_RECURSIVE_name, true); #endif return class_entry; @@ -567,21 +567,21 @@ static zend_class_entry *register_class_SQLite3Stmt(void) zval const_EXPLAIN_MODE_PREPARED_value; ZVAL_LONG(&const_EXPLAIN_MODE_PREPARED_value, 0); - zend_string *const_EXPLAIN_MODE_PREPARED_name = zend_string_init_interned("EXPLAIN_MODE_PREPARED", sizeof("EXPLAIN_MODE_PREPARED") - 1, 1); + zend_string *const_EXPLAIN_MODE_PREPARED_name = zend_string_init_interned("EXPLAIN_MODE_PREPARED", sizeof("EXPLAIN_MODE_PREPARED") - 1, true); zend_declare_typed_class_constant(class_entry, const_EXPLAIN_MODE_PREPARED_name, &const_EXPLAIN_MODE_PREPARED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EXPLAIN_MODE_PREPARED_name); + zend_string_release_ex(const_EXPLAIN_MODE_PREPARED_name, true); zval const_EXPLAIN_MODE_EXPLAIN_value; ZVAL_LONG(&const_EXPLAIN_MODE_EXPLAIN_value, 1); - zend_string *const_EXPLAIN_MODE_EXPLAIN_name = zend_string_init_interned("EXPLAIN_MODE_EXPLAIN", sizeof("EXPLAIN_MODE_EXPLAIN") - 1, 1); + zend_string *const_EXPLAIN_MODE_EXPLAIN_name = zend_string_init_interned("EXPLAIN_MODE_EXPLAIN", sizeof("EXPLAIN_MODE_EXPLAIN") - 1, true); zend_declare_typed_class_constant(class_entry, const_EXPLAIN_MODE_EXPLAIN_name, &const_EXPLAIN_MODE_EXPLAIN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EXPLAIN_MODE_EXPLAIN_name); + zend_string_release_ex(const_EXPLAIN_MODE_EXPLAIN_name, true); zval const_EXPLAIN_MODE_EXPLAIN_QUERY_PLAN_value; ZVAL_LONG(&const_EXPLAIN_MODE_EXPLAIN_QUERY_PLAN_value, 2); - zend_string *const_EXPLAIN_MODE_EXPLAIN_QUERY_PLAN_name = zend_string_init_interned("EXPLAIN_MODE_EXPLAIN_QUERY_PLAN", sizeof("EXPLAIN_MODE_EXPLAIN_QUERY_PLAN") - 1, 1); + zend_string *const_EXPLAIN_MODE_EXPLAIN_QUERY_PLAN_name = zend_string_init_interned("EXPLAIN_MODE_EXPLAIN_QUERY_PLAN", sizeof("EXPLAIN_MODE_EXPLAIN_QUERY_PLAN") - 1, true); zend_declare_typed_class_constant(class_entry, const_EXPLAIN_MODE_EXPLAIN_QUERY_PLAN_name, &const_EXPLAIN_MODE_EXPLAIN_QUERY_PLAN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EXPLAIN_MODE_EXPLAIN_QUERY_PLAN_name); + zend_string_release_ex(const_EXPLAIN_MODE_EXPLAIN_QUERY_PLAN_name, true); #endif return class_entry; diff --git a/ext/sqlite3/tests/gh20699.phpt b/ext/sqlite3/tests/gh20699.phpt new file mode 100644 index 0000000000000..1b53bfc98e39f --- /dev/null +++ b/ext/sqlite3/tests/gh20699.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-20699 (SQLite3Result fetchArray return array|false, null returned) +--EXTENSIONS-- +sqlite3 +--CREDITS-- +plusminmax +--FILE-- +prepare('BEGIN;')->execute()->fetchArray()); +?> +--EXPECTF-- +Warning: SQLite3Result::fetchArray(): Unable to execute statement: cannot start a transaction within a transaction in %s on line %d +bool(false) diff --git a/ext/sqlite3/tests/text_column_NUL_bytes.phpt b/ext/sqlite3/tests/text_column_NUL_bytes.phpt new file mode 100644 index 0000000000000..cf9403d91302d --- /dev/null +++ b/ext/sqlite3/tests/text_column_NUL_bytes.phpt @@ -0,0 +1,38 @@ +--TEST-- +Text column with NUL bytes +--EXTENSIONS-- +sqlite3 +--FILE-- +exec( + 'CREATE TABLE messages ( + content TEXT + )' +); + +$insert = $db->prepare( + 'INSERT INTO messages (content) VALUES (:content)' +); + +$insert->bindValue(':content', "with\0null", SQLITE3_TEXT); +$insert->execute(); +$insert->bindValue(':content', "\0", SQLITE3_TEXT); +$insert->execute(); + +$result = $db->query('SELECT * FROM messages'); +while ($row = $result->fetchArray(SQLITE3_ASSOC)) { + var_dump($row); +} + +?> +--EXPECTF-- +array(1) { + ["content"]=> + string(9) "with%0null" +} +array(1) { + ["content"]=> + string(1) "%0" +} diff --git a/ext/standard/array.c b/ext/standard/array.c index 522e7f715acb7..893e07dd8f99a 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -214,7 +214,7 @@ static zend_always_inline int php_array_key_compare_string_unstable_i(Bucket *f, } /* }}} */ -static int php_array_key_compare_string_natural_general(Bucket *f, Bucket *s, int fold_case) /* {{{ */ +static int php_array_key_compare_string_natural_general(Bucket *f, Bucket *s, bool fold_case) /* {{{ */ { const char *s1, *s2; size_t l1, l2; @@ -241,25 +241,25 @@ static int php_array_key_compare_string_natural_general(Bucket *f, Bucket *s, in static int php_array_key_compare_string_natural_case(Bucket *a, Bucket *b) /* {{{ */ { - RETURN_STABLE_SORT(a, b, php_array_key_compare_string_natural_general(a, b, 1)); + RETURN_STABLE_SORT(a, b, php_array_key_compare_string_natural_general(a, b, true)); } /* }}} */ static int php_array_reverse_key_compare_string_natural_case(Bucket *a, Bucket *b) /* {{{ */ { - RETURN_STABLE_SORT(a, b, php_array_key_compare_string_natural_general(b, a, 1)); + RETURN_STABLE_SORT(a, b, php_array_key_compare_string_natural_general(b, a, true)); } /* }}} */ static int php_array_key_compare_string_natural(Bucket *a, Bucket *b) /* {{{ */ { - RETURN_STABLE_SORT(a, b, php_array_key_compare_string_natural_general(a, b, 0)); + RETURN_STABLE_SORT(a, b, php_array_key_compare_string_natural_general(a, b, false)); } /* }}} */ static int php_array_reverse_key_compare_string_natural(Bucket *a, Bucket *b) /* {{{ */ { - RETURN_STABLE_SORT(a, b, php_array_key_compare_string_natural_general(b, a, 0)); + RETURN_STABLE_SORT(a, b, php_array_key_compare_string_natural_general(b, a, false)); } /* }}} */ @@ -327,7 +327,7 @@ static zend_always_inline int php_array_data_compare_string_unstable_i(Bucket *f } /* }}} */ -static int php_array_natural_general_compare(Bucket *f, Bucket *s, int fold_case) /* {{{ */ +static int php_array_natural_general_compare(Bucket *f, Bucket *s, bool fold_case) /* {{{ */ { zend_string *tmp_str1, *tmp_str2; zend_string *str1 = zval_get_tmp_string(&f->val, &tmp_str1); @@ -343,13 +343,13 @@ static int php_array_natural_general_compare(Bucket *f, Bucket *s, int fold_case static zend_always_inline int php_array_natural_compare_unstable_i(Bucket *a, Bucket *b) /* {{{ */ { - return php_array_natural_general_compare(a, b, 0); + return php_array_natural_general_compare(a, b, false); } /* }}} */ static zend_always_inline int php_array_natural_case_compare_unstable_i(Bucket *a, Bucket *b) /* {{{ */ { - return php_array_natural_general_compare(a, b, 1); + return php_array_natural_general_compare(a, b, true); } /* }}} */ @@ -372,135 +372,127 @@ DEFINE_SORT_VARIANTS(data_compare_string_locale); DEFINE_SORT_VARIANTS(natural_compare); DEFINE_SORT_VARIANTS(natural_case_compare); -static bucket_compare_func_t php_get_key_compare_func(zend_long sort_type, int reverse) /* {{{ */ +static bucket_compare_func_t php_get_key_compare_func(zend_long sort_type) { switch (sort_type & ~PHP_SORT_FLAG_CASE) { case PHP_SORT_NUMERIC: - if (reverse) { - return php_array_reverse_key_compare_numeric; - } else { - return php_array_key_compare_numeric; - } - break; + return php_array_key_compare_numeric; case PHP_SORT_STRING: if (sort_type & PHP_SORT_FLAG_CASE) { - if (reverse) { - return php_array_reverse_key_compare_string_case; - } else { - return php_array_key_compare_string_case; - } + return php_array_key_compare_string_case; } else { - if (reverse) { - return php_array_reverse_key_compare_string; - } else { - return php_array_key_compare_string; - } + return php_array_key_compare_string; } - break; case PHP_SORT_NATURAL: if (sort_type & PHP_SORT_FLAG_CASE) { - if (reverse) { - return php_array_reverse_key_compare_string_natural_case; - } else { - return php_array_key_compare_string_natural_case; - } + return php_array_key_compare_string_natural_case; } else { - if (reverse) { - return php_array_reverse_key_compare_string_natural; - } else { - return php_array_key_compare_string_natural; - } + return php_array_key_compare_string_natural; } - break; case PHP_SORT_LOCALE_STRING: - if (reverse) { - return php_array_reverse_key_compare_string_locale; - } else { - return php_array_key_compare_string_locale; - } - break; + return php_array_key_compare_string_locale; case PHP_SORT_REGULAR: default: - if (reverse) { - return php_array_reverse_key_compare; - } else { - return php_array_key_compare; - } - break; + return php_array_key_compare; } return NULL; } -/* }}} */ -static bucket_compare_func_t php_get_data_compare_func(zend_long sort_type, int reverse) /* {{{ */ +static bucket_compare_func_t php_get_key_reverse_compare_func(zend_long sort_type) { switch (sort_type & ~PHP_SORT_FLAG_CASE) { case PHP_SORT_NUMERIC: - if (reverse) { - return php_array_reverse_data_compare_numeric; - } else { - return php_array_data_compare_numeric; - } - break; + return php_array_reverse_key_compare_numeric; case PHP_SORT_STRING: if (sort_type & PHP_SORT_FLAG_CASE) { - if (reverse) { - return php_array_reverse_data_compare_string_case; - } else { - return php_array_data_compare_string_case; - } + return php_array_reverse_key_compare_string_case; } else { - if (reverse) { - return php_array_reverse_data_compare_string; - } else { - return php_array_data_compare_string; - } + return php_array_reverse_key_compare_string; } - break; case PHP_SORT_NATURAL: if (sort_type & PHP_SORT_FLAG_CASE) { - if (reverse) { - return php_array_reverse_natural_case_compare; - } else { - return php_array_natural_case_compare; - } + return php_array_reverse_key_compare_string_natural_case; } else { - if (reverse) { - return php_array_reverse_natural_compare; - } else { - return php_array_natural_compare; - } + return php_array_reverse_key_compare_string_natural; } - break; case PHP_SORT_LOCALE_STRING: - if (reverse) { - return php_array_reverse_data_compare_string_locale; + return php_array_reverse_key_compare_string_locale; + + case PHP_SORT_REGULAR: + default: + return php_array_reverse_key_compare; + } + return NULL; +} + +static bucket_compare_func_t php_get_data_compare_func(zend_long sort_type) /* {{{ */ +{ + switch (sort_type & ~PHP_SORT_FLAG_CASE) { + case PHP_SORT_NUMERIC: + return php_array_data_compare_numeric; + + case PHP_SORT_STRING: + if (sort_type & PHP_SORT_FLAG_CASE) { + return php_array_data_compare_string_case; } else { - return php_array_data_compare_string_locale; + return php_array_data_compare_string; } - break; + + case PHP_SORT_NATURAL: + if (sort_type & PHP_SORT_FLAG_CASE) { + return php_array_natural_case_compare; + } else { + return php_array_natural_compare; + } + + case PHP_SORT_LOCALE_STRING: + return php_array_data_compare_string_locale; case PHP_SORT_REGULAR: default: - if (reverse) { - return php_array_reverse_data_compare; + return php_array_data_compare; + } + return NULL; +} + +static bucket_compare_func_t php_get_data_reverse_compare_func(zend_long sort_type) /* {{{ */ +{ + switch (sort_type & ~PHP_SORT_FLAG_CASE) { + case PHP_SORT_NUMERIC: + return php_array_reverse_data_compare_numeric; + + case PHP_SORT_STRING: + if (sort_type & PHP_SORT_FLAG_CASE) { + return php_array_reverse_data_compare_string_case; } else { - return php_array_data_compare; + return php_array_reverse_data_compare_string; } - break; + + case PHP_SORT_NATURAL: + if (sort_type & PHP_SORT_FLAG_CASE) { + return php_array_reverse_natural_case_compare; + } else { + return php_array_reverse_natural_compare; + } + + case PHP_SORT_LOCALE_STRING: + return php_array_reverse_data_compare_string_locale; + + case PHP_SORT_REGULAR: + default: + return php_array_reverse_data_compare; } return NULL; } -/* }}} */ -static bucket_compare_func_t php_get_data_compare_func_unstable(zend_long sort_type, int reverse) /* {{{ */ +static bucket_compare_func_t php_get_data_compare_func_unstable(zend_long sort_type, bool reverse) /* {{{ */ { switch (sort_type & ~PHP_SORT_FLAG_CASE) { case PHP_SORT_NUMERIC: @@ -564,48 +556,6 @@ static bucket_compare_func_t php_get_data_compare_func_unstable(zend_long sort_t } /* }}} */ -/* {{{ Sort an array by key value in reverse order */ -PHP_FUNCTION(krsort) -{ - zval *array; - zend_long sort_type = PHP_SORT_REGULAR; - bucket_compare_func_t cmp; - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_ARRAY_EX(array, 0, 1) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(sort_type) - ZEND_PARSE_PARAMETERS_END(); - - cmp = php_get_key_compare_func(sort_type, 1); - - zend_hash_sort(Z_ARRVAL_P(array), cmp, 0); - - RETURN_TRUE; -} -/* }}} */ - -/* {{{ Sort an array by key */ -PHP_FUNCTION(ksort) -{ - zval *array; - zend_long sort_type = PHP_SORT_REGULAR; - bucket_compare_func_t cmp; - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_ARRAY_EX(array, 0, 1) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(sort_type) - ZEND_PARSE_PARAMETERS_END(); - - cmp = php_get_key_compare_func(sort_type, 0); - - zend_hash_sort(Z_ARRVAL_P(array), cmp, 0); - - RETURN_TRUE; -} -/* }}} */ - PHPAPI zend_long php_count_recursive(HashTable *ht) /* {{{ */ { zend_long cnt = 0; @@ -702,119 +652,92 @@ PHP_FUNCTION(count) } /* }}} */ -static void php_natsort(INTERNAL_FUNCTION_PARAMETERS, int fold_case) /* {{{ */ +static void php_natsort(INTERNAL_FUNCTION_PARAMETERS, bucket_compare_func_t sort_fn) { - zval *array; + HashTable *array; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_ARRAY_EX(array, 0, 1) + Z_PARAM_ARRAY_HT_EX(array, 0, 1) ZEND_PARSE_PARAMETERS_END(); - if (fold_case) { - zend_array_sort(Z_ARRVAL_P(array), php_array_natural_case_compare, 0); - } else { - zend_array_sort(Z_ARRVAL_P(array), php_array_natural_compare, 0); - } + zend_array_sort(array, sort_fn, false); RETURN_TRUE; } -/* }}} */ /* {{{ Sort an array using natural sort */ PHP_FUNCTION(natsort) { - php_natsort(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + php_natsort(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_array_natural_compare); } /* }}} */ /* {{{ Sort an array using case-insensitive natural sort */ PHP_FUNCTION(natcasesort) { - php_natsort(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); + php_natsort(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_array_natural_case_compare); } /* }}} */ -/* {{{ Sort an array and maintain index association */ -PHP_FUNCTION(asort) -{ - zval *array; +typedef bucket_compare_func_t(*get_compare_function)(zend_long); + +static zend_always_inline void php_sort(INTERNAL_FUNCTION_PARAMETERS, get_compare_function get_cmp, bool renumber) { + HashTable *array; zend_long sort_type = PHP_SORT_REGULAR; bucket_compare_func_t cmp; ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_ARRAY_EX(array, 0, 1) + Z_PARAM_ARRAY_HT_EX(array, 0, 1) Z_PARAM_OPTIONAL Z_PARAM_LONG(sort_type) ZEND_PARSE_PARAMETERS_END(); - cmp = php_get_data_compare_func(sort_type, 0); + cmp = get_cmp(sort_type); - zend_array_sort(Z_ARRVAL_P(array), cmp, 0); + zend_array_sort(array, cmp, renumber); RETURN_TRUE; } + +/* {{{ Sort an array and maintain index association */ +PHP_FUNCTION(asort) +{ + php_sort(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_get_data_compare_func, false); +} /* }}} */ /* {{{ Sort an array in reverse order and maintain index association */ PHP_FUNCTION(arsort) { - zval *array; - zend_long sort_type = PHP_SORT_REGULAR; - bucket_compare_func_t cmp; - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_ARRAY_EX(array, 0, 1) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(sort_type) - ZEND_PARSE_PARAMETERS_END(); - - cmp = php_get_data_compare_func(sort_type, 1); - - zend_array_sort(Z_ARRVAL_P(array), cmp, 0); - - RETURN_TRUE; + php_sort(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_get_data_reverse_compare_func, false); } /* }}} */ /* {{{ Sort an array */ PHP_FUNCTION(sort) { - zval *array; - zend_long sort_type = PHP_SORT_REGULAR; - bucket_compare_func_t cmp; - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_ARRAY_EX(array, 0, 1) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(sort_type) - ZEND_PARSE_PARAMETERS_END(); - - cmp = php_get_data_compare_func(sort_type, 0); - - zend_array_sort(Z_ARRVAL_P(array), cmp, 1); - - RETURN_TRUE; + php_sort(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_get_data_compare_func, true); } /* }}} */ /* {{{ Sort an array in reverse order */ PHP_FUNCTION(rsort) { - zval *array; - zend_long sort_type = PHP_SORT_REGULAR; - bucket_compare_func_t cmp; - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_ARRAY_EX(array, 0, 1) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(sort_type) - ZEND_PARSE_PARAMETERS_END(); - - cmp = php_get_data_compare_func(sort_type, 1); + php_sort(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_get_data_reverse_compare_func, true); +} +/* }}} */ - zend_array_sort(Z_ARRVAL_P(array), cmp, 1); +/* {{{ Sort an array by key value in reverse order */ +PHP_FUNCTION(krsort) +{ + php_sort(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_get_key_reverse_compare_func, false); +} +/* }}} */ - RETURN_TRUE; +/* {{{ Sort an array by key */ +PHP_FUNCTION(ksort) +{ + php_sort(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_get_key_compare_func, false); } /* }}} */ @@ -912,14 +835,14 @@ static void php_usort(INTERNAL_FUNCTION_PARAMETERS, bucket_compare_func_t compar /* {{{ Sort an array by values using a user-defined comparison function */ PHP_FUNCTION(usort) { - php_usort(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_array_user_compare, 1); + php_usort(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_array_user_compare, true); } /* }}} */ /* {{{ Sort an array with a user-defined comparison function and maintain index association */ PHP_FUNCTION(uasort) { - php_usort(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_array_user_compare, 0); + php_usort(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_array_user_compare, false); } /* }}} */ @@ -986,7 +909,7 @@ static int php_array_user_key_compare(Bucket *a, Bucket *b) /* {{{ */ /* {{{ Sort an array by keys using a user-defined comparison function */ PHP_FUNCTION(uksort) { - php_usort(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_array_user_key_compare, 0); + php_usort(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_array_user_key_compare, false); } /* }}} */ @@ -1219,7 +1142,7 @@ PHP_FUNCTION(min) min_lval = Z_LVAL(args[i]); min = &args[i]; } - } else if (Z_TYPE(args[i]) == IS_DOUBLE && (zend_dval_to_lval((double) min_lval) == min_lval)) { + } else if (Z_TYPE(args[i]) == IS_DOUBLE && (zend_dval_to_lval_silent((double) min_lval) == min_lval)) { /* if min_lval can be exactly represented as a double, go to double dedicated code */ min_dval = (double) min_lval; goto double_compare; @@ -1239,7 +1162,7 @@ PHP_FUNCTION(min) min_dval = Z_DVAL(args[i]); min = &args[i]; } - } else if (Z_TYPE(args[i]) == IS_LONG && (zend_dval_to_lval((double) Z_LVAL(args[i])) == Z_LVAL(args[i]))) { + } else if (Z_TYPE(args[i]) == IS_LONG && (zend_dval_to_lval_silent((double) Z_LVAL(args[i])) == Z_LVAL(args[i]))) { /* if the value can be exactly represented as a double, use double dedicated code otherwise generic */ if (min_dval > (double)Z_LVAL(args[i])) { min_dval = (double)Z_LVAL(args[i]); @@ -1277,7 +1200,7 @@ ZEND_FRAMELESS_FUNCTION(min, 2) if (EXPECTED(Z_TYPE_P(rhs) == IS_LONG)) { RETURN_COPY_VALUE(lhs_lval < Z_LVAL_P(rhs) ? lhs : rhs); - } else if (Z_TYPE_P(rhs) == IS_DOUBLE && (zend_dval_to_lval((double) lhs_lval) == lhs_lval)) { + } else if (Z_TYPE_P(rhs) == IS_DOUBLE && (zend_dval_to_lval_silent((double) lhs_lval) == lhs_lval)) { /* if lhs_lval can be exactly represented as a double, go to double dedicated code */ lhs_dval = (double) lhs_lval; goto double_compare; @@ -1290,7 +1213,7 @@ ZEND_FRAMELESS_FUNCTION(min, 2) if (EXPECTED(Z_TYPE_P(rhs) == IS_DOUBLE)) { double_compare: RETURN_COPY_VALUE(lhs_dval < Z_DVAL_P(rhs) ? lhs : rhs); - } else if (Z_TYPE_P(rhs) == IS_LONG && (zend_dval_to_lval((double) Z_LVAL_P(rhs)) == Z_LVAL_P(rhs))) { + } else if (Z_TYPE_P(rhs) == IS_LONG && (zend_dval_to_lval_silent((double) Z_LVAL_P(rhs)) == Z_LVAL_P(rhs))) { /* if the value can be exactly represented as a double, use double dedicated code otherwise generic */ RETURN_COPY_VALUE(lhs_dval < (double)Z_LVAL_P(rhs) ? lhs : rhs); } else { @@ -1347,7 +1270,7 @@ PHP_FUNCTION(max) max_lval = Z_LVAL(args[i]); max = &args[i]; } - } else if (Z_TYPE(args[i]) == IS_DOUBLE && (zend_dval_to_lval((double) max_lval) == max_lval)) { + } else if (Z_TYPE(args[i]) == IS_DOUBLE && (zend_dval_to_lval_silent((double) max_lval) == max_lval)) { /* if max_lval can be exactly represented as a double, go to double dedicated code */ max_dval = (double) max_lval; goto double_compare; @@ -1367,7 +1290,7 @@ PHP_FUNCTION(max) max_dval = Z_DVAL(args[i]); max = &args[i]; } - } else if (Z_TYPE(args[i]) == IS_LONG && (zend_dval_to_lval((double) Z_LVAL(args[i])) == Z_LVAL(args[i]))) { + } else if (Z_TYPE(args[i]) == IS_LONG && (zend_dval_to_lval_silent((double) Z_LVAL(args[i])) == Z_LVAL(args[i]))) { /* if the value can be exactly represented as a double, use double dedicated code otherwise generic */ if (max_dval < (double)Z_LVAL(args[i])) { max_dval = (double)Z_LVAL(args[i]); @@ -1405,7 +1328,7 @@ ZEND_FRAMELESS_FUNCTION(max, 2) if (EXPECTED(Z_TYPE_P(rhs) == IS_LONG)) { RETURN_COPY_VALUE(lhs_lval >= Z_LVAL_P(rhs) ? lhs : rhs); - } else if (Z_TYPE_P(rhs) == IS_DOUBLE && (zend_dval_to_lval((double) lhs_lval) == lhs_lval)) { + } else if (Z_TYPE_P(rhs) == IS_DOUBLE && (zend_dval_to_lval_silent((double) lhs_lval) == lhs_lval)) { /* if lhs_lval can be exactly represented as a double, go to double dedicated code */ lhs_dval = (double) lhs_lval; goto double_compare; @@ -1418,7 +1341,7 @@ ZEND_FRAMELESS_FUNCTION(max, 2) if (EXPECTED(Z_TYPE_P(rhs) == IS_DOUBLE)) { double_compare: RETURN_COPY_VALUE(lhs_dval >= Z_DVAL_P(rhs) ? lhs : rhs); - } else if (Z_TYPE_P(rhs) == IS_LONG && (zend_dval_to_lval((double) Z_LVAL_P(rhs)) == Z_LVAL_P(rhs))) { + } else if (Z_TYPE_P(rhs) == IS_LONG && (zend_dval_to_lval_silent((double) Z_LVAL_P(rhs)) == Z_LVAL_P(rhs))) { /* if the value can be exactly represented as a double, use double dedicated code otherwise generic */ RETURN_COPY_VALUE(lhs_dval >= (double)Z_LVAL_P(rhs) ? lhs : rhs); } else { @@ -1457,7 +1380,7 @@ static zend_result php_array_walk( /* Set up known arguments */ ZVAL_UNDEF(&args[1]); if (userdata) { - ZVAL_COPY(&args[2], userdata); + ZVAL_COPY_VALUE(&args[2], userdata); } fci.retval = &retval; @@ -1531,21 +1454,14 @@ static zend_result php_array_walk( } zval_ptr_dtor(&ref); } else { - ZVAL_COPY(&args[0], zv); + ZVAL_COPY_VALUE(&args[0], zv); /* Call the userland function */ result = zend_call_function(&fci, &context->fci_cache); - if (result == SUCCESS) { - zval_ptr_dtor(&retval); - } - - zval_ptr_dtor(&args[0]); + zval_ptr_dtor(&retval); } - if (Z_TYPE(args[1]) != IS_UNDEF) { - zval_ptr_dtor(&args[1]); - ZVAL_UNDEF(&args[1]); - } + zval_ptr_dtor_str(&args[1]); if (result == FAILURE) { break; @@ -1565,9 +1481,6 @@ static zend_result php_array_walk( } } while (!EG(exception)); - if (userdata) { - zval_ptr_dtor(&args[2]); - } zend_hash_iterator_del(ht_iter); return result; } @@ -1762,9 +1675,8 @@ PHP_FUNCTION(array_search) } /* }}} */ -static zend_always_inline int php_valid_var_name(const char *var_name, size_t var_name_len) /* {{{ */ +static zend_always_inline bool php_valid_var_name(const zend_string *var_name) /* {{{ */ { -#if 1 /* first 256 bits for first character, and second 256 bits for the next */ static const uint32_t charset[8] = { /* 31 0 63 32 95 64 127 96 */ @@ -1774,67 +1686,37 @@ static zend_always_inline int php_valid_var_name(const char *var_name, size_t va /* 31 0 63 32 95 64 127 96 */ 0x00000000, 0x03ff0000, 0x87fffffe, 0x07fffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}; -#endif - size_t i; - uint32_t ch; - if (UNEXPECTED(!var_name_len)) { - return 0; + if (UNEXPECTED(!ZSTR_LEN(var_name))) { + return false; } /* These are allowed as first char: [a-zA-Z_\x7f-\xff] */ - ch = (uint32_t)((unsigned char *)var_name)[0]; -#if 1 + uint32_t ch = (uint32_t)((unsigned char *)ZSTR_VAL(var_name))[0]; if (UNEXPECTED(!ZEND_BIT_TEST(charset, ch))) { -#else - if (var_name[0] != '_' && - (ch < 65 /* A */ || /* Z */ ch > 90) && - (ch < 97 /* a */ || /* z */ ch > 122) && - (ch < 127 /* 0x7f */ || /* 0xff */ ch > 255) - ) { -#endif - return 0; + return false; } /* And these as the rest: [a-zA-Z0-9_\x7f-\xff] */ - if (var_name_len > 1) { - i = 1; + if (ZSTR_LEN(var_name) > 1) { + size_t i = 1; do { - ch = (uint32_t)((unsigned char *)var_name)[i]; -#if 1 + ch = (uint32_t)((unsigned char *)ZSTR_VAL(var_name))[i]; if (UNEXPECTED(!ZEND_BIT_TEST(charset2, ch))) { -#else - if (var_name[i] != '_' && - (ch < 48 /* 0 */ || /* 9 */ ch > 57) && - (ch < 65 /* A */ || /* Z */ ch > 90) && - (ch < 97 /* a */ || /* z */ ch > 122) && - (ch < 127 /* 0x7f */ || /* 0xff */ ch > 255) - ) { -#endif - return 0; + return false; } - } while (++i < var_name_len); + } while (++i < ZSTR_LEN(var_name)); } - return 1; + return true; } /* }}} */ -PHPAPI int php_prefix_varname(zval *result, zend_string *prefix, const char *var_name, size_t var_name_len, bool add_underscore) /* {{{ */ +static zend_string* php_prefix_varname(const zend_string *prefix, const zend_string *var_name) { - ZVAL_NEW_STR(result, zend_string_alloc(ZSTR_LEN(prefix) + (add_underscore ? 1 : 0) + var_name_len, 0)); - memcpy(Z_STRVAL_P(result), ZSTR_VAL(prefix), ZSTR_LEN(prefix)); - - if (add_underscore) { - Z_STRVAL_P(result)[ZSTR_LEN(prefix)] = '_'; - } - - memcpy(Z_STRVAL_P(result) + ZSTR_LEN(prefix) + (add_underscore ? 1 : 0), var_name, var_name_len + 1); - - return SUCCESS; + return zend_string_concat3(ZSTR_VAL(prefix), ZSTR_LEN(prefix), ZEND_STRL("_"), ZSTR_VAL(var_name), ZSTR_LEN(var_name)); } -/* }}} */ -static zend_long php_extract_ref_if_exists(zend_array *arr, zend_array *symbol_table) /* {{{ */ +static zend_long php_extract_ref_if_exists(const zend_array *arr, const zend_array *symbol_table) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -1855,7 +1737,7 @@ static zend_long php_extract_ref_if_exists(zend_array *arr, zend_array *symbol_t continue; } } - if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) { + if (!php_valid_var_name(var_name)) { continue; } if (zend_string_equals_literal(var_name, "GLOBALS")) { @@ -1880,7 +1762,7 @@ static zend_long php_extract_ref_if_exists(zend_array *arr, zend_array *symbol_t } /* }}} */ -static zend_long php_extract_if_exists(zend_array *arr, zend_array *symbol_table) /* {{{ */ +static zend_long php_extract_if_exists(const zend_array *arr, const zend_array *symbol_table) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -1901,7 +1783,7 @@ static zend_long php_extract_if_exists(zend_array *arr, zend_array *symbol_table continue; } } - if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) { + if (!php_valid_var_name(var_name)) { continue; } if (zend_string_equals_literal(var_name, "GLOBALS")) { @@ -1924,7 +1806,7 @@ static zend_long php_extract_if_exists(zend_array *arr, zend_array *symbol_table } /* }}} */ -static zend_long php_extract_ref_overwrite(zend_array *arr, zend_array *symbol_table) /* {{{ */ +static zend_long php_extract_ref_overwrite(const zend_array *arr, zend_array *symbol_table) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -1937,7 +1819,7 @@ static zend_long php_extract_ref_overwrite(zend_array *arr, zend_array *symbol_t if (!var_name) { continue; } - if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) { + if (!php_valid_var_name(var_name)) { continue; } if (zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) { @@ -1976,7 +1858,7 @@ static zend_long php_extract_ref_overwrite(zend_array *arr, zend_array *symbol_t } /* }}} */ -static zend_long php_extract_overwrite(zend_array *arr, zend_array *symbol_table) /* {{{ */ +static zend_long php_extract_overwrite(const zend_array *arr, zend_array *symbol_table) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -1989,7 +1871,7 @@ static zend_long php_extract_overwrite(zend_array *arr, zend_array *symbol_table if (!var_name) { continue; } - if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) { + if (!php_valid_var_name(var_name)) { continue; } if (zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) { @@ -2021,11 +1903,11 @@ static zend_long php_extract_overwrite(zend_array *arr, zend_array *symbol_table } /* }}} */ -static zend_long php_extract_ref_prefix_if_exists(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ +static zend_long php_extract_ref_prefix_if_exists(const zend_array *arr, zend_array *symbol_table, const zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; - zval *entry, *orig_var, final_name; + zval *entry, *orig_var; if (HT_IS_PACKED(arr)) { return 0; @@ -2049,30 +1931,28 @@ static zend_long php_extract_ref_prefix_if_exists(zend_array *arr, zend_array *s continue; } } - php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1); - if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) { - if (zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))) { - zend_throw_error(NULL, "Cannot re-assign $this"); - return -1; + zend_string *final_name = php_prefix_varname(prefix, var_name); + if (php_valid_var_name(final_name)) { + /* Prefixed varname cannot be equal to "this" due to underscore between prefix and name */ + ZEND_ASSERT(!zend_string_equals(final_name, ZSTR_KNOWN(ZEND_STR_THIS))); + + if (Z_ISREF_P(entry)) { + Z_ADDREF_P(entry); } else { - if (Z_ISREF_P(entry)) { - Z_ADDREF_P(entry); - } else { - ZVAL_MAKE_REF_EX(entry, 2); - } - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { - if (Z_TYPE_P(orig_var) == IS_INDIRECT) { - orig_var = Z_INDIRECT_P(orig_var); - } - zval_ptr_dtor(orig_var); - ZVAL_REF(orig_var, Z_REF_P(entry)); - } else { - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + ZVAL_MAKE_REF_EX(entry, 2); + } + if ((orig_var = zend_hash_find(symbol_table, final_name)) != NULL) { + if (Z_TYPE_P(orig_var) == IS_INDIRECT) { + orig_var = Z_INDIRECT_P(orig_var); } - count++; + zval_ptr_dtor(orig_var); + ZVAL_REF(orig_var, Z_REF_P(entry)); + } else { + zend_hash_add_new(symbol_table, final_name, entry); } + count++; } - zval_ptr_dtor_str(&final_name); + zend_string_release_ex(final_name, false); } } ZEND_HASH_FOREACH_END(); @@ -2080,11 +1960,11 @@ static zend_long php_extract_ref_prefix_if_exists(zend_array *arr, zend_array *s } /* }}} */ -static zend_long php_extract_prefix_if_exists(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ +static zend_long php_extract_prefix_if_exists(const zend_array *arr, zend_array *symbol_table, const zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; - zval *entry, *orig_var, final_name; + zval *entry, *orig_var; if (HT_IS_PACKED(arr)) { return 0; @@ -2103,30 +1983,28 @@ static zend_long php_extract_prefix_if_exists(zend_array *arr, zend_array *symbo continue; } } - php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1); - if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) { - if (zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))) { - zend_throw_error(NULL, "Cannot re-assign $this"); - return -1; - } else { - ZVAL_DEREF(entry); - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { - if (Z_TYPE_P(orig_var) == IS_INDIRECT) { - orig_var = Z_INDIRECT_P(orig_var); - } - ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0); - if (UNEXPECTED(EG(exception))) { - zend_string_release_ex(Z_STR(final_name), 0); - return -1; - } - } else { - Z_TRY_ADDREF_P(entry); - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + zend_string *final_name = php_prefix_varname(prefix, var_name); + if (php_valid_var_name(final_name)) { + /* Prefixed varname cannot be equal to "this" due to underscore between prefix and name */ + ZEND_ASSERT(!zend_string_equals(final_name, ZSTR_KNOWN(ZEND_STR_THIS))); + + ZVAL_DEREF(entry); + if ((orig_var = zend_hash_find(symbol_table, final_name)) != NULL) { + if (Z_TYPE_P(orig_var) == IS_INDIRECT) { + orig_var = Z_INDIRECT_P(orig_var); } - count++; + ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0); + if (UNEXPECTED(EG(exception))) { + zend_string_release_ex(final_name, 0); + return -1; + } + } else { + Z_TRY_ADDREF_P(entry); + zend_hash_add_new(symbol_table, final_name, entry); } + count++; } - zval_ptr_dtor_str(&final_name); + zend_string_release_ex(final_name, false); } } ZEND_HASH_FOREACH_END(); @@ -2134,11 +2012,11 @@ static zend_long php_extract_prefix_if_exists(zend_array *arr, zend_array *symbo } /* }}} */ -static zend_long php_extract_ref_prefix_same(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ +static zend_long php_extract_ref_prefix_same(const zend_array *arr, zend_array *symbol_table, const zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; - zval *entry, *orig_var, final_name; + zval *entry, *orig_var; if (HT_IS_PACKED(arr)) { return 0; @@ -2165,33 +2043,31 @@ static zend_long php_extract_ref_prefix_same(zend_array *arr, zend_array *symbol continue; } } -prefix: - php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1); - if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) { - if (zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))) { - zend_throw_error(NULL, "Cannot re-assign $this"); - return -1; +prefix:; + zend_string *final_name = php_prefix_varname(prefix, var_name); + if (php_valid_var_name(final_name)) { + /* Prefixed varname cannot be equal to "this" due to underscore between prefix and name */ + ZEND_ASSERT(!zend_string_equals(final_name, ZSTR_KNOWN(ZEND_STR_THIS))); + + if (Z_ISREF_P(entry)) { + Z_ADDREF_P(entry); } else { - if (Z_ISREF_P(entry)) { - Z_ADDREF_P(entry); - } else { - ZVAL_MAKE_REF_EX(entry, 2); - } - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { - if (Z_TYPE_P(orig_var) == IS_INDIRECT) { - orig_var = Z_INDIRECT_P(orig_var); - } - zval_ptr_dtor(orig_var); - ZVAL_REF(orig_var, Z_REF_P(entry)); - } else { - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + ZVAL_MAKE_REF_EX(entry, 2); + } + if ((orig_var = zend_hash_find(symbol_table, final_name)) != NULL) { + if (Z_TYPE_P(orig_var) == IS_INDIRECT) { + orig_var = Z_INDIRECT_P(orig_var); } - count++; + zval_ptr_dtor(orig_var); + ZVAL_REF(orig_var, Z_REF_P(entry)); + } else { + zend_hash_add_new(symbol_table, final_name, entry); } + count++; } - zval_ptr_dtor_str(&final_name); + zend_string_release_ex(final_name, false); } else { - if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) { + if (!php_valid_var_name(var_name)) { continue; } if (zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) { @@ -2211,11 +2087,11 @@ static zend_long php_extract_ref_prefix_same(zend_array *arr, zend_array *symbol } /* }}} */ -static zend_long php_extract_prefix_same(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ +static zend_long php_extract_prefix_same(const zend_array *arr, zend_array *symbol_table, const zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; - zval *entry, *orig_var, final_name; + zval *entry, *orig_var; if (HT_IS_PACKED(arr)) { return 0; @@ -2237,33 +2113,31 @@ static zend_long php_extract_prefix_same(zend_array *arr, zend_array *symbol_tab continue; } } -prefix: - php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1); - if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) { - if (zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))) { - zend_throw_error(NULL, "Cannot re-assign $this"); - return -1; - } else { - ZVAL_DEREF(entry); - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { - if (Z_TYPE_P(orig_var) == IS_INDIRECT) { - orig_var = Z_INDIRECT_P(orig_var); - } - ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0); - if (UNEXPECTED(EG(exception))) { - zend_string_release_ex(Z_STR(final_name), 0); - return -1; - } - } else { - Z_TRY_ADDREF_P(entry); - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); +prefix:; + zend_string *final_name = php_prefix_varname(prefix, var_name); + if (php_valid_var_name(final_name)) { + /* Prefixed varname cannot be equal to "this" due to underscore between prefix and name */ + ZEND_ASSERT(!zend_string_equals(final_name, ZSTR_KNOWN(ZEND_STR_THIS))); + + ZVAL_DEREF(entry); + if ((orig_var = zend_hash_find(symbol_table, final_name)) != NULL) { + if (Z_TYPE_P(orig_var) == IS_INDIRECT) { + orig_var = Z_INDIRECT_P(orig_var); } - count++; + ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0); + if (UNEXPECTED(EG(exception))) { + zend_string_release_ex(final_name, false); + return -1; + } + } else { + Z_TRY_ADDREF_P(entry); + zend_hash_add_new(symbol_table, final_name, entry); } + count++; } - zval_ptr_dtor_str(&final_name); + zend_string_release_ex(final_name, false); } else { - if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) { + if (!php_valid_var_name(var_name)) { continue; } if (zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) { @@ -2280,211 +2154,210 @@ static zend_long php_extract_prefix_same(zend_array *arr, zend_array *symbol_tab } /* }}} */ -static zend_long php_extract_ref_prefix_all(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ +static zend_long php_extract_ref_prefix_all(const zend_array *arr, zend_array *symbol_table, const zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; zend_ulong num_key; - zval *entry, *orig_var, final_name; + zval *entry, *orig_var; ZEND_HASH_FOREACH_KEY_VAL(arr, num_key, var_name, entry) { + zend_string *final_name; if (var_name) { if (ZSTR_LEN(var_name) == 0) { continue; } - php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1); + final_name = php_prefix_varname(prefix, var_name); } else { zend_string *str = zend_long_to_str(num_key); - php_prefix_varname(&final_name, prefix, ZSTR_VAL(str), ZSTR_LEN(str), 1); - zend_string_release_ex(str, 0); + final_name = php_prefix_varname(prefix, str); + zend_string_release_ex(str, false); } - if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) { - if (zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))) { - zend_throw_error(NULL, "Cannot re-assign $this"); - return -1; + if (php_valid_var_name(final_name)) { + /* Prefixed varname cannot be equal to "this" due to underscore between prefix and name */ + ZEND_ASSERT(!zend_string_equals(final_name, ZSTR_KNOWN(ZEND_STR_THIS))); + + if (Z_ISREF_P(entry)) { + Z_ADDREF_P(entry); } else { - if (Z_ISREF_P(entry)) { - Z_ADDREF_P(entry); - } else { - ZVAL_MAKE_REF_EX(entry, 2); - } - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { - if (Z_TYPE_P(orig_var) == IS_INDIRECT) { - orig_var = Z_INDIRECT_P(orig_var); - } - zval_ptr_dtor(orig_var); - ZVAL_REF(orig_var, Z_REF_P(entry)); - } else { - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + ZVAL_MAKE_REF_EX(entry, 2); + } + if ((orig_var = zend_hash_find(symbol_table, final_name)) != NULL) { + if (Z_TYPE_P(orig_var) == IS_INDIRECT) { + orig_var = Z_INDIRECT_P(orig_var); } - count++; + zval_ptr_dtor(orig_var); + ZVAL_REF(orig_var, Z_REF_P(entry)); + } else { + zend_hash_add_new(symbol_table, final_name, entry); } + count++; } - zval_ptr_dtor_str(&final_name); + zend_string_release_ex(final_name, false); } ZEND_HASH_FOREACH_END(); return count; } /* }}} */ -static zend_long php_extract_prefix_all(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ +static zend_long php_extract_prefix_all(const zend_array *arr, zend_array *symbol_table, const zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; zend_ulong num_key; - zval *entry, *orig_var, final_name; + zval *entry, *orig_var; ZEND_HASH_FOREACH_KEY_VAL(arr, num_key, var_name, entry) { + zend_string *final_name; if (var_name) { if (ZSTR_LEN(var_name) == 0) { continue; } - php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1); + final_name = php_prefix_varname(prefix, var_name); } else { zend_string *str = zend_long_to_str(num_key); - php_prefix_varname(&final_name, prefix, ZSTR_VAL(str), ZSTR_LEN(str), 1); - zend_string_release_ex(str, 0); + final_name = php_prefix_varname(prefix, str); + zend_string_release_ex(str, false); } - if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) { - if (zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))) { - zend_throw_error(NULL, "Cannot re-assign $this"); - return -1; - } else { - ZVAL_DEREF(entry); - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { - if (Z_TYPE_P(orig_var) == IS_INDIRECT) { - orig_var = Z_INDIRECT_P(orig_var); - } - ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0); - if (UNEXPECTED(EG(exception))) { - zend_string_release_ex(Z_STR(final_name), 0); - return -1; - } - } else { - Z_TRY_ADDREF_P(entry); - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + if (php_valid_var_name(final_name)) { + /* Prefixed varname cannot be equal to "this" due to underscore between prefix and name */ + ZEND_ASSERT(!zend_string_equals(final_name, ZSTR_KNOWN(ZEND_STR_THIS))); + + ZVAL_DEREF(entry); + if ((orig_var = zend_hash_find(symbol_table, final_name)) != NULL) { + if (Z_TYPE_P(orig_var) == IS_INDIRECT) { + orig_var = Z_INDIRECT_P(orig_var); } - count++; + ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0); + if (UNEXPECTED(EG(exception))) { + zend_string_release_ex(final_name, false); + return -1; + } + } else { + Z_TRY_ADDREF_P(entry); + zend_hash_add_new(symbol_table, final_name, entry); } + count++; } - zval_ptr_dtor_str(&final_name); + zend_string_release_ex(final_name, false); } ZEND_HASH_FOREACH_END(); return count; } /* }}} */ -static zend_long php_extract_ref_prefix_invalid(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ +static zend_long php_extract_ref_prefix_invalid(const zend_array *arr, zend_array *symbol_table, const zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; zend_ulong num_key; - zval *entry, *orig_var, final_name; + zval *entry, *orig_var; ZEND_HASH_FOREACH_KEY_VAL(arr, num_key, var_name, entry) { + zend_string *final_name; if (var_name) { - if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name)) - || zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) { - php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1); - if (!php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) { - zval_ptr_dtor_str(&final_name); + if (!php_valid_var_name(var_name) || zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) { + final_name = php_prefix_varname(prefix, var_name); + + if (!php_valid_var_name(final_name)) { + zend_string_release_ex(final_name, false); continue; } } else { - ZVAL_STR_COPY(&final_name, var_name); + final_name = zend_string_copy(var_name); } } else { zend_string *str = zend_long_to_str(num_key); - php_prefix_varname(&final_name, prefix, ZSTR_VAL(str), ZSTR_LEN(str), 1); - zend_string_release_ex(str, 0); - if (!php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) { - zval_ptr_dtor_str(&final_name); + final_name = php_prefix_varname(prefix, str); + zend_string_release_ex(str, false); + if (!php_valid_var_name(final_name)) { + zend_string_release_ex(final_name, false); continue; } } - if (zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))) { - zend_throw_error(NULL, "Cannot re-assign $this"); - return -1; + + /* We previously checked if the var name is "this" to prefix it */ + ZEND_ASSERT(!zend_string_equals(final_name, ZSTR_KNOWN(ZEND_STR_THIS))); + + if (Z_ISREF_P(entry)) { + Z_ADDREF_P(entry); } else { - if (Z_ISREF_P(entry)) { - Z_ADDREF_P(entry); - } else { - ZVAL_MAKE_REF_EX(entry, 2); - } - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { - if (Z_TYPE_P(orig_var) == IS_INDIRECT) { - orig_var = Z_INDIRECT_P(orig_var); - } - zval_ptr_dtor(orig_var); - ZVAL_REF(orig_var, Z_REF_P(entry)); - } else { - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + ZVAL_MAKE_REF_EX(entry, 2); + } + if ((orig_var = zend_hash_find(symbol_table, final_name)) != NULL) { + if (Z_TYPE_P(orig_var) == IS_INDIRECT) { + orig_var = Z_INDIRECT_P(orig_var); } - count++; + zval_ptr_dtor(orig_var); + ZVAL_REF(orig_var, Z_REF_P(entry)); + } else { + zend_hash_add_new(symbol_table, final_name, entry); } - zval_ptr_dtor_str(&final_name); + count++; + + zend_string_release_ex(final_name, false); } ZEND_HASH_FOREACH_END(); return count; } /* }}} */ -static zend_long php_extract_prefix_invalid(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ +static zend_long php_extract_prefix_invalid(const zend_array *arr, zend_array *symbol_table, const zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; zend_ulong num_key; - zval *entry, *orig_var, final_name; + zval *entry, *orig_var; ZEND_HASH_FOREACH_KEY_VAL(arr, num_key, var_name, entry) { + zend_string *final_name; if (var_name) { - if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name)) - || zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) { - php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1); - if (!php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) { - zval_ptr_dtor_str(&final_name); + if (!php_valid_var_name(var_name) || zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) { + final_name = php_prefix_varname(prefix, var_name); + if (!php_valid_var_name(final_name)) { + zend_string_release_ex(final_name, false); continue; } } else { - ZVAL_STR_COPY(&final_name, var_name); + final_name = zend_string_copy(var_name); } } else { zend_string *str = zend_long_to_str(num_key); - php_prefix_varname(&final_name, prefix, ZSTR_VAL(str), ZSTR_LEN(str), 1); + final_name = php_prefix_varname(prefix, str); zend_string_release_ex(str, 0); - if (!php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) { - zval_ptr_dtor_str(&final_name); + if (!php_valid_var_name(final_name)) { + zend_string_release_ex(final_name, false); continue; } } - if (zend_string_equals(Z_STR(final_name), ZSTR_KNOWN(ZEND_STR_THIS))) { - zend_throw_error(NULL, "Cannot re-assign $this"); - return -1; - } else { - ZVAL_DEREF(entry); - if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) { - if (Z_TYPE_P(orig_var) == IS_INDIRECT) { - orig_var = Z_INDIRECT_P(orig_var); - } - ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0); - if (UNEXPECTED(EG(exception))) { - zend_string_release_ex(Z_STR(final_name), 0); - return -1; - } - } else { - Z_TRY_ADDREF_P(entry); - zend_hash_add_new(symbol_table, Z_STR(final_name), entry); + + /* We previously checked if the var name is "this" to prefix it */ + ZEND_ASSERT(!zend_string_equals(final_name, ZSTR_KNOWN(ZEND_STR_THIS))); + + ZVAL_DEREF(entry); + if ((orig_var = zend_hash_find(symbol_table, final_name)) != NULL) { + if (Z_TYPE_P(orig_var) == IS_INDIRECT) { + orig_var = Z_INDIRECT_P(orig_var); } - count++; + ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0); + if (UNEXPECTED(EG(exception))) { + zend_string_release_ex(final_name, false); + return -1; + } + } else { + Z_TRY_ADDREF_P(entry); + zend_hash_add_new(symbol_table, final_name, entry); } - zval_ptr_dtor_str(&final_name); + count++; + + zend_string_release_ex(final_name, false); } ZEND_HASH_FOREACH_END(); return count; } /* }}} */ -static zend_long php_extract_ref_skip(zend_array *arr, zend_array *symbol_table) /* {{{ */ +static zend_long php_extract_ref_skip(const zend_array *arr, zend_array *symbol_table) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -2497,7 +2370,7 @@ static zend_long php_extract_ref_skip(zend_array *arr, zend_array *symbol_table) if (!var_name) { continue; } - if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) { + if (!php_valid_var_name(var_name)) { continue; } if (zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) { @@ -2532,7 +2405,7 @@ static zend_long php_extract_ref_skip(zend_array *arr, zend_array *symbol_table) } /* }}} */ -static zend_long php_extract_skip(zend_array *arr, zend_array *symbol_table) /* {{{ */ +static zend_long php_extract_skip(const zend_array *arr, zend_array *symbol_table) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -2545,7 +2418,7 @@ static zend_long php_extract_skip(zend_array *arr, zend_array *symbol_table) /* if (!var_name) { continue; } - if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) { + if (!php_valid_var_name(var_name)) { continue; } if (zend_string_equals(var_name, ZSTR_KNOWN(ZEND_STR_THIS))) { @@ -2606,7 +2479,7 @@ PHP_FUNCTION(extract) } if (prefix) { - if (ZSTR_LEN(prefix) && !php_valid_var_name(ZSTR_VAL(prefix), ZSTR_LEN(prefix))) { + if (ZSTR_LEN(prefix) && !php_valid_var_name(prefix)) { zend_argument_value_error(3, "must be a valid identifier"); RETURN_THROWS(); } @@ -2830,16 +2703,19 @@ PHP_FUNCTION(array_fill_keys) ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(keys), entry) { ZVAL_DEREF(entry); - Z_TRY_ADDREF_P(val); if (Z_TYPE_P(entry) == IS_LONG) { - zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_P(entry), val); + zend_hash_index_add(Z_ARRVAL_P(return_value), Z_LVAL_P(entry), val); } else { zend_string *tmp_key; zend_string *key = zval_get_tmp_string(entry, &tmp_key); - zend_symtable_update(Z_ARRVAL_P(return_value), key, val); + zend_symtable_add(Z_ARRVAL_P(return_value), key, val); zend_tmp_string_release(tmp_key); } } ZEND_HASH_FOREACH_END(); + + if (Z_REFCOUNTED_P(val)) { + GC_ADDREF_EX(Z_COUNTED_P(val), zend_hash_num_elements(Z_ARRVAL_P(return_value))); + } } /* }}} */ @@ -2980,7 +2856,7 @@ PHP_FUNCTION(range) is_step_negative = true; step_double *= -1; } - step = zend_dval_to_lval(step_double); + step = zend_dval_to_lval_silent(step_double); if (!zend_is_long_compatible(step_double, step)) { is_step_double = true; } @@ -3047,18 +2923,18 @@ PHP_FUNCTION(range) if (start_type == IS_STRING || end_type == IS_STRING) { php_error_docref(NULL, E_WARNING, "Argument #3 ($step) must be of type int when generating an array" " of characters, inputs converted to 0"); - } - if (UNEXPECTED(EG(exception))) { - RETURN_THROWS(); + if (UNEXPECTED(EG(exception))) { + RETURN_THROWS(); + } } end_type = IS_LONG; start_type = IS_LONG; goto handle_numeric_inputs; } - /* Generate array of characters */ - unsigned char low = (unsigned char)Z_STRVAL_P(user_start)[0]; - unsigned char high = (unsigned char)Z_STRVAL_P(user_end)[0]; + /* Generate array of characters, as zero-extended ints to make bounds checking possible in the loop condition */ + int low = (unsigned char) Z_STRVAL_P(user_start)[0]; + int high = (unsigned char) Z_STRVAL_P(user_end)[0]; /* Decreasing char range */ if (low > high) { @@ -3069,12 +2945,9 @@ PHP_FUNCTION(range) array_init_size(return_value, (uint32_t)(((low - high) / step) + 1)); zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { - for (; low >= high; low -= (unsigned int)step) { + for (; low >= high; low -= step) { ZEND_HASH_FILL_SET_INTERNED_STR(ZSTR_CHAR(low)); ZEND_HASH_FILL_NEXT(); - if (((signed int)low - step) < 0) { - break; - } } } ZEND_HASH_FILL_END(); } else if (high > low) { /* Increasing char range */ @@ -3087,12 +2960,9 @@ PHP_FUNCTION(range) array_init_size(return_value, (uint32_t)(((high - low) / step) + 1)); zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { - for (; low <= high; low += (unsigned int)step) { + for (; low <= high; low += step) { ZEND_HASH_FILL_SET_INTERNED_STR(ZSTR_CHAR(low)); ZEND_HASH_FILL_NEXT(); - if (((signed int)low + step) > 255) { - break; - } } } ZEND_HASH_FILL_END(); } else { @@ -3318,6 +3188,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 +3358,21 @@ 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; + + /* Set internal pointer to 0 directly instead of calling zend_hash_internal_pointer_reset(). + * This avoids the COW violation assertion and delays advancing to the first valid position + * until after we've switched to the new array structure (out_hash). The iterator will be + * advanced when actually accessed, at which point it will find valid indexes in the new array. */ + in_hash->nInternalPointer = 0; + + 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); @@ -3495,8 +3383,6 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H in_hash->nNextFreeElement = out_hash.nNextFreeElement; in_hash->arData = out_hash.arData; in_hash->pDestructor = out_hash.pDestructor; - - zend_hash_internal_pointer_reset(in_hash); } /* }}} */ @@ -3734,18 +3620,34 @@ PHP_FUNCTION(array_unshift) ZEND_PARSE_PARAMETERS_END(); zend_hash_init(&new_hash, zend_hash_num_elements(Z_ARRVAL_P(stack)) + argc, NULL, ZVAL_PTR_DTOR, 0); - for (uint32_t i = 0; i < argc; i++) { - Z_TRY_ADDREF(args[i]); - zend_hash_next_index_insert_new(&new_hash, &args[i]); - } - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(stack), key, value) { - if (key) { - zend_hash_add_new(&new_hash, key, value); - } else { - zend_hash_next_index_insert_new(&new_hash, value); + if (HT_IS_PACKED(Z_ARRVAL_P(stack))) { + zend_hash_real_init_packed(&new_hash); + + ZEND_HASH_FILL_PACKED(&new_hash) { + for (uint32_t i = 0; i < argc; i++) { + Z_TRY_ADDREF(args[i]); + ZEND_HASH_FILL_ADD(&args[i]); + } + + ZEND_HASH_PACKED_FOREACH_VAL(Z_ARRVAL_P(stack), value) { + ZEND_HASH_FILL_ADD(value); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FILL_END(); + } else { + for (uint32_t i = 0; i < argc; i++) { + Z_TRY_ADDREF(args[i]); + zend_hash_next_index_insert_new(&new_hash, &args[i]); } - } ZEND_HASH_FOREACH_END(); + + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(stack), key, value) { + if (key) { + zend_hash_add_new(&new_hash, key, value); + } else { + zend_hash_next_index_insert_new(&new_hash, value); + } + } ZEND_HASH_FOREACH_END(); + } if (UNEXPECTED(HT_HAS_ITERATORS(Z_ARRVAL_P(stack)))) { zend_hash_iterators_advance(Z_ARRVAL_P(stack), argc); @@ -3844,7 +3746,6 @@ static inline Bucket* find_bucket_at_offset(HashTable* ht, zend_long offset) ZEND_ASSERT(offset >= 0 && offset <= ht->nNumOfElements); if (HT_IS_WITHOUT_HOLES(ht)) { /* There's no need to iterate over the array to filter out holes if there are no holes */ - /* This properly handles both packed and unpacked arrays. */ return ht->arData + offset; } /* Otherwise, this code has to iterate over the HashTable and skip holes in the array. */ @@ -3871,7 +3772,6 @@ static inline zval* find_packed_val_at_offset(HashTable* ht, zend_long offset) ZEND_ASSERT(offset >= 0 && offset <= ht->nNumOfElements); if (HT_IS_WITHOUT_HOLES(ht)) { /* There's no need to iterate over the array to filter out holes if there are no holes */ - /* This properly handles both packed and unpacked arrays. */ return ht->arPacked + offset; } /* Otherwise, this code has to iterate over the HashTable and skip holes in the array. */ @@ -4256,7 +4156,7 @@ static zend_always_inline void php_array_merge_wrapper(INTERNAL_FUNCTION_PARAMET uint32_t argc, i; zval *src_entry; HashTable *src, *dest; - uint32_t count = 0; + uint64_t count = 0; ZEND_PARSE_PARAMETERS_START(0, -1) Z_PARAM_VARIADIC('+', args, argc) @@ -4276,6 +4176,11 @@ static zend_always_inline void php_array_merge_wrapper(INTERNAL_FUNCTION_PARAMET count += zend_hash_num_elements(Z_ARRVAL_P(arg)); } + if (UNEXPECTED(count >= HT_MAX_SIZE)) { + zend_throw_error(NULL, "The total number of elements must be lower than %u", HT_MAX_SIZE); + RETURN_THROWS(); + } + if (argc == 2) { zval *ret = NULL; @@ -4287,22 +4192,20 @@ static zend_always_inline void php_array_merge_wrapper(INTERNAL_FUNCTION_PARAMET if (ret) { if (HT_IS_PACKED(Z_ARRVAL_P(ret))) { if (HT_IS_WITHOUT_HOLES(Z_ARRVAL_P(ret))) { - ZVAL_COPY(return_value, ret); - return; + RETURN_COPY(ret); } } else { - bool copy = 1; + bool copy = true; zend_string *string_key; - ZEND_HASH_FOREACH_STR_KEY(Z_ARRVAL_P(ret), string_key) { + ZEND_HASH_MAP_FOREACH_STR_KEY(Z_ARRVAL_P(ret), string_key) { if (!string_key) { - copy = 0; + copy = false; break; } } ZEND_HASH_FOREACH_END(); if (copy) { - ZVAL_COPY(return_value, ret); - return; + RETURN_COPY(ret); } } } @@ -4317,7 +4220,7 @@ static zend_always_inline void php_array_merge_wrapper(INTERNAL_FUNCTION_PARAMET if (HT_IS_WITHOUT_HOLES(src) && zend_may_modify_arg_in_place(arg)) { dest = src; in_place = true; - ZVAL_ARR(return_value, dest); + RETVAL_ARR(dest); } else { array_init_size(return_value, count); dest = Z_ARRVAL_P(return_value); @@ -4999,7 +4902,7 @@ PHP_FUNCTION(array_unique) return; } - cmp = php_get_data_compare_func_unstable(sort_type, 0); + cmp = php_get_data_compare_func_unstable(sort_type, false); bool in_place = zend_may_modify_arg_in_place(array); if (in_place) { @@ -5032,6 +4935,11 @@ PHP_FUNCTION(array_unique) ZVAL_UNDEF(&arTmp[i].b.val); zend_sort((void *) arTmp, i, sizeof(struct bucketindex), (compare_func_t) cmp, (swap_func_t) array_bucketindex_swap); + + if (UNEXPECTED(EG(exception))) { + goto out; + } + /* go through the sorted array and delete duplicates from the copy */ lastkept = arTmp; for (cmpdata = arTmp + 1; Z_TYPE(cmpdata->b.val) != IS_UNDEF; cmpdata++) { @@ -5051,6 +4959,8 @@ PHP_FUNCTION(array_unique) } } } + +out: pefree(arTmp, GC_FLAGS(Z_ARRVAL_P(array)) & IS_ARRAY_PERSISTENT); if (in_place) { @@ -5129,13 +5039,13 @@ static void php_array_intersect_key(INTERNAL_FUNCTION_PARAMETERS, int data_compa val = Z_REFVAL_P(val); } if (key == NULL) { - ok = 1; + ok = true; for (i = 1; i < argc; i++) { if ((data = zend_hash_index_find(Z_ARRVAL(args[i]), h)) == NULL || (intersect_data_compare_func && intersect_data_compare_func(val, data) != 0) ) { - ok = 0; + ok = false; break; } } @@ -5144,13 +5054,13 @@ static void php_array_intersect_key(INTERNAL_FUNCTION_PARAMETERS, int data_compa zend_hash_index_add_new(Z_ARRVAL_P(return_value), h, val); } } else { - ok = 1; + ok = true; for (i = 1; i < argc; i++) { if ((data = zend_hash_find_known_hash(Z_ARRVAL(args[i]), key)) == NULL || (intersect_data_compare_func && intersect_data_compare_func(val, data) != 0) ) { - ok = 0; + ok = false; break; } } @@ -5525,13 +5435,13 @@ static void php_array_diff_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_ty val = Z_REFVAL_P(val); } if (key == NULL) { - ok = 1; + ok = true; for (i = 1; i < argc; i++) { if ((data = zend_hash_index_find(Z_ARRVAL(args[i]), h)) != NULL && (!diff_data_compare_func || diff_data_compare_func(val, data) == 0) ) { - ok = 0; + ok = false; break; } } @@ -5540,13 +5450,13 @@ static void php_array_diff_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_ty zend_hash_index_add_new(Z_ARRVAL_P(return_value), h, val); } } else { - ok = 1; + ok = true; for (i = 1; i < argc; i++) { if ((data = zend_hash_find_known_hash(Z_ARRVAL(args[i]), key)) != NULL && (!diff_data_compare_func || diff_data_compare_func(val, data) == 0) ) { - ok = 0; + ok = false; break; } } @@ -5879,6 +5789,7 @@ PHP_FUNCTION(array_diff) for (i = 1; i < argc; i++) { if (Z_TYPE(args[i]) != IS_ARRAY) { + zend_tmp_string_release(tmp_search_str); zend_argument_type_error(i + 1, "must be of type array, %s given", zend_zval_value_name(&args[i])); RETURN_THROWS(); } @@ -6051,7 +5962,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 +5978,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 +6030,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 +6047,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 +6128,7 @@ PHP_FUNCTION(array_multisort) efree(indirect); efree(func); efree(arrays); + ARRAYG(multisort_func) = old_multisort_func; } /* }}} */ @@ -6738,11 +6653,11 @@ PHP_FUNCTION(array_all) PHP_FUNCTION(array_map) { zval *arrays = NULL; - int n_arrays = 0; + uint32_t n_arrays = 0; zval result; zend_fcall_info fci; zend_fcall_info_cache fci_cache; - int i; + uint32_t i; uint32_t k, maxlen = 0; ZEND_PARSE_PARAMETERS_START(2, -1) @@ -6784,8 +6699,7 @@ PHP_FUNCTION(array_map) ZEND_IGNORE_VALUE(ret); if (UNEXPECTED(Z_ISUNDEF(result))) { ZEND_HASH_FILL_FINISH(); - zend_array_destroy(output); - RETURN_NULL(); + RETURN_THROWS(); } } else { ZVAL_UNDEF(&result); @@ -6808,8 +6722,7 @@ PHP_FUNCTION(array_map) ZEND_ASSERT(ret == SUCCESS); ZEND_IGNORE_VALUE(ret); if (UNEXPECTED(Z_ISUNDEF(result))) { - zend_array_destroy(output); - RETURN_NULL(); + RETURN_THROWS(); } if (str_key) { _zend_hash_append(output, str_key, &result); @@ -6819,12 +6732,9 @@ PHP_FUNCTION(array_map) } ZEND_HASH_FOREACH_END(); } } else { - uint32_t *array_pos = (HashPosition *)ecalloc(n_arrays, sizeof(HashPosition)); - for (i = 0; i < n_arrays; i++) { if (Z_TYPE(arrays[i]) != IS_ARRAY) { zend_argument_type_error(i + 2, "must be of type array, %s given", zend_zval_value_name(&arrays[i])); - efree(array_pos); RETURN_THROWS(); } if (zend_hash_num_elements(Z_ARRVAL(arrays[i])) > maxlen) { @@ -6835,6 +6745,7 @@ PHP_FUNCTION(array_map) array_init_size(return_value, maxlen); if (!ZEND_FCI_INITIALIZED(fci)) { + uint32_t *array_pos = ecalloc(n_arrays, sizeof(HashPosition)); zval zv; /* We iterate through all the arrays at once. */ @@ -6878,23 +6789,34 @@ PHP_FUNCTION(array_map) zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &result); } + + efree(array_pos); } else { zval *params = (zval *)safe_emalloc(n_arrays, sizeof(zval), 0); + /* Remember next starting point in the array, initialize those as zeros. */ + for (i = 0; i < n_arrays; i++) { + Z_EXTRA(params[i]) = 0; + } + + fci.retval = &result; + fci.param_count = n_arrays; + fci.params = params; + /* We iterate through all the arrays at once. */ for (k = 0; k < maxlen; k++) { for (i = 0; i < n_arrays; i++) { /* If this array still has elements, add the current one to the * parameter list, otherwise use null value. */ - uint32_t pos = array_pos[i]; + uint32_t pos = Z_EXTRA(params[i]); if (HT_IS_PACKED(Z_ARRVAL(arrays[i]))) { while (1) { if (pos >= Z_ARRVAL(arrays[i])->nNumUsed) { ZVAL_NULL(¶ms[i]); break; } else if (Z_TYPE(Z_ARRVAL(arrays[i])->arPacked[pos]) != IS_UNDEF) { - ZVAL_COPY(¶ms[i], &Z_ARRVAL(arrays[i])->arPacked[pos]); - array_pos[i] = pos + 1; + ZVAL_COPY_VALUE(¶ms[i], &Z_ARRVAL(arrays[i])->arPacked[pos]); + Z_EXTRA(params[i]) = pos + 1; break; } pos++; @@ -6905,8 +6827,8 @@ PHP_FUNCTION(array_map) ZVAL_NULL(¶ms[i]); break; } else if (Z_TYPE(Z_ARRVAL(arrays[i])->arData[pos].val) != IS_UNDEF) { - ZVAL_COPY(¶ms[i], &Z_ARRVAL(arrays[i])->arData[pos].val); - array_pos[i] = pos + 1; + ZVAL_COPY_VALUE(¶ms[i], &Z_ARRVAL(arrays[i])->arData[pos].val); + Z_EXTRA(params[i]) = pos + 1; break; } pos++; @@ -6914,26 +6836,13 @@ PHP_FUNCTION(array_map) } } - fci.retval = &result; - fci.param_count = n_arrays; - fci.params = params; - zend_result ret = zend_call_function(&fci, &fci_cache); ZEND_ASSERT(ret == SUCCESS); ZEND_IGNORE_VALUE(ret); if (Z_TYPE(result) == IS_UNDEF) { - efree(array_pos); - zend_array_destroy(Z_ARR_P(return_value)); - for (i = 0; i < n_arrays; i++) { - zval_ptr_dtor(¶ms[i]); - } efree(params); - RETURN_NULL(); - } else { - for (i = 0; i < n_arrays; i++) { - zval_ptr_dtor(¶ms[i]); - } + RETURN_THROWS(); } zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &result); @@ -6941,7 +6850,6 @@ PHP_FUNCTION(array_map) efree(params); } - efree(array_pos); } } /* }}} */ @@ -6965,6 +6873,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: @@ -7016,20 +6925,19 @@ PHP_FUNCTION(array_chunk) if (size > num_in) { if (num_in == 0) { - RETVAL_EMPTY_ARRAY(); - return; + RETURN_EMPTY_ARRAY(); } size = num_in; } array_init_size(return_value, (uint32_t)(((num_in - 1) / size) + 1)); - - ZVAL_UNDEF(&chunk); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(input), num_key, str_key, entry) { /* If new chunk, create and initialize it. */ - if (Z_TYPE(chunk) == IS_UNDEF) { + if (current == 0) { array_init_size(&chunk, (uint32_t)size); + add_next_index_zval(return_value, &chunk); } /* Add entry to the chunk, preserving keys if necessary. */ @@ -7044,18 +6952,10 @@ PHP_FUNCTION(array_chunk) } zval_add_ref(entry); - /* If reached the chunk size, add it to the result array, and reset the - * pointer. */ - if (!(++current % size)) { - add_next_index_zval(return_value, &chunk); - ZVAL_UNDEF(&chunk); + if (++current == size) { + current = 0; } } ZEND_HASH_FOREACH_END(); - - /* Add the final chunk if there is one. */ - if (Z_TYPE(chunk) != IS_UNDEF) { - add_next_index_zval(return_value, &chunk); - } } /* }}} */ diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index ea2f8884bdef6..8b72ffffc8379 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 }; @@ -303,6 +304,7 @@ PHP_MINIT_FUNCTION(basic) /* {{{ */ BASIC_MINIT_SUBMODULE(standard_filters) BASIC_MINIT_SUBMODULE(user_filters) BASIC_MINIT_SUBMODULE(password) + BASIC_MINIT_SUBMODULE(image) #ifdef ZTS BASIC_MINIT_SUBMODULE(localeconv) @@ -376,6 +378,7 @@ PHP_MSHUTDOWN_FUNCTION(basic) /* {{{ */ #endif BASIC_MSHUTDOWN_SUBMODULE(crypt) BASIC_MSHUTDOWN_SUBMODULE(password) + BASIC_MSHUTDOWN_SUBMODULE(image) return SUCCESS; } @@ -558,7 +561,7 @@ PHP_FUNCTION(inet_pton) char buffer[17]; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(address, address_len) + Z_PARAM_PATH(address, address_len) ZEND_PARSE_PARAMETERS_END(); memset(buffer, 0, sizeof(buffer)); @@ -590,7 +593,7 @@ PHP_FUNCTION(ip2long) struct in_addr ip; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(addr, addr_len) + Z_PARAM_PATH(addr, addr_len) ZEND_PARSE_PARAMETERS_END(); if (addr_len == 0 || inet_pton(AF_INET, addr, &ip) != 1) { @@ -1985,10 +1988,8 @@ PHP_FUNCTION(ini_set) /* open basedir check */ if (PG(open_basedir)) { if ( - zend_string_equals_literal(varname, "error_log") - || zend_string_equals_literal(varname, "java.class.path") + zend_string_equals_literal(varname, "java.class.path") || zend_string_equals_literal(varname, "java.home") - || zend_string_equals_literal(varname, "mail.log") || zend_string_equals_literal(varname, "java.library.path") || zend_string_equals_literal(varname, "vpopmail.directory") ) { @@ -2138,8 +2139,8 @@ PHP_FUNCTION(getservbyname) struct servent *serv; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_STR(name) - Z_PARAM_STRING(proto, proto_len) + Z_PARAM_PATH_STR(name) + Z_PARAM_PATH(proto, proto_len) ZEND_PARSE_PARAMETERS_END(); @@ -2182,7 +2183,7 @@ PHP_FUNCTION(getservbyport) ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_LONG(port) - Z_PARAM_STRING(proto, proto_len) + Z_PARAM_PATH(proto, proto_len) ZEND_PARSE_PARAMETERS_END(); serv = getservbyport(htons((unsigned short) port), proto); @@ -2209,7 +2210,7 @@ PHP_FUNCTION(getprotobyname) struct protoent *ent; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(name, name_len) + Z_PARAM_PATH(name, name_len) ZEND_PARSE_PARAMETERS_END(); ent = getprotobyname(name); diff --git a/ext/standard/basic_functions.h b/ext/standard/basic_functions.h index bad6fcf4e645e..8c8c6ba58dfd6 100644 --- a/ext/standard/basic_functions.h +++ b/ext/standard/basic_functions.h @@ -49,7 +49,6 @@ PHP_RSHUTDOWN_FUNCTION(browscap); /* Left for BC (not binary safe!) */ PHPAPI int _php_error_log(int opt_err, const char *message, const char *opt, const char *headers); PHPAPI int _php_error_log_ex(int opt_err, const char *message, size_t message_len, const char *opt, const char *headers); -PHPAPI int php_prefix_varname(zval *result, zend_string *prefix, const char *var_name, size_t var_name_len, bool add_underscore); typedef struct _php_basic_globals { HashTable *user_shutdown_function_names; diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index b7be370bb4777..e27dca069c55b 100644 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -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; @@ -1624,6 +1606,12 @@ function min(mixed $value, mixed ...$values): mixed {} */ function max(mixed $value, mixed ...$values): mixed {} +/** + * @compile-time-eval + * @frameless-function {"arity": 3} + */ +function clamp(mixed $value, mixed $min, mixed $max): mixed {} + function array_walk(array|object &$array, callable $callback, mixed $arg = UNKNOWN): true {} function array_walk_recursive(array|object &$array, callable $callback, mixed $arg = UNKNOWN): true {} @@ -2692,7 +2680,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 {} @@ -3582,6 +3569,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 c77447bd83c63..6f202c01463fd 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: b9958c8f2f643e072ba7c6ee33ad238ea8dd702e */ + * Stub hash: 1a1667a5c59111f096a758d5bb4aa7cf3ec09cfe */ 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) @@ -138,6 +138,12 @@ ZEND_END_ARG_INFO() #define arginfo_max arginfo_min +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_clamp, 0, 3, IS_MIXED, 0) + ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0) + ZEND_ARG_TYPE_INFO(0, min, IS_MIXED, 0) + ZEND_ARG_TYPE_INFO(0, max, IS_MIXED, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_walk, 0, 2, IS_TRUE, 0) ZEND_ARG_TYPE_MASK(1, array, MAY_BE_ARRAY|MAY_BE_OBJECT, NULL) ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0) @@ -2197,6 +2203,12 @@ static const zend_frameless_function_info frameless_function_infos_max[] = { { 0 }, }; +ZEND_FRAMELESS_FUNCTION(clamp, 3); +static const zend_frameless_function_info frameless_function_infos_clamp[] = { + { ZEND_FRAMELESS_FUNCTION_NAME(clamp, 3), 3 }, + { 0 }, +}; + ZEND_FRAMELESS_FUNCTION(in_array, 2); ZEND_FRAMELESS_FUNCTION(in_array, 3); static const zend_frameless_function_info frameless_function_infos_in_array[] = { @@ -2332,6 +2344,7 @@ ZEND_FUNCTION(current); ZEND_FUNCTION(key); ZEND_FUNCTION(min); ZEND_FUNCTION(max); +ZEND_FUNCTION(clamp); ZEND_FUNCTION(array_walk); ZEND_FUNCTION(array_walk_recursive); ZEND_FUNCTION(in_array); @@ -2925,6 +2938,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(key, arginfo_key) ZEND_RAW_FENTRY("min", zif_min, arginfo_min, ZEND_ACC_COMPILE_TIME_EVAL, frameless_function_infos_min, NULL) ZEND_RAW_FENTRY("max", zif_max, arginfo_max, ZEND_ACC_COMPILE_TIME_EVAL, frameless_function_infos_max, NULL) + ZEND_RAW_FENTRY("clamp", zif_clamp, arginfo_clamp, ZEND_ACC_COMPILE_TIME_EVAL, frameless_function_infos_clamp, NULL) ZEND_FE(array_walk, arginfo_array_walk) ZEND_FE(array_walk_recursive, arginfo_array_walk_recursive) ZEND_RAW_FENTRY("in_array", zif_in_array, arginfo_in_array, ZEND_ACC_COMPILE_TIME_EVAL, frameless_function_infos_in_array, NULL) @@ -3431,7 +3445,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) @@ -3645,8 +3659,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); @@ -3896,10 +3911,8 @@ static void register_basic_functions_symbols(int module_number) 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_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 @@ -3910,68 +3923,58 @@ static void register_basic_functions_symbols(int module_number) 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_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_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); - zval attribute_Deprecated_const_ASSERT_ACTIVE_0_arg1; 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_arg1, attribute_Deprecated_const_ASSERT_ACTIVE_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_ASSERT_ACTIVE_0->args[1].value, &attribute_Deprecated_const_ASSERT_ACTIVE_0_arg1); + 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 attribute_Deprecated_const_ASSERT_CALLBACK_0_arg1; - zend_string *attribute_Deprecated_const_ASSERT_CALLBACK_0_arg1_str = zend_string_init("as assert_options() is deprecated", strlen("as assert_options() is deprecated"), 1); - ZVAL_STR(&attribute_Deprecated_const_ASSERT_CALLBACK_0_arg1, attribute_Deprecated_const_ASSERT_CALLBACK_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_ASSERT_CALLBACK_0->args[1].value, &attribute_Deprecated_const_ASSERT_CALLBACK_0_arg1); + 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 attribute_Deprecated_const_ASSERT_BAIL_0_arg1; - zend_string *attribute_Deprecated_const_ASSERT_BAIL_0_arg1_str = zend_string_init("as assert_options() is deprecated", strlen("as assert_options() is deprecated"), 1); - ZVAL_STR(&attribute_Deprecated_const_ASSERT_BAIL_0_arg1, attribute_Deprecated_const_ASSERT_BAIL_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_ASSERT_BAIL_0->args[1].value, &attribute_Deprecated_const_ASSERT_BAIL_0_arg1); + 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 attribute_Deprecated_const_ASSERT_WARNING_0_arg1; - zend_string *attribute_Deprecated_const_ASSERT_WARNING_0_arg1_str = zend_string_init("as assert_options() is deprecated", strlen("as assert_options() is deprecated"), 1); - ZVAL_STR(&attribute_Deprecated_const_ASSERT_WARNING_0_arg1, attribute_Deprecated_const_ASSERT_WARNING_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_ASSERT_WARNING_0->args[1].value, &attribute_Deprecated_const_ASSERT_WARNING_0_arg1); + 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 attribute_Deprecated_const_ASSERT_EXCEPTION_0_arg1; - zend_string *attribute_Deprecated_const_ASSERT_EXCEPTION_0_arg1_str = zend_string_init("as assert_options() is deprecated", strlen("as assert_options() is deprecated"), 1); - ZVAL_STR(&attribute_Deprecated_const_ASSERT_EXCEPTION_0_arg1, attribute_Deprecated_const_ASSERT_EXCEPTION_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_ASSERT_EXCEPTION_0->args[1].value, &attribute_Deprecated_const_ASSERT_EXCEPTION_0_arg1); + 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); } @@ -3982,9 +3985,9 @@ static zend_class_entry *register_class___PHP_Incomplete_Class(void) INIT_CLASS_ENTRY(ce, "__PHP_Incomplete_Class", NULL); class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL|ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES); - zend_string *attribute_name_AllowDynamicProperties_class___PHP_Incomplete_Class_0 = zend_string_init_interned("AllowDynamicProperties", sizeof("AllowDynamicProperties") - 1, 1); + zend_string *attribute_name_AllowDynamicProperties_class___PHP_Incomplete_Class_0 = zend_string_init_interned("AllowDynamicProperties", sizeof("AllowDynamicProperties") - 1, true); zend_add_class_attribute(class_entry, attribute_name_AllowDynamicProperties_class___PHP_Incomplete_Class_0, 0); - zend_string_release(attribute_name_AllowDynamicProperties_class___PHP_Incomplete_Class_0); + zend_string_release_ex(attribute_name_AllowDynamicProperties_class___PHP_Incomplete_Class_0, true); return class_entry; } diff --git a/ext/standard/browscap.c b/ext/standard/browscap.c index 685fe09357d06..5009c7793688c 100644 --- a/ext/standard/browscap.c +++ b/ext/standard/browscap.c @@ -277,7 +277,7 @@ static HashTable *browscap_entry_to_array(browser_data *bdata, browscap_entry *e zval tmp; HashTable *ht = zend_new_array(2 + (entry->parent ? 1 : 0) + (entry->kv_end - entry->kv_start)); - ZVAL_STR(&tmp, browscap_convert_pattern(entry->pattern, 0)); + ZVAL_STR(&tmp, browscap_convert_pattern(entry->pattern, false)); zend_string *key = ZSTR_INIT_LITERAL("browser_name_regex", 0); ZSTR_H(key) = zend_inline_hash_func("browser_name_regex", sizeof("browser_name_regex")-1); zend_hash_add_new(ht, key, &tmp); @@ -485,7 +485,7 @@ PHP_INI_MH(OnChangeBrowscap) } else if (stage == PHP_INI_STAGE_ACTIVATE) { browser_data *bdata = &BROWSCAP_G(activation_bdata); if (bdata->filename[0] != '\0') { - browscap_bdata_dtor(bdata, 0); + browscap_bdata_dtor(bdata, false); } if (VCWD_REALPATH(ZSTR_VAL(new_value), bdata->filename) == NULL) { return FAILURE; @@ -520,7 +520,7 @@ PHP_RSHUTDOWN_FUNCTION(browscap) /* {{{ */ { browser_data *bdata = &BROWSCAP_G(activation_bdata); if (bdata->filename[0] != '\0') { - browscap_bdata_dtor(bdata, 0); + browscap_bdata_dtor(bdata, false); } return SUCCESS; @@ -529,7 +529,7 @@ PHP_RSHUTDOWN_FUNCTION(browscap) /* {{{ */ PHP_MSHUTDOWN_FUNCTION(browscap) /* {{{ */ { - browscap_bdata_dtor(&global_bdata, 1); + browscap_bdata_dtor(&global_bdata, true); return SUCCESS; } diff --git a/ext/standard/crypt_sha256.c b/ext/standard/crypt_sha256.c index 5bc3e93fe15fb..2673dcf2b08e8 100644 --- a/ext/standard/crypt_sha256.c +++ b/ext/standard/crypt_sha256.c @@ -338,7 +338,7 @@ char * php_sha256_crypt_r(const char *key, const char *salt, char *buffer, int b char *s_bytes; /* Default number of rounds. */ size_t rounds = ROUNDS_DEFAULT; - bool rounds_custom = 0; + bool rounds_custom = false; /* Find beginning of salt string. The prefix should normally always be present. Just in case it is not. */ @@ -358,7 +358,7 @@ char * php_sha256_crypt_r(const char *key, const char *salt, char *buffer, int b } rounds = srounds; - rounds_custom = 1; + rounds_custom = true; } } diff --git a/ext/standard/crypt_sha512.c b/ext/standard/crypt_sha512.c index e6410fb916228..e8cedaa55c205 100644 --- a/ext/standard/crypt_sha512.c +++ b/ext/standard/crypt_sha512.c @@ -375,7 +375,7 @@ php_sha512_crypt_r(const char *key, const char *salt, char *buffer, int buflen) char *s_bytes; /* Default number of rounds. */ size_t rounds = ROUNDS_DEFAULT; - bool rounds_custom = 0; + bool rounds_custom = false; /* Find beginning of salt string. The prefix should normally always be present. Just in case it is not. */ @@ -396,7 +396,7 @@ php_sha512_crypt_r(const char *key, const char *salt, char *buffer, int buflen) } rounds = srounds; - rounds_custom = 1; + rounds_custom = true; } } diff --git a/ext/standard/dir.c b/ext/standard/dir.c index cced88e4ac8a5..7c1f8efe68875 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); @@ -557,11 +558,15 @@ PHP_FUNCTION(scandir) RETURN_FALSE; } - array_init(return_value); + array_init_size(return_value, n); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); - for (i = 0; i < n; i++) { - add_next_index_str(return_value, namelist[i]); - } + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { + for (i = 0; i < n; i++) { + ZEND_HASH_FILL_SET_STR(namelist[i]); + ZEND_HASH_FILL_NEXT(); + } + } ZEND_HASH_FILL_END(); if (n) { efree(namelist); diff --git a/ext/standard/dir_arginfo.h b/ext/standard/dir_arginfo.h index 703088d1eb0d5..d4cfc19556353 100644 --- a/ext/standard/dir_arginfo.h +++ b/ext/standard/dir_arginfo.h @@ -66,9 +66,9 @@ static zend_class_entry *register_class_Directory(void) zval property_handle_default_value; ZVAL_UNDEF(&property_handle_default_value); - zend_string *property_handle_name = zend_string_init("handle", sizeof("handle") - 1, 1); + zend_string *property_handle_name = zend_string_init("handle", sizeof("handle") - 1, true); zend_declare_typed_property(class_entry, property_handle_name, &property_handle_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ANY)); - zend_string_release(property_handle_name); + zend_string_release_ex(property_handle_name, true); return class_entry; } diff --git a/ext/standard/dns.c b/ext/standard/dns.c index bd5720210fdaf..a574d8dd9aeb8 100644 --- a/ext/standard/dns.c +++ b/ext/standard/dns.c @@ -382,7 +382,7 @@ PHP_FUNCTION(dns_check_record) #endif ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_STRING(hostname, hostname_len) + Z_PARAM_PATH(hostname, hostname_len) Z_PARAM_OPTIONAL Z_PARAM_STR(rectype) ZEND_PARSE_PARAMETERS_END(); @@ -829,7 +829,7 @@ PHP_FUNCTION(dns_get_record) bool raw = 0; ZEND_PARSE_PARAMETERS_START(1, 5) - Z_PARAM_STRING(hostname, hostname_len) + Z_PARAM_PATH(hostname, hostname_len) Z_PARAM_OPTIONAL Z_PARAM_LONG(type_param) Z_PARAM_ZVAL(authns) @@ -1067,7 +1067,7 @@ PHP_FUNCTION(dns_get_mx) #endif ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_STRING(hostname, hostname_len) + Z_PARAM_PATH(hostname, hostname_len) Z_PARAM_ZVAL(mx_list) Z_PARAM_OPTIONAL Z_PARAM_ZVAL(weight_list) diff --git a/ext/standard/dns_win32.c b/ext/standard/dns_win32.c index 26c6487902e1a..1f7c6c0146e47 100644 --- a/ext/standard/dns_win32.c +++ b/ext/standard/dns_win32.c @@ -32,7 +32,7 @@ PHP_FUNCTION(dns_get_mx) /* {{{ */ DNS_STATUS status; /* Return value of DnsQuery_A() function */ PDNS_RECORD pResult, pRec; /* Pointer to DNS_RECORD structure */ - if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz|z", &hostname, &hostname_len, &mx_list, &weight_list) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "pz|z", &hostname, &hostname_len, &mx_list, &weight_list) == FAILURE) { RETURN_THROWS(); } @@ -86,7 +86,7 @@ PHP_FUNCTION(dns_check_record) DNS_STATUS status; /* Return value of DnsQuery_A() function */ PDNS_RECORD pResult; /* Pointer to DNS_RECORD structure */ - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|S", &hostname, &hostname_len, &rectype) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|S", &hostname, &hostname_len, &rectype) == FAILURE) { RETURN_THROWS(); } @@ -341,9 +341,9 @@ PHP_FUNCTION(dns_get_record) zend_long type_param = PHP_DNS_ANY; zval *authns = NULL, *addtl = NULL; int type, type_to_fetch, first_query = 1, store_results = 1; - bool raw = 0; + bool raw = false; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|lz!z!b", + if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|lz!z!b", &hostname, &hostname_len, &type_param, &authns, &addtl, &raw) == FAILURE) { RETURN_THROWS(); } 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 ab6ed4fbadd2d..bd6ee252875e5 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -663,11 +663,10 @@ PHP_FUNCTION(file) p = e; goto parse_eol; } - } - if (target_buf) { - zend_string_free(target_buf); + zend_string_efree(target_buf); } + php_stream_close(stream); } /* }}} */ @@ -961,7 +960,8 @@ PHP_FUNCTION(fscanf) efree(buf); if (SCAN_ERROR_WRONG_PARAM_COUNT == result) { - WRONG_PARAM_COUNT; + zend_wrong_param_count(); + RETURN_THROWS(); } } /* }}} */ @@ -1554,7 +1554,6 @@ PHPAPI PHP_FUNCTION(fread) str = php_stream_read_to_str(stream, len); if (!str) { - zval_ptr_dtor_str(return_value); RETURN_FALSE; } diff --git a/ext/standard/file.stub.php b/ext/standard/file.stub.php index 91d2ea08708ec..5e12c43f397c7 100644 --- a/ext/standard/file.stub.php +++ b/ext/standard/file.stub.php @@ -444,14 +444,9 @@ */ const FILE_NO_DEFAULT_CONTEXT = UNKNOWN; -/** - * @var int - */ #[\Deprecated(since: '8.1', message: 'as the constant has no effect')] const FILE_TEXT = 0; -/** - * @var int - */ + #[\Deprecated(since: '8.1', message: 'as the constant has no effect')] const FILE_BINARY = 0; diff --git a/ext/standard/file_arginfo.h b/ext/standard/file_arginfo.h index 471c9a07cb4c0..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: dde0b40909dbadb565d898338834de7fa689c5e9 */ + * Stub hash: c394e14cd32587ce9ad0503e21c6c4cf5b301697 */ static void register_file_symbols(int module_number) { @@ -123,18 +123,13 @@ static void register_file_symbols(int module_number) 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); - zval attribute_Deprecated_const_FILE_TEXT_0_arg1; 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_arg1, attribute_Deprecated_const_FILE_TEXT_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_FILE_TEXT_0->args[1].value, &attribute_Deprecated_const_FILE_TEXT_0_arg1); + 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 attribute_Deprecated_const_FILE_BINARY_0_arg1; - zend_string *attribute_Deprecated_const_FILE_BINARY_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_BINARY_0_arg1, attribute_Deprecated_const_FILE_BINARY_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_FILE_BINARY_0->args[1].value, &attribute_Deprecated_const_FILE_BINARY_0_arg1); + 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/formatted_print.c b/ext/standard/formatted_print.c index b2c287c02900c..b0fbfcc89099f 100644 --- a/ext/standard/formatted_print.c +++ b/ext/standard/formatted_print.c @@ -103,7 +103,7 @@ php_sprintf_appendstring(zend_string **buffer, size_t *pos, char *add, if (req_size > ZSTR_LEN(*buffer)) { size_t size = ZSTR_LEN(*buffer); while (req_size > size) { - if (size > ZEND_SIZE_MAX/2) { + if (size > SIZE_MAX/2) { zend_error_noreturn(E_ERROR, "Field width %zd is too long", req_size); } size <<= 1; @@ -298,9 +298,9 @@ php_sprintf_appenddouble(zend_string **buffer, size_t *pos, char exp_char = fmt == 'G' || fmt == 'H' ? 'E' : 'e'; /* We use &num_buf[ 1 ], so that we have room for the sign. */ s = zend_gcvt(number, precision, decimal_point, exp_char, &num_buf[1]); - is_negative = 0; + is_negative = false; if (*s == '-') { - is_negative = 1; + is_negative = true; s = &num_buf[1]; } else if (always_sign) { num_buf[0] = '+'; diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c index 51b7b311a9540..d1bb3aeeccd68 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; @@ -147,7 +155,7 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char if (resource->port == 0) resource->port = 21; - transport_len = (int)spprintf(&transport, 0, "tcp://%s:%d", ZSTR_VAL(resource->host), resource->port); + transport_len = (int)spprintf(&transport, 0, "tcp://%s:" ZEND_LONG_FMT, ZSTR_VAL(resource->host), resource->port); stream = php_stream_xport_create(transport, transport_len, REPORT_ERRORS, STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, NULL, NULL, context, NULL, NULL); efree(transport); if (stream == NULL) { @@ -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; @@ -413,7 +421,7 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, const char *pa php_stream *reuseid=NULL; size_t file_size = 0; zval *tmpzval; - bool allow_overwrite = 0; + bool allow_overwrite = false; int8_t read_write = 0; char *transport; int transport_len; @@ -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..76ba89dc01713 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? */ @@ -126,13 +131,9 @@ PHPAPI zend_result php_setcookie(zend_string *name, zend_string *value, time_t e * so in order to force cookies to be deleted, even on MSIE, we * pick an expiry date in the past */ - dt = 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, 1, 0); smart_str_appends(&buf, "Set-Cookie: "); smart_str_append(&buf, name); - smart_str_appends(&buf, "=deleted; expires="); - smart_str_append(&buf, dt); - smart_str_appends(&buf, "; Max-Age=0"); - zend_string_free(dt); + smart_str_appends(&buf, "=deleted; expires=Thu, 01 Jan 1970 00:00:01 GMT; Max-Age=0"); } else { smart_str_appends(&buf, "Set-Cookie: "); smart_str_append(&buf, name); @@ -182,6 +183,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 +196,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; @@ -209,11 +213,13 @@ static zend_result php_head_parse_cookie_options_array(HashTable *options, zend_ } else if (zend_string_equals_literal_ci(key, "domain")) { *domain = zval_get_string(value); } else if (zend_string_equals_literal_ci(key, "secure")) { - *secure = zval_is_true(value); + *secure = zend_is_true(value); } else if (zend_string_equals_literal_ci(key, "httponly")) { - *httponly = zval_is_true(value); + *httponly = zend_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 = zend_is_true(value); } else { zend_value_error("%s(): option \"%s\" is invalid", get_active_function_name(), ZSTR_VAL(key)); return FAILURE; @@ -227,7 +233,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 +254,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; @@ -375,6 +381,14 @@ PHP_FUNCTION(http_response_code) } RETURN_FALSE; } + + if (SG(sapi_headers).http_status_line) { + php_error_docref(NULL, E_WARNING, "Calling http_response_code() after header('HTTP/...') has no effect"); + // If it is decided that this should have effect in the future, replace warning with + // efree(SG(sapi_headers).http_status_line); + // SG(sapi_headers).http_status_line = NULL; + } + zend_long old_response_code; old_response_code = SG(sapi_headers).http_response_code; 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..652531bd3ed4f 100644 --- a/ext/standard/hrtime.c +++ b/ext/standard/hrtime.c @@ -31,9 +31,9 @@ } while (0) #endif #define PHP_RETURN_HRTIME(t) do { \ - char _a[ZEND_LTOA_BUF_LEN]; \ + char _a[65]; \ double _d; \ - HRTIME_U64A(t, _a, ZEND_LTOA_BUF_LEN); \ + HRTIME_U64A(t, _a, sizeof(_a)); \ _d = zend_strtod(_a, NULL); \ RETURN_DOUBLE(_d); \ } while (0) @@ -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..eaba9ddffc1d0 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)); } /* }}} */ @@ -981,7 +1017,7 @@ PHPAPI zend_string *php_unescape_html_entities(zend_string *str, int all, int fl } if (all) { - charset = determine_charset(hint_charset, /* quiet */ 0); + charset = determine_charset(hint_charset, /* quiet */ false); } else { charset = cs_8859_1; /* charset shouldn't matter, use ISO-8859-1 for performance */ } @@ -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; } @@ -1007,7 +1043,7 @@ PHPAPI zend_string *php_unescape_html_entities(zend_string *str, int all, int fl PHPAPI zend_string *php_escape_html_entities(const unsigned char *old, size_t oldlen, int all, int flags, const char *hint_charset) { - return php_escape_html_entities_ex(old, oldlen, all, flags, hint_charset, 1, /* quiet */ 0); + return php_escape_html_entities_ex(old, oldlen, all, flags, hint_charset, true, /* quiet */ false); } /* {{{ find_entity_for_char */ @@ -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.c b/ext/standard/http.c index ae6f668e0cb8f..47443f74ffe98 100644 --- a/ext/standard/http.c +++ b/ext/standard/http.c @@ -83,6 +83,15 @@ static void php_url_encode_scalar(zval *scalar, smart_str *form_str, } } +static zend_always_inline bool php_url_check_stack_limit(void) +{ +#ifdef ZEND_CHECK_STACK_LIMIT + return zend_call_stack_overflowed(EG(stack_limit)); +#else + return false; +#endif +} + /* {{{ php_url_encode_hash */ PHPAPI void php_url_encode_hash_ex(HashTable *ht, smart_str *formstr, const char *num_prefix, size_t num_prefix_len, @@ -101,6 +110,12 @@ PHPAPI void php_url_encode_hash_ex(HashTable *ht, smart_str *formstr, return; } + /* Very deeply structured data could trigger a stack overflow, even without recursion. */ + if (UNEXPECTED(php_url_check_stack_limit())) { + zend_throw_error(NULL, "Maximum call stack size reached."); + return; + } + if (!arg_sep) { arg_sep = PG(arg_separator).output; if (ZSTR_LEN(arg_sep) == 0) { @@ -109,14 +124,14 @@ PHPAPI void php_url_encode_hash_ex(HashTable *ht, smart_str *formstr, } ZEND_HASH_FOREACH_KEY_VAL(ht, idx, key, zdata) { - bool is_dynamic = 1; + bool is_dynamic = true; if (Z_TYPE_P(zdata) == IS_INDIRECT) { zdata = Z_INDIRECT_P(zdata); if (Z_ISUNDEF_P(zdata)) { continue; } - is_dynamic = 0; + is_dynamic = false; } /* handling for private & protected object properties */ diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index 9fefe153622fc..da150381f43f3 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 @@ -109,11 +111,11 @@ static bool check_has_header(const char *headers, const char *header) { const char *s = headers; while ((s = strstr(s, header))) { if (s == headers || (*(s-1) == '\n' && *(s-2) == '\r')) { - return 1; + return true; } s++; } - return 0; + return false; } static zend_result php_stream_handle_proxy_authorization_header(const char *s, smart_str *header) @@ -157,7 +159,7 @@ static void php_stream_http_response_header_info_init( php_stream_http_response_header_info *header_info) { memset(header_info, 0, sizeof(php_stream_http_response_header_info)); - header_info->follow_location = 1; + header_info->follow_location = true; } /* Trim white spaces from response header line and update its length */ @@ -274,14 +276,14 @@ static zend_string *php_stream_http_response_headers_parse(php_stream_wrapper *w if (!strncasecmp(last_header_line, "Location:", sizeof("Location:")-1)) { /* Check if the location should be followed. */ if (context && (tmpzval = php_stream_context_get_option(context, "http", "follow_location")) != NULL) { - header_info->follow_location = zval_is_true(tmpzval); + header_info->follow_location = zend_is_true(tmpzval); } else if (!((response_code >= 300 && response_code < 304) || 307 == response_code || 308 == response_code)) { /* The redirection should not be automatic if follow_location is not set and * response_code not in (300, 301, 302, 303 and 307) * see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.1 * RFC 7238 defines 308: http://tools.ietf.org/html/rfc7238 */ - header_info->follow_location = 0; + header_info->follow_location = false; } size_t last_header_value_len = strlen(last_header_value); if (last_header_value_len > HTTP_HEADER_MAX_LOCATION_SIZE) { @@ -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; } @@ -439,13 +446,13 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, use_proxy = 1; transport_string = zend_string_copy(Z_STR_P(tmpzval)); } else { - transport_string = zend_strpprintf(0, "%s://%s:%d", use_ssl ? "ssl" : "tcp", ZSTR_VAL(resource->host), resource->port); + transport_string = zend_strpprintf(0, "%s://%s:" ZEND_LONG_FMT, use_ssl ? "ssl" : "tcp", ZSTR_VAL(resource->host), resource->port); } } 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 @@ -596,7 +603,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, redirect_max = (int)zval_get_long(tmpzval); } - custom_request_method = 0; + custom_request_method = false; if (context && (tmpzval = php_stream_context_get_option(context, "http", "method")) != NULL) { if (Z_TYPE_P(tmpzval) == IS_STRING && Z_STRLEN_P(tmpzval) > 0) { /* As per the RFC, automatically redirected requests MUST NOT use other methods than @@ -605,7 +612,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, || zend_string_equals_literal(Z_STR_P(tmpzval), "GET") || zend_string_equals_literal(Z_STR_P(tmpzval), "HEAD") ) { - custom_request_method = 1; + custom_request_method = true; smart_str_append(&req_buf, Z_STR_P(tmpzval)); smart_str_appendc(&req_buf, ' '); } @@ -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 */ @@ -1082,7 +1083,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, header_info.location = NULL; } if ((use_ssl && resource->port != 443) || (!use_ssl && resource->port != 80)) { - spprintf(&new_path, 0, "%s://%s:%d%s", ZSTR_VAL(resource->scheme), + spprintf(&new_path, 0, "%s://%s:" ZEND_LONG_FMT "%s", ZSTR_VAL(resource->scheme), ZSTR_VAL(resource->host), resource->port, loc_path); } else { spprintf(&new_path, 0, "%s://%s%s", ZSTR_VAL(resource->scheme), @@ -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..08cf8983d029c 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]; @@ -408,6 +406,7 @@ static size_t php_read_stream_all_chunks(php_stream *stream, char *buffer, size_ if (read_now < stream->chunk_size && read_total != length) { return 0; } + buffer += read_now; } while (read_total < length); return read_total; @@ -448,9 +447,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 +472,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 +575,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 +598,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 +646,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 +772,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 +840,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 +852,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 +888,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 +913,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 +974,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 +988,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 +1035,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 +1047,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 +1070,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 +1097,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 +1120,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 +1182,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 +1199,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 +1209,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 +1249,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 +1273,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 +1342,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) { @@ -1427,6 +1440,12 @@ PHPAPI int php_getimagetype(php_stream *stream, const char *input, char *filetyp return IMAGE_FILETYPE_AVIF; } + /* See GH-20201: this needs to be after avif checks to avoid identifying avif as heif. */ + 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; + } + /* AFTER ALL ABOVE FAILED */ if (php_get_wbmp(stream, NULL, 1)) { return IMAGE_FILETYPE_WBMP; @@ -1441,6 +1460,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 +1476,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 +1502,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 +1545,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 +1581,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 +1616,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 +1656,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/iptc.c b/ext/standard/iptc.c index 44dd33bab10ac..5078c0813ccb8 100644 --- a/ext/standard/iptc.c +++ b/ext/standard/iptc.c @@ -308,7 +308,6 @@ PHP_FUNCTION(iptcparse) unsigned char *buffer, recnum, dataset; char *str, key[16]; size_t str_len; - zval values, *element; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_STRING(str, str_len) @@ -357,10 +356,9 @@ PHP_FUNCTION(iptcparse) array_init(return_value); } - if ((element = zend_hash_str_find(Z_ARRVAL_P(return_value), key, strlen(key))) == NULL) { - array_init(&values); - - element = zend_hash_str_update(Z_ARRVAL_P(return_value), key, strlen(key), &values); + zval *element = zend_hash_str_lookup(Z_ARRVAL_P(return_value), key, strlen(key)); + if (Z_ISNULL_P(element)) { + array_init(element); } add_next_index_stringl(element, (char *) buffer+inx, len); diff --git a/ext/standard/mail.c b/ext/standard/mail.c index 41e2a02078e78..8c8b4e6717e0b 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,45 @@ 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; + + if (msg_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/math.c b/ext/standard/math.c index 142d473864f75..95384c06588ac 100644 --- a/ext/standard/math.c +++ b/ext/standard/math.c @@ -389,6 +389,62 @@ PHP_FUNCTION(round) } /* }}} */ +/* Return the given value if in range of min and max */ +static void php_math_clamp(zval *return_value, zval *value, zval *min, zval *max) +{ + if (Z_TYPE_P(min) == IS_DOUBLE && UNEXPECTED(zend_isnan(Z_DVAL_P(min)))) { + zend_argument_value_error(2, "must not be NAN"); + RETURN_THROWS(); + } + + if (Z_TYPE_P(max) == IS_DOUBLE && UNEXPECTED(zend_isnan(Z_DVAL_P(max)))) { + zend_argument_value_error(3, "must not be NAN"); + RETURN_THROWS(); + } + + if (zend_compare(max, min) == -1) { + zend_argument_value_error(2, "must be smaller than or equal to argument #3 ($max)"); + RETURN_THROWS(); + } + + if (zend_compare(max, value) == -1) { + RETURN_COPY(max); + } + + if (zend_compare(value, min) == -1) { + RETURN_COPY(min); + } + + RETURN_COPY(value); +} + +/* {{{ Return the given value if in range of min and max */ +PHP_FUNCTION(clamp) +{ + zval *zvalue, *zmin, *zmax; + + ZEND_PARSE_PARAMETERS_START(3, 3) + Z_PARAM_ZVAL(zvalue) + Z_PARAM_ZVAL(zmin) + Z_PARAM_ZVAL(zmax) + ZEND_PARSE_PARAMETERS_END(); + + php_math_clamp(return_value, zvalue, zmin, zmax); +} +/* }}} */ + +/* {{{ Return the given value if in range of min and max */ +ZEND_FRAMELESS_FUNCTION(clamp, 3) +{ + zval *zvalue, *zmin, *zmax; + Z_FLF_PARAM_ZVAL(1, zvalue); + Z_FLF_PARAM_ZVAL(2, zmin); + Z_FLF_PARAM_ZVAL(3, zmax); + + php_math_clamp(return_value, zvalue, zmin, zmax); +} +/* }}} */ + /* {{{ Returns the sine of the number in radians */ PHP_FUNCTION(sin) { diff --git a/ext/standard/password.c b/ext/standard/password.c index 1e647bb301c3b..a8aab315657c0 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; } @@ -140,7 +140,7 @@ static bool php_password_bcrypt_needs_rehash(const zend_string *hash, zend_array if (!php_password_bcrypt_valid(hash)) { /* Should never get called this way. */ - return 1; + return true; } sscanf(ZSTR_VAL(hash), "$2y$" ZEND_LONG_FMT "$", &old_cost); @@ -156,12 +156,12 @@ static bool php_password_bcrypt_verify(const zend_string *password, const zend_s zend_string *ret = php_crypt(ZSTR_VAL(password), (int)ZSTR_LEN(password), ZSTR_VAL(hash), (int)ZSTR_LEN(hash), 1); if (!ret) { - return 0; + return false; } if (ZSTR_LEN(hash) < 13) { zend_string_free(ret); - return 0; + return false; } /* We're using this method instead of == in order to provide 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_smart_string.h b/ext/standard/php_smart_string.h deleted file mode 100644 index 0013775d18f83..0000000000000 --- a/ext/standard/php_smart_string.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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. | - +----------------------------------------------------------------------+ - | Author: Sascha Schumann | - | Xinchen Hui | - +----------------------------------------------------------------------+ - */ - -/* Header moved to Zend. This file is retained for BC. */ -#include "zend_smart_string.h" diff --git a/ext/standard/php_smart_string_public.h b/ext/standard/php_smart_string_public.h deleted file mode 100644 index 264723e28e1b2..0000000000000 --- a/ext/standard/php_smart_string_public.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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. | - +----------------------------------------------------------------------+ - | Author: Sascha Schumann | - | Xinchen Hui | - +----------------------------------------------------------------------+ - */ - -/* Header moved to Zend. This file is retained for BC. */ -#include "zend_smart_string_public.h" diff --git a/ext/standard/php_string.h b/ext/standard/php_string.h index 51c537de6e628..ef62329ba8eda 100644 --- a/ext/standard/php_string.h +++ b/ext/standard/php_string.h @@ -29,9 +29,9 @@ PHP_MINIT_FUNCTION(string_intrin); #endif #define strnatcmp(a, b) \ - strnatcmp_ex(a, strlen(a), b, strlen(b), 0) + strnatcmp_ex(a, strlen(a), b, strlen(b), false) #define strnatcasecmp(a, b) \ - strnatcmp_ex(a, strlen(a), b, strlen(b), 1) + strnatcmp_ex(a, strlen(a), b, strlen(b), true) PHPAPI int strnatcmp_ex(char const *a, size_t a_len, char const *b, size_t b_len, bool is_case_insensitive); PHPAPI struct lconv *localeconv_r(struct lconv *out); PHPAPI char *php_strtr(char *str, size_t len, const char *str_from, const char *str_to, size_t trlen); diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c index 06a3f916a849c..55f4dd4849587 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,8 +502,8 @@ 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) { - zend_string *str = zval_get_string(zv); +static zend_string *get_valid_arg_string(zval *zv, uint32_t elem_num) { + zend_string *str = zval_try_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); @@ -647,7 +643,7 @@ static zend_string *create_win_command_from_args(HashTable *args) append_win_escaped_arg(&str, arg_str, !is_prog_name && is_cmd_execution); - is_prog_name = 0; + is_prog_name = false; zend_string_release(arg_str); } ZEND_HASH_FOREACH_END(); smart_str_0(&str); @@ -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 2e38965232c74..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; @@ -869,22 +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); - zend_call_known_fcc(context->notifier->fcc, NULL, 6, zvs, NULL); + 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) { - ZEND_ASSERT(notifier); - ZEND_ASSERT(notifier->fcc); - ZEND_ASSERT(notifier->fcc->function_handler); - zend_fcc_dtor(notifier->fcc); - efree(notifier->fcc); - notifier->fcc = NULL; + 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; @@ -908,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; @@ -931,7 +913,7 @@ static zend_result parse_context_params(php_stream_context *context, HashTable * context->notifier = php_stream_notification_alloc(); context->notifier->func = user_space_stream_notifier; - context->notifier->fcc = fcc; + context->notifier->ptr = fcc; context->notifier->dtor = user_space_stream_notifier_dtor; } if (NULL != (tmp = zend_hash_str_find(params, "options", sizeof("options")-1))) { @@ -1128,10 +1110,10 @@ PHP_FUNCTION(stream_context_get_params) } array_init(return_value); - if (context->notifier && context->notifier->fcc) { - ZEND_ASSERT(context->notifier->func == user_space_stream_notifier); + 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(context->notifier->fcc, &fn); + zend_get_callable_zval_from_fcc(fcc, &fn); add_assoc_zval_ex(return_value, ZEND_STRL("notification"), &fn); } Z_TRY_ADDREF(context->options); @@ -1220,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; @@ -1228,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) @@ -1259,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); } } @@ -1276,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); } } @@ -1380,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)); } /* }}} */ @@ -1425,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) */ /* }}} */ @@ -1605,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); } /* }}} */ @@ -1622,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. */ @@ -1653,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 } @@ -1707,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 4bc56f550fe1b..0b7d5be1a2576 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); @@ -1344,15 +1348,15 @@ static bool _is_basename_start(const char *start, const char *pos) && *(pos-1) != '/' && *(pos-1) != '\\') { if (pos - start == 1) { - return 1; + return true; } else if (*(pos-2) == '/' || *(pos-2) == '\\') { - return 1; + return true; } else if (*(pos-2) == ':' && _is_basename_start(start, pos - 2)) { - return 1; + return true; } } - return 0; + return false; } #endif @@ -2105,13 +2109,11 @@ PHP_FUNCTION(strripos) needle_dup = zend_string_tolower(needle); if ((found = (char *)zend_memnrstr(p, ZSTR_VAL(needle_dup), ZSTR_LEN(needle_dup), e))) { RETVAL_LONG(found - ZSTR_VAL(haystack_dup)); - zend_string_release_ex(needle_dup, 0); - zend_string_release_ex(haystack_dup, 0); } else { - zend_string_release_ex(needle_dup, 0); - zend_string_release_ex(haystack_dup, 0); - RETURN_FALSE; + RETVAL_FALSE; } + zend_string_release_ex(needle_dup, false); + zend_string_release_ex(haystack_dup, false); } /* }}} */ @@ -2651,6 +2653,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 +2676,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); } @@ -2953,7 +2970,7 @@ static void php_strtr_array_ex(zval *return_value, zend_string *input, HashTable len = ZSTR_LEN(key_used); if (UNEXPECTED(len > slen)) { /* skip long patterns */ - zend_string_release(key_used); + zend_string_release_ex(key_used, false); continue; } if (len > maxlen) { @@ -4938,7 +4955,7 @@ PHP_FUNCTION(setlocale) 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], true, i + 2))) { - zend_wrong_parameter_type_error(i + 2, Z_EXPECTED_ARRAY_OR_STRING, &args[i]); + zend_wrong_parameter_type_error(i + 2, Z_EXPECTED_ARRAY_OR_STRING_OR_NULL, &args[i]); goto out; } } @@ -5017,11 +5034,11 @@ static bool php_tag_find(char *tag, size_t len, const char *set) { char c, *n; const char *t; int state = 0; - bool done = 0; + bool done = false; char *norm; if (len == 0) { - return 0; + return false; } norm = emalloc(len+1); @@ -5040,7 +5057,7 @@ static bool php_tag_find(char *tag, size_t len, const char *set) { *(n++) = c; break; case '>': - done =1; + done = true; break; default: if (!isspace((int)c)) { @@ -5052,7 +5069,7 @@ static bool php_tag_find(char *tag, size_t len, const char *set) { } } else { if (state == 1) - done=1; + done = true; } break; } @@ -5061,9 +5078,9 @@ static bool php_tag_find(char *tag, size_t len, const char *set) { *(n++) = '>'; *n = '\0'; if (strstr(set, norm)) { - done=1; + done = true; } else { - done=0; + done = false; } efree(norm); return done; @@ -5072,7 +5089,7 @@ static bool php_tag_find(char *tag, size_t len, const char *set) { PHPAPI size_t php_strip_tags(char *rbuf, size_t len, const char *allow, size_t allow_len) /* {{{ */ { - return php_strip_tags_ex(rbuf, len, allow, allow_len, 0); + return php_strip_tags_ex(rbuf, len, allow, allow_len, false); } /* }}} */ @@ -5737,6 +5754,27 @@ PHP_FUNCTION(substr_count) } /* }}} */ +static void php_str_pad_fill(zend_string *result, size_t pad_chars, const char *pad_str, size_t pad_str_len) { + char *p = ZSTR_VAL(result) + ZSTR_LEN(result); + + if (pad_str_len == 1) { + memset(p, pad_str[0], pad_chars); + ZSTR_LEN(result) += pad_chars; + return; + } + + const char *end = p + pad_chars; + while (p + pad_str_len <= end) { + p = zend_mempcpy(p, pad_str, pad_str_len); + } + + if (p < end) { + memcpy(p, pad_str, end - p); + } + + ZSTR_LEN(result) += pad_chars; +} + /* {{{ Returns input string padded on the left or right to specified length with pad_string */ PHP_FUNCTION(str_pad) { @@ -5749,7 +5787,7 @@ PHP_FUNCTION(str_pad) char *pad_str = " "; /* Pointer to padding string */ size_t pad_str_len = 1; zend_long pad_type_val = PHP_STR_PAD_RIGHT; /* The padding type value */ - size_t i, left_pad=0, right_pad=0; + size_t left_pad=0, right_pad=0; zend_string *result = NULL; /* Resulting string */ ZEND_PARSE_PARAMETERS_START(2, 4) @@ -5799,16 +5837,18 @@ PHP_FUNCTION(str_pad) } /* First we pad on the left. */ - for (i = 0; i < left_pad; i++) - ZSTR_VAL(result)[ZSTR_LEN(result)++] = pad_str[i % pad_str_len]; + if (left_pad > 0) { + php_str_pad_fill(result, left_pad, pad_str, pad_str_len); + } /* Then we copy the input string. */ memcpy(ZSTR_VAL(result) + ZSTR_LEN(result), ZSTR_VAL(input), ZSTR_LEN(input)); ZSTR_LEN(result) += ZSTR_LEN(input); /* Finally, we pad on the right. */ - for (i = 0; i < right_pad; i++) - ZSTR_VAL(result)[ZSTR_LEN(result)++] = pad_str[i % pad_str_len]; + if (right_pad > 0) { + php_str_pad_fill(result, right_pad, pad_str, pad_str_len); + } ZSTR_VAL(result)[ZSTR_LEN(result)] = '\0'; @@ -5833,7 +5873,8 @@ PHP_FUNCTION(sscanf) result = php_sscanf_internal(str, format, num_args, args, 0, return_value); if (SCAN_ERROR_WRONG_PARAM_COUNT == result) { - WRONG_PARAM_COUNT; + zend_wrong_param_count(); + RETURN_THROWS(); } } /* }}} */ @@ -6112,23 +6153,31 @@ PHP_FUNCTION(str_split) } array_init_size(return_value, 1); - add_next_index_stringl(return_value, ZSTR_VAL(str), ZSTR_LEN(str)); + GC_TRY_ADDREF(str); + add_next_index_str(return_value, str); return; } array_init_size(return_value, (uint32_t)(((ZSTR_LEN(str) - 1) / split_length) + 1)); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); n_reg_segments = ZSTR_LEN(str) / split_length; p = ZSTR_VAL(str); - while (n_reg_segments-- > 0) { - add_next_index_stringl(return_value, p, split_length); - p += split_length; - } + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { + zval zv; + while (n_reg_segments-- > 0) { + ZEND_ASSERT(split_length > 0); + ZVAL_STRINGL_FAST(&zv, p, split_length); + ZEND_HASH_FILL_ADD(&zv); + p += split_length; + } - if (p != (ZSTR_VAL(str) + ZSTR_LEN(str))) { - add_next_index_stringl(return_value, p, (ZSTR_VAL(str) + ZSTR_LEN(str) - p)); - } + if (p != (ZSTR_VAL(str) + ZSTR_LEN(str))) { + ZVAL_STRINGL_FAST(&zv, p, (ZSTR_VAL(str) + ZSTR_LEN(str) - p)); + ZEND_HASH_FILL_ADD(&zv); + } + } ZEND_HASH_FILL_END(); } /* }}} */ diff --git a/ext/standard/tests/array/005.phpt b/ext/standard/tests/array/005.phpt index 40e9eac265fec..1980d4ba14bf4 100644 --- a/ext/standard/tests/array/005.phpt +++ b/ext/standard/tests/array/005.phpt @@ -18,7 +18,7 @@ $mixed_array = array( array( "1" => "one", "2" => "two", "3" => "three", "4" => "four", "5" => "five" ), array( 1 => "one", 2 => "two", 3 => 7, 4 => "four", 5 => "five" ), array( "f" => "fff", "1" => "one", 4 => 6, "" => "blank", 2 => "float", "F" => "FFF", - "blank" => "", 3 => 3.7, 5 => 7, 6 => 8.6, '5' => "Five", "4name" => "jonny", "a" => NULL, NULL => 3 ), + "blank" => "", 3 => 3.7, 5 => 7, 6 => 8.6, '5' => "Five", "4name" => "jonny", "a" => NULL), array( 12, "name", 'age', '45' ), array( array("oNe", "tWo", 4), array(10, 20, 30, 40, 50), array() ), array( "one" => 1, "one" => 2, "three" => 3, 3, 4, 3 => 33, 4 => 44, 5, 6, @@ -202,7 +202,7 @@ array(12) { [4]=> int(6) [""]=> - int(3) + string(5) "blank" [2]=> string(5) "float" ["F"]=> diff --git a/ext/standard/tests/array/GHSA-h96m-rvf9-jgm2.phpt b/ext/standard/tests/array/GHSA-h96m-rvf9-jgm2.phpt new file mode 100644 index 0000000000000..2e3e85357e13c --- /dev/null +++ b/ext/standard/tests/array/GHSA-h96m-rvf9-jgm2.phpt @@ -0,0 +1,16 @@ +--TEST-- +GHSA-h96m-rvf9-jgm2 +--FILE-- +getMessage(), "\n"; +} + +?> +--EXPECTF-- +The total number of elements must be lower than %d diff --git a/ext/standard/tests/array/array_change_key_case_variation3.phpt b/ext/standard/tests/array/array_change_key_case_variation3.phpt index 0c3ed4eb0deac..886eed3862c7f 100644 --- a/ext/standard/tests/array/array_change_key_case_variation3.phpt +++ b/ext/standard/tests/array/array_change_key_case_variation3.phpt @@ -9,76 +9,28 @@ Test array_change_key_case() function : usage variations - different data types echo "*** Testing array_change_key_case() : usage variations ***\n"; -//get an unset variable -$unset_var = 10; -unset ($unset_var); - -// heredoc string -$heredoc = << array( +$inputs = [ + 'int' => [ 0 => 'zero', 1 => 'one', 12345 => 'positive', -2345 => 'negative', - ), - - // null data -/*3*/ 'null uppercase' => array( - NULL => 'null 1', - ), - 'null lowercase' => array( - null => 'null 2', - ), - - // boolean data -/*4*/ 'bool lowercase' => array( - true => 'lowert', - false => 'lowerf', - ), - 'bool uppercase' => array( - TRUE => 'uppert', - FALSE => 'upperf', - ), - - // empty data -/*5*/ 'empty double quotes' => array( - "" => 'emptyd', - ), - 'empty single quotes' => array( - '' => 'emptys', - ), - - // string data -/*6*/ 'string' => array( - "stringd" => 'stringd', + ], + 'bool' => [ + true => 'true', + false => 'false', + ], + 'string' => [ 'strings' => 'strings', - $heredoc => 'stringh', - ), - - // undefined data -/*8*/ 'undefined' => array( - @$undefined_var => 'undefined', - ), - - // unset data -/*9*/ 'unset' => array( - @$unset_var => 'unset', - ), -); + '' => 'emptys', + ], +]; // loop through each sub-array of $inputs to check the behavior of array_change_key_case() -$iterator = 1; foreach($inputs as $key => $input) { - echo "\n-- Iteration $iterator : $key data --\n"; + echo "\n-- $key data --\n"; var_dump( array_change_key_case($input, CASE_UPPER) ); - $iterator++; }; echo "Done"; @@ -86,7 +38,7 @@ echo "Done"; --EXPECT-- *** Testing array_change_key_case() : usage variations *** --- Iteration 1 : int data -- +-- int data -- array(4) { [0]=> string(4) "zero" @@ -98,65 +50,19 @@ array(4) { string(8) "negative" } --- Iteration 2 : null uppercase data -- -array(1) { - [""]=> - string(6) "null 1" -} - --- Iteration 3 : null lowercase data -- -array(1) { - [""]=> - string(6) "null 2" -} - --- Iteration 4 : bool lowercase data -- +-- bool data -- array(2) { [1]=> - string(6) "lowert" + string(4) "true" [0]=> - string(6) "lowerf" + string(5) "false" } --- Iteration 5 : bool uppercase data -- +-- string data -- array(2) { - [1]=> - string(6) "uppert" - [0]=> - string(6) "upperf" -} - --- Iteration 6 : empty double quotes data -- -array(1) { - [""]=> - string(6) "emptyd" -} - --- Iteration 7 : empty single quotes data -- -array(1) { - [""]=> - string(6) "emptys" -} - --- Iteration 8 : string data -- -array(3) { - ["STRINGD"]=> - string(7) "stringd" ["STRINGS"]=> string(7) "strings" - ["HELLO WORLD"]=> - string(7) "stringh" -} - --- Iteration 9 : undefined data -- -array(1) { [""]=> - string(9) "undefined" -} - --- Iteration 10 : unset data -- -array(1) { - [""]=> - string(5) "unset" + string(6) "emptys" } Done diff --git a/ext/standard/tests/array/array_change_key_case_variation8.phpt b/ext/standard/tests/array/array_change_key_case_variation8.phpt index bb4dbc4af60f0..892cda2818ffe 100644 --- a/ext/standard/tests/array/array_change_key_case_variation8.phpt +++ b/ext/standard/tests/array/array_change_key_case_variation8.phpt @@ -10,7 +10,7 @@ echo "*** Testing array_change_key_case() : usage variations ***\n"; $inputs = array ( // group of escape sequences - array(null => 1, NULL => 2, "\a" => 3, "\cx" => 4, "\e" => 5, "\f" => 6, "\n" => 7, "\t" => 8, "\xhh" => 9, "\ddd" => 10, "\v" => 11), + array("\a" => 3, "\cx" => 4, "\e" => 5, "\f" => 6, "\n" => 7, "\t" => 8, "\xhh" => 9, "\ddd" => 10, "\v" => 11), // array contains combination of capital/small letters array("lemoN" => 1, "Orange" => 2, "banana" => 3, "apple" => 4, "Test" => 5, "TTTT" => 6, "ttt" => 7, "ww" => 8, "x" => 9, "X" => 10, "oraNGe" => 11, "BANANA" => 12) @@ -29,9 +29,7 @@ echo "Done"; *** Testing array_change_key_case() : usage variations *** -- $case = default -- -array(10) { - [""]=> - int(2) +array(9) { ["\a"]=> int(3) ["\cx"]=> @@ -53,9 +51,7 @@ array(10) { int(11) } -- $case = upper -- -array(10) { - [""]=> - int(2) +array(9) { ["\A"]=> int(3) ["\CX"]=> diff --git a/ext/standard/tests/array/array_combine_variation3.phpt b/ext/standard/tests/array/array_combine_variation3.phpt index 94901eedf6495..241ead058c809 100644 --- a/ext/standard/tests/array/array_combine_variation3.phpt +++ b/ext/standard/tests/array/array_combine_variation3.phpt @@ -23,13 +23,6 @@ the lazy dog This is a double quoted string EOT; -// heredoc with different whitespaces -$diff_whitespaces = <<22 @@ -45,9 +38,9 @@ $arrays = array ( array(false,true), // with default keys and boolean values array(), // empty array /*5*/ array(NULL), // with NULL - array("a\v\f","aaaa\r","b","b\tbbb","c","\[\]\!\@\#\$\%\^\&\*\(\)\{\}"), // with double quoted strings - array('a\v\f','aaaa\r','b','b\tbbb','c','\[\]\!\@\#\$\%\^\&\*\(\)\{\}'), // with single quoted strings - array("h1" => $blank_line, "h2" => $multiline_string, "h3" => $diff_whitespaces, $numeric_string), // with heredocs + array("a\v\f","aaaa\n","b","b\tbbb","c","\[\]\!\@\#\$\%\^\&\*\(\)\{\}"), // with double quoted strings + array('a\v\f','aaaa\n','b','b\tbbb','c','\[\]\!\@\#\$\%\^\&\*\(\)\{\}'), // with single quoted strings + array("h1" => $blank_line, "h2" => $multiline_string, $numeric_string), // with heredocs // associative arrays /*9*/ array(1 => "one", 2 => "two", 3 => "three"), // explicit numeric keys, string values @@ -57,11 +50,11 @@ $arrays = array ( array("one" => 1, 2 => "two", 4 => "four"), //mixed // associative array, containing null/empty/boolean values as key/value -/*14*/ array(NULL => "NULL", null => "null", "NULL" => NULL, "null" => null), +/*14*/ array(true => "true", false => "false", "false" => false, "true" => true), array("" => "emptyd", '' => 'emptys', "emptyd" => "", 'emptys' => ''), - array(1 => '', 2 => "", 3 => NULL, 4 => null, 5 => false, 6 => true), - array('' => 1, "" => 2, NULL => 3, null => 4, false => 5, true => 6), + array(1 => '', 2 => "", 5 => false, 6 => true), + array('' => 1, "" => 2, false => 5, true => 6), // array with repetitive keys /*19*/ array("One" => 1, "two" => 2, "One" => 10, "two" => 20, "three" => 3) @@ -113,8 +106,10 @@ array(1) { array(6) { ["a "]=> string(3) "a " - ["aaaa "]=> - string(5) "aaaa " + ["aaaa +"]=> + string(5) "aaaa +" ["b"]=> string(1) "b" ["b bbb"]=> @@ -128,8 +123,8 @@ array(6) { array(6) { ["a\v\f"]=> string(5) "a\v\f" - ["aaaa\r"]=> - string(6) "aaaa\r" + ["aaaa\n"]=> + string(6) "aaaa\n" ["b"]=> string(1) "b" ["b\tbbb"]=> @@ -140,7 +135,7 @@ array(6) { string(28) "\[\]\!\@\#\$\%\^\&\*\(\)\{\}" } -- Iteration 8 -- -array(4) { +array(3) { [" "]=> string(1) " @@ -153,14 +148,6 @@ This is a double quoted string"]=> The quick brown fox jumped over; the lazy dog This is a double quoted string" - ["hello world -1111 != 2222 -heredoc -double quoted string. with different white spaces"]=> - string(88) "hello world -1111 != 2222 -heredoc -double quoted string. with different white spaces" ["11 < 12. 123 >22 'single quoted string' "double quoted string" @@ -220,13 +207,6 @@ array(3) { string(4) "four" } -- Iteration 14 -- -array(2) { - ["null"]=> - string(4) "null" - [""]=> - NULL -} --- Iteration 15 -- array(4) { ["true"]=> string(4) "true" @@ -237,30 +217,30 @@ array(4) { [1]=> bool(true) } --- Iteration 16 -- +-- Iteration 15 -- array(2) { ["emptys"]=> string(6) "emptys" [""]=> string(0) "" } --- Iteration 17 -- +-- Iteration 16 -- array(2) { [""]=> bool(false) [1]=> bool(true) } --- Iteration 18 -- +-- Iteration 17 -- array(3) { - [4]=> - int(4) + [2]=> + int(2) [5]=> int(5) [6]=> int(6) } --- Iteration 19 -- +-- Iteration 18 -- array(3) { [10]=> int(10) diff --git a/ext/standard/tests/array/array_combine_variation4.phpt b/ext/standard/tests/array/array_combine_variation4.phpt index 1ff6b64f175e5..993119edcedfe 100644 --- a/ext/standard/tests/array/array_combine_variation4.phpt +++ b/ext/standard/tests/array/array_combine_variation4.phpt @@ -9,9 +9,6 @@ Test array_combine() function : usage variations - associative array with differ */ echo "*** Testing array_combine() : assoc array with diff keys to both \$keys and \$values argument ***\n"; -// get an unset variable -$unset_var = 10; -unset ($unset_var); // get a resource variable $fp = fopen(__FILE__, "r"); @@ -24,11 +21,6 @@ class classA } } -// get a heredoc string -$heredoc = << 2.2, 'pen\n' => 33), array("\tHello" => 111, "re\td" => "color", "\v\fworld" => 2.2, "pen\n" => 33), - array("hello", $heredoc => "string"), // heredoc // array with object, unset variable and resource variable -/*10*/ array(@$unset_var => "hello", $fp => 'resource'), +/*10*/ array($fp => 'resource'), // array with mixed keys /*11*/ array('hello' => 1, "fruit" => 2.2, $fp => 'resource', 133 => "int", - @$unset_var => "unset", $heredoc => "heredoc") + ) ); // array to be passsed to $arr2 argument @@ -128,21 +119,12 @@ array(4) { int(33) } -- Iteration 7 -- -array(2) { - ["hello"]=> - string(5) "hello" - ["string"]=> - string(6) "string" -} --- Iteration 8 -- -array(2) { - ["hello"]=> - string(5) "hello" +array(1) { ["resource"]=> string(8) "resource" } --- Iteration 9 -- -array(6) { +-- Iteration 8 -- +array(4) { [1]=> int(1) ["2.2"]=> @@ -151,9 +133,5 @@ array(6) { string(8) "resource" ["int"]=> string(3) "int" - ["unset"]=> - string(5) "unset" - ["heredoc"]=> - string(7) "heredoc" } Done 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_key_variation7.phpt b/ext/standard/tests/array/array_diff_key_variation7.phpt deleted file mode 100644 index 9ca74cccb9597..0000000000000 --- a/ext/standard/tests/array/array_diff_key_variation7.phpt +++ /dev/null @@ -1,52 +0,0 @@ ---TEST-- -Test array_diff_key() function : usage variation - Passing null,unset and undefined variable indexed array ---FILE-- - '10', "" => 'empty'); - -//get an unset variable -$unset_var = 10; -unset ($unset_var); - -$input_arrays = array( - 'null indexed' => array(NULL => 'null 1', null => 'null 2'), - 'undefined indexed' => array(@$undefined_var => 'undefined'), - 'unset indexed' => array(@$unset_var => 'unset'), -); - -foreach($input_arrays as $key =>$value) { - echo "\n--$key--\n"; - // loop through each element of the array for arr1 - var_dump( array_diff_key($input_array, $value) ); - var_dump( array_diff_key($value, $input_array) ); -} -?> ---EXPECT-- -*** Testing array_diff_key() : usage variation *** - ---null indexed-- -array(1) { - [10]=> - string(2) "10" -} -array(0) { -} - ---undefined indexed-- -array(1) { - [10]=> - string(2) "10" -} -array(0) { -} - ---unset indexed-- -array(1) { - [10]=> - string(2) "10" -} -array(0) { -} diff --git a/ext/standard/tests/array/array_diff_leak_custom_type_checks.phpt b/ext/standard/tests/array/array_diff_leak_custom_type_checks.phpt new file mode 100644 index 0000000000000..77aef0ccc08b2 --- /dev/null +++ b/ext/standard/tests/array/array_diff_leak_custom_type_checks.phpt @@ -0,0 +1,14 @@ +--TEST-- +array_diff() memory leak with custom type checks +--FILE-- +getMessage(), "\n"; +} + +?> +--EXPECT-- +array_diff(): Argument #2 must be of type array, string given diff --git a/ext/standard/tests/array/array_diff_uassoc_variation12.phpt b/ext/standard/tests/array/array_diff_uassoc_variation12.phpt deleted file mode 100644 index d5681c94cbdec..0000000000000 --- a/ext/standard/tests/array/array_diff_uassoc_variation12.phpt +++ /dev/null @@ -1,52 +0,0 @@ ---TEST-- -Test array_diff_uassoc() function : usage variation - Passing null,unset and undefined variable indexed array ---FILE-- - '10', "" => ''); - -//get an unset variable -$unset_var = 10; -unset ($unset_var); - -$input_arrays = array( - 'null indexed' => array(NULL => NULL, null => null), - 'undefined indexed' => array(@$undefined_var => @$undefined_var), - 'unset indexed' => array(@$unset_var => @$unset_var), -); - -foreach($input_arrays as $key =>$value) { - echo "\n--$key--\n"; - var_dump( array_diff_uassoc($input_array, $value, "strcasecmp") ); - var_dump( array_diff_uassoc($value, $input_array, "strcasecmp") ); -} - -?> ---EXPECT-- -*** Testing array_diff_uassoc() : usage variation *** - ---null indexed-- -array(1) { - [10]=> - string(2) "10" -} -array(0) { -} - ---undefined indexed-- -array(1) { - [10]=> - string(2) "10" -} -array(0) { -} - ---unset indexed-- -array(1) { - [10]=> - string(2) "10" -} -array(0) { -} diff --git a/ext/standard/tests/array/array_diff_ukey_variation9.phpt b/ext/standard/tests/array/array_diff_ukey_variation9.phpt deleted file mode 100644 index 22cd3d45fdf84..0000000000000 --- a/ext/standard/tests/array/array_diff_ukey_variation9.phpt +++ /dev/null @@ -1,52 +0,0 @@ ---TEST-- -Test array_diff_ukey() function : usage variation - Passing null,unset and undefined variable indexed array ---FILE-- - '10', "" => 'empty'); - -//get an unset variable -$unset_var = 10; -unset ($unset_var); - -$input_arrays = array( - 'null indexed' => array(NULL => 'null 1', null => 'null 2'), - 'undefined indexed' => array(@$undefined_var => 'undefined'), - 'unset indexed' => array(@$unset_var => 'unset'), -); - -foreach($input_arrays as $key =>$value) { - echo "\n--$key--\n"; - var_dump( array_diff_ukey($value, $input_array, 'strcasecmp') ); - var_dump( array_diff_ukey($input_array, $value, 'strcasecmp') ); -} - -?> ---EXPECT-- -*** Testing array_diff_ukey() : usage variation *** - ---null indexed-- -array(0) { -} -array(1) { - [10]=> - string(2) "10" -} - ---undefined indexed-- -array(0) { -} -array(1) { - [10]=> - string(2) "10" -} - ---unset indexed-- -array(0) { -} -array(1) { - [10]=> - string(2) "10" -} 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_fill_variation5.phpt b/ext/standard/tests/array/array_fill_variation5.phpt index f984a09675976..4f8b48d308382 100644 --- a/ext/standard/tests/array/array_fill_variation5.phpt +++ b/ext/standard/tests/array/array_fill_variation5.phpt @@ -23,10 +23,9 @@ $values = array( /* 5 */ array('color' => 'red' , 'item' => 'pen'), array( 'color' => 'red' , 2 => 'green ' ), array("colour" => "red" , "item" => "pen"), - array( TRUE => "red" , FALSE => "green" ), - array( true => "red" , FALSE => "green" ), + array( true => "red" , false => "green" ), /* 10 */ array( 1 => "Hi" , "color" => "red" , 'item' => 'pen'), - array( NULL => "Hi", '1' => "Hello" , "1" => "Green"), + array( '' => "Hi", '1' => "Hello" , "1" => "Green"), array( ""=>1, "color" => "green"), /* 13 */ array('Saffron' , 'White' , 'Green') ); @@ -191,23 +190,6 @@ array(2) { } } -- Iteration 9 -- -array(2) { - [0]=> - array(2) { - [1]=> - string(3) "red" - [0]=> - string(5) "green" - } - [1]=> - array(2) { - [1]=> - string(3) "red" - [0]=> - string(5) "green" - } -} --- Iteration 10 -- array(2) { [0]=> array(3) { @@ -228,7 +210,7 @@ array(2) { string(3) "pen" } } --- Iteration 11 -- +-- Iteration 10 -- array(2) { [0]=> array(2) { @@ -245,7 +227,7 @@ array(2) { string(5) "Green" } } --- Iteration 12 -- +-- Iteration 11 -- array(2) { [0]=> array(2) { @@ -262,7 +244,7 @@ array(2) { string(5) "green" } } --- Iteration 13 -- +-- Iteration 12 -- array(2) { [0]=> array(3) { diff --git a/ext/standard/tests/array/array_filter_variation3.phpt b/ext/standard/tests/array/array_filter_variation3.phpt index a81bb35951435..c5e6c121965b0 100644 --- a/ext/standard/tests/array/array_filter_variation3.phpt +++ b/ext/standard/tests/array/array_filter_variation3.phpt @@ -24,11 +24,10 @@ $input_values = array( array(0, 1, 2, -1, 034, 0X4A), // integer values array(0.0, 1.2, 1.2e3, 1.2e-3), // float values array('value1', "value2", '', " ", ""), // string values - array(true, false, TRUE, FALSE), // bool values - array(null, NULL), // null values + array(true, false), // bool values array(1 => 'one', 'zero' => 0, -2 => "value"), //associative array - array("one" => 1, null => 'null', 5 => "float", true => 1, "" => 'empty'), // associative array with different keys - array(1 => 'one', 2, "key" => 'value') // combinition of associative and non-associative array + array("one" => 1, 5 => "float", true => 1, "" => 'empty'), // associative array with different keys + array(1 => 'one', 2, "key" => 'value') // combination of associative and non-associative array ); @@ -119,36 +118,19 @@ array(5) { array(0) { } -- Iteration 4 -- -array(2) { +array(1) { [0]=> bool(true) - [2]=> - bool(true) } -array(4) { +array(2) { [0]=> bool(true) [1]=> bool(false) - [2]=> - bool(true) - [3]=> - bool(false) } array(0) { } -- Iteration 5 -- -array(0) { -} -array(2) { - [0]=> - NULL - [1]=> - NULL -} -array(0) { -} --- Iteration 6 -- array(2) { [1]=> string(3) "one" @@ -165,30 +147,30 @@ array(3) { } array(0) { } --- Iteration 7 -- +-- Iteration 6 -- array(4) { ["one"]=> int(1) - [""]=> - string(5) "empty" [5]=> string(5) "float" [1]=> int(1) + [""]=> + string(5) "empty" } array(4) { ["one"]=> int(1) - [""]=> - string(5) "empty" [5]=> string(5) "float" [1]=> int(1) + [""]=> + string(5) "empty" } array(0) { } --- Iteration 8 -- +-- Iteration 7 -- array(3) { [1]=> string(3) "one" 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_flip_variation2.phpt b/ext/standard/tests/array/array_flip_variation2.phpt index 9cf90905c15f9..bd433db9dd5a7 100644 --- a/ext/standard/tests/array/array_flip_variation2.phpt +++ b/ext/standard/tests/array/array_flip_variation2.phpt @@ -8,25 +8,12 @@ Test array_flip() function : usage variations - 'input' array with different key echo "*** Testing array_flip() : different keys for 'input' array argument ***\n"; -// different heredoc strings -$empty_heredoc = << 'int_key', // expected: value will be replaced by 'bool_key3' + 1 => 'int_key', // expected: value will be replaced by 'bool_key1' -2 => 'negative_key', 012 => 'octal_key', 0x34 => 'hex_key', @@ -41,21 +28,10 @@ $input = array( // bool keys true => 'bool_key1', false => 'bool_key2', - TRUE => 'bool_key3', - FALSE => 'bool_key4', - - // null keys - null => 'null_key1', // expected: value will be replaced by 'null_key2' - NULL => 'null_key2', // binary key "a".chr(0)."b" => 'binary_key1', b"binary" => 'binary_key2', - - //heredoc keys - $empty_heredoc => 'empty_heredoc', - $simple_heredoc => 'simple_heredoc', - $multiline_heredoc => 'multiline_heredoc', ); var_dump( array_flip($input) ); @@ -64,10 +40,10 @@ echo "Done" ?> --EXPECTF-- *** Testing array_flip() : different keys for 'input' array argument *** -array(13) { - ["bool_key4"]=> +array(11) { + ["bool_key2"]=> int(0) - ["bool_key3"]=> + ["bool_key1"]=> int(1) ["negative_key"]=> int(-2) @@ -79,7 +55,7 @@ array(13) { string(3) "key" ["string_key2"]=> string(3) "two" - ["empty_heredoc"]=> + ["string_key4"]=> string(0) "" ["string_key5"]=> string(1) " " @@ -87,11 +63,5 @@ array(13) { string(3) "a%0b" ["binary_key2"]=> string(6) "binary" - ["simple_heredoc"]=> - string(6) "simple" - ["multiline_heredoc"]=> - string(6%d) "multiline heredoc with 123 and -speci@! ch@r$...checking -and also" } Done diff --git a/ext/standard/tests/array/array_flip_variation5.phpt b/ext/standard/tests/array/array_flip_variation5.phpt index e7c47dffa5215..49876f35a82f3 100644 --- a/ext/standard/tests/array/array_flip_variation5.phpt +++ b/ext/standard/tests/array/array_flip_variation5.phpt @@ -3,39 +3,35 @@ Test array_flip() function : usage variations - 'input' argument with repeatitiv --FILE-- 'value', 2 => 'VALUE', 1 => "VaLuE", 3 => 4, 3 => 5); var_dump( array_flip($input) ); -// array with string key repeatition +// array with string key repetition $input = array("key" => 1, "two" => 'TWO', 'three' => 3, 'key' => "FOUR"); var_dump( array_flip($input) ); -// array with bool key repeatition +// array with bool key repetition $input = array(true => 1, false => 0, TRUE => -1); var_dump( array_flip($input) ); -// array with null key repeatition -$input = array(null => "Hello", NULL => 0); -var_dump( array_flip($input) ); - -// array with numeric value repeatition +// array with numeric value repetition $input = array('one' => 1, 'two' => 2, 3 => 1, "index" => 1); var_dump( array_flip($input) ); -//array with string value repeatition +//array with string value repetition $input = array('key1' => "value1", "key2" => '2', 'key3' => 'value1'); var_dump( array_flip($input) ); echo "Done" ?> --EXPECT-- -*** Testing array_flip() : 'input' array with repeatitive keys/values *** +*** Testing array_flip() : 'input' array with repetitive keys/values *** array(3) { ["VaLuE"]=> int(1) @@ -58,10 +54,6 @@ array(2) { [0]=> int(0) } -array(1) { - [0]=> - string(0) "" -} array(2) { [1]=> string(5) "index" diff --git a/ext/standard/tests/array/array_intersect_assoc_variation3.phpt b/ext/standard/tests/array/array_intersect_assoc_variation3.phpt index bb439a053bd28..532a79e688fa6 100644 --- a/ext/standard/tests/array/array_intersect_assoc_variation3.phpt +++ b/ext/standard/tests/array/array_intersect_assoc_variation3.phpt @@ -25,13 +25,6 @@ the lazy dog This is a double quoted string EOT; -// heredoc with different whitespaces -$diff_whitespaces = <<22 @@ -49,7 +42,7 @@ $arrays = array ( /*5*/ array(NULL), // with NULL array("a\v\f","aaaa\r","b","b\tbbb","c","\[\]\!\@\#\$\%\^\&\*\(\)\{\}"), // with double quoted strings array('a\v\f','aaaa\r','b','b\tbbb','c','\[\]\!\@\#\$\%\^\&\*\(\)\{\}'), // with single quoted strings - array("h1" => $blank_line, "h2" => $multiline_string, "h3" => $diff_whitespaces, $numeric_string), // with heredocs + array("h1" => $blank_line, "h2" => $multiline_string, $numeric_string), // with heredocs // associative arrays /*9*/ array(1 => "one", 2 => "two", 3 => "three"), // explicit numeric keys, string values @@ -59,11 +52,10 @@ $arrays = array ( array("one" => 1, 2 => "two", 4 => "four"), //mixed // associative array, containing null/empty/boolean values as key/value -/*14*/ array(NULL => "NULL", null => "null", "NULL" => NULL, "null" => null), - array(true => "true", false => "false", "false" => false, "true" => true), +/*14*/ array(true => "true", false => "false", "false" => false, "true" => true), array("" => "emptyd", '' => 'emptys', "emptyd" => "", 'emptys' => ''), array(1 => '', 2 => "", 3 => NULL, 4 => null, 5 => false, 6 => true), - array('' => 1, "" => 2, NULL => 3, null => 4, false => 5, true => 6), + array('' => 1, "" => 2, false => 5, true => 6), // array with repetitive keys /*19*/ array("One" => 1, "two" => 2, "One" => 10, "two" => 20, "three" => 3) @@ -74,9 +66,9 @@ $arrays = array ( $arr2 = array ( 1, 1.1, 2.2, "hello", "one", NULL, 2, 'world', true,5 => false, 1 => 'aaaa\r', "aaaa\r", - 'h3' => $diff_whitespaces, $numeric_string, + $numeric_string, "one" => "ten", 4 => "four", "two" => 2, - '', null => "null", '' => 'emptys', "emptyd" => "", + '', '' => 'emptys', "emptyd" => "", ); // loop through each sub-array within $arrays to check the behavior of array_intersect_assoc() @@ -141,19 +133,9 @@ array(1) { string(6) "aaaa\r" } -- Iteration 8 -- -array(1) { - ["h3"]=> - string(88) "hello world -1111 != 2222 -heredoc -double quoted string. with different white spaces" +array(0) { } -array(1) { - ["h3"]=> - string(88) "hello world -1111 != 2222 -heredoc -double quoted string. with different white spaces" +array(0) { } -- Iteration 9 -- array(0) { @@ -198,11 +180,6 @@ array(0) { array(0) { } -- Iteration 15 -- -array(0) { -} -array(0) { -} --- Iteration 16 -- array(2) { [""]=> string(6) "emptys" @@ -215,7 +192,7 @@ array(2) { ["emptyd"]=> string(0) "" } --- Iteration 17 -- +-- Iteration 16 -- array(1) { [5]=> bool(false) @@ -224,12 +201,12 @@ array(1) { [5]=> bool(false) } --- Iteration 18 -- +-- Iteration 17 -- array(0) { } array(0) { } --- Iteration 19 -- +-- Iteration 18 -- array(0) { } array(0) { diff --git a/ext/standard/tests/array/array_intersect_assoc_variation4.phpt b/ext/standard/tests/array/array_intersect_assoc_variation4.phpt index 859b7280d8ee4..91b64869c373a 100644 --- a/ext/standard/tests/array/array_intersect_assoc_variation4.phpt +++ b/ext/standard/tests/array/array_intersect_assoc_variation4.phpt @@ -25,13 +25,6 @@ the lazy dog This is a double quoted string EOT; -// heredoc with different whitespaces -$diff_whitespaces = <<22 @@ -40,13 +33,13 @@ $numeric_string = << true, "hello", "one", NULL, 2, 'world', true, false, 3 => "b\tbbb", "aaaa\r", - $numeric_string, "h3" => $diff_whitespaces, "true" => true, + $numeric_string, "true" => true, "one" => "ten", 4 => "four", "two" => 2, 6 => "six", - '', null => "null", '' => 'emptys' + '', '' => 'emptys' ); // arrays to be passed to $arr2 argument @@ -58,7 +51,7 @@ $arrays = array ( /*5*/ array(NULL), // array with NULL array("a\v\f","aaaa\r","b","b\tbbb","c","\[\]\!\@\#\$\%\^\&\*\(\)\{\}"), // array with double quoted strings array('a\v\f','aaaa\r','b','b\tbbb','c','\[\]\!\@\#\$\%\^\&\*\(\)\{\}'), // array with single quoted strings - array($blank_line, "h2" => $multiline_string, "h3" => $diff_whitespaces, $numeric_string), // array with heredocs + array($blank_line, "h2" => $multiline_string, $numeric_string), // array with heredocs // associative arrays /*9*/ array(1 => "one", 2 => "two", 6 => "six"), // explicit numeric keys, string values @@ -68,11 +61,10 @@ $arrays = array ( array("one" => 1, 2 => "two", 4 => "four"), //mixed // associative array, containing null/empty/boolean values as key/value -/*14*/ array(NULL => "NULL", null => "null", "NULL" => NULL, "null" => null), - array(true => "true", false => "false", "false" => false, "true" => true), +/*14*/ array(true => "true", false => "false", "false" => false, "true" => true), array("" => "emptyd", '' => 'emptys', "emptyd" => "", 'emptys' => ''), - array(1 => '', 2 => "", 3 => NULL, 4 => null, 5 => false, 6 => true), - array('' => 1, "" => 2, NULL => 3, null => 4, false => 5, true => 6), + array(1 => '', 2 => "", 5 => false, 6 => true), + array('' => 1, "" => 2, false => 5, true => 6), // array with repetitive keys /*19*/ array("One" => 1, "two" => 2, "One" => 10, "two" => 20, "three" => 3) @@ -148,19 +140,9 @@ array(0) { array(0) { } -- Iteration 8 -- -array(1) { - ["h3"]=> - string(88) "hello world -1111 != 2222 -heredoc -double quoted string. with different white spaces" +array(0) { } -array(1) { - ["h3"]=> - string(88) "hello world -1111 != 2222 -heredoc -double quoted string. with different white spaces" +array(0) { } -- Iteration 9 -- array(1) { @@ -204,11 +186,6 @@ array(1) { string(4) "four" } -- Iteration 14 -- -array(0) { -} -array(0) { -} --- Iteration 15 -- array(1) { ["true"]=> bool(true) @@ -217,7 +194,7 @@ array(1) { ["true"]=> bool(true) } --- Iteration 16 -- +-- Iteration 15 -- array(1) { [""]=> string(6) "emptys" @@ -226,7 +203,7 @@ array(1) { [""]=> string(6) "emptys" } --- Iteration 17 -- +-- Iteration 16 -- array(1) { [5]=> NULL @@ -235,12 +212,12 @@ array(1) { [5]=> NULL } --- Iteration 18 -- +-- Iteration 17 -- array(0) { } array(0) { } --- Iteration 19 -- +-- Iteration 18 -- array(0) { } array(0) { diff --git a/ext/standard/tests/array/array_intersect_assoc_variation5.phpt b/ext/standard/tests/array/array_intersect_assoc_variation5.phpt index 65ce1dae17d13..64cfdbb529407 100644 --- a/ext/standard/tests/array/array_intersect_assoc_variation5.phpt +++ b/ext/standard/tests/array/array_intersect_assoc_variation5.phpt @@ -10,10 +10,6 @@ Test array_intersect_assoc() function : usage variations - assoc array with diff echo "*** Testing array_intersect_assoc() : assoc array with diff keys to \$arr1 argument ***\n"; -// get an unset variable -$unset_var = 10; -unset ($unset_var); - // get a heredoc string $heredoc = << 2.2, "pen\n" => 33), array("hello", $heredoc => "string"), // heredoc - // array with object, unset variable and resource variable -/*10*/ array(@$unset_var => "hello"), - // array with mixed keys /*11*/ array('hello' => 1, "fruit" => 2.2, 133 => "int", - @$unset_var => "unset", $heredoc => "heredoc") + $heredoc => "heredoc") ); // array to be passed to $arr2 argument @@ -123,11 +116,6 @@ array(1) { string(6) "string" } -- Iteration 8 -- -array(0) { -} -array(0) { -} --- Iteration 9 -- array(1) { [133]=> string(3) "int" diff --git a/ext/standard/tests/array/array_intersect_assoc_variation6.phpt b/ext/standard/tests/array/array_intersect_assoc_variation6.phpt index f446c6870419d..92664a83b79da 100644 --- a/ext/standard/tests/array/array_intersect_assoc_variation6.phpt +++ b/ext/standard/tests/array/array_intersect_assoc_variation6.phpt @@ -10,10 +10,6 @@ Test array_intersect_assoc() function : usage variations - assoc array with diff echo "*** Testing array_intersect_assoc() : assoc array with diff keys to \$arr2 argument ***\n"; -// get an unset variable -$unset_var = 10; -unset ($unset_var); - // get a heredoc string $heredoc = << "string"), // heredoc // array with unset variable -/*10*/ array( @$unset_var => "hello"), // array with mixed keys /*11*/ array('hello' => 1, "fruit" => 2.2, 133 => "int", - @$unset_var => "unset", $heredoc => "heredoc") + $heredoc => "heredoc") ); // array to be passed to $arr1 argument @@ -123,11 +118,6 @@ array(1) { string(6) "string" } -- Iteration 8 -- -array(0) { -} -array(0) { -} --- Iteration 9 -- array(1) { [133]=> string(3) "int" diff --git a/ext/standard/tests/array/array_intersect_key_variation7.phpt b/ext/standard/tests/array/array_intersect_key_variation7.phpt deleted file mode 100644 index 2b6ead7919adb..0000000000000 --- a/ext/standard/tests/array/array_intersect_key_variation7.phpt +++ /dev/null @@ -1,56 +0,0 @@ ---TEST-- -Test array_intersect_key() function : usage variation - Passing null,unset and undefeined variable indexed array ---FILE-- - '0', 1 => '1' , -10 => '-10' , null => 'null'); -//get an unset variable -$unset_var = 10; -unset ($unset_var); - -$input_arrays = array( - 'null indexed' => array(NULL => 'null 1', null => 'null 2'), - 'undefined indexed' => array(@$undefined_var => 'undefined'), - 'unset indexed' => array(@$unset_var => 'unset'), -); - -foreach($input_arrays as $key =>$value) { - echo "\n--$key--\n"; - var_dump( array_intersect_key($input_array, $value) ); - var_dump( array_intersect_key($value,$input_array ) ); -} -?> ---EXPECT-- -*** Testing array_intersect_key() : usage variation *** - ---null indexed-- -array(1) { - [""]=> - string(4) "null" -} -array(1) { - [""]=> - string(6) "null 2" -} - ---undefined indexed-- -array(1) { - [""]=> - string(4) "null" -} -array(1) { - [""]=> - string(9) "undefined" -} - ---unset indexed-- -array(1) { - [""]=> - string(4) "null" -} -array(1) { - [""]=> - string(5) "unset" -} diff --git a/ext/standard/tests/array/array_intersect_variation3.phpt b/ext/standard/tests/array/array_intersect_variation3.phpt index 1f3258ae8326b..05584ae0a49ce 100644 --- a/ext/standard/tests/array/array_intersect_variation3.phpt +++ b/ext/standard/tests/array/array_intersect_variation3.phpt @@ -25,13 +25,6 @@ the lazy dog This is a double quoted string EOT; -// heredoc with different whitespaces -$diff_whitespaces = <<22 @@ -47,9 +40,9 @@ $arrays = array ( array(false,true), // array with default keys and boolean values array(), // empty array /*5*/ array(NULL), // array with NULL - array("a\v\f","aaaa\r","b","b\tbbb","c","\[\]\!\@\#\$\%\^\&\*\(\)\{\}"), // array with double quoted strings - array('a\v\f','aaaa\r','b','b\tbbb','c','\[\]\!\@\#\$\%\^\&\*\(\)\{\}'), // array with single quoted strings - array($blank_line, $multiline_string, $diff_whitespaces, $numeric_string), // array with heredocs + array("a\v\f","aaaa\n","b","b\tbbb","c","\[\]\!\@\#\$\%\^\&\*\(\)\{\}"), // array with double quoted strings + array('a\v\f','aaaa\n','b','b\tbbb','c','\[\]\!\@\#\$\%\^\&\*\(\)\{\}'), // array with single quoted strings + array($blank_line, $multiline_string, $numeric_string), // array with heredocs // associative arrays /*9*/ array(1 => "one", 2 => "two", 3 => "three"), // explicit numeric keys, string values @@ -58,25 +51,24 @@ $arrays = array ( array( "one" => "ten", "two" => "twenty", "three" => "thirty"), // string key/value array("one" => 1, 2 => "two", 4 => "four"), //mixed - // associative array, containing null/empty/boolean values as key/value -/*14*/ array(NULL => "NULL", null => "null", "NULL" => NULL, "null" => null), - array(true => "true", false => "false", "false" => false, "true" => true), + // associative array, containing empty/boolean values as key/value +/*14*/ array(true => "true", false => "false", "false" => false, "true" => true), array("" => "emptyd", '' => 'emptys', "emptyd" => "", 'emptys' => ''), - array(1 => '', 2 => "", 3 => NULL, 4 => null, 5 => false, 6 => true), - array('' => 1, "" => 2, NULL => 3, null => 4, false => 5, true => 6), + array(1 => '', 2 => "", 5 => false, 6 => true), + array('' => 1, "" => 2, false => 5, true => 6), // array with repetitive keys /*19*/ array("One" => 1, "two" => 2, "One" => 10, "two" => 20, "three" => 3) ); -// array to be passsed to $arr2 argument +// array to be passed to $arr2 argument $arr2 = array ( 1, 1.1, "hello", "one", NULL, 2, - 'world', true, false, false => 5, 'aaaa\r', "aaaa\r", - $numeric_string, $diff_whitespaces, + 'world', true, false, false => 5, 'aaaa\n', "aaaa\n", + $numeric_string, "one" => "ten", 4 => "four", "two" => 2, 2 => "two", - '', null => "null", '' => 'emptys' + '', '' => 'emptys' ); // loop through each sub-array within $arrays to check the behavior of array_intersect() @@ -149,42 +141,34 @@ array(1) { -- Iterator 6 -- array(1) { [1]=> - string(5) "aaaa " + string(5) "aaaa +" } array(1) { [1]=> - string(5) "aaaa " + string(5) "aaaa +" } -- Iterator 7 -- array(1) { [1]=> - string(6) "aaaa\r" + string(6) "aaaa\n" } array(1) { [1]=> - string(6) "aaaa\r" + string(6) "aaaa\n" } -- Iterator 8 -- -array(2) { +array(1) { [2]=> - string(88) "hello world -1111 != 2222 -heredoc -double quoted string. with different white spaces" - [3]=> string(90) "11 < 12. 123 >22 'single quoted string' "double quoted string" 2222 != 1111. 0000 = 0000 " } -array(2) { +array(1) { [2]=> - string(88) "hello world -1111 != 2222 -heredoc -double quoted string. with different white spaces" - [3]=> string(90) "11 < 12. 123 >22 'single quoted string' "double quoted string" @@ -249,19 +233,6 @@ array(3) { string(4) "four" } -- Iterator 14 -- -array(2) { - ["NULL"]=> - NULL - ["null"]=> - NULL -} -array(2) { - ["NULL"]=> - NULL - ["null"]=> - NULL -} --- Iterator 15 -- array(2) { ["false"]=> bool(false) @@ -274,7 +245,7 @@ array(2) { ["true"]=> bool(true) } --- Iterator 16 -- +-- Iterator 15 -- array(3) { [""]=> string(6) "emptys" @@ -291,45 +262,41 @@ array(3) { ["emptys"]=> string(0) "" } --- Iterator 17 -- -array(6) { +-- Iterator 16 -- +array(4) { [1]=> string(0) "" [2]=> string(0) "" - [3]=> - NULL - [4]=> - NULL [5]=> bool(false) [6]=> bool(true) } -array(6) { +array(4) { [1]=> string(0) "" [2]=> string(0) "" - [3]=> - NULL - [4]=> - NULL [5]=> bool(false) [6]=> bool(true) } --- Iterator 18 -- -array(1) { +-- Iterator 17 -- +array(2) { + [""]=> + int(2) [0]=> int(5) } -array(1) { +array(2) { + [""]=> + int(2) [0]=> int(5) } --- Iterator 19 -- +-- Iterator 18 -- array(0) { } array(0) { diff --git a/ext/standard/tests/array/array_intersect_variation4.phpt b/ext/standard/tests/array/array_intersect_variation4.phpt index ce0fa47b03f38..cb41dcd029049 100644 --- a/ext/standard/tests/array/array_intersect_variation4.phpt +++ b/ext/standard/tests/array/array_intersect_variation4.phpt @@ -25,13 +25,6 @@ the lazy dog This is a double quoted string EOT; -// heredoc with different whitespaces -$diff_whitespaces = <<22 @@ -43,10 +36,10 @@ EOT; // array to be passsed to $arr1 argument $arr1 = array ( 1, 1.1, "hello", "one", NULL, 2, - 'world', true, false, false => 5, 'aaaa\r', "aaaa\r", - $numeric_string, $diff_whitespaces, + 'world', true, false, false => 5, 'aaaa\n', "aaaa\n", + $numeric_string, "one" => "ten", 4 => "four", "two" => 2, 2 => "two", - '', null => "null", '' => 'emptys' + '', '' => 'emptys' ); // arrays to be passed to $arr2 argument @@ -56,9 +49,9 @@ $arrays = array ( array(false,true), // array with default keys and boolean values array(), // empty array /*5*/ array(NULL), // array with NULL - array("a\v\f","aaaa\r","b","b\tbbb","c","\[\]\!\@\#\$\%\^\&\*\(\)\{\}"), // array with double quoted strings - array('a\v\f','aaaa\r','b','b\tbbb','c','\[\]\!\@\#\$\%\^\&\*\(\)\{\}'), // array with single quoted strings - array($blank_line, $multiline_string, $diff_whitespaces, $numeric_string), // array with heredocs + array("a\v\f","aaaa\n","b","b\tbbb","c","\[\]\!\@\#\$\%\^\&\*\(\)\{\}"), // array with double quoted strings + array('a\v\f','aaaa\n','b','b\tbbb','c','\[\]\!\@\#\$\%\^\&\*\(\)\{\}'), // array with single quoted strings + array($blank_line, $multiline_string, $numeric_string), // array with heredocs // associative arrays /*9*/ array(1 => "one", 2 => "two", 3 => "three"), // explicit numeric keys, string values @@ -68,11 +61,11 @@ $arrays = array ( array("one" => 1, 2 => "two", 4 => "four"), //mixed // associative array, containing null/empty/boolean values as key/value -/*14*/ array(NULL => "NULL", null => "null", "NULL" => NULL, "null" => null), +/*14*/ array(true => "true", false => "false", "false" => false, "true" => true), array("" => "emptyd", '' => 'emptys', "emptyd" => "", 'emptys' => ''), - array(1 => '', 2 => "", 3 => NULL, 4 => null, 5 => false, 6 => true), - array('' => 1, "" => 2, NULL => 3, null => 4, false => 5, true => 6), + array(1 => '', 2 => "", 5 => false, 6 => true), + array('' => 1, "" => 2, false => 5, true => 6), // array with repetitive keys /*19*/ array("One" => 1, "two" => 2, "One" => 10, "two" => 20, "three" => 3) @@ -128,7 +121,7 @@ array(3) { bool(true) [8]=> bool(false) - [13]=> + [12]=> string(0) "" } array(3) { @@ -136,7 +129,7 @@ array(3) { bool(true) [8]=> bool(false) - [13]=> + [12]=> string(0) "" } -- Iteration 4 -- @@ -148,59 +141,51 @@ array(0) { array(2) { [8]=> bool(false) - [13]=> + [12]=> string(0) "" } array(2) { [8]=> bool(false) - [13]=> + [12]=> string(0) "" } -- Iteration 6 -- array(1) { [10]=> - string(5) "aaaa " + string(5) "aaaa +" } array(1) { [10]=> - string(5) "aaaa " + string(5) "aaaa +" } -- Iteration 7 -- array(1) { [9]=> - string(6) "aaaa\r" + string(6) "aaaa\n" } array(1) { [9]=> - string(6) "aaaa\r" + string(6) "aaaa\n" } -- Iteration 8 -- -array(2) { +array(1) { [11]=> string(90) "11 < 12. 123 >22 'single quoted string' "double quoted string" 2222 != 1111. 0000 = 0000 " - [12]=> - string(88) "hello world -1111 != 2222 -heredoc -double quoted string. with different white spaces" } -array(2) { +array(1) { [11]=> string(90) "11 < 12. 123 >22 'single quoted string' "double quoted string" 2222 != 1111. 0000 = 0000 " - [12]=> - string(88) "hello world -1111 != 2222 -heredoc -double quoted string. with different white spaces" } -- Iteration 9 -- array(2) { @@ -264,25 +249,12 @@ array(3) { bool(true) } -- Iteration 14 -- -array(2) { - [8]=> - bool(false) - [13]=> - string(0) "" -} -array(2) { - [8]=> - bool(false) - [13]=> - string(0) "" -} --- Iteration 15 -- array(3) { [7]=> bool(true) [8]=> bool(false) - [13]=> + [12]=> string(0) "" } array(3) { @@ -290,14 +262,14 @@ array(3) { bool(true) [8]=> bool(false) - [13]=> + [12]=> string(0) "" } --- Iteration 16 -- +-- Iteration 15 -- array(3) { [8]=> bool(false) - [13]=> + [12]=> string(0) "" [""]=> string(6) "emptys" @@ -305,18 +277,18 @@ array(3) { array(3) { [8]=> bool(false) - [13]=> + [12]=> string(0) "" [""]=> string(6) "emptys" } --- Iteration 17 -- +-- Iteration 16 -- array(3) { [7]=> bool(true) [8]=> bool(false) - [13]=> + [12]=> string(0) "" } array(3) { @@ -324,19 +296,27 @@ array(3) { bool(true) [8]=> bool(false) - [13]=> + [12]=> string(0) "" } --- Iteration 18 -- -array(1) { +-- Iteration 17 -- +array(3) { [0]=> int(5) + [5]=> + int(2) + ["two"]=> + int(2) } -array(1) { +array(3) { [0]=> int(5) + [5]=> + int(2) + ["two"]=> + int(2) } --- Iteration 19 -- +-- Iteration 18 -- array(0) { } array(0) { diff --git a/ext/standard/tests/array/array_intersect_variation5.phpt b/ext/standard/tests/array/array_intersect_variation5.phpt index 12edea88196e6..f394a030bd78e 100644 --- a/ext/standard/tests/array/array_intersect_variation5.phpt +++ b/ext/standard/tests/array/array_intersect_variation5.phpt @@ -10,10 +10,6 @@ Test array_intersect() function : usage variations - assoc array with diff keys echo "*** Testing array_intersect() : assoc array with diff keys to \$arr1 argument ***\n"; -// get an unset variable -$unset_var = 10; -unset ($unset_var); - // get a heredoc string $heredoc = << 2.2, "pen\n" => 33), array("hello", $heredoc => "string"), // heredoc - // array with unset variable -/*10*/ array( @$unset_var => "hello"), - // array with mixed keys /*11*/ array('hello' => 1, "fruit" => 2.2, 133 => "int", - @$unset_var => "unset", $heredoc => "heredoc") + $heredoc => "heredoc") ); // array to be passed to $arr2 argument @@ -135,15 +128,6 @@ array(2) { string(6) "string" } -- Iterator 8 -- -array(1) { - [""]=> - string(5) "hello" -} -array(1) { - [""]=> - string(5) "hello" -} --- Iterator 9 -- array(2) { ["hello"]=> int(1) diff --git a/ext/standard/tests/array/array_intersect_variation6.phpt b/ext/standard/tests/array/array_intersect_variation6.phpt index 93ff4271d70a9..7bad0b25b9580 100644 --- a/ext/standard/tests/array/array_intersect_variation6.phpt +++ b/ext/standard/tests/array/array_intersect_variation6.phpt @@ -10,10 +10,6 @@ Test array_intersect() function : usage variations - assoc array with diff keys echo "*** Testing array_intersect() : assoc array with diff keys to \$arr2 argument ***\n"; -// get an unset variable -$unset_var = 10; -unset ($unset_var); - // get a heredoc string $heredoc = << 2.2, "pen\n" => 33), array("hello", $heredoc => "string"), // heredoc - // array with unset variable -/*10*/ array( @$unset_var => "hello"), - // array with mixed keys /*11*/ array('hello' => 1, "fruit" => 2.2, 133 => "int", - @$unset_var => "unset", $heredoc => "heredoc") + $heredoc => "heredoc") ); // array to be passed to $arr1 argument @@ -135,15 +128,6 @@ array(2) { string(6) "string" } -- Iterator 8 -- -array(1) { - [3]=> - string(5) "hello" -} -array(1) { - [3]=> - string(5) "hello" -} --- Iterator 9 -- array(2) { [0]=> int(1) diff --git a/ext/standard/tests/array/array_key_exists.phpt b/ext/standard/tests/array/array_key_exists.phpt index 8cc2f9c5207c2..92373b04bb450 100644 --- a/ext/standard/tests/array/array_key_exists.phpt +++ b/ext/standard/tests/array/array_key_exists.phpt @@ -44,7 +44,7 @@ $search_arrays_v = array ( array(), array(NULL), array(array(), 1, 2), - array(1,2,3, "" => "value", NULL => "value", true => "value" ), + array(1,2,3, "" => "value", true => "value" ), array( array(2,4,5), array ("a","b","d") ) ); // search for $key_variations in each sub array of $search_arrays_v @@ -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/array_key_exists_variation8.phpt b/ext/standard/tests/array/array_key_exists_variation8.phpt index 417b56aae8453..23a7212bbae1d 100644 --- a/ext/standard/tests/array/array_key_exists_variation8.phpt +++ b/ext/standard/tests/array/array_key_exists_variation8.phpt @@ -10,10 +10,6 @@ Test array_key_exists() function : usage variations - array keys are different d echo "*** Testing array_key_exists() : usage variations ***\n"; -//get an unset variable -$unset_var = 10; -unset ($unset_var); - // heredoc string $heredoc = << 'negative', ), - // null data -/*3*/ 'null uppercase' => array( - NULL => 'null 1', - ), - 'null lowercase' => array( - null => 'null 2', - ), - // boolean data /*4*/ 'bool lowercase' => array( true => 'lowert', false => 'lowerf', ), - 'bool uppercase' => array( - TRUE => 'uppert', - FALSE => 'upperf', - ), // empty data -/*5*/ 'empty double quotes' => array( - "" => 'emptyd', - ), - 'empty single quotes' => array( +/*5*/ 'empty single quotes' => array( '' => 'emptys', ), @@ -62,22 +43,12 @@ $inputs = array( 'strings' => 'strings', $heredoc => 'stringh', ), - - // undefined data -/*8*/ 'undefined' => array( - @$undefined_var => 'undefined', - ), - - // unset data -/*9*/ 'unset' => array( - @$unset_var => 'unset', - ), ); // loop through each element of $inputs to check the behavior of array_key_exists() $iterator = 1; foreach($inputs as $type => $input) { - echo "\n-- Iteration $iterator: $type data --\n"; + echo "\n-- $type data --\n"; //iterate over again to get all different key values foreach ($inputs as $new_type => $new_input) { @@ -94,293 +65,67 @@ echo "Done"; --EXPECT-- *** Testing array_key_exists() : usage variations *** --- Iteration 1: int data -- +-- int data -- -- $key arguments are int data: bool(true) bool(true) bool(true) bool(true) --- $key arguments are null uppercase data: -bool(false) --- $key arguments are null lowercase data: -bool(false) -- $key arguments are bool lowercase data: bool(true) bool(true) --- $key arguments are bool uppercase data: -bool(true) -bool(true) --- $key arguments are empty double quotes data: -bool(false) -- $key arguments are empty single quotes data: bool(false) -- $key arguments are string data: bool(false) bool(false) bool(false) --- $key arguments are undefined data: -bool(false) --- $key arguments are unset data: -bool(false) --- Iteration 2: null uppercase data -- +-- bool lowercase data -- -- $key arguments are int data: -bool(false) -bool(false) -bool(false) -bool(false) --- $key arguments are null uppercase data: -bool(true) --- $key arguments are null lowercase data: -bool(true) --- $key arguments are bool lowercase data: -bool(false) -bool(false) --- $key arguments are bool uppercase data: -bool(false) -bool(false) --- $key arguments are empty double quotes data: -bool(true) --- $key arguments are empty single quotes data: -bool(true) --- $key arguments are string data: -bool(false) -bool(false) -bool(false) --- $key arguments are undefined data: -bool(true) --- $key arguments are unset data: -bool(true) - --- Iteration 3: null lowercase data -- --- $key arguments are int data: -bool(false) -bool(false) -bool(false) -bool(false) --- $key arguments are null uppercase data: bool(true) --- $key arguments are null lowercase data: bool(true) --- $key arguments are bool lowercase data: -bool(false) -bool(false) --- $key arguments are bool uppercase data: -bool(false) -bool(false) --- $key arguments are empty double quotes data: -bool(true) --- $key arguments are empty single quotes data: -bool(true) --- $key arguments are string data: -bool(false) -bool(false) -bool(false) --- $key arguments are undefined data: -bool(true) --- $key arguments are unset data: -bool(true) - --- Iteration 4: bool lowercase data -- --- $key arguments are int data: -bool(true) -bool(true) -bool(false) -bool(false) --- $key arguments are null uppercase data: -bool(false) --- $key arguments are null lowercase data: -bool(false) --- $key arguments are bool lowercase data: -bool(true) -bool(true) --- $key arguments are bool uppercase data: -bool(true) -bool(true) --- $key arguments are empty double quotes data: -bool(false) --- $key arguments are empty single quotes data: -bool(false) --- $key arguments are string data: -bool(false) -bool(false) -bool(false) --- $key arguments are undefined data: -bool(false) --- $key arguments are unset data: -bool(false) - --- Iteration 5: bool uppercase data -- --- $key arguments are int data: -bool(true) -bool(true) -bool(false) -bool(false) --- $key arguments are null uppercase data: bool(false) --- $key arguments are null lowercase data: bool(false) -- $key arguments are bool lowercase data: bool(true) bool(true) --- $key arguments are bool uppercase data: -bool(true) -bool(true) --- $key arguments are empty double quotes data: -bool(false) -- $key arguments are empty single quotes data: bool(false) -- $key arguments are string data: bool(false) bool(false) bool(false) --- $key arguments are undefined data: -bool(false) --- $key arguments are unset data: -bool(false) --- Iteration 6: empty double quotes data -- +-- empty single quotes data -- -- $key arguments are int data: bool(false) bool(false) bool(false) bool(false) --- $key arguments are null uppercase data: -bool(true) --- $key arguments are null lowercase data: -bool(true) -- $key arguments are bool lowercase data: bool(false) bool(false) --- $key arguments are bool uppercase data: -bool(false) -bool(false) --- $key arguments are empty double quotes data: -bool(true) -- $key arguments are empty single quotes data: bool(true) -- $key arguments are string data: bool(false) bool(false) bool(false) --- $key arguments are undefined data: -bool(true) --- $key arguments are unset data: -bool(true) --- Iteration 7: empty single quotes data -- +-- string data -- -- $key arguments are int data: bool(false) bool(false) bool(false) bool(false) --- $key arguments are null uppercase data: -bool(true) --- $key arguments are null lowercase data: -bool(true) -- $key arguments are bool lowercase data: bool(false) bool(false) --- $key arguments are bool uppercase data: -bool(false) -bool(false) --- $key arguments are empty double quotes data: -bool(true) --- $key arguments are empty single quotes data: -bool(true) --- $key arguments are string data: -bool(false) -bool(false) -bool(false) --- $key arguments are undefined data: -bool(true) --- $key arguments are unset data: -bool(true) - --- Iteration 8: string data -- --- $key arguments are int data: -bool(false) -bool(false) -bool(false) -bool(false) --- $key arguments are null uppercase data: -bool(false) --- $key arguments are null lowercase data: -bool(false) --- $key arguments are bool lowercase data: -bool(false) -bool(false) --- $key arguments are bool uppercase data: -bool(false) -bool(false) --- $key arguments are empty double quotes data: -bool(false) -- $key arguments are empty single quotes data: bool(false) -- $key arguments are string data: bool(true) bool(true) bool(true) --- $key arguments are undefined data: -bool(false) --- $key arguments are unset data: -bool(false) - --- Iteration 9: undefined data -- --- $key arguments are int data: -bool(false) -bool(false) -bool(false) -bool(false) --- $key arguments are null uppercase data: -bool(true) --- $key arguments are null lowercase data: -bool(true) --- $key arguments are bool lowercase data: -bool(false) -bool(false) --- $key arguments are bool uppercase data: -bool(false) -bool(false) --- $key arguments are empty double quotes data: -bool(true) --- $key arguments are empty single quotes data: -bool(true) --- $key arguments are string data: -bool(false) -bool(false) -bool(false) --- $key arguments are undefined data: -bool(true) --- $key arguments are unset data: -bool(true) - --- Iteration 10: unset data -- --- $key arguments are int data: -bool(false) -bool(false) -bool(false) -bool(false) --- $key arguments are null uppercase data: -bool(true) --- $key arguments are null lowercase data: -bool(true) --- $key arguments are bool lowercase data: -bool(false) -bool(false) --- $key arguments are bool uppercase data: -bool(false) -bool(false) --- $key arguments are empty double quotes data: -bool(true) --- $key arguments are empty single quotes data: -bool(true) --- $key arguments are string data: -bool(false) -bool(false) -bool(false) --- $key arguments are undefined data: -bool(true) --- $key arguments are unset data: -bool(true) Done diff --git a/ext/standard/tests/array/array_key_first.phpt b/ext/standard/tests/array/array_key_first.phpt index d3360f6bfe9fc..c0aa1d770097e 100644 --- a/ext/standard/tests/array/array_key_first.phpt +++ b/ext/standard/tests/array/array_key_first.phpt @@ -15,7 +15,7 @@ $mixed_array = array( array( "1" => "one", "2" => "two", "3" => "three", "4" => "four", "5" => "five" ), array( 1 => "one", 2 => "two", 3 => 7, 4 => "four", 5 => "five" ), array( "f" => "fff", "1" => "one", 4 => 6, "" => "blank", 2 => "float", "F" => "FFF", - "blank" => "", 3 => 3.7, 5 => 7, 6 => 8.6, '5' => "Five", "4name" => "jonny", "a" => NULL, NULL => 3 ), + "blank" => "", 3 => 3.7, 5 => 7, 6 => 8.6, '5' => "Five", "4name" => "jonny", "a" => NULL ), array( 12, "name", 'age', '45' ), array( array("oNe", "tWo", 4), array(10, 20, 30, 40, 50), array() ), array( "one" => 1, "one" => 2, "three" => 3, 3, 4, 3 => 33, 4 => 44, 5, 6, @@ -174,7 +174,7 @@ array(12) { [4]=> int(6) [""]=> - int(3) + string(5) "blank" [2]=> string(5) "float" ["F"]=> diff --git a/ext/standard/tests/array/array_key_last.phpt b/ext/standard/tests/array/array_key_last.phpt index c325be6560029..14c4bfe9a2e69 100644 --- a/ext/standard/tests/array/array_key_last.phpt +++ b/ext/standard/tests/array/array_key_last.phpt @@ -15,7 +15,7 @@ $mixed_array = array( array( "1" => "one", "2" => "two", "3" => "three", "4" => "four", "5" => "five" ), array( 1 => "one", 2 => "two", 3 => 7, 4 => "four", 5 => "five" ), array( "f" => "fff", "1" => "one", 4 => 6, "" => "blank", 2 => "float", "F" => "FFF", - "blank" => "", 3 => 3.7, 5 => 7, 6 => 8.6, '5' => "Five", "4name" => "jonny", "a" => NULL, NULL => 3 ), + "blank" => "", 3 => 3.7, 5 => 7, 6 => 8.6, '5' => "Five", "4name" => "jonny", "a" => NULL ), array( 12, "name", 'age', '45' ), array( array("oNe", "tWo", 4), array(10, 20, 30, 40, 50), array() ), array( "one" => 1, "one" => 2, "three" => 3, 3, 4, 3 => 33, 4 => 44, 5, 6, @@ -174,7 +174,7 @@ array(12) { [4]=> int(6) [""]=> - int(3) + string(5) "blank" [2]=> string(5) "float" ["F"]=> diff --git a/ext/standard/tests/array/array_keys_variation_001.phpt b/ext/standard/tests/array/array_keys_variation_001.phpt index fdba88afbdd5f..4727beefa073e 100644 --- a/ext/standard/tests/array/array_keys_variation_001.phpt +++ b/ext/standard/tests/array/array_keys_variation_001.phpt @@ -14,7 +14,7 @@ $arrays = array( array("a" => 1, "b" => 2, "c" =>3, "d" => array()), array(0 => 0, 1 => 1, 2 => 2, 3 => 3), array(0 =>3.000, 1 =>2, 1 =>3, "a"=>3, 3=>5, "5"=>3.000), - array(TRUE => TRUE, FALSE => FALSE, NULL => NULL, "\x000", "\000"), + array(TRUE => TRUE, FALSE => FALSE, "\x000", "\000"), array("a" => "abcd", "a" => "", "ab" => -6, "cd" => -0.5 ), array(0 => array(), 1=> array(0), 2 => array(1), ""=> array(),""=>"" ) ); @@ -110,16 +110,14 @@ array(5) { } -- Iteration 9 -- -array(5) { +array(4) { [0]=> int(1) [1]=> int(0) [2]=> - string(0) "" - [3]=> int(2) - [4]=> + [3]=> int(3) } diff --git a/ext/standard/tests/array/array_map_variation3.phpt b/ext/standard/tests/array/array_map_variation3.phpt index e252c5a7c5a5f..10b1793df0252 100644 --- a/ext/standard/tests/array/array_map_variation3.phpt +++ b/ext/standard/tests/array/array_map_variation3.phpt @@ -31,11 +31,11 @@ $arrays = array ( array("one" => 1, 2 => "two", 4 => "four"), //mixed // associative array, containing null/empty/boolean values as key/value -/*13*/ array(NULL => "NULL", null => "null", "NULL" => NULL, "null" => null), +/*13*/ array(true => "true", false => "false", "false" => false, "true" => true), array("" => "emptyd", '' => 'emptys', "emptyd" => "", 'emptys' => ''), - array(1 => '', 2 => "", 3 => NULL, 4 => null, 5 => false, 6 => true), - array('' => 1, "" => 2, NULL => 3, null => 4, false => 5, true => 6), + array(1 => '', 2 => "", 5 => false, 6 => true), + array('' => 1, "" => 2, false => 5, true => 6), // array with repetitive keys /*18*/ array("One" => 1, "two" => 2, "One" => 10, "two" => 20, "three" => 3) @@ -158,15 +158,6 @@ array(3) { string(4) "four" } -- Iteration 13 -- -array(3) { - [""]=> - string(4) "null" - ["NULL"]=> - NULL - ["null"]=> - NULL -} --- Iteration 14 -- array(4) { [1]=> string(4) "true" @@ -177,7 +168,7 @@ array(4) { ["true"]=> bool(true) } --- Iteration 15 -- +-- Iteration 14 -- array(3) { [""]=> string(6) "emptys" @@ -186,31 +177,27 @@ array(3) { ["emptys"]=> string(0) "" } --- Iteration 16 -- -array(6) { +-- Iteration 15 -- +array(4) { [1]=> string(0) "" [2]=> string(0) "" - [3]=> - NULL - [4]=> - NULL [5]=> bool(false) [6]=> bool(true) } --- Iteration 17 -- +-- Iteration 16 -- array(3) { [""]=> - int(4) + int(2) [0]=> int(5) [1]=> int(6) } --- Iteration 18 -- +-- Iteration 17 -- array(3) { ["One"]=> int(10) diff --git a/ext/standard/tests/array/array_map_variation4.phpt b/ext/standard/tests/array/array_map_variation4.phpt index d75a0bcf26108..2062588fc4e51 100644 --- a/ext/standard/tests/array/array_map_variation4.phpt +++ b/ext/standard/tests/array/array_map_variation4.phpt @@ -46,12 +46,12 @@ $arrays = array ( array("hello", $heredoc => "string"), // heredoc // array with object, unset variable and resource variable - array(@$unset_var => "hello", STDERR => 'resource'), + array(STDERR => 'resource'), // array with mixed values /*11*/ array('hello' => 1, "fruit" => 2.2, STDERR => 'resource', 133 => "int", - @$unset_var => "unset", $heredoc => "heredoc") + $heredoc => "heredoc") ); // loop through the various elements of $arrays to test array_map() @@ -125,14 +125,12 @@ array(2) { string(6) "string" } -- Iteration 8 -- -array(2) { - [""]=> - string(5) "hello" +array(1) { [3]=> string(8) "resource" } -- Iteration 9 -- -array(6) { +array(5) { ["hello"]=> int(1) ["fruit"]=> @@ -141,8 +139,6 @@ array(6) { string(8) "resource" [133]=> string(3) "int" - [""]=> - string(5) "unset" ["Hello world"]=> string(7) "heredoc" } diff --git a/ext/standard/tests/array/array_map_variation7.phpt b/ext/standard/tests/array/array_map_variation7.phpt index 30e6f9d91d613..811219b6bb83d 100644 --- a/ext/standard/tests/array/array_map_variation7.phpt +++ b/ext/standard/tests/array/array_map_variation7.phpt @@ -27,7 +27,7 @@ var_dump( array_map('callback', array(), array(1, 2, 3), array('a', 'b')) ); // echo "Done"; ?> ---EXPECT-- +--EXPECTF-- *** Testing array_map() : arrays with diff. size *** array(3) { [0]=> @@ -46,6 +46,12 @@ array(3) { NULL } } + +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 + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d array(3) { [0]=> array(1) { @@ -97,6 +103,12 @@ array(3) { NULL } } + +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 + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d array(3) { [0]=> array(1) { diff --git a/ext/standard/tests/array/array_merge_recursive_variation3.phpt b/ext/standard/tests/array/array_merge_recursive_variation3.phpt index 214d7654426b9..a7f746d1076ac 100644 --- a/ext/standard/tests/array/array_merge_recursive_variation3.phpt +++ b/ext/standard/tests/array/array_merge_recursive_variation3.phpt @@ -27,7 +27,7 @@ EOT; // heredoc with different whitespaces $diff_whitespaces = << $blank_line, "h2" => $multiline_string, "h3" => $diff_whitespaces), // with heredocs // associative arrays @@ -59,11 +59,11 @@ $arrays = array ( array("one" => 1, 2 => "two", 4 => "four"), //mixed // associative array, containing null/empty/boolean values as key/value -/*14*/ array(NULL => "NULL", null => "null", "NULL" => NULL, "null" => null), +/*14*/ array(true => "true", false => "false", "false" => false, "true" => true), array("" => "emptyd", '' => 'emptys', "emptyd" => "", 'emptys' => ''), - array(1 => '', 2 => "", 3 => NULL, 4 => null, 5 => false, 6 => true), - array('' => 1, "" => 2, NULL => 3, null => 4, false => 5, true => 6), + array(1 => '', 2 => "", 5 => false, 6 => true), + array('' => 1, "" => 2, false => 5, true => 6), // array containing embedded arrays /*15*/ array("str1", "array" => array("hello", 'world'), array(1, 2)) @@ -236,7 +236,8 @@ array(4) { [0]=> string(3) "a " [1]=> - string(5) "aaaa " + string(5) "aaaa +" [2]=> string(1) "b" [3]=> @@ -247,7 +248,8 @@ array(8) { [0]=> string(3) "a " [1]=> - string(5) "aaaa " + string(5) "aaaa +" [2]=> string(1) "b" [3]=> @@ -274,7 +276,7 @@ array(4) { [0]=> string(5) "a\v\f" [1]=> - string(6) "aaaa\r" + string(6) "aaaa\n" [2]=> string(1) "b" [3]=> @@ -285,7 +287,7 @@ array(8) { [0]=> string(5) "a\v\f" [1]=> - string(6) "aaaa\r" + string(6) "aaaa\n" [2]=> string(1) "b" [3]=> @@ -318,7 +320,8 @@ The quick brown fox jumped over; the lazy dog This is a double quoted string" ["h3"]=> - string(88) "hello world + string(88) "hello + world 1111 != 2222 heredoc double quoted string. with different white spaces" @@ -334,7 +337,8 @@ The quick brown fox jumped over; the lazy dog This is a double quoted string" ["h3"]=> - string(88) "hello world + string(88) "hello + world 1111 != 2222 heredoc double quoted string. with different white spaces" @@ -518,40 +522,6 @@ array(7) { } -- Iteration 14 -- -- With default argument -- -array(3) { - [""]=> - string(4) "null" - ["NULL"]=> - NULL - ["null"]=> - NULL -} --- With more arguments -- -array(7) { - [""]=> - string(4) "null" - ["NULL"]=> - NULL - ["null"]=> - NULL - [0]=> - string(3) "one" - [1]=> - int(2) - ["string"]=> - string(5) "hello" - ["array"]=> - array(3) { - [0]=> - string(1) "a" - [1]=> - string(1) "b" - [2]=> - string(1) "c" - } -} --- Iteration 15 -- --- With default argument -- array(4) { [0]=> string(4) "true" @@ -588,7 +558,7 @@ array(8) { string(1) "c" } } --- Iteration 16 -- +-- Iteration 15 -- -- With default argument -- array(3) { [""]=> @@ -622,39 +592,31 @@ array(7) { string(1) "c" } } --- Iteration 17 -- +-- Iteration 16 -- -- With default argument -- -array(6) { +array(4) { [0]=> string(0) "" [1]=> string(0) "" [2]=> - NULL - [3]=> - NULL - [4]=> bool(false) - [5]=> + [3]=> bool(true) } -- With more arguments -- -array(10) { +array(8) { [0]=> string(0) "" [1]=> string(0) "" [2]=> - NULL - [3]=> - NULL - [4]=> bool(false) - [5]=> + [3]=> bool(true) - [6]=> + [4]=> string(3) "one" - [7]=> + [5]=> int(2) ["string"]=> string(5) "hello" @@ -668,11 +630,11 @@ array(10) { string(1) "c" } } --- Iteration 18 -- +-- Iteration 17 -- -- With default argument -- array(3) { [""]=> - int(4) + int(2) [0]=> int(5) [1]=> @@ -681,7 +643,7 @@ array(3) { -- With more arguments -- array(7) { [""]=> - int(4) + int(2) [0]=> int(5) [1]=> @@ -702,7 +664,7 @@ array(7) { string(1) "c" } } --- Iteration 19 -- +-- Iteration 18 -- -- With default argument -- array(3) { [0]=> diff --git a/ext/standard/tests/array/array_merge_recursive_variation4.phpt b/ext/standard/tests/array/array_merge_recursive_variation4.phpt index 71f4a4d66fbcc..e5dcc5b9cc25a 100644 --- a/ext/standard/tests/array/array_merge_recursive_variation4.phpt +++ b/ext/standard/tests/array/array_merge_recursive_variation4.phpt @@ -9,10 +9,6 @@ Test array_merge_recursive() function : usage variations - associative array wit echo "*** Testing array_merge_recursive() : assoc. array with diff. keys to \$arr1 argument ***\n"; -// get an unset variable -$unset_var = 10; -unset ($unset_var); - // get a resource variable $fp = fopen(__FILE__, "r"); @@ -41,7 +37,7 @@ $arrays = array ( array("hello", $heredoc => array("heredoc", 'string'), "string"), // array with object, unset variable and resource variable -/*8*/ array(@$unset_var => array("unset"), $fp => 'resource', 11, "hello") +/*8*/ array($fp => 'resource', 11, "hello") ); // initialise the second array @@ -292,12 +288,7 @@ array(7) { } -- Iteration 6 -- -- With default argument -- -array(4) { - [""]=> - array(1) { - [0]=> - string(5) "unset" - } +array(3) { [0]=> string(8) "resource" [1]=> @@ -306,12 +297,7 @@ array(4) { string(5) "hello" } -- With more arguments -- -array(8) { - [""]=> - array(1) { - [0]=> - string(5) "unset" - } +array(7) { [0]=> string(8) "resource" [1]=> diff --git a/ext/standard/tests/array/array_merge_variation4.phpt b/ext/standard/tests/array/array_merge_variation4.phpt index e34bf73526886..ad4ee5b248170 100644 --- a/ext/standard/tests/array/array_merge_variation4.phpt +++ b/ext/standard/tests/array/array_merge_variation4.phpt @@ -12,10 +12,6 @@ echo "*** Testing array_merge() : usage variations ***\n"; // Initialise function arguments not being substituted $arr = array ('one' => 1, 'two' => 2); -//get an unset variable -$unset_var = 10; -unset ($unset_var); - // heredoc string $heredoc = << 'negative', ), - // null data -/*4*/ 'null uppercase' => array( - NULL => 'null 1', - ), - -/*5*/ 'null lowercase' => array( - null => 'null 2', - ), - // boolean data /*6*/ 'bool lowercase' => array( true => 'lowert', false => 'lowerf', ), -/*7*/ 'bool uppercase' => array( - TRUE => 'uppert', - FALSE => 'upperf', - ), - // empty data -/*8*/ 'empty double quotes' => array( - "" => 'emptyd', - ), - /*9*/ 'empty single quotes' => array( '' => 'emptys', ), @@ -67,16 +45,6 @@ $inputs = array( 'strings' => 'strings', $heredoc => 'stringh', ), - - // undefined data -/*11*/ 'undefined' => array( - @$undefined_var => 'undefined', - ), - - // unset data -/*12*/ 'unset' => array( - @$unset_var => 'unset', - ), ); // loop through each element of $inputs to check the behavior of array_merge @@ -123,43 +91,7 @@ array(6) { string(8) "negative" } --- Iteration 2: null uppercase data -- -array(3) { - [""]=> - string(6) "null 1" - ["one"]=> - int(1) - ["two"]=> - int(2) -} -array(3) { - ["one"]=> - int(1) - ["two"]=> - int(2) - [""]=> - string(6) "null 1" -} - --- Iteration 3: null lowercase data -- -array(3) { - [""]=> - string(6) "null 2" - ["one"]=> - int(1) - ["two"]=> - int(2) -} -array(3) { - ["one"]=> - int(1) - ["two"]=> - int(2) - [""]=> - string(6) "null 2" -} - --- Iteration 4: bool lowercase data -- +-- Iteration 2: bool lowercase data -- array(4) { [0]=> string(6) "lowert" @@ -181,47 +113,7 @@ array(4) { string(6) "lowerf" } --- Iteration 5: bool uppercase data -- -array(4) { - [0]=> - string(6) "uppert" - [1]=> - string(6) "upperf" - ["one"]=> - int(1) - ["two"]=> - int(2) -} -array(4) { - ["one"]=> - int(1) - ["two"]=> - int(2) - [0]=> - string(6) "uppert" - [1]=> - string(6) "upperf" -} - --- Iteration 6: empty double quotes data -- -array(3) { - [""]=> - string(6) "emptyd" - ["one"]=> - int(1) - ["two"]=> - int(2) -} -array(3) { - ["one"]=> - int(1) - ["two"]=> - int(2) - [""]=> - string(6) "emptyd" -} - --- Iteration 7: empty single quotes data -- +-- Iteration 3: empty single quotes data -- array(3) { [""]=> string(6) "emptys" @@ -239,7 +131,7 @@ array(3) { string(6) "emptys" } --- Iteration 8: string data -- +-- Iteration 4: string data -- array(5) { ["stringd"]=> string(7) "stringd" @@ -264,40 +156,4 @@ array(5) { ["hello world"]=> string(7) "stringh" } - --- Iteration 9: undefined data -- -array(3) { - [""]=> - string(9) "undefined" - ["one"]=> - int(1) - ["two"]=> - int(2) -} -array(3) { - ["one"]=> - int(1) - ["two"]=> - int(2) - [""]=> - string(9) "undefined" -} - --- Iteration 10: unset data -- -array(3) { - [""]=> - string(5) "unset" - ["one"]=> - int(1) - ["two"]=> - int(2) -} -array(3) { - ["one"]=> - int(1) - ["two"]=> - int(2) - [""]=> - string(5) "unset" -} Done diff --git a/ext/standard/tests/array/array_merge_variation7.phpt b/ext/standard/tests/array/array_merge_variation7.phpt index a196effc75bdc..546206872730e 100644 --- a/ext/standard/tests/array/array_merge_variation7.phpt +++ b/ext/standard/tests/array/array_merge_variation7.phpt @@ -11,7 +11,7 @@ echo "*** Testing array_merge() : usage variations ***\n"; //mixed keys $arr1 = array('zero', 20 => 'twenty', 'thirty' => 30, true => 'bool'); -$arr2 = array(0, 1, 2, null => 'null', 0 => 'float'); +$arr2 = array(0, 1, 2, 0 => 'float'); var_dump(array_merge($arr1, $arr2)); var_dump(array_merge($arr2, $arr1)); @@ -20,7 +20,7 @@ echo "Done"; ?> --EXPECT-- *** Testing array_merge() : usage variations *** -array(8) { +array(7) { [0]=> string(4) "zero" [1]=> @@ -35,18 +35,14 @@ array(8) { int(1) [5]=> int(2) - [""]=> - string(4) "null" } -array(8) { +array(7) { [0]=> string(5) "float" [1]=> int(1) [2]=> int(2) - [""]=> - string(4) "null" [3]=> string(4) "zero" [4]=> diff --git a/ext/standard/tests/array/array_pad_variation6.phpt b/ext/standard/tests/array/array_pad_variation6.phpt index fc2d705dbe0f2..800f03ca91533 100644 --- a/ext/standard/tests/array/array_pad_variation6.phpt +++ b/ext/standard/tests/array/array_pad_variation6.phpt @@ -28,7 +28,7 @@ EOT; // heredoc with different whitespaces $diff_whitespaces = << $blank_line, "h2" => $multiline_string, "h3" => $diff_whitespaces, $numeric_string), // with heredocs // associative arrays @@ -60,11 +60,11 @@ $inputs = array ( array("one" => 1, 2 => "two", 4 => "four"), //mixed // associative array, containing null/empty/boolean values as key/value -/*14*/ array(NULL => "NULL", null => "null", "NULL" => NULL, "null" => null), +/*14*/ array(true => "true", false => "false", "false" => false, "true" => true), array("" => "emptyd", '' => 'emptys', "emptyd" => "", 'emptys' => ''), - array(1 => '', 2 => "", 3 => NULL, 4 => null, 5 => false, 6 => true), - array('' => 1, "" => 2, NULL => 3, null => 4, false => 5, true => 6), + array(1 => '', 2 => "", 5 => false, 6 => true), + array('' => 1, "" => 2, false => 5, true => 6), // array with repetitive keys /*19*/ array("One" => 1, "two" => 2, "One" => 10, "two" => 20, "three" => 3) @@ -237,7 +237,8 @@ array(6) { [0]=> string(3) "a " [1]=> - string(5) "aaaa " + string(5) "aaaa +" [2]=> string(5) "b bbb" [3]=> @@ -255,7 +256,8 @@ array(6) { [2]=> string(3) "a " [3]=> - string(5) "aaaa " + string(5) "aaaa +" [4]=> string(5) "b bbb" [5]=> @@ -266,7 +268,7 @@ array(6) { [0]=> string(5) "a\v\f" [1]=> - string(6) "aaaa\r" + string(6) "aaaa\n" [2]=> string(6) "b\tbbb" [3]=> @@ -284,7 +286,7 @@ array(6) { [2]=> string(5) "a\v\f" [3]=> - string(6) "aaaa\r" + string(6) "aaaa\n" [4]=> string(6) "b\tbbb" [5]=> @@ -301,7 +303,8 @@ The big brown fox jumped over; the lazy dog This is a double quoted string" ["h3"]=> - string(88) "hello world + string(88) "hello + world 1111 != 2222 heredoc double quoted string. with different white spaces" @@ -330,7 +333,8 @@ The big brown fox jumped over; the lazy dog This is a double quoted string" ["h3"]=> - string(88) "hello world + string(88) "hello + world 1111 != 2222 heredoc double quoted string. with different white spaces" @@ -487,35 +491,6 @@ array(6) { string(4) "four" } -- Iteration 14 -- -array(6) { - [""]=> - string(4) "null" - ["NULL"]=> - NULL - ["null"]=> - NULL - [0]=> - string(5) "HELLO" - [1]=> - string(5) "HELLO" - [2]=> - string(5) "HELLO" -} -array(6) { - [0]=> - string(5) "HELLO" - [1]=> - string(5) "HELLO" - [2]=> - string(5) "HELLO" - [""]=> - string(4) "null" - ["NULL"]=> - NULL - ["null"]=> - NULL -} --- Iteration 15 -- array(6) { [0]=> string(4) "true" @@ -544,7 +519,7 @@ array(6) { ["true"]=> bool(true) } --- Iteration 16 -- +-- Iteration 15 -- array(6) { [""]=> string(6) "emptys" @@ -573,39 +548,39 @@ array(6) { ["emptys"]=> string(0) "" } --- Iteration 17 -- +-- Iteration 16 -- array(6) { + [0]=> + string(0) "" [1]=> string(0) "" [2]=> - string(0) "" + bool(false) [3]=> - NULL + bool(true) [4]=> - NULL + string(5) "HELLO" [5]=> - bool(false) - [6]=> - bool(true) + string(5) "HELLO" } array(6) { + [0]=> + string(5) "HELLO" [1]=> - string(0) "" + string(5) "HELLO" [2]=> string(0) "" [3]=> - NULL + string(0) "" [4]=> - NULL - [5]=> bool(false) - [6]=> + [5]=> bool(true) } --- Iteration 18 -- +-- Iteration 17 -- array(6) { [""]=> - int(4) + int(2) [0]=> int(5) [1]=> @@ -625,13 +600,13 @@ array(6) { [2]=> string(5) "HELLO" [""]=> - int(4) + int(2) [3]=> int(5) [4]=> int(6) } --- Iteration 19 -- +-- Iteration 18 -- array(6) { ["One"]=> int(10) diff --git a/ext/standard/tests/array/array_pop.phpt b/ext/standard/tests/array/array_pop.phpt index 2066f1acb6673..7125a3e6f7f32 100644 --- a/ext/standard/tests/array/array_pop.phpt +++ b/ext/standard/tests/array/array_pop.phpt @@ -18,7 +18,7 @@ $mixed_array = array( array( "1" => "one", "2" => "two", "3" => "three", "4" => "four", "5" => "five" ), array( 1 => "one", 2 => "two", 3 => 7, 4 => "four", 5 => "five" ), array( "f" => "fff", "1" => "one", 4 => 6, "" => "blank", 2 => "float", "F" => "FFF", - "blank" => "", 3 => 3.7, 5 => 7, 6 => 8.6, '5' => "Five", "4name" => "jonny", "a" => NULL, NULL => 3 ), + "blank" => "", 3 => 3.7, 5 => 7, 6 => 8.6, '5' => "Five", "4name" => "jonny", "a" => NULL ), array( 12, "name", 'age', '45' ), array( array("oNe", "tWo", 4), array(10, 20, 30, 40, 50), array() ), array( "one" => 1, "one" => 2, "three" => 3, 3, 4, 3 => 33, 4 => 44, 5, 6, @@ -175,7 +175,7 @@ array(12) { [4]=> int(6) [""]=> - int(3) + string(5) "blank" [2]=> string(5) "float" ["F"]=> diff --git a/ext/standard/tests/array/array_pop_variation.phpt b/ext/standard/tests/array/array_pop_variation.phpt index af8b0cc0f9a9e..c36f17baf0a6e 100644 --- a/ext/standard/tests/array/array_pop_variation.phpt +++ b/ext/standard/tests/array/array_pop_variation.phpt @@ -13,7 +13,7 @@ $mixed_array = array( array( "1" => "one", "2" => "two", "3" => "three", "4" => "four", "5" => "five" ), array( 1 => "one", 2 => "two", 3 => 7, 4 => "four", 5 => "five" ), array( "f" => "fff", "1" => "one", 4 => 6, "" => "blank", 2 => "float", "F" => "FFF", - "blank" => "", 3 => 3.7, 5 => 7, 6 => 8.6, '5' => "Five", "4name" => "jonny", "a" => NULL, NULL => 3 ), + "blank" => "", 3 => 3.7, 5 => 7, 6 => 8.6, '5' => "Five", "4name" => "jonny", "a" => NULL ), array( 12, "name", 'age', '45' ), array( array("oNe", "tWo", 4), array(10, 20, 30, 40, 50), array() ), array( "one" => 1, "one" => 2, "three" => 3, 3, 4, 3 => 33, 4 => 44, 5, 6, diff --git a/ext/standard/tests/array/array_push.phpt b/ext/standard/tests/array/array_push.phpt index 1c560adc518ac..f65f4b35e8d0c 100644 --- a/ext/standard/tests/array/array_push.phpt +++ b/ext/standard/tests/array/array_push.phpt @@ -18,7 +18,7 @@ $mixed_array = array( array( "1" => "one", "2" => "two", "3" => "three", "4" => "four", "5" => "five" ), array( 1 => "one", 2 => "two", 3 => 7, 4 => "four", 5 => "five" ), array( "f" => "fff", "1" => "one", 4 => 6, "" => "blank", 2 => "float", "F" => "FFF", - "blank" => "", 3 => 3.7, 5 => 7, 6 => 8.6, '5' => "Five", "4name" => "jonny", "a" => NULL, NULL => 3 ), + "blank" => "", 3 => 3.7, 5 => 7, 6 => 8.6, '5' => "Five", "4name" => "jonny", "a" => NULL), array( 12, "name", 'age', '45' ), array( array("oNe", "tWo", 4), array(10, 20, 30, 40, 50), array() ), array( "one" => 1, "one" => 2, "three" => 3, 3, 4, 3 => 33, 4 => 44, 5, 6, @@ -198,7 +198,7 @@ array(12) { [4]=> int(6) [""]=> - int(3) + string(5) "blank" [2]=> string(5) "float" ["F"]=> diff --git a/ext/standard/tests/array/array_push_variation6.phpt b/ext/standard/tests/array/array_push_variation6.phpt index 610e4efaa0e3e..38801e75da571 100644 --- a/ext/standard/tests/array/array_push_variation6.phpt +++ b/ext/standard/tests/array/array_push_variation6.phpt @@ -11,10 +11,6 @@ echo "*** Testing array_push() : usage variations ***\n"; // Initialise function arguments not being substituted $var = 'value'; -//get an unset variable -$unset_var = 10; -unset ($unset_var); - // heredoc string $heredoc = << 'negative', ), - // null data -/*3*/ 'null uppercase' => array( - NULL => 'null 1', - ), - 'null lowercase' => array( - null => 'null 2', - ), - // boolean data /*4*/ 'bool lowercase' => array( true => 'lowert', false => 'lowerf', ), - 'bool uppercase' => array( - TRUE => 'uppert', - FALSE => 'upperf', - ), // empty data -/*5*/ 'empty double quotes' => array( - "" => 'emptyd', - ), 'empty single quotes' => array( '' => 'emptys', ), @@ -63,27 +44,15 @@ $inputs = array( 'strings' => 'strings', $heredoc => 'stringh', ), - - // undefined data -/*8*/ 'undefined' => array( - @$undefined_var => 'undefined', - ), - - // unset data -/*9*/ 'unset' => array( - @$unset_var => 'unset', - ), ); // loop through each sub-array of $inputs to check the behavior of array_push() -$iterator = 1; foreach($inputs as $key => $input) { - echo "\n-- Iteration $iterator : $key data --\n"; + echo "\n-- $key data --\n"; echo "Before : "; var_dump(count($input)); echo "After : "; var_dump( array_push($input, $var) ); - $iterator++; }; echo "Done"; @@ -91,43 +60,19 @@ echo "Done"; --EXPECT-- *** Testing array_push() : usage variations *** --- Iteration 1 : int data -- +-- int data -- Before : int(4) After : int(5) --- Iteration 2 : null uppercase data -- -Before : int(1) -After : int(2) - --- Iteration 3 : null lowercase data -- -Before : int(1) -After : int(2) - --- Iteration 4 : bool lowercase data -- +-- bool lowercase data -- Before : int(2) After : int(3) --- Iteration 5 : bool uppercase data -- -Before : int(2) -After : int(3) - --- Iteration 6 : empty double quotes data -- -Before : int(1) -After : int(2) - --- Iteration 7 : empty single quotes data -- +-- empty single quotes data -- Before : int(1) After : int(2) --- Iteration 8 : string data -- +-- string data -- Before : int(3) After : int(4) - --- Iteration 9 : undefined data -- -Before : int(1) -After : int(2) - --- Iteration 10 : unset data -- -Before : int(1) -After : int(2) Done diff --git a/ext/standard/tests/array/array_reverse_variation3.phpt b/ext/standard/tests/array/array_reverse_variation3.phpt index b5c222684ee6f..087c10ba8dd10 100644 --- a/ext/standard/tests/array/array_reverse_variation3.phpt +++ b/ext/standard/tests/array/array_reverse_variation3.phpt @@ -9,10 +9,6 @@ Test array_reverse() function : usage variations - different array values for 'a echo "*** Testing array_reverse() : usage variations ***\n"; -//get an unset variable -$unset_var = 10; -unset ($unset_var); - //get a resource variable $fp = fopen(__FILE__, "r"); @@ -46,11 +42,11 @@ $arrays = array ( array("one" => 1, 2 => "two", 4 => "four"), //mixed // associative array, containing null/empty/boolean values as key/value -/*13*/ array(NULL => "NULL", null => "null", "NULL" => NULL, "null" => null), +/*13*/ array(true => "true", false => "false", "false" => false, "true" => true), array("" => "emptyd", '' => 'emptys', "emptyd" => "", 'emptys' => ''), - array(1 => '', 2 => "", 3 => NULL, 4 => null, 5 => false, 6 => true), - array('' => 1, "" => 2, NULL => 3, null => 4, false => 5, true => 6), + array(1 => '', 2 => "", 5 => false, 6 => true), + array('' => 1, "" => 2, false => 5, true => 6), // array with repetitive keys /*18*/ array("One" => 1, "two" => 2, "One" => 10, "two" => 20, "three" => 3) @@ -404,34 +400,6 @@ array(3) { } -- Iteration 13 -- - with default argument - -array(3) { - ["null"]=> - NULL - ["NULL"]=> - NULL - [""]=> - string(4) "null" -} -- with $preserve keys = true - -array(3) { - ["null"]=> - NULL - ["NULL"]=> - NULL - [""]=> - string(4) "null" -} -- with $preserve_keys = false - -array(3) { - ["null"]=> - NULL - ["NULL"]=> - NULL - [""]=> - string(4) "null" -} --- Iteration 14 -- -- with default argument - array(4) { ["true"]=> bool(true) @@ -464,7 +432,7 @@ array(4) { [1]=> string(4) "true" } --- Iteration 15 -- +-- Iteration 14 -- - with default argument - array(3) { ["emptys"]=> @@ -492,53 +460,41 @@ array(3) { [""]=> string(6) "emptys" } --- Iteration 16 -- +-- Iteration 15 -- - with default argument - -array(6) { +array(4) { [0]=> bool(true) [1]=> bool(false) [2]=> - NULL - [3]=> - NULL - [4]=> string(0) "" - [5]=> + [3]=> string(0) "" } - with $preserve keys = true - -array(6) { +array(4) { [6]=> bool(true) [5]=> bool(false) - [4]=> - NULL - [3]=> - NULL [2]=> string(0) "" [1]=> string(0) "" } - with $preserve_keys = false - -array(6) { +array(4) { [0]=> bool(true) [1]=> bool(false) [2]=> - NULL - [3]=> - NULL - [4]=> string(0) "" - [5]=> + [3]=> string(0) "" } --- Iteration 17 -- +-- Iteration 16 -- - with default argument - array(3) { [0]=> @@ -546,7 +502,7 @@ array(3) { [1]=> int(5) [""]=> - int(4) + int(2) } - with $preserve keys = true - array(3) { @@ -555,7 +511,7 @@ array(3) { [0]=> int(5) [""]=> - int(4) + int(2) } - with $preserve_keys = false - array(3) { @@ -564,9 +520,9 @@ array(3) { [1]=> int(5) [""]=> - int(4) + int(2) } --- Iteration 18 -- +-- Iteration 17 -- - with default argument - array(3) { ["three"]=> diff --git a/ext/standard/tests/array/array_reverse_variation4.phpt b/ext/standard/tests/array/array_reverse_variation4.phpt index 4967f6e4dacb0..2cf8d3a68d2f2 100644 --- a/ext/standard/tests/array/array_reverse_variation4.phpt +++ b/ext/standard/tests/array/array_reverse_variation4.phpt @@ -9,10 +9,6 @@ Test array_reverse() function : usage variations - assoc. array with diff. keys echo "*** Testing array_reverse() : usage variations ***\n"; -//get an unset variable -$unset_var = 10; -unset ($unset_var); - //get a class class classA{ public function __toString(){ @@ -42,10 +38,10 @@ $arrays = array ( array("hello", $heredoc => "string"), // heredoc // array with object, unset variable and resource variable - array(@$unset_var => "hello", STDERR => 'resource'), + array(STDERR => 'resource'), // array with mixed values -/*11*/ array('hello' => 1, "fruit" => 2.2, STDERR => 'resource', 133 => "int", @$unset_var => "unset", $heredoc => "heredoc") +/*11*/ array('hello' => 1, "fruit" => 2.2, STDERR => 'resource', 133 => "int", $heredoc => "heredoc") ); // loop through the various elements of $arrays to test array_reverse() @@ -245,33 +241,25 @@ array(2) { } -- Iteration 8 -- - default argument - -array(2) { +array(1) { [0]=> string(8) "resource" - [""]=> - string(5) "hello" } - $preserve keys = true - -array(2) { +array(1) { [3]=> string(8) "resource" - [""]=> - string(5) "hello" } - $preserve_keys = false - -array(2) { +array(1) { [0]=> string(8) "resource" - [""]=> - string(5) "hello" } -- Iteration 9 -- - default argument - -array(6) { +array(5) { ["Hello world"]=> string(7) "heredoc" - [""]=> - string(5) "unset" [0]=> string(3) "int" [1]=> @@ -282,11 +270,9 @@ array(6) { int(1) } - $preserve keys = true - -array(6) { +array(5) { ["Hello world"]=> string(7) "heredoc" - [""]=> - string(5) "unset" [133]=> string(3) "int" [3]=> @@ -297,11 +283,9 @@ array(6) { int(1) } - $preserve_keys = false - -array(6) { +array(5) { ["Hello world"]=> string(7) "heredoc" - [""]=> - string(5) "unset" [0]=> string(3) "int" [1]=> diff --git a/ext/standard/tests/array/array_search_variation2.phpt b/ext/standard/tests/array/array_search_variation2.phpt index c391989f320d9..1f1cec9b64b5e 100644 --- a/ext/standard/tests/array/array_search_variation2.phpt +++ b/ext/standard/tests/array/array_search_variation2.phpt @@ -15,7 +15,7 @@ $misc_array = array ( 0 =>"-.08", "e" =>"5", "y" =>NULL, - NULL =>"", + '' =>"", 0, TRUE, FALSE, diff --git a/ext/standard/tests/array/array_shift_variation3.phpt b/ext/standard/tests/array/array_shift_variation3.phpt index e43bc86858d78..3949015612184 100644 --- a/ext/standard/tests/array/array_shift_variation3.phpt +++ b/ext/standard/tests/array/array_shift_variation3.phpt @@ -8,10 +8,6 @@ Test array_shift() function : usage variations - Pass array with different data echo "*** Testing array_shift() : usage variations ***\n"; -//get an unset variable -$unset_var = 10; -unset ($unset_var); - // heredoc string $heredoc = << 'negative', ), - // null data -/*4*/ 'null uppercase' => array( - NULL => 'null 1', - ), - -/*5*/ 'null lowercase' => array( - null => 'null 2', - ), - // boolean data /*6*/ 'bool lowercase' => array( true => 'lowert', false => 'lowerf', ), -/*7*/ 'bool uppercase' => array( - TRUE => 'uppert', - FALSE => 'upperf', - ), - // empty data -/*8*/ 'empty double quotes' => array( - "" => 'emptyd', - ), /*9*/ 'empty single quotes' => array( '' => 'emptys', @@ -63,16 +42,6 @@ $inputs = array( 'strings' => 'strings', $heredoc => 'stringh', ), - - // undefined data -/*11*/ 'undefined' => array( - @$undefined_var => 'undefined', - ), - - // unset data -/*12*/ 'unset' => array( - @$unset_var => 'unset', - ), ); // loop through each element of $inputs to check the behavior of array_shift() @@ -100,41 +69,19 @@ array(3) { string(8) "negative" } --- Iteration 2 : null uppercase data -- -string(6) "null 1" -array(0) { -} - --- Iteration 3 : null lowercase data -- -string(6) "null 2" -array(0) { -} - --- Iteration 4 : bool lowercase data -- +-- Iteration 2 : bool lowercase data -- string(6) "lowert" array(1) { [0]=> string(6) "lowerf" } --- Iteration 5 : bool uppercase data -- -string(6) "uppert" -array(1) { - [0]=> - string(6) "upperf" -} - --- Iteration 6 : empty double quotes data -- -string(6) "emptyd" -array(0) { -} - --- Iteration 7 : empty single quotes data -- +-- Iteration 3 : empty single quotes data -- string(6) "emptys" array(0) { } --- Iteration 8 : string data -- +-- Iteration 4 : string data -- string(7) "stringd" array(2) { ["strings"]=> @@ -142,14 +89,4 @@ array(2) { ["hello world"]=> string(7) "stringh" } - --- Iteration 9 : undefined data -- -string(9) "undefined" -array(0) { -} - --- Iteration 10 : unset data -- -string(5) "unset" -array(0) { -} Done diff --git a/ext/standard/tests/array/array_slice_variation7.phpt b/ext/standard/tests/array/array_slice_variation7.phpt index d0db376ad5830..53cf70e185780 100644 --- a/ext/standard/tests/array/array_slice_variation7.phpt +++ b/ext/standard/tests/array/array_slice_variation7.phpt @@ -13,10 +13,6 @@ echo "*** Testing array_slice() : usage variations ***\n"; $offset = 0; $length = 10; // to ensure all elements are displayed -//get an unset variable -$unset_var = 10; -unset ($unset_var); - // heredoc string $heredoc = << 'negative', ), - // null data -/*4*/ 'null uppercase' => array( - NULL => 'null 1', - ), - -/*5*/ 'null lowercase' => array( - null => 'null 2', - ), - // boolean data /*6*/ 'bool lowercase' => array( true => 'lowert', false => 'lowerf', ), -/*7*/ 'bool uppercase' => array( - TRUE => 'uppert', - FALSE => 'upperf', - ), - // empty data -/*8*/ 'empty double quotes' => array( - "" => 'emptyd', - ), /*9*/ 'empty single quotes' => array( '' => 'emptys', @@ -68,16 +47,6 @@ $inputs = array( 'strings' => 'strings', $heredoc => 'stringh', ), - - // undefined data -/*11*/ 'undefined' => array( - @$undefined_var => 'undefined', - ), - - // unset data -/*12*/ 'unset' => array( - @$unset_var => 'unset', - ), ); // loop through each element of $inputs to check the behavior of array_slice() @@ -120,31 +89,7 @@ array(4) { string(8) "negative" } --- Iteration 2 : key type is null uppercase -- -$preserve_keys = TRUE -array(1) { - [""]=> - string(6) "null 1" -} -$preserve_keys = FALSE -array(1) { - [""]=> - string(6) "null 1" -} - --- Iteration 3 : key type is null lowercase -- -$preserve_keys = TRUE -array(1) { - [""]=> - string(6) "null 2" -} -$preserve_keys = FALSE -array(1) { - [""]=> - string(6) "null 2" -} - --- Iteration 4 : key type is bool lowercase -- +-- Iteration 2 : key type is bool lowercase -- $preserve_keys = TRUE array(2) { [1]=> @@ -160,35 +105,7 @@ array(2) { string(6) "lowerf" } --- Iteration 5 : key type is bool uppercase -- -$preserve_keys = TRUE -array(2) { - [1]=> - string(6) "uppert" - [0]=> - string(6) "upperf" -} -$preserve_keys = FALSE -array(2) { - [0]=> - string(6) "uppert" - [1]=> - string(6) "upperf" -} - --- Iteration 6 : key type is empty double quotes -- -$preserve_keys = TRUE -array(1) { - [""]=> - string(6) "emptyd" -} -$preserve_keys = FALSE -array(1) { - [""]=> - string(6) "emptyd" -} - --- Iteration 7 : key type is empty single quotes -- +-- Iteration 3 : key type is empty single quotes -- $preserve_keys = TRUE array(1) { [""]=> @@ -200,7 +117,7 @@ array(1) { string(6) "emptys" } --- Iteration 8 : key type is string -- +-- Iteration 4 : key type is string -- $preserve_keys = TRUE array(3) { ["stringd"]=> @@ -219,28 +136,4 @@ array(3) { ["hello world"]=> string(7) "stringh" } - --- Iteration 9 : key type is undefined -- -$preserve_keys = TRUE -array(1) { - [""]=> - string(9) "undefined" -} -$preserve_keys = FALSE -array(1) { - [""]=> - string(9) "undefined" -} - --- Iteration 10 : key type is unset -- -$preserve_keys = TRUE -array(1) { - [""]=> - string(5) "unset" -} -$preserve_keys = FALSE -array(1) { - [""]=> - string(5) "unset" -} Done diff --git a/ext/standard/tests/array/array_unique_variation2.phpt b/ext/standard/tests/array/array_unique_variation2.phpt index 6a9d8e36fd2bc..ca6b33434044b 100644 --- a/ext/standard/tests/array/array_unique_variation2.phpt +++ b/ext/standard/tests/array/array_unique_variation2.phpt @@ -26,7 +26,7 @@ EOT; // heredoc with different whitespaces $diff_whitespaces = << $blank_line, "h2" => $multiline_string, "h3" => $diff_whitespaces, $blank_line), // with heredocs // associative arrays @@ -58,11 +58,11 @@ $inputs = array ( array("one" => 1, 2 => "two", 4 => "four"), //mixed // associative array, containing null/empty/boolean values as key/value -/*14*/ array(NULL => "NULL", null => "null", "NULL" => NULL, "null" => null), +/*14*/ array(true => "true", false => "false", "false" => false, "true" => true), array("" => "emptyd", '' => 'emptys', "emptyd" => "", 'emptys' => ''), - array(1 => '', 2 => "", 3 => NULL, 4 => null, 5 => false, 6 => true), -/*18*/ array('' => 1, "" => 2, NULL => 3, null => 4, false => 5, true => 6), + array(1 => '', 2 => "", 5 => false, 6 => true), +/*18*/ array('' => 1, "" => 2, false => 5, true => 6), ); // loop through each sub-array of $inputs to check the behavior of array_unique() @@ -111,7 +111,8 @@ array(4) { [0]=> string(3) "a " [1]=> - string(5) "aaaa " + string(5) "aaaa +" [2]=> string(1) "b" [4]=> @@ -122,7 +123,7 @@ array(4) { [0]=> string(5) "a\v\f" [1]=> - string(6) "aaaa\r" + string(6) "aaaa\n" [2]=> string(1) "b" [4]=> @@ -139,7 +140,8 @@ The quick brown fox jumped over; the lazy dog This is a double quoted string" ["h3"]=> - string(88) "hello world + string(88) "hello + world 1111 != 2222 heredoc double quoted string. with different white spaces" @@ -184,13 +186,6 @@ array(3) { string(4) "four" } -- Iteration 14 -- -array(2) { - [""]=> - string(4) "null" - ["NULL"]=> - NULL -} --- Iteration 15 -- array(4) { [1]=> string(4) "true" @@ -201,24 +196,24 @@ array(4) { ["true"]=> bool(true) } --- Iteration 16 -- +-- Iteration 15 -- array(2) { [""]=> string(6) "emptys" ["emptyd"]=> string(0) "" } --- Iteration 17 -- +-- Iteration 16 -- array(2) { [1]=> string(0) "" [6]=> bool(true) } --- Iteration 18 -- +-- Iteration 17 -- array(3) { [""]=> - int(4) + int(2) [0]=> int(5) [1]=> diff --git a/ext/standard/tests/array/array_unique_variation3.phpt b/ext/standard/tests/array/array_unique_variation3.phpt index 91b551bb60402..3c1b0f2e35ff7 100644 --- a/ext/standard/tests/array/array_unique_variation3.phpt +++ b/ext/standard/tests/array/array_unique_variation3.phpt @@ -9,10 +9,6 @@ Test array_unique() function : usage variations - associative array with differe echo "*** Testing array_unique() : assoc. array with diff. keys passed to \$input argument ***\n"; -// get an unset variable -$unset_var = 10; -unset ($unset_var); - // get a class class classA { @@ -38,7 +34,7 @@ $inputs = array ( array("hello", $heredoc => "string", "string"), // array with object, unset variable and resource variable -/*8*/ array(@$unset_var => "hello", STDERR => 'resource', 11, "hello"), +/*8*/ array(STDERR => 'resource', 11, "hello"), ); // loop through each sub-array of $inputs to check the behavior of array_unique() @@ -96,11 +92,11 @@ array(2) { } -- Iteration 6 -- array(3) { - [""]=> - string(5) "hello" [3]=> string(8) "resource" [4]=> int(11) + [5]=> + string(5) "hello" } Done diff --git a/ext/standard/tests/array/array_unshift_variation3.phpt b/ext/standard/tests/array/array_unshift_variation3.phpt index 75e39600e1f8a..7af0690d75758 100644 --- a/ext/standard/tests/array/array_unshift_variation3.phpt +++ b/ext/standard/tests/array/array_unshift_variation3.phpt @@ -29,12 +29,11 @@ $arrays = array ( array( "one" => "ten", "two" => "twenty", "three" => "thirty"), // string key/value array("one" => 1, 2 => "two", 4 => "four"), //mixed - // associative array, containing null/empty/boolean values as key/value -/*13*/ array(NULL => "NULL", null => "null", "NULL" => NULL, "null" => null), - array(true => "true", false => "false", "false" => false, "true" => true), + // associative array, containing empty/boolean values as key/value +/*13*/ array(true => "true", false => "false", "false" => false, "true" => true), array("" => "emptyd", '' => 'emptys', "emptyd" => "", 'emptys' => ''), - array(1 => '', 2 => "", 3 => NULL, 4 => null, 5 => false, 6 => true), - array('' => 1, "" => 2, NULL => 3, null => 4, false => 5, true => 6), + array(1 => '', 2 => "", 5 => false, 6 => true), + array('' => 1, "" => 2, false => 5, true => 6), // array with repetitive keys /*18*/ array("One" => 1, "two" => 2, "One" => 10, "two" => 20, "three" => 3) @@ -386,33 +385,6 @@ array(6) { string(4) "four" } -- Iteration 13 -- -int(4) -array(4) { - [0]=> - int(10) - [""]=> - string(4) "null" - ["NULL"]=> - NULL - ["null"]=> - NULL -} -int(6) -array(6) { - [0]=> - int(10) - [1]=> - string(5) "hello" - [2]=> - string(5) "world" - [""]=> - string(4) "null" - ["NULL"]=> - NULL - ["null"]=> - NULL -} --- Iteration 14 -- int(5) array(5) { [0]=> @@ -443,7 +415,7 @@ array(7) { ["true"]=> bool(true) } --- Iteration 15 -- +-- Iteration 14 -- int(4) array(4) { [0]=> @@ -470,9 +442,9 @@ array(6) { ["emptys"]=> string(0) "" } --- Iteration 16 -- -int(7) -array(7) { +-- Iteration 15 -- +int(5) +array(5) { [0]=> int(10) [1]=> @@ -480,16 +452,12 @@ array(7) { [2]=> string(0) "" [3]=> - NULL - [4]=> - NULL - [5]=> bool(false) - [6]=> + [4]=> bool(true) } -int(9) -array(9) { +int(7) +array(7) { [0]=> int(10) [1]=> @@ -501,21 +469,17 @@ array(9) { [4]=> string(0) "" [5]=> - NULL - [6]=> - NULL - [7]=> bool(false) - [8]=> + [6]=> bool(true) } --- Iteration 17 -- +-- Iteration 16 -- int(4) array(4) { [0]=> int(10) [""]=> - int(4) + int(2) [1]=> int(5) [2]=> @@ -530,13 +494,13 @@ array(6) { [2]=> string(5) "world" [""]=> - int(4) + int(2) [3]=> int(5) [4]=> int(6) } --- Iteration 18 -- +-- Iteration 17 -- int(4) array(4) { [0]=> diff --git a/ext/standard/tests/array/array_unshift_variation4.phpt b/ext/standard/tests/array/array_unshift_variation4.phpt index ed89e06311776..2af08f15717e6 100644 --- a/ext/standard/tests/array/array_unshift_variation4.phpt +++ b/ext/standard/tests/array/array_unshift_variation4.phpt @@ -10,10 +10,6 @@ Test array_unshift() function : usage variations - assoc. array with diff. keys echo "*** Testing array_unshift() : associative array with different keys ***\n"; -//get an unset variable -$unset_var = 10; -unset ($unset_var); - //get a resource variable $fp = fopen(__FILE__, "r"); @@ -52,12 +48,12 @@ $arrays = array ( array("hello", $heredoc => "string"), // heredoc // array with object, unset variable and resource variable - array(@$unset_var => "hello", $fp => 'resource'), + array($fp => 'resource'), // array with mixed keys /*11*/ array('hello' => 1, "fruit" => 2.2, $fp => 'resource', 133 => "int", - @$unset_var => "unset", $heredoc => "heredoc") + $heredoc => "heredoc") ); // loop through the various elements of $arrays to test array_unshift() @@ -265,31 +261,27 @@ array(5) { string(6) "string" } -- Iteration 8 -- -int(3) -array(3) { +int(2) +array(2) { [0]=> int(10) - [""]=> - string(5) "hello" [1]=> string(8) "resource" } -int(5) -array(5) { +int(4) +array(4) { [0]=> int(10) [1]=> string(5) "hello" [2]=> string(5) "world" - [""]=> - string(5) "hello" [3]=> string(8) "resource" } -- Iteration 9 -- -int(7) -array(7) { +int(6) +array(6) { [0]=> int(10) ["hello"]=> @@ -300,13 +292,11 @@ array(7) { string(8) "resource" [2]=> string(3) "int" - [""]=> - string(5) "unset" ["Hello world"]=> string(7) "heredoc" } -int(9) -array(9) { +int(8) +array(8) { [0]=> int(10) [1]=> @@ -321,8 +311,6 @@ array(9) { string(8) "resource" [4]=> string(3) "int" - [""]=> - string(5) "unset" ["Hello world"]=> string(7) "heredoc" } diff --git a/ext/standard/tests/array/array_values_variation3.phpt b/ext/standard/tests/array/array_values_variation3.phpt index 4d09a31fb8eef..e7ee302b3d159 100644 --- a/ext/standard/tests/array/array_values_variation3.phpt +++ b/ext/standard/tests/array/array_values_variation3.phpt @@ -9,10 +9,6 @@ Test array_values() function : usage variations - array keys different data type echo "*** Testing array_values() : usage variations ***\n"; -//get an unset variable -$unset_var = 10; -unset ($unset_var); - // heredoc string $heredoc = << 'negative', ), - // null data -/*4*/ 'null uppercase' => array( - NULL => 'null 1', - ), - -/*5*/ 'null lowercase' => array( - null => 'null 2', - ), - // boolean data /*6*/ 'bool lowercase' => array( true => 'lowert', false => 'lowerf', ), -/*7*/ 'bool uppercase' => array( - TRUE => 'uppert', - FALSE => 'upperf', - ), - - // empty data -/*8*/ 'empty double quotes' => array( - "" => 'emptyd', - ), - /*9*/ 'empty single quotes' => array( '' => 'emptys', ), @@ -64,31 +41,19 @@ $inputs = array( 'strings' => 'strings', $heredoc => 'stringh', ), - - // undefined data -/*11*/ 'undefined' => array( - @$undefined_var => 'undefined', - ), - - // unset data -/*12*/ 'unset' => array( - @$unset_var => 'unset', - ), ); // loop through each element of $inputs to check the behavior of array_values() -$iterator = 1; foreach($inputs as $key => $input) { - echo "\n-- Iteration $iterator: $key data --\n"; + echo "\n-- $key data --\n"; var_dump( array_values($input) ); - $iterator++; }; echo "Done"; ?> --EXPECT-- *** Testing array_values() : usage variations *** --- Iteration 1: int data -- +-- int data -- array(4) { [0]=> string(4) "zero" @@ -100,19 +65,7 @@ array(4) { string(8) "negative" } --- Iteration 2: null uppercase data -- -array(1) { - [0]=> - string(6) "null 1" -} - --- Iteration 3: null lowercase data -- -array(1) { - [0]=> - string(6) "null 2" -} - --- Iteration 4: bool lowercase data -- +-- bool lowercase data -- array(2) { [0]=> string(6) "lowert" @@ -120,27 +73,13 @@ array(2) { string(6) "lowerf" } --- Iteration 5: bool uppercase data -- -array(2) { - [0]=> - string(6) "uppert" - [1]=> - string(6) "upperf" -} - --- Iteration 6: empty double quotes data -- -array(1) { - [0]=> - string(6) "emptyd" -} - --- Iteration 7: empty single quotes data -- +-- empty single quotes data -- array(1) { [0]=> string(6) "emptys" } --- Iteration 8: string data -- +-- string data -- array(3) { [0]=> string(7) "stringd" @@ -149,16 +88,4 @@ array(3) { [2]=> string(7) "stringh" } - --- Iteration 9: undefined data -- -array(1) { - [0]=> - string(9) "undefined" -} - --- Iteration 10: unset data -- -array(1) { - [0]=> - string(5) "unset" -} 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/bug68553.phpt b/ext/standard/tests/array/bug68553.phpt index f16c94699d5af..d309171096c95 100644 --- a/ext/standard/tests/array/bug68553.phpt +++ b/ext/standard/tests/array/bug68553.phpt @@ -37,6 +37,10 @@ try { Warning: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d Deprecated: Implicit conversion from float 7.38 to int loses precision in %s on line %d + +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(8) { [10]=> array(1) { diff --git a/ext/standard/tests/array/count_recursive.phpt b/ext/standard/tests/array/count_recursive.phpt index 27896ba2c7fab..598bbe1efef23 100644 --- a/ext/standard/tests/array/count_recursive.phpt +++ b/ext/standard/tests/array/count_recursive.phpt @@ -17,7 +17,7 @@ print "COUNT_RECURSIVE: should be 6, is ".count($arr, COUNT_RECURSIVE)."\n"; print "-- Testing various types with no second argument --\n"; print "COUNT_NORMAL: should be 2, is ".count(array("a", array("b")))."\n"; -$arr = array('a'=>array(NULL, NULL, NULL), 1=>array(NULL=>1, 1=>NULL), +$arr = array('a'=>array(NULL, NULL, NULL), 1=>array(''=>1, 1=>NULL), array(array(array(array(array(NULL)))))); print "-- Testing really cool arrays --\n"; print "COUNT_NORMAL: should be 3, is ".count($arr, COUNT_NORMAL)."\n"; @@ -27,14 +27,14 @@ echo "\n*** Testing possible variations of count() function on arrays ***"; $count_array = array( array(), array( 1 => "string"), - array( "" => "string", 0 => "a", NULL => "b", -1 => "c", + array( "" => "string", 0 => "a", -1 => "c", array(array(array(NULL)))), array( -2 => 12, array(array(1, 2, array(array("0"))))), array( "a" => 1, "b" => -2.344, "b" => "string", "c" => NULL, "d" => -2.344), array( 4 => 1, 3 => -2.344, "3" => "string", "2" => NULL, 1 => -2.344, array()), array( TRUE => TRUE, FALSE => FALSE, "" => "", " " => " ", - NULL => NULL, "\x000" => "\x000", "\000" => "\000"), + "\x000" => "\x000", "\000" => "\000"), array( NULL, 1 => "Hi", "string" => "hello", array("" => "World", "-2.34" => "a", "0" => "b")) ); diff --git a/ext/standard/tests/array/extract_negative_keys.phpt b/ext/standard/tests/array/extract_negative_keys.phpt new file mode 100644 index 0000000000000..55fce2a656570 --- /dev/null +++ b/ext/standard/tests/array/extract_negative_keys.phpt @@ -0,0 +1,31 @@ +--TEST-- +extract() with negative keys +--FILE-- + 'hello', 'world', 2 => 'positive', 'check' => 'extracted']; + +function foo(array $a) { + extract($a, EXTR_PREFIX_ALL, 'prefix'); + var_dump(get_defined_vars()); +} + +foo($a); +?> +--EXPECT-- +array(3) { + ["a"]=> + array(4) { + [-5]=> + string(5) "hello" + [-4]=> + string(5) "world" + [2]=> + string(8) "positive" + ["check"]=> + string(9) "extracted" + } + ["prefix_2"]=> + string(8) "positive" + ["prefix_check"]=> + string(9) "extracted" +} diff --git a/ext/standard/tests/array/extract_negative_keys2.phpt b/ext/standard/tests/array/extract_negative_keys2.phpt new file mode 100644 index 0000000000000..dd2a1fa7a18a4 --- /dev/null +++ b/ext/standard/tests/array/extract_negative_keys2.phpt @@ -0,0 +1,11 @@ +--TEST-- +extract() with negative keys +--FILE-- + "foo"]; +var_dump(extract($arr, EXTR_PREFIX_ALL | EXTR_REFS, "prefix")); + +?> +--EXPECT-- +int(0) diff --git a/ext/standard/tests/array/extract_variation4.phpt b/ext/standard/tests/array/extract_variation4.phpt index cdbbce225cb04..86dbdcf6419f6 100644 --- a/ext/standard/tests/array/extract_variation4.phpt +++ b/ext/standard/tests/array/extract_variation4.phpt @@ -6,7 +6,7 @@ Test extract() function (variation 4) $mixed_array = array( array( 1 => "one", 2 => "two", 3 => 7, 4 => "four", 5 => "five" ), array( "f" => "fff", "1" => "one", 4 => 6, "" => "blank", 2 => "float", "F" => "FFF", - "blank" => "", 3 => 3.7, 5 => 7, 6 => 8.6, '5' => "Five", "4name" => "jonny", "a" => NULL, NULL => 3 ), + "blank" => "", 3 => 3.7, 5 => 7, 6 => 8.6, '5' => "Five", "4name" => "jonny", "a" => NULL), array( 12, "name", 'age', '45' ), ); diff --git a/ext/standard/tests/array/extract_variation7.phpt b/ext/standard/tests/array/extract_variation7.phpt index 268a24773643c..3cf80c3ecb1e2 100644 --- a/ext/standard/tests/array/extract_variation7.phpt +++ b/ext/standard/tests/array/extract_variation7.phpt @@ -9,7 +9,7 @@ $a = array( "1" => "one", "2" => "two", "3" => "three", "4" => "four", "5" => "f var_dump ( extract($a, EXTR_PREFIX_ALL, "same")); $b = array( "f" => "fff", "1" => "one", 4 => 6, "" => "blank", 2 => "float", "F" => "FFF", - "blank" => "", 3 => 3.7, 5 => 7, 6 => 8.6, '5' => "Five", "4name" => "jonny", "a" => NULL, NULL => 3 ); + "blank" => "", 3 => 3.7, 5 => 7, 6 => 8.6, '5' => "Five", "4name" => "jonny", "a" => NULL); var_dump ( extract($b, EXTR_PREFIX_ALL, "same")); var_dump ( extract($b, EXTR_PREFIX_ALL, "diff")); 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/gh19926.phpt b/ext/standard/tests/array/gh19926.phpt new file mode 100644 index 0000000000000..b714db9eb2b32 --- /dev/null +++ b/ext/standard/tests/array/gh19926.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-19926 (Assertion failure zend_hash_internal_pointer_reset_ex) +--FILE-- + +--EXPECT-- +Exception caught, no assertion failure diff --git a/ext/standard/tests/array/gh19926_pointer.phpt b/ext/standard/tests/array/gh19926_pointer.phpt new file mode 100644 index 0000000000000..c134f3b594b3d --- /dev/null +++ b/ext/standard/tests/array/gh19926_pointer.phpt @@ -0,0 +1,19 @@ +--TEST-- +GH-19926 (internal pointer behavior after array_splice) +--FILE-- + +--EXPECT-- +Before array_splice: int(3) +After array_splice: int(999) diff --git a/ext/standard/tests/array/gh20043.phpt b/ext/standard/tests/array/gh20043.phpt new file mode 100644 index 0000000000000..d5c7e06417f18 --- /dev/null +++ b/ext/standard/tests/array/gh20043.phpt @@ -0,0 +1,12 @@ +--TEST-- +GH-20043 (array_unique assertion failure with RC1 array causing an exception on sort) +--FILE-- +getMessage(); +} +?> +--EXPECT-- +Object of class stdClass could not be converted to string diff --git a/ext/standard/tests/array/in_array_variation2.phpt b/ext/standard/tests/array/in_array_variation2.phpt index 3976232243c48..2b4ac3cfe3a09 100644 --- a/ext/standard/tests/array/in_array_variation2.phpt +++ b/ext/standard/tests/array/in_array_variation2.phpt @@ -14,7 +14,7 @@ $misc_array = array ( 0 =>"-.08", "e" =>"5", "y" =>NULL, - NULL =>"", + '' =>"", 0, TRUE, FALSE, diff --git a/ext/standard/tests/array/key_variation2.phpt b/ext/standard/tests/array/key_variation2.phpt index d1eed890ffc5e..bb0ca07b27383 100644 --- a/ext/standard/tests/array/key_variation2.phpt +++ b/ext/standard/tests/array/key_variation2.phpt @@ -28,31 +28,12 @@ $inputs = array( -2345 => 'negative', ), - // null data -/*4*/ 'null uppercase' => array( - NULL => 'null 1', - ), - -/*5*/ 'null lowercase' => array( - null => 'null 2', - ), - // boolean data /*6*/ 'bool lowercase' => array( true => 'lowert', false => 'lowerf', ), -/*7*/ 'bool uppercase' => array( - TRUE => 'uppert', - FALSE => 'upperf', - ), - - // empty data -/*8*/ 'empty double quotes' => array( - "" => 'emptyd', - ), - /*9*/ 'empty single quotes' => array( '' => 'emptys', ), @@ -63,16 +44,6 @@ $inputs = array( 'strings' => 'strings', $heredoc => 'stringh', ), - - // undefined data -/*11*/ 'undefined' => array( - @$undefined_var => 'undefined', - ), - - // unset data -/*12*/ 'unset' => array( - @$unset_var => 'unset', - ), ); // loop through each element of $inputs to check the behavior of key() @@ -95,33 +66,14 @@ int(1) int(12345) int(-2345) --- Iteration 2 : null uppercase data -- -string(0) "" - --- Iteration 3 : null lowercase data -- -string(0) "" - --- Iteration 4 : bool lowercase data -- -int(1) -int(0) - --- Iteration 5 : bool uppercase data -- +-- Iteration 2 : bool lowercase data -- int(1) int(0) --- Iteration 6 : empty double quotes data -- +-- Iteration 3 : empty single quotes data -- string(0) "" --- Iteration 7 : empty single quotes data -- -string(0) "" - --- Iteration 8 : string data -- +-- Iteration 4 : string data -- string(7) "stringd" string(7) "strings" string(11) "hello world" - --- Iteration 9 : undefined data -- -string(0) "" - --- Iteration 10 : unset data -- -string(0) "" diff --git a/ext/standard/tests/array/range/range_inputs_float_NAN_values.phpt b/ext/standard/tests/array/range/range_inputs_float_NAN_values.phpt index 03ed069fd893a..cbfd2e9144131 100644 --- a/ext/standard/tests/array/range/range_inputs_float_NAN_values.phpt +++ b/ext/standard/tests/array/range/range_inputs_float_NAN_values.phpt @@ -16,9 +16,16 @@ var_dump($f3); $fs = [$f1, $f2, $f3, 5.5]; +function safe_to_string(int|float $number): string { + if (is_nan($number)) { + return 'NAN'; + } + return $number; +} + foreach ($fs as $s) { foreach ($fs as $e) { - echo "range($s, $e);\n"; + echo 'range(', safe_to_string($s), ', ', safe_to_string($e), ");\n"; try { var_dump( range($s, $e) ); } catch (\ValueError $e) { diff --git a/ext/standard/tests/array/sort/arsort_variation11.phpt b/ext/standard/tests/array/sort/arsort_variation11.phpt index b5405ac3d55e6..af72a4599f584 100644 --- a/ext/standard/tests/array/sort/arsort_variation11.phpt +++ b/ext/standard/tests/array/sort/arsort_variation11.phpt @@ -17,7 +17,7 @@ $mixed_values = array ( "sub_array[2,3]" => array(22,-55), "sub_array[2,4]" => array() ), 4 => 4, "4" => "4", 4 => 4.01, "b" => "b", "5" => "5", -2 => -2, -2 => -2.01, - -2 => -2.98989, "-.9" => "-.9", "True" => "True", "" => "", NULL => NULL, + -2 => -2.98989, "-.9" => "-.9", "True" => "True", "" => "", "ab" => "ab", "abcd" => "abcd", 0 => 0.01, -0 => -0, '' => '' , "abcd\x00abcd\x00abcd" => "abcd\x00abcd\x00abcd", 0 => 0.001 ); diff --git a/ext/standard/tests/array/sort/arsort_variation_escape_sequences.phpt b/ext/standard/tests/array/sort/arsort_variation_escape_sequences.phpt index b4a533c42114c..db60f7c93f5a5 100644 --- a/ext/standard/tests/array/sort/arsort_variation_escape_sequences.phpt +++ b/ext/standard/tests/array/sort/arsort_variation_escape_sequences.phpt @@ -14,11 +14,9 @@ const EXPECTED_RESULT = [ "\v" => "\v", "\n" => "\n", "\t" => "\t", - null => null, ]; $array = [ - null => null, "\a" => "\a", "\cx" => "\cx", "\e" => "\e", diff --git a/ext/standard/tests/array/sort/asort_variation11.phpt b/ext/standard/tests/array/sort/asort_variation11.phpt index 82eab55993ac1..e9f3a438e5f12 100644 --- a/ext/standard/tests/array/sort/asort_variation11.phpt +++ b/ext/standard/tests/array/sort/asort_variation11.phpt @@ -17,7 +17,7 @@ $mixed_values = array ( "sub_array[2,3]" => array(22,-55), "sub_array[2,4]" => array() ), 4 => 4, "4" => "4", 4 => 4.01, "b" => "b", "5" => "5", -2 => -2, -2 => -2.01, - -2 => -2.98989, "-.9" => "-.9", "True" => "True", "" => "", NULL => NULL, + -2 => -2.98989, "-.9" => "-.9", "True" => "True", "" => "", "ab" => "ab", "abcd" => "abcd", 0 => 0.01, -0 => -0, '' => '' , "abcd\x00abcd\x00abcd" => "abcd\x00abcd\x00abcd", 0 => 0.001 ); diff --git a/ext/standard/tests/array/sort/asort_variation_escape_sequences.phpt b/ext/standard/tests/array/sort/asort_variation_escape_sequences.phpt index 6de02b66ae0a6..1a33fd197c0fd 100644 --- a/ext/standard/tests/array/sort/asort_variation_escape_sequences.phpt +++ b/ext/standard/tests/array/sort/asort_variation_escape_sequences.phpt @@ -4,7 +4,6 @@ Test asort() function: sorting escape sequences null, "\t" => "\t", "\n" => "\n", "\v" => "\v", @@ -18,7 +17,6 @@ const EXPECTED_RESULT = [ ]; $array = [ - null => null, "\a" => "\a", "\cx" => "\cx", "\e" => "\e", diff --git a/ext/standard/tests/array/sort/krsort_variation8.phpt b/ext/standard/tests/array/sort/krsort_variation8.phpt index 4c1c6f2173d26..9379cf4ec4ff3 100644 --- a/ext/standard/tests/array/sort/krsort_variation8.phpt +++ b/ext/standard/tests/array/sort/krsort_variation8.phpt @@ -18,7 +18,7 @@ $mixed_values = array ( "sub_array[2,3]" => array(22,-55), "sub_array[2,4]" => array() ), 4 => 4, "4" => "4", 4 => 4.01, "b" => "b", "5" => "5", -2 => -2, -2 => -2.01, - -2 => -2.98989, "-.9" => "-.9", "True" => "True", "" => "", NULL => NULL, + -2 => -2.98989, "-.9" => "-.9", "True" => "True", "" => "", "ab" => "ab", "abcd" => "abcd", 0 => 0.01, -0 => -0, '' => '' , "abcd\x00abcd\x00abcd" => "abcd\x00abcd\x00abcd", 0 => 0.001 ); diff --git a/ext/standard/tests/array/sort/krsort_variation_escape_sequences.phpt b/ext/standard/tests/array/sort/krsort_variation_escape_sequences.phpt index ac56df76ed7ca..371980293a0ea 100644 --- a/ext/standard/tests/array/sort/krsort_variation_escape_sequences.phpt +++ b/ext/standard/tests/array/sort/krsort_variation_escape_sequences.phpt @@ -14,11 +14,9 @@ const EXPECTED_RESULT = [ "\v" => "\v", "\n" => "\n", "\t" => "\t", - null => null, ]; $array = [ - null => null, "\a" => "\a", "\cx" => "\cx", "\e" => "\e", diff --git a/ext/standard/tests/array/sort/ksort_variation8.phpt b/ext/standard/tests/array/sort/ksort_variation8.phpt index 236c405c64b95..e04abcfbc4731 100644 --- a/ext/standard/tests/array/sort/ksort_variation8.phpt +++ b/ext/standard/tests/array/sort/ksort_variation8.phpt @@ -17,7 +17,7 @@ $mixed_values = array ( "sub_array[2,3]" => array(22,-55), "sub_array[2,4]" => array() ), 4 => 4, "4" => "4", 4 => 4.01, "b" => "b", "5" => "5", -2 => -2, -2 => -2.01, - -2 => -2.98989, "-.9" => "-.9", "True" => "True", "" => "", NULL => NULL, + -2 => -2.98989, "-.9" => "-.9", "True" => "True", "" => "", "ab" => "ab", "abcd" => "abcd", 0 => 0.01, -0 => -0, '' => '' , "abcd\x00abcd\x00abcd" => "abcd\x00abcd\x00abcd", 0 => 0.001 ); diff --git a/ext/standard/tests/array/sort/ksort_variation_escape_sequences.phpt b/ext/standard/tests/array/sort/ksort_variation_escape_sequences.phpt index e880227b1c9e0..acbcde58defe0 100644 --- a/ext/standard/tests/array/sort/ksort_variation_escape_sequences.phpt +++ b/ext/standard/tests/array/sort/ksort_variation_escape_sequences.phpt @@ -4,7 +4,6 @@ Test ksort() function: sorting escape sequences null, "\t" => "\t", "\n" => "\n", "\v" => "\v", @@ -18,7 +17,6 @@ const EXPECTED_RESULT = [ ]; $array = [ - null => null, "\a" => "\a", "\cx" => "\cx", "\e" => "\e", diff --git a/ext/standard/tests/array/sort/natcasesort_variation11.phpt b/ext/standard/tests/array/sort/natcasesort_variation11.phpt index 5934b5230c51c..bc86669a54520 100644 --- a/ext/standard/tests/array/sort/natcasesort_variation11.phpt +++ b/ext/standard/tests/array/sort/natcasesort_variation11.phpt @@ -8,10 +8,6 @@ Test natcasesort() function : usage variations - Different array keys echo "*** Testing natcasesort() : usage variations ***\n"; -//get an unset variable -$unset_var = 10; -unset ($unset_var); - // heredoc string $heredoc = << 'negative', ), - // null data -/*4*/ 'null uppercase' => array( - NULL => 'null 1', - ), - -/*5*/ 'null lowercase' => array( - null => 'null 2', - ), - // boolean data /*6*/ 'bool lowercase' => array( true => 'lowert', false => 'lowerf', ), -/*7*/ 'bool uppercase' => array( - TRUE => 'uppert', - FALSE => 'upperf', - ), - - // empty data -/*8*/ 'empty double quotes' => array( - "" => 'emptyd', - ), - /*9*/ 'empty single quotes' => array( '' => 'emptys', ), @@ -64,16 +41,6 @@ $inputs = array( $heredoc => 'stringh', ), - // undefined data -/*11*/ 'undefined' => array( - @$undefined_var => 'undefined', - ), - - // unset data -/*12*/ 'unset' => array( - @$unset_var => 'unset', - ), - // duplicate values /*13*/ 'duplicate' => array( 'foo' => 'bar', @@ -112,20 +79,6 @@ array(4) { -- Iteration 2 -- bool(true) -array(1) { - [""]=> - string(6) "null 1" -} - --- Iteration 3 -- -bool(true) -array(1) { - [""]=> - string(6) "null 2" -} - --- Iteration 4 -- -bool(true) array(2) { [0]=> string(6) "lowerf" @@ -133,30 +86,14 @@ array(2) { string(6) "lowert" } --- Iteration 5 -- -bool(true) -array(2) { - [0]=> - string(6) "upperf" - [1]=> - string(6) "uppert" -} - --- Iteration 6 -- -bool(true) -array(1) { - [""]=> - string(6) "emptyd" -} - --- Iteration 7 -- +-- Iteration 3 -- bool(true) array(1) { [""]=> string(6) "emptys" } --- Iteration 8 -- +-- Iteration 4 -- bool(true) array(3) { ["stringd"]=> @@ -167,21 +104,7 @@ array(3) { string(7) "strings" } --- Iteration 9 -- -bool(true) -array(1) { - [""]=> - string(9) "undefined" -} - --- Iteration 10 -- -bool(true) -array(1) { - [""]=> - string(5) "unset" -} - --- Iteration 11 -- +-- Iteration 5 -- bool(true) array(3) { ["foo"]=> diff --git a/ext/standard/tests/array/sort/shuffle_variation4.phpt b/ext/standard/tests/array/sort/shuffle_variation4.phpt index 1d3269e76e933..e2736379624c9 100644 --- a/ext/standard/tests/array/sort/shuffle_variation4.phpt +++ b/ext/standard/tests/array/sort/shuffle_variation4.phpt @@ -33,7 +33,7 @@ $array_arg = array( /*7*/ array("hex1" => 0x123, 'hex2' => 0xabc, "hex\t3" => 0xABC, "hex\04" => 0xAb1), // array with negative hexa values - array(NULL => -0x123, "NULL" => -0xabc, "-ABC" => -0xABC, -0xAB1 => -0xAb1), + array('' => -0x123, "NULL" => -0xabc, "-ABC" => -0xABC, -0xAB1 => -0xAb1), // array with positive octal values /*9*/ array(0123 => 0123, "0234" => 0234, '034' => 034, 00 => 00), @@ -41,9 +41,6 @@ $array_arg = array( // array with negative octal values array(-0123 => -0123, "-0234" => -0234, '-034' => -034), - // array with null values -/*11*/ array(NULL => NULL, "null" => NULL, "NULL" => NULL) - ); // looping to test shuffle() with each sub-array in the $array_arg array @@ -209,17 +206,4 @@ array(3) { [2]=> int(-%d) } - --- Iteration 11 -- -bool(true) - -The output array is: -array(3) { - [0]=> - NULL - [1]=> - NULL - [2]=> - NULL -} Done diff --git a/ext/standard/tests/array/sort/uasort_variation3.phpt b/ext/standard/tests/array/sort/uasort_variation3.phpt index 1b690e4dfd032..75e6e3993fbca 100644 --- a/ext/standard/tests/array/sort/uasort_variation3.phpt +++ b/ext/standard/tests/array/sort/uasort_variation3.phpt @@ -51,19 +51,12 @@ $array_arg = array( // string keys 'key' => 5, //single quoted key "two" => 4, //double quoted key - '' => 3, - "" => 2, + '' => 35, " " => 0, // space as key // bool keys - true => 15, - false => 5, - TRUE => 100, - FALSE => 25, - - // null keys - null => 20, // expecting: value will be replaced by 'NULL' - NULL => 35, + true => 100, + false => 25, // binary key "a".chr(0)."b" => 45, diff --git a/ext/standard/tests/array/sort/usort_variation3.phpt b/ext/standard/tests/array/sort/usort_variation3.phpt index 5478ca09abe28..7987fe3eecdaa 100644 --- a/ext/standard/tests/array/sort/usort_variation3.phpt +++ b/ext/standard/tests/array/sort/usort_variation3.phpt @@ -45,14 +45,12 @@ $array_arg = array( 'key' => 5, //single quoted key "two" => 4, //double quoted key " " => 0, // space as key + '' => 35, // bool keys TRUE => 100, FALSE => 25, - // null keys - NULL => 35, - // binary key "a".chr(0)."b" => 45, b"binary" => 30, 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/bug46347.phpt b/ext/standard/tests/file/bug46347.phpt index 903a6e35cc2b2..e337ade9eb8fb 100644 --- a/ext/standard/tests/file/bug46347.phpt +++ b/ext/standard/tests/file/bug46347.phpt @@ -8,14 +8,14 @@ $str = <<< EOF part1.*.part2 = 1 EOF; -$file = __DIR__ . '/parse.ini'; +$file = __DIR__ . '/bug46347.ini'; file_put_contents($file, $str); var_dump(parse_ini_file($file)); ?> --CLEAN-- --EXPECT-- array(1) { 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_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://xn--xampl-9raf.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/file/windows_mb_path/bug54028.phpt b/ext/standard/tests/file/windows_mb_path/bug54028.phpt index 61913a1a7218f..3603bced34d8a 100644 --- a/ext/standard/tests/file/windows_mb_path/bug54028.phpt +++ b/ext/standard/tests/file/windows_mb_path/bug54028.phpt @@ -4,12 +4,8 @@ Bug #54028 Directory::read() cannot handle non-unicode chars properly mbstring --SKIPIF-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- ---EXPECTF-- +--EXPECT-- Active code page: 65001 filetype()[dir ] == is_dir()[dir ] -> OK: . filetype()[dir ] == is_dir()[dir ] -> OK: .. @@ -58,4 +55,3 @@ filetype()[dir ] == is_dir()[dir ] -> OK: ソ filetype()[dir ] == is_dir()[dir ] -> OK: ゾ filetype()[dir ] == is_dir()[dir ] -> OK: 多国語 filetype()[dir ] == is_dir()[dir ] -> OK: 表 -Active code page: %d diff --git a/ext/standard/tests/file/windows_mb_path/bug70903.phpt b/ext/standard/tests/file/windows_mb_path/bug70903.phpt index 48cbf524c96d8..25a6f92b0abcc 100644 --- a/ext/standard/tests/file/windows_mb_path/bug70903.phpt +++ b/ext/standard/tests/file/windows_mb_path/bug70903.phpt @@ -2,12 +2,8 @@ Bug #70903 scandir wrongly interprets the Turkish "ı" character --SKIPIF-- --FILE-- --CONFLICTS-- bug71509 diff --git a/ext/standard/tests/file/windows_mb_path/bug74923.phpt b/ext/standard/tests/file/windows_mb_path/bug74923.phpt index 9cffd5860f601..fb87f2b266d54 100644 --- a/ext/standard/tests/file/windows_mb_path/bug74923.phpt +++ b/ext/standard/tests/file/windows_mb_path/bug74923.phpt @@ -2,11 +2,8 @@ Bug #74923 Crash when crawling through network share --SKIPIF-- --FILE-- --INI-- default_charset=cp1251 diff --git a/ext/standard/tests/file/windows_mb_path/bug75063_utf8.phpt b/ext/standard/tests/file/windows_mb_path/bug75063_utf8.phpt index a1878bb88a37c..615b76d196fb6 100644 --- a/ext/standard/tests/file/windows_mb_path/bug75063_utf8.phpt +++ b/ext/standard/tests/file/windows_mb_path/bug75063_utf8.phpt @@ -2,12 +2,8 @@ Bug #75063 Many filesystem-related functions do not work with multibyte file names, UTF-8 --SKIPIF-- --FILE-- 259) die("skip Unsuitable starting path length"); ?> --FILE-- diff --git a/ext/standard/tests/file/windows_mb_path/test_big5_0.phpt b/ext/standard/tests/file/windows_mb_path/test_big5_0.phpt index 794c1a2f7b878..7dc11a6167b5d 100644 --- a/ext/standard/tests/file/windows_mb_path/test_big5_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_big5_0.phpt @@ -4,9 +4,8 @@ Test fopen() for reading big5 path diff --git a/ext/standard/tests/file/windows_mb_path/test_big5_1.phpt b/ext/standard/tests/file/windows_mb_path/test_big5_1.phpt index d4821b23be0e4..7a88f57b7cf0d 100644 --- a/ext/standard/tests/file/windows_mb_path/test_big5_1.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_big5_1.phpt @@ -4,9 +4,8 @@ Test mkdir/rmdir big5 path diff --git a/ext/standard/tests/file/windows_mb_path/test_big5_2.phpt b/ext/standard/tests/file/windows_mb_path/test_big5_2.phpt index d7652615dea4e..89a8970344814 100644 --- a/ext/standard/tests/file/windows_mb_path/test_big5_2.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_big5_2.phpt @@ -4,9 +4,8 @@ Test fopen() for write big5 to UTF-8 path diff --git a/ext/standard/tests/file/windows_mb_path/test_big5_to_utf8_0.phpt b/ext/standard/tests/file/windows_mb_path/test_big5_to_utf8_0.phpt index b355267f851d9..c68bd58be0fc6 100644 --- a/ext/standard/tests/file/windows_mb_path/test_big5_to_utf8_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_big5_to_utf8_0.phpt @@ -2,12 +2,8 @@ Test fopen() for reading big5 to UTF-8 path --SKIPIF-- --CONFLICTS-- file_big5 diff --git a/ext/standard/tests/file/windows_mb_path/test_big5_to_utf8_1.phpt b/ext/standard/tests/file/windows_mb_path/test_big5_to_utf8_1.phpt index 5076768c955b3..33573f04ec39e 100644 --- a/ext/standard/tests/file/windows_mb_path/test_big5_to_utf8_1.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_big5_to_utf8_1.phpt @@ -2,12 +2,8 @@ Test mkdir/rmdir big5 to UTF-8 path --SKIPIF-- --CONFLICTS-- dir_big5 diff --git a/ext/standard/tests/file/windows_mb_path/test_big5_to_utf8_2.phpt b/ext/standard/tests/file/windows_mb_path/test_big5_to_utf8_2.phpt index 4f94f898796f3..2451ebca18e95 100644 --- a/ext/standard/tests/file/windows_mb_path/test_big5_to_utf8_2.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_big5_to_utf8_2.phpt @@ -2,12 +2,8 @@ Test fopen() for write big5 to UTF-8 path --SKIPIF-- --CONFLICTS-- file_big5 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_0.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_0.phpt index 98c716678a6d7..20e5de98e07f9 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_0.phpt @@ -2,12 +2,8 @@ Test fopen() for reading UTF-8 path with cp1250 specific symbols --SKIPIF-- --CONFLICTS-- file_cp1250 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_1.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_1.phpt index ad09ff1967caf..1411911f6d54c 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_1.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_1.phpt @@ -2,12 +2,8 @@ Test mkdir/rmdir UTF-8 path with cp1250 specific symbols --SKIPIF-- --CONFLICTS-- dir_cp1250 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_2.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_2.phpt index 61e1b4eaa598b..72cf60068d246 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_2.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_2.phpt @@ -2,12 +2,8 @@ Test fopen() for write to UTF-8 path with cp1250 specific symbols --SKIPIF-- --CONFLICTS-- dir_cp1250 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_3.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_3.phpt index 2f3ae9afd608d..4c07d5a6de656 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_3.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_3.phpt @@ -2,12 +2,8 @@ Test fopen() for reading UTF-8 path with cp1250 specific symbols --SKIPIF-- --CONFLICTS-- file_cp1250 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_4.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_4.phpt index 8992a847eb507..9d2a13de2b949 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_4.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_4.phpt @@ -2,12 +2,8 @@ Test mkdir/rmdir UTF-8 path with cp1250 specific symbols --SKIPIF-- --CONFLICTS-- dir_cp1250 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_5.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_5.phpt index 392c486a767f7..4ed862f08b086 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_5.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1250_to_utf8_5.phpt @@ -2,12 +2,8 @@ Test fopen() for write to UTF-8 path with cp1250 specific symbols --SKIPIF-- --CONFLICTS-- dir_cp1250 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1251_0.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1251_0.phpt index bf30b4baeb040..7766d6dfd327e 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1251_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1251_0.phpt @@ -4,9 +4,8 @@ Test fopen() for reading CP1251 path diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1251_1.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1251_1.phpt index 0ea67f575e563..1ea343ae30ce1 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1251_1.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1251_1.phpt @@ -4,9 +4,8 @@ Test mkdir/rmdir CP1251 path diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1251_2.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1251_2.phpt index f65b38eafdad0..60a7dbf07fd89 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1251_2.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1251_2.phpt @@ -4,9 +4,8 @@ Test fopen() for write CP1251 path diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1251_to_utf8_0.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1251_to_utf8_0.phpt index 0cd657e94c596..6cb74e468eaeb 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1251_to_utf8_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1251_to_utf8_0.phpt @@ -1,13 +1,11 @@ --TEST-- Test fopen() for reading CP1251 to UTF-8 path +--EXTENSIONS-- +iconv --SKIPIF-- --CONFLICTS-- file_cp1251 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1251_to_utf8_1.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1251_to_utf8_1.phpt index 6e53ff48c99d9..7776b908a8de9 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1251_to_utf8_1.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1251_to_utf8_1.phpt @@ -1,13 +1,11 @@ --TEST-- Test mkdir/rmdir CP1251 to UTF-8 path +--EXTENSIONS-- +iconv --SKIPIF-- --CONFLICTS-- dir_cp1251 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1251_to_utf8_2.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1251_to_utf8_2.phpt index 95b75985c6188..90c9ddf01254c 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1251_to_utf8_2.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1251_to_utf8_2.phpt @@ -1,13 +1,11 @@ --TEST-- Test fopen() for write CP1251 to UTF-8 path +--EXTENSIONS-- +iconv --SKIPIF-- --CONFLICTS-- file_cp1251 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1251_zend_multibyte_0.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1251_zend_multibyte_0.phpt index 8b800ed3bdeab..f962c5c0b0240 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1251_zend_multibyte_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1251_zend_multibyte_0.phpt @@ -7,12 +7,8 @@ zend.multibyte=1 zend.script_encoding=cp1251 --SKIPIF-- --CONFLICTS-- file_cp1251 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1251_zend_multibyte_1.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1251_zend_multibyte_1.phpt index 31db615f4d2c8..6d8a1f5d0050f 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1251_zend_multibyte_1.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1251_zend_multibyte_1.phpt @@ -7,12 +7,8 @@ zend.multibyte=1 zend.script_encoding=cp1251 --SKIPIF-- --CONFLICTS-- dir_cp1251 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1251_zend_multibyte_2.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1251_zend_multibyte_2.phpt index d6075da559c92..63745231771de 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1251_zend_multibyte_2.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1251_zend_multibyte_2.phpt @@ -7,12 +7,8 @@ zend.multibyte=1 zend.script_encoding=cp1251 --SKIPIF-- --CONFLICTS-- file_cp1251 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1252_0.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1252_0.phpt index f2671aa6054a5..aa3bc38dded21 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1252_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1252_0.phpt @@ -4,9 +4,8 @@ cp1252 cmd test diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_0.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_0.phpt index 45234243cee44..c7631eb601538 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_0.phpt @@ -1,13 +1,11 @@ --TEST-- Test fopen() for reading cp1252 to UTF-8 path +--EXTENSIONS-- +iconv --SKIPIF-- --CONFLICTS-- file_cp1252 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_1.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_1.phpt index 5f5a6a78385a7..ea14608ad4c03 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_1.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_1.phpt @@ -1,13 +1,11 @@ --TEST-- Test mkdir/rmdir cp1252 to UTF-8 path +--EXTENSIONS-- +iconv --SKIPIF-- --CONFLICTS-- dir_cp1252 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_2.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_2.phpt index 04baef95b0252..381b64eda6045 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_2.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_2.phpt @@ -1,13 +1,11 @@ --TEST-- Test fopen() for write cp1252 to UTF-8 path +--EXTENSIONS-- +iconv --SKIPIF-- --CONFLICTS-- dir_cp1252 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_3.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_3.phpt index f6559253d2de4..ef441bcbbfddf 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_3.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_3.phpt @@ -1,13 +1,11 @@ --TEST-- Test fopen() for reading cp1252 to UTF-8 path +--EXTENSIONS-- +iconv --SKIPIF-- --CONFLICTS-- file2_cp1252 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_4.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_4.phpt index a3359f686c1b3..739413dd74848 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_4.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_4.phpt @@ -1,13 +1,11 @@ --TEST-- Test mkdir/rmdir cp1252 to UTF-8 path +--EXTENSIONS-- +iconv --SKIPIF-- --CONFLICTS-- dir2_cp1252 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_5.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_5.phpt index 42212d027126c..9cf7a31feea1b 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_5.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1252_to_utf8_5.phpt @@ -1,13 +1,11 @@ --TEST-- Test fopen() for write cp1252 to UTF-8 path +--EXTENSIONS-- +iconv --SKIPIF-- --CONFLICTS-- dir2_cp1252 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1253_0.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1253_0.phpt index 93b63a536e839..11116849036b1 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1253_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1253_0.phpt @@ -4,9 +4,8 @@ Test fopen() for reading cp1253 path diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1253_1.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1253_1.phpt index 9ffdb11b2b83e..998ab348a0dc3 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1253_1.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1253_1.phpt @@ -4,9 +4,8 @@ Test mkdir/rmdir cp1253 path diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1253_2.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1253_2.phpt index 642e4aaabd194..01177620bd549 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1253_2.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1253_2.phpt @@ -4,9 +4,8 @@ Test fopen() for write cp1253 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1253_to_utf8_0.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1253_to_utf8_0.phpt index d12a174a7feaf..a592ed1f85bc6 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1253_to_utf8_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1253_to_utf8_0.phpt @@ -2,12 +2,8 @@ Test fopen() for reading cp1253 to UTF-8 path --SKIPIF-- --CONFLICTS-- file_cp1253 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1253_to_utf8_1.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1253_to_utf8_1.phpt index c84e9c95b3694..addc407f3e976 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1253_to_utf8_1.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1253_to_utf8_1.phpt @@ -2,12 +2,8 @@ Test mkdir/rmdir cp1253 to UTF-8 path --SKIPIF-- --CONFLICTS-- dir_cp1253 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1253_to_utf8_2.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1253_to_utf8_2.phpt index c0723d18b1228..cf88d95a4c696 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1253_to_utf8_2.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1253_to_utf8_2.phpt @@ -2,12 +2,8 @@ Test fopen() for write cp1253 to UTF-8 path --SKIPIF-- --CONFLICTS-- dir_cp1253 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1254_0.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1254_0.phpt index 77b52e0f1a2d6..83a413549ab31 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1254_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1254_0.phpt @@ -4,9 +4,8 @@ Test fopen() for reading cp1254 path diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1254_1.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1254_1.phpt index 82d74c750961b..9dc8225598358 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1254_1.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1254_1.phpt @@ -4,9 +4,8 @@ Test mkdir/rmdir cp1254 to UTF-8 path diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1254_2.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1254_2.phpt index f14a4c3de086e..2e386b3af45b9 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1254_2.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1254_2.phpt @@ -4,9 +4,8 @@ Test fopen() for write cp1254 path diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1254_3.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1254_3.phpt index 0e0e83d285a3b..076bf2eba50ea 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1254_3.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1254_3.phpt @@ -4,9 +4,8 @@ cp1254 cmd test diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1254_to_utf8_0.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1254_to_utf8_0.phpt index 211233de1c8e4..8dff7615dbfb5 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1254_to_utf8_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1254_to_utf8_0.phpt @@ -2,12 +2,8 @@ Test fopen() for reading cp1254 to UTF-8 path --SKIPIF-- --CONFLICTS-- file_cp1254 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1254_to_utf8_1.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1254_to_utf8_1.phpt index 42b241176ffb6..7b83cdbb395b3 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1254_to_utf8_1.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1254_to_utf8_1.phpt @@ -2,12 +2,8 @@ Test mkdir/rmdir cp1254 to UTF-8 path --SKIPIF-- --CONFLICTS-- dir_cp1254 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1254_to_utf8_2.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1254_to_utf8_2.phpt index b0c4f5ec83f0e..5ec63de4bc6e8 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1254_to_utf8_2.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1254_to_utf8_2.phpt @@ -2,12 +2,8 @@ Test fopen() for write cp1254 to UTF-8 path --SKIPIF-- --CONFLICTS-- dir_cp1254 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1254_to_utf8_3.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1254_to_utf8_3.phpt index 67549daf601d2..1e70dc8fe5b14 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1254_to_utf8_3.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1254_to_utf8_3.phpt @@ -2,12 +2,8 @@ cp1254 cmd test --SKIPIF-- --CONFLICTS-- file_cp1254 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1255_0.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1255_0.phpt index e9adaf843fb6a..61bb6b4155dc0 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1255_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1255_0.phpt @@ -4,9 +4,8 @@ Test fopen() for reading cp1255 path diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1255_1.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1255_1.phpt index 2cf42239267ad..a539ce8fd34e3 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1255_1.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1255_1.phpt @@ -4,9 +4,8 @@ Test mkdir/rmdir cp1255 path diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1255_2.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1255_2.phpt index e4779b721ba92..7fe2fecb7ea39 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1255_2.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1255_2.phpt @@ -4,9 +4,8 @@ Test fopen() for write cp1255 path diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1255_to_utf8_0.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1255_to_utf8_0.phpt index 1b65143553425..e8b35687e2fa8 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1255_to_utf8_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1255_to_utf8_0.phpt @@ -2,12 +2,8 @@ Test fopen() for reading cp1255 to UTF-8 path --SKIPIF-- --CONFLICTS-- file_cp1255 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1255_to_utf8_1.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1255_to_utf8_1.phpt index 356143ca7876a..48fa4f26a4b73 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1255_to_utf8_1.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1255_to_utf8_1.phpt @@ -2,12 +2,8 @@ Test mkdir/rmdir cp1255 to UTF-8 path --SKIPIF-- --CONFLICTS-- dir_cp1255 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1255_to_utf8_2.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1255_to_utf8_2.phpt index b378a7231d15e..358908ae56bd2 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1255_to_utf8_2.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1255_to_utf8_2.phpt @@ -2,12 +2,8 @@ Test fopen() for write cp1255 to UTF-8 path --SKIPIF-- --CONFLICTS-- dir_cp1255 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1256_0.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1256_0.phpt index 40910894b8ee7..9c0abe4c83269 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1256_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1256_0.phpt @@ -4,9 +4,8 @@ Test fopen() for reading cp1256 to UTF-8 path diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1256_1.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1256_1.phpt index 244758fe7bd67..f19bd04e9da98 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1256_1.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1256_1.phpt @@ -4,9 +4,8 @@ Test mkdir/rmdir cp1256 to UTF-8 path diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1256_2.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1256_2.phpt index f5b5db8935277..c734e24205d6a 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1256_2.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1256_2.phpt @@ -4,9 +4,8 @@ Test fopen() for write cp1256 to UTF-8 path diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1256_to_utf8_0.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1256_to_utf8_0.phpt index 901026f3899b0..9af7d83df2ad9 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1256_to_utf8_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1256_to_utf8_0.phpt @@ -2,12 +2,8 @@ Test fopen() for reading cp1256 to UTF-8 path --SKIPIF-- --CONFLICTS-- file_cp1256 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1256_to_utf8_1.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1256_to_utf8_1.phpt index b630f37648bc4..6da6d789e45ee 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1256_to_utf8_1.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1256_to_utf8_1.phpt @@ -2,12 +2,8 @@ Test mkdir/rmdir cp1256 to UTF-8 path --SKIPIF-- --CONFLICTS-- dir_cp1256 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp1256_to_utf8_2.phpt b/ext/standard/tests/file/windows_mb_path/test_cp1256_to_utf8_2.phpt index 6aa29f43c4268..2cce0b5411169 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp1256_to_utf8_2.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp1256_to_utf8_2.phpt @@ -2,12 +2,8 @@ Test fopen() for write cp1256 to UTF-8 path --SKIPIF-- --CONFLICTS-- dir_cp1256 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp874_0.phpt b/ext/standard/tests/file/windows_mb_path/test_cp874_0.phpt index e8bc394a5d0d1..cbab58e84855c 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp874_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp874_0.phpt @@ -4,9 +4,8 @@ Thai cp874 basic test diff --git a/ext/standard/tests/file/windows_mb_path/test_cp874_1.phpt b/ext/standard/tests/file/windows_mb_path/test_cp874_1.phpt index 9d948d4023aa6..cd438c52f361e 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp874_1.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp874_1.phpt @@ -4,9 +4,8 @@ Thai cp874 cmd test diff --git a/ext/standard/tests/file/windows_mb_path/test_cp874_to_utf8_0.phpt b/ext/standard/tests/file/windows_mb_path/test_cp874_to_utf8_0.phpt index c21f124b6e195..b8ed1c23758a3 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp874_to_utf8_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp874_to_utf8_0.phpt @@ -2,12 +2,8 @@ Thai UTF-8 basic test --SKIPIF-- --FILE-- --CONFLICTS-- file_cp874 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp932_0.phpt b/ext/standard/tests/file/windows_mb_path/test_cp932_0.phpt index ccb273a94ce0f..d2a8e06a61cb0 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp932_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp932_0.phpt @@ -4,9 +4,8 @@ Test fopen() for reading cp932 path diff --git a/ext/standard/tests/file/windows_mb_path/test_cp932_1.phpt b/ext/standard/tests/file/windows_mb_path/test_cp932_1.phpt index 744d1a592be95..3f58aa5614f5c 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp932_1.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp932_1.phpt @@ -4,9 +4,8 @@ Test mkdir/rmdir cp932 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp932_2.phpt b/ext/standard/tests/file/windows_mb_path/test_cp932_2.phpt index 737a4d3eb869b..dc474cf9dff38 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp932_2.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp932_2.phpt @@ -4,9 +4,8 @@ Test fopen() for write to cp932 path diff --git a/ext/standard/tests/file/windows_mb_path/test_cp932_3.phpt b/ext/standard/tests/file/windows_mb_path/test_cp932_3.phpt index 4fdfb925a82db..d54d90e17beed 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp932_3.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp932_3.phpt @@ -4,9 +4,8 @@ cp932 cmd test diff --git a/ext/standard/tests/file/windows_mb_path/test_cp932_to_utf8_0.phpt b/ext/standard/tests/file/windows_mb_path/test_cp932_to_utf8_0.phpt index df855aaca4e3b..925e0558ab26a 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp932_to_utf8_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp932_to_utf8_0.phpt @@ -1,13 +1,11 @@ --TEST-- Test fopen() for reading cp932 to UTF-8 path +--EXTENSIONS-- +iconv --SKIPIF-- --CONFLICTS-- file_cp932 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp932_to_utf8_1.phpt b/ext/standard/tests/file/windows_mb_path/test_cp932_to_utf8_1.phpt index b9575302c8abc..8346c86a4d195 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp932_to_utf8_1.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp932_to_utf8_1.phpt @@ -1,13 +1,11 @@ --TEST-- Test mkdir/rmdir cp932 to UTF-8 path +--EXTENSIONS-- +iconv --SKIPIF-- --CONFLICTS-- dir_cp932 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp932_to_utf8_2.phpt b/ext/standard/tests/file/windows_mb_path/test_cp932_to_utf8_2.phpt index 7c3870593692e..5d0f10f647acd 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp932_to_utf8_2.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp932_to_utf8_2.phpt @@ -1,13 +1,11 @@ --TEST-- Test fopen() for write cp932 to UTF-8 path +--EXTENSIONS-- +iconv --SKIPIF-- --CONFLICTS-- dir_cp932 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp936_0.phpt b/ext/standard/tests/file/windows_mb_path/test_cp936_0.phpt index b1a4f8744f94c..3199aa979355e 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp936_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp936_0.phpt @@ -4,9 +4,8 @@ Test fopen() for reading cp936 path diff --git a/ext/standard/tests/file/windows_mb_path/test_cp936_1.phpt b/ext/standard/tests/file/windows_mb_path/test_cp936_1.phpt index 529808aad5fb2..8ee68392ff318 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp936_1.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp936_1.phpt @@ -4,9 +4,8 @@ Test mkdir/rmdir cp936 path diff --git a/ext/standard/tests/file/windows_mb_path/test_cp936_2.phpt b/ext/standard/tests/file/windows_mb_path/test_cp936_2.phpt index e872c05942a68..024e84d4317fc 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp936_2.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp936_2.phpt @@ -4,9 +4,8 @@ Test fopen() for write cp936 path diff --git a/ext/standard/tests/file/windows_mb_path/test_cp936_to_utf8_0.phpt b/ext/standard/tests/file/windows_mb_path/test_cp936_to_utf8_0.phpt index 2797d25904f7f..39f989371968d 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp936_to_utf8_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp936_to_utf8_0.phpt @@ -1,13 +1,11 @@ --TEST-- Test fopen() for reading cp936 to UTF-8 path +--EXTENSIONS-- +iconv --SKIPIF-- --CONFLICTS-- file_cp936 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp936_to_utf8_1.phpt b/ext/standard/tests/file/windows_mb_path/test_cp936_to_utf8_1.phpt index f9730b6fe9a08..7321ea0ed9d59 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp936_to_utf8_1.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp936_to_utf8_1.phpt @@ -1,13 +1,11 @@ --TEST-- Test mkdir/rmdir cp936 to UTF-8 path +--EXTENSIONS-- +iconv --SKIPIF-- --CONFLICTS-- dir_cp936 diff --git a/ext/standard/tests/file/windows_mb_path/test_cp936_to_utf8_2.phpt b/ext/standard/tests/file/windows_mb_path/test_cp936_to_utf8_2.phpt index 31ff1db318b84..8b3eb208f12fe 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cp936_to_utf8_2.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cp936_to_utf8_2.phpt @@ -1,13 +1,11 @@ --TEST-- Test fopen() for write cp936 to UTF-8 path +--EXTENSIONS-- +iconv --SKIPIF-- --CONFLICTS-- file_cp936 diff --git a/ext/standard/tests/file/windows_mb_path/test_cwd_mb_names.phpt b/ext/standard/tests/file/windows_mb_path/test_cwd_mb_names.phpt index 3cb09f777d37f..9f9d1f24e6cdc 100644 --- a/ext/standard/tests/file/windows_mb_path/test_cwd_mb_names.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_cwd_mb_names.phpt @@ -2,15 +2,8 @@ Test chdir()/getcwd() with a dir for multibyte filenames --SKIPIF-- --CONFLICTS-- dir_mb @@ -24,8 +17,9 @@ $prefix = create_data("dir_mb"); $dirw = $prefix . DIRECTORY_SEPARATOR . "テストマルチバイト・パス42"; touch($dirw . DIRECTORY_SEPARATOR . "dummy.txt"); -$old_cp = get_active_cp(); -set_active_cp(65001); +$old_cp = sapi_windows_cp_get(); +sapi_windows_cp_set(65001); +echo "Active code page: ", sapi_windows_cp_get(), "\n"; $oldcwd = getcwd(); var_dump(chdir($dirw)); @@ -33,7 +27,7 @@ var_dump(getcwd()); var_dump(file_exists("dummy.txt")); -set_active_cp($old_cp); +sapi_windows_cp_set($old_cp); chdir($oldcwd); remove_data("dir_mb"); @@ -44,4 +38,3 @@ Active code page: 65001 bool(true) string(%d) "%s\テストマルチバイト・パス42" bool(true) -Active code page: %d diff --git a/ext/standard/tests/file/windows_mb_path/test_eucjp_to_utf8_0.phpt b/ext/standard/tests/file/windows_mb_path/test_eucjp_to_utf8_0.phpt index 7a06f53b7dd0c..48f2443017d6c 100644 --- a/ext/standard/tests/file/windows_mb_path/test_eucjp_to_utf8_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_eucjp_to_utf8_0.phpt @@ -1,13 +1,11 @@ --TEST-- Test fopen() for reading eucjp to UTF-8 path +--EXTENSIONS-- +iconv --SKIPIF-- --CONFLICTS-- file_eucjp diff --git a/ext/standard/tests/file/windows_mb_path/test_eucjp_to_utf8_1.phpt b/ext/standard/tests/file/windows_mb_path/test_eucjp_to_utf8_1.phpt index e3111ba33af7e..922f9e8290644 100644 --- a/ext/standard/tests/file/windows_mb_path/test_eucjp_to_utf8_1.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_eucjp_to_utf8_1.phpt @@ -1,13 +1,11 @@ --TEST-- Test mkdir/rmdir eucjp to UTF-8 path +--EXTENSIONS-- +iconv --SKIPIF-- --CONFLICTS-- dir_eucjp diff --git a/ext/standard/tests/file/windows_mb_path/test_eucjp_to_utf8_2.phpt b/ext/standard/tests/file/windows_mb_path/test_eucjp_to_utf8_2.phpt index 9425a1cc1cea8..b4a9895428d53 100644 --- a/ext/standard/tests/file/windows_mb_path/test_eucjp_to_utf8_2.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_eucjp_to_utf8_2.phpt @@ -1,13 +1,11 @@ --TEST-- Test fopen() for write eucjp to UTF-8 path +--EXTENSIONS-- +iconv --SKIPIF-- --CONFLICTS-- dir_eucjp diff --git a/ext/standard/tests/file/windows_mb_path/test_kartuli_utf8_0.phpt b/ext/standard/tests/file/windows_mb_path/test_kartuli_utf8_0.phpt index 0840610c2058e..f3c4f18131fa7 100644 --- a/ext/standard/tests/file/windows_mb_path/test_kartuli_utf8_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_kartuli_utf8_0.phpt @@ -2,12 +2,8 @@ Test fopen() for reading Kartuli UTF-8 path --SKIPIF-- --CONFLICTS-- file_kartuli diff --git a/ext/standard/tests/file/windows_mb_path/test_kartuli_utf8_1.phpt b/ext/standard/tests/file/windows_mb_path/test_kartuli_utf8_1.phpt index d348ccfd3c8fd..16f68f0f0ecb8 100644 --- a/ext/standard/tests/file/windows_mb_path/test_kartuli_utf8_1.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_kartuli_utf8_1.phpt @@ -2,12 +2,8 @@ Test mkdir/rmdir Kartuli UTF-8 path --SKIPIF-- --CONFLICTS-- dir_kartuli diff --git a/ext/standard/tests/file/windows_mb_path/test_kartuli_utf8_2.phpt b/ext/standard/tests/file/windows_mb_path/test_kartuli_utf8_2.phpt index 2e57dc0c91fa0..ca6c887a24ed9 100644 --- a/ext/standard/tests/file/windows_mb_path/test_kartuli_utf8_2.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_kartuli_utf8_2.phpt @@ -2,12 +2,8 @@ Test fopen() for write Kartuli UTF-8 path --SKIPIF-- --CONFLICTS-- dir_kartuli diff --git a/ext/standard/tests/file/windows_mb_path/test_kartuli_utf8_3.phpt b/ext/standard/tests/file/windows_mb_path/test_kartuli_utf8_3.phpt index 8d498d19907b1..e0984b0dd73bd 100644 --- a/ext/standard/tests/file/windows_mb_path/test_kartuli_utf8_3.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_kartuli_utf8_3.phpt @@ -2,12 +2,8 @@ Kartuli UTF-8 cmd test --SKIPIF-- --CONFLICTS-- file_kartuli diff --git a/ext/standard/tests/file/windows_mb_path/test_long_path_0.phpt b/ext/standard/tests/file/windows_mb_path/test_long_path_0.phpt index 6a5b60f08bbeb..daabfaad17fe4 100644 --- a/ext/standard/tests/file/windows_mb_path/test_long_path_0.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_long_path_0.phpt @@ -4,12 +4,8 @@ Basic long path test mbstring --SKIPIF-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- 248 has be a long path --SKIPIF-- 260 || strlen($start) > 248) { +if (strlen($start) > 260 || strlen($start) < 248) { die("skip the starting path length is unsuitable for this test"); } diff --git a/ext/standard/tests/file/windows_mb_path/test_readdir_mb_names.phpt b/ext/standard/tests/file/windows_mb_path/test_readdir_mb_names.phpt index 84fe5e327335b..65a0dada9f4c4 100644 --- a/ext/standard/tests/file/windows_mb_path/test_readdir_mb_names.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_readdir_mb_names.phpt @@ -2,12 +2,8 @@ Test readdir() with a dir for multibyte filenames --SKIPIF-- --CONFLICTS-- mb_names @@ -38,8 +34,9 @@ create_verify_dir($prefix, "żółć"); $dirw = $prefix . DIRECTORY_SEPARATOR; -$old_cp = get_active_cp(); -set_active_cp(65001); +$old_cp = sapi_windows_cp_get(); +sapi_windows_cp_set(65001); +echo "Active code page: ", sapi_windows_cp_get(), "\n"; if (is_dir($dirw)) { if ($dh = opendir($dirw)) { @@ -51,12 +48,12 @@ if (is_dir($dirw)) { } else { echo "is_dir failed\n"; } -set_active_cp($old_cp); +sapi_windows_cp_set($old_cp); remove_data("mb_names"); ?> ---EXPECTF-- +--EXPECT-- Active code page: 65001 filename: . : filetype: dir filename: .. : filetype: dir @@ -76,4 +73,3 @@ filename: テストマルチバイト・パス : filetype: file filename: テストマルチバイト・パス42 : filetype: dir filename: 測試多字節路徑 : filetype: file filename: 測試多字節路徑5 : filetype: dir -Active code page: %d diff --git a/ext/standard/tests/file/windows_mb_path/test_rename_mb_names.phpt b/ext/standard/tests/file/windows_mb_path/test_rename_mb_names.phpt index 53dd1bd3ea862..ce040d1eda545 100644 --- a/ext/standard/tests/file/windows_mb_path/test_rename_mb_names.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_rename_mb_names.phpt @@ -2,62 +2,42 @@ Test rename() with a dir for multibyte filenames --SKIPIF-- --CONFLICTS-- file2_mb --FILE-- ---EXPECTF-- +--EXPECT-- Active code page: 65001 bool(true) string(21) "Ελλάδα_copy.txt" @@ -66,4 +46,3 @@ bool(true) string(27) "測試多字節路徑17.txt" bool(true) bool(true) -Active code page: %d diff --git a/ext/standard/tests/file/windows_mb_path/util.inc b/ext/standard/tests/file/windows_mb_path/util.inc index a26a66c01751b..c8f0f6c586cb3 100644 --- a/ext/standard/tests/file/windows_mb_path/util.inc +++ b/ext/standard/tests/file/windows_mb_path/util.inc @@ -1,36 +1,7 @@ 20, 'line-break-chars' => "\n"); +test_roundtrip("Long text that will be wrapped", "convert.base64-encode", "convert.base64-decode", $opts); + +$opts2 = array('binary' => true); +test_roundtrip("Text\t\r\n", "convert.quoted-printable-encode", "convert.quoted-printable-decode", $opts2); + +$fp = tmpfile(); +fwrite($fp, "Test"); +rewind($fp); +stream_filter_prepend($fp, 'convert.base64-encode', STREAM_FILTER_READ); +$result = stream_get_contents($fp); +fclose($fp); +var_dump($result === base64_encode("Test")); + +?> +--EXPECTF-- +Filter: convert.base64-encode +Original: Hello World! +Encoded: SGVsbG8gV29ybGQh +Decoded: Hello World! +bool(true) + +Filter: convert.base64-encode +Original (hex): 414243ff +Encoded: QUJD/w== +Decoded (hex): 414243ff +bool(true) + +Filter: convert.base64-encode +Original: +Encoded: +Decoded: +bool(true) + +Filter: convert.base64-encode +Original: A +Encoded: QQ== +Decoded: A +bool(true) + +Filter: convert.quoted-printable-encode +Original: Hello World! +Encoded: Hello World! +Decoded: Hello World! +bool(true) + +Filter: convert.quoted-printable-encode +Original: Line1 +Line2 +Encoded: Line1=0D=0ALine2 +Decoded: Line1 +Line2 +bool(true) + +Filter: convert.base64-encode +Original: Long text that will be wrapped +Encoded: TG9uZyB0ZXh0IHRoYXQg +d2lsbCBiZSB3cmFwcGVk +Decoded: Long text that will be wrapped +bool(true) + +Filter: convert.quoted-printable-encode +Original: Text + +Encoded: Text=09=0D=0A +Decoded: Text + +bool(true) + +bool(true) diff --git a/ext/standard/tests/filters/filter_errors.inc b/ext/standard/tests/filters/filter_errors.inc index 18711844f834e..e933eea725e2e 100644 --- a/ext/standard/tests/filters/filter_errors.inc +++ b/ext/standard/tests/filters/filter_errors.inc @@ -1,16 +1,5 @@ --FILE-- +--EXTENSIONS-- +zlib --FILE-- +--EXTENSIONS-- +zlib --FILE-- data = strtoupper($bucket->data); + $consumed += $bucket->datalen; + stream_bucket_prepend($out, $bucket); + // Interleave new bucket + stream_bucket_prepend($out, clone $bucket); + stream_bucket_prepend($out, $bucket); + } + return PSFS_PASS_ON; + } + + function onCreate(): bool + { + echo "fffffffffff\n"; + return true; + } + + function onClose(): void + { + echo "hello\n"; + } +} + +stream_filter_register("strtoupper", "strtoupper_filter"); +$fp=fopen($file, "w"); +stream_filter_append($fp, "strtoupper"); +fread($fp, 1024); +fwrite($fp, "Thank you\n"); +fclose($fp); +readfile($file); +unlink($file); +?> +--EXPECTF-- +fffffffffff + +Notice: fread(): Read of 8192 bytes failed with errno=9 Bad file descriptor in %s on line %d +hello +THANK YOU diff --git a/ext/standard/tests/streams/gh17650.phpt b/ext/standard/tests/filters/gh17650.phpt similarity index 100% rename from ext/standard/tests/streams/gh17650.phpt rename to ext/standard/tests/filters/gh17650.phpt diff --git a/ext/standard/tests/filters/gh20370.phpt b/ext/standard/tests/filters/gh20370.phpt new file mode 100644 index 0000000000000..abcf49bfc9f4c --- /dev/null +++ b/ext/standard/tests/filters/gh20370.phpt @@ -0,0 +1,44 @@ +--TEST-- +GH-20370 (User filters should respect typed properties) +--FILE-- +datalen; + stream_bucket_append($out, $bucket); + } + return PSFS_PASS_ON; + } +} + +stream_filter_register("pass", "pass_filter"); +$fp = fopen("php://memory", "w"); +stream_filter_append($fp, "pass"); + +try { + fwrite($fp, "data"); +} catch (TypeError $e) { + echo $e::class, ": ", $e->getMessage(), "\n"; +} + +try { + fclose($fp); +} catch (TypeError $e) { + echo $e::class, ": ", $e->getMessage(), "\n"; +} + +unset($fp); // prevent cleanup at shutdown + +?> +--EXPECTF-- +Warning: fwrite(): Unprocessed filter buckets remaining on input brigade in %s on line %d +TypeError: Cannot assign resource to property pass_filter::$stream of type int +TypeError: Cannot assign resource to property pass_filter::$stream of type int diff --git a/ext/standard/tests/filters/gh20370_dynamic_stream_property.phpt b/ext/standard/tests/filters/gh20370_dynamic_stream_property.phpt new file mode 100644 index 0000000000000..97f24b854c5ea --- /dev/null +++ b/ext/standard/tests/filters/gh20370_dynamic_stream_property.phpt @@ -0,0 +1,51 @@ +--TEST-- +GH-20370 (User filters should update dynamic stream property if it exists) +--FILE-- +stream = null; + return true; + } + + function filter($in, $out, &$consumed, $closing): int + { + while ($bucket = stream_bucket_make_writeable($in)) { + $consumed += $bucket->datalen; + stream_bucket_append($out, $bucket); + } + var_dump(property_exists($this, 'stream')); + if (is_resource($this->stream)) { + var_dump(get_resource_type($this->stream)); + } + return PSFS_PASS_ON; + } +} + +stream_filter_register("pass", "pass_filter"); +$fp = fopen("php://memory", "w"); +stream_filter_append($fp, "pass"); + +fwrite($fp, "data"); +rewind($fp); +echo fread($fp, 1024) . "\n"; + +?> +--EXPECTF-- +bool(true) +string(6) "stream" +bool(true) +string(6) "stream" +bool(true) +string(6) "stream" +bool(true) +string(6) "stream" +data +bool(true) diff --git a/ext/standard/tests/filters/gh20370_no_stream_property.phpt b/ext/standard/tests/filters/gh20370_no_stream_property.phpt new file mode 100644 index 0000000000000..1b52c4c4155b8 --- /dev/null +++ b/ext/standard/tests/filters/gh20370_no_stream_property.phpt @@ -0,0 +1,37 @@ +--TEST-- +GH-20370 (User filters should not create stream property if not declared) +--FILE-- +datalen; + stream_bucket_append($out, $bucket); + } + + var_dump(property_exists($this, 'stream')); + return PSFS_PASS_ON; + } +} + +stream_filter_register("pass", "pass_filter"); +$fp = fopen("php://memory", "w"); +stream_filter_append($fp, "pass"); +fwrite($fp, "data"); +rewind($fp); +echo fread($fp, 1024) . "\n"; + +?> +--EXPECT-- +bool(false) +bool(false) +bool(false) +bool(false) +data +bool(false) diff --git a/ext/standard/tests/filters/gh20370_private_stream_property.phpt b/ext/standard/tests/filters/gh20370_private_stream_property.phpt new file mode 100644 index 0000000000000..bfbbba6099ad0 --- /dev/null +++ b/ext/standard/tests/filters/gh20370_private_stream_property.phpt @@ -0,0 +1,38 @@ +--TEST-- +GH-20370 (User filters should handle private stream property correctly) +--FILE-- +datalen; + stream_bucket_append($out, $bucket); + } + return PSFS_PASS_ON; + } + + function onClose() + { + var_dump($this->stream); // should be null + } +} + +stream_filter_register("pass", "pass_filter"); +$fp = fopen("php://memory", "w"); +stream_filter_append($fp, "pass", STREAM_FILTER_WRITE); + +fwrite($fp, "data"); +rewind($fp); +echo fread($fp, 1024) . "\n"; + +?> +--EXPECT-- +data +NULL 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/streams/stream_filter_register.phpt b/ext/standard/tests/filters/stream_filter_register.phpt similarity index 100% rename from ext/standard/tests/streams/stream_filter_register.phpt rename to ext/standard/tests/filters/stream_filter_register.phpt diff --git a/ext/standard/tests/filters/stream_filter_register_class_coerce_consumed_by_ref_param.phpt b/ext/standard/tests/filters/stream_filter_register_class_coerce_consumed_by_ref_param.phpt new file mode 100644 index 0000000000000..f5f0ecca79751 --- /dev/null +++ b/ext/standard/tests/filters/stream_filter_register_class_coerce_consumed_by_ref_param.phpt @@ -0,0 +1,32 @@ +--TEST-- +stream_filter_register() with a class that coerces the $consumed parameter of filter method +--XFAIL-- +This leaks memory +--FILE-- + +--EXPECTF-- +bool(true) +resource(4) of type (stream filter) + +Warning: Object of class stdClass could not be converted to int in %s on line %d + +Warning: fwrite(): Unprocessed filter buckets remaining on input brigade in %s on line %d +int(1) + +Warning: Object of class stdClass could not be converted to int in Unknown on line 0 diff --git a/ext/standard/tests/filters/stream_filter_register_class_completely_invalid.phpt b/ext/standard/tests/filters/stream_filter_register_class_completely_invalid.phpt new file mode 100644 index 0000000000000..6bd3e7bc1c9dc --- /dev/null +++ b/ext/standard/tests/filters/stream_filter_register_class_completely_invalid.phpt @@ -0,0 +1,33 @@ +--TEST-- +stream_filter_register() with a class name that exist but does not extend php_user_filter nor mock anything +--FILE-- + +--EXPECTF-- +bool(true) + +Deprecated: Creation of dynamic property foo::$filtername is deprecated in %s on line %d + +Deprecated: Creation of dynamic property foo::$params is deprecated in %s on line %d +resource(%d) of type (stream filter) + +Warning: fwrite(): Unprocessed filter buckets remaining on input brigade in %s on line %d + +Fatal error: Uncaught Error: Invalid callback foo::filter, class foo does not have a method "filter" in %s:%d +Stack trace: +#0 %s(%d): fwrite(Resource id #%d, 'Hello\n') +#1 {main} + thrown in %s on line %d + +Fatal error: Invalid callback foo::filter, class foo does not have a method "filter" in Unknown on line 0 diff --git a/ext/standard/tests/filters/stream_filter_register_class_completely_invalid_filtername_prop_type.phpt b/ext/standard/tests/filters/stream_filter_register_class_completely_invalid_filtername_prop_type.phpt new file mode 100644 index 0000000000000..793c112791a99 --- /dev/null +++ b/ext/standard/tests/filters/stream_filter_register_class_completely_invalid_filtername_prop_type.phpt @@ -0,0 +1,28 @@ +--TEST-- +stream_filter_register() with a class name exist but does not extend php_user_filter and defines a $filtername prop with different type +--FILE-- + +--EXPECTF-- +bool(true) + +Deprecated: Creation of dynamic property foo::$params is deprecated in %s on line %d + +Fatal error: Uncaught TypeError: Cannot assign string to property foo::$filtername of type array in %s:%d +Stack trace: +#0 %s(%d): stream_filter_append(Resource id #2, 'invalid_filter') +#1 {main} + thrown in %s on line %d + +Fatal error: Invalid callback foo::filter, class foo does not have a method "filter" in Unknown on line 0 diff --git a/ext/standard/tests/filters/stream_filter_register_class_completely_invalid_no_dynamic_props.phpt b/ext/standard/tests/filters/stream_filter_register_class_completely_invalid_no_dynamic_props.phpt new file mode 100644 index 0000000000000..86994d5c1b665 --- /dev/null +++ b/ext/standard/tests/filters/stream_filter_register_class_completely_invalid_no_dynamic_props.phpt @@ -0,0 +1,28 @@ +--TEST-- +stream_filter_register() with a class name exist but does not extend php_user_filter and cannot have dynamic properties +--FILE-- + +--EXPECTF-- +bool(true) + +Fatal error: Uncaught Error: Cannot create dynamic property SensitiveParameter::$filtername in %s:%d +Stack trace: +#0 %s(%d): stream_filter_append(Resource id #%d, 'invalid_filter') +#1 {main} + +Next Error: Cannot create dynamic property SensitiveParameter::$params in %s:%d +Stack trace: +#0 %s(%d): stream_filter_append(Resource id #%d, 'invalid_filter') +#1 {main} + thrown in %s on line %d + +Fatal error: Invalid callback SensitiveParameter::filter, class SensitiveParameter does not have a method "filter" in Unknown on line 0 diff --git a/ext/standard/tests/filters/stream_filter_register_class_private_filtername_prop.phpt b/ext/standard/tests/filters/stream_filter_register_class_private_filtername_prop.phpt new file mode 100644 index 0000000000000..6b9be4bbbb4b7 --- /dev/null +++ b/ext/standard/tests/filters/stream_filter_register_class_private_filtername_prop.phpt @@ -0,0 +1,28 @@ +--TEST-- +stream_filter_register() with a class name exist but does not extend php_user_filter and defines a private $filtername prop +--FILE-- + +--EXPECTF-- +bool(true) + +Deprecated: Creation of dynamic property foo::$params is deprecated in %s on line %d + +Fatal error: Uncaught Error: Cannot access private property foo::$filtername in %s:%d +Stack trace: +#0 %s(%d): stream_filter_append(Resource id #2, 'invalid_filter') +#1 {main} + thrown in %s on line %d + +Fatal error: Invalid callback foo::filter, class foo does not have a method "filter" in Unknown on line 0 diff --git a/ext/standard/tests/filters/stream_filter_register_class_throwing_onclose.phpt b/ext/standard/tests/filters/stream_filter_register_class_throwing_onclose.phpt new file mode 100644 index 0000000000000..76b925cc0483a --- /dev/null +++ b/ext/standard/tests/filters/stream_filter_register_class_throwing_onclose.phpt @@ -0,0 +1,30 @@ +--TEST-- +stream_filter_register() with a class that has a onclose method that throws +--FILE-- + +--EXPECTF-- +bool(true) +resource(4) of type (stream filter) + +Warning: fwrite(): Unprocessed filter buckets remaining on input brigade in %s on line %d +bool(false) + +Fatal error: Uncaught Exception: No in %s:%d +Stack trace: +#0 [internal function]: foo->onclose() +#1 {main} + thrown in %s on line %d diff --git a/ext/standard/tests/filters/stream_filter_register_class_throwing_oncreate.phpt b/ext/standard/tests/filters/stream_filter_register_class_throwing_oncreate.phpt new file mode 100644 index 0000000000000..3e429a2cc343a --- /dev/null +++ b/ext/standard/tests/filters/stream_filter_register_class_throwing_oncreate.phpt @@ -0,0 +1,27 @@ +--TEST-- +stream_filter_register() with a class that has a oncreate method that throws +--FILE-- + +--EXPECTF-- +bool(true) + +Fatal error: Uncaught Exception: No in %s:%d +Stack trace: +#0 [internal function]: foo->oncreate() +#1 %s(%d): stream_filter_append(Resource id #2, 'invalid_filter') +#2 {main} + thrown in %s on line %d diff --git a/ext/standard/tests/filters/stream_filter_register_filter_always_feed.phpt b/ext/standard/tests/filters/stream_filter_register_filter_always_feed.phpt new file mode 100644 index 0000000000000..7a3d3f8899938 --- /dev/null +++ b/ext/standard/tests/filters/stream_filter_register_filter_always_feed.phpt @@ -0,0 +1,24 @@ +--TEST-- +stream_filter_register() with a filter method always returning PSFS_FEED_ME +--FILE-- + +--EXPECTF-- +bool(true) +resource(4) of type (stream filter) + +Warning: fwrite(): Unprocessed filter buckets remaining on input brigade in %s on line %d +int(0) diff --git a/ext/standard/tests/filters/stream_filter_register_mock_class_filter.phpt b/ext/standard/tests/filters/stream_filter_register_mock_class_filter.phpt new file mode 100644 index 0000000000000..4d2309a718eb5 --- /dev/null +++ b/ext/standard/tests/filters/stream_filter_register_mock_class_filter.phpt @@ -0,0 +1,30 @@ +--TEST-- +stream_filter_register() with a class name exist that mocks php_user_filter with a filter method +--XFAIL-- +This leaks memory +--FILE-- + +--EXPECTF-- +bool(true) +resource(4) of type (stream filter) + +Warning: fwrite(): Unprocessed filter buckets remaining on input brigade in %s on line %d +int(0) diff --git a/ext/standard/tests/filters/stream_filter_register_mock_class_filter_incorect_return_type.phpt b/ext/standard/tests/filters/stream_filter_register_mock_class_filter_incorect_return_type.phpt new file mode 100644 index 0000000000000..b5ec8da3dde1b --- /dev/null +++ b/ext/standard/tests/filters/stream_filter_register_mock_class_filter_incorect_return_type.phpt @@ -0,0 +1,32 @@ +--TEST-- +stream_filter_register() with a class name exist that mocks php_user_filter with a filter method returning not an int +--FILE-- + +--EXPECTF-- +bool(true) +resource(4) of type (stream filter) + +Warning: Object of class stdClass could not be converted to int in %s on line %d + +Warning: fwrite(): Unprocessed filter buckets remaining on input brigade in %s on line %d +int(0) + +Warning: Object of class stdClass could not be converted to int in Unknown on line 0 diff --git a/ext/standard/tests/filters/stream_filter_register_mock_class_filter_is_private.phpt b/ext/standard/tests/filters/stream_filter_register_mock_class_filter_is_private.phpt new file mode 100644 index 0000000000000..6abffe1ff5f80 --- /dev/null +++ b/ext/standard/tests/filters/stream_filter_register_mock_class_filter_is_private.phpt @@ -0,0 +1,35 @@ +--TEST-- +stream_filter_register() with a class name exist that mocks php_user_filter with a private filter method +--FILE-- + +--EXPECTF-- +bool(true) +resource(%d) of type (stream filter) + +Warning: fwrite(): Unprocessed filter buckets remaining on input brigade in %s on line %d + +Fatal error: Uncaught Error: Invalid callback foo::filter, cannot access private method foo::filter() in %s:%d +Stack trace: +#0 %s(%d): fwrite(Resource id #%d, 'Hello\n') +#1 {main} + thrown in %s on line %d + +Fatal error: Invalid callback foo::filter, cannot access private method foo::filter() in Unknown on line 0 diff --git a/ext/standard/tests/filters/stream_filter_register_non_existing_class.phpt b/ext/standard/tests/filters/stream_filter_register_non_existing_class.phpt new file mode 100644 index 0000000000000..1c08201cff0c5 --- /dev/null +++ b/ext/standard/tests/filters/stream_filter_register_non_existing_class.phpt @@ -0,0 +1,21 @@ +--TEST-- +stream_filter_register() with a class name that does not exist +--FILE-- + +--EXPECTF-- +bool(true) + +Warning: stream_filter_append(): User-filter "not_existing_filter" requires class "not_existing", but that class is not defined in %s on line %d + +Warning: stream_filter_append(): Unable to create or locate filter "not_existing_filter" in %s on line %d +Hello +int(6) diff --git a/ext/standard/tests/streams/stream_multi_filters_close.phpt b/ext/standard/tests/filters/stream_multi_filters_close.phpt similarity index 100% rename from ext/standard/tests/streams/stream_multi_filters_close.phpt rename to ext/standard/tests/filters/stream_multi_filters_close.phpt diff --git a/ext/standard/tests/streams/user_streams_consumed_bug.phpt b/ext/standard/tests/filters/user_streams_consumed_bug.phpt similarity index 100% rename from ext/standard/tests/streams/user_streams_consumed_bug.phpt rename to ext/standard/tests/filters/user_streams_consumed_bug.phpt diff --git a/ext/standard/tests/file/userfilters.phpt b/ext/standard/tests/filters/userfilters.phpt similarity index 100% rename from ext/standard/tests/file/userfilters.phpt rename to ext/standard/tests/filters/userfilters.phpt 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/general_functions/debug_zval_dump_gh19801_memory_leak.phpt b/ext/standard/tests/general_functions/debug_zval_dump_gh19801_memory_leak.phpt new file mode 100644 index 0000000000000..cf2f1d444f1dc --- /dev/null +++ b/ext/standard/tests/general_functions/debug_zval_dump_gh19801_memory_leak.phpt @@ -0,0 +1,32 @@ +--TEST-- +GH-19801 (debug_zval_dump() leak with __debugInfo() that modifies circular references) +--FILE-- +a = null; + gc_collect_cycles(); + return []; + } + }, +]; + +$b = new stdClass; +$b->a = &$a; + +debug_zval_dump($b); +?> +--EXPECTF-- +object(stdClass)#2 (1) refcount(%d){ + ["a"]=> + reference refcount(%d) { + array(1) packed refcount(%d){ + [0]=> + object(class@anonymous)#1 (0) refcount(%d){ + } + } + } +} diff --git a/ext/standard/tests/general_functions/get_defined_constants_basic.phpt b/ext/standard/tests/general_functions/get_defined_constants_basic.phpt index b89cc937aae8c..f701945fb0e7d 100644 --- a/ext/standard/tests/general_functions/get_defined_constants_basic.phpt +++ b/ext/standard/tests/general_functions/get_defined_constants_basic.phpt @@ -9,7 +9,7 @@ var_dump(gettype(get_defined_constants())); $arr1 = get_defined_constants(false); $arr2 = get_defined_constants(); -var_dump(array_diff($arr1, $arr2)); +var_dump(array_diff_key($arr1, $arr2)); $n1 = count(get_defined_constants()); define("USER_CONSTANT", "test"); diff --git a/ext/standard/tests/general_functions/gettype_settype_variation2.phpt b/ext/standard/tests/general_functions/gettype_settype_variation2.phpt index 12f001e924e46..5f35d713d512f 100644 --- a/ext/standard/tests/general_functions/gettype_settype_variation2.phpt +++ b/ext/standard/tests/general_functions/gettype_settype_variation2.phpt @@ -274,6 +274,7 @@ int(1) string(7) "integer" -- Iteration 20 -- string(6) "string" +2: The float-string "2974394749328742328432" is not representable as an int, cast occurred bool(true) int(2147483647) string(7) "integer" @@ -304,6 +305,7 @@ int(1) string(7) "integer" -- Iteration 26 -- string(6) "string" +2: The float-string "2974394749328742328432" is not representable as an int, cast occurred bool(true) int(2147483647) string(7) "integer" @@ -424,11 +426,13 @@ int(2147483647) string(7) "integer" -- Iteration 50 -- string(6) "double" +2: The float 2147483649 is not representable as an int, cast occurred bool(true) int(-2147483647) string(7) "integer" -- Iteration 51 -- string(6) "double" +2: The float 1232147483649 is not representable as an int, cast occurred bool(true) int(-508130303) string(7) "integer" @@ -439,6 +443,7 @@ int(85) string(7) "integer" -- Iteration 53 -- string(6) "double" +2: The float 1058513956921 is not representable as an int, cast occurred bool(true) int(1952002105) string(7) "integer" @@ -459,6 +464,7 @@ int(-365) string(7) "integer" -- Iteration 57 -- string(6) "double" +2: The float 80561044571754 is not representable as an int, cast occurred bool(true) int(343000682) string(7) "integer" @@ -669,6 +675,7 @@ int(1) string(7) "integer" -- Iteration 20 -- string(6) "string" +2: The float-string "2974394749328742328432" is not representable as an int, cast occurred bool(true) int(2147483647) string(7) "integer" @@ -699,6 +706,7 @@ int(1) string(7) "integer" -- Iteration 26 -- string(6) "string" +2: The float-string "2974394749328742328432" is not representable as an int, cast occurred bool(true) int(2147483647) string(7) "integer" @@ -819,11 +827,13 @@ int(2147483647) string(7) "integer" -- Iteration 50 -- string(6) "double" +2: The float 2147483649 is not representable as an int, cast occurred bool(true) int(-2147483647) string(7) "integer" -- Iteration 51 -- string(6) "double" +2: The float 1232147483649 is not representable as an int, cast occurred bool(true) int(-508130303) string(7) "integer" @@ -834,6 +844,7 @@ int(85) string(7) "integer" -- Iteration 53 -- string(6) "double" +2: The float 1058513956921 is not representable as an int, cast occurred bool(true) int(1952002105) string(7) "integer" @@ -854,6 +865,7 @@ int(-365) string(7) "integer" -- Iteration 57 -- string(6) "double" +2: The float 80561044571754 is not representable as an int, cast occurred bool(true) int(343000682) string(7) "integer" diff --git a/ext/standard/tests/general_functions/intval.phpt b/ext/standard/tests/general_functions/intval.phpt index 51d3b128f4797..83377d85a099a 100644 --- a/ext/standard/tests/general_functions/intval.phpt +++ b/ext/standard/tests/general_functions/intval.phpt @@ -94,13 +94,10 @@ $not_int_types = array ( array(), array(0), array(1), - array(NULL), array(null), array("string"), array(true), - array(TRUE), array(false), - array(FALSE), array(1,2,3,4), array(1 => "One", "two" => 2), @@ -127,12 +124,6 @@ $not_int_types = array ( /* booleans */ true, false, - TRUE, - FALSE, - - /* undefined and unset vars */ - @$unset_var, - @$undefined_var ); @@ -230,11 +221,19 @@ int(-2147483648) int(2147483647) *** Testing intval() on non integer types *** + +Warning: The float-string "-2147483649" is not representable as an int, cast occurred in %s on line %d int(-2147483648) + +Warning: The float-string "2147483648" is not representable as an int, cast occurred in %s on line %d int(2147483647) int(0) int(0) + +Warning: The float-string "020000000001" is not representable as an int, cast occurred in %s on line %d int(2147483647) + +Warning: The float-string "-020000000001" is not representable as an int, cast occurred in %s on line %d int(-2147483648) int(0) int(0) @@ -256,9 +255,6 @@ int(1) int(1) int(1) int(1) -int(1) -int(1) -int(1) int(0) int(0) int(0) @@ -279,9 +275,5 @@ int(0) int(0) int(1) int(0) -int(1) -int(0) -int(0) -int(0) --- Done --- diff --git a/ext/standard/tests/general_functions/proc_open_multiplex.phpt b/ext/standard/tests/general_functions/proc_open_multiplex.phpt index 63e856b29c31e..798b5e74c475e 100644 --- a/ext/standard/tests/general_functions/proc_open_multiplex.phpt +++ b/ext/standard/tests/general_functions/proc_open_multiplex.phpt @@ -1,5 +1,11 @@ --TEST-- Multiplexing of child output +--SKIPIF-- + --FILE-- a = null; + gc_collect_cycles(); + return []; + } + }, +]; + +$b = new stdClass; +$b->a = &$a; + +var_dump($b); +?> +--EXPECTF-- +object(stdClass)#2 (1) { + ["a"]=> + &array(1) { + [0]=> + object(class@anonymous)#1 (0) { + } + } +} diff --git a/ext/standard/tests/gh20695.phpt b/ext/standard/tests/gh20695.phpt new file mode 100644 index 0000000000000..64c81ab9fdb54 --- /dev/null +++ b/ext/standard/tests/gh20695.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-20695 (Assertion failure in normalize_value() when parsing malformed INI input via parse_ini_string()) +--FILE-- + +--EXPECT-- +array(1) { + [8]=> + array(1) { + ["["]=> + int(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_build_query/gh20583.phpt b/ext/standard/tests/http/http_build_query/gh20583.phpt new file mode 100644 index 0000000000000..5ea0dbe9006bc --- /dev/null +++ b/ext/standard/tests/http/http_build_query/gh20583.phpt @@ -0,0 +1,27 @@ +--TEST-- +GH-20583 (Stack overflow in http_build_query via deep structures) +--SKIPIF-- + +--INI-- +zend.max_allowed_stack_size=128K +--FILE-- + $a]; +} +try { + http_build_query($a, 'p'); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), "\n"; +} +?> +--EXPECT-- +Error: Maximum call stack size reached. 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/gh20201.avif b/ext/standard/tests/image/gh20201.avif new file mode 100644 index 0000000000000..3cf1ffdec1818 Binary files /dev/null and b/ext/standard/tests/image/gh20201.avif differ diff --git a/ext/standard/tests/image/gh20201.phpt b/ext/standard/tests/image/gh20201.phpt new file mode 100644 index 0000000000000..272eb1d8dd162 --- /dev/null +++ b/ext/standard/tests/image/gh20201.phpt @@ -0,0 +1,27 @@ +--TEST-- +GH-20201 (AVIF images misdetected as HEIF after introducing HEIF support in getimagesize()) +--FILE-- + +--EXPECT-- +array(9) { + [0]=> + int(8) + [1]=> + int(8) + [2]=> + int(19) + [3]=> + string(20) "width="8" height="8"" + ["bits"]=> + int(8) + ["channels"]=> + int(3) + ["mime"]=> + string(10) "image/avif" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" +} diff --git a/ext/standard/tests/image/gh20584.phpt b/ext/standard/tests/image/gh20584.phpt new file mode 100644 index 0000000000000..d117f21820264 --- /dev/null +++ b/ext/standard/tests/image/gh20584.phpt @@ -0,0 +1,39 @@ +--TEST-- +GH-20584 (Information Leak of Memory) +--CREDITS-- +Nikita Sveshnikov (Positive Technologies) +--FILE-- + +--CLEAN-- + +--EXPECT-- +bool(true) 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/mail/gh20257.phpt b/ext/standard/tests/mail/gh20257.phpt new file mode 100644 index 0000000000000..68374173413fc --- /dev/null +++ b/ext/standard/tests/mail/gh20257.phpt @@ -0,0 +1,17 @@ +--TEST-- +GH-20257: heap overflow with empty message and mail.cr_lf_mode=lf set +--INI-- +sendmail_path="exit 1" +mail.cr_lf_mode=lf +--CREDITS-- +YuanchengJiang +--FILE-- + +--EXPECTF-- + +Warning: mail(): Sendmail exited with non-zero exit code 1 in %s on line %d +bool(false) diff --git a/ext/standard/tests/math/bug30695.phpt b/ext/standard/tests/math/bug30695.phpt index 82771d0e0ab92..a2ac79c112629 100644 --- a/ext/standard/tests/math/bug30695.phpt +++ b/ext/standard/tests/math/bug30695.phpt @@ -53,22 +53,22 @@ if (PHP_INT_SIZE != 4) die("skip this test is for 32bit platform only"); echo "\n", toUTF8(65), "\n", toUTF8(233), "\n", toUTF8(1252), "\n", toUTF8(20095), "\n"; ?> --EXPECTF-- -Deprecated: Implicit conversion from float 4294967168 to int loses precision in %s on line %d +Warning: The float 4294967168 is not representable as an int, cast occurred in %s on line %d A -Deprecated: Implicit conversion from float 4294967168 to int loses precision in %s on line %d +Warning: The float 4294967168 is not representable as an int, cast occurred in %s on line %d -Deprecated: Implicit conversion from float 4294965248 to int loses precision in %s on line %d +Warning: The float 4294965248 is not representable as an int, cast occurred in %s on line %d é -Deprecated: Implicit conversion from float 4294967168 to int loses precision in %s on line %d +Warning: The float 4294967168 is not representable as an int, cast occurred in %s on line %d -Deprecated: Implicit conversion from float 4294965248 to int loses precision in %s on line %d +Warning: The float 4294965248 is not representable as an int, cast occurred in %s on line %d Ӥ -Deprecated: Implicit conversion from float 4294967168 to int loses precision in %s on line %d +Warning: The float 4294967168 is not representable as an int, cast occurred in %s on line %d -Deprecated: Implicit conversion from float 4294965248 to int loses precision in %s on line %d +Warning: The float 4294965248 is not representable as an int, cast occurred in %s on line %d -Deprecated: Implicit conversion from float 4294901760 to int loses precision in %s on line %d +Warning: The float 4294901760 is not representable as an int, cast occurred in %s on line %d 乿 diff --git a/ext/standard/tests/math/clamp.phpt b/ext/standard/tests/math/clamp.phpt new file mode 100644 index 0000000000000..beb4c8d53148d --- /dev/null +++ b/ext/standard/tests/math/clamp.phpt @@ -0,0 +1,104 @@ +--TEST-- +clamp() tests +--INI-- +precision=14 +date.timezone=UTC +zend.assertions=1 +--FILE-- +getMessage(), "\n"; + } + + try { + var_dump(make_clamp_fcc()($value, $min, $max)); + } catch (ValueError $error) { + echo $error->getMessage(), "\n"; + } +} + +var_dump(check_clamp_result(2, 1, 3)); +var_dump(check_clamp_result(0, 1, 3)); +var_dump(check_clamp_result(6, 1, 3)); +var_dump(check_clamp_result(2, 1.3, 3.4)); +var_dump(check_clamp_result(2.5, 1, 3)); +var_dump(check_clamp_result(2.5, 1.3, 3.4)); +var_dump(check_clamp_result(0, 1.3, 3.4)); +var_dump(check_clamp_result(M_PI, -INF, INF)); +var_dump(check_clamp_result(NAN, 4, 6)); +var_dump(check_clamp_result("a", "c", "g")); +var_dump(check_clamp_result("d", "c", "g")); +echo check_clamp_result('2025-08-01', '2025-08-15', '2025-09-15'), "\n"; +echo check_clamp_result('2025-08-20', '2025-08-15', '2025-09-15'), "\n"; +echo check_clamp_result(new \DateTimeImmutable('2025-08-01'), new \DateTimeImmutable('2025-08-15'), new \DateTimeImmutable('2025-09-15'))->format('Y-m-d'), "\n"; +echo check_clamp_result(new \DateTimeImmutable('2025-08-20'), new \DateTimeImmutable('2025-08-15'), new \DateTimeImmutable('2025-09-15'))->format('Y-m-d'), "\n"; +var_dump(check_clamp_result(null, -1, 1)); +var_dump(check_clamp_result(null, 1, 3)); +var_dump(check_clamp_result(null, -3, -1)); +var_dump(check_clamp_result(-9999, null, 10)); +var_dump(check_clamp_result(12, null, 10)); + +$a = new \InvalidArgumentException('a'); +$b = new \RuntimeException('b'); +$c = new \LogicException('c'); +echo check_clamp_result($a, $b, $c)::class, "\n"; +echo check_clamp_result($b, $a, $c)::class, "\n"; +echo check_clamp_result($c, $a, $b)::class, "\n"; + +check_clamp_exception(4, NAN, 6); +check_clamp_exception(7, 6, NAN); +check_clamp_exception(1, 3, 2); +check_clamp_exception(-9999, 5, null); +check_clamp_exception(12, -5, null); + +?> +--EXPECT-- +int(2) +int(1) +int(3) +int(2) +float(2.5) +float(2.5) +float(1.3) +float(3.141592653589793) +float(NAN) +string(1) "c" +string(1) "d" +2025-08-15 +2025-08-20 +2025-08-15 +2025-08-20 +int(-1) +int(1) +int(-3) +int(-9999) +int(10) +InvalidArgumentException +RuntimeException +LogicException +clamp(): Argument #2 ($min) must not be NAN +clamp(): Argument #2 ($min) must not be NAN +clamp(): Argument #3 ($max) must not be NAN +clamp(): Argument #3 ($max) must not be NAN +clamp(): Argument #2 ($min) must be smaller than or equal to argument #3 ($max) +clamp(): Argument #2 ($min) must be smaller than or equal to argument #3 ($max) +clamp(): Argument #2 ($min) must be smaller than or equal to argument #3 ($max) +clamp(): Argument #2 ($min) must be smaller than or equal to argument #3 ($max) +clamp(): Argument #2 ($min) must be smaller than or equal to argument #3 ($max) +clamp(): Argument #2 ($min) must be smaller than or equal to argument #3 ($max) diff --git a/ext/standard/tests/math/fpow.phpt b/ext/standard/tests/math/fpow.phpt index 3f3c64862e81e..524051ba26c48 100644 --- a/ext/standard/tests/math/fpow.phpt +++ b/ext/standard/tests/math/fpow.phpt @@ -24,13 +24,20 @@ $numbers = [ NAN, ]; +function safe_to_string(int|float $number): string { + if (is_nan($number)) { + return 'NAN'; + } + return $number; +} + foreach ($numbers as $base) { foreach ($numbers as $exp) { - print str_pad($base, 4, " ", STR_PAD_LEFT) . - " ** " . - str_pad($exp, 4) . - " = " . - fpow($base, $exp) . + echo str_pad(safe_to_string($base), 4, " ", STR_PAD_LEFT), + " ** ", + str_pad(safe_to_string($exp), 4), + " = ", + safe_to_string(fpow($base, $exp)), PHP_EOL; } } diff --git a/ext/standard/tests/math/pow_basic.phpt b/ext/standard/tests/math/pow_basic.phpt index bc594b27c631a..847e569a47996 100644 --- a/ext/standard/tests/math/pow_basic.phpt +++ b/ext/standard/tests/math/pow_basic.phpt @@ -8,40 +8,51 @@ if (PHP_INT_SIZE != 4) die("skip this test is for 32bit platform only"); ?> --FILE-- --FILE-- getMessage(), "\n"; +} +try { + dns_get_mx("\0", $out); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + dns_get_record("\0"); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + getprotobyname("\0"); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + getservbyname("\0", "tcp"); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + getservbyname("x", "tcp\0"); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + getservbyport(0, "tcp\0"); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + inet_pton("\0"); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + ip2long("\0"); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +?> +--EXPECT-- +dns_check_record(): Argument #1 ($hostname) must not contain any null bytes +dns_get_mx(): Argument #1 ($hostname) must not contain any null bytes +dns_get_record(): Argument #1 ($hostname) must not contain any null bytes +getprotobyname(): Argument #1 ($protocol) must not contain any null bytes +getservbyname(): Argument #1 ($service) must not contain any null bytes +getservbyname(): Argument #2 ($protocol) must not contain any null bytes +getservbyport(): Argument #2 ($protocol) must not contain any null bytes +inet_pton(): Argument #1 ($ip) must not contain any null bytes +ip2long(): Argument #1 ($ip) must not contain any null bytes 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/network/so_reuseaddr.phpt b/ext/standard/tests/network/so_reuseaddr.phpt new file mode 100644 index 0000000000000..d400a81ac33d3 --- /dev/null +++ b/ext/standard/tests/network/so_reuseaddr.phpt @@ -0,0 +1,73 @@ +--TEST-- +stream_socket_server() SO_REUSEADDR context option test +--FILE-- + ['so_reuseaddr' => false]]); +$server3 = stream_socket_server("tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $context); +if (!$server3) { + die('Unable to create server3'); +} + +$addr = stream_socket_get_name($server3, false); +$port = (int)substr(strrchr($addr, ':'), 1); + +$client3 = stream_socket_client("tcp://127.0.0.1:$port"); +$accepted = stream_socket_accept($server3, 1); + +// Force real TCP connection with data +fwrite($client3, "test"); +fread($accepted, 4); +fwrite($accepted, "response"); +fread($client3, 8); + +// Client closes first (becomes active closer) +fclose($client3); // This enters TIME_WAIT +if (!$is_win) { // Windows would always succeed if server is closed + fclose($server3); +} + +// Try immediate bind with SO_REUSEADDR disabled (should fail) +$server4 = @stream_socket_server("tcp://127.0.0.1:$port", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $context); +if ($server4) { + echo "Disabled: Server restart succeeded\n"; + fclose($server4); +} else { + echo "Disabled: Server restart failed\n"; +} +?> +--EXPECT-- +Default: Server restart succeeded +Disabled: Server restart failed diff --git a/ext/standard/tests/network/so_reuseport.phpt b/ext/standard/tests/network/so_reuseport.phpt new file mode 100644 index 0000000000000..12a07bbd42364 --- /dev/null +++ b/ext/standard/tests/network/so_reuseport.phpt @@ -0,0 +1,136 @@ +--TEST-- +stream_socket_server() SO_REUSEPORT context option test +--SKIPIF-- + +--FILE-- + ['so_reuseport' => true]]); +$server1 = stream_socket_server("tcp://127.0.0.1:0", $errno, $errstr, + STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $context1); + +if (!$server1) { + die('Unable to create server1'); +} + +$addr = stream_socket_get_name($server1, false); +$port = (int)substr(strrchr($addr, ':'), 1); + +// Establish actual connection on server1 +$client1 = stream_socket_client("tcp://127.0.0.1:$port"); +$accepted1 = stream_socket_accept($server1, 1); + +// Force real TCP connection with data +fwrite($client1, "test"); +fread($accepted1, 4); +fwrite($accepted1, "response"); +fread($client1, 8); + +// Try to bind second server to SAME port with SO_REUSEPORT (while server1 still active) +$context2 = stream_context_create(['socket' => ['so_reuseport' => true]]); +$server2 = @stream_socket_server("tcp://127.0.0.1:$port", $errno, $errstr, + STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $context2); + +if ($server2) { + echo "SO_REUSEPORT enabled: Multiple servers succeeded\n"; + + // Verify server2 can also accept connections + $client2 = stream_socket_client("tcp://127.0.0.1:$port"); + $accepted2_on_srv1 = @stream_socket_accept($server1, 0.1); + $accepted2_on_srv2 = @stream_socket_accept($server2, 0.1); + + if ($accepted2_on_srv1 || $accepted2_on_srv2) { + echo "SO_REUSEPORT enabled: Connections accepted\n"; + } + + if ($accepted2_on_srv1) fclose($accepted2_on_srv1); + if ($accepted2_on_srv2) fclose($accepted2_on_srv2); + if ($client2) fclose($client2); + + fclose($server2); +} else { + echo "SO_REUSEPORT enabled: Multiple servers failed\n"; +} + +fclose($accepted1); +fclose($client1); +fclose($server1); + +// SO_REUSEPORT disabled (default) - should NOT allow multiple servers +$server3 = stream_socket_server("tcp://127.0.0.1:0", $errno, $errstr, + STREAM_SERVER_BIND | STREAM_SERVER_LISTEN); + +if (!$server3) { + die('Unable to create server3'); +} + +$addr = stream_socket_get_name($server3, false); +$port = (int)substr(strrchr($addr, ':'), 1); + +$client3 = stream_socket_client("tcp://127.0.0.1:$port"); +$accepted3 = stream_socket_accept($server3, 1); + +fwrite($client3, "test"); +fread($accepted3, 4); +fwrite($accepted3, "response"); +fread($client3, 8); + +// Try to bind second server WITHOUT SO_REUSEPORT (while server3 still active) +$server4 = @stream_socket_server("tcp://127.0.0.1:$port", $errno, $errstr, + STREAM_SERVER_BIND | STREAM_SERVER_LISTEN); + +if ($server4) { + echo "SO_REUSEPORT disabled: Multiple servers succeeded\n"; + fclose($server4); +} else { + echo "SO_REUSEPORT disabled: Multiple servers failed\n"; +} + +fclose($accepted3); +fclose($client3); +fclose($server3); + +// SO_REUSEPORT explicitly disabled +$context3 = stream_context_create(['socket' => ['so_reuseport' => false]]); +$server5 = stream_socket_server("tcp://127.0.0.1:0", $errno, $errstr, + STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $context3); + +if (!$server5) { + die('Unable to create server5'); +} + +$addr = stream_socket_get_name($server5, false); +$port = (int)substr(strrchr($addr, ':'), 1); + +$client5 = stream_socket_client("tcp://127.0.0.1:$port"); +$accepted5 = stream_socket_accept($server5, 1); + +fwrite($client5, "test"); +fread($accepted5, 4); +fwrite($accepted5, "response"); +fread($client5, 8); + +$context4 = stream_context_create(['socket' => ['so_reuseport' => false]]); +$server6 = @stream_socket_server("tcp://127.0.0.1:$port", $errno, $errstr, + STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $context4); + +if ($server6) { + echo "SO_REUSEPORT explicitly disabled: Multiple servers succeeded\n"; + fclose($server6); +} else { + echo "SO_REUSEPORT explicitly disabled: Multiple servers failed\n"; +} + +fclose($accepted5); +fclose($client5); +fclose($server5); +?> +--EXPECT-- +SO_REUSEPORT enabled: Multiple servers succeeded +SO_REUSEPORT enabled: Connections accepted +SO_REUSEPORT disabled: Multiple servers failed +SO_REUSEPORT explicitly disabled: Multiple servers failed diff --git a/ext/standard/tests/network/udp4loop.phpt b/ext/standard/tests/network/udp4loop.phpt index 92709233ba19c..bde3f8dcef561 100644 --- a/ext/standard/tests/network/udp4loop.phpt +++ b/ext/standard/tests/network/udp4loop.phpt @@ -3,7 +3,7 @@ Streams Based IPv4 UDP Loopback test --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..22246b4e47920 --- /dev/null +++ b/ext/standard/tests/serialize/gh12265b.phpt @@ -0,0 +1,48 @@ +--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-- +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..d7ef08e20331b --- /dev/null +++ b/ext/standard/tests/serialize/gh19701.phpt @@ -0,0 +1,30 @@ +--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-- +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/shm_corruption_coercion_unserialize_options.phpt b/ext/standard/tests/serialize/shm_corruption_coercion_unserialize_options.phpt new file mode 100644 index 0000000000000..6a24a0137526c --- /dev/null +++ b/ext/standard/tests/serialize/shm_corruption_coercion_unserialize_options.phpt @@ -0,0 +1,14 @@ +--TEST-- +Shm corruption with coercion in options of unserialize() +--FILE-- + [new MyStringable]]); +?> +--EXPECTF-- +Warning: unserialize(): Error at offset 0 of 2 bytes in %s on line %d 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-- array('pipe', 'w'), // strerr ); -$environment = array('test' => array(1, 2, 3)); +$environment = array('test' => array(1, 2, 3), 'PATH' => getenv('PATH')); $cmd = (substr(PHP_OS, 0, 3) == 'WIN') ? 'dir' : 'ls'; $p = proc_open($cmd, $descs, $pipes, '.', $environment); 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/gh19570.phpt b/ext/standard/tests/streams/gh19570.phpt new file mode 100644 index 0000000000000..e3d486ea83cf9 --- /dev/null +++ b/ext/standard/tests/streams/gh19570.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-19570 (unable to fseek in /dev/zero and /dev/null) +--SKIPIF-- + +--FILE-- + +--EXPECT-- +int(0) +int(0) +int(0) diff --git a/ext/standard/tests/streams/gh19705.phpt b/ext/standard/tests/streams/gh19705.phpt new file mode 100644 index 0000000000000..d34cfc700596d --- /dev/null +++ b/ext/standard/tests/streams/gh19705.phpt @@ -0,0 +1,11 @@ +--TEST-- +GH-19705 segmentation fault with non writable stream at stream_filter_append call. +--EXTENSIONS-- +zlib +--FILE-- + +--EXPECTF-- +resource(%d) of type (stream filter) diff --git a/ext/standard/tests/streams/gh20286.phpt b/ext/standard/tests/streams/gh20286.phpt new file mode 100644 index 0000000000000..6d15e167aee90 --- /dev/null +++ b/ext/standard/tests/streams/gh20286.phpt @@ -0,0 +1,43 @@ +--TEST-- +GH-20286 use after destroy on userland stream_close +--CREDITS-- +vi3tL0u1s +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Fatal error: Cannot redeclare function a() (previously declared in %s:%d) in %s on line %d + +Fatal error: Cannot redeclare function a() (previously declared in %s:%d) in %s on line %d + +Fatal error: Cannot redeclare function a() (previously declared in %s:%d) in %s on line %d + +Fatal error: Cannot redeclare function a() (previously declared in %s:%d) in %s on line %d 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/bug47842.phpt b/ext/standard/tests/strings/bug47842.phpt index fe97308ea53a7..1c8da881e7ced 100644 --- a/ext/standard/tests/strings/bug47842.phpt +++ b/ext/standard/tests/strings/bug47842.phpt @@ -23,12 +23,14 @@ printf("printf 64-bit signed int '18446744073709551615' (2^64)-1 = %u\n", 184467 echo "Done\n"; ?> ---EXPECT-- +--EXPECTF-- -Test sscanf 32-bit signed int '2147483647' (2^31)-1 = 2147483647 sscanf 32-bit unsign int '4294967295' (2^32)-1 = 4294967295 sscanf 64-bit signed int '9223372036854775807' (2^63)-1 = 9223372036854775807 sscanf 64-bit unsign int '18446744073709551615' (2^64)-1 = 18446744073709551615 printf 64-bit signed int '9223372036854775807' (2^63)-1 = 9223372036854775807 + +Warning: The float 1.8446744073709552E+19 is not representable as an int, cast occurred in %s on line %d printf 64-bit signed int '18446744073709551615' (2^64)-1 = 0 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-- --EXPECT-- -setlocale(): Argument #2 ($locales) must be of type array|string, int given -setlocale(): Argument #3 must be of type array|string, int given +setlocale(): Argument #2 ($locales) must be of type array|string|null, int given +setlocale(): Argument #3 must be of type array|string|null, int given 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/join_variation3.phpt b/ext/standard/tests/strings/join_variation3.phpt index dc6661f3bf55f..6e4ba433c957a 100644 --- a/ext/standard/tests/strings/join_variation3.phpt +++ b/ext/standard/tests/strings/join_variation3.phpt @@ -24,12 +24,11 @@ $pieces_arrays = array ( array( "one" => "ten", "two" => "twenty", "three" => "thirty"), // string key/value array("one" => 1, 2 => "two", 4 => "four"), //mixed - // associative array, containing null/empty/boolean values as key/value - array(NULL => "NULL", null => "null", "NULL" => NULL, "null" => null), + // associative array, containing empty/boolean values as key/value array(true => "true", false => "false", "false" => false, "true" => true), array("" => "emptyd", '' => 'emptys', "emptyd" => "", 'emptys' => ''), - array(1 => '', 2 => "", 3 => NULL, 4 => null, 5 => false, 6 => true), - array('' => 1, "" => 2, NULL => 3, null => 4, false => 5, true => 6), + array(1 => '', 2 => "", 5 => false, 6 => true), + array('' => 1, "" => 2, false => 5, true => 6), // array with repetitive keys array("One" => 1, "two" => 2, "One" => 10, "two" => 20, "three" => 3) @@ -79,15 +78,13 @@ string(23) "ten], [twenty], [thirty" -- Iteration 12 -- string(16) "1], [two], [four" -- Iteration 13 -- -string(12) "null], [], [" --- Iteration 14 -- string(22) "true], [false], [], [1" --- Iteration 15 -- +-- Iteration 14 -- string(14) "emptys], [], [" +-- Iteration 15 -- +string(13) "], [], [], [1" -- Iteration 16 -- -string(21) "], [], [], [], [], [1" +string(11) "2], [5], [6" -- Iteration 17 -- -string(11) "4], [5], [6" --- Iteration 18 -- string(13) "10], [20], [3" Done 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/pack.phpt b/ext/standard/tests/strings/pack.phpt index af449266671da..e71f9ce37a964 100644 --- a/ext/standard/tests/strings/pack.phpt +++ b/ext/standard/tests/strings/pack.phpt @@ -97,7 +97,7 @@ print_r(unpack("v", pack("v", -1000))); print_r(unpack("v", pack("v", -64434))); print_r(unpack("v", pack("v", -65535))); ?> ---EXPECT-- +--EXPECTF-- Array ( [1] => h @@ -143,10 +143,14 @@ Array ( [1] => -64434 ) + +Warning: The float 4294967296 is not representable as an int, cast occurred in %s on line %d Array ( [1] => 0 ) + +Warning: The float -4294967296 is not representable as an int, cast occurred in %s on line %d Array ( [1] => 0 @@ -159,10 +163,14 @@ Array ( [1] => 0 ) + +Warning: The float 2147483650 is not representable as an int, cast occurred in %s on line %d Array ( [1] => -2147483646 ) + +Warning: The float 4294967295 is not representable as an int, cast occurred in %s on line %d Array ( [1] => -1 @@ -179,10 +187,14 @@ Array ( [1] => 0 ) + +Warning: The float 2147483650 is not representable as an int, cast occurred in %s on line %d Array ( [1] => -2147483646 ) + +Warning: The float 4294967296 is not representable as an int, cast occurred in %s on line %d Array ( [1] => 0 @@ -227,10 +239,14 @@ Array ( [1] => 0 ) + +Warning: The float 2147483650 is not representable as an int, cast occurred in %s on line %d Array ( [1] => -2147483646 ) + +Warning: The float 4294967296 is not representable as an int, cast occurred in %s on line %d Array ( [1] => 0 @@ -299,10 +315,14 @@ Array ( [1] => 0 ) + +Warning: The float 2147483650 is not representable as an int, cast occurred in %s on line %d Array ( [1] => -2147483646 ) + +Warning: The float 4294967296 is not representable as an int, cast occurred in %s on line %d Array ( [1] => 0 diff --git a/ext/standard/tests/strings/pack64.phpt b/ext/standard/tests/strings/pack64.phpt index 84e69008284d4..238195287b2b2 100644 --- a/ext/standard/tests/strings/pack64.phpt +++ b/ext/standard/tests/strings/pack64.phpt @@ -37,7 +37,7 @@ print_r(unpack("i", pack("i", -2147483647))); print_r(unpack("i", pack("i", -2147483648))); // Min int32 print_r(unpack("I", pack("I", 4294967295))); // Max uint32 ?> ---EXPECT-- +--EXPECTF-- Array ( [1] => 281474976710654 @@ -46,6 +46,8 @@ Array ( [1] => 0 ) + +Warning: The float 9.223372036854776E+18 is not representable as an int, cast occurred in %s on line %d Array ( [1] => -9223372036854775808 @@ -54,6 +56,8 @@ Array ( [1] => -1 ) + +Warning: The float 9.223372036854776E+18 is not representable as an int, cast occurred in %s on line %d Array ( [1] => -9223372036854775808 @@ -66,6 +70,8 @@ Array ( [1] => 0 ) + +Warning: The float 9.223372036854776E+18 is not representable as an int, cast occurred in %s on line %d Array ( [1] => -9223372036854775808 @@ -74,6 +80,8 @@ Array ( [1] => -1 ) + +Warning: The float 9.223372036854776E+18 is not representable as an int, cast occurred in %s on line %d Array ( [1] => -9223372036854775808 @@ -86,6 +94,8 @@ Array ( [1] => 0 ) + +Warning: The float 9.223372036854776E+18 is not representable as an int, cast occurred in %s on line %d Array ( [1] => -9223372036854775808 @@ -94,6 +104,8 @@ Array ( [1] => -1 ) + +Warning: The float 9.223372036854776E+18 is not representable as an int, cast occurred in %s on line %d Array ( [1] => -9223372036854775808 @@ -106,6 +118,8 @@ Array ( [1] => 0 ) + +Warning: The float 9.223372036854776E+18 is not representable as an int, cast occurred in %s on line %d Array ( [1] => -9223372036854775808 @@ -114,6 +128,8 @@ Array ( [1] => -1 ) + +Warning: The float 9.223372036854776E+18 is not representable as an int, cast occurred in %s on line %d Array ( [1] => -9223372036854775808 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 = << ---EXPECT-- +--EXPECTF-- *** Testing vprintf() : octal formats and non-octal values *** -- Iteration 1 -- + +Warning: The float 20000000000 is not representable as an int, cast occurred in %s on line %d + +Warning: The float 2000000000000 is not representable as an int, cast occurred in %s on line %d + +Warning: The float 22000000000000 is not representable as an int, cast occurred in %s on line %d 2 0 12 361100 37777775456 2322 diff --git a/ext/standard/tests/strings/vprintf_variation14.phpt b/ext/standard/tests/strings/vprintf_variation14.phpt index ce65e8726d871..4bda95917770a 100644 --- a/ext/standard/tests/strings/vprintf_variation14.phpt +++ b/ext/standard/tests/strings/vprintf_variation14.phpt @@ -75,10 +75,16 @@ foreach($args_array as $args) { } ?> ---EXPECT-- +--EXPECTF-- *** Testing vprintf() : hexa formats and non-hexa values *** -- Iteration 1 -- + +Warning: The float 20000000000 is not representable as an int, cast occurred in %s on line %d + +Warning: The float 2000000000000 is not representable as an int, cast occurred in %s on line %d + +Warning: The float 22000000000000 is not representable as an int, cast occurred in %s on line %d 2 0 a 1e240 x fffffb2e 4d2 diff --git a/ext/standard/tests/strings/vprintf_variation15.phpt b/ext/standard/tests/strings/vprintf_variation15.phpt index c8ae74f2aa75e..2eda443ebb95f 100644 --- a/ext/standard/tests/strings/vprintf_variation15.phpt +++ b/ext/standard/tests/strings/vprintf_variation15.phpt @@ -44,7 +44,7 @@ foreach($formats as $format) { } ?> ---EXPECT-- +--EXPECTF-- *** Testing vprintf() : unsigned formats and unsigned values *** -- Iteration 1 -- @@ -52,10 +52,14 @@ foreach($formats as $format) { int(16) -- Iteration 2 -- + +Warning: The float 12345678900 is not representable as an int, cast occurred in %s on line %d 3755744308 1234 12345 int(21) -- Iteration 3 -- + +Warning: The float 101234567000 is not representable as an int, cast occurred in %s on line %d 1234000 2450319192 120 int(25) diff --git a/ext/standard/tests/strings/vprintf_variation15_64bit.phpt b/ext/standard/tests/strings/vprintf_variation15_64bit.phpt index 2729e8f54af74..0ccb490095aac 100644 --- a/ext/standard/tests/strings/vprintf_variation15_64bit.phpt +++ b/ext/standard/tests/strings/vprintf_variation15_64bit.phpt @@ -44,7 +44,7 @@ foreach($formats as $format) { } ?> ---EXPECT-- +--EXPECTF-- *** Testing vprintf() : unsigned formats and unsigned values *** -- Iteration 1 -- @@ -56,6 +56,8 @@ int(16) int(22) -- Iteration 3 -- + +Warning: The float 1.0E+21 is not representable as an int, cast occurred in %s on line %d 1234000 3875820019684212736 120 int(34) diff --git a/ext/standard/tests/strings/vprintf_variation16.phpt b/ext/standard/tests/strings/vprintf_variation16.phpt index 70ecdab99e071..c064b7c4f0c78 100644 --- a/ext/standard/tests/strings/vprintf_variation16.phpt +++ b/ext/standard/tests/strings/vprintf_variation16.phpt @@ -66,10 +66,16 @@ foreach($args_array as $args) { $counter++; } ?> ---EXPECT-- +--EXPECTF-- *** Testing vprintf() : unsigned formats and signed & other types of values *** -- Iteration 1 -- + +Warning: The float 20000000000 is not representable as an int, cast occurred in %s on line %d + +Warning: The float 2000000000000 is not representable as an int, cast occurred in %s on line %d + +Warning: The float 22000000000000 is not representable as an int, cast occurred in %s on line %d 2 0 10 123456 123456 1234 2820130816 2840207360 1177509888 diff --git a/ext/standard/tests/strings/vprintf_variation4.phpt b/ext/standard/tests/strings/vprintf_variation4.phpt index 63018a9db8a86..96836f83ee618 100644 --- a/ext/standard/tests/strings/vprintf_variation4.phpt +++ b/ext/standard/tests/strings/vprintf_variation4.phpt @@ -67,10 +67,12 @@ foreach($args_array as $args) { } ?> ---EXPECT-- +--EXPECTF-- *** Testing vprintf() : int formats and non-integer values *** -- Iteration 1 -- + +Warning: The float 20000000000 is not representable as an int, cast occurred in %s on line %d 2 +0 10 123456 -1234 1234 -1474836480 200000 4000 22000000 diff --git a/ext/standard/type.c b/ext/standard/type.c index 4557014ff5a33..c05926b1a3770 100644 --- a/ext/standard/type.c +++ b/ext/standard/type.c @@ -173,14 +173,17 @@ PHP_FUNCTION(intval) } if (strval[offset] == '0' && (strval[offset + 1] == 'b' || strval[offset + 1] == 'B')) { + if (strval[0] != '-') { + /* Either "+0b", or "0b" */ + RETURN_LONG(ZEND_STRTOL(strval + 2 + offset, NULL, 2)); + } + char *tmpval; strlen -= 2; /* Removing "0b" */ tmpval = emalloc(strlen + 1); - /* Place the unary symbol at pos 0 if there was one */ - if (offset) { - tmpval[0] = strval[0]; - } + /* Place the unary symbol at pos 0 */ + tmpval[0] = '-'; /* Copy the data from after "0b" to the end of the buffer */ memcpy(tmpval + offset, strval + offset + 2, strlen - offset); diff --git a/ext/standard/url.c b/ext/standard/url.c index 504805484ef2c..4ddf7f80c64f9 100644 --- a/ext/standard/url.c +++ b/ext/standard/url.c @@ -93,7 +93,7 @@ PHPAPI php_url *php_url_parse_ex2(char const *str, size_t length, bool *has_port php_url *ret = ecalloc(1, sizeof(php_url)); char const *s, *e, *p, *pp, *ue; - *has_port = 0; + *has_port = false; s = str; ue = s + length; @@ -183,7 +183,7 @@ PHPAPI php_url *php_url_parse_ex2(char const *str, size_t length, bool *has_port port_buf[pp - p] = '\0'; port = ZEND_STRTOL(port_buf, &end, 10); if (port >= 0 && port <= 65535 && end != port_buf) { - *has_port = 1; + *has_port = true; ret->port = (unsigned short) port; if (s + 1 < ue && *s == '/' && *(s + 1) == '/') { /* relative-scheme URL */ s += 2; @@ -249,7 +249,7 @@ PHPAPI php_url *php_url_parse_ex2(char const *str, size_t length, bool *has_port port_buf[e - p] = '\0'; port = ZEND_STRTOL(port_buf, &end, 10); if (port >= 0 && port <= 65535 && end != port_buf) { - *has_port = 1; + *has_port = true; ret->port = (unsigned short)port; } else { php_url_free(ret); diff --git a/ext/standard/user_filters.c b/ext/standard/user_filters.c index d91e168ce53a7..da8260dfd6de3 100644 --- a/ext/standard/user_filters.c +++ b/ext/standard/user_filters.c @@ -148,14 +148,31 @@ static php_stream_filter_status_t userfilter_filter( uint32_t orig_no_fclose = stream->flags & PHP_STREAM_FLAG_NO_FCLOSE; stream->flags |= PHP_STREAM_FLAG_NO_FCLOSE; - zval *stream_prop = zend_hash_str_find_ind(Z_OBJPROP_P(obj), "stream", sizeof("stream")-1); - if (stream_prop) { - /* Give the userfilter class a hook back to the stream */ - zval_ptr_dtor(stream_prop); - php_stream_to_zval(stream, stream_prop); - Z_ADDREF_P(stream_prop); + /* Give the userfilter class a hook back to the stream */ + const zend_class_entry *old_scope = EG(fake_scope); + EG(fake_scope) = Z_OBJCE_P(obj); + + zend_string *stream_name = ZSTR_INIT_LITERAL("stream", 0); + bool stream_property_exists = Z_OBJ_HT_P(obj)->has_property(Z_OBJ_P(obj), stream_name, ZEND_PROPERTY_EXISTS, NULL); + if (stream_property_exists) { + zval stream_zval; + php_stream_to_zval(stream, &stream_zval); + zend_update_property_ex(Z_OBJCE_P(obj), Z_OBJ_P(obj), stream_name, &stream_zval); + /* If property update threw an exception, skip filter execution */ + if (EG(exception)) { + EG(fake_scope) = old_scope; + if (buckets_in->head) { + php_error_docref(NULL, E_WARNING, "Unprocessed filter buckets remaining on input brigade"); + } + zend_string_release(stream_name); + stream->flags &= ~PHP_STREAM_FLAG_NO_FCLOSE; + stream->flags |= orig_no_fclose; + return PSFS_ERR_FATAL; + } } + EG(fake_scope) = old_scope; + ZVAL_STRINGL(&func_name, "filter", sizeof("filter")-1); /* Setup calling arguments */ @@ -196,11 +213,16 @@ static php_stream_filter_status_t userfilter_filter( /* filter resources are cleaned up by the stream destructor, * keeping a reference to the stream resource here would prevent it - * from being destroyed properly */ - if (stream_prop) { - convert_to_null(stream_prop); + * from being destroyed properly. + * Since the property accepted a resource assignment above, it must have + * no type hint or be typed as mixed, so we can safely assign null. + */ + if (stream_property_exists) { + zend_update_property_null(Z_OBJCE_P(obj), Z_OBJ_P(obj), ZSTR_VAL(stream_name), ZSTR_LEN(stream_name)); } + zend_string_release(stream_name); + zval_ptr_dtor(&args[3]); zval_ptr_dtor(&args[2]); zval_ptr_dtor(&args[1]); @@ -237,7 +259,7 @@ static php_stream_filter *user_filter_factory_create(const char *filtername, len = strlen(filtername); /* determine the classname/class entry */ - if (NULL == (fdat = zend_hash_str_find_ptr(BG(user_filter_map), (char*)filtername, len))) { + if (NULL == (fdat = zend_hash_str_find_ptr(BG(user_filter_map), filtername, len))) { char *period; /* Userspace Filters using ambiguous wildcards could cause problems. @@ -283,13 +305,9 @@ 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); + add_property_string(&obj, "filtername", filtername); /* and the parameters, if any */ if (filterparams) { @@ -305,9 +323,6 @@ static php_stream_filter *user_filter_factory_create(const char *filtername, if (Z_TYPE(retval) != IS_UNDEF) { if (Z_TYPE(retval) == IS_FALSE) { - /* User reported filter creation error "return false;" */ - zval_ptr_dtor(&retval); - /* Kill the filter (safely) */ ZVAL_UNDEF(&filter->abstract); php_stream_filter_free(filter); @@ -408,17 +423,19 @@ static void php_stream_bucket_attach(int append, INTERNAL_FUNCTION_PARAMETERS) memcpy(bucket->buf, Z_STRVAL_P(pzdata), bucket->buflen); } + /* If the bucket is already on a brigade we have to unlink it first to keep the + * linked list consistent. Furthermore, we can transfer the refcount in that case. */ + if (bucket->brigade) { + php_stream_bucket_unlink(bucket); + } else { + bucket->refcount++; + } + if (append) { php_stream_bucket_append(brigade, bucket); } else { php_stream_bucket_prepend(brigade, bucket); } - /* This is a hack necessary to accommodate situations where bucket is appended to the stream - * multiple times. See bug35916.phpt for reference. - */ - if (bucket->refcount == 1) { - bucket->refcount++; - } } /* }}} */ diff --git a/ext/standard/user_filters_arginfo.h b/ext/standard/user_filters_arginfo.h index 0411355b71222..9fd13204e2322 100644 --- a/ext/standard/user_filters_arginfo.h +++ b/ext/standard/user_filters_arginfo.h @@ -44,21 +44,21 @@ static zend_class_entry *register_class_php_user_filter(void) zval property_filtername_default_value; ZVAL_EMPTY_STRING(&property_filtername_default_value); - zend_string *property_filtername_name = zend_string_init("filtername", sizeof("filtername") - 1, 1); + zend_string *property_filtername_name = zend_string_init("filtername", sizeof("filtername") - 1, true); zend_declare_typed_property(class_entry, property_filtername_name, &property_filtername_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_filtername_name); + zend_string_release_ex(property_filtername_name, true); zval property_params_default_value; ZVAL_EMPTY_STRING(&property_params_default_value); - zend_string *property_params_name = zend_string_init("params", sizeof("params") - 1, 1); + zend_string *property_params_name = zend_string_init("params", sizeof("params") - 1, true); zend_declare_typed_property(class_entry, property_params_name, &property_params_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ANY)); - zend_string_release(property_params_name); + zend_string_release_ex(property_params_name, true); zval property_stream_default_value; ZVAL_NULL(&property_stream_default_value); - zend_string *property_stream_name = zend_string_init("stream", sizeof("stream") - 1, 1); + zend_string *property_stream_name = zend_string_init("stream", sizeof("stream") - 1, true); zend_declare_typed_property(class_entry, property_stream_name, &property_stream_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0)); - zend_string_release(property_stream_name); + zend_string_release_ex(property_stream_name, true); return class_entry; } @@ -72,27 +72,27 @@ static zend_class_entry *register_class_StreamBucket(void) zval property_bucket_default_value; ZVAL_NULL(&property_bucket_default_value); - zend_string *property_bucket_name = zend_string_init("bucket", sizeof("bucket") - 1, 1); + zend_string *property_bucket_name = zend_string_init("bucket", sizeof("bucket") - 1, true); zend_declare_typed_property(class_entry, property_bucket_name, &property_bucket_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0)); - zend_string_release(property_bucket_name); + zend_string_release_ex(property_bucket_name, true); zval property_data_default_value; ZVAL_UNDEF(&property_data_default_value); - zend_string *property_data_name = zend_string_init("data", sizeof("data") - 1, 1); + zend_string *property_data_name = zend_string_init("data", sizeof("data") - 1, true); zend_declare_typed_property(class_entry, property_data_name, &property_data_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_data_name); + zend_string_release_ex(property_data_name, true); zval property_datalen_default_value; ZVAL_UNDEF(&property_datalen_default_value); - zend_string *property_datalen_name = zend_string_init("datalen", sizeof("datalen") - 1, 1); + zend_string *property_datalen_name = zend_string_init("datalen", sizeof("datalen") - 1, true); zend_declare_typed_property(class_entry, property_datalen_name, &property_datalen_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_datalen_name); + zend_string_release_ex(property_datalen_name, true); zval property_dataLength_default_value; ZVAL_UNDEF(&property_dataLength_default_value); - zend_string *property_dataLength_name = zend_string_init("dataLength", sizeof("dataLength") - 1, 1); + zend_string *property_dataLength_name = zend_string_init("dataLength", sizeof("dataLength") - 1, true); zend_declare_typed_property(class_entry, property_dataLength_name, &property_dataLength_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_dataLength_name); + zend_string_release_ex(property_dataLength_name, true); return class_entry; } diff --git a/ext/standard/var.c b/ext/standard/var.c index 1c2b0eb164a1c..a1ef60410a338 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -153,7 +153,7 @@ PHPAPI void php_var_dump(zval *struc, int level) /* {{{ */ } ZEND_HASH_FOREACH_END(); if (!(GC_FLAGS(myht) & GC_IMMUTABLE)) { GC_UNPROTECT_RECURSION(myht); - GC_DELREF(myht); + GC_DTOR_NO_REF(myht); } if (level > 1) { php_printf("%*c", level-1, ' '); @@ -354,7 +354,7 @@ PHPAPI void php_debug_zval_dump(zval *struc, int level) /* {{{ */ } ZEND_HASH_FOREACH_END(); if (!(GC_FLAGS(myht) & GC_IMMUTABLE)) { GC_UNPROTECT_RECURSION(myht); - GC_DELREF(myht); + GC_DTOR_NO_REF(myht); } if (level > 1) { php_printf("%*c", level - 1, ' '); @@ -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; } @@ -981,7 +984,7 @@ static void php_var_serialize_nested_data(smart_str *buf, zval *struc, HashTable ZEND_HASH_FOREACH_KEY_VAL_IND(ht, index, key, data) { if (incomplete_class && zend_string_equals_literal(key, MAGIC_MEMBER)) { - incomplete_class = 0; + incomplete_class = false; continue; } @@ -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); @@ -1027,7 +1023,8 @@ static void php_var_serialize_class(smart_str *buf, zval *struc, HashTable *ht, if (php_var_serialize_get_sleep_props(&props, struc, ht) == SUCCESS) { php_var_serialize_class_name(buf, struc); php_var_serialize_nested_data( - buf, struc, &props, zend_hash_num_elements(&props), /* incomplete_class */ 0, var_hash, GC_REFCOUNT(&props) > 1); + buf, struc, &props, zend_hash_num_elements(&props), /* incomplete_class */ false, var_hash, + GC_REFCOUNT(&props) > 1); } zend_hash_destroy(&props); } @@ -1303,8 +1300,8 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_ smart_str_appendl(buf, "a:", 2); myht = Z_ARRVAL_P(struc); php_var_serialize_nested_data( - buf, struc, myht, zend_array_count(myht), /* incomplete_class */ 0, var_hash, - !is_root && (in_rcn_array || GC_REFCOUNT(myht) > 1)); + buf, struc, myht, zend_array_count(myht), /* incomplete_class */ false, var_hash, + !is_root && (in_rcn_array || GC_REFCOUNT(myht) > 1)); return; case IS_REFERENCE: struc = Z_REFVAL_P(struc); @@ -1418,19 +1415,20 @@ PHPAPI void php_unserialize_with_options(zval *return_value, const char *buf, co function_name, zend_zval_value_name(entry)); goto cleanup; } - zend_string *name = zval_try_get_string(entry); + zend_string *tmp_str; + zend_string *name = zval_try_get_tmp_string(entry, &tmp_str); if (UNEXPECTED(name == NULL)) { goto cleanup; } if (UNEXPECTED(!zend_is_valid_class_name(name))) { zend_value_error("%s(): Option \"allowed_classes\" must be an array of class names, \"%s\" given", function_name, ZSTR_VAL(name)); - zend_string_release_ex(name, false); + zend_tmp_string_release(tmp_str); goto cleanup; } zend_string *lcname = zend_string_tolower(name); zend_hash_add_empty_element(class_hash, lcname); - zend_string_release_ex(name, false); zend_string_release_ex(lcname, false); + zend_tmp_string_release(tmp_str); } ZEND_HASH_FOREACH_END(); } php_var_unserialize_set_allowed_classes(var_hash, class_hash); 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..65d29d12c0f9e 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); } /* }}} */ @@ -265,13 +256,11 @@ PHP_FUNCTION(msg_receive) zval *out_message, *queue, *out_msgtype, *zerrcode = NULL; zend_long desiredmsgtype, maxsize, flags = 0; zend_long realflags = 0; - bool do_unserialize = 1; + bool do_unserialize = true; sysvmsg_queue_t *mq = NULL; 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); } @@ -347,14 +337,12 @@ PHP_FUNCTION(msg_send) { zval *message, *queue, *zerror=NULL; zend_long msgtype; - bool do_serialize = 1, blocking = 1; + bool do_serialize = true, blocking = true; sysvmsg_queue_t * mq = NULL; struct php_msgbuf * messagebuffer = NULL; /* buffer to transmit */ 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..ce624ab4b2372 100644 --- a/ext/sysvsem/sysvsem.c +++ b/ext/sysvsem/sysvsem.c @@ -172,7 +172,7 @@ PHP_MINFO_FUNCTION(sysvsem) PHP_FUNCTION(sem_get) { zend_long key, max_acquire = 1, perm = 0666; - bool auto_release = 1; + bool auto_release = true; int semid; struct sembuf sop[3]; int count; @@ -266,10 +266,10 @@ 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; + bool nowait = false; sysvsem_sem *sem_ptr; struct sembuf sop; @@ -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..55ee6493bfb0a 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) @@ -131,7 +131,7 @@ PHP_FUNCTION(shm_attach) char *shm_ptr; sysvshm_chunk_head *chunk_ptr; zend_long shm_key, shm_id, shm_size, shm_flag = 0666; - bool shm_size_is_null = 1; + bool shm_size_is_null = true; if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "l|l!l", &shm_key, &shm_size, &shm_size_is_null, &shm_flag)) { RETURN_THROWS(); @@ -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..18fa9acb3d4bd 100644 --- a/ext/tidy/config.m4 +++ b/ext/tidy/config.m4 @@ -57,17 +57,35 @@ if test "$PHP_TIDY" != "no"; then [], [-L$TIDY_LIBDIR]) - PHP_CHECK_LIBRARY([$TIDY_LIB_NAME], [tidyOptGetCategory], - [AC_DEFINE([HAVE_TIDYOPTGETCATEGORY], [1], - [Define to 1 if Tidy library has the 'tidyOptGetCategory' function.])], - [], - [-L$TIDY_LIBDIR]) - PHP_ADD_LIBRARY_WITH_PATH([$TIDY_LIB_NAME], [$TIDY_LIBDIR], [TIDY_SHARED_LIBADD]) PHP_ADD_INCLUDE([$TIDY_INCDIR]) + old_CPPFLAGS=$CPPFLAGS + CPPFLAGS=-I$TIDY_INCDIR + + dnl The tidyOptGetCategory function (added in tidy-html5 5.4.0) is only + dnl useable if TidyInternalCategory (added in tidy-html5 5.6.0) is also + dnl present. + AC_CACHE_CHECK([for tidyOptGetCategory], [php_ac_cv_have_tidyoptgetcategory], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ],[ + TidyDoc doc = tidyCreate(); + TidyOption badopt = tidyGetOptionByName(doc, ""); + Bool v = (tidyOptGetCategory(badopt) == TidyInternalCategory); + (void)v; + tidyRelease(doc); + ])], + [php_ac_cv_have_tidyoptgetcategory=yes], + [php_ac_cv_have_tidyoptgetcategory=no]) + ]) + AS_VAR_IF([php_ac_cv_have_tidyoptgetcategory], [yes], + [AC_DEFINE([HAVE_TIDYOPTGETCATEGORY], [1], + [Define to 1 if Tidy library has the 'tidyOptGetCategory' function and + supports the 'TidyInternalCategory' enumeration.])]) + + CPPFLAGS=$old_CPPFLAGS + dnl Add -Wno-ignored-qualifiers as this is an issue upstream. Fixed in dnl tidy-html5 5.7.20: https://github.com/htacg/tidy-html5/issues/866 PHP_NEW_EXTENSION([tidy], diff --git a/ext/tidy/config.w32 b/ext/tidy/config.w32 index a1f93f2976af8..1b2436ac9dfad 100644 --- a/ext/tidy/config.w32 +++ b/ext/tidy/config.w32 @@ -21,6 +21,7 @@ if (PHP_TIDY != "no") { AC_DEFINE('HAVE_TIDY_H', 1, "Define to 1 if you have the header file.") AC_DEFINE('HAVE_TIDYOPTGETDOC', 1, "Define to 1 if Tidy library has the 'tidyOptGetDoc' function.") AC_DEFINE('HAVE_TIDYRELEASEDATE', 1, "Define to 1 if Tidy library has the 'tidyReleaseDate' function.") + AC_DEFINE('HAVE_TIDYOPTGETCATEGORY', 1, "Define to 1 if Tidy library has the 'tidyOptGetCategory' function and supports the 'TidyInternalCategory' enumeration.") ADD_FLAG('CFLAGS_TIDY', '/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1'); if (!PHP_TIDY_SHARED) { ADD_DEF_FILE("ext\\tidy\\php_tidy.def"); diff --git a/ext/tidy/tests/018.phpt b/ext/tidy/tests/018.phpt index b07770eebb2b1..e3934aa6d9fa0 100644 --- a/ext/tidy/tests/018.phpt +++ b/ext/tidy/tests/018.phpt @@ -7,7 +7,7 @@ tidy $x = tidy_repair_string("

abra\0cadabra

", array( 'show-body-only' => true, 'clean' => false, - 'newline' => "\n") + 'newline' => "LF") ); var_dump($x); ?> 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/gh20374.phpt b/ext/tidy/tests/gh20374.phpt new file mode 100644 index 0000000000000..39c3ba06d315e --- /dev/null +++ b/ext/tidy/tests/gh20374.phpt @@ -0,0 +1,175 @@ +--TEST-- +GH-20374 (PHP with tidy and custom-tags) +--EXTENSIONS-- +tidy +--CREDITS-- +franck-paul +--FILE-- +ret; + } +} + +class MyThrowingStringable { + public function __toString(): string { + throw new Error('no'); + } +} + +$values = [ + 'string blocklevel' => 'blocklevel', + 'int' => 1, + 'double overflow' => (string) (2.0**80.0), + 'numeric string int 1' => '1', + 'numeric string double 1.0' => '1.0', + 'false' => false, + 'true' => true, + 'NAN' => NAN, + 'INF' => INF, + 'object with numeric string int 0' => new MyStringable('0'), + 'object with string blocklevel' => new MyStringable('blocklevel'), + 'object with string empty' => new MyStringable('empty'), + 'object with exception' => new MyThrowingStringable, +]; + +foreach ($values as $key => $value) { + echo "--- $key ---\n"; + $str = 'test'; + + $config = [ + 'custom-tags' => $value, + ]; + + $tidy = new tidy(); + try { + $tidy->parseString($str, $config, 'utf8'); + echo $tidy->value, "\n"; + } catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), "\n"; + } +} + +?> +--EXPECTF-- +--- string blocklevel --- + + + + + +test + + +--- int --- + + + + + +test + + +--- double overflow --- + +Warning: The float-string "1.2089258196146E+24" is not representable as an int, cast occurred in %s on line %d + + + + + +test + + +--- numeric string int 1 --- + + + + + +test + + +--- numeric string double 1.0 --- + + + + + +test + + +--- false --- + + + + + +test + + +--- true --- + + + + + +test + + +--- NAN --- + +Warning: The float NAN is not representable as an int, cast occurred in %s on line %d + + + + + +test + + +--- INF --- + +Warning: The float INF is not representable as an int, cast occurred in %s on line %d + + + + + +test + + +--- object with numeric string int 0 --- + + + + + +test + + +--- object with string blocklevel --- + + + + + +test + + +--- object with string empty --- + + + + + + +test + + +--- object with exception --- +Error: no 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..8cf45dc7fcbbc 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) { @@ -440,7 +387,7 @@ static zend_object *tidy_object_new(zend_class_entry *class_type, const zend_obj efree(intern->ptdoc->errbuf); tidyRelease(intern->ptdoc->doc); efree(intern->ptdoc); - efree(intern); + /* TODO: convert to exception */ php_error_docref(NULL, E_ERROR, "Could not set Tidy error buffer"); } @@ -526,8 +473,7 @@ static zend_result tidy_node_cast_handler(zend_object *in, zval *out, int type) case IS_STRING: obj = php_tidy_fetch_object(in); tidyBufInit(&buf); - if (obj->ptdoc) { - tidyNodeGetText(obj->ptdoc->doc, obj->node, &buf); + if (obj->ptdoc && tidyNodeGetText(obj->ptdoc->doc, obj->node, &buf)) { ZVAL_STRINGL(out, (const char *) buf.bp, buf.size-1); } else { ZVAL_EMPTY_STRING(out); @@ -583,7 +529,7 @@ static void tidy_add_node_default_properties(PHPTidyObj *obj) const char *name; tidyBufInit(&buf); - tidyNodeGetText(obj->ptdoc->doc, obj->node, &buf); + (void) tidyNodeGetText(obj->ptdoc->doc, obj->node, &buf); zend_update_property_stringl( tidy_ce_node, @@ -669,12 +615,14 @@ static void tidy_add_node_default_properties(PHPTidyObj *obj) do { const char *attr_name = tidyAttrName(tempattr); if (attr_name) { + zval value; const char *val = tidyAttrValue(tempattr); if (val) { - add_assoc_string(&attribute, attr_name, val); + ZVAL_STRING_FAST(&value, val); } else { - add_assoc_str(&attribute, attr_name, zend_empty_string); + ZVAL_EMPTY_STRING(&value); } + zend_hash_str_add_new(Z_ARRVAL(attribute), attr_name, strlen(attr_name), &value); } } while((tempattr = tidyAttrNext(tempattr))); } else { @@ -720,28 +668,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 +715,100 @@ 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; + zend_string *tmp_str; + + 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) { + 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) { /* integer or enum */ + ZVAL_DEREF(value); + /* Enum will correspond to a non-numeric string or object */ + if (Z_TYPE_P(value) == IS_STRING || Z_TYPE_P(value) == IS_OBJECT) { + double dval; + bool result; + const zend_string *str = zval_try_get_tmp_string(value, &tmp_str); + if (UNEXPECTED(!str)) { + return false; + } + uint8_t type = is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), &lval, &dval, true); + if (type == IS_DOUBLE) { + lval = zend_dval_to_lval_cap(dval, str); + type = IS_LONG; + } + if (type == IS_LONG) { + result = tidyOptSetInt(doc, tidyOptGetId(opt), lval); + } else { + 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 { + 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 +818,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 +1024,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 +1077,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 +1092,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 +1330,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 +1357,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 +1377,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 +1402,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 +1414,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 +1442,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/tidy/tidy_arginfo.h b/ext/tidy/tidy_arginfo.h index 4084a29f4d908..2448b3bca2940 100644 --- a/ext/tidy/tidy_arginfo.h +++ b/ext/tidy/tidy_arginfo.h @@ -476,9 +476,9 @@ static zend_class_entry *register_class_tidy(void) zval property_errorBuffer_default_value; ZVAL_NULL(&property_errorBuffer_default_value); - zend_string *property_errorBuffer_name = zend_string_init("errorBuffer", sizeof("errorBuffer") - 1, 1); + zend_string *property_errorBuffer_name = zend_string_init("errorBuffer", sizeof("errorBuffer") - 1, true); zend_declare_typed_property(class_entry, property_errorBuffer_name, &property_errorBuffer_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING|MAY_BE_NULL)); - zend_string_release(property_errorBuffer_name); + zend_string_release_ex(property_errorBuffer_name, true); zval property_value_default_value; ZVAL_NULL(&property_value_default_value); @@ -512,33 +512,33 @@ static zend_class_entry *register_class_tidyNode(void) zval property_column_default_value; ZVAL_UNDEF(&property_column_default_value); - zend_string *property_column_name = zend_string_init("column", sizeof("column") - 1, 1); + zend_string *property_column_name = zend_string_init("column", sizeof("column") - 1, true); zend_declare_typed_property(class_entry, property_column_name, &property_column_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_column_name); + zend_string_release_ex(property_column_name, true); zval property_proprietary_default_value; ZVAL_UNDEF(&property_proprietary_default_value); - zend_string *property_proprietary_name = zend_string_init("proprietary", sizeof("proprietary") - 1, 1); + zend_string *property_proprietary_name = zend_string_init("proprietary", sizeof("proprietary") - 1, true); zend_declare_typed_property(class_entry, property_proprietary_name, &property_proprietary_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_proprietary_name); + zend_string_release_ex(property_proprietary_name, true); 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_string *property_id_name = zend_string_init("id", sizeof("id") - 1, true); zend_declare_typed_property(class_entry, property_id_name, &property_id_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG|MAY_BE_NULL)); - zend_string_release(property_id_name); + zend_string_release_ex(property_id_name, true); zval property_attribute_default_value; ZVAL_UNDEF(&property_attribute_default_value); - zend_string *property_attribute_name = zend_string_init("attribute", sizeof("attribute") - 1, 1); + zend_string *property_attribute_name = zend_string_init("attribute", sizeof("attribute") - 1, true); zend_declare_typed_property(class_entry, property_attribute_name, &property_attribute_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ARRAY|MAY_BE_NULL)); - zend_string_release(property_attribute_name); + zend_string_release_ex(property_attribute_name, true); zval property_child_default_value; ZVAL_UNDEF(&property_child_default_value); - zend_string *property_child_name = zend_string_init("child", sizeof("child") - 1, 1); + zend_string *property_child_name = zend_string_init("child", sizeof("child") - 1, true); zend_declare_typed_property(class_entry, property_child_name, &property_child_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ARRAY|MAY_BE_NULL)); - zend_string_release(property_child_name); + zend_string_release_ex(property_child_name, true); return class_entry; } 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('= 1.0.0]) + 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 php_uriparser.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 6954ca06af555..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 php_uriparser.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 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 UriShorten.c", "uri"); -PHP_INSTALL_HEADERS("ext/uri", "php_lexbor.h php_uri.h php_uri_common.h php_uriparser.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_lexbor.c b/ext/uri/php_lexbor.c deleted file mode 100644 index 5287bbcd9023d..0000000000000 --- a/ext/uri/php_lexbor.c +++ /dev/null @@ -1,638 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Máté Kocsis | - +----------------------------------------------------------------------+ -*/ - -#include "php.h" -#include "php_lexbor.h" -#include "php_uri_common.h" -#include "Zend/zend_enum.h" -#include "Zend/zend_smart_str.h" -#include "Zend/zend_exceptions.h" -#ifdef HAVE_ARPA_INET_H -#include -#endif - -ZEND_TLS lxb_url_parser_t lexbor_parser; -ZEND_TLS unsigned short int lexbor_urls; - -#define LEXBOR_MAX_URL_COUNT 500 -#define LEXBOR_MRAW_BYTE_SIZE 8192 - -static zend_always_inline void zval_string_or_null_to_lexbor_str(zval *value, lexbor_str_t *lexbor_str) -{ - if (Z_TYPE_P(value) == IS_STRING && Z_STRLEN_P(value) > 0) { - lexbor_str->data = (lxb_char_t *) Z_STRVAL_P(value); - lexbor_str->length = Z_STRLEN_P(value); - } else { - ZEND_ASSERT(Z_ISNULL_P(value) || (Z_TYPE_P(value) == IS_STRING && Z_STRLEN_P(value) == 0)); - lexbor_str->data = (lxb_char_t *) ""; - lexbor_str->length = 0; - } -} - -static zend_always_inline void zval_long_or_null_to_lexbor_str(zval *value, lexbor_str_t *lexbor_str) -{ - if (Z_TYPE_P(value) == IS_LONG) { - ZVAL_STR(value, zend_long_to_str(Z_LVAL_P(value))); - lexbor_str_init_append(lexbor_str, lexbor_parser.mraw, (const lxb_char_t *) Z_STRVAL_P(value), Z_STRLEN_P(value)); - zval_ptr_dtor_str(value); - } else { - ZEND_ASSERT(Z_ISNULL_P(value)); - lexbor_str->data = (lxb_char_t *) ""; - lexbor_str->length = 0; - } -} - -static void lexbor_cleanup_parser(void) -{ - if (++lexbor_urls % LEXBOR_MAX_URL_COUNT == 0) { - lexbor_mraw_clean(lexbor_parser.mraw); - lexbor_urls = 0; - } - - lxb_url_parser_clean(&lexbor_parser); -} - -/** - * Creates a Uri\WhatWg\UrlValidationError class by mapping error codes listed in - * https://url.spec.whatwg.org/#writing to a Uri\WhatWg\UrlValidationErrorType enum. - * The result is passed by reference to the errors parameter. - * - * When errors is NULL, the caller is not interested in the additional error information, - * so the function does nothing. - */ -static const char *fill_errors(zval *errors) -{ - if (errors == NULL) { - return NULL; - } - - ZEND_ASSERT(Z_ISUNDEF_P(errors)); - - array_init(errors); - - if (lexbor_parser.log == NULL) { - return NULL; - } - - const char *result = NULL; - lexbor_plog_entry_t *lxb_error; - while ((lxb_error = lexbor_array_obj_pop(&lexbor_parser.log->list)) != NULL) { - zval error; - object_init_ex(&error, uri_whatwg_url_validation_error_ce); - zend_update_property_string(uri_whatwg_url_validation_error_ce, Z_OBJ(error), ZEND_STRL("context"), (const char *) lxb_error->data); - - const char *error_str; - zval failure; - switch (lxb_error->id) { - case LXB_URL_ERROR_TYPE_DOMAIN_TO_ASCII: - error_str = "DomainToAscii"; - ZVAL_TRUE(&failure); - break; - case LXB_URL_ERROR_TYPE_DOMAIN_TO_UNICODE: - error_str = "DomainToUnicode"; - ZVAL_FALSE(&failure); - break; - case LXB_URL_ERROR_TYPE_DOMAIN_INVALID_CODE_POINT: - error_str = "DomainInvalidCodePoint"; - ZVAL_TRUE(&failure); - break; - case LXB_URL_ERROR_TYPE_HOST_INVALID_CODE_POINT: - error_str = "HostInvalidCodePoint"; - ZVAL_TRUE(&failure); - break; - case LXB_URL_ERROR_TYPE_IPV4_EMPTY_PART: - error_str = "Ipv4EmptyPart"; - ZVAL_FALSE(&failure); - break; - case LXB_URL_ERROR_TYPE_IPV4_TOO_MANY_PARTS: - error_str = "Ipv4TooManyParts"; - ZVAL_TRUE(&failure); - break; - case LXB_URL_ERROR_TYPE_IPV4_NON_NUMERIC_PART: - error_str = "Ipv4NonNumericPart"; - ZVAL_TRUE(&failure); - break; - case LXB_URL_ERROR_TYPE_IPV4_NON_DECIMAL_PART: - error_str = "Ipv4NonDecimalPart"; - ZVAL_FALSE(&failure); - break; - case LXB_URL_ERROR_TYPE_IPV4_OUT_OF_RANGE_PART: - error_str = "Ipv4OutOfRangePart"; - ZVAL_TRUE(&failure); - break; - case LXB_URL_ERROR_TYPE_IPV6_UNCLOSED: - error_str = "Ipv6Unclosed"; - ZVAL_TRUE(&failure); - break; - case LXB_URL_ERROR_TYPE_IPV6_INVALID_COMPRESSION: - error_str = "Ipv6InvalidCompression"; - ZVAL_TRUE(&failure); - break; - case LXB_URL_ERROR_TYPE_IPV6_TOO_MANY_PIECES: - error_str = "Ipv6TooManyPieces"; - ZVAL_TRUE(&failure); - break; - case LXB_URL_ERROR_TYPE_IPV6_MULTIPLE_COMPRESSION: - error_str = "Ipv6MultipleCompression"; - ZVAL_TRUE(&failure); - break; - case LXB_URL_ERROR_TYPE_IPV6_INVALID_CODE_POINT: - error_str = "Ipv6InvalidCodePoint"; - ZVAL_TRUE(&failure); - break; - case LXB_URL_ERROR_TYPE_IPV6_TOO_FEW_PIECES: - error_str = "Ipv6TooFewPieces"; - ZVAL_TRUE(&failure); - break; - case LXB_URL_ERROR_TYPE_IPV4_IN_IPV6_TOO_MANY_PIECES: - error_str = "Ipv4InIpv6TooManyPieces"; - ZVAL_TRUE(&failure); - break; - case LXB_URL_ERROR_TYPE_IPV4_IN_IPV6_INVALID_CODE_POINT: - error_str = "Ipv4InIpv6InvalidCodePoint"; - ZVAL_TRUE(&failure); - break; - case LXB_URL_ERROR_TYPE_IPV4_IN_IPV6_OUT_OF_RANGE_PART: - error_str = "Ipv4InIpv6OutOfRangePart"; - ZVAL_TRUE(&failure); - break; - case LXB_URL_ERROR_TYPE_IPV4_IN_IPV6_TOO_FEW_PARTS: - error_str = "Ipv4InIpv6TooFewParts"; - ZVAL_TRUE(&failure); - break; - case LXB_URL_ERROR_TYPE_INVALID_URL_UNIT: - error_str = "InvalidUrlUnit"; - ZVAL_FALSE(&failure); - break; - case LXB_URL_ERROR_TYPE_SPECIAL_SCHEME_MISSING_FOLLOWING_SOLIDUS: - error_str = "SpecialSchemeMissingFollowingSolidus"; - ZVAL_FALSE(&failure); - break; - case LXB_URL_ERROR_TYPE_MISSING_SCHEME_NON_RELATIVE_URL: - error_str = "MissingSchemeNonRelativeUrl"; - ZVAL_TRUE(&failure); - break; - case LXB_URL_ERROR_TYPE_INVALID_REVERSE_SOLIDUS: - error_str = "InvalidReverseSoldius"; - ZVAL_FALSE(&failure); - break; - case LXB_URL_ERROR_TYPE_INVALID_CREDENTIALS: - error_str = "InvalidCredentials"; - ZVAL_FALSE(&failure); - break; - case LXB_URL_ERROR_TYPE_HOST_MISSING: - error_str = "HostMissing"; - ZVAL_TRUE(&failure); - break; - case LXB_URL_ERROR_TYPE_PORT_OUT_OF_RANGE: - error_str = "PortOutOfRange"; - ZVAL_TRUE(&failure); - break; - case LXB_URL_ERROR_TYPE_PORT_INVALID: - error_str = "PortInvalid"; - ZVAL_TRUE(&failure); - break; - case LXB_URL_ERROR_TYPE_FILE_INVALID_WINDOWS_DRIVE_LETTER: - error_str = "FileInvalidWindowsDriveLetter"; - ZVAL_FALSE(&failure); - break; - case LXB_URL_ERROR_TYPE_FILE_INVALID_WINDOWS_DRIVE_LETTER_HOST: - error_str = "FileInvalidWindowsDriveLetterHost"; - ZVAL_FALSE(&failure); - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - - zval error_type; - ZVAL_OBJ(&error_type, zend_enum_get_case_cstr(uri_whatwg_url_validation_error_type_ce, error_str)); - zend_update_property_ex(uri_whatwg_url_validation_error_ce, Z_OBJ(error), ZSTR_KNOWN(ZEND_STR_TYPE), &error_type); - - zend_update_property(uri_whatwg_url_validation_error_ce, Z_OBJ(error), ZEND_STRL("failure"), &failure); - - if (Z_TYPE(failure) == IS_TRUE) { - result = error_str; - } - - add_next_index_zval(errors, &error); - } - - return result; -} - -static void throw_invalid_url_exception_during_write(zval *errors, const char *component) -{ - const char *reason = fill_errors(errors); - zend_object *exception = zend_throw_exception_ex( - uri_whatwg_invalid_url_exception_ce, - 0, - "The specified %s is malformed%s%s%s", - component, - reason ? " (" : "", - reason ? reason : "", - reason ? ")" : "" - ); - zend_update_property(exception->ce, exception, ZEND_STRL("errors"), errors); -} - -static lxb_status_t lexbor_serialize_callback(const lxb_char_t *data, size_t length, void *ctx) -{ - smart_str *uri_str = ctx; - - if (data != NULL && length > 0) { - smart_str_appendl(uri_str, (const char *) data, length); - } - - return LXB_STATUS_OK; -} - -static zend_result lexbor_read_scheme(const struct uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) -{ - lxb_url_t *lexbor_uri = internal_uri->uri; - - ZEND_ASSERT(lexbor_uri->scheme.type != LXB_URL_SCHEMEL_TYPE__UNDEF); - - ZVAL_STRINGL(retval, (const char *) lexbor_uri->scheme.name.data, lexbor_uri->scheme.name.length); - - return SUCCESS; -} - -static zend_result lexbor_write_scheme(struct uri_internal_t *internal_uri, zval *value, zval *errors) -{ - lxb_url_t *lexbor_uri = internal_uri->uri; - lexbor_str_t str = {0}; - - zval_string_or_null_to_lexbor_str(value, &str); - - if (lxb_url_api_protocol_set(lexbor_uri, &lexbor_parser, str.data, str.length) != LXB_STATUS_OK) { - throw_invalid_url_exception_during_write(errors, "scheme"); - - return FAILURE; - } - - return SUCCESS; -} - -static zend_result lexbor_read_username(const struct uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) -{ - lxb_url_t *lexbor_uri = internal_uri->uri; - - if (lexbor_uri->username.length) { - ZVAL_STRINGL(retval, (const char *) lexbor_uri->username.data, lexbor_uri->username.length); - } else { - ZVAL_NULL(retval); - } - - return SUCCESS; -} - -static zend_result lexbor_write_username(uri_internal_t *internal_uri, zval *value, zval *errors) -{ - lxb_url_t *lexbor_uri = internal_uri->uri; - lexbor_str_t str = {0}; - - zval_string_or_null_to_lexbor_str(value, &str); - - if (lxb_url_api_username_set(lexbor_uri, str.data, str.length) != LXB_STATUS_OK) { - throw_invalid_url_exception_during_write(errors, "username"); - - return FAILURE; - } - - return SUCCESS; -} - -static zend_result lexbor_read_password(const struct uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) -{ - lxb_url_t *lexbor_uri = internal_uri->uri; - - if (lexbor_uri->password.length > 0) { - ZVAL_STRINGL(retval, (const char *) lexbor_uri->password.data, lexbor_uri->password.length); - } else { - ZVAL_NULL(retval); - } - - return SUCCESS; -} - -static zend_result lexbor_write_password(struct uri_internal_t *internal_uri, zval *value, zval *errors) -{ - lxb_url_t *lexbor_uri = internal_uri->uri; - lexbor_str_t str = {0}; - - zval_string_or_null_to_lexbor_str(value, &str); - - if (lxb_url_api_password_set(lexbor_uri, str.data, str.length) != LXB_STATUS_OK) { - throw_invalid_url_exception_during_write(errors, "password"); - - return FAILURE; - } - - return SUCCESS; -} - -static zend_result init_idna(void) -{ - if (lexbor_parser.idna != NULL) { - return SUCCESS; - } - - lexbor_parser.idna = lxb_unicode_idna_create(); - - return lxb_unicode_idna_init(lexbor_parser.idna) == LXB_STATUS_OK ? SUCCESS : FAILURE; -} - -static zend_result lexbor_read_host(const struct uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) -{ - lxb_url_t *lexbor_uri = internal_uri->uri; - - if (lexbor_uri->host.type == LXB_URL_HOST_TYPE_IPV4) { - smart_str host_str = {0}; - - lxb_url_serialize_host_ipv4(lexbor_uri->host.u.ipv4, lexbor_serialize_callback, &host_str); - - ZVAL_NEW_STR(retval, smart_str_extract(&host_str)); - } else if (lexbor_uri->host.type == LXB_URL_HOST_TYPE_IPV6) { - smart_str host_str = {0}; - - smart_str_appendc(&host_str, '['); - lxb_url_serialize_host_ipv6(lexbor_uri->host.u.ipv6, lexbor_serialize_callback, &host_str); - smart_str_appendc(&host_str, ']'); - - ZVAL_NEW_STR(retval, smart_str_extract(&host_str)); - } else if (lexbor_uri->host.type == LXB_URL_HOST_TYPE_EMPTY) { - ZVAL_EMPTY_STRING(retval); - } else if (lexbor_uri->host.type != LXB_URL_HOST_TYPE__UNDEF) { - switch (read_mode) { - case URI_COMPONENT_READ_NORMALIZED_UNICODE: { - smart_str host_str = {0}; - if (init_idna() == FAILURE) { - return FAILURE; - } - lxb_url_serialize_host_unicode(lexbor_parser.idna, &lexbor_uri->host, lexbor_serialize_callback, &host_str); - lxb_unicode_idna_clean(lexbor_parser.idna); - - ZVAL_NEW_STR(retval, smart_str_extract(&host_str)); - break; - } - case URI_COMPONENT_READ_NORMALIZED_ASCII: - ZEND_FALLTHROUGH; - case URI_COMPONENT_READ_RAW: - ZVAL_STRINGL(retval, (const char *) lexbor_uri->host.u.domain.data, lexbor_uri->host.u.domain.length); - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - } else { - ZVAL_NULL(retval); - } - - return SUCCESS; -} - -static zend_result lexbor_write_host(struct uri_internal_t *internal_uri, zval *value, zval *errors) -{ - lxb_url_t *lexbor_uri = internal_uri->uri; - lexbor_str_t str = {0}; - - zval_string_or_null_to_lexbor_str(value, &str); - - if (lxb_url_api_hostname_set(lexbor_uri, &lexbor_parser, str.data, str.length) != LXB_STATUS_OK) { - throw_invalid_url_exception_during_write(errors, "host"); - - return FAILURE; - } - - return SUCCESS; -} - -static zend_result lexbor_read_port(const struct uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) -{ - lxb_url_t *lexbor_uri = internal_uri->uri; - - if (lexbor_uri->has_port) { - ZVAL_LONG(retval, lexbor_uri->port); - } else { - ZVAL_NULL(retval); - } - - return SUCCESS; -} - -static zend_result lexbor_write_port(struct uri_internal_t *internal_uri, zval *value, zval *errors) -{ - lxb_url_t *lexbor_uri = internal_uri->uri; - lexbor_str_t str = {0}; - - zval_long_or_null_to_lexbor_str(value, &str); - - if (lxb_url_api_port_set(lexbor_uri, &lexbor_parser, str.data, str.length) != LXB_STATUS_OK) { - throw_invalid_url_exception_during_write(errors, "port"); - - return FAILURE; - } - - return SUCCESS; -} - -static zend_result lexbor_read_path(const struct uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) -{ - lxb_url_t *lexbor_uri = internal_uri->uri; - - if (lexbor_uri->path.str.length) { - ZVAL_STRINGL(retval, (const char *) lexbor_uri->path.str.data, lexbor_uri->path.str.length); - } else { - ZVAL_EMPTY_STRING(retval); - } - - return SUCCESS; -} - -static zend_result lexbor_write_path(struct uri_internal_t *internal_uri, zval *value, zval *errors) -{ - lxb_url_t *lexbor_uri = internal_uri->uri; - lexbor_str_t str = {0}; - - zval_string_or_null_to_lexbor_str(value, &str); - - if (lxb_url_api_pathname_set(lexbor_uri, &lexbor_parser, str.data, str.length) != LXB_STATUS_OK) { - throw_invalid_url_exception_during_write(errors, "path"); - - return FAILURE; - } - - return SUCCESS; -} - -static zend_result lexbor_read_query(const struct uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) -{ - lxb_url_t *lexbor_uri = internal_uri->uri; - - if (lexbor_uri->query.length) { - ZVAL_STRINGL(retval, (const char *) lexbor_uri->query.data, lexbor_uri->query.length); - } else { - ZVAL_NULL(retval); - } - - return SUCCESS; -} - -static zend_result lexbor_write_query(struct uri_internal_t *internal_uri, zval *value, zval *errors) -{ - lxb_url_t *lexbor_uri = internal_uri->uri; - lexbor_str_t str = {0}; - - zval_string_or_null_to_lexbor_str(value, &str); - - if (lxb_url_api_search_set(lexbor_uri, &lexbor_parser, str.data, str.length) != LXB_STATUS_OK) { - throw_invalid_url_exception_during_write(errors, "query string"); - - return FAILURE; - } - - return SUCCESS; -} - -static zend_result lexbor_read_fragment(const struct uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) -{ - lxb_url_t *lexbor_uri = internal_uri->uri; - - if (lexbor_uri->fragment.length) { - ZVAL_STRINGL(retval, (const char *) lexbor_uri->fragment.data, lexbor_uri->fragment.length); - } else { - ZVAL_NULL(retval); - } - - return SUCCESS; -} - -static zend_result lexbor_write_fragment(struct uri_internal_t *internal_uri, zval *value, zval *errors) -{ - lxb_url_t *lexbor_uri = internal_uri->uri; - lexbor_str_t str = {0}; - - zval_string_or_null_to_lexbor_str(value, &str); - - if (lxb_url_api_hash_set(lexbor_uri, &lexbor_parser, str.data, str.length) != LXB_STATUS_OK) { - throw_invalid_url_exception_during_write(errors, "fragment"); - - return FAILURE; - } - - return SUCCESS; -} - -zend_result lexbor_request_init(void) -{ - lexbor_mraw_t *mraw = lexbor_mraw_create(); - lxb_status_t status = lexbor_mraw_init(mraw, LEXBOR_MRAW_BYTE_SIZE); - if (status != LXB_STATUS_OK) { - lexbor_mraw_destroy(mraw, true); - return FAILURE; - } - - status = lxb_url_parser_init(&lexbor_parser, mraw); - if (status != LXB_STATUS_OK) { - lxb_url_parser_destroy(&lexbor_parser, false); - lexbor_mraw_destroy(mraw, true); - return FAILURE; - } - - lexbor_urls = 0; - - return SUCCESS; -} - -void lexbor_request_shutdown(void) -{ - lxb_url_parser_memory_destroy(&lexbor_parser); - lxb_url_parser_destroy(&lexbor_parser, false); - - lexbor_urls = 0; -} - -lxb_url_t *lexbor_parse_uri_ex(const zend_string *uri_str, const lxb_url_t *lexbor_base_url, zval *errors, bool silent) -{ - lexbor_cleanup_parser(); - - lxb_url_t *url = lxb_url_parse(&lexbor_parser, lexbor_base_url, (unsigned char *) ZSTR_VAL(uri_str), ZSTR_LEN(uri_str)); - const char *reason = fill_errors(errors); - - if (url == NULL && !silent) { - zend_object *exception = zend_throw_exception_ex(uri_whatwg_invalid_url_exception_ce, 0, "The specified URI is malformed%s%s%s", reason ? " (" : "", reason ? reason : "", reason ? ")" : ""); - zend_update_property(exception->ce, exception, ZEND_STRL("errors"), errors); - } - - return url; -} - -static void *lexbor_parse_uri(const zend_string *uri_str, const void *base_url, zval *errors, bool silent) -{ - return lexbor_parse_uri_ex(uri_str, base_url, errors, silent); -} - -static void *lexbor_clone_uri(void *uri) -{ - lxb_url_t *lexbor_uri = (lxb_url_t *) uri; - - return lxb_url_clone(lexbor_parser.mraw, lexbor_uri); -} - -static zend_string *lexbor_uri_to_string(void *uri, uri_recomposition_mode_t recomposition_mode, bool exclude_fragment) -{ - lxb_url_t *lexbor_uri = (lxb_url_t *) uri; - smart_str uri_str = {0}; - - switch (recomposition_mode) { - case URI_RECOMPOSITION_RAW_UNICODE: - ZEND_FALLTHROUGH; - case URI_RECOMPOSITION_NORMALIZED_UNICODE: - if (init_idna() == FAILURE) { - return NULL; - } - lxb_url_serialize_idna(lexbor_parser.idna, lexbor_uri, lexbor_serialize_callback, &uri_str, exclude_fragment); - lxb_unicode_idna_clean(lexbor_parser.idna); - break; - case URI_RECOMPOSITION_RAW_ASCII: - ZEND_FALLTHROUGH; - case URI_RECOMPOSITION_NORMALIZED_ASCII: - lxb_url_serialize(lexbor_uri, lexbor_serialize_callback, &uri_str, exclude_fragment); - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - - return smart_str_extract(&uri_str); -} - -static void lexbor_free_uri(void *uri) -{ -} - -const uri_handler_t lexbor_uri_handler = { - .name = URI_PARSER_WHATWG, - .parse_uri = lexbor_parse_uri, - .clone_uri = lexbor_clone_uri, - .uri_to_string = lexbor_uri_to_string, - .free_uri = lexbor_free_uri, - { - .scheme = {.read_func = lexbor_read_scheme, .write_func = lexbor_write_scheme}, - .username = {.read_func = lexbor_read_username, .write_func = lexbor_write_username}, - .password = {.read_func = lexbor_read_password, .write_func = lexbor_write_password}, - .host = {.read_func = lexbor_read_host, .write_func = lexbor_write_host}, - .port = {.read_func = lexbor_read_port, .write_func = lexbor_write_port}, - .path = {.read_func = lexbor_read_path, .write_func = lexbor_write_path}, - .query = {.read_func = lexbor_read_query, .write_func = lexbor_write_query}, - .fragment = {.read_func = lexbor_read_fragment, .write_func = lexbor_write_fragment}, - } -}; diff --git a/ext/uri/php_lexbor.h b/ext/uri/php_lexbor.h deleted file mode 100644 index 30d68b5cdf681..0000000000000 --- a/ext/uri/php_lexbor.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Máté Kocsis | - +----------------------------------------------------------------------+ -*/ - -#ifndef PHP_LEXBOR_H -#define PHP_LEXBOR_H - -#include "php_uri_common.h" -#include "lexbor/url/url.h" - -extern const uri_handler_t lexbor_uri_handler; - -lxb_url_t *lexbor_parse_uri_ex(const zend_string *uri_str, const lxb_url_t *lexbor_base_url, zval *errors, bool silent); - -zend_result lexbor_request_init(void); -void lexbor_request_shutdown(void); - -#endif diff --git a/ext/uri/php_uri.c b/ext/uri/php_uri.c index f5a5b160bba06..77fc627b6a99d 100644 --- a/ext/uri/php_uri.c +++ b/ext/uri/php_uri.c @@ -25,87 +25,267 @@ #include "Zend/zend_enum.h" #include "ext/standard/info.h" -#include "php_uri_common.h" -#include "php_lexbor.h" -#include "php_uriparser.h" +#include "php_uri.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/Uri.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; -zend_class_entry *uri_exception_ce; -zend_class_entry *uri_invalid_uri_exception_ce; -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; +zend_class_entry *php_uri_ce_rfc3986_uri; +zend_class_entry *php_uri_ce_whatwg_url; +zend_class_entry *php_uri_ce_comparison_mode; +zend_class_entry *php_uri_ce_exception; +zend_class_entry *php_uri_ce_error; +zend_class_entry *php_uri_ce_invalid_uri_exception; +zend_class_entry *php_uri_ce_whatwg_invalid_url_exception; +zend_class_entry *php_uri_ce_whatwg_url_validation_error_type; +zend_class_entry *php_uri_ce_whatwg_url_validation_error; -#define URIPARSER_VERSION PACKAGE_VERSION +static zend_object_handlers object_handlers_rfc3986_uri; +static zend_object_handlers object_handlers_whatwg_uri; static const zend_module_dep uri_deps[] = { ZEND_MOD_REQUIRED("lexbor") ZEND_MOD_END }; -static zend_array uri_handlers; +static zend_array uri_parsers; -static uri_handler_t *uri_handler_by_name(const char *handler_name, size_t handler_name_len) +static HashTable *uri_get_debug_properties(php_uri_object *object) { - return zend_hash_str_find_ptr(&uri_handlers, handler_name, handler_name_len); -} - -static HashTable *uri_get_debug_properties(zend_object *object) -{ - uri_internal_t *internal_uri = uri_internal_from_obj(object); - ZEND_ASSERT(internal_uri != NULL); - - HashTable *std_properties = zend_std_get_properties(object); + const HashTable *std_properties = zend_std_get_properties(&object->std); HashTable *result = zend_array_dup(std_properties); - if (UNEXPECTED(internal_uri->uri == NULL)) { + const php_uri_parser * const parser = object->parser; + void * const uri = object->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; } +PHPAPI const php_uri_parser *php_uri_get_parser(zend_string *uri_parser_name) +{ + 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); + } + + return zend_hash_find_ptr(&uri_parsers, uri_parser_name); +} + +ZEND_ATTRIBUTE_NONNULL PHPAPI php_uri_internal *php_uri_parse(const php_uri_parser *uri_parser, const char *uri_str, size_t uri_str_len, bool silent) +{ + void *uri = uri_parser->parse(uri_str, uri_str_len, NULL, NULL, silent); + + if (uri == NULL) { + return NULL; + } + + php_uri_internal *internal_uri = emalloc(sizeof(*internal_uri)); + internal_uri->parser = uri_parser; + internal_uri->uri = uri; + + return internal_uri; +} + +ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_scheme(const php_uri_internal *internal_uri, php_uri_component_read_mode read_mode, zval *zv) +{ + return internal_uri->parser->property_handler.scheme.read(internal_uri->uri, read_mode, zv); +} + +ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_username(const php_uri_internal *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_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_password(const php_uri_internal *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 php_uri_internal *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 php_uri_internal *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 php_uri_internal *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 php_uri_internal *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 php_uri_internal *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(php_uri_internal *internal_uri) +{ + internal_uri->parser->destroy(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 +) { + php_uri_internal *uri_internal = php_uri_parse(uri_parser, uri_str, uri_str_len, silent); + if (uri_internal == NULL) { + return NULL; + } + + 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); + } + + 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); +} + /** * Pass the errors parameter by ref to errors_zv for userland, and frees it if * it is not not needed anymore. @@ -127,30 +307,49 @@ static zend_result pass_errors_by_ref_and_free(zval *errors_zv, zval *errors) return SUCCESS; } - ZEND_TRY_ASSIGN_REF_ARR(errors_zv, Z_ARRVAL_P(errors)); + ZEND_TRY_ASSIGN_REF_TMP(errors_zv, 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 php_uri_object *base_url_object, + bool should_throw, bool should_update_this_object, zval *errors_zv ) { + + php_uri_object *uri_object; + if (should_update_this_object) { + uri_object = Z_URI_OBJECT_P(ZEND_THIS); + if (uri_object->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->parser; + zval errors; ZVAL_UNDEF(&errors); void *base_url = NULL; if (base_url_object != NULL) { - uri_internal_t *internal_base_url = uri_internal_from_obj(base_url_object); - URI_ASSERT_INITIALIZATION(internal_base_url); - base_url = internal_base_url->uri; + ZEND_ASSERT(base_url_object->std.ce == uri_object->std.ce); + ZEND_ASSERT(base_url_object->uri != NULL); + ZEND_ASSERT(base_url_object->parser == uri_parser); + base_url = base_url_object->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); @@ -159,28 +358,17 @@ 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->destroy(uri); RETURN_THROWS(); } - uri_object_t *uri_object; - if (should_update_this_object) { - uri_object = Z_URI_OBJECT_P(ZEND_THIS); - } 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); - } - - uri_object->internal.handler = handler; - uri_object->internal.uri = uri; + uri_object->uri = uri; } static void create_rfc3986_uri(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor) @@ -189,12 +377,34 @@ static void create_rfc3986_uri(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor zend_object *base_url_object = NULL; ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_PATH_STR(uri_str) + Z_PARAM_STR(uri_str) Z_PARAM_OPTIONAL - Z_PARAM_OBJ_OF_CLASS_OR_NULL(base_url_object, uri_rfc3986_uri_ce) + Z_PARAM_OBJ_OF_CLASS_OR_NULL(base_url_object, php_uri_ce_rfc3986_uri) ZEND_PARSE_PARAMETERS_END(); - php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, &uriparser_uri_handler, uri_str, base_url_object, is_constructor, is_constructor, NULL); + php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, + uri_str, base_url_object ? php_uri_object_from_obj(base_url_object) : NULL, 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), php_uri_ce_whatwg_url_validation_error)) { + return false; + } + } ZEND_HASH_FOREACH_END(); + + return true; } PHP_METHOD(Uri_Rfc3986_Uri, parse) @@ -229,9 +439,14 @@ PHP_METHOD(Uri_WhatWg_InvalidUrlException, __construct) 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); + zend_update_property(php_uri_ce_whatwg_invalid_url_exception, 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 (!is_list_of_whatwg_validation_errors(Z_ARR_P(errors))) { + zend_argument_value_error(2, "must be a list of %s", ZSTR_VAL(php_uri_ce_whatwg_url_validation_error->name)); + RETURN_THROWS(); + } + + zend_update_property(php_uri_ce_whatwg_invalid_url_exception, Z_OBJ_P(ZEND_THIS), ZEND_STRL("errors"), errors); } if (EG(exception)) { RETURN_THROWS(); @@ -246,23 +461,23 @@ PHP_METHOD(Uri_WhatWg_UrlValidationError, __construct) 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_OBJECT_OF_CLASS(type, php_uri_ce_whatwg_url_validation_error_type) 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); + zend_update_property_str(php_uri_ce_whatwg_url_validation_error, 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); + zend_update_property_ex(php_uri_ce_whatwg_url_validation_error, 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); + zend_update_property(php_uri_ce_whatwg_url_validation_error, Z_OBJ_P(ZEND_THIS), ZEND_STRL("failure"), &failure_zv); if (EG(exception)) { RETURN_THROWS(); } @@ -275,13 +490,14 @@ static void create_whatwg_uri(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor) zval *errors = NULL; ZEND_PARSE_PARAMETERS_START(1, 3) - Z_PARAM_PATH_STR(uri_str) + Z_PARAM_STR(uri_str) Z_PARAM_OPTIONAL - Z_PARAM_OBJ_OF_CLASS_OR_NULL(base_url_object, uri_whatwg_url_ce) + Z_PARAM_OBJ_OF_CLASS_OR_NULL(base_url_object, php_uri_ce_whatwg_url) 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 ? php_uri_object_from_obj(base_url_object) : NULL, is_constructor, is_constructor, errors); } PHP_METHOD(Uri_WhatWg_Url, parse) @@ -296,22 +512,27 @@ PHP_METHOD(Uri_WhatWg_Url, __construct) PHP_METHOD(Uri_Rfc3986_Uri, getScheme) { - uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_SCHEME, URI_COMPONENT_READ_NORMALIZED_ASCII); + php_uri_property_read_helper(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, URI_PROPERTY_NAME_SCHEME, URI_COMPONENT_READ_RAW); + php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_SCHEME, PHP_URI_COMPONENT_READ_MODE_RAW); } -static void read_uriparser_userinfo(INTERNAL_FUNCTION_PARAMETERS, uri_component_read_mode_t read_mode) +PHP_METHOD(Uri_Rfc3986_Uri, withScheme) +{ + php_uri_property_write_str_or_null_helper(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); + php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS); + ZEND_ASSERT(uri_object->uri != NULL); - if (UNEXPECTED(uriparser_read_userinfo(internal_uri, read_mode, return_value) == FAILURE)) { + if (UNEXPECTED(php_uri_parser_rfc3986_userinfo_read(uri_object->uri, read_mode, return_value) == FAILURE)) { zend_throw_error(NULL, "The userinfo component cannot be retrieved"); RETURN_THROWS(); } @@ -319,96 +540,153 @@ static void read_uriparser_userinfo(INTERNAL_FUNCTION_PARAMETERS, uri_component_ PHP_METHOD(Uri_Rfc3986_Uri, getUserInfo) { - read_uriparser_userinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_COMPONENT_READ_NORMALIZED_ASCII); + rfc3986_userinfo_read(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII); } PHP_METHOD(Uri_Rfc3986_Uri, getRawUserInfo) { - read_uriparser_userinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_COMPONENT_READ_RAW); + 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_STR_OR_NULL(value) + ZEND_PARSE_PARAMETERS_END(); + + zval zv; + if (value == NULL) { + ZVAL_NULL(&zv); + } else { + ZVAL_STR(&zv, value); + } + + php_uri_object *old_uri_object = php_uri_object_from_obj(Z_OBJ_P(ZEND_THIS)); + ZEND_ASSERT(old_uri_object->uri != NULL); + + zend_object *new_object = old_uri_object->std.handlers->clone_obj(&old_uri_object->std); + 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); + + php_uri_object *new_uri_object = php_uri_object_from_obj(new_object); + ZEND_ASSERT(new_uri_object->uri != NULL); + + if (UNEXPECTED(php_uri_parser_rfc3986_userinfo_write(new_uri_object->uri, &zv, NULL) == FAILURE)) { + RETURN_THROWS(); + } } PHP_METHOD(Uri_Rfc3986_Uri, getUsername) { - uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_USERNAME, URI_COMPONENT_READ_NORMALIZED_ASCII); + php_uri_property_read_helper(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, URI_PROPERTY_NAME_USERNAME, URI_COMPONENT_READ_RAW); + php_uri_property_read_helper(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, URI_PROPERTY_NAME_PASSWORD, URI_COMPONENT_READ_NORMALIZED_ASCII); + php_uri_property_read_helper(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, URI_PROPERTY_NAME_PASSWORD, URI_COMPONENT_READ_RAW); + php_uri_property_read_helper(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, URI_PROPERTY_NAME_HOST, URI_COMPONENT_READ_NORMALIZED_ASCII); + php_uri_property_read_helper(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, URI_PROPERTY_NAME_HOST, URI_COMPONENT_READ_RAW); + php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_HOST, PHP_URI_COMPONENT_READ_MODE_RAW); +} + +PHP_METHOD(Uri_Rfc3986_Uri, withHost) +{ + php_uri_property_write_str_or_null_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_HOST); } PHP_METHOD(Uri_Rfc3986_Uri, getPort) { - uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PORT, URI_COMPONENT_READ_NORMALIZED_ASCII); + php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PORT, PHP_URI_COMPONENT_READ_MODE_RAW); +} + +PHP_METHOD(Uri_Rfc3986_Uri, withPort) +{ + php_uri_property_write_long_or_null_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PORT); } PHP_METHOD(Uri_Rfc3986_Uri, getPath) { - uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PATH, URI_COMPONENT_READ_NORMALIZED_ASCII); + php_uri_property_read_helper(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, URI_PROPERTY_NAME_PATH, URI_COMPONENT_READ_RAW); + php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PATH, PHP_URI_COMPONENT_READ_MODE_RAW); +} + +PHP_METHOD(Uri_Rfc3986_Uri, withPath) +{ + php_uri_property_write_str_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PATH); } PHP_METHOD(Uri_Rfc3986_Uri, getQuery) { - uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_QUERY, URI_COMPONENT_READ_NORMALIZED_ASCII); + php_uri_property_read_helper(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, URI_PROPERTY_NAME_QUERY, URI_COMPONENT_READ_RAW); + php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_QUERY, PHP_URI_COMPONENT_READ_MODE_RAW); +} + +PHP_METHOD(Uri_Rfc3986_Uri, withQuery) +{ + php_uri_property_write_str_or_null_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_QUERY); } PHP_METHOD(Uri_Rfc3986_Uri, getFragment) { - uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_FRAGMENT, URI_COMPONENT_READ_NORMALIZED_ASCII); + php_uri_property_read_helper(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, URI_PROPERTY_NAME_FRAGMENT, URI_COMPONENT_READ_RAW); + php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_FRAGMENT, PHP_URI_COMPONENT_READ_MODE_RAW); } -static void throw_cannot_recompose_uri_to_string(zend_object *object) +PHP_METHOD(Uri_Rfc3986_Uri, withFragment) { - zend_throw_exception_ex(NULL, 0, "Cannot recompose %s to a string", ZSTR_VAL(object->ce->name)); + php_uri_property_write_str_or_null_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_FRAGMENT); } -static void uri_equals(INTERNAL_FUNCTION_PARAMETERS, zend_object *that_object, zend_object *comparison_mode) +static void throw_cannot_recompose_uri_to_string(php_uri_object *object) { - zend_object *this_object = Z_OBJ_P(ZEND_THIS); - uri_internal_t *this_internal_uri = uri_internal_from_obj(this_object); - URI_ASSERT_INITIALIZATION(this_internal_uri); + zend_throw_exception_ex(php_uri_ce_error, 0, "Cannot recompose %s to a string", ZSTR_VAL(object->std.ce->name)); +} - uri_internal_t *that_internal_uri = uri_internal_from_obj(that_object); - URI_ASSERT_INITIALIZATION(that_internal_uri); +static void uri_equals(INTERNAL_FUNCTION_PARAMETERS, php_uri_object *that_object, zend_object *comparison_mode) +{ + php_uri_object *this_object = Z_URI_OBJECT_P(ZEND_THIS); + ZEND_ASSERT(this_object->uri != NULL); + ZEND_ASSERT(that_object->uri != NULL); - if (this_object->ce != that_object->ce && - !instanceof_function(this_object->ce, that_object->ce) && - !instanceof_function(that_object->ce, this_object->ce) + if (this_object->std.ce != that_object->std.ce && + !instanceof_function(this_object->std.ce, that_object->std.ce) && + !instanceof_function(that_object->std.ce, this_object->std.ce) ) { RETURN_FALSE; } @@ -419,15 +697,15 @@ 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_object->parser->to_string( + this_object->uri, PHP_URI_RECOMPOSITION_MODE_NORMALIZED_ASCII, exclude_fragment); if (this_str == NULL) { 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_object->parser->to_string( + that_object->uri, PHP_URI_RECOMPOSITION_MODE_NORMALIZED_ASCII, exclude_fragment); if (that_str == NULL) { zend_string_release(this_str); throw_cannot_recompose_uri_to_string(that_object); @@ -446,25 +724,24 @@ PHP_METHOD(Uri_Rfc3986_Uri, equals) zend_object *comparison_mode = NULL; ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_OBJ_OF_CLASS(that_object, uri_rfc3986_uri_ce) + Z_PARAM_OBJ_OF_CLASS(that_object, php_uri_ce_rfc3986_uri) Z_PARAM_OPTIONAL - Z_PARAM_OBJ_OF_CLASS(comparison_mode, uri_comparison_mode_ce) + Z_PARAM_OBJ_OF_CLASS(comparison_mode, php_uri_ce_comparison_mode) ZEND_PARSE_PARAMETERS_END(); - uri_equals(INTERNAL_FUNCTION_PARAM_PASSTHRU, that_object, comparison_mode); + uri_equals(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_uri_object_from_obj(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); + php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS); + ZEND_ASSERT(uri_object->uri != NULL); - zend_string *uri_str = internal_uri->handler->uri_to_string(internal_uri->uri, URI_RECOMPOSITION_RAW_ASCII, false); + zend_string *uri_str = uri_object->parser->to_string(uri_object->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false); if (uri_str == NULL) { - throw_cannot_recompose_uri_to_string(this_object); + throw_cannot_recompose_uri_to_string(uri_object); RETURN_THROWS(); } @@ -475,13 +752,12 @@ 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); + php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS); + ZEND_ASSERT(uri_object->uri != NULL); - zend_string *uri_str = internal_uri->handler->uri_to_string(internal_uri->uri, URI_RECOMPOSITION_NORMALIZED_ASCII, false); + zend_string *uri_str = uri_object->parser->to_string(uri_object->uri, PHP_URI_RECOMPOSITION_MODE_NORMALIZED_ASCII, false); if (uri_str == NULL) { - throw_cannot_recompose_uri_to_string(this_object); + throw_cannot_recompose_uri_to_string(uri_object); RETURN_THROWS(); } @@ -493,28 +769,24 @@ PHP_METHOD(Uri_Rfc3986_Uri, resolve) zend_string *uri_str; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_PATH_STR(uri_str) + Z_PARAM_STR(uri_str) 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, NULL); + php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, + uri_str, Z_URI_OBJECT_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); + php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS); + ZEND_ASSERT(uri_object->uri != NULL); /* 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 = uri_object->parser->to_string(uri_object->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false); if (uri_str == NULL) { - throw_cannot_recompose_uri_to_string(this_object); + throw_cannot_recompose_uri_to_string(uri_object); RETURN_THROWS(); } zval tmp; @@ -524,16 +796,15 @@ PHP_METHOD(Uri_Rfc3986_Uri, __serialize) 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_str_add_new(Z_ARRVAL(arr), PHP_URI_SERIALIZE_URI_FIELD_NAME, sizeof(PHP_URI_SERIALIZE_URI_FIELD_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); + ZVAL_EMPTY_ARRAY(&arr); zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &arr); } -static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS, const char *handler_name) +static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS) { HashTable *data; @@ -541,125 +812,106 @@ static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS, const char *handler_na Z_PARAM_ARRAY_HT(data) ZEND_PARSE_PARAMETERS_END(); - zend_object *object = Z_OBJ_P(ZEND_THIS); + php_uri_object *uri_object = php_uri_object_from_obj(Z_OBJ_P(ZEND_THIS)); + if (uri_object->uri != NULL) { + /* Intentionally throw two exceptions for proper chaining. */ + zend_throw_error(NULL, "Cannot modify readonly object of class %s", ZSTR_VAL(uri_object->std.ce->name)); + zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name)); + RETURN_THROWS(); + } /* Verify the expected number of elements, this implicitly ensures that no additional elements are present. */ if (zend_hash_num_elements(data) != 2) { - zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(object->ce->name)); + zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name)); RETURN_THROWS(); } /* Unserialize state: "uri" key in the first array */ zval *arr = zend_hash_index_find(data, 0); if (arr == NULL || Z_TYPE_P(arr) != IS_ARRAY) { - zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(object->ce->name)); + zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name)); RETURN_THROWS(); } /* Verify the expected number of elements inside the first array, this implicitly ensures that no additional elements are present. */ if (zend_hash_num_elements(Z_ARRVAL_P(arr)) != 1) { - zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(object->ce->name)); + zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name)); RETURN_THROWS(); } - zval *uri_zv = zend_hash_str_find_ind(Z_ARRVAL_P(arr), ZEND_STRL(URI_SERIALIZED_PROPERTY_NAME)); + zval *uri_zv = zend_hash_str_find(Z_ARRVAL_P(arr), ZEND_STRL(PHP_URI_SERIALIZE_URI_FIELD_NAME)); if (uri_zv == NULL || Z_TYPE_P(uri_zv) != IS_STRING) { - zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(object->ce->name)); + zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name)); RETURN_THROWS(); } - 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); - } - internal_uri->uri = internal_uri->handler->parse_uri(Z_STR_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)); + uri_object->uri = uri_object->parser->parse(Z_STRVAL_P(uri_zv), Z_STRLEN_P(uri_zv), NULL, NULL, true); + if (uri_object->uri == NULL) { + zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name)); RETURN_THROWS(); } /* Unserialize regular properties: second array */ arr = zend_hash_index_find(data, 1); if (arr == NULL || Z_TYPE_P(arr) != IS_ARRAY) { - zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(object->ce->name)); + zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name)); RETURN_THROWS(); } /* Verify that there is no regular property in the second array, because the URI classes have no properties and they are final. */ if (zend_hash_num_elements(Z_ARRVAL_P(arr)) > 0) { - zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(object->ce->name)); + zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name)); RETURN_THROWS(); } } PHP_METHOD(Uri_Rfc3986_Uri, __unserialize) { - uri_unserialize(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PARSER_RFC3986); + uri_unserialize(INTERNAL_FUNCTION_PARAM_PASSTHRU); } PHP_METHOD(Uri_Rfc3986_Uri, __debugInfo) { ZEND_PARSE_PARAMETERS_NONE(); - zend_object *object = Z_OBJ_P(ZEND_THIS); + php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS); - RETURN_ARR(uri_get_debug_properties(object)); + RETURN_ARR(uri_get_debug_properties(uri_object)); } PHP_METHOD(Uri_WhatWg_Url, getScheme) { - uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_SCHEME, URI_COMPONENT_READ_NORMALIZED_ASCII); + php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_SCHEME, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII); } PHP_METHOD(Uri_WhatWg_Url, withScheme) { - uri_write_component_str(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_SCHEME); + php_uri_property_write_str_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_SCHEME); } PHP_METHOD(Uri_WhatWg_Url, withUsername) { - uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_USERNAME); + php_uri_property_write_str_or_null_helper(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); + php_uri_property_write_str_or_null_helper(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); + php_uri_property_read_helper(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_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_HOST, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_UNICODE); } -PHP_METHOD(Uri_WhatWg_Url, withHost) +PHP_METHOD(Uri_WhatWg_Url, getFragment) { - uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_HOST); -} - -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, withPath) -{ - uri_write_component_str(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PATH); -} - -PHP_METHOD(Uri_WhatWg_Url, withQuery) -{ - uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_QUERY); -} - -PHP_METHOD(Uri_WhatWg_Url, withFragment) -{ - uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_FRAGMENT); + php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_FRAGMENT, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_UNICODE); } PHP_METHOD(Uri_WhatWg_Url, equals) @@ -668,12 +920,12 @@ PHP_METHOD(Uri_WhatWg_Url, equals) zend_object *comparison_mode = NULL; ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_OBJ_OF_CLASS(that_object, uri_whatwg_url_ce) + Z_PARAM_OBJ_OF_CLASS(that_object, php_uri_ce_whatwg_url) Z_PARAM_OPTIONAL - Z_PARAM_OBJ_OF_CLASS(comparison_mode, uri_comparison_mode_ce) + Z_PARAM_OBJ_OF_CLASS(comparison_mode, php_uri_ce_comparison_mode) ZEND_PARSE_PARAMETERS_END(); - uri_equals(INTERNAL_FUNCTION_PARAM_PASSTHRU, that_object, comparison_mode); + uri_equals(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_uri_object_from_obj(that_object), comparison_mode); } PHP_METHOD(Uri_WhatWg_Url, toUnicodeString) @@ -681,10 +933,10 @@ PHP_METHOD(Uri_WhatWg_Url, toUnicodeString) 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); + php_uri_object *uri_object = php_uri_object_from_obj(this_object); + ZEND_ASSERT(uri_object->uri != NULL); - RETURN_STR(internal_uri->handler->uri_to_string(internal_uri->uri, URI_RECOMPOSITION_RAW_UNICODE, false)); + RETURN_STR(uri_object->parser->to_string(uri_object->uri, PHP_URI_RECOMPOSITION_MODE_RAW_UNICODE, false)); } PHP_METHOD(Uri_WhatWg_Url, toAsciiString) @@ -692,10 +944,10 @@ PHP_METHOD(Uri_WhatWg_Url, toAsciiString) 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); + php_uri_object *uri_object = php_uri_object_from_obj(this_object); + ZEND_ASSERT(uri_object->uri != NULL); - RETURN_STR(internal_uri->handler->uri_to_string(internal_uri->uri, URI_RECOMPOSITION_RAW_ASCII, false)); + RETURN_STR(uri_object->parser->to_string(uri_object->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false)); } PHP_METHOD(Uri_WhatWg_Url, resolve) @@ -704,28 +956,24 @@ PHP_METHOD(Uri_WhatWg_Url, resolve) zval *errors = NULL; ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_PATH_STR(uri_str) + Z_PARAM_STR(uri_str) Z_PARAM_OPTIONAL 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_URI_OBJECT_P(ZEND_THIS), true, false, errors); } PHP_METHOD(Uri_WhatWg_Url, __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); + php_uri_object *this_object = Z_URI_OBJECT_P(ZEND_THIS); + ZEND_ASSERT(this_object->uri != NULL); /* 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 = this_object->parser->to_string(this_object->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false); if (uri_str == NULL) { throw_cannot_recompose_uri_to_string(this_object); RETURN_THROWS(); @@ -737,96 +985,89 @@ PHP_METHOD(Uri_WhatWg_Url, __serialize) zval arr; array_init(&arr); - zend_hash_str_add_new(Z_ARRVAL(arr), ZEND_STRL(URI_SERIALIZED_PROPERTY_NAME), &tmp); + zend_hash_str_add_new(Z_ARRVAL(arr), ZEND_STRL(PHP_URI_SERIALIZE_URI_FIELD_NAME), &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_ADDREF(arr); + ZVAL_EMPTY_ARRAY(&arr); zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &arr); } 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) { ZEND_PARSE_PARAMETERS_NONE(); - zend_object *object = Z_OBJ_P(ZEND_THIS); + php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS); - RETURN_ARR(uri_get_debug_properties(object)); + RETURN_ARR(uri_get_debug_properties(uri_object)); } -static zend_object *uri_create_object_handler(zend_class_entry *class_type) +PHPAPI php_uri_object *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); + php_uri_object *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->parser = parser; + uri_object->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) +{ + php_uri_object *uri_object = php_uri_object_from_obj(object); + uri_object->parser->destroy(uri_object->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); + php_uri_object *uri_object = php_uri_object_from_obj(object); - 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); + ZEND_ASSERT(uri_object->uri != NULL); - new_uri_object->internal.handler = internal_uri->handler; + php_uri_object *new_uri_object = php_uri_object_from_obj(object->ce->create_object(object->ce)); + ZEND_ASSERT(new_uri_object->parser == uri_object->parser); - void *uri = internal_uri->handler->clone_uri(internal_uri->uri); + void *uri = uri_object->parser->clone(uri_object->uri); ZEND_ASSERT(uri != NULL); - new_uri_object->internal.uri = uri; + new_uri_object->uri = uri; zend_objects_clone_members(&new_uri_object->std, &uri_object->std); return &new_uri_object->std; } -PHPAPI void php_uri_implementation_set_object_handlers(zend_class_entry *ce, zend_object_handlers *object_handlers) +PHPAPI zend_result php_uri_parser_register(const php_uri_parser *uri_parser) { - 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_string *key = zend_string_init_interned(uri_parser->name, strlen(uri_parser->name), true); -zend_result uri_handler_register(const uri_handler_t *uri_handler) -{ - zend_string *key = zend_string_init_interned(uri_handler->name, strlen(uri_handler->name), 1); + 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->destroy != NULL); - 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_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); @@ -835,26 +1076,41 @@ 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(); - php_uri_implementation_set_object_handlers(uri_rfc3986_uri_ce, &uri_rfc3986_uri_object_handlers); - - 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_comparison_mode_ce = register_class_Uri_UriComparisonMode(); - uri_exception_ce = register_class_Uri_UriException(zend_ce_exception); - uri_invalid_uri_exception_ce = register_class_Uri_InvalidUriException(uri_exception_ce); - uri_whatwg_invalid_url_exception_ce = register_class_Uri_WhatWg_InvalidUrlException(uri_invalid_uri_exception_ce); - 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); + php_uri_ce_rfc3986_uri = register_class_Uri_Rfc3986_Uri(); + php_uri_ce_rfc3986_uri->create_object = php_uri_object_create_rfc3986; + php_uri_ce_rfc3986_uri->default_object_handlers = &object_handlers_rfc3986_uri; + memcpy(&object_handlers_rfc3986_uri, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + object_handlers_rfc3986_uri.offset = XtOffsetOf(php_uri_object, std); + object_handlers_rfc3986_uri.free_obj = php_uri_object_handler_free; + object_handlers_rfc3986_uri.clone_obj = php_uri_object_handler_clone; + + php_uri_ce_whatwg_url = register_class_Uri_WhatWg_Url(); + php_uri_ce_whatwg_url->create_object = php_uri_object_create_whatwg; + php_uri_ce_whatwg_url->default_object_handlers = &object_handlers_whatwg_uri; + memcpy(&object_handlers_whatwg_uri, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + object_handlers_whatwg_uri.offset = XtOffsetOf(php_uri_object, std); + object_handlers_whatwg_uri.free_obj = php_uri_object_handler_free; + object_handlers_whatwg_uri.clone_obj = php_uri_object_handler_clone; + + php_uri_ce_comparison_mode = register_class_Uri_UriComparisonMode(); + php_uri_ce_exception = register_class_Uri_UriException(zend_ce_exception); + php_uri_ce_error = register_class_Uri_UriError(zend_ce_error); + php_uri_ce_invalid_uri_exception = register_class_Uri_InvalidUriException(php_uri_ce_exception); + php_uri_ce_whatwg_invalid_url_exception = register_class_Uri_WhatWg_InvalidUrlException(php_uri_ce_invalid_uri_exception); + php_uri_ce_whatwg_url_validation_error = register_class_Uri_WhatWg_UrlValidationError(); + php_uri_ce_whatwg_url_validation_error_type = register_class_Uri_WhatWg_UrlValidationErrorType(); + + zend_hash_init(&uri_parsers, 4, NULL, NULL, true); + + if (php_uri_parser_register(&php_uri_parser_rfc3986) == FAILURE) { + return FAILURE; + } - if (PHP_MINIT(uri_uriparser)(INIT_FUNC_ARGS_PASSTHRU) == 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; } @@ -864,30 +1120,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; } @@ -900,8 +1163,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..1ec3617b096ca 100644 --- a/ext/uri/php_uri.h +++ b/ext/uri/php_uri.h @@ -22,6 +22,193 @@ 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; + /* port is a zend_long to match the userland port getter, which + * returns the port in zval. */ + zend_long 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 php_uri_internal *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 php_uri_internal *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 php_uri_internal *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 php_uri_internal *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 php_uri_internal *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 php_uri_internal *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 php_uri_internal *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 php_uri_internal *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 php_uri_internal *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(php_uri_internal *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 php_uri_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 9fbd40d98e5e9..9f12fbb1c0701 100644 --- a/ext/uri/php_uri.stub.php +++ b/ext/uri/php_uri.stub.php @@ -8,6 +8,11 @@ class UriException extends \Exception { } + /** @strict-properties */ + class UriError extends \Error + { + } + /** @strict-properties */ class InvalidUriException extends \Uri\UriException { @@ -32,10 +37,14 @@ 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 {} @@ -48,20 +57,30 @@ 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 {} @@ -157,26 +176,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 65630f113a3d3..d3a9c4fde7bca 100644 --- a/ext/uri/php_uri_arginfo.h +++ b/ext/uri/php_uri_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: e2c448000b1e00485bc988f073ea61dfc984e953 */ + * Stub hash: f3c524798d1933a400cc9377cfbfdcbaf77b87f0 */ 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) @@ -16,10 +16,18 @@ 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 @@ -32,22 +40,42 @@ ZEND_END_ARG_INFO() #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") @@ -117,33 +145,23 @@ ZEND_END_ARG_INFO() #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 #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_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_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_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) @@ -169,21 +187,28 @@ 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); @@ -201,11 +226,6 @@ ZEND_METHOD(Uri_WhatWg_Url, withUsername); 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, withPort); -ZEND_METHOD(Uri_WhatWg_Url, withPath); -ZEND_METHOD(Uri_WhatWg_Url, withQuery); -ZEND_METHOD(Uri_WhatWg_Url, withFragment); ZEND_METHOD(Uri_WhatWg_Url, equals); ZEND_METHOD(Uri_WhatWg_Url, toAsciiString); ZEND_METHOD(Uri_WhatWg_Url, toUnicodeString); @@ -219,21 +239,28 @@ static const zend_function_entry class_Uri_Rfc3986_Uri_methods[] = { 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) @@ -265,15 +292,15 @@ static const zend_function_entry class_Uri_WhatWg_Url_methods[] = { 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_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_ME(Uri_WhatWg_Url, withPort, arginfo_class_Uri_WhatWg_Url_withPort, ZEND_ACC_PUBLIC) + 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_ME(Uri_WhatWg_Url, withPath, arginfo_class_Uri_WhatWg_Url_withPath, ZEND_ACC_PUBLIC) + 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_ME(Uri_WhatWg_Url, withQuery, arginfo_class_Uri_WhatWg_Url_withQuery, ZEND_ACC_PUBLIC) + 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_ME(Uri_WhatWg_Url, withFragment, arginfo_class_Uri_WhatWg_Url_withFragment, ZEND_ACC_PUBLIC) + 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) @@ -294,6 +321,16 @@ static zend_class_entry *register_class_Uri_UriException(zend_class_entry *class return class_entry; } +static zend_class_entry *register_class_Uri_UriError(zend_class_entry *class_entry_Error) +{ + zend_class_entry ce, *class_entry; + + INIT_NS_CLASS_ENTRY(ce, "Uri", "UriError", NULL); + class_entry = zend_register_internal_class_with_flags(&ce, class_entry_Error, ZEND_ACC_NO_DYNAMIC_PROPERTIES); + + return class_entry; +} + static zend_class_entry *register_class_Uri_InvalidUriException(zend_class_entry *class_entry_Uri_UriException) { zend_class_entry ce, *class_entry; @@ -322,6 +359,9 @@ static zend_class_entry *register_class_Uri_Rfc3986_Uri(void) 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; } @@ -334,9 +374,9 @@ static zend_class_entry *register_class_Uri_WhatWg_InvalidUrlException(zend_clas zval property_errors_default_value; ZVAL_UNDEF(&property_errors_default_value); - zend_string *property_errors_name = zend_string_init("errors", sizeof("errors") - 1, 1); + zend_string *property_errors_name = zend_string_init("errors", sizeof("errors") - 1, true); zend_declare_typed_property(class_entry, property_errors_name, &property_errors_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ARRAY)); - zend_string_release(property_errors_name); + zend_string_release_ex(property_errors_name, true); return class_entry; } @@ -415,9 +455,9 @@ static zend_class_entry *register_class_Uri_WhatWg_UrlValidationError(void) zval property_context_default_value; ZVAL_UNDEF(&property_context_default_value); - zend_string *property_context_name = zend_string_init("context", sizeof("context") - 1, 1); + zend_string *property_context_name = zend_string_init("context", sizeof("context") - 1, true); zend_declare_typed_property(class_entry, property_context_name, &property_context_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_context_name); + zend_string_release_ex(property_context_name, true); zval property_type_default_value; ZVAL_UNDEF(&property_type_default_value); @@ -426,9 +466,9 @@ static zend_class_entry *register_class_Uri_WhatWg_UrlValidationError(void) zval property_failure_default_value; ZVAL_UNDEF(&property_failure_default_value); - zend_string *property_failure_name = zend_string_init("failure", sizeof("failure") - 1, 1); + zend_string *property_failure_name = zend_string_init("failure", sizeof("failure") - 1, true); zend_declare_typed_property(class_entry, property_failure_name, &property_failure_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_failure_name); + zend_string_release_ex(property_failure_name, true); return class_entry; } diff --git a/ext/uri/php_uri_common.c b/ext/uri/php_uri_common.c index 29de370bd56b6..da73bc59bf9cf 100644 --- a/ext/uri/php_uri_common.c +++ b/ext/uri/php_uri_common.c @@ -19,120 +19,98 @@ #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 php_uri_property_read_helper(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); + php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS); + ZEND_ASSERT(uri_object->uri != NULL); - 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(uri_object->parser, property_name); - if (UNEXPECTED(property_handler->read_func(internal_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))); + if (UNEXPECTED(property_handler->read(uri_object->uri, component_read_mode, return_value) == FAILURE)) { + zend_throw_exception_ex(php_uri_ce_error, 0, "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 php_uri_property_write_helper(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name, zval *property_zv) { - uri_internal_t *internal_uri = Z_URI_INTERNAL_P(ZEND_THIS); - URI_ASSERT_INITIALIZATION(internal_uri); + php_uri_object *old_uri_object = Z_URI_OBJECT_P(ZEND_THIS); + ZEND_ASSERT(old_uri_object->uri != NULL); - 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 = old_uri_object->std.handlers->clone_obj(&old_uri_object->std); + if (new_object == NULL) { + RETURN_THROWS(); + } - zend_object *new_object = uri_clone_obj_handler(Z_OBJ_P(ZEND_THIS)); - ZEND_ASSERT(new_object != NULL); + /* 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(property_handler->write_func == NULL)) { - zend_readonly_property_modification_error_ex(ZSTR_VAL(Z_OBJ_P(ZEND_THIS)->ce->name), + const php_uri_property_handler *property_handler = php_uri_parser_property_handler_by_name(old_uri_object->parser, property_name); + + php_uri_object *new_uri_object = php_uri_object_from_obj(new_object); + ZEND_ASSERT(new_uri_object->uri != NULL); + if (UNEXPECTED(property_handler->write == NULL)) { + zend_readonly_property_modification_error_ex(ZSTR_VAL(old_uri_object->std.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 (UNEXPECTED(property_handler->write_func(new_internal_uri, property_zv, &errors) == FAILURE)) { + if (UNEXPECTED(property_handler->write(new_uri_object->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 php_uri_property_write_str_helper(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name) { zend_string *value; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_PATH_STR(value) + Z_PARAM_STR(value) ZEND_PARSE_PARAMETERS_END(); zval zv; ZVAL_STR(&zv, value); - uri_write_component_ex(INTERNAL_FUNCTION_PARAM_PASSTHRU, property_name, &zv); + php_uri_property_write_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, property_name, &zv); } -void uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t property_name) +void php_uri_property_write_str_or_null_helper(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name) { zend_string *value; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_PATH_STR_OR_NULL(value) + Z_PARAM_STR_OR_NULL(value) ZEND_PARSE_PARAMETERS_END(); zval zv; @@ -142,10 +120,10 @@ void uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAMETERS, uri_property_ ZVAL_STR(&zv, value); } - uri_write_component_ex(INTERNAL_FUNCTION_PARAM_PASSTHRU, property_name, &zv); + php_uri_property_write_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, property_name, &zv); } -void uri_write_component_long_or_null(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t property_name) +void php_uri_property_write_long_or_null_helper(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name) { zend_long value; bool value_is_null; @@ -161,5 +139,5 @@ void uri_write_component_long_or_null(INTERNAL_FUNCTION_PARAMETERS, uri_property ZVAL_LONG(&zv, value); } - uri_write_component_ex(INTERNAL_FUNCTION_PARAM_PASSTHRU, property_name, &zv); + php_uri_property_write_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, property_name, &zv); } diff --git a/ext/uri/php_uri_common.h b/ext/uri/php_uri_common.h index 8e5b0c2d2279f..109236879ae7f 100644 --- a/ext/uri/php_uri_common.h +++ b/ext/uri/php_uri_common.h @@ -17,69 +17,57 @@ #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; -extern zend_class_entry *uri_exception_ce; -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 { +extern zend_class_entry *php_uri_ce_rfc3986_uri; +extern zend_class_entry *php_uri_ce_whatwg_url; +extern zend_class_entry *php_uri_ce_comparison_mode; +extern zend_class_entry *php_uri_ce_exception; +extern zend_class_entry *php_uri_ce_error; +extern zend_class_entry *php_uri_ce_invalid_uri_exception; +extern zend_class_entry *php_uri_ce_whatwg_invalid_url_exception; +extern zend_class_entry *php_uri_ce_whatwg_url_validation_error_type; +extern zend_class_entry *php_uri_ce_whatwg_url_validation_error; + +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. @@ -93,49 +81,112 @@ 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); -typedef struct uri_internal_t { - const uri_handler_t *handler; + /** + * Destroy (free) the provided URI. + * + * @param uri The URI to free. Must do nothing if NULL. + */ + void (*destroy)(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 php_uri_internal { + const php_uri_parser *parser; void *uri; -} uri_internal_t; +} php_uri_internal; -typedef struct uri_object_t { - uri_internal_t internal; +typedef struct php_uri_object { + const php_uri_parser *parser; + void *uri; zend_object std; -} uri_object_t; +} php_uri_object; -static inline uri_object_t *uri_object_from_obj(const zend_object *object) { - return (uri_object_t*)((char*)(object) - XtOffsetOf(uri_object_t, std)); +static inline php_uri_object *php_uri_object_from_obj(zend_object *object) { + return (php_uri_object*)((char*)(object) - XtOffsetOf(php_uri_object, std)); } -static inline uri_internal_t *uri_internal_from_obj(const zend_object *object) { - return &(uri_object_from_obj(object)->internal); +#define Z_URI_OBJECT_P(zv) php_uri_object_from_obj(Z_OBJ_P((zv))) + +PHPAPI php_uri_object *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 PHP_URI_SERIALIZE_URI_FIELD_NAME "uri" + +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() + } } -#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_RFC3986 "Uri\\Rfc3986\\Uri" -#define URI_PARSER_WHATWG "Uri\\WhatWg\\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); - -#define URI_ASSERT_INITIALIZATION(internal_uri) do { \ - ZEND_ASSERT(internal_uri != NULL && internal_uri->uri != NULL); \ -} while (0) +void php_uri_property_read_helper(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name, php_uri_component_read_mode component_read_mode); +void php_uri_property_write_str_helper(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name); +void php_uri_property_write_str_or_null_helper(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name); +void php_uri_property_write_long_or_null_helper(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name); #endif diff --git a/ext/uri/php_uriparser.c b/ext/uri/php_uriparser.c deleted file mode 100644 index ba6f1ce776cb6..0000000000000 --- a/ext/uri/php_uriparser.c +++ /dev/null @@ -1,423 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Máté Kocsis | - +----------------------------------------------------------------------+ -*/ - -#include "php.h" -#include "php_uriparser.h" -#include "php_uri_common.h" -#include "Zend/zend_smart_str.h" -#include "Zend/zend_exceptions.h" - -static void uriparser_free_uri(void *uri); -static void throw_invalid_uri_exception(void); - -static void *uriparser_malloc(UriMemoryManager *memory_manager, size_t size) -{ - return emalloc(size); -} - -static void *uriparser_calloc(UriMemoryManager *memory_manager, size_t nmemb, size_t size) -{ - return ecalloc(nmemb, size); -} - -static void *uriparser_realloc(UriMemoryManager *memory_manager, void *ptr, size_t size) -{ - return erealloc(ptr, size); -} - -static void *uriparser_reallocarray(UriMemoryManager *memory_manager, void *ptr, size_t nmemb, size_t size) -{ - return safe_erealloc(ptr, nmemb, size, 0); -} - -static void uriparser_free(UriMemoryManager *memory_manager, void *ptr) -{ - efree(ptr); -} - -static const UriMemoryManager uriparser_mm = { - .malloc = uriparser_malloc, - .calloc = uriparser_calloc, - .realloc = uriparser_realloc, - .reallocarray = uriparser_reallocarray, - .free = uriparser_free, - .userData = NULL, -}; - -/* The library expects a pointer to a non-const UriMemoryManager, but does - * not actually modify it (and neither does our implementation). Use a - * const struct with a non-const pointer for convenience. */ -static UriMemoryManager* const mm = (UriMemoryManager*)&uriparser_mm; - -static inline size_t get_text_range_length(const UriTextRangeA *range) -{ - return range->afterLast - range->first; -} - -ZEND_ATTRIBUTE_NONNULL static void uriparser_copy_uri(UriUriA *new_uriparser_uri, const UriUriA *uriparser_uri) -{ - int result = uriCopyUriMmA(new_uriparser_uri, uriparser_uri, mm); - ZEND_ASSERT(result == URI_SUCCESS); -} - -ZEND_ATTRIBUTE_NONNULL static UriUriA *get_normalized_uri(uriparser_uris_t *uriparser_uris) { - if (!uriparser_uris->normalized_uri_initialized) { - uriparser_copy_uri(&uriparser_uris->normalized_uri, &uriparser_uris->uri); - int result = uriNormalizeSyntaxExMmA(&uriparser_uris->normalized_uri, (unsigned int)-1, mm); - ZEND_ASSERT(result == URI_SUCCESS); - uriparser_uris->normalized_uri_initialized = true; - } - - return &uriparser_uris->normalized_uri; -} - -ZEND_ATTRIBUTE_NONNULL static UriUriA *uriparser_read_uri(uriparser_uris_t *uriparser_uris, uri_component_read_mode_t read_mode) -{ - switch (read_mode) { - case URI_COMPONENT_READ_RAW: - return &uriparser_uris->uri; - case URI_COMPONENT_READ_NORMALIZED_ASCII: - ZEND_FALLTHROUGH; - case URI_COMPONENT_READ_NORMALIZED_UNICODE: - return get_normalized_uri(uriparser_uris); - EMPTY_SWITCH_DEFAULT_CASE() - } -} - -ZEND_ATTRIBUTE_NONNULL static zend_result uriparser_read_scheme(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) -{ - UriUriA *uriparser_uri = uriparser_read_uri(internal_uri->uri, read_mode); - ZEND_ASSERT(uriparser_uri != NULL); - - if (uriparser_uri->scheme.first != NULL && uriparser_uri->scheme.afterLast != NULL) { - zend_string *str = zend_string_init(uriparser_uri->scheme.first, get_text_range_length(&uriparser_uri->scheme), false); - ZVAL_NEW_STR(retval, str); - } else { - ZVAL_NULL(retval); - } - - return SUCCESS; -} - -ZEND_ATTRIBUTE_NONNULL zend_result uriparser_read_userinfo(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) -{ - UriUriA *uriparser_uri = uriparser_read_uri(internal_uri->uri, read_mode); - ZEND_ASSERT(uriparser_uri != NULL); - - if (uriparser_uri->userInfo.first != NULL && uriparser_uri->userInfo.afterLast != NULL) { - ZVAL_STRINGL(retval, uriparser_uri->userInfo.first, get_text_range_length(&uriparser_uri->userInfo)); - } else { - ZVAL_NULL(retval); - } - - return SUCCESS; -} - -ZEND_ATTRIBUTE_NONNULL static zend_result uriparser_read_username(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) -{ - UriUriA *uriparser_uri = uriparser_read_uri(internal_uri->uri, read_mode); - ZEND_ASSERT(uriparser_uri != NULL); - - if (uriparser_uri->userInfo.first != NULL && uriparser_uri->userInfo.afterLast != NULL) { - size_t length = get_text_range_length(&uriparser_uri->userInfo); - const char *c = memchr(uriparser_uri->userInfo.first, ':', length); - - if (c == NULL && length > 0) { - ZVAL_STRINGL(retval, uriparser_uri->userInfo.first, length); - } else if (c != NULL && c - uriparser_uri->userInfo.first > 0) { - ZVAL_STRINGL(retval, uriparser_uri->userInfo.first, c - uriparser_uri->userInfo.first); - } else { - ZVAL_NULL(retval); - } - } else { - ZVAL_NULL(retval); - } - - return SUCCESS; -} - -ZEND_ATTRIBUTE_NONNULL static zend_result uriparser_read_password(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) -{ - UriUriA *uriparser_uri = uriparser_read_uri(internal_uri->uri, read_mode); - ZEND_ASSERT(uriparser_uri != NULL); - - if (uriparser_uri->userInfo.first != NULL && uriparser_uri->userInfo.afterLast != NULL) { - const char *c = memchr(uriparser_uri->userInfo.first, ':', get_text_range_length(&uriparser_uri->userInfo)); - - if (c != NULL && uriparser_uri->userInfo.afterLast - c - 1 > 0) { - ZVAL_STRINGL(retval, c + 1, uriparser_uri->userInfo.afterLast - c - 1); - } else { - ZVAL_NULL(retval); - } - } else { - ZVAL_NULL(retval); - } - - return SUCCESS; -} - -ZEND_ATTRIBUTE_NONNULL static zend_result uriparser_read_host(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) -{ - UriUriA *uriparser_uri = uriparser_read_uri(internal_uri->uri, read_mode); - ZEND_ASSERT(uriparser_uri != NULL); - - if (uriparser_uri->hostText.first != NULL && uriparser_uri->hostText.afterLast != NULL) { - if (uriparser_uri->hostData.ip6 != NULL || uriparser_uri->hostData.ipFuture.first != NULL) { - /* the textual representation of the host is always accessible in the .hostText field no matter what the host is */ - smart_str host_str = {0}; - - smart_str_appendc(&host_str, '['); - smart_str_appendl(&host_str, uriparser_uri->hostText.first, get_text_range_length(&uriparser_uri->hostText)); - smart_str_appendc(&host_str, ']'); - - ZVAL_NEW_STR(retval, smart_str_extract(&host_str)); - } else { - ZVAL_STRINGL(retval, uriparser_uri->hostText.first, get_text_range_length(&uriparser_uri->hostText)); - } - } else { - ZVAL_NULL(retval); - } - - return SUCCESS; -} - -ZEND_ATTRIBUTE_NONNULL static size_t str_to_int(const char *str, size_t len) -{ - size_t result = 0; - - for (size_t i = 0; i < len; ++i) { - result = result * 10 + (str[i] - '0'); - } - - return result; -} - -ZEND_ATTRIBUTE_NONNULL static zend_result uriparser_read_port(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) -{ - UriUriA *uriparser_uri = uriparser_read_uri(internal_uri->uri, read_mode); - ZEND_ASSERT(uriparser_uri != NULL); - - if (uriparser_uri->portText.first != NULL && uriparser_uri->portText.afterLast != NULL) { - ZVAL_LONG(retval, str_to_int(uriparser_uri->portText.first, get_text_range_length(&uriparser_uri->portText))); - } else { - ZVAL_NULL(retval); - } - - return SUCCESS; -} - -ZEND_ATTRIBUTE_NONNULL static zend_result uriparser_read_path(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) -{ - UriUriA *uriparser_uri = uriparser_read_uri(internal_uri->uri, read_mode); - ZEND_ASSERT(uriparser_uri != NULL); - - if (uriparser_uri->pathHead != NULL) { - smart_str str = {0}; - - if (uriparser_uri->absolutePath || uriHasHostA(uriparser_uri)) { - smart_str_appendc(&str, '/'); - } - - for (const UriPathSegmentA *p = uriparser_uri->pathHead; p; p = p->next) { - smart_str_appendl(&str, p->text.first, get_text_range_length(&p->text)); - if (p->next) { - smart_str_appendc(&str, '/'); - } - } - - ZVAL_NEW_STR(retval, smart_str_extract(&str)); - } else if (uriparser_uri->absolutePath) { - ZVAL_CHAR(retval, '/'); - } else { - ZVAL_EMPTY_STRING(retval); - } - - return SUCCESS; -} - -ZEND_ATTRIBUTE_NONNULL static zend_result uriparser_read_query(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) -{ - UriUriA *uriparser_uri = uriparser_read_uri(internal_uri->uri, read_mode); - ZEND_ASSERT(uriparser_uri != NULL); - - if (uriparser_uri->query.first != NULL && uriparser_uri->query.afterLast != NULL) { - ZVAL_STRINGL(retval, uriparser_uri->query.first, get_text_range_length(&uriparser_uri->query)); - } else { - ZVAL_NULL(retval); - } - - return SUCCESS; -} - -ZEND_ATTRIBUTE_NONNULL static zend_result uriparser_read_fragment(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) -{ - UriUriA *uriparser_uri = uriparser_read_uri(internal_uri->uri, read_mode); - ZEND_ASSERT(uriparser_uri != NULL); - - if (uriparser_uri->fragment.first != NULL && uriparser_uri->fragment.afterLast != NULL) { - ZVAL_STRINGL(retval, uriparser_uri->fragment.first, get_text_range_length(&uriparser_uri->fragment)); - } else { - ZVAL_NULL(retval); - } - - return SUCCESS; -} - -PHP_MINIT_FUNCTION(uri_uriparser) -{ - if (uri_handler_register(&uriparser_uri_handler) == FAILURE) { - return FAILURE; - } - - return SUCCESS; -} - -static uriparser_uris_t *uriparser_create_uris(void) -{ - uriparser_uris_t *uriparser_uris = ecalloc(1, sizeof(*uriparser_uris)); - uriparser_uris->normalized_uri_initialized = false; - - return uriparser_uris; -} - -static void throw_invalid_uri_exception(void) -{ - zend_throw_exception(uri_invalid_uri_exception_ce, "The specified URI is malformed", 0); -} - -#define PARSE_URI(dest_uri, uri_str, uriparser_uris, silent) \ - do { \ - if (ZSTR_LEN(uri_str) == 0 || \ - uriParseSingleUriExMmA(dest_uri, ZSTR_VAL(uri_str), ZSTR_VAL(uri_str) + ZSTR_LEN(uri_str), NULL, mm) != URI_SUCCESS \ - ) { \ - efree(uriparser_uris); \ - if (!silent) { \ - throw_invalid_uri_exception(); \ - } \ - return NULL; \ - } \ - } while (0) - -void *uriparser_parse_uri_ex(const zend_string *uri_str, const uriparser_uris_t *uriparser_base_urls, bool silent) -{ - uriparser_uris_t *uriparser_uris = uriparser_create_uris(); - - if (uriparser_base_urls == NULL) { - PARSE_URI(&uriparser_uris->uri, uri_str, uriparser_uris, silent); - uriMakeOwnerMmA(&uriparser_uris->uri, mm); - } else { - UriUriA uri; - - PARSE_URI(&uri, uri_str, uriparser_uris, silent); - - if (uriAddBaseUriExMmA(&uriparser_uris->uri, &uri, &uriparser_base_urls->uri, URI_RESOLVE_STRICTLY, mm) != URI_SUCCESS) { - efree(uriparser_uris); - uriFreeUriMembersMmA(&uri, mm); - if (!silent) { - throw_invalid_uri_exception(); - } - - return NULL; - } - - uriMakeOwnerMmA(&uriparser_uris->uri, mm); - uriFreeUriMembersMmA(&uri, mm); - } - - return uriparser_uris; -} - -void *uriparser_parse_uri(const zend_string *uri_str, const void *base_url, zval *errors, bool silent) -{ - return uriparser_parse_uri_ex(uri_str, base_url, silent); -} - -/* TODO make the clone handler accept a flag to distinguish between clone() calls and withers. - * When calling a wither successfully, the normalized URI is surely invalidated, therefore - * it doesn't make sense to copy it. In case of failure, an exception is thrown, and the URI object - * is discarded altogether. */ -ZEND_ATTRIBUTE_NONNULL static void *uriparser_clone_uri(void *uri) -{ - uriparser_uris_t *uriparser_uris = uri; - - uriparser_uris_t *new_uriparser_uris = uriparser_create_uris(); - uriparser_copy_uri(&new_uriparser_uris->uri, &uriparser_uris->uri); - if (uriparser_uris->normalized_uri_initialized) { - uriparser_copy_uri(&new_uriparser_uris->normalized_uri, &uriparser_uris->normalized_uri); - new_uriparser_uris->normalized_uri_initialized = true; - } - - return new_uriparser_uris; -} - -ZEND_ATTRIBUTE_NONNULL static zend_string *uriparser_uri_to_string(void *uri, uri_recomposition_mode_t recomposition_mode, bool exclude_fragment) -{ - uriparser_uris_t *uriparser_uris = uri; - UriUriA *uriparser_uri; - - if (recomposition_mode == URI_RECOMPOSITION_RAW_ASCII || recomposition_mode == URI_RECOMPOSITION_RAW_UNICODE) { - uriparser_uri = &uriparser_uris->uri; - } else { - uriparser_uri = get_normalized_uri(uriparser_uris); - } - - int charsRequired = 0; - int result = uriToStringCharsRequiredA(uriparser_uri, &charsRequired); - ZEND_ASSERT(result == URI_SUCCESS); - - charsRequired++; - - zend_string *uri_string = zend_string_alloc(charsRequired - 1, false); - result = uriToStringA(ZSTR_VAL(uri_string), uriparser_uri, charsRequired, NULL); - ZEND_ASSERT(result == URI_SUCCESS); - - if (exclude_fragment) { - const char *pos = zend_memrchr(ZSTR_VAL(uri_string), '#', ZSTR_LEN(uri_string)); - if (pos != NULL) { - uri_string = zend_string_truncate(uri_string, (pos - ZSTR_VAL(uri_string)), false); - } - } - - return uri_string; -} - -ZEND_ATTRIBUTE_NONNULL static void uriparser_free_uri(void *uri) -{ - uriparser_uris_t *uriparser_uris = uri; - - uriFreeUriMembersMmA(&uriparser_uris->uri, mm); - uriFreeUriMembersMmA(&uriparser_uris->normalized_uri, mm); - - efree(uriparser_uris); -} - -const uri_handler_t uriparser_uri_handler = { - .name = URI_PARSER_RFC3986, - .parse_uri = uriparser_parse_uri, - .clone_uri = uriparser_clone_uri, - .uri_to_string = uriparser_uri_to_string, - .free_uri = uriparser_free_uri, - { - .scheme = {.read_func = uriparser_read_scheme, .write_func = NULL}, - .username = {.read_func = uriparser_read_username, .write_func = NULL}, - .password = {.read_func = uriparser_read_password, .write_func = NULL}, - .host = {.read_func = uriparser_read_host, .write_func = NULL}, - .port = {.read_func = uriparser_read_port, .write_func = NULL}, - .path = {.read_func = uriparser_read_path, .write_func = NULL}, - .query = {.read_func = uriparser_read_query, .write_func = NULL}, - .fragment = {.read_func = uriparser_read_fragment, .write_func = NULL}, - } -}; diff --git a/ext/uri/php_uriparser.h b/ext/uri/php_uriparser.h deleted file mode 100644 index 1f35c7e69d7a0..0000000000000 --- a/ext/uri/php_uriparser.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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: Máté Kocsis | - +----------------------------------------------------------------------+ -*/ - -#ifndef PHP_URIPARSER_H -#define PHP_URIPARSER_H - -#include -#include "php_uri_common.h" - -extern const uri_handler_t uriparser_uri_handler; - -typedef struct uriparser_uris_t { - UriUriA uri; - UriUriA normalized_uri; - bool normalized_uri_initialized; -} uriparser_uris_t; - -PHP_MINIT_FUNCTION(uri_uriparser); - -zend_result uriparser_read_userinfo(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval); - -void *uriparser_parse_uri_ex(const zend_string *uri_str, const uriparser_uris_t *uriparser_base_url, bool silent); - -#endif diff --git a/ext/uri/tests/004.phpt b/ext/uri/tests/004.phpt index 10e90dc584a8d..d22f52f30c48f 100644 --- a/ext/uri/tests/004.phpt +++ b/ext/uri/tests/004.phpt @@ -5,12 +5,7 @@ uri --FILE-- getMessage() . "\n"; -} - +var_dump(new Uri\Rfc3986\Uri("")); var_dump(Uri\Rfc3986\Uri::parse("")); try { @@ -29,8 +24,42 @@ var_dump(Uri\WhatWg\Url::parse("http://rupaul/'s Drag Race All Stars 7 Winners Ca ?> --EXPECTF-- -The specified URI is malformed -NULL +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) { diff --git a/ext/uri/tests/023.phpt b/ext/uri/tests/023.phpt index a1ca06bd6f6e5..d1b97eaa9ae5c 100644 --- a/ext/uri/tests/023.phpt +++ b/ext/uri/tests/023.phpt @@ -5,6 +5,30 @@ uri --FILE-- getRawScheme()); +var_dump($uri1->getScheme()); + +$uri2 = $uri1->withScheme("http"); +var_dump($uri2->getRawScheme()); +var_dump($uri2->getScheme()); + +$uri3 = $uri2->withScheme(null); +var_dump($uri3->getRawScheme()); +var_dump($uri3->getScheme()); + +try { + $uri3->withScheme(""); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + +try { + $uri3->withScheme("http%73"); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + $url1 = Uri\WhatWg\Url::parse("https://example.com/"); $url2 = $url1->withScheme("http"); @@ -26,6 +50,14 @@ try { ?> --EXPECT-- string(5) "https" +string(5) "https" +string(4) "http" +string(4) "http" +NULL +NULL +The specified scheme is malformed +The specified scheme is malformed +string(5) "https" string(4) "http" The specified scheme is malformed The specified scheme is malformed diff --git a/ext/uri/tests/026.phpt b/ext/uri/tests/026.phpt index 47a8597fa2e7d..2f50e41bb8c1f 100644 --- a/ext/uri/tests/026.phpt +++ b/ext/uri/tests/026.phpt @@ -5,19 +5,84 @@ uri --FILE-- getRawHost()); +var_dump($uri1->getHost()); + +$uri2 = $uri1->withHost("test.com"); +var_dump($uri2->getRawHost()); +var_dump($uri2->getHost()); + +$uri3 = $uri2->withHost("t%65st.com"); // test.com +var_dump($uri3->getRawHost()); +var_dump($uri3->getHost()); + +$uri4 = $uri3->withHost(null); +var_dump($uri4->getRawHost()); +var_dump($uri4->getHost()); + +$uri5 = $uri4->withHost("192.168.0.1"); +var_dump($uri5->getRawHost()); +var_dump($uri5->getHost()); + +$uri6 = $uri5->withHost("[2001:db8:3333:4444:5555:6666:7777:8888]"); +var_dump($uri6->getRawHost()); +var_dump($uri6->getHost()); + +try { + $uri3->withHost("test.com:8080"); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + +try { + $uri3->withHost("t%3As%2Ft.com"); // t:s/t.com +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + +try { + $uri3->withHost("t:s/t.com"); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + +try { + $uri2->withHost(""); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + +$uri1 = Uri\Rfc3986\Uri::parse("ftp://user:pass@foo.com?query=abc#foo"); +$uri2 = $uri1->withHost("test.com"); + +var_dump($uri1->getHost()); +var_dump($uri2->getHost()); + +try { + $uri1->withHost(null); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + $url1 = Uri\WhatWg\Url::parse("https://example.com/"); $url2 = $url1->withHost("test.com"); $url3 = $url2->withHost("t%65st.com"); // test.com +$url4 = $url3->withHost("192.168.0.1"); +$url5 = $url4->withHost("[2001:db8:3333:4444:5555:6666:7777:8888]"); + +var_dump($url1->getAsciiHost()); +var_dump($url2->getAsciiHost()); +var_dump($url3->getAsciiHost()); +var_dump($url4->getAsciiHost()); +var_dump($url5->getAsciiHost()); + try { $url3->withHost("test.com:8080"); } catch (Uri\WhatWg\InvalidUrlException $e) { echo $e->getMessage() . "\n"; } -var_dump($url1->getAsciiHost()); -var_dump($url2->getAsciiHost()); -var_dump($url3->getAsciiHost()); - try { $url3->withHost("t%3As%2Ft.com"); // t:s/t.com } catch (Uri\WhatWg\InvalidUrlException $e) { @@ -44,10 +109,29 @@ var_dump($url2->getAsciiHost()); ?> --EXPECTF-- +string(11) "example.com" +string(11) "example.com" +string(8) "test.com" +string(8) "test.com" +string(10) "t%65st.com" +string(8) "test.com" +NULL +NULL +string(11) "192.168.0.1" +string(11) "192.168.0.1" +string(40) "[2001:db8:3333:4444:5555:6666:7777:8888]" +string(40) "[2001:db8:3333:4444:5555:6666:7777:8888]" +The specified host is malformed The specified host is malformed +string(7) "foo.com" +string(8) "test.com" +Cannot remove the host from a URI that has a userinfo string(11) "example.com" string(8) "test.com" string(8) "test.com" +string(11) "192.168.0.1" +string(40) "[2001:db8:3333:4444:5555:6666:7777:8888]" +The specified host is malformed The specified host is malformed (DomainInvalidCodePoint) The specified host is malformed The specified host is malformed (HostMissing) diff --git a/ext/uri/tests/026_userinfo.phpt b/ext/uri/tests/026_userinfo.phpt new file mode 100644 index 0000000000000..75f54fccf6124 --- /dev/null +++ b/ext/uri/tests/026_userinfo.phpt @@ -0,0 +1,53 @@ +--TEST-- +Test property mutation - userinfo +--EXTENSIONS-- +uri +--FILE-- +getRawUserInfo()); +var_dump($uri1->getUserInfo()); + +$uri2 = $uri1->withUserInfo("user"); +var_dump($uri2->getRawUserInfo()); +var_dump($uri2->getUserInfo()); + +$uri3 = $uri2->withUserInfo(null); +var_dump($uri3->getRawUserInfo()); +var_dump($uri3->getUserInfo()); + +$uri4 = $uri3->withUserInfo("%75s%2Fr:pass"); // us/r:pass +var_dump($uri4->getRawUserInfo()); +var_dump($uri4->getUserInfo()); + +$uri1 = Uri\Rfc3986\Uri::parse("/foo"); +$uri2 = $uri1->withUserInfo(null); +var_dump($uri2->getPort()); + +try { + $uri4->withUserInfo("u:s/r"); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + +$uri5 = Uri\Rfc3986\Uri::parse("file:///foo/bar/"); +$uri6 = $uri5->withUserinfo("user:pass"); + +var_dump($uri5->getUserInfo()); +var_dump($uri6->getUserInfo()); + +?> +--EXPECT-- +NULL +NULL +string(4) "user" +string(4) "user" +NULL +NULL +string(13) "%75s%2Fr:pass" +string(11) "us%2Fr:pass" +NULL +The specified userinfo is malformed +NULL +string(9) "user:pass" diff --git a/ext/uri/tests/027.phpt b/ext/uri/tests/027.phpt index 79c121dd7f383..781932f5889ea 100644 --- a/ext/uri/tests/027.phpt +++ b/ext/uri/tests/027.phpt @@ -5,6 +5,36 @@ uri --FILE-- withPort(22); +$uri3 = $uri2->withPort(null); + +var_dump($uri1->getPort()); +var_dump($uri2->getPort()); +var_dump($uri3->getPort()); + +$uri1 = Uri\Rfc3986\Uri::parse("ftp://foo.com:443?query=abc#foo"); +$uri2 = $uri1->withPort(8080); + +var_dump($uri1->getPort()); +var_dump($uri2->getPort()); + +$uri1 = Uri\Rfc3986\Uri::parse("file:///foo/bar"); +$uri2 = $uri1->withPort(80); + +var_dump($uri1->getPort()); +var_dump($uri2->getPort()); + +$uri1 = Uri\Rfc3986\Uri::parse("/foo"); +$uri2 = $uri1->withPort(null); +var_dump($uri2->getPort()); + +try { + $uri1->withPort(1); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + $url1 = Uri\WhatWg\Url::parse("https://example.com:8080/"); $url2 = $url1->withPort(22); $url3 = $url2->withPort(null); @@ -33,4 +63,13 @@ NULL int(443) int(8080) NULL +int(80) +NULL +Cannot set a port without having a host +int(8080) +int(22) +NULL +int(443) +int(8080) +NULL NULL diff --git a/ext/uri/tests/028.phpt b/ext/uri/tests/028.phpt index fd565c900e02f..9c9c92c00cc0f 100644 --- a/ext/uri/tests/028.phpt +++ b/ext/uri/tests/028.phpt @@ -5,6 +5,44 @@ uri --FILE-- getRawPath()); +var_dump($uri1->getPath()); + +$uri2 = $uri1->withPath("/foo"); +var_dump($uri2->getRawPath()); +var_dump($uri2->getPath()); + +$uri3 = $uri2->withPath("/t%65st"); +var_dump($uri3->getRawPath()); +var_dump($uri3->getPath()); + +$uri4 = $uri3->withPath("/foo%2Fbar"); +var_dump($uri4->getRawPath()); +var_dump($uri4->getPath()); + +$uri5 = $uri4->withPath(""); +var_dump($uri5->getRawPath()); +var_dump($uri5->getPath()); + +try { + $uri5->withPath("test"); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + +try { + $uri5->withPath("/#"); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + +$uri1 = Uri\Rfc3986\Uri::parse("/foo"); +$uri2 = $uri1->withPath("bar"); + +var_dump($uri1->getPath()); +var_dump($uri2->getPath()); + $url1 = Uri\WhatWg\Url::parse("https://example.com/foo/bar/"); $url2 = $url1->withPath("/foo"); $url3 = $url2->withPath(""); @@ -28,6 +66,20 @@ var_dump($url2->getPath()); ?> --EXPECT-- string(9) "/foo/bar/" +string(9) "/foo/bar/" +string(4) "/foo" +string(4) "/foo" +string(7) "/t%65st" +string(5) "/test" +string(10) "/foo%2Fbar" +string(10) "/foo%2Fbar" +string(0) "" +string(0) "" +The specified path is malformed +The specified path is malformed +string(4) "/foo" +string(3) "bar" +string(9) "/foo/bar/" string(4) "/foo" string(1) "/" string(7) "/t%65st" diff --git a/ext/uri/tests/029.phpt b/ext/uri/tests/029.phpt index e23008a65ad6a..f7a1a0989910d 100644 --- a/ext/uri/tests/029.phpt +++ b/ext/uri/tests/029.phpt @@ -5,6 +5,44 @@ uri --FILE-- getRawQuery()); +var_dump($uri1->getQuery()); + +$uri2 = $uri1->withQuery("foo=baz"); +var_dump($uri2->getRawQuery()); +var_dump($uri2->getQuery()); + +$uri3 = $uri2->withQuery(null); +var_dump($uri3->getRawQuery()); +var_dump($uri3->getQuery()); + +$uri1 = Uri\Rfc3986\Uri::parse("https://example.com/"); +var_dump($uri1->getRawQuery()); +var_dump($uri1->getQuery()); + +$uri2 = $uri1->withQuery("?foo=bar&foo=baz"); +var_dump($uri2->getRawQuery()); +var_dump($uri2->getQuery()); + +$uri3 = $uri1->withQuery("foo=bar&foo=baz"); +var_dump($uri3->getRawQuery()); +var_dump($uri3->getQuery()); + +$uri4 = $uri3->withQuery("t%65st"); +var_dump($uri4->getRawQuery()); +var_dump($uri4->getQuery()); + +$uri5 = $uri4->withQuery("foo=foo%26bar&baz=/qux%3D"); +var_dump($uri5->getRawQuery()); +var_dump($uri5->getQuery()); + +try { + $uri5->withQuery("#"); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + $url1 = Uri\WhatWg\Url::parse("https://example.com/?foo=bar"); $url2 = $url1->withQuery("?foo=baz"); $url3 = $url2->withQuery(null); @@ -30,6 +68,23 @@ var_dump($url6->getQuery()); ?> --EXPECT-- string(7) "foo=bar" +string(7) "foo=bar" +string(7) "foo=baz" +string(7) "foo=baz" +NULL +NULL +NULL +NULL +string(16) "?foo=bar&foo=baz" +string(16) "?foo=bar&foo=baz" +string(15) "foo=bar&foo=baz" +string(15) "foo=bar&foo=baz" +string(6) "t%65st" +string(4) "test" +string(25) "foo=foo%26bar&baz=/qux%3D" +string(25) "foo=foo%26bar&baz=/qux%3D" +The specified query is malformed +string(7) "foo=bar" string(7) "foo=baz" NULL NULL diff --git a/ext/uri/tests/030.phpt b/ext/uri/tests/030.phpt index 6bb85e6720c95..92e99d01f8929 100644 --- a/ext/uri/tests/030.phpt +++ b/ext/uri/tests/030.phpt @@ -5,6 +5,36 @@ uri --FILE-- getRawFragment()); +var_dump($uri1->getFragment()); + +$uri2 = $uri1->withFragment("fragment2"); +var_dump($uri2->getRawFragment()); +var_dump($uri2->getFragment()); + +$uri3 = $uri2->withFragment(null); +var_dump($uri3->getRawFragment()); +var_dump($uri3->getFragment()); + +try { + $uri3->withFragment(" "); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + +try { + $uri1->withFragment("#fragment2"); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + +$uri1 = Uri\Rfc3986\Uri::parse("https://example.com/?abc=def"); +$uri2 = $uri1->withFragment("fragment"); + +var_dump($uri1->getFragment()); +var_dump($uri2->getFragment()); + $url1 = Uri\WhatWg\Url::parse("https://example.com/#fragment1"); $url2 = $url1->withFragment("#fragment2"); $url3 = $url2->withFragment(null); @@ -24,6 +54,16 @@ var_dump($url2->getFragment()); ?> --EXPECT-- string(9) "fragment1" +string(9) "fragment1" +string(9) "fragment2" +string(9) "fragment2" +NULL +NULL +The specified fragment is malformed +The specified fragment is malformed +NULL +string(8) "fragment" +string(9) "fragment1" string(9) "fragment2" NULL string(3) "%20" diff --git a/ext/uri/tests/035.phpt b/ext/uri/tests/035.phpt deleted file mode 100644 index 2712038d4e3d7..0000000000000 --- a/ext/uri/tests/035.phpt +++ /dev/null @@ -1,31 +0,0 @@ ---TEST-- -Test URI parsing containing null bytes ---EXTENSIONS-- -uri ---FILE-- -getMessage() . "\n"; -} - -try { - new Uri\WhatWg\Url("https://exam/0ple.com"); -} catch (Error $e) { - echo $e->getMessage() . "\n"; -} - -$url = new Uri\WhatWg\Url("https://example.com/"); -try { - $url->withHost("exam\0ple.com"); -} catch (Error $e) { - echo $e->getMessage() . "\n"; -} - -?> ---EXPECT-- -Uri\Rfc3986\Uri::__construct(): Argument #1 ($uri) must not contain any null bytes -Uri\WhatWg\Url::__construct(): Argument #1 ($uri) must not contain any null bytes -Uri\WhatWg\Url::withHost(): Argument #1 ($host) must not contain any null bytes diff --git a/ext/uri/tests/055.phpt b/ext/uri/tests/055.phpt index 95aac9d3a8b67..1b1684d350b09 100644 --- a/ext/uri/tests/055.phpt +++ b/ext/uri/tests/055.phpt @@ -12,4 +12,4 @@ try { } ?> --EXPECT-- -The specified URI is malformed +The specified base URI must be absolute diff --git a/ext/uri/tests/056.phpt b/ext/uri/tests/056.phpt new file mode 100644 index 0000000000000..a39d7897357d4 --- /dev/null +++ b/ext/uri/tests/056.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Lexbor memory management +--EXTENSIONS-- +uri +--FILE-- +toAsciiString() !== "https://example.com/%7B$i%7D/") { + die("FAIL"); + } +} + +?> +==DONE== +--EXPECT-- +==DONE== diff --git a/ext/uri/tests/057.phpt b/ext/uri/tests/057.phpt new file mode 100644 index 0000000000000..458bdb468e341 --- /dev/null +++ b/ext/uri/tests/057.phpt @@ -0,0 +1,21 @@ +--TEST-- +Test assigning errors by reference fails +--EXTENSIONS-- +uri +--FILE-- +x); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +TypeError: Cannot assign array to reference held by property Foo::$x of type string diff --git a/ext/uri/tests/058.phpt b/ext/uri/tests/058.phpt new file mode 100644 index 0000000000000..efca0a0e8aaf6 --- /dev/null +++ b/ext/uri/tests/058.phpt @@ -0,0 +1,32 @@ +--TEST-- +Test that integer overflows in the port are rejected +--EXTENSIONS-- +uri +--FILE-- +getPort(), PHP_EOL; + echo "2147483647", PHP_EOL; +} else { + $uri = new \Uri\Rfc3986\Uri('https://example.com:2147483647'); + echo "9223372036854775807", PHP_EOL; + echo $uri->getPort(), PHP_EOL; +} + +try { + if (PHP_INT_SIZE == 8) { + new \Uri\Rfc3986\Uri('https://example.com:9223372036854775808'); + } else { + new \Uri\Rfc3986\Uri('https://example.com:2147483648'); + } +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +9223372036854775807 +2147483647 +Uri\InvalidUriException: The port is out of range diff --git a/ext/uri/tests/059.phpt b/ext/uri/tests/059.phpt new file mode 100644 index 0000000000000..3d7cef10dff12 --- /dev/null +++ b/ext/uri/tests/059.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test empty ports become null +--EXTENSIONS-- +uri +--FILE-- +getPort()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (8) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +NULL diff --git a/ext/uri/tests/065.phpt b/ext/uri/tests/065.phpt new file mode 100644 index 0000000000000..d9a6c905c9ef8 --- /dev/null +++ b/ext/uri/tests/065.phpt @@ -0,0 +1,117 @@ +--TEST-- +Test that overwriting the URI is not possible +--EXTENSIONS-- +uri +--FILE-- +__construct('ftp://example.org'); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} +var_dump($uri); + +$uri = new Uri\WhatWg\Url('https://example.com/'); +try { + $uri->__unserialize([['uri' => 'ftp://example.org'], []]); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} +var_dump($uri); + +$uri = new Uri\Rfc3986\Uri('https://example.com/'); +try { + $uri->__construct('ftp://example.org'); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} +var_dump($uri); + +$uri = new Uri\Rfc3986\Uri('https://example.com/'); +try { + $uri->__unserialize([['uri' => 'ftp://example.org'], []]); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} +var_dump($uri); + +?> +--EXPECTF-- +Error: Cannot modify readonly object of class Uri\WhatWg\Url +object(Uri\WhatWg\Url)#%d (8) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +Exception: Invalid serialization data for Uri\WhatWg\Url object +object(Uri\WhatWg\Url)#%d (8) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +Error: Cannot modify readonly object of class Uri\Rfc3986\Uri +object(Uri\Rfc3986\Uri)#%d (8) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +Exception: Invalid serialization data for Uri\Rfc3986\Uri object +object(Uri\Rfc3986\Uri)#%d (8) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL +} diff --git a/ext/uri/tests/100.phpt b/ext/uri/tests/100.phpt new file mode 100644 index 0000000000000..0c1abcdd00b6f --- /dev/null +++ b/ext/uri/tests/100.phpt @@ -0,0 +1,71 @@ +--TEST-- +Test the parse_url-based URI parser +--EXTENSIONS-- +uri +zend_test +--FILE-- + +--EXPECT-- +array(3) { + ["normalized"]=> + array(8) { + ["scheme"]=> + string(5) "https" + ["username"]=> + string(7) "example" + ["password"]=> + string(7) "example" + ["host"]=> + string(11) "example.com" + ["port"]=> + int(123) + ["path"]=> + string(13) "/example.html" + ["query"]=> + string(15) "example=example" + ["fragment"]=> + string(7) "example" + } + ["raw"]=> + array(8) { + ["scheme"]=> + string(5) "https" + ["username"]=> + string(9) "%65xample" + ["password"]=> + string(9) "%65xample" + ["host"]=> + string(13) "%65xample.com" + ["port"]=> + int(123) + ["path"]=> + string(15) "/%65xample.html" + ["query"]=> + string(19) "%65xample=%65xample" + ["fragment"]=> + string(9) "%65xample" + } + ["struct"]=> + array(8) { + ["scheme"]=> + string(5) "https" + ["username"]=> + string(9) "%65xample" + ["password"]=> + string(9) "%65xample" + ["host"]=> + string(13) "%65xample.com" + ["port"]=> + int(123) + ["path"]=> + string(15) "/%65xample.html" + ["query"]=> + string(19) "%65xample=%65xample" + ["fragment"]=> + string(9) "%65xample" + } +} diff --git a/ext/uri/tests/101.phpt b/ext/uri/tests/101.phpt new file mode 100644 index 0000000000000..8a44b376a6127 --- /dev/null +++ b/ext/uri/tests/101.phpt @@ -0,0 +1,29 @@ +--TEST-- +Test the Lexbor-based URI parser +--EXTENSIONS-- +uri +zend_test +--FILE-- +getMessage(), PHP_EOL; + var_dump($e->errors); +} + +?> +--EXPECTF-- +The specified URI is malformed (MissingSchemeNonRelativeUrl) +array(1) { + [0]=> + object(Uri\WhatWg\UrlValidationError)#%d (3) { + ["context"]=> + string(11) "invalid uri" + ["type"]=> + enum(Uri\WhatWg\UrlValidationErrorType::MissingSchemeNonRelativeUrl) + ["failure"]=> + bool(true) + } +} diff --git a/ext/uri/tests/102.phpt b/ext/uri/tests/102.phpt new file mode 100644 index 0000000000000..6080c1be884cd --- /dev/null +++ b/ext/uri/tests/102.phpt @@ -0,0 +1,71 @@ +--TEST-- +Test the handling large ports for the uri struct +--EXTENSIONS-- +uri +zend_test +--FILE-- + +--EXPECT-- +array(3) { + ["normalized"]=> + array(8) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + int(42424242) + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL + } + ["raw"]=> + array(8) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + int(42424242) + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL + } + ["struct"]=> + array(8) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + int(42424242) + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL + } +} diff --git a/ext/uri/tests/gh19780.phpt b/ext/uri/tests/gh19780.phpt new file mode 100644 index 0000000000000..7271c60e8f938 --- /dev/null +++ b/ext/uri/tests/gh19780.phpt @@ -0,0 +1,29 @@ +--TEST-- +GH-19780 (InvalidUrlException should check $errors argument) +--EXTENSIONS-- +uri +--FILE-- +getMessage(), "\n"; +} + +try { + new InvalidUrlException('message', [ + 1 => new UrlValidationError('context', UrlValidationErrorType::HostMissing, true) + ]); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException::__construct(): Argument #2 ($errors) must be a list of Uri\WhatWg\UrlValidationError +Uri\WhatWg\InvalidUrlException::__construct(): Argument #2 ($errors) must be a list of Uri\WhatWg\UrlValidationError diff --git a/ext/uri/tests/gh19892.phpt b/ext/uri/tests/gh19892.phpt new file mode 100644 index 0000000000000..42a9c660e0d05 --- /dev/null +++ b/ext/uri/tests/gh19892.phpt @@ -0,0 +1,12 @@ +--TEST-- +GH-19892: Successful \Uri\WhatWg\Url::parse() with empty errors array +--FILE-- + +--EXPECT-- +array(0) { +} diff --git a/ext/uri/tests/gh19979.phpt b/ext/uri/tests/gh19979.phpt new file mode 100644 index 0000000000000..982dfb9359434 --- /dev/null +++ b/ext/uri/tests/gh19979.phpt @@ -0,0 +1,28 @@ +--TEST-- +GH-19979: Zend/zend_string.h:191:24: runtime error: null pointer passed as argument 2, which is declared to never be null +--FILE-- + +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (8) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(9) "/relative" + ["query"]=> + NULL + ["fragment"]=> + NULL +} diff --git a/ext/uri/tests/rfc3986/modification/fragment_error_reserved.phpt b/ext/uri/tests/rfc3986/modification/fragment_error_reserved.phpt new file mode 100644 index 0000000000000..1afde4151ac69 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/fragment_error_reserved.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - fragment - reserved characters +--EXTENSIONS-- +uri +--FILE-- +withFragment("#fragment"); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified fragment is malformed diff --git a/ext/uri/tests/rfc3986/modification/fragment_error_unicode.phpt b/ext/uri/tests/rfc3986/modification/fragment_error_unicode.phpt new file mode 100644 index 0000000000000..5d6cf1198c9c0 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/fragment_error_unicode.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - fragment - unicode characters +--EXTENSIONS-- +uri +--FILE-- +withFragment("ő"); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified fragment is malformed diff --git a/ext/uri/tests/rfc3986/modification/fragment_success_empty.phpt b/ext/uri/tests/rfc3986/modification/fragment_success_empty.phpt new file mode 100644 index 0000000000000..f0a05d5bb5bb0 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/fragment_success_empty.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - fragment - empty string +--EXTENSIONS-- +uri +--FILE-- +withFragment(""); + +var_dump($uri1->getRawFragment()); +var_dump($uri2->getRawFragment()); +var_dump($uri2->toRawString()); +var_dump($uri2->getFragment()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +NULL +string(0) "" +string(20) "https://example.com/#" +string(0) "" +string(20) "https://example.com/#" diff --git a/ext/uri/tests/rfc3986/modification/fragment_success_encoded.phpt b/ext/uri/tests/rfc3986/modification/fragment_success_encoded.phpt new file mode 100644 index 0000000000000..b1b1081ff81c0 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/fragment_success_encoded.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - fragment - URL encoded characters +--EXTENSIONS-- +uri +--FILE-- +withFragment("foo%3db%61r"); // foo=bar + +var_dump($uri1->getRawFragment()); +var_dump($uri2->getRawFragment()); +var_dump($uri2->toRawString()); +var_dump($uri2->getFragment()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +NULL +string(11) "foo%3db%61r" +string(31) "https://example.com/#foo%3db%61r" +string(9) "foo%3Dbar" +string(29) "https://example.com/#foo%3Dbar" diff --git a/ext/uri/tests/rfc3986/modification/fragment_success_existing.phpt b/ext/uri/tests/rfc3986/modification/fragment_success_existing.phpt new file mode 100644 index 0000000000000..fe534e8465041 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/fragment_success_existing.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - fragment - changing an existing one +--EXTENSIONS-- +uri +--FILE-- +withFragment("bar"); + +var_dump($uri1->getRawFragment()); +var_dump($uri2->getRawFragment()); +var_dump($uri2->toRawString()); +var_dump($uri2->getFragment()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +string(3) "foo" +string(3) "bar" +string(23) "https://example.com/#bar" +string(3) "bar" +string(23) "https://example.com/#bar" diff --git a/ext/uri/tests/rfc3986/modification/fragment_success_unset_existing.phpt b/ext/uri/tests/rfc3986/modification/fragment_success_unset_existing.phpt new file mode 100644 index 0000000000000..7532c35e0fe76 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/fragment_success_unset_existing.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - fragment - unsetting existing +--EXTENSIONS-- +uri +--FILE-- +withFragment(null); + +var_dump($uri1->getRawFragment()); +var_dump($uri2->getRawFragment()); +var_dump($uri2->toRawString()); +var_dump($uri2->getFragment()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +string(3) "foo" +NULL +string(19) "https://example.com/" +NULL +string(19) "https://example.com/" diff --git a/ext/uri/tests/rfc3986/modification/fragment_success_unset_non_existent.phpt b/ext/uri/tests/rfc3986/modification/fragment_success_unset_non_existent.phpt new file mode 100644 index 0000000000000..1c6fa898dde36 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/fragment_success_unset_non_existent.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - fragment - unsetting not-existent +--EXTENSIONS-- +uri +--FILE-- +withFragment(null); + +var_dump($uri1->getRawFragment()); +var_dump($uri2->getRawFragment()); +var_dump($uri2->toRawString()); +var_dump($uri2->getFragment()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +NULL +NULL +string(19) "https://example.com/" +NULL +string(19) "https://example.com/" diff --git a/ext/uri/tests/rfc3986/modification/host_error_reserved.phpt b/ext/uri/tests/rfc3986/modification/host_error_reserved.phpt new file mode 100644 index 0000000000000..ca87c1a3ce266 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/host_error_reserved.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - host - reserved characters +--EXTENSIONS-- +uri +--FILE-- +withHost("ex#mple.com"); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified host is malformed diff --git a/ext/uri/tests/rfc3986/modification/host_success_empty.phpt b/ext/uri/tests/rfc3986/modification/host_success_empty.phpt new file mode 100644 index 0000000000000..b337674841c6b --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/host_success_empty.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - host - empty string +--EXTENSIONS-- +uri +--FILE-- +withHost(""); + +var_dump($uri1->getRawHost()); +var_dump($uri2->getRawHost()); +var_dump($uri2->toRawString()); +var_dump($uri2->getHost()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +string(11) "example.com" +string(0) "" +string(8) "https://" +string(0) "" +string(8) "https://" diff --git a/ext/uri/tests/rfc3986/modification/host_success_encoded.phpt b/ext/uri/tests/rfc3986/modification/host_success_encoded.phpt new file mode 100644 index 0000000000000..d9db6003b1572 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/host_success_encoded.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - host - URL encoded characters +--EXTENSIONS-- +uri +--FILE-- +withHost("%65xample.net"); // example.net + +var_dump($uri1->getRawHost()); +var_dump($uri2->getRawHost()); +var_dump($uri2->toRawString()); +var_dump($uri2->getHost()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +string(11) "example.com" +string(13) "%65xample.net" +string(21) "https://example.net/" +string(11) "example.net" +string(19) "https://example.net/" diff --git a/ext/uri/tests/rfc3986/modification/host_success_existing.phpt b/ext/uri/tests/rfc3986/modification/host_success_existing.phpt new file mode 100644 index 0000000000000..f9d3da987abc0 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/host_success_existing.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - host - changing an existing one +--EXTENSIONS-- +uri +--FILE-- +withHost("example.net"); + +var_dump($uri1->getRawHost()); +var_dump($uri2->getRawHost()); +var_dump($uri2->toRawString()); +var_dump($uri2->getHost()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +string(11) "example.com" +string(11) "example.net" +string(19) "https://example.net/" +string(11) "example.net" +string(19) "https://example.net/" diff --git a/ext/uri/tests/rfc3986/modification/host_success_ip_future.phpt b/ext/uri/tests/rfc3986/modification/host_success_ip_future.phpt new file mode 100644 index 0000000000000..004210000cf43 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/host_success_ip_future.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - host - IP future address +--EXTENSIONS-- +uri +--FILE-- +withHost("[vF.addr]"); + +var_dump($uri1->getRawHost()); +var_dump($uri2->getRawHost()); +var_dump($uri2->toRawString()); +var_dump($uri2->getHost()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +string(11) "example.com" +string(9) "[vF.addr]" +string(17) "https://[vF.addr]" +string(9) "[vf.addr]" +string(17) "https://[vf.addr]" diff --git a/ext/uri/tests/rfc3986/modification/host_success_ipv4.phpt b/ext/uri/tests/rfc3986/modification/host_success_ipv4.phpt new file mode 100644 index 0000000000000..850a32281aba6 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/host_success_ipv4.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - host - IPv4 address +--EXTENSIONS-- +uri +--FILE-- +withHost("192.168.0.1"); + +var_dump($uri1->getRawHost()); +var_dump($uri2->getRawHost()); +var_dump($uri2->toRawString()); +var_dump($uri2->getHost()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +string(11) "example.com" +string(11) "192.168.0.1" +string(19) "https://192.168.0.1/" +string(11) "192.168.0.1" +string(19) "https://192.168.0.1/" diff --git a/ext/uri/tests/rfc3986/modification/host_success_ipv6.phpt b/ext/uri/tests/rfc3986/modification/host_success_ipv6.phpt new file mode 100644 index 0000000000000..4750888401599 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/host_success_ipv6.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - host - IPv6 address +--EXTENSIONS-- +uri +--FILE-- +withHost("[2001:0db8:3333:4444:5555:6666:7777:8888]"); + +var_dump($uri1->getRawHost()); +var_dump($uri2->getRawHost()); +var_dump($uri2->toRawString()); +var_dump($uri2->getHost()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +string(11) "example.com" +string(41) "[2001:0db8:3333:4444:5555:6666:7777:8888]" +string(49) "https://[2001:db8:3333:4444:5555:6666:7777:8888]/" +string(41) "[2001:0db8:3333:4444:5555:6666:7777:8888]" +string(49) "https://[2001:db8:3333:4444:5555:6666:7777:8888]/" diff --git a/ext/uri/tests/rfc3986/modification/host_success_new.phpt b/ext/uri/tests/rfc3986/modification/host_success_new.phpt new file mode 100644 index 0000000000000..326616140078f --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/host_success_new.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - host - adding a new one +--EXTENSIONS-- +uri +--FILE-- +withHost("example.com"); + +var_dump($uri1->getRawHost()); +var_dump($uri2->getRawHost()); +var_dump($uri2->toRawString()); +var_dump($uri2->getHost()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +NULL +string(11) "example.com" +string(21) "//example.com/foo/bar" +string(11) "example.com" +string(21) "//example.com/foo/bar" diff --git a/ext/uri/tests/rfc3986/modification/host_success_unset_existing.phpt b/ext/uri/tests/rfc3986/modification/host_success_unset_existing.phpt new file mode 100644 index 0000000000000..8f79d723be5dd --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/host_success_unset_existing.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - host - unsetting existing +--EXTENSIONS-- +uri +--FILE-- +withHost(null); + +var_dump($uri1->getRawHost()); +var_dump($uri2->getRawHost()); +var_dump($uri2->toRawString()); +var_dump($uri2->getHost()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +string(11) "example.com" +NULL +string(6) "https:" +NULL +string(6) "https:" diff --git a/ext/uri/tests/rfc3986/modification/host_success_unset_non_existent.phpt b/ext/uri/tests/rfc3986/modification/host_success_unset_non_existent.phpt new file mode 100644 index 0000000000000..b1793a31413ab --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/host_success_unset_non_existent.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - host - unsetting non-existent +--EXTENSIONS-- +uri +--FILE-- +withHost(null); + +var_dump($uri1->getRawHost()); +var_dump($uri2->getRawHost()); +var_dump($uri2->toRawString()); +var_dump($uri2->getHost()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +NULL +NULL +string(8) "/foo/bar" +NULL +string(8) "/foo/bar" diff --git a/ext/uri/tests/rfc3986/modification/path_error_null_byte.phpt b/ext/uri/tests/rfc3986/modification/path_error_null_byte.phpt new file mode 100644 index 0000000000000..d02e3e8575f2d --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/path_error_null_byte.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - path - null byte +--EXTENSIONS-- +uri +--FILE-- +withPath("/\0foo"); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified path is malformed diff --git a/ext/uri/tests/rfc3986/modification/path_error_reserved.phpt b/ext/uri/tests/rfc3986/modification/path_error_reserved.phpt new file mode 100644 index 0000000000000..e883a7daed19e --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/path_error_reserved.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - path - reserved characters +--EXTENSIONS-- +uri +--FILE-- +withPath("/[foo]"); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified path is malformed diff --git a/ext/uri/tests/rfc3986/modification/path_error_unicode.phpt b/ext/uri/tests/rfc3986/modification/path_error_unicode.phpt new file mode 100644 index 0000000000000..5fc836533ca11 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/path_error_unicode.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - path - unicode characters +--EXTENSIONS-- +uri +--FILE-- +withPath("/ő"); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified path is malformed diff --git a/ext/uri/tests/rfc3986/modification/path_error_without_leading_slash.phpt b/ext/uri/tests/rfc3986/modification/path_error_without_leading_slash.phpt new file mode 100644 index 0000000000000..b6f66bdb5e44c --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/path_error_without_leading_slash.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - path - without leading slash +--EXTENSIONS-- +uri +--FILE-- +withPath("foo"); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified path is malformed diff --git a/ext/uri/tests/rfc3986/modification/path_success_email.phpt b/ext/uri/tests/rfc3986/modification/path_success_email.phpt new file mode 100644 index 0000000000000..58f5ab4baa6d5 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/path_success_email.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - path - using an email format +--EXTENSIONS-- +uri +--FILE-- +withPath("john.doe@example.com"); + +var_dump($uri1->getRawPath()); +var_dump($uri2->getRawPath()); +var_dump($uri2->toRawString()); +var_dump($uri2->getPath()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +string(0) "" +string(20) "john.doe@example.com" +string(20) "john.doe@example.com" +string(20) "john.doe@example.com" +string(20) "john.doe@example.com" diff --git a/ext/uri/tests/rfc3986/modification/path_success_empty.phpt b/ext/uri/tests/rfc3986/modification/path_success_empty.phpt new file mode 100644 index 0000000000000..a67eeae44eed4 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/path_success_empty.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - path - empty string +--EXTENSIONS-- +uri +--FILE-- +withPath(""); + +var_dump($uri1->getRawPath()); +var_dump($uri2->getRawPath()); +var_dump($uri2->toRawString()); +var_dump($uri2->getPath()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +string(0) "" +string(0) "" +string(19) "https://example.com/" +string(0) "" +string(19) "https://example.com/" diff --git a/ext/uri/tests/rfc3986/modification/path_success_encoded.phpt b/ext/uri/tests/rfc3986/modification/path_success_encoded.phpt new file mode 100644 index 0000000000000..05b62cafe2509 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/path_success_encoded.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - path - URL encoded characters +--EXTENSIONS-- +uri +--FILE-- +withPath("/foo%2Fb%61r"); // /foo/bar + +var_dump($uri1->getRawPath()); +var_dump($uri2->getRawPath()); +var_dump($uri2->toRawString()); +var_dump($uri2->getPath()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +string(0) "" +string(12) "/foo%2Fb%61r" +string(31) "https://example.com/foo%2Fb%61r" +string(10) "/foo%2Fbar" +string(29) "https://example.com/foo%2Fbar" diff --git a/ext/uri/tests/rfc3986/modification/path_success_existing.phpt b/ext/uri/tests/rfc3986/modification/path_success_existing.phpt new file mode 100644 index 0000000000000..6dafbc0a3ff80 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/path_success_existing.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - path - changing an existing one +--EXTENSIONS-- +uri +--FILE-- +withPath("/baz"); + +var_dump($uri1->getRawPath()); +var_dump($uri2->getRawPath()); +var_dump($uri2->toRawString()); +var_dump($uri2->getPath()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +string(8) "/foo/bar" +string(4) "/baz" +string(23) "https://example.com/baz" +string(4) "/baz" +string(23) "https://example.com/baz" diff --git a/ext/uri/tests/rfc3986/modification/port_error_negative.phpt b/ext/uri/tests/rfc3986/modification/port_error_negative.phpt new file mode 100644 index 0000000000000..b8a25ee766673 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/port_error_negative.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - host - too small number +--EXTENSIONS-- +uri +--FILE-- +withPort(-1); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified port is malformed diff --git a/ext/uri/tests/rfc3986/modification/port_success_existing.phpt b/ext/uri/tests/rfc3986/modification/port_success_existing.phpt new file mode 100644 index 0000000000000..8451f1bcf4690 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/port_success_existing.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - port - changing an existing one +--EXTENSIONS-- +uri +--FILE-- +withPort(443); + +var_dump($uri1->getPort()); +var_dump($uri2->getPort()); +var_dump($uri2->toRawString()); + +?> +--EXPECT-- +int(80) +int(443) +string(23) "https://example.com/" diff --git a/ext/uri/tests/rfc3986/modification/port_success_new.phpt b/ext/uri/tests/rfc3986/modification/port_success_new.phpt new file mode 100644 index 0000000000000..36ccea04a9497 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/port_success_new.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - port - adding a new one +--EXTENSIONS-- +uri +--FILE-- +withPort(443); + +var_dump($uri1->getPort()); +var_dump($uri2->getPort()); +var_dump($uri2->toRawString()); + +?> +--EXPECT-- +NULL +int(443) +string(23) "https://example.com/" diff --git a/ext/uri/tests/rfc3986/modification/port_success_unset_existing.phpt b/ext/uri/tests/rfc3986/modification/port_success_unset_existing.phpt new file mode 100644 index 0000000000000..574af3f6e3ee7 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/port_success_unset_existing.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - port - unsetting existing +--EXTENSIONS-- +uri +--FILE-- +withPort(null); + +var_dump($uri1->getPort()); +var_dump($uri2->getPort()); +var_dump($uri2->toRawString()); + +?> +--EXPECT-- +int(80) +NULL +string(19) "https://example.com/" diff --git a/ext/uri/tests/rfc3986/modification/port_success_unset_non_existent.phpt b/ext/uri/tests/rfc3986/modification/port_success_unset_non_existent.phpt new file mode 100644 index 0000000000000..a3fbdc5e87422 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/port_success_unset_non_existent.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - port - unsetting non-existent +--EXTENSIONS-- +uri +--FILE-- +withPort(null); + +var_dump($uri2->getPort()); +var_dump($uri2->getPort()); +var_dump($uri2->toRawString()); + +?> +--EXPECT-- +NULL +NULL +string(17) "ftp://example.com" diff --git a/ext/uri/tests/rfc3986/modification/query_error_reserved.phpt b/ext/uri/tests/rfc3986/modification/query_error_reserved.phpt new file mode 100644 index 0000000000000..d7f9745e9ef75 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/query_error_reserved.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - query - reserved characters +--EXTENSIONS-- +uri +--FILE-- +withQuery("#foo"); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified query is malformed diff --git a/ext/uri/tests/rfc3986/modification/query_error_unicode.phpt b/ext/uri/tests/rfc3986/modification/query_error_unicode.phpt new file mode 100644 index 0000000000000..964e6b36d72bc --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/query_error_unicode.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - query - unicode characters +--EXTENSIONS-- +uri +--FILE-- +withQuery("ő"); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified query is malformed diff --git a/ext/uri/tests/rfc3986/modification/query_success_context_sensitive_reserved.phpt b/ext/uri/tests/rfc3986/modification/query_success_context_sensitive_reserved.phpt new file mode 100644 index 0000000000000..d40a7f7e09efb --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/query_success_context_sensitive_reserved.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - query - context-sensitive reserved character +--EXTENSIONS-- +uri +--FILE-- +withQuery("?foo=bar"); + +var_dump($uri1->getRawQuery()); +var_dump($uri2->getRawQuery()); +var_dump($uri2->toRawString()); +var_dump($uri2->getQuery()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +NULL +string(8) "?foo=bar" +string(28) "https://example.com/??foo=bar" +string(8) "?foo=bar" +string(28) "https://example.com/??foo=bar" diff --git a/ext/uri/tests/rfc3986/modification/query_success_empty.phpt b/ext/uri/tests/rfc3986/modification/query_success_empty.phpt new file mode 100644 index 0000000000000..e668b44df9b3a --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/query_success_empty.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - query - empty string +--EXTENSIONS-- +uri +--FILE-- +withQuery(""); + +var_dump($uri1->getRawQuery()); +var_dump($uri2->getRawQuery()); +var_dump($uri2->toRawString()); +var_dump($uri2->getQuery()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +NULL +string(0) "" +string(20) "https://example.com/?" +string(0) "" +string(20) "https://example.com/?" diff --git a/ext/uri/tests/rfc3986/modification/query_success_encoded.phpt b/ext/uri/tests/rfc3986/modification/query_success_encoded.phpt new file mode 100644 index 0000000000000..7fd9707220d88 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/query_success_encoded.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - query - URL encoded characters +--EXTENSIONS-- +uri +--FILE-- +withQuery("foo%3dbar"); // foo=bar + +var_dump($uri1->getRawQuery()); +var_dump($uri2->getRawQuery()); +var_dump($uri2->toRawString()); +var_dump($uri2->getQuery()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +NULL +string(9) "foo%3dbar" +string(29) "https://example.com/?foo%3dbar" +string(9) "foo%3Dbar" +string(29) "https://example.com/?foo%3Dbar" diff --git a/ext/uri/tests/rfc3986/modification/query_success_existing.phpt b/ext/uri/tests/rfc3986/modification/query_success_existing.phpt new file mode 100644 index 0000000000000..b5af7feee2507 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/query_success_existing.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - query - changing an existing one +--EXTENSIONS-- +uri +--FILE-- +withQuery("foo=bar&baz=qux"); + +var_dump($uri1->getRawQuery()); +var_dump($uri2->getRawQuery()); +var_dump($uri2->toRawString()); +var_dump($uri2->getQuery()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +string(7) "foo=bar" +string(15) "foo=bar&baz=qux" +string(35) "https://example.com/?foo=bar&baz=qux" +string(15) "foo=bar&baz=qux" +string(35) "https://example.com/?foo=bar&baz=qux" diff --git a/ext/uri/tests/rfc3986/modification/query_success_unset_existing.phpt b/ext/uri/tests/rfc3986/modification/query_success_unset_existing.phpt new file mode 100644 index 0000000000000..89d130eedc27b --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/query_success_unset_existing.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - query - unsetting existing +--EXTENSIONS-- +uri +--FILE-- +withQuery(null); + +var_dump($uri1->getRawQuery()); +var_dump($uri2->getRawQuery()); +var_dump($uri2->toRawString()); +var_dump($uri2->getQuery()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +string(7) "foo=bar" +NULL +string(19) "https://example.com/" +NULL +string(19) "https://example.com/" diff --git a/ext/uri/tests/rfc3986/modification/query_success_unset_non_existent.phpt b/ext/uri/tests/rfc3986/modification/query_success_unset_non_existent.phpt new file mode 100644 index 0000000000000..d9dfcd2083100 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/query_success_unset_non_existent.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - query - unsetting not-existent +--EXTENSIONS-- +uri +--FILE-- +withQuery(null); + +var_dump($uri1->getRawQuery()); +var_dump($uri2->getRawQuery()); +var_dump($uri2->toRawString()); +var_dump($uri2->getQuery()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +NULL +NULL +string(19) "https://example.com/" +NULL +string(19) "https://example.com/" diff --git a/ext/uri/tests/rfc3986/modification/roundtrip_special_case1.phpt b/ext/uri/tests/rfc3986/modification/roundtrip_special_case1.phpt new file mode 100644 index 0000000000000..4349764d4dd1f --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/roundtrip_special_case1.phpt @@ -0,0 +1,24 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification when roundtripping is not guaranteed - case 1 +--EXTENSIONS-- +uri +--FILE-- +withHost("host"); +$uri2 = $uri2->withHost(null); + +var_dump($uri1->getRawPath()); +var_dump($uri2->getRawPath()); +var_dump($uri2->toRawString()); +var_dump($uri2->getPath()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +string(5) "path1" +string(6) "/path1" +string(6) "/path1" +string(6) "/path1" +string(6) "/path1" diff --git a/ext/uri/tests/rfc3986/modification/roundtrip_special_case2.phpt b/ext/uri/tests/rfc3986/modification/roundtrip_special_case2.phpt new file mode 100644 index 0000000000000..624abf2fc49ca --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/roundtrip_special_case2.phpt @@ -0,0 +1,20 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification when roundtripping is not guaranteed - case 2 +--EXTENSIONS-- +uri +--FILE-- +withScheme(null); +$uri2 = $uri2->withScheme("scheme"); + +var_dump($uri1->toRawString()); +var_dump($uri2->toRawString()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +string(13) "scheme:path1:" +string(15) "scheme:./path1:" +string(13) "scheme:path1:" diff --git a/ext/uri/tests/rfc3986/modification/roundtrip_special_case3.phpt b/ext/uri/tests/rfc3986/modification/roundtrip_special_case3.phpt new file mode 100644 index 0000000000000..7d6e1e4d0489b --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/roundtrip_special_case3.phpt @@ -0,0 +1,20 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification when roundtripping is not guaranteed - case 3 +--EXTENSIONS-- +uri +--FILE-- +withHost(null); +$uri2 = $uri2->withHost("host"); + +var_dump($uri1->toRawString()); +var_dump($uri2->toRawString()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +string(12) "//host//path" +string(14) "//host/.//path" +string(12) "//host//path" diff --git a/ext/uri/tests/rfc3986/modification/scheme_error_empty.phpt b/ext/uri/tests/rfc3986/modification/scheme_error_empty.phpt new file mode 100644 index 0000000000000..94888c446f690 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/scheme_error_empty.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - scheme - empty string +--EXTENSIONS-- +uri +--FILE-- +withScheme(""); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified scheme is malformed diff --git a/ext/uri/tests/rfc3986/modification/scheme_error_encoded.phpt b/ext/uri/tests/rfc3986/modification/scheme_error_encoded.phpt new file mode 100644 index 0000000000000..e44e8df85ed0d --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/scheme_error_encoded.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - scheme - URL encoded characters +--EXTENSIONS-- +uri +--FILE-- +withScheme("http%73"); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified scheme is malformed diff --git a/ext/uri/tests/rfc3986/modification/scheme_error_reserved.phpt b/ext/uri/tests/rfc3986/modification/scheme_error_reserved.phpt new file mode 100644 index 0000000000000..7d235e56d113e --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/scheme_error_reserved.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - scheme - reserved characters +--EXTENSIONS-- +uri +--FILE-- +withScheme("https:"); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified scheme is malformed diff --git a/ext/uri/tests/rfc3986/modification/scheme_success_basic.phpt b/ext/uri/tests/rfc3986/modification/scheme_success_basic.phpt new file mode 100644 index 0000000000000..695cb9c7f1e49 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/scheme_success_basic.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - scheme - basic case +--EXTENSIONS-- +uri +--FILE-- +withScheme("HTTP"); + +var_dump($uri1->getRawScheme()); +var_dump($uri2->getRawScheme()); +var_dump($uri2->toRawString()); +var_dump($uri2->getScheme()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +string(5) "https" +string(4) "HTTP" +string(18) "HTTP://example.com" +string(4) "http" +string(18) "http://example.com/" diff --git a/ext/uri/tests/rfc3986/modification/scheme_success_unset_existing.phpt b/ext/uri/tests/rfc3986/modification/scheme_success_unset_existing.phpt new file mode 100644 index 0000000000000..67d447e8810e4 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/scheme_success_unset_existing.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - scheme - unsetting existing +--EXTENSIONS-- +uri +--FILE-- +withScheme(null); + +var_dump($uri1->getRawScheme()); +var_dump($uri2->getRawScheme()); +var_dump($uri2->toRawString()); +var_dump($uri2->getScheme()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +string(5) "https" +NULL +string(13) "//example.com" +NULL +string(13) "//example.com" diff --git a/ext/uri/tests/rfc3986/modification/scheme_success_unset_non_existent.phpt b/ext/uri/tests/rfc3986/modification/scheme_success_unset_non_existent.phpt new file mode 100644 index 0000000000000..4aa9b2d9dd2c6 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/scheme_success_unset_non_existent.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - scheme - unsetting non-existent +--EXTENSIONS-- +uri +--FILE-- +withScheme(null); + +var_dump($uri1->getRawScheme()); +var_dump($uri2->getRawScheme()); +var_dump($uri2->toRawString()); +var_dump($uri2->getScheme()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +NULL +NULL +string(8) "/foo/bar" +NULL +string(8) "/foo/bar" diff --git a/ext/uri/tests/rfc3986/modification/userinfo_error_reserved.phpt b/ext/uri/tests/rfc3986/modification/userinfo_error_reserved.phpt new file mode 100644 index 0000000000000..c416ea43eb730 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/userinfo_error_reserved.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - userinfo - reserved characters +--EXTENSIONS-- +uri +--FILE-- +withUserInfo("us/r:password"); // us/r:password +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified userinfo is malformed diff --git a/ext/uri/tests/rfc3986/modification/userinfo_success_empty.phpt b/ext/uri/tests/rfc3986/modification/userinfo_success_empty.phpt new file mode 100644 index 0000000000000..ab753e6de507a --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/userinfo_success_empty.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - userinfo - empty string +--EXTENSIONS-- +uri +--FILE-- +withUserInfo(""); + +var_dump($uri1->getRawUserInfo()); +var_dump($uri2->getRawUserInfo()); +var_dump($uri2->getUserInfo()); + +?> +--EXPECT-- +NULL +string(0) "" +string(0) "" diff --git a/ext/uri/tests/rfc3986/modification/userinfo_success_encoded.phpt b/ext/uri/tests/rfc3986/modification/userinfo_success_encoded.phpt new file mode 100644 index 0000000000000..a4b7409d67063 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/userinfo_success_encoded.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - userinfo - URL encoded characters +--EXTENSIONS-- +uri +--FILE-- +withUserInfo("%75s%2Fr:password"); // us/r:password + +var_dump($uri1->getRawUserInfo()); +var_dump($uri2->getRawUserInfo()); +var_dump($uri2->toRawString()); +var_dump($uri2->getUserInfo()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +NULL +string(17) "%75s%2Fr:password" +string(37) "https://%75s%2Fr:password@example.com/" +string(15) "us%2Fr:password" +string(35) "https://us%2Fr:password@example.com/" diff --git a/ext/uri/tests/rfc3986/modification/userinfo_success_existing.phpt b/ext/uri/tests/rfc3986/modification/userinfo_success_existing.phpt new file mode 100644 index 0000000000000..a13e091075cb6 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/userinfo_success_existing.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - userinfo - changing an existing one +--EXTENSIONS-- +uri +--FILE-- +withUserInfo("user:password"); + +var_dump($uri1->getRawUserInfo()); +var_dump($uri2->getRawUserInfo()); +var_dump($uri2->toRawString()); +var_dump($uri2->getUserInfo()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +string(5) ":pass" +string(13) "user:password" +string(33) "https://user:password@example.com/" +string(13) "user:password" +string(33) "https://user:password@example.com/" diff --git a/ext/uri/tests/rfc3986/modification/userinfo_success_new.phpt b/ext/uri/tests/rfc3986/modification/userinfo_success_new.phpt new file mode 100644 index 0000000000000..dc49c10d7526a --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/userinfo_success_new.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - userinfo - adding a new one +--EXTENSIONS-- +uri +--FILE-- +withUserInfo("user:password"); + +var_dump($uri1->getRawUserInfo()); +var_dump($uri2->getRawUserInfo()); +var_dump($uri2->toRawString()); +var_dump($uri2->getUserInfo()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +NULL +string(13) "user:password" +string(33) "https://user:password@example.com/" +string(13) "user:password" +string(33) "https://user:password@example.com/" diff --git a/ext/uri/tests/rfc3986/modification/userinfo_success_unset_existing.phpt b/ext/uri/tests/rfc3986/modification/userinfo_success_unset_existing.phpt new file mode 100644 index 0000000000000..0f4e7219cbd35 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/userinfo_success_unset_existing.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - userinfo - unsetting existing +--EXTENSIONS-- +uri +--FILE-- +withUserInfo(null); + +var_dump($uri1->getRawUserInfo()); +var_dump($uri2->getRawUserInfo()); +var_dump($uri2->toRawString()); +var_dump($uri2->getUserInfo()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +string(13) "user:password" +NULL +string(19) "https://example.com/" +NULL +string(19) "https://example.com/" diff --git a/ext/uri/tests/rfc3986/modification/userinfo_success_unset_non_existent.phpt b/ext/uri/tests/rfc3986/modification/userinfo_success_unset_non_existent.phpt new file mode 100644 index 0000000000000..9aa2a5999ac43 --- /dev/null +++ b/ext/uri/tests/rfc3986/modification/userinfo_success_unset_non_existent.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\Rfc3986\Uri component modification - userinfo - unsetting non-existent +--EXTENSIONS-- +uri +--FILE-- +withUserInfo(null); + +var_dump($uri1->getRawUserInfo()); +var_dump($uri2->getRawUserInfo()); +var_dump($uri2->toRawString()); +var_dump($uri2->getUserInfo()); +var_dump($uri2->toString()); + +?> +--EXPECT-- +NULL +NULL +string(8) "/foo/bar" +NULL +string(8) "/foo/bar" diff --git a/ext/uri/tests/rfc3986/parsing/basic_error_multibyte.phpt b/ext/uri/tests/rfc3986/parsing/basic_error_multibyte.phpt new file mode 100644 index 0000000000000..cb6007c844aae --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/basic_error_multibyte.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - basic - multibyte character +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified URI is malformed diff --git a/ext/uri/tests/rfc3986/parsing/basic_error_null_byte.phpt b/ext/uri/tests/rfc3986/parsing/basic_error_null_byte.phpt new file mode 100644 index 0000000000000..91d194e2ff5e5 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/basic_error_null_byte.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - basic - URI contains null byte +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified URI is malformed diff --git a/ext/uri/tests/rfc3986/parsing/basic_success_all.phpt b/ext/uri/tests/rfc3986/parsing/basic_success_all.phpt new file mode 100644 index 0000000000000..06d5edeb1c568 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/basic_success_all.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - basic - all components +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + string(4) "user" + ["password"]=> + string(4) "info" + ["host"]=> + string(11) "example.com" + ["port"]=> + int(443) + ["path"]=> + string(8) "/foo/bar" + ["query"]=> + string(15) "abc=123&def=ghi" + ["fragment"]=> + string(8) "hashmark" +} +string(66) "https://user:info@example.com/foo/bar?abc=123&def=ghi#hashmark" +string(66) "https://user:info@example.com/foo/bar?abc=123&def=ghi#hashmark" diff --git a/ext/uri/tests/rfc3986/parsing/basic_sucess_email.phpt b/ext/uri/tests/rfc3986/parsing/basic_sucess_email.phpt new file mode 100644 index 0000000000000..9d0f01c9ac087 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/basic_sucess_email.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - basic - mailto email +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(6) "mailto" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + NULL + ["port"]=> + NULL + ["path"]=> + string(16) "user@example.com" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(23) "mailto:user@example.com" +string(23) "mailto:user@example.com" diff --git a/ext/uri/tests/rfc3986/parsing/basic_sucess_empty.phpt b/ext/uri/tests/rfc3986/parsing/basic_sucess_empty.phpt new file mode 100644 index 0000000000000..db72394c08212 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/basic_sucess_empty.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - basic - empty string +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + NULL + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + NULL + ["port"]=> + NULL + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(0) "" +string(0) "" diff --git a/ext/uri/tests/rfc3986/parsing/basic_sucess_file.phpt b/ext/uri/tests/rfc3986/parsing/basic_sucess_file.phpt new file mode 100644 index 0000000000000..420b1071dd63f --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/basic_sucess_file.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - basic - file +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(4) "file" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(0) "" + ["port"]=> + NULL + ["path"]=> + string(30) "/E:/Documents%20and%20Settings" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(37) "file:///E:/Documents%20and%20Settings" +string(37) "file:///E:/Documents%20and%20Settings" diff --git a/ext/uri/tests/rfc3986/parsing/basic_sucess_urn.phpt b/ext/uri/tests/rfc3986/parsing/basic_sucess_urn.phpt new file mode 100644 index 0000000000000..81fe978c9fc75 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/basic_sucess_urn.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - basic - URN +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(3) "urn" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + NULL + ["port"]=> + NULL + ["path"]=> + string(41) "uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(45) "urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66" +string(45) "urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66" diff --git a/ext/uri/tests/rfc3986/parsing/host_error_multibyte.phpt b/ext/uri/tests/rfc3986/parsing/host_error_multibyte.phpt new file mode 100644 index 0000000000000..d901d0fdecbdb --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/host_error_multibyte.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - host - multibyte character +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified URI is malformed diff --git a/ext/uri/tests/rfc3986/parsing/host_error_reserved.phpt b/ext/uri/tests/rfc3986/parsing/host_error_reserved.phpt new file mode 100644 index 0000000000000..0568a027f5b9a --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/host_error_reserved.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - host - reserved character +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified URI is malformed diff --git a/ext/uri/tests/rfc3986/parsing/host_success_empty1.phpt b/ext/uri/tests/rfc3986/parsing/host_success_empty1.phpt new file mode 100644 index 0000000000000..da1ea6f00afcc --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/host_success_empty1.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - host - empty +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(0) "" + ["port"]=> + NULL + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(8) "https://" +string(8) "https://" diff --git a/ext/uri/tests/rfc3986/parsing/host_success_empty2.phpt b/ext/uri/tests/rfc3986/parsing/host_success_empty2.phpt new file mode 100644 index 0000000000000..9f392631a44e7 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/host_success_empty2.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - host - empty +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + string(4) "user" + ["password"]=> + string(4) "pass" + ["host"]=> + string(0) "" + ["port"]=> + NULL + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(18) "https://user:pass@" +string(18) "https://user:pass@" diff --git a/ext/uri/tests/rfc3986/parsing/host_success_empty3.phpt b/ext/uri/tests/rfc3986/parsing/host_success_empty3.phpt new file mode 100644 index 0000000000000..eb399678eaa39 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/host_success_empty3.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - host - empty +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + NULL + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(0) "" + ["port"]=> + NULL + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(2) "//" +string(2) "//" diff --git a/ext/uri/tests/rfc3986/parsing/host_success_empty4.phpt b/ext/uri/tests/rfc3986/parsing/host_success_empty4.phpt new file mode 100644 index 0000000000000..ed470e00575f4 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/host_success_empty4.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - host - empty +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + NULL + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(0) "" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(3) "///" +string(3) "///" diff --git a/ext/uri/tests/rfc3986/parsing/host_success_ipv4.phpt b/ext/uri/tests/rfc3986/parsing/host_success_ipv4.phpt new file mode 100644 index 0000000000000..206864317074a --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/host_success_ipv4.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - host - IPv4 +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "192.168.0.1" + ["port"]=> + NULL + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(19) "https://192.168.0.1/" +string(19) "https://192.168.0.1/" diff --git a/ext/uri/tests/rfc3986/parsing/host_success_ipv4_wrong.phpt b/ext/uri/tests/rfc3986/parsing/host_success_ipv4_wrong.phpt new file mode 100644 index 0000000000000..84664187c555c --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/host_success_ipv4_wrong.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - host - wrong IPv4 format +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(7) "192.168" + ["port"]=> + NULL + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(15) "https://192.0.0.168/" +string(15) "https://192.0.0.168/" diff --git a/ext/uri/tests/rfc3986/parsing/host_success_ipv6.phpt b/ext/uri/tests/rfc3986/parsing/host_success_ipv6.phpt new file mode 100644 index 0000000000000..2292fb1573681 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/host_success_ipv6.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - host - IPv6 +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(41) "[2001:0db8:3333:4444:5555:6666:7777:8888]" + ["port"]=> + NULL + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(49) "https://[2001:db8:3333:4444:5555:6666:7777:8888]/" +string(49) "https://[2001:db8:3333:4444:5555:6666:7777:8888]/" diff --git a/ext/uri/tests/rfc3986/parsing/host_success_ipvfuture.phpt b/ext/uri/tests/rfc3986/parsing/host_success_ipvfuture.phpt new file mode 100644 index 0000000000000..7b64137248939 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/host_success_ipvfuture.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - host - IPvFuture +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(9) "[v7.host]" + ["port"]=> + NULL + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(17) "https://[v7.host]" +string(17) "https://[v7.host]" diff --git a/ext/uri/tests/rfc3986/parsing/path_error_multibyte.phpt b/ext/uri/tests/rfc3986/parsing/path_error_multibyte.phpt new file mode 100644 index 0000000000000..ded528d03082c --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/path_error_multibyte.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - path - multibyte character +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified URI is malformed diff --git a/ext/uri/tests/rfc3986/parsing/path_error_reserved.phpt b/ext/uri/tests/rfc3986/parsing/path_error_reserved.phpt new file mode 100644 index 0000000000000..2a7efd7025693 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/path_error_reserved.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - path - reserved character +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified URI is malformed diff --git a/ext/uri/tests/rfc3986/parsing/path_success_relative_reference.phpt b/ext/uri/tests/rfc3986/parsing/path_success_relative_reference.phpt new file mode 100644 index 0000000000000..13a9169da3bbb --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/path_success_relative_reference.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - path - relative reference +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + NULL + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + NULL + ["port"]=> + NULL + ["path"]=> + string(3) "foo" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(3) "foo" +string(3) "foo" diff --git a/ext/uri/tests/rfc3986/parsing/path_success_relative_reference_absolute.phpt b/ext/uri/tests/rfc3986/parsing/path_success_relative_reference_absolute.phpt new file mode 100644 index 0000000000000..4096e00dc32da --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/path_success_relative_reference_absolute.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - path - relative reference +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + NULL + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + NULL + ["port"]=> + NULL + ["path"]=> + string(4) "/foo" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(4) "/foo" +string(4) "/foo" diff --git a/ext/uri/tests/rfc3986/parsing/path_success_relative_reference_only_query_fragment.phpt b/ext/uri/tests/rfc3986/parsing/path_success_relative_reference_only_query_fragment.phpt new file mode 100644 index 0000000000000..5e7ec7b68f756 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/path_success_relative_reference_only_query_fragment.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - path - relative reference +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + NULL + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + NULL + ["port"]=> + NULL + ["path"]=> + string(0) "" + ["query"]=> + string(5) "query" + ["fragment"]=> + string(8) "fragment" +} +string(15) "?query#fragment" +string(15) "?query#fragment" diff --git a/ext/uri/tests/rfc3986/parsing/path_success_slash_only.phpt b/ext/uri/tests/rfc3986/parsing/path_success_slash_only.phpt new file mode 100644 index 0000000000000..e743869570e5e --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/path_success_slash_only.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - path - slash only +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(20) "https://example.com/" +string(20) "https://example.com/" diff --git a/ext/uri/tests/rfc3986/parsing/port_error_multibyte.phpt b/ext/uri/tests/rfc3986/parsing/port_error_multibyte.phpt new file mode 100644 index 0000000000000..54bcd849e5f39 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/port_error_multibyte.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - port - multibyte character +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified URI is malformed diff --git a/ext/uri/tests/rfc3986/parsing/port_error_negative.phpt b/ext/uri/tests/rfc3986/parsing/port_error_negative.phpt new file mode 100644 index 0000000000000..df29c2767f05d --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/port_error_negative.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - port - negative value +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified URI is malformed diff --git a/ext/uri/tests/rfc3986/parsing/port_error_percent_encoded.phpt b/ext/uri/tests/rfc3986/parsing/port_error_percent_encoded.phpt new file mode 100644 index 0000000000000..e38ad85b57589 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/port_error_percent_encoded.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - port - percent encoded character +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified URI is malformed diff --git a/ext/uri/tests/rfc3986/parsing/port_error_user_info_wrong_place.phpt b/ext/uri/tests/rfc3986/parsing/port_error_user_info_wrong_place.phpt new file mode 100644 index 0000000000000..d2632a6f28063 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/port_error_user_info_wrong_place.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - port - user info component is in wrong place +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified URI is malformed diff --git a/ext/uri/tests/rfc3986/parsing/port_success_empty.phpt b/ext/uri/tests/rfc3986/parsing/port_success_empty.phpt new file mode 100644 index 0000000000000..d007625ae8b85 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/port_success_empty.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - port - empty +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(4) "http" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(19) "http://example.com/" +string(19) "http://example.com/" diff --git a/ext/uri/tests/rfc3986/parsing/port_success_zero.phpt b/ext/uri/tests/rfc3986/parsing/port_success_zero.phpt new file mode 100644 index 0000000000000..5d115a255c9f3 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/port_success_zero.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - port - zero +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(4) "http" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + int(0) + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(20) "http://example.com:0/" +string(20) "http://example.com:0/" diff --git a/ext/uri/tests/rfc3986/parsing/scheme_error_empty.phpt b/ext/uri/tests/rfc3986/parsing/scheme_error_empty.phpt new file mode 100644 index 0000000000000..ba686e7fafcae --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/scheme_error_empty.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - scheme - empty +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified URI is malformed diff --git a/ext/uri/tests/rfc3986/parsing/scheme_error_multibyte.phpt b/ext/uri/tests/rfc3986/parsing/scheme_error_multibyte.phpt new file mode 100644 index 0000000000000..f638ca80e0cd7 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/scheme_error_multibyte.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - scheme - multibyte characters +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified URI is malformed diff --git a/ext/uri/tests/rfc3986/parsing/scheme_error_percent_encoded.phpt b/ext/uri/tests/rfc3986/parsing/scheme_error_percent_encoded.phpt new file mode 100644 index 0000000000000..d4dba6f260ade --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/scheme_error_percent_encoded.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - scheme - percent encoded character +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified URI is malformed diff --git a/ext/uri/tests/rfc3986/parsing/scheme_error_reserved.phpt b/ext/uri/tests/rfc3986/parsing/scheme_error_reserved.phpt new file mode 100644 index 0000000000000..99dfb664ea054 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/scheme_error_reserved.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - scheme - reserved character +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified URI is malformed diff --git a/ext/uri/tests/rfc3986/parsing/scheme_success_empty_host.phpt b/ext/uri/tests/rfc3986/parsing/scheme_success_empty_host.phpt new file mode 100644 index 0000000000000..c0110735db8d0 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/scheme_success_empty_host.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - scheme - empty host +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + NULL + ["port"]=> + NULL + ["path"]=> + string(11) "example.com" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(17) "https:example.com" +string(17) "https:example.com" diff --git a/ext/uri/tests/rfc3986/parsing/scheme_success_iana.phpt b/ext/uri/tests/rfc3986/parsing/scheme_success_iana.phpt new file mode 100644 index 0000000000000..e054e258b63b5 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/scheme_success_iana.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - scheme - IANA scheme +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--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 +} +string(30) "chrome-extension://example.com" +string(30) "chrome-extension://example.com" diff --git a/ext/uri/tests/rfc3986/parsing/scheme_success_only.phpt b/ext/uri/tests/rfc3986/parsing/scheme_success_only.phpt new file mode 100644 index 0000000000000..a898c8012725d --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/scheme_success_only.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - scheme - only scheme +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(4) "http" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + NULL + ["port"]=> + NULL + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(5) "http:" +string(5) "http:" diff --git a/ext/uri/tests/rfc3986/parsing/scheme_success_only2.phpt b/ext/uri/tests/rfc3986/parsing/scheme_success_only2.phpt new file mode 100644 index 0000000000000..65c52faafcf66 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/scheme_success_only2.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - scheme - only scheme +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(4) "http" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + NULL + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(6) "http:/" +string(6) "http:/" diff --git a/ext/uri/tests/rfc3986/parsing/userinfo_error_extended_ascii.phpt b/ext/uri/tests/rfc3986/parsing/userinfo_error_extended_ascii.phpt new file mode 100644 index 0000000000000..61ea8ecc3c282 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/userinfo_error_extended_ascii.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - userinfo - extended ASCII character +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified URI is malformed diff --git a/ext/uri/tests/rfc3986/parsing/userinfo_error_multibyte.phpt b/ext/uri/tests/rfc3986/parsing/userinfo_error_multibyte.phpt new file mode 100644 index 0000000000000..fbceea77b1cd5 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/userinfo_error_multibyte.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - userinfo - multibyte character +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified URI is malformed diff --git a/ext/uri/tests/rfc3986/parsing/userinfo_error_reserved.phpt b/ext/uri/tests/rfc3986/parsing/userinfo_error_reserved.phpt new file mode 100644 index 0000000000000..3b6caeb7a0edf --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/userinfo_error_reserved.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - userinfo - reserved character +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified URI is malformed diff --git a/ext/uri/tests/rfc3986/parsing/userinfo_success_empty.phpt b/ext/uri/tests/rfc3986/parsing/userinfo_success_empty.phpt new file mode 100644 index 0000000000000..8b7df6c55ca00 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/userinfo_success_empty.phpt @@ -0,0 +1,35 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - userinfo - empty +--EXTENSIONS-- +uri +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + string(0) "" + ["password"]=> + string(0) "" + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(20) "https://example.com/" +string(20) "https://example.com/" diff --git a/ext/uri/tests/rfc3986/parsing/userinfo_success_only_password.phpt b/ext/uri/tests/rfc3986/parsing/userinfo_success_only_password.phpt new file mode 100644 index 0000000000000..eb5053c10490d --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/userinfo_success_only_password.phpt @@ -0,0 +1,35 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - userinfo - only password +--EXTENSIONS-- +uri +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + string(0) "" + ["password"]=> + string(4) "pass" + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(25) "https://:pass@example.com/" +string(25) "https://:pass@example.com/" diff --git a/ext/uri/tests/rfc3986/parsing/userinfo_success_only_username.phpt b/ext/uri/tests/rfc3986/parsing/userinfo_success_only_username.phpt new file mode 100644 index 0000000000000..1081a0e048580 --- /dev/null +++ b/ext/uri/tests/rfc3986/parsing/userinfo_success_only_username.phpt @@ -0,0 +1,35 @@ +--TEST-- +Test Uri\Rfc3986\Uri parsing - userinfo - only username +--EXTENSIONS-- +uri +--FILE-- +toRawString()); +var_dump($uri->toString()); + +?> +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + string(4) "user" + ["password"]=> + string(0) "" + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(25) "https://user@example.com/" +string(25) "https://user@example.com/" diff --git a/ext/uri/tests/rfc3986/reference_resolution/resolve_error_null_byte.phpt b/ext/uri/tests/rfc3986/reference_resolution/resolve_error_null_byte.phpt new file mode 100644 index 0000000000000..16b2f61dce78b --- /dev/null +++ b/ext/uri/tests/rfc3986/reference_resolution/resolve_error_null_byte.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\Rfc3986\Uri reference resolution - resolve() - null byte +--EXTENSIONS-- +uri +--FILE-- +resolve("/f\0o"); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\InvalidUriException: The specified URI is malformed diff --git a/ext/uri/tests/whatwg/modification/fragment_success_auto_encode.phpt b/ext/uri/tests/whatwg/modification/fragment_success_auto_encode.phpt new file mode 100644 index 0000000000000..ac74b8668cd23 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/fragment_success_auto_encode.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - fragment - characters from the percent encode set +--EXTENSIONS-- +uri +--FILE-- +withFragment("<>"); + +var_dump($url1->getFragment()); +var_dump($url2->getFragment()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +string(6) "%3C%3E" +string(27) "https://example.com/#%3C%3E" diff --git a/ext/uri/tests/whatwg/modification/fragment_success_empty.phpt b/ext/uri/tests/whatwg/modification/fragment_success_empty.phpt new file mode 100644 index 0000000000000..5b3aa9426232c --- /dev/null +++ b/ext/uri/tests/whatwg/modification/fragment_success_empty.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - fragment - empty string +--EXTENSIONS-- +uri +--FILE-- +withFragment(""); + +var_dump($url1->getFragment()); +var_dump($url2->getFragment()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +NULL +string(20) "https://example.com/" diff --git a/ext/uri/tests/whatwg/modification/fragment_success_encoded.phpt b/ext/uri/tests/whatwg/modification/fragment_success_encoded.phpt new file mode 100644 index 0000000000000..9473ea9535f96 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/fragment_success_encoded.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - fragment - URL encoded characters +--EXTENSIONS-- +uri +--FILE-- +withFragment("foo%3db%61r"); // foo=bar + +var_dump($url1->getFragment()); +var_dump($url2->getFragment()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +string(11) "foo%3db%61r" +string(32) "https://example.com/#foo%3db%61r" diff --git a/ext/uri/tests/whatwg/modification/fragment_success_existing.phpt b/ext/uri/tests/whatwg/modification/fragment_success_existing.phpt new file mode 100644 index 0000000000000..0a7d253434d41 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/fragment_success_existing.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - fragment - changing an existing one +--EXTENSIONS-- +uri +--FILE-- +withFragment("bar"); + +var_dump($url1->getFragment()); +var_dump($url2->getFragment()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(3) "foo" +string(3) "bar" +string(24) "https://example.com/#bar" diff --git a/ext/uri/tests/whatwg/modification/fragment_success_hashmark.phpt b/ext/uri/tests/whatwg/modification/fragment_success_hashmark.phpt new file mode 100644 index 0000000000000..4639d993df04d --- /dev/null +++ b/ext/uri/tests/whatwg/modification/fragment_success_hashmark.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - fragment - only a hashmark character +--EXTENSIONS-- +uri +--FILE-- +withFragment("#"); + +var_dump($url1->getFragment()); +var_dump($url2->getFragment()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +string(0) "" +string(21) "https://example.com/#" diff --git a/ext/uri/tests/whatwg/modification/fragment_success_null_byte.phpt b/ext/uri/tests/whatwg/modification/fragment_success_null_byte.phpt new file mode 100644 index 0000000000000..faaf41796c746 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/fragment_success_null_byte.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - fragment - null byte +--EXTENSIONS-- +uri +--FILE-- +withFragment("frag\0ment"); + +var_dump($url1->getFragment()); +var_dump($url2->getFragment()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +string(11) "frag%00ment" +string(32) "https://example.com/#frag%00ment" diff --git a/ext/uri/tests/whatwg/modification/fragment_success_unicode.phpt b/ext/uri/tests/whatwg/modification/fragment_success_unicode.phpt new file mode 100644 index 0000000000000..c609b5df042de --- /dev/null +++ b/ext/uri/tests/whatwg/modification/fragment_success_unicode.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - fragment - unicode characters +--EXTENSIONS-- +uri +--FILE-- +withFragment("ő"); + +var_dump($url1->getFragment()); +var_dump($url2->getFragment()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +string(6) "%C5%91" +string(27) "https://example.com/#%C5%91" diff --git a/ext/uri/tests/whatwg/modification/fragment_success_unset_existing.phpt b/ext/uri/tests/whatwg/modification/fragment_success_unset_existing.phpt new file mode 100644 index 0000000000000..585707e497e5c --- /dev/null +++ b/ext/uri/tests/whatwg/modification/fragment_success_unset_existing.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - fragment - unsetting existing +--EXTENSIONS-- +uri +--FILE-- +withFragment(null); + +var_dump($url1->getFragment()); +var_dump($url2->getFragment()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(3) "foo" +NULL +string(20) "https://example.com/" diff --git a/ext/uri/tests/whatwg/modification/fragment_success_unset_non_existent.phpt b/ext/uri/tests/whatwg/modification/fragment_success_unset_non_existent.phpt new file mode 100644 index 0000000000000..21e295db23ec2 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/fragment_success_unset_non_existent.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - fragment - unsetting not-existent +--EXTENSIONS-- +uri +--FILE-- +withFragment(null); + +var_dump($url1->getFragment()); +var_dump($url2->getFragment()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +NULL +string(20) "https://example.com/" diff --git a/ext/uri/tests/whatwg/modification/fragment_success_with_leading_hashmark.phpt b/ext/uri/tests/whatwg/modification/fragment_success_with_leading_hashmark.phpt new file mode 100644 index 0000000000000..4523388223b68 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/fragment_success_with_leading_hashmark.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - fragment - with leading hashmark +--EXTENSIONS-- +uri +--FILE-- +withFragment("#fragment"); + +var_dump($url1->getFragment()); +var_dump($url2->getFragment()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +string(8) "fragment" +string(29) "https://example.com/#fragment" diff --git a/ext/uri/tests/whatwg/modification/host_error_empty.phpt b/ext/uri/tests/whatwg/modification/host_error_empty.phpt new file mode 100644 index 0000000000000..7ce0fa9dff2b0 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/host_error_empty.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - host - empty string +--EXTENSIONS-- +uri +--FILE-- +withHost(""); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified host is malformed (HostMissing) diff --git a/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_opaque1.phpt b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_opaque1.phpt new file mode 100644 index 0000000000000..a6ef7e6a5d5d4 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_opaque1.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - host - forbidden host code point +--EXTENSIONS-- +uri +--FILE-- +withHost("ex@mple.com"); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified host is malformed (HostInvalidCodePoint) diff --git a/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_opaque2.phpt b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_opaque2.phpt new file mode 100644 index 0000000000000..6d8b0c8b6565e --- /dev/null +++ b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_opaque2.phpt @@ -0,0 +1,17 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - host - forbidden host code point +--EXTENSIONS-- +uri +--FILE-- +withHost("ex#mple.com"); + +var_dump($url1->getAsciiHost()); +var_dump($url2->getAsciiHost()); + +?> +--EXPECT-- +string(11) "example.com" +string(2) "ex" diff --git a/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_opaque3.phpt b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_opaque3.phpt new file mode 100644 index 0000000000000..7d32dcba2c6cf --- /dev/null +++ b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_opaque3.phpt @@ -0,0 +1,17 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - host - forbidden host codepoint +--EXTENSIONS-- +uri +--FILE-- +withHost("ex#mple.com"); + +var_dump($url1->getAsciiHost()); +var_dump($url2->getAsciiHost()); + +?> +--EXPECT-- +string(11) "example.com" +string(2) "ex" diff --git a/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_special1.phpt b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_special1.phpt new file mode 100644 index 0000000000000..d06234d949b85 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_special1.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - host - forbidden domain code point +--EXTENSIONS-- +uri +--FILE-- +withHost("ex@mple.com"); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified host is malformed (DomainInvalidCodePoint) diff --git a/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_special2.phpt b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_special2.phpt new file mode 100644 index 0000000000000..4413802fdb9ef --- /dev/null +++ b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_special2.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - host - forbidden domain code point +--EXTENSIONS-- +uri +--FILE-- +withHost("ex:mple.com"); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified host is malformed diff --git a/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_special3.phpt b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_special3.phpt new file mode 100644 index 0000000000000..4413802fdb9ef --- /dev/null +++ b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_special3.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - host - forbidden domain code point +--EXTENSIONS-- +uri +--FILE-- +withHost("ex:mple.com"); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified host is malformed diff --git a/ext/uri/tests/whatwg/modification/host_error_null_byte.phpt b/ext/uri/tests/whatwg/modification/host_error_null_byte.phpt new file mode 100644 index 0000000000000..84a6bc1ebdbc6 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/host_error_null_byte.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - host - null byte +--EXTENSIONS-- +uri +--FILE-- +withHost("h\0st"); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified host is malformed (DomainInvalidCodePoint) diff --git a/ext/uri/tests/whatwg/modification/host_error_unset_existing.phpt b/ext/uri/tests/whatwg/modification/host_error_unset_existing.phpt new file mode 100644 index 0000000000000..627fe8d3e5887 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/host_error_unset_existing.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - host - unsetting existing +--EXTENSIONS-- +uri +--FILE-- +withHost(null); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified host is malformed (HostMissing) diff --git a/ext/uri/tests/whatwg/modification/host_success_encoded.phpt b/ext/uri/tests/whatwg/modification/host_success_encoded.phpt new file mode 100644 index 0000000000000..9604476554fc8 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/host_success_encoded.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - host - URL encoded characters +--EXTENSIONS-- +uri +--FILE-- +withHost("%65xample.net"); // example.net + +var_dump($url1->getAsciiHost()); +var_dump($url2->getAsciiHost()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(11) "example.com" +string(11) "example.net" +string(20) "https://example.net/" diff --git a/ext/uri/tests/whatwg/modification/host_success_existing.phpt b/ext/uri/tests/whatwg/modification/host_success_existing.phpt new file mode 100644 index 0000000000000..57394c851c775 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/host_success_existing.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - host - changing an existing one +--EXTENSIONS-- +uri +--FILE-- +withHost("example.net"); + +var_dump($url1->getAsciiHost()); +var_dump($url2->getAsciiHost()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(11) "example.com" +string(11) "example.net" +string(20) "https://example.net/" diff --git a/ext/uri/tests/whatwg/modification/host_success_idna.phpt b/ext/uri/tests/whatwg/modification/host_success_idna.phpt new file mode 100644 index 0000000000000..919e22934dfa2 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/host_success_idna.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - host - IDNA characters +--EXTENSIONS-- +uri +--FILE-- +withHost("éxämple.com"); + +var_dump($url1->getAsciiHost()); +var_dump($url2->getAsciiHost()); +var_dump($url2->toAsciiString()); +var_dump($url2->getUnicodeHost()); +var_dump($url2->toUnicodeString()); + +?> +--EXPECT-- +string(11) "example.com" +string(19) "xn--xmple-gra7a.com" +string(28) "https://xn--xmple-gra7a.com/" +string(13) "éxämple.com" +string(22) "https://xn--xmple-gra7a.com/" diff --git a/ext/uri/tests/whatwg/modification/host_success_ipv4.phpt b/ext/uri/tests/whatwg/modification/host_success_ipv4.phpt new file mode 100644 index 0000000000000..fef9e0fc63761 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/host_success_ipv4.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - host - IPv4 address +--EXTENSIONS-- +uri +--FILE-- +withHost("192.168.0.1"); + +var_dump($url1->getAsciiHost()); +var_dump($url2->getAsciiHost()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(11) "example.com" +string(11) "192.168.0.1" +string(20) "https://192.168.0.1/" diff --git a/ext/uri/tests/whatwg/modification/host_success_ipv6.phpt b/ext/uri/tests/whatwg/modification/host_success_ipv6.phpt new file mode 100644 index 0000000000000..2124b70ef56d7 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/host_success_ipv6.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - host - IPv6 address +--EXTENSIONS-- +uri +--FILE-- +withHost("[2001:0db8:3333:4444:5555:6666:7777:8888]"); + +var_dump($url1->getAsciiHost()); +var_dump($url2->getAsciiHost()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(11) "example.com" +string(40) "[2001:db8:3333:4444:5555:6666:7777:8888]" +string(49) "https://[2001:db8:3333:4444:5555:6666:7777:8888]/" diff --git a/ext/uri/tests/whatwg/modification/password_success_auto_encoded.phpt b/ext/uri/tests/whatwg/modification/password_success_auto_encoded.phpt new file mode 100644 index 0000000000000..5db68cb90a622 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/password_success_auto_encoded.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - password - characters from the percent encode set +--EXTENSIONS-- +uri +--FILE-- +withPassword("p:s/"); + +var_dump($url1->getPassword()); +var_dump($url2->getPassword()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(8) "password" +string(8) "p%3As%2F" +string(34) "https://user:p%3As%2F@example.com/" diff --git a/ext/uri/tests/whatwg/modification/password_success_empty.phpt b/ext/uri/tests/whatwg/modification/password_success_empty.phpt new file mode 100644 index 0000000000000..40c350cc1b30e --- /dev/null +++ b/ext/uri/tests/whatwg/modification/password_success_empty.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - password - empty string +--EXTENSIONS-- +uri +--FILE-- +withPassword(""); + +var_dump($url1->getPassword()); +var_dump($url2->getPassword()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +NULL +string(20) "https://example.com/" diff --git a/ext/uri/tests/whatwg/modification/password_success_encoded.phpt b/ext/uri/tests/whatwg/modification/password_success_encoded.phpt new file mode 100644 index 0000000000000..82b172d914af1 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/password_success_encoded.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - password - URL encoded characters +--EXTENSIONS-- +uri +--FILE-- +withPassword("p%61ssword"); + +var_dump($url1->getPassword()); +var_dump($url2->getPassword()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +string(10) "p%61ssword" +string(32) "https://:p%61ssword@example.com/" diff --git a/ext/uri/tests/whatwg/modification/password_success_existing.phpt b/ext/uri/tests/whatwg/modification/password_success_existing.phpt new file mode 100644 index 0000000000000..61b0ce3909b4d --- /dev/null +++ b/ext/uri/tests/whatwg/modification/password_success_existing.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - password - changing an existing one +--EXTENSIONS-- +uri +--FILE-- +withPassword("password"); + +var_dump($url1->getPassword()); +var_dump($url2->getPassword()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(4) "pass" +string(8) "password" +string(30) "https://:password@example.com/" diff --git a/ext/uri/tests/whatwg/modification/password_success_new.phpt b/ext/uri/tests/whatwg/modification/password_success_new.phpt new file mode 100644 index 0000000000000..8357b9972109d --- /dev/null +++ b/ext/uri/tests/whatwg/modification/password_success_new.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - username - adding a new one +--EXTENSIONS-- +uri +--FILE-- +withPassword("password"); + +var_dump($url1->getPassword()); +var_dump($url2->getPassword()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +string(8) "password" +string(30) "https://:password@example.com/" diff --git a/ext/uri/tests/whatwg/modification/password_success_null_byte.phpt b/ext/uri/tests/whatwg/modification/password_success_null_byte.phpt new file mode 100644 index 0000000000000..2216fa4e8e845 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/password_success_null_byte.phpt @@ -0,0 +1,20 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - password - null byte +--EXTENSIONS-- +uri +--FILE-- +withPassword("pass\0word"); + +var_dump($url1->getPassword()); +var_dump($url2->getPassword()); +var_dump($url2->toAsciiString()); + + +?> +--EXPECT-- +NULL +string(11) "pass%00word" +string(33) "https://:pass%00word@example.com/" diff --git a/ext/uri/tests/whatwg/modification/password_success_unset_existing.phpt b/ext/uri/tests/whatwg/modification/password_success_unset_existing.phpt new file mode 100644 index 0000000000000..203b831411a66 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/password_success_unset_existing.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - password - unsetting existing +--EXTENSIONS-- +uri +--FILE-- +withPassword(null); + +var_dump($url1->getPassword()); +var_dump($url2->getPassword()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(8) "password" +string(0) "" +string(29) "https://username@example.com/" diff --git a/ext/uri/tests/whatwg/modification/password_success_unset_existing2.phpt b/ext/uri/tests/whatwg/modification/password_success_unset_existing2.phpt new file mode 100644 index 0000000000000..06bade29468fd --- /dev/null +++ b/ext/uri/tests/whatwg/modification/password_success_unset_existing2.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - password - unsetting existing +--EXTENSIONS-- +uri +--FILE-- +withPassword(null); + +var_dump($url1->getPassword()); +var_dump($url2->getPassword()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(8) "password" +NULL +string(20) "https://example.com/" diff --git a/ext/uri/tests/whatwg/modification/password_success_unset_non_existent1.phpt b/ext/uri/tests/whatwg/modification/password_success_unset_non_existent1.phpt new file mode 100644 index 0000000000000..357b33b78c0ba --- /dev/null +++ b/ext/uri/tests/whatwg/modification/password_success_unset_non_existent1.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - password - unsetting non-existent +--EXTENSIONS-- +uri +--FILE-- +withPassword(null); + +var_dump($url1->getPassword()); +var_dump($url2->getPassword()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +NULL +string(20) "https://example.com/" diff --git a/ext/uri/tests/whatwg/modification/password_success_unset_non_existent2.phpt b/ext/uri/tests/whatwg/modification/password_success_unset_non_existent2.phpt new file mode 100644 index 0000000000000..a795f3197a6dc --- /dev/null +++ b/ext/uri/tests/whatwg/modification/password_success_unset_non_existent2.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - username - unsetting non-existent +--EXTENSIONS-- +uri +--FILE-- +withPassword(null); + +var_dump($url1->getPassword()); +var_dump($url2->getPassword()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(0) "" +string(0) "" +string(29) "https://username@example.com/" diff --git a/ext/uri/tests/whatwg/modification/path_success_auto_encoded.phpt b/ext/uri/tests/whatwg/modification/path_success_auto_encoded.phpt new file mode 100644 index 0000000000000..59f539124c68b --- /dev/null +++ b/ext/uri/tests/whatwg/modification/path_success_auto_encoded.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - path - characters from the percent encode set +--EXTENSIONS-- +uri +--FILE-- +withPath("/p^th#"); + +var_dump($url1->getPath()); +var_dump($url2->getPath()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(1) "/" +string(8) "/p^th%23" +string(27) "https://example.com/p%5Eth%23" diff --git a/ext/uri/tests/whatwg/modification/path_success_empty.phpt b/ext/uri/tests/whatwg/modification/path_success_empty.phpt new file mode 100644 index 0000000000000..9e8d3495445a4 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/path_success_empty.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - path - empty string +--EXTENSIONS-- +uri +--FILE-- +withPath(""); + +var_dump($url1->getPath()); +var_dump($url2->getPath()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(1) "/" +string(1) "/" +string(20) "https://example.com/" diff --git a/ext/uri/tests/whatwg/modification/path_success_encoded.phpt b/ext/uri/tests/whatwg/modification/path_success_encoded.phpt new file mode 100644 index 0000000000000..b698c4691b0ca --- /dev/null +++ b/ext/uri/tests/whatwg/modification/path_success_encoded.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - path - URL encoded characters +--EXTENSIONS-- +uri +--FILE-- +withPath("/foo%2Fb%61r"); // /foo/bar + +var_dump($url1->getPath()); +var_dump($url2->getPath()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(1) "/" +string(12) "/foo%2Fb%61r" +string(31) "https://example.com/foo%2Fb%61r" diff --git a/ext/uri/tests/whatwg/modification/path_success_existing.phpt b/ext/uri/tests/whatwg/modification/path_success_existing.phpt new file mode 100644 index 0000000000000..113c8c88d48bd --- /dev/null +++ b/ext/uri/tests/whatwg/modification/path_success_existing.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - path - changing an existing one +--EXTENSIONS-- +uri +--FILE-- +withPath("/baz"); + +var_dump($url1->getPath()); +var_dump($url2->getPath()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(8) "/foo/bar" +string(4) "/baz" +string(23) "https://example.com/baz" diff --git a/ext/uri/tests/whatwg/modification/path_success_null_byte.phpt b/ext/uri/tests/whatwg/modification/path_success_null_byte.phpt new file mode 100644 index 0000000000000..c09a3aa2810f4 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/path_success_null_byte.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - path - null byte +--EXTENSIONS-- +uri +--FILE-- +withPath("/p\0th\0"); + +var_dump($url1->getPath()); +var_dump($url2->getPath()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(1) "/" +string(10) "/p%00th%00" +string(29) "https://example.com/p%00th%00" diff --git a/ext/uri/tests/whatwg/modification/path_success_unicode.phpt b/ext/uri/tests/whatwg/modification/path_success_unicode.phpt new file mode 100644 index 0000000000000..d195a6dadbc18 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/path_success_unicode.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - path - unicode characters +--EXTENSIONS-- +uri +--FILE-- +withPath("/ő"); + +var_dump($url1->getPath()); +var_dump($url2->getPath()); +var_dump($url2->toAsciiString()); +?> +--EXPECT-- +string(1) "/" +string(7) "/%C5%91" +string(26) "https://example.com/%C5%91" diff --git a/ext/uri/tests/whatwg/modification/path_success_without_leading_slash.phpt b/ext/uri/tests/whatwg/modification/path_success_without_leading_slash.phpt new file mode 100644 index 0000000000000..1149287dc5319 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/path_success_without_leading_slash.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - path - without leading slash +--EXTENSIONS-- +uri +--FILE-- +withPath("foo/bar"); + +var_dump($url1->getPath()); +var_dump($url2->getPath()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(1) "/" +string(8) "/foo/bar" +string(27) "https://example.com/foo/bar" diff --git a/ext/uri/tests/whatwg/modification/port_error_negative.phpt b/ext/uri/tests/whatwg/modification/port_error_negative.phpt new file mode 100644 index 0000000000000..27e29995ce35b --- /dev/null +++ b/ext/uri/tests/whatwg/modification/port_error_negative.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - port - negative number +--EXTENSIONS-- +uri +--FILE-- +withPort(-1); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified port is malformed diff --git a/ext/uri/tests/whatwg/modification/port_error_too_large.phpt b/ext/uri/tests/whatwg/modification/port_error_too_large.phpt new file mode 100644 index 0000000000000..f530b36721639 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/port_error_too_large.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - host - larger than a 16-bit unsigned integer +--EXTENSIONS-- +uri +--FILE-- +withPort(65536); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified port is malformed (PortOutOfRange) diff --git a/ext/uri/tests/whatwg/modification/port_success_existing.phpt b/ext/uri/tests/whatwg/modification/port_success_existing.phpt new file mode 100644 index 0000000000000..e5ea806bd1a40 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/port_success_existing.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - port - changing an existing one +--EXTENSIONS-- +uri +--FILE-- +withPort(443); + +var_dump($url1->getPort()); +var_dump($url2->getPort()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +int(80) +int(443) +string(24) "scheme://example.com:443" diff --git a/ext/uri/tests/whatwg/modification/port_success_new.phpt b/ext/uri/tests/whatwg/modification/port_success_new.phpt new file mode 100644 index 0000000000000..85098b21b7b32 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/port_success_new.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - port - adding a new one +--EXTENSIONS-- +uri +--FILE-- +withPort(443); + +var_dump($url1->getPort()); +var_dump($url2->getPort()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +int(443) +string(24) "scheme://example.com:443" diff --git a/ext/uri/tests/whatwg/modification/port_success_special1.phpt b/ext/uri/tests/whatwg/modification/port_success_special1.phpt new file mode 100644 index 0000000000000..ba85449e43536 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/port_success_special1.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - port - adding a new one for a special URL +--EXTENSIONS-- +uri +--FILE-- +withPort(80); + +var_dump($url1->getPort()); +var_dump($url2->getPort()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +int(88) +NULL +string(19) "http://example.com/" diff --git a/ext/uri/tests/whatwg/modification/port_success_special2.phpt b/ext/uri/tests/whatwg/modification/port_success_special2.phpt new file mode 100644 index 0000000000000..d9f0074f05329 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/port_success_special2.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - port - adding a new one for a special URL +--EXTENSIONS-- +uri +--FILE-- +withPort(443); + +var_dump($url1->getPort()); +var_dump($url2->getPort()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +NULL +string(20) "https://example.com/" diff --git a/ext/uri/tests/whatwg/modification/port_success_unset_existing.phpt b/ext/uri/tests/whatwg/modification/port_success_unset_existing.phpt new file mode 100644 index 0000000000000..c280c181b19a4 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/port_success_unset_existing.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - port - unsetting existing +--EXTENSIONS-- +uri +--FILE-- +withPort(null); + +var_dump($url1->getPort()); +var_dump($url2->getPort()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +int(80) +NULL +string(20) "https://example.com/" diff --git a/ext/uri/tests/whatwg/modification/port_success_unset_non_existent.phpt b/ext/uri/tests/whatwg/modification/port_success_unset_non_existent.phpt new file mode 100644 index 0000000000000..d364c72d7002b --- /dev/null +++ b/ext/uri/tests/whatwg/modification/port_success_unset_non_existent.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - port - unsetting non-existent +--EXTENSIONS-- +uri +--FILE-- +withPort(null); + +var_dump($url2->getPort()); +var_dump($url2->getPort()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +NULL +string(18) "ftp://example.com/" diff --git a/ext/uri/tests/whatwg/modification/query_success_auto_encoded.phpt b/ext/uri/tests/whatwg/modification/query_success_auto_encoded.phpt new file mode 100644 index 0000000000000..fc487f33797d5 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/query_success_auto_encoded.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - query - characters from the percent encode set +--EXTENSIONS-- +uri +--FILE-- +withQuery("#foo "); + +var_dump($url1->getQuery()); +var_dump($url2->getQuery()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +string(9) "%23foo%20" +string(30) "https://example.com/?%23foo%20" diff --git a/ext/uri/tests/whatwg/modification/query_success_context_sensitive_reserved.phpt b/ext/uri/tests/whatwg/modification/query_success_context_sensitive_reserved.phpt new file mode 100644 index 0000000000000..cb220a0a33ef3 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/query_success_context_sensitive_reserved.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - query - context-sensitive reserved character +--EXTENSIONS-- +uri +--FILE-- +withQuery("?foo=bar"); + +var_dump($url1->getQuery()); +var_dump($url2->getQuery()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +string(7) "foo=bar" +string(28) "https://example.com/?foo=bar" diff --git a/ext/uri/tests/whatwg/modification/query_success_empty.phpt b/ext/uri/tests/whatwg/modification/query_success_empty.phpt new file mode 100644 index 0000000000000..dcb98bc37689d --- /dev/null +++ b/ext/uri/tests/whatwg/modification/query_success_empty.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - query - empty string +--EXTENSIONS-- +uri +--FILE-- +withQuery(""); + +var_dump($url1->getQuery()); +var_dump($url2->getQuery()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +NULL +string(20) "https://example.com/" diff --git a/ext/uri/tests/whatwg/modification/query_success_encoded.phpt b/ext/uri/tests/whatwg/modification/query_success_encoded.phpt new file mode 100644 index 0000000000000..f9935015f7bd7 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/query_success_encoded.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - query - URL encoded characters +--EXTENSIONS-- +uri +--FILE-- +withQuery("foo%3db%61r"); // foo=bar + +var_dump($url1->getQuery()); +var_dump($url2->getQuery()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +string(11) "foo%3db%61r" +string(32) "https://example.com/?foo%3db%61r" diff --git a/ext/uri/tests/whatwg/modification/query_success_existing.phpt b/ext/uri/tests/whatwg/modification/query_success_existing.phpt new file mode 100644 index 0000000000000..b3429b58b8651 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/query_success_existing.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - query - changing an existing one +--EXTENSIONS-- +uri +--FILE-- +withQuery("foo=bar&baz=qux"); + +var_dump($url1->getQuery()); +var_dump($url2->getQuery()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(7) "foo=bar" +string(15) "foo=bar&baz=qux" +string(36) "https://example.com/?foo=bar&baz=qux" diff --git a/ext/uri/tests/whatwg/modification/query_success_null_byte.phpt b/ext/uri/tests/whatwg/modification/query_success_null_byte.phpt new file mode 100644 index 0000000000000..81232d8b2aa2d --- /dev/null +++ b/ext/uri/tests/whatwg/modification/query_success_null_byte.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - query - null byte +--EXTENSIONS-- +uri +--FILE-- +withQuery("f\0o=bar&baz=q\0x"); + +var_dump($url1->getQuery()); +var_dump($url2->getQuery()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +string(19) "f%00o=bar&baz=q%00x" +string(40) "https://example.com/?f%00o=bar&baz=q%00x" diff --git a/ext/uri/tests/whatwg/modification/query_success_question_mark.phpt b/ext/uri/tests/whatwg/modification/query_success_question_mark.phpt new file mode 100644 index 0000000000000..3e1bf5ab9dce5 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/query_success_question_mark.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - query - only a question mark character +--EXTENSIONS-- +uri +--FILE-- +withQuery("?"); + +var_dump($url1->getQuery()); +var_dump($url2->getQuery()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +string(0) "" +string(21) "https://example.com/?" diff --git a/ext/uri/tests/whatwg/modification/query_success_unicode.phpt b/ext/uri/tests/whatwg/modification/query_success_unicode.phpt new file mode 100644 index 0000000000000..526138f8954af --- /dev/null +++ b/ext/uri/tests/whatwg/modification/query_success_unicode.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - query - unicode characters +--EXTENSIONS-- +uri +--FILE-- +withQuery("ő"); + +var_dump($url1->getQuery()); +var_dump($url2->getQuery()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +string(6) "%C5%91" +string(27) "https://example.com/?%C5%91" diff --git a/ext/uri/tests/whatwg/modification/query_success_unset_existing.phpt b/ext/uri/tests/whatwg/modification/query_success_unset_existing.phpt new file mode 100644 index 0000000000000..cb5a2a701e24a --- /dev/null +++ b/ext/uri/tests/whatwg/modification/query_success_unset_existing.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - query - unsetting existing +--EXTENSIONS-- +uri +--FILE-- +withQuery(null); + +var_dump($url1->getQuery()); +var_dump($url2->getQuery()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(7) "foo=bar" +NULL +string(20) "https://example.com/" diff --git a/ext/uri/tests/whatwg/modification/query_success_unset_non_existent.phpt b/ext/uri/tests/whatwg/modification/query_success_unset_non_existent.phpt new file mode 100644 index 0000000000000..6456dcacac7f9 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/query_success_unset_non_existent.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - query - unsetting not-existent +--EXTENSIONS-- +uri +--FILE-- +withQuery(null); + +var_dump($url1->getQuery()); +var_dump($url2->getQuery()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +NULL +string(20) "https://example.com/" diff --git a/ext/uri/tests/whatwg/modification/query_success_with_leading_question_mark.phpt b/ext/uri/tests/whatwg/modification/query_success_with_leading_question_mark.phpt new file mode 100644 index 0000000000000..ce67dcb6bb352 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/query_success_with_leading_question_mark.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - query - with leading question mark +--EXTENSIONS-- +uri +--FILE-- +withQuery("?foo=bar"); + +var_dump($url1->getQuery()); +var_dump($url2->getQuery()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +string(7) "foo=bar" +string(35) "https://example.com/foo/bar?foo=bar" diff --git a/ext/uri/tests/whatwg/modification/scheme_error_empty.phpt b/ext/uri/tests/whatwg/modification/scheme_error_empty.phpt new file mode 100644 index 0000000000000..5e3525de7d94f --- /dev/null +++ b/ext/uri/tests/whatwg/modification/scheme_error_empty.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - scheme - empty string +--EXTENSIONS-- +uri +--FILE-- +withScheme(""); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified scheme is malformed diff --git a/ext/uri/tests/whatwg/modification/scheme_error_encoded.phpt b/ext/uri/tests/whatwg/modification/scheme_error_encoded.phpt new file mode 100644 index 0000000000000..bda1ac497e25d --- /dev/null +++ b/ext/uri/tests/whatwg/modification/scheme_error_encoded.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - scheme - URL encoded characters +--EXTENSIONS-- +uri +--FILE-- +withScheme("http%73"); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified scheme is malformed diff --git a/ext/uri/tests/whatwg/modification/scheme_error_invalid.phpt b/ext/uri/tests/whatwg/modification/scheme_error_invalid.phpt new file mode 100644 index 0000000000000..ad98af24e4afd --- /dev/null +++ b/ext/uri/tests/whatwg/modification/scheme_error_invalid.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - scheme - invalid characters +--EXTENSIONS-- +uri +--FILE-- +withScheme("http?"); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified scheme is malformed diff --git a/ext/uri/tests/whatwg/modification/scheme_error_null_byte.phpt b/ext/uri/tests/whatwg/modification/scheme_error_null_byte.phpt new file mode 100644 index 0000000000000..ab2845ae64937 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/scheme_error_null_byte.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - scheme - null byte +--EXTENSIONS-- +uri +--FILE-- +withScheme("sch\0me"); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified scheme is malformed diff --git a/ext/uri/tests/whatwg/modification/scheme_success_basic.phpt b/ext/uri/tests/whatwg/modification/scheme_success_basic.phpt new file mode 100644 index 0000000000000..6f66b30b2b7b4 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/scheme_success_basic.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - scheme - basic case +--EXTENSIONS-- +uri +--FILE-- +withScheme("HTTP"); + +var_dump($url1->getScheme()); +var_dump($url2->getScheme()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(5) "https" +string(4) "http" +string(19) "http://example.com/" diff --git a/ext/uri/tests/whatwg/modification/scheme_success_colon.phpt b/ext/uri/tests/whatwg/modification/scheme_success_colon.phpt new file mode 100644 index 0000000000000..052eca6e247b0 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/scheme_success_colon.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - scheme - trailing colon +--EXTENSIONS-- +uri +--FILE-- +withScheme("http:"); + +var_dump($url1->getScheme()); +var_dump($url2->getScheme()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(5) "https" +string(4) "http" +string(19) "http://example.com/" diff --git a/ext/uri/tests/whatwg/modification/scheme_success_full.phpt b/ext/uri/tests/whatwg/modification/scheme_success_full.phpt new file mode 100644 index 0000000000000..957a1fab7aff2 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/scheme_success_full.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - scheme - trailing colon and double slash +--EXTENSIONS-- +uri +--FILE-- +withScheme("http://"); + +var_dump($url1->getScheme()); +var_dump($url2->getScheme()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(5) "https" +string(4) "http" +string(19) "http://example.com/" diff --git a/ext/uri/tests/whatwg/modification/username_success_auto_encoded.phpt b/ext/uri/tests/whatwg/modification/username_success_auto_encoded.phpt new file mode 100644 index 0000000000000..bc0beab496495 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/username_success_auto_encoded.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - username - characters from the percent encode set +--EXTENSIONS-- +uri +--FILE-- +withUsername("u:s/r"); + +var_dump($url1->getUsername()); +var_dump($url2->getUsername()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(4) "user" +string(9) "u%3As%2Fr" +string(39) "https://u%3As%2Fr:password@example.com/" diff --git a/ext/uri/tests/whatwg/modification/username_success_existing.phpt b/ext/uri/tests/whatwg/modification/username_success_existing.phpt new file mode 100644 index 0000000000000..2506acf85d714 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/username_success_existing.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - username - changing existing +--EXTENSIONS-- +uri +--FILE-- +withUsername("username"); + +var_dump($url1->getUsername()); +var_dump($url2->getUsername()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(4) "user" +string(8) "username" +string(29) "https://username@example.com/" diff --git a/ext/uri/tests/whatwg/modification/username_success_new.phpt b/ext/uri/tests/whatwg/modification/username_success_new.phpt new file mode 100644 index 0000000000000..56666a68ea7d2 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/username_success_new.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - username - adding a new one +--EXTENSIONS-- +uri +--FILE-- +withUsername("username"); + +var_dump($url1->getUsername()); +var_dump($url2->getUsername()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +string(8) "username" +string(29) "https://username@example.com/" diff --git a/ext/uri/tests/whatwg/modification/username_success_null_byte.phpt b/ext/uri/tests/whatwg/modification/username_success_null_byte.phpt new file mode 100644 index 0000000000000..86f6a62e0f200 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/username_success_null_byte.phpt @@ -0,0 +1,20 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - username - null byte +--EXTENSIONS-- +uri +--FILE-- +withUsername("usern\0me"); + +var_dump($url1->getUsername()); +var_dump($url2->getUsername()); +var_dump($url2->toAsciiString()); + + +?> +--EXPECT-- +NULL +string(10) "usern%00me" +string(31) "https://usern%00me@example.com/" diff --git a/ext/uri/tests/whatwg/modification/username_success_unset_existing.phpt b/ext/uri/tests/whatwg/modification/username_success_unset_existing.phpt new file mode 100644 index 0000000000000..8340b4ca1db61 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/username_success_unset_existing.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - username - unsetting existing +--EXTENSIONS-- +uri +--FILE-- +withUsername(null); + +var_dump($url1->getUsername()); +var_dump($url2->getUsername()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(8) "username" +string(0) "" +string(30) "https://:password@example.com/" diff --git a/ext/uri/tests/whatwg/modification/username_success_unset_existing2.phpt b/ext/uri/tests/whatwg/modification/username_success_unset_existing2.phpt new file mode 100644 index 0000000000000..ccfeac222e4e9 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/username_success_unset_existing2.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - username - unsetting existing +--EXTENSIONS-- +uri +--FILE-- +withUsername(null); + +var_dump($url1->getUsername()); +var_dump($url2->getUsername()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(8) "username" +NULL +string(20) "https://example.com/" diff --git a/ext/uri/tests/whatwg/modification/username_success_unset_non_existent1.phpt b/ext/uri/tests/whatwg/modification/username_success_unset_non_existent1.phpt new file mode 100644 index 0000000000000..44a6486104242 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/username_success_unset_non_existent1.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - username - unsetting non-existent +--EXTENSIONS-- +uri +--FILE-- +withUsername(null); + +var_dump($url1->getUsername()); +var_dump($url2->getUsername()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +NULL +NULL +string(20) "https://example.com/" diff --git a/ext/uri/tests/whatwg/modification/username_success_unset_non_existent2.phpt b/ext/uri/tests/whatwg/modification/username_success_unset_non_existent2.phpt new file mode 100644 index 0000000000000..7886b35fd9b84 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/username_success_unset_non_existent2.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - username - unsetting non-existent +--EXTENSIONS-- +uri +--FILE-- +withUsername(null); + +var_dump($url1->getUsername()); +var_dump($url2->getUsername()); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +string(0) "" +string(0) "" +string(30) "https://:password@example.com/" diff --git a/ext/uri/tests/whatwg/parsing/basic_error_empty.phpt b/ext/uri/tests/whatwg/parsing/basic_error_empty.phpt new file mode 100644 index 0000000000000..2b7114baa738a --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/basic_error_empty.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - basic - empty string +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (MissingSchemeNonRelativeUrl) diff --git a/ext/uri/tests/whatwg/parsing/basic_success_all.phpt b/ext/uri/tests/whatwg/parsing/basic_success_all.phpt new file mode 100644 index 0000000000000..0af4d16e4cb3a --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/basic_success_all.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - basic - all components +--FILE-- +toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + string(4) "user" + ["password"]=> + string(4) "info" + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(8) "/foo/bar" + ["query"]=> + string(15) "abc=123&def=ghi" + ["fragment"]=> + string(8) "hashmark" +} +string(62) "https://user:info@example.com/foo/bar?abc=123&def=ghi#hashmark" diff --git a/ext/uri/tests/whatwg/parsing/basic_sucess_email.phpt b/ext/uri/tests/whatwg/parsing/basic_sucess_email.phpt new file mode 100644 index 0000000000000..dcceb441c676f --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/basic_sucess_email.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - basic - mailto email +--FILE-- +toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(6) "mailto" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + NULL + ["port"]=> + NULL + ["path"]=> + string(16) "user@example.com" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(23) "mailto:user@example.com" diff --git a/ext/uri/tests/whatwg/parsing/basic_sucess_file.phpt b/ext/uri/tests/whatwg/parsing/basic_sucess_file.phpt new file mode 100644 index 0000000000000..96b67bc24b791 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/basic_sucess_file.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - basic - file +--FILE-- +toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(4) "file" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(0) "" + ["port"]=> + NULL + ["path"]=> + string(30) "/E:/Documents%20and%20Settings" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(37) "file:///E:/Documents%20and%20Settings" diff --git a/ext/uri/tests/whatwg/parsing/basic_sucess_urn.phpt b/ext/uri/tests/whatwg/parsing/basic_sucess_urn.phpt new file mode 100644 index 0000000000000..91fe664fb68fd --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/basic_sucess_urn.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - basic - URN +--FILE-- +toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(3) "urn" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + NULL + ["port"]=> + NULL + ["path"]=> + string(41) "uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(45) "urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66" diff --git a/ext/uri/tests/whatwg/parsing/host_error_Invalid.phpt b/ext/uri/tests/whatwg/parsing/host_error_Invalid.phpt new file mode 100644 index 0000000000000..8444ee9e3e96b --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/host_error_Invalid.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - host - invalid code point +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (DomainInvalidCodePoint) diff --git a/ext/uri/tests/whatwg/parsing/host_error_empty1.phpt b/ext/uri/tests/whatwg/parsing/host_error_empty1.phpt new file mode 100644 index 0000000000000..92b317078ebbe --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/host_error_empty1.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - host - empty +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (HostMissing) diff --git a/ext/uri/tests/whatwg/parsing/host_error_empty2.phpt b/ext/uri/tests/whatwg/parsing/host_error_empty2.phpt new file mode 100644 index 0000000000000..934185455641f --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/host_error_empty2.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - host - empty +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed diff --git a/ext/uri/tests/whatwg/parsing/host_error_empty3.phpt b/ext/uri/tests/whatwg/parsing/host_error_empty3.phpt new file mode 100644 index 0000000000000..90f2738148f48 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/host_error_empty3.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - host - empty +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (MissingSchemeNonRelativeUrl) diff --git a/ext/uri/tests/whatwg/parsing/host_error_ipvfuture.phpt b/ext/uri/tests/whatwg/parsing/host_error_ipvfuture.phpt new file mode 100644 index 0000000000000..959aa0c4442b3 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/host_error_ipvfuture.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - host - IPvFuture +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (Ipv6InvalidCodePoint) diff --git a/ext/uri/tests/whatwg/parsing/host_error_null_byte.phpt b/ext/uri/tests/whatwg/parsing/host_error_null_byte.phpt new file mode 100644 index 0000000000000..f450d26c41648 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/host_error_null_byte.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - basic - URL contains null byte +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (DomainInvalidCodePoint) diff --git a/ext/uri/tests/whatwg/parsing/host_success_empty4.phpt b/ext/uri/tests/whatwg/parsing/host_success_empty4.phpt new file mode 100644 index 0000000000000..25a28a9750c4e --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/host_success_empty4.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - host - empty +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (MissingSchemeNonRelativeUrl) diff --git a/ext/uri/tests/whatwg/parsing/host_success_ipv4.phpt b/ext/uri/tests/whatwg/parsing/host_success_ipv4.phpt new file mode 100644 index 0000000000000..f47a43aa8351f --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/host_success_ipv4.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - host - IPv4 +--FILE-- +toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "192.168.0.1" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(20) "https://192.168.0.1/" diff --git a/ext/uri/tests/whatwg/parsing/host_success_ipv4_wrong.phpt b/ext/uri/tests/whatwg/parsing/host_success_ipv4_wrong.phpt new file mode 100644 index 0000000000000..9096bfec3d6e6 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/host_success_ipv4_wrong.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - host - wrong IPv4 format +--FILE-- +toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "192.0.0.168" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(20) "https://192.0.0.168/" diff --git a/ext/uri/tests/whatwg/parsing/host_success_ipv6.phpt b/ext/uri/tests/whatwg/parsing/host_success_ipv6.phpt new file mode 100644 index 0000000000000..8cbe42f23ab5d --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/host_success_ipv6.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - host - IPv6 +--FILE-- +toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(40) "[2001:db8:3333:4444:5555:6666:7777:8888]" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(49) "https://[2001:db8:3333:4444:5555:6666:7777:8888]/" diff --git a/ext/uri/tests/whatwg/parsing/host_success_multibyte.phpt b/ext/uri/tests/whatwg/parsing/host_success_multibyte.phpt new file mode 100644 index 0000000000000..15613a1a0a9dc --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/host_success_multibyte.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - host - multibyte codepoint +--FILE-- +toAsciiString()); +var_dump($url->toUnicodeString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(19) "xn--exmple-xf7b.com" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(28) "https://xn--exmple-xf7b.com/" +string(22) "https://xn--exmple-xf7b.com/" diff --git a/ext/uri/tests/whatwg/parsing/password_success_empty.phpt b/ext/uri/tests/whatwg/parsing/password_success_empty.phpt new file mode 100644 index 0000000000000..adfa82357c2a4 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/password_success_empty.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - password - empty +--FILE-- +toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + string(4) "user" + ["password"]=> + string(0) "" + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(25) "https://user@example.com/" diff --git a/ext/uri/tests/whatwg/parsing/password_success_extended_ascii.phpt b/ext/uri/tests/whatwg/parsing/password_success_extended_ascii.phpt new file mode 100644 index 0000000000000..02ccf71c6f694 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/password_success_extended_ascii.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - password - extended ASCII character +--FILE-- +toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(4) "http" + ["username"]=> + string(4) "user" + ["password"]=> + string(18) "p%C3%A1ssw%C3%B6rd" + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(43) "http://user:p%C3%A1ssw%C3%B6rd@example.com/" diff --git a/ext/uri/tests/whatwg/parsing/password_success_multibyte.phpt b/ext/uri/tests/whatwg/parsing/password_success_multibyte.phpt new file mode 100644 index 0000000000000..96d636ea2847a --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/password_success_multibyte.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - password - multibyte codepoint +--FILE-- +toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(4) "http" + ["username"]=> + string(4) "user" + ["password"]=> + string(9) "p%C4%85ss" + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(34) "http://user:p%C4%85ss@example.com/" diff --git a/ext/uri/tests/whatwg/parsing/password_success_null_byte.phpt b/ext/uri/tests/whatwg/parsing/password_success_null_byte.phpt new file mode 100644 index 0000000000000..9dada6a9f387e --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/password_success_null_byte.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - password - null byte +--FILE-- +toAsciiString()); + +?> +--EXPECT-- +object(Uri\WhatWg\Url)#1 (8) { + ["scheme"]=> + string(5) "https" + ["username"]=> + string(8) "username" + ["password"]=> + string(7) "%00pass" + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(37) "https://username:%00pass@example.com/" diff --git a/ext/uri/tests/whatwg/parsing/password_success_percent_encode_set.phpt b/ext/uri/tests/whatwg/parsing/password_success_percent_encode_set.phpt new file mode 100644 index 0000000000000..3a104bd634050 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/password_success_percent_encode_set.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - password - codepoint in percent-encode set +--FILE-- +toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(4) "http" + ["username"]=> + string(4) "user" + ["password"]=> + string(6) "pa%7Cs" + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(31) "http://user:pa%7Cs@example.com/" diff --git a/ext/uri/tests/whatwg/parsing/path_error_relative_reference.phpt b/ext/uri/tests/whatwg/parsing/path_error_relative_reference.phpt new file mode 100644 index 0000000000000..8e6c6fd3842ec --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/path_error_relative_reference.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - path - relative reference +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (MissingSchemeNonRelativeUrl) diff --git a/ext/uri/tests/whatwg/parsing/path_error_relative_reference_absolute.phpt b/ext/uri/tests/whatwg/parsing/path_error_relative_reference_absolute.phpt new file mode 100644 index 0000000000000..01d549210d9f7 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/path_error_relative_reference_absolute.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - path - relative reference +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (MissingSchemeNonRelativeUrl) diff --git a/ext/uri/tests/whatwg/parsing/path_error_relative_reference_only_query_fragment.phpt b/ext/uri/tests/whatwg/parsing/path_error_relative_reference_only_query_fragment.phpt new file mode 100644 index 0000000000000..9c6a7a7906b23 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/path_error_relative_reference_only_query_fragment.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - path - relative reference +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (MissingSchemeNonRelativeUrl) diff --git a/ext/uri/tests/whatwg/parsing/path_success_multibyte.phpt b/ext/uri/tests/whatwg/parsing/path_success_multibyte.phpt new file mode 100644 index 0000000000000..d89db40fcb381 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/path_success_multibyte.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - path - multibyte +--FILE-- +toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(14) "/f%C8%8E%C8%8E" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(33) "https://example.com/f%C8%8E%C8%8E" diff --git a/ext/uri/tests/whatwg/parsing/path_success_null_byte.phpt b/ext/uri/tests/whatwg/parsing/path_success_null_byte.phpt new file mode 100644 index 0000000000000..d20242dcee53a --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/path_success_null_byte.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - path - null byte +--FILE-- +toAsciiString()); + +?> +--EXPECT-- +object(Uri\WhatWg\Url)#1 (8) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(8) "/pa%00th" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(27) "https://example.com/pa%00th" diff --git a/ext/uri/tests/whatwg/parsing/path_success_percent_encode_set2.phpt b/ext/uri/tests/whatwg/parsing/path_success_percent_encode_set2.phpt new file mode 100644 index 0000000000000..9419c817fbbd4 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/path_success_percent_encode_set2.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - path - codepoint in percent-encode set +--FILE-- +/^{baz}"); + +var_dump($url); +var_dump($url->toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(28) "/foo%22/%3Cbar%3E/^%7Bbaz%7D" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(47) "https://example.com/foo%22/%3Cbar%3E/%5E%7Bbaz%7D" diff --git a/ext/uri/tests/whatwg/parsing/path_success_slash_only.phpt b/ext/uri/tests/whatwg/parsing/path_success_slash_only.phpt new file mode 100644 index 0000000000000..66bd4e24e0fa6 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/path_success_slash_only.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - path - slash only +--FILE-- +toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(20) "https://example.com/" diff --git a/ext/uri/tests/whatwg/parsing/path_success_special.phpt b/ext/uri/tests/whatwg/parsing/path_success_special.phpt new file mode 100644 index 0000000000000..33feecd69eef5 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/path_success_special.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - path - special characters +--FILE-- +toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(20) "/fo[o/ba]r/baz=q@z,&" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(39) "https://example.com/fo[o/ba]r/baz=q@z,&" diff --git a/ext/uri/tests/whatwg/parsing/port_error_multibyte.phpt b/ext/uri/tests/whatwg/parsing/port_error_multibyte.phpt new file mode 100644 index 0000000000000..8175f2ca992a3 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/port_error_multibyte.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - port - multibyte +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (PortInvalid) diff --git a/ext/uri/tests/whatwg/parsing/port_error_negative.phpt b/ext/uri/tests/whatwg/parsing/port_error_negative.phpt new file mode 100644 index 0000000000000..bb23476db57c9 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/port_error_negative.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - port - negative value +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (PortInvalid) diff --git a/ext/uri/tests/whatwg/parsing/port_error_percent_encoded.phpt b/ext/uri/tests/whatwg/parsing/port_error_percent_encoded.phpt new file mode 100644 index 0000000000000..874211ccb1cf4 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/port_error_percent_encoded.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - port - percent encoded character +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (PortInvalid) diff --git a/ext/uri/tests/whatwg/parsing/port_error_user_info_wrong_place.phpt b/ext/uri/tests/whatwg/parsing/port_error_user_info_wrong_place.phpt new file mode 100644 index 0000000000000..f0f79670230df --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/port_error_user_info_wrong_place.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - port - user info component is in wrong place +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (PortInvalid) diff --git a/ext/uri/tests/whatwg/parsing/port_success_empty.phpt b/ext/uri/tests/whatwg/parsing/port_success_empty.phpt new file mode 100644 index 0000000000000..85ba06f0ba7aa --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/port_success_empty.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - port - empty +--FILE-- +toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(4) "http" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(19) "http://example.com/" diff --git a/ext/uri/tests/whatwg/parsing/port_success_zero.phpt b/ext/uri/tests/whatwg/parsing/port_success_zero.phpt new file mode 100644 index 0000000000000..22b5b89427a41 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/port_success_zero.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - port - zero +--FILE-- +toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(4) "http" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + int(0) + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(21) "http://example.com:0/" diff --git a/ext/uri/tests/whatwg/parsing/query_success_null_byte.phpt b/ext/uri/tests/whatwg/parsing/query_success_null_byte.phpt new file mode 100644 index 0000000000000..bf1364365156b --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/query_success_null_byte.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - query - null byte +--FILE-- +toAsciiString()); + +?> +--EXPECT-- +object(Uri\WhatWg\Url)#1 (8) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + string(9) "fo%00=bar" + ["fragment"]=> + NULL +} +string(30) "https://example.com/?fo%00=bar" diff --git a/ext/uri/tests/whatwg/parsing/scheme_error_empty.phpt b/ext/uri/tests/whatwg/parsing/scheme_error_empty.phpt new file mode 100644 index 0000000000000..023c1d3fab9d7 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/scheme_error_empty.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - scheme - empty +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (MissingSchemeNonRelativeUrl) diff --git a/ext/uri/tests/whatwg/parsing/scheme_error_invalid.phpt b/ext/uri/tests/whatwg/parsing/scheme_error_invalid.phpt new file mode 100644 index 0000000000000..9c69b08161ef8 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/scheme_error_invalid.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - scheme - invalid character +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (MissingSchemeNonRelativeUrl) diff --git a/ext/uri/tests/whatwg/parsing/scheme_error_multibyte.phpt b/ext/uri/tests/whatwg/parsing/scheme_error_multibyte.phpt new file mode 100644 index 0000000000000..0d6601e718ea3 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/scheme_error_multibyte.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - scheme - multibyte codepoint +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (MissingSchemeNonRelativeUrl) diff --git a/ext/uri/tests/whatwg/parsing/scheme_error_null_byte.phpt b/ext/uri/tests/whatwg/parsing/scheme_error_null_byte.phpt new file mode 100644 index 0000000000000..5674c1f330932 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/scheme_error_null_byte.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - scheme - null byte +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (MissingSchemeNonRelativeUrl) diff --git a/ext/uri/tests/whatwg/parsing/scheme_error_only1.phpt b/ext/uri/tests/whatwg/parsing/scheme_error_only1.phpt new file mode 100644 index 0000000000000..92832f65a019f --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/scheme_error_only1.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - scheme - only scheme +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (HostMissing) diff --git a/ext/uri/tests/whatwg/parsing/scheme_error_only2.phpt b/ext/uri/tests/whatwg/parsing/scheme_error_only2.phpt new file mode 100644 index 0000000000000..22ab6fc53515e --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/scheme_error_only2.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - scheme - only scheme +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (HostMissing) diff --git a/ext/uri/tests/whatwg/parsing/scheme_error_percent_encoded.phpt b/ext/uri/tests/whatwg/parsing/scheme_error_percent_encoded.phpt new file mode 100644 index 0000000000000..a0324edd37016 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/scheme_error_percent_encoded.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - scheme - percent encoded character +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (MissingSchemeNonRelativeUrl) diff --git a/ext/uri/tests/whatwg/parsing/scheme_error_special.phpt b/ext/uri/tests/whatwg/parsing/scheme_error_special.phpt new file mode 100644 index 0000000000000..9966ad6248e51 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/scheme_error_special.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - scheme - invalid character +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (MissingSchemeNonRelativeUrl) diff --git a/ext/uri/tests/whatwg/parsing/scheme_success_iana.phpt b/ext/uri/tests/whatwg/parsing/scheme_success_iana.phpt new file mode 100644 index 0000000000000..a59888f5a1e48 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/scheme_success_iana.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - scheme - IANA scheme +--FILE-- +toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%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 +} +string(30) "chrome-extension://example.com" diff --git a/ext/uri/tests/whatwg/parsing/scheme_success_without_slash.phpt b/ext/uri/tests/whatwg/parsing/scheme_success_without_slash.phpt new file mode 100644 index 0000000000000..ab3da6438ce4e --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/scheme_success_without_slash.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - scheme - without // +--FILE-- +toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(20) "https://example.com/" diff --git a/ext/uri/tests/whatwg/parsing/username_success_empty.phpt b/ext/uri/tests/whatwg/parsing/username_success_empty.phpt new file mode 100644 index 0000000000000..804fe1feaae3b --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/username_success_empty.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - username - empty +--FILE-- +toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + string(0) "" + ["password"]=> + string(4) "pass" + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(26) "https://:pass@example.com/" diff --git a/ext/uri/tests/whatwg/parsing/username_success_extended_ascii.phpt b/ext/uri/tests/whatwg/parsing/username_success_extended_ascii.phpt new file mode 100644 index 0000000000000..54e6de85cd6b4 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/username_success_extended_ascii.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - username - extended ASCII character +--FILE-- +toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + string(14) "%C3%BAz%C3%B6r" + ["password"]=> + string(0) "" + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(35) "https://%C3%BAz%C3%B6r@example.com/" diff --git a/ext/uri/tests/whatwg/parsing/username_success_multibyte.phpt b/ext/uri/tests/whatwg/parsing/username_success_multibyte.phpt new file mode 100644 index 0000000000000..bf08c404d0433 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/username_success_multibyte.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - username - multibyte codepoint +--FILE-- +toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + string(9) "us%C4%95r" + ["password"]=> + string(4) "pass" + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(35) "https://us%C4%95r:pass@example.com/" diff --git a/ext/uri/tests/whatwg/parsing/username_success_null_byte.phpt b/ext/uri/tests/whatwg/parsing/username_success_null_byte.phpt new file mode 100644 index 0000000000000..d99c3cefdc153 --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/username_success_null_byte.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - username - null byte +--FILE-- +toAsciiString()); + +?> +--EXPECT-- +object(Uri\WhatWg\Url)#1 (8) { + ["scheme"]=> + string(5) "https" + ["username"]=> + string(11) "user%00name" + ["password"]=> + string(4) "pass" + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(37) "https://user%00name:pass@example.com/" diff --git a/ext/uri/tests/whatwg/parsing/username_success_percent_encode_set.phpt b/ext/uri/tests/whatwg/parsing/username_success_percent_encode_set.phpt new file mode 100644 index 0000000000000..d4aeaf61d72eb --- /dev/null +++ b/ext/uri/tests/whatwg/parsing/username_success_percent_encode_set.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url parsing - username - codepoint in percent-encode set +--FILE-- +toAsciiString()); + +?> +--EXPECTF-- +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(4) "http" + ["username"]=> + string(10) "us%5Ber%5D" + ["password"]=> + string(4) "pass" + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(35) "http://us%5Ber%5D:pass@example.com/" diff --git a/ext/uri/tests/whatwg/reference_resolution/resolve_error_host_null_byte.phpt b/ext/uri/tests/whatwg/reference_resolution/resolve_error_host_null_byte.phpt new file mode 100644 index 0000000000000..ed31e0e5daead --- /dev/null +++ b/ext/uri/tests/whatwg/reference_resolution/resolve_error_host_null_byte.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test Uri\WhatWg\Url reference resolution - resolve() - null byte +--EXTENSIONS-- +uri +--FILE-- +resolve("https://ex/0mple.com"); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (DomainInvalidCodePoint) diff --git a/ext/uri/tests/whatwg/reference_resolution/resolve_success_path_null_byte.phpt b/ext/uri/tests/whatwg/reference_resolution/resolve_success_path_null_byte.phpt new file mode 100644 index 0000000000000..abdcec98e8421 --- /dev/null +++ b/ext/uri/tests/whatwg/reference_resolution/resolve_success_path_null_byte.phpt @@ -0,0 +1,53 @@ +--TEST-- +Test Uri\WhatWg\Url reference resolution - resolve() - null byte in path +--EXTENSIONS-- +uri +--FILE-- +resolve("/f\0o"); + +var_dump($url1); +var_dump($url2); +var_dump($url2->toAsciiString()); + +?> +--EXPECT-- +object(Uri\WhatWg\Url)#1 (8) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +object(Uri\WhatWg\Url)#2 (8) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(6) "/f%00o" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +string(25) "https://example.com/f%00o" diff --git a/ext/uri/uri_parser_php_parse_url.c b/ext/uri/uri_parser_php_parse_url.c new file mode 100644 index 0000000000000..8cee29e8f0c6c --- /dev/null +++ b/ext/uri/uri_parser_php_parse_url.c @@ -0,0 +1,184 @@ +/* + +----------------------------------------------------------------------+ + | 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: Máté Kocsis | + | Tim Düsterhus | + +----------------------------------------------------------------------+ +*/ + +#include "php.h" +#include "uri_parser_php_parse_url.h" +#include "php_uri_common.h" +#include "Zend/zend_exceptions.h" +#include "ext/standard/url.h" + +static zend_string *decode_component(zend_string *in, php_uri_component_read_mode read_mode) +{ + switch (read_mode) { + case PHP_URI_COMPONENT_READ_MODE_RAW: + return zend_string_copy(in); + case PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII: + case PHP_URI_COMPONENT_READ_MODE_NORMALIZED_UNICODE: { + zend_string *out = zend_string_alloc(ZSTR_LEN(in), false); + + ZSTR_LEN(out) = php_raw_url_decode_ex(ZSTR_VAL(out), ZSTR_VAL(in), ZSTR_LEN(in)); + + return out; + } + EMPTY_SWITCH_DEFAULT_CASE(); + } +} + +static zend_result uri_parser_php_parse_url_scheme_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const php_url *parse_url_uri = uri; + + if (parse_url_uri->scheme) { + ZVAL_STR(retval, decode_component(parse_url_uri->scheme, read_mode)); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result uri_parser_php_parse_url_username_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const php_url *parse_url_uri = uri; + + if (parse_url_uri->user) { + ZVAL_STR(retval, decode_component(parse_url_uri->user, read_mode)); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result uri_parser_php_parse_url_password_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const php_url *parse_url_uri = uri; + + if (parse_url_uri->pass) { + ZVAL_STR(retval, decode_component(parse_url_uri->pass, read_mode)); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result uri_parser_php_parse_url_host_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const php_url *parse_url_uri = uri; + + if (parse_url_uri->host) { + ZVAL_STR(retval, decode_component(parse_url_uri->host, read_mode)); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result uri_parser_php_parse_url_port_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const php_url *parse_url_uri = uri; + + if (parse_url_uri->port) { + ZVAL_LONG(retval, parse_url_uri->port); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result uri_parser_php_parse_url_path_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const php_url *parse_url_uri = uri; + + if (parse_url_uri->path) { + ZVAL_STR(retval, decode_component(parse_url_uri->path, read_mode)); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result uri_parser_php_parse_url_query_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const php_url *parse_url_uri = uri; + + if (parse_url_uri->query) { + ZVAL_STR(retval, decode_component(parse_url_uri->query, read_mode)); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result uri_parser_php_parse_url_fragment_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const php_url *parse_url_uri = uri; + + if (parse_url_uri->fragment) { + ZVAL_STR(retval, decode_component(parse_url_uri->fragment, read_mode)); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static void *uri_parser_php_parse_url_parse(const char *uri_str, size_t uri_str_len, const void *base_url, zval *errors, bool silent) +{ + bool has_port; + + php_url *url = php_url_parse_ex2(uri_str, uri_str_len, &has_port); + if (url == NULL && !silent) { + zend_throw_exception(php_uri_ce_invalid_uri_exception, "The specified URI is malformed", 0); + } + + return url; +} + +static void uri_parser_php_parse_url_destroy(void *uri) +{ + php_url *parse_url_uri = uri; + + if (UNEXPECTED(parse_url_uri == NULL)) { + return; + } + + php_url_free(parse_url_uri); +} + +PHPAPI const php_uri_parser php_uri_parser_php_parse_url = { + .name = PHP_URI_PARSER_PHP_PARSE_URL, + .parse = uri_parser_php_parse_url_parse, + .clone = NULL, + .to_string = NULL, + .destroy = uri_parser_php_parse_url_destroy, + { + .scheme = {.read = uri_parser_php_parse_url_scheme_read, .write = NULL}, + .username = {.read = uri_parser_php_parse_url_username_read, .write = NULL}, + .password = {.read = uri_parser_php_parse_url_password_read, .write = NULL}, + .host = {.read = uri_parser_php_parse_url_host_read, .write = NULL}, + .port = {.read = uri_parser_php_parse_url_port_read, .write = NULL}, + .path = {.read = uri_parser_php_parse_url_path_read, .write = NULL}, + .query = {.read = uri_parser_php_parse_url_query_read, .write = NULL}, + .fragment = {.read = uri_parser_php_parse_url_fragment_read, .write = NULL}, + } +}; diff --git a/ext/uri/uri_parser_php_parse_url.h b/ext/uri/uri_parser_php_parse_url.h new file mode 100644 index 0000000000000..6cf532db83527 --- /dev/null +++ b/ext/uri/uri_parser_php_parse_url.h @@ -0,0 +1,25 @@ +/* + +----------------------------------------------------------------------+ + | 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: Máté Kocsis | + | Tim Düsterhus | + +----------------------------------------------------------------------+ +*/ + +#ifndef PHP_URI_PARSER_PHP_PARSE_URL_H +#define PHP_URI_PARSER_PHP_PARSE_URL_H + +#include "php_uri_common.h" + +PHPAPI extern const php_uri_parser php_uri_parser_php_parse_url; + +#endif diff --git a/ext/uri/uri_parser_rfc3986.c b/ext/uri/uri_parser_rfc3986.c new file mode 100644 index 0000000000000..69bd6ef9ecdc4 --- /dev/null +++ b/ext/uri/uri_parser_rfc3986.c @@ -0,0 +1,634 @@ +/* + +----------------------------------------------------------------------+ + | 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: Máté Kocsis | + +----------------------------------------------------------------------+ +*/ + +#include "php.h" +#include "uri_parser_rfc3986.h" +#include "php_uri_common.h" +#include "Zend/zend_smart_str.h" +#include "Zend/zend_exceptions.h" + +#include + +struct php_uri_parser_rfc3986_uris { + UriUriA uri; + UriUriA normalized_uri; + bool normalized_uri_initialized; +}; + +static void *php_uri_parser_rfc3986_memory_manager_malloc(UriMemoryManager *memory_manager, size_t size) +{ + return emalloc(size); +} + +static void *php_uri_parser_rfc3986_memory_manager_calloc(UriMemoryManager *memory_manager, size_t nmemb, size_t size) +{ + return ecalloc(nmemb, size); +} + +static void *php_uri_parser_rfc3986_memory_manager_realloc(UriMemoryManager *memory_manager, void *ptr, size_t size) +{ + return erealloc(ptr, size); +} + +static void *php_uri_parser_rfc3986_memory_manager_reallocarray(UriMemoryManager *memory_manager, void *ptr, size_t nmemb, size_t size) +{ + return safe_erealloc(ptr, nmemb, size, 0); +} + +static void php_uri_parser_rfc3986_memory_manager_destroy(UriMemoryManager *memory_manager, void *ptr) +{ + efree(ptr); +} + +static const UriMemoryManager php_uri_parser_rfc3986_memory_manager = { + .malloc = php_uri_parser_rfc3986_memory_manager_malloc, + .calloc = php_uri_parser_rfc3986_memory_manager_calloc, + .realloc = php_uri_parser_rfc3986_memory_manager_realloc, + .reallocarray = php_uri_parser_rfc3986_memory_manager_reallocarray, + .free = php_uri_parser_rfc3986_memory_manager_destroy, + .userData = NULL, +}; + +/* The library expects a pointer to a non-const UriMemoryManager, but does + * not actually modify it (and neither does our implementation). Use a + * const struct with a non-const pointer for convenience. */ +static UriMemoryManager* const mm = (UriMemoryManager*)&php_uri_parser_rfc3986_memory_manager; + +static inline size_t get_text_range_length(const UriTextRangeA *range) +{ + return range->afterLast - range->first; +} + +static inline bool has_text_range(const UriTextRangeA *range) +{ + return range->first != NULL && range->afterLast != NULL; +} + +ZEND_ATTRIBUTE_NONNULL static void copy_uri(UriUriA *new_uriparser_uri, const UriUriA *uriparser_uri) +{ + int result = uriCopyUriMmA(new_uriparser_uri, uriparser_uri, mm); + ZEND_ASSERT(result == URI_SUCCESS); +} + +ZEND_ATTRIBUTE_NONNULL static UriUriA *get_normalized_uri(php_uri_parser_rfc3986_uris *uriparser_uris) { + if (!uriparser_uris->normalized_uri_initialized) { + copy_uri(&uriparser_uris->normalized_uri, &uriparser_uris->uri); + int result = uriNormalizeSyntaxExMmA(&uriparser_uris->normalized_uri, (unsigned int)-1, mm); + ZEND_ASSERT(result == URI_SUCCESS); + uriparser_uris->normalized_uri_initialized = true; + } + + return &uriparser_uris->normalized_uri; +} + +ZEND_ATTRIBUTE_NONNULL static UriUriA *get_uri_for_reading(php_uri_parser_rfc3986_uris *uriparser_uris, php_uri_component_read_mode read_mode) +{ + switch (read_mode) { + case PHP_URI_COMPONENT_READ_MODE_RAW: + return &uriparser_uris->uri; + case PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII: + ZEND_FALLTHROUGH; + case PHP_URI_COMPONENT_READ_MODE_NORMALIZED_UNICODE: + return get_normalized_uri(uriparser_uris); + EMPTY_SWITCH_DEFAULT_CASE() + } +} + +ZEND_ATTRIBUTE_NONNULL static UriUriA *get_uri_for_writing(php_uri_parser_rfc3986_uris *uriparser_uris) +{ + return &uriparser_uris->uri; +} + +ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_scheme_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const UriUriA *uriparser_uri = get_uri_for_reading(uri, read_mode); + + if (has_text_range(&uriparser_uri->scheme)) { + ZVAL_STRINGL(retval, uriparser_uri->scheme.first, get_text_range_length(&uriparser_uri->scheme)); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result php_uri_parser_rfc3986_scheme_write(void *uri, zval *value, zval *errors) +{ + UriUriA *uriparser_uri = get_uri_for_writing(uri); + int result; + + if (Z_TYPE_P(value) == IS_NULL) { + result = uriSetSchemeMmA(uriparser_uri, NULL, NULL, mm); + } else { + result = uriSetSchemeMmA(uriparser_uri, Z_STRVAL_P(value), Z_STRVAL_P(value) + Z_STRLEN_P(value), mm); + } + + switch (result) { + case URI_SUCCESS: + return SUCCESS; + case URI_ERROR_SYNTAX: + zend_throw_exception(php_uri_ce_invalid_uri_exception, "The specified scheme is malformed", 0); + return FAILURE; + default: + /* This should be unreachable in practice. */ + zend_throw_exception(php_uri_ce_error, "Failed to update the scheme", 0); + return FAILURE; + } +} + +ZEND_ATTRIBUTE_NONNULL zend_result php_uri_parser_rfc3986_userinfo_read(php_uri_parser_rfc3986_uris *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const UriUriA *uriparser_uri = get_uri_for_reading(uri, read_mode); + + if (has_text_range(&uriparser_uri->userInfo)) { + ZVAL_STRINGL(retval, uriparser_uri->userInfo.first, get_text_range_length(&uriparser_uri->userInfo)); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +zend_result php_uri_parser_rfc3986_userinfo_write(php_uri_parser_rfc3986_uris *uri, zval *value, zval *errors) +{ + UriUriA *uriparser_uri = get_uri_for_writing(uri); + int result; + + if (Z_TYPE_P(value) == IS_NULL) { + result = uriSetUserInfoMmA(uriparser_uri, NULL, NULL, mm); + } else { + result = uriSetUserInfoMmA(uriparser_uri, Z_STRVAL_P(value), Z_STRVAL_P(value) + Z_STRLEN_P(value), mm); + } + + switch (result) { + case URI_SUCCESS: + return SUCCESS; + case URI_ERROR_SETUSERINFO_HOST_NOT_SET: + zend_throw_exception(php_uri_ce_invalid_uri_exception, "Cannot set a userinfo without having a host", 0); + return FAILURE; + case URI_ERROR_SYNTAX: + zend_throw_exception(php_uri_ce_invalid_uri_exception, "The specified userinfo is malformed", 0); + return FAILURE; + default: + /* This should be unreachable in practice. */ + zend_throw_exception(php_uri_ce_error, "Failed to update the userinfo", 0); + return FAILURE; + } +} + +ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_username_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const UriUriA *uriparser_uri = get_uri_for_reading(uri, read_mode); + + if (has_text_range(&uriparser_uri->userInfo)) { + size_t length = get_text_range_length(&uriparser_uri->userInfo); + const char *c = memchr(uriparser_uri->userInfo.first, ':', length); + + if (c == NULL && length > 0) { + ZVAL_STRINGL(retval, uriparser_uri->userInfo.first, length); + } else if (c != NULL && c - uriparser_uri->userInfo.first > 0) { + ZVAL_STRINGL(retval, uriparser_uri->userInfo.first, c - uriparser_uri->userInfo.first); + } else { + ZVAL_EMPTY_STRING(retval); + } + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_password_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const UriUriA *uriparser_uri = get_uri_for_reading(uri, read_mode); + + if (has_text_range(&uriparser_uri->userInfo)) { + const char *c = memchr(uriparser_uri->userInfo.first, ':', get_text_range_length(&uriparser_uri->userInfo)); + + if (c != NULL && uriparser_uri->userInfo.afterLast - c - 1 > 0) { + ZVAL_STRINGL(retval, c + 1, uriparser_uri->userInfo.afterLast - c - 1); + } else { + ZVAL_EMPTY_STRING(retval); + } + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_host_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const UriUriA *uriparser_uri = get_uri_for_reading(uri, read_mode); + + if (has_text_range(&uriparser_uri->hostText)) { + if (uriparser_uri->hostData.ip6 != NULL || uriparser_uri->hostData.ipFuture.first != NULL) { + /* the textual representation of the host is always accessible in the .hostText field no matter what the host is */ + smart_str host_str = {0}; + + smart_str_appendc(&host_str, '['); + smart_str_appendl(&host_str, uriparser_uri->hostText.first, get_text_range_length(&uriparser_uri->hostText)); + smart_str_appendc(&host_str, ']'); + + ZVAL_NEW_STR(retval, smart_str_extract(&host_str)); + } else { + ZVAL_STRINGL(retval, uriparser_uri->hostText.first, get_text_range_length(&uriparser_uri->hostText)); + } + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result php_uri_parser_rfc3986_host_write(void *uri, zval *value, zval *errors) +{ + UriUriA *uriparser_uri = get_uri_for_writing(uri); + int result; + + if (Z_TYPE_P(value) == IS_NULL) { + result = uriSetHostAutoMmA(uriparser_uri, NULL, NULL, mm); + } else { + result = uriSetHostAutoMmA(uriparser_uri, Z_STRVAL_P(value), Z_STRVAL_P(value) + Z_STRLEN_P(value), mm); + } + + switch (result) { + case URI_SUCCESS: + return SUCCESS; + case URI_ERROR_SETHOST_PORT_SET: + zend_throw_exception(php_uri_ce_invalid_uri_exception, "Cannot remove the host from a URI that has a port", 0); + return FAILURE; + case URI_ERROR_SETHOST_USERINFO_SET: + zend_throw_exception(php_uri_ce_invalid_uri_exception, "Cannot remove the host from a URI that has a userinfo", 0); + return FAILURE; + case URI_ERROR_SYNTAX: + zend_throw_exception(php_uri_ce_invalid_uri_exception, "The specified host is malformed", 0); + return FAILURE; + default: + /* This should be unreachable in practice. */ + zend_throw_exception(php_uri_ce_error, "Failed to update the host", 0); + return FAILURE; + } +} + +ZEND_ATTRIBUTE_NONNULL static zend_long port_str_to_zend_long_checked(const char *str, size_t len) +{ + if (len > MAX_LENGTH_OF_LONG) { + return -1; + } + + char buf[MAX_LENGTH_OF_LONG + 1]; + *(char*)zend_mempcpy(buf, str, len) = 0; + + zend_ulong result = ZEND_STRTOUL(buf, NULL, 10); + + if (result > ZEND_LONG_MAX) { + return -1; + } + + return (zend_long)result; +} + +ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_port_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const UriUriA *uriparser_uri = get_uri_for_reading(uri, read_mode); + + if (has_text_range(&uriparser_uri->portText) && get_text_range_length(&uriparser_uri->portText) > 0) { + ZVAL_LONG(retval, port_str_to_zend_long_checked(uriparser_uri->portText.first, get_text_range_length(&uriparser_uri->portText))); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result php_uri_parser_rfc3986_port_write(void *uri, zval *value, zval *errors) +{ + UriUriA *uriparser_uri = get_uri_for_writing(uri); + int result; + + if (Z_TYPE_P(value) == IS_NULL) { + result = uriSetPortTextMmA(uriparser_uri, NULL, NULL, mm); + } else { + zend_string *tmp = zend_long_to_str(Z_LVAL_P(value)); + result = uriSetPortTextMmA(uriparser_uri, ZSTR_VAL(tmp), ZSTR_VAL(tmp) + ZSTR_LEN(tmp), mm); + zend_string_release_ex(tmp, false); + } + + switch (result) { + case URI_SUCCESS: + return SUCCESS; + case URI_ERROR_SETPORT_HOST_NOT_SET: + zend_throw_exception(php_uri_ce_invalid_uri_exception, "Cannot set a port without having a host", 0); + return FAILURE; + case URI_ERROR_SYNTAX: + zend_throw_exception(php_uri_ce_invalid_uri_exception, "The specified port is malformed", 0); + return FAILURE; + default: + /* This should be unreachable in practice. */ + zend_throw_exception(php_uri_ce_error, "Failed to update the port", 0); + return FAILURE; + } +} + +ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_path_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const UriUriA *uriparser_uri = get_uri_for_reading(uri, read_mode); + + if (uriparser_uri->pathHead != NULL) { + smart_str str = {0}; + + if (uriparser_uri->absolutePath || uriHasHostA(uriparser_uri)) { + smart_str_appendc(&str, '/'); + } + + for (const UriPathSegmentA *p = uriparser_uri->pathHead; p; p = p->next) { + smart_str_appendl(&str, p->text.first, get_text_range_length(&p->text)); + if (p->next) { + smart_str_appendc(&str, '/'); + } + } + + ZVAL_NEW_STR(retval, smart_str_extract(&str)); + } else if (uriparser_uri->absolutePath) { + ZVAL_CHAR(retval, '/'); + } else { + ZVAL_EMPTY_STRING(retval); + } + + return SUCCESS; +} + +static zend_result php_uri_parser_rfc3986_path_write(void *uri, zval *value, zval *errors) +{ + UriUriA *uriparser_uri = get_uri_for_writing(uri); + int result; + + if (Z_STRLEN_P(value) == 0) { + result = uriSetPathMmA(uriparser_uri, NULL, NULL, mm); + } else { + result = uriSetPathMmA(uriparser_uri, Z_STRVAL_P(value), Z_STRVAL_P(value) + Z_STRLEN_P(value), mm); + } + + switch (result) { + case URI_SUCCESS: + return SUCCESS; + case URI_ERROR_SYNTAX: + zend_throw_exception(php_uri_ce_invalid_uri_exception, "The specified path is malformed", 0); + return FAILURE; + default: + /* This should be unreachable in practice. */ + zend_throw_exception(php_uri_ce_error, "Failed to update the path", 0); + return FAILURE; + } +} + +ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_query_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const UriUriA *uriparser_uri = get_uri_for_reading(uri, read_mode); + + if (has_text_range(&uriparser_uri->query)) { + ZVAL_STRINGL(retval, uriparser_uri->query.first, get_text_range_length(&uriparser_uri->query)); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result php_uri_parser_rfc3986_query_write(void *uri, zval *value, zval *errors) +{ + UriUriA *uriparser_uri = get_uri_for_writing(uri); + int result; + + if (Z_TYPE_P(value) == IS_NULL) { + result = uriSetQueryMmA(uriparser_uri, NULL, NULL, mm); + } else { + result = uriSetQueryMmA(uriparser_uri, Z_STRVAL_P(value), Z_STRVAL_P(value) + Z_STRLEN_P(value), mm); + } + + switch (result) { + case URI_SUCCESS: + return SUCCESS; + case URI_ERROR_SYNTAX: + zend_throw_exception(php_uri_ce_invalid_uri_exception, "The specified query is malformed", 0); + return FAILURE; + default: + /* This should be unreachable in practice. */ + zend_throw_exception(php_uri_ce_error, "Failed to update the query", 0); + return FAILURE; + } +} + +ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_fragment_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const UriUriA *uriparser_uri = get_uri_for_reading(uri, read_mode); + + if (has_text_range(&uriparser_uri->fragment)) { + ZVAL_STRINGL(retval, uriparser_uri->fragment.first, get_text_range_length(&uriparser_uri->fragment)); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result php_uri_parser_rfc3986_fragment_write(void *uri, zval *value, zval *errors) +{ + UriUriA *uriparser_uri = get_uri_for_writing(uri); + int result; + + if (Z_TYPE_P(value) == IS_NULL) { + result = uriSetFragmentMmA(uriparser_uri, NULL, NULL, mm); + } else { + result = uriSetFragmentMmA(uriparser_uri, Z_STRVAL_P(value), Z_STRVAL_P(value) + Z_STRLEN_P(value), mm); + } + + switch (result) { + case URI_SUCCESS: + return SUCCESS; + case URI_ERROR_SYNTAX: + zend_throw_exception(php_uri_ce_invalid_uri_exception, "The specified fragment is malformed", 0); + return FAILURE; + default: + /* This should be unreachable in practice. */ + zend_throw_exception(php_uri_ce_error, "Failed to update the fragment", 0); + return FAILURE; + } +} + +static php_uri_parser_rfc3986_uris *uriparser_create_uris(void) +{ + php_uri_parser_rfc3986_uris *uriparser_uris = ecalloc(1, sizeof(*uriparser_uris)); + uriparser_uris->normalized_uri_initialized = false; + + return uriparser_uris; +} + +php_uri_parser_rfc3986_uris *php_uri_parser_rfc3986_parse_ex(const char *uri_str, size_t uri_str_len, const php_uri_parser_rfc3986_uris *uriparser_base_urls, bool silent) +{ + UriUriA uri = {0}; + + /* Parse the URI. */ + int result = uriParseSingleUriExMmA(&uri, uri_str, uri_str + uri_str_len, NULL, mm); + if (result != URI_SUCCESS) { + if (!silent) { + switch (result) { + case URI_ERROR_SYNTAX: + zend_throw_exception(php_uri_ce_invalid_uri_exception, "The specified URI is malformed", 0); + break; + default: + /* This should be unreachable in practice. */ + zend_throw_exception(php_uri_ce_error, "Failed to parse the specified URI", 0); + break; + } + } + + goto fail; + } + + if (uriparser_base_urls != NULL) { + UriUriA tmp = {0}; + + /* Combine the parsed URI with the base URI and store the result in 'tmp', + * since the target and source URLs must be distinct. */ + int result = uriAddBaseUriExMmA(&tmp, &uri, &uriparser_base_urls->uri, URI_RESOLVE_STRICTLY, mm); + if (result != URI_SUCCESS) { + if (!silent) { + switch (result) { + case URI_ERROR_ADDBASE_REL_BASE: + zend_throw_exception(php_uri_ce_invalid_uri_exception, "The specified base URI must be absolute", 0); + break; + default: + /* This should be unreachable in practice. */ + zend_throw_exception(php_uri_ce_error, "Failed to resolve the specified URI against the base URI", 0); + break; + } + } + + goto fail; + } + + /* Store the combined URI back into 'uri'. */ + uriFreeUriMembersMmA(&uri, mm); + uri = tmp; + } + + /* Make the resulting URI independent of the 'uri_str'. */ + uriMakeOwnerMmA(&uri, mm); + + if (has_text_range(&uri.portText) && get_text_range_length(&uri.portText) > 0) { + if (port_str_to_zend_long_checked(uri.portText.first, get_text_range_length(&uri.portText)) == -1) { + if (!silent) { + zend_throw_exception(php_uri_ce_invalid_uri_exception, "The port is out of range", 0); + } + + goto fail; + } + } + + php_uri_parser_rfc3986_uris *uriparser_uris = uriparser_create_uris(); + uriparser_uris->uri = uri; + + return uriparser_uris; + + fail: + + uriFreeUriMembersMmA(&uri, mm); + + return NULL; +} + +void *php_uri_parser_rfc3986_parse(const char *uri_str, size_t uri_str_len, const void *base_url, zval *errors, bool silent) +{ + return php_uri_parser_rfc3986_parse_ex(uri_str, uri_str_len, base_url, silent); +} + +ZEND_ATTRIBUTE_NONNULL static void *php_uri_parser_rfc3986_clone(void *uri) +{ + const php_uri_parser_rfc3986_uris *uriparser_uris = uri; + + php_uri_parser_rfc3986_uris *new_uriparser_uris = uriparser_create_uris(); + copy_uri(&new_uriparser_uris->uri, &uriparser_uris->uri); + /* Do not copy the normalized URI: The expected action after cloning is + * modifying the cloned URI (which will invalidate the cached normalized + * URI). */ + + return new_uriparser_uris; +} + +ZEND_ATTRIBUTE_NONNULL static zend_string *php_uri_parser_rfc3986_to_string(void *uri, php_uri_recomposition_mode recomposition_mode, bool exclude_fragment) +{ + php_uri_parser_rfc3986_uris *uriparser_uris = uri; + const UriUriA *uriparser_uri; + + if (recomposition_mode == PHP_URI_RECOMPOSITION_MODE_RAW_ASCII || recomposition_mode == PHP_URI_RECOMPOSITION_MODE_RAW_UNICODE) { + uriparser_uri = &uriparser_uris->uri; + } else { + uriparser_uri = get_normalized_uri(uriparser_uris); + } + + int charsRequired = 0; + int result = uriToStringCharsRequiredA(uriparser_uri, &charsRequired); + ZEND_ASSERT(result == URI_SUCCESS); + + charsRequired++; + + zend_string *uri_string = zend_string_alloc(charsRequired - 1, false); + result = uriToStringA(ZSTR_VAL(uri_string), uriparser_uri, charsRequired, NULL); + ZEND_ASSERT(result == URI_SUCCESS); + + if (exclude_fragment) { + const char *pos = zend_memrchr(ZSTR_VAL(uri_string), '#', ZSTR_LEN(uri_string)); + if (pos != NULL) { + uri_string = zend_string_truncate(uri_string, (pos - ZSTR_VAL(uri_string)), false); + } + } + + return uri_string; +} + +static void php_uri_parser_rfc3986_destroy(void *uri) +{ + php_uri_parser_rfc3986_uris *uriparser_uris = uri; + + if (UNEXPECTED(uriparser_uris == NULL)) { + return; + } + + uriFreeUriMembersMmA(&uriparser_uris->uri, mm); + uriFreeUriMembersMmA(&uriparser_uris->normalized_uri, mm); + + efree(uriparser_uris); +} + +PHPAPI const php_uri_parser php_uri_parser_rfc3986 = { + .name = PHP_URI_PARSER_RFC3986, + .parse = php_uri_parser_rfc3986_parse, + .clone = php_uri_parser_rfc3986_clone, + .to_string = php_uri_parser_rfc3986_to_string, + .destroy = php_uri_parser_rfc3986_destroy, + { + .scheme = {.read = php_uri_parser_rfc3986_scheme_read, .write = php_uri_parser_rfc3986_scheme_write}, + .username = {.read = php_uri_parser_rfc3986_username_read, .write = NULL}, + .password = {.read = php_uri_parser_rfc3986_password_read, .write = NULL}, + .host = {.read = php_uri_parser_rfc3986_host_read, .write = php_uri_parser_rfc3986_host_write}, + .port = {.read = php_uri_parser_rfc3986_port_read, .write = php_uri_parser_rfc3986_port_write}, + .path = {.read = php_uri_parser_rfc3986_path_read, .write = php_uri_parser_rfc3986_path_write}, + .query = {.read = php_uri_parser_rfc3986_query_read, .write = php_uri_parser_rfc3986_query_write}, + .fragment = {.read = php_uri_parser_rfc3986_fragment_read, .write = php_uri_parser_rfc3986_fragment_write}, + } +}; diff --git a/ext/uri/uri_parser_rfc3986.h b/ext/uri/uri_parser_rfc3986.h new file mode 100644 index 0000000000000..4d88478b6063d --- /dev/null +++ b/ext/uri/uri_parser_rfc3986.h @@ -0,0 +1,31 @@ +/* + +----------------------------------------------------------------------+ + | 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: Máté Kocsis | + +----------------------------------------------------------------------+ +*/ + +#ifndef PHP_URI_PARSER_RFC3986_H +#define PHP_URI_PARSER_RFC3986_H + +#include "php_uri_common.h" + +PHPAPI extern const php_uri_parser php_uri_parser_rfc3986; + +typedef struct php_uri_parser_rfc3986_uris php_uri_parser_rfc3986_uris; + +zend_result php_uri_parser_rfc3986_userinfo_read(php_uri_parser_rfc3986_uris *uri, php_uri_component_read_mode read_mode, zval *retval); +zend_result php_uri_parser_rfc3986_userinfo_write(php_uri_parser_rfc3986_uris *uri, zval *value, zval *errors); + +php_uri_parser_rfc3986_uris *php_uri_parser_rfc3986_parse_ex(const char *uri_str, size_t uri_str_len, const php_uri_parser_rfc3986_uris *uriparser_base_url, bool silent); + +#endif diff --git a/ext/uri/uri_parser_whatwg.c b/ext/uri/uri_parser_whatwg.c new file mode 100644 index 0000000000000..2e9ffad22d463 --- /dev/null +++ b/ext/uri/uri_parser_whatwg.c @@ -0,0 +1,646 @@ +/* + +----------------------------------------------------------------------+ + | 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: Máté Kocsis | + +----------------------------------------------------------------------+ +*/ + +#include "php.h" +#include "uri_parser_whatwg.h" +#include "php_uri_common.h" +#include "Zend/zend_enum.h" +#include "Zend/zend_smart_str.h" +#include "Zend/zend_exceptions.h" +#ifdef HAVE_ARPA_INET_H +#include +#endif + +ZEND_TLS lexbor_mraw_t lexbor_mraw = {0}; +ZEND_TLS lxb_url_parser_t lexbor_parser = {0}; +ZEND_TLS lxb_unicode_idna_t lexbor_idna = {0}; + +static const size_t lexbor_mraw_byte_size = 8192; + +static zend_always_inline void zval_string_or_null_to_lexbor_str(zval *value, lexbor_str_t *lexbor_str) +{ + if (Z_TYPE_P(value) == IS_STRING && Z_STRLEN_P(value) > 0) { + lexbor_str->data = (lxb_char_t *) Z_STRVAL_P(value); + lexbor_str->length = Z_STRLEN_P(value); + } else { + ZEND_ASSERT(Z_ISNULL_P(value) || (Z_TYPE_P(value) == IS_STRING && Z_STRLEN_P(value) == 0)); + lexbor_str->data = (lxb_char_t *) ""; + lexbor_str->length = 0; + } +} + +static zend_always_inline void zval_long_or_null_to_lexbor_str(zval *value, lexbor_str_t *lexbor_str) +{ + if (Z_TYPE_P(value) == IS_LONG) { + ZVAL_STR(value, zend_long_to_str(Z_LVAL_P(value))); + lexbor_str_init_append(lexbor_str, lexbor_parser.mraw, (const lxb_char_t *) Z_STRVAL_P(value), Z_STRLEN_P(value)); + zval_ptr_dtor_str(value); + } else { + ZEND_ASSERT(Z_ISNULL_P(value)); + lexbor_str->data = (lxb_char_t *) ""; + lexbor_str->length = 0; + } +} + +/** + * Creates a Uri\WhatWg\UrlValidationError class by mapping error codes listed in + * https://url.spec.whatwg.org/#writing to a Uri\WhatWg\UrlValidationErrorType enum. + * The result is passed by reference to the errors parameter. + */ +static const char *fill_errors(zval *errors) +{ + if (lexbor_parser.log == NULL || lexbor_plog_length(lexbor_parser.log) == 0) { + ZVAL_EMPTY_ARRAY(errors); + return NULL; + } + + array_init(errors); + const char *result = NULL; + + lexbor_plog_entry_t *lxb_error; + while ((lxb_error = lexbor_array_obj_pop(&lexbor_parser.log->list)) != NULL) { + zval error; + object_init_ex(&error, php_uri_ce_whatwg_url_validation_error); + zend_update_property_string(php_uri_ce_whatwg_url_validation_error, Z_OBJ(error), ZEND_STRL("context"), (const char *) lxb_error->data); + + const char *error_str; + zval failure; + switch (lxb_error->id) { + case LXB_URL_ERROR_TYPE_DOMAIN_TO_ASCII: + error_str = "DomainToAscii"; + ZVAL_TRUE(&failure); + break; + case LXB_URL_ERROR_TYPE_DOMAIN_TO_UNICODE: + error_str = "DomainToUnicode"; + ZVAL_FALSE(&failure); + break; + case LXB_URL_ERROR_TYPE_DOMAIN_INVALID_CODE_POINT: + error_str = "DomainInvalidCodePoint"; + ZVAL_TRUE(&failure); + break; + case LXB_URL_ERROR_TYPE_HOST_INVALID_CODE_POINT: + error_str = "HostInvalidCodePoint"; + ZVAL_TRUE(&failure); + break; + case LXB_URL_ERROR_TYPE_IPV4_EMPTY_PART: + error_str = "Ipv4EmptyPart"; + ZVAL_FALSE(&failure); + break; + case LXB_URL_ERROR_TYPE_IPV4_TOO_MANY_PARTS: + error_str = "Ipv4TooManyParts"; + ZVAL_TRUE(&failure); + break; + case LXB_URL_ERROR_TYPE_IPV4_NON_NUMERIC_PART: + error_str = "Ipv4NonNumericPart"; + ZVAL_TRUE(&failure); + break; + case LXB_URL_ERROR_TYPE_IPV4_NON_DECIMAL_PART: + error_str = "Ipv4NonDecimalPart"; + ZVAL_FALSE(&failure); + break; + case LXB_URL_ERROR_TYPE_IPV4_OUT_OF_RANGE_PART: + error_str = "Ipv4OutOfRangePart"; + ZVAL_TRUE(&failure); + break; + case LXB_URL_ERROR_TYPE_IPV6_UNCLOSED: + error_str = "Ipv6Unclosed"; + ZVAL_TRUE(&failure); + break; + case LXB_URL_ERROR_TYPE_IPV6_INVALID_COMPRESSION: + error_str = "Ipv6InvalidCompression"; + ZVAL_TRUE(&failure); + break; + case LXB_URL_ERROR_TYPE_IPV6_TOO_MANY_PIECES: + error_str = "Ipv6TooManyPieces"; + ZVAL_TRUE(&failure); + break; + case LXB_URL_ERROR_TYPE_IPV6_MULTIPLE_COMPRESSION: + error_str = "Ipv6MultipleCompression"; + ZVAL_TRUE(&failure); + break; + case LXB_URL_ERROR_TYPE_IPV6_INVALID_CODE_POINT: + error_str = "Ipv6InvalidCodePoint"; + ZVAL_TRUE(&failure); + break; + case LXB_URL_ERROR_TYPE_IPV6_TOO_FEW_PIECES: + error_str = "Ipv6TooFewPieces"; + ZVAL_TRUE(&failure); + break; + case LXB_URL_ERROR_TYPE_IPV4_IN_IPV6_TOO_MANY_PIECES: + error_str = "Ipv4InIpv6TooManyPieces"; + ZVAL_TRUE(&failure); + break; + case LXB_URL_ERROR_TYPE_IPV4_IN_IPV6_INVALID_CODE_POINT: + error_str = "Ipv4InIpv6InvalidCodePoint"; + ZVAL_TRUE(&failure); + break; + case LXB_URL_ERROR_TYPE_IPV4_IN_IPV6_OUT_OF_RANGE_PART: + error_str = "Ipv4InIpv6OutOfRangePart"; + ZVAL_TRUE(&failure); + break; + case LXB_URL_ERROR_TYPE_IPV4_IN_IPV6_TOO_FEW_PARTS: + error_str = "Ipv4InIpv6TooFewParts"; + ZVAL_TRUE(&failure); + break; + case LXB_URL_ERROR_TYPE_INVALID_URL_UNIT: + error_str = "InvalidUrlUnit"; + ZVAL_FALSE(&failure); + break; + case LXB_URL_ERROR_TYPE_SPECIAL_SCHEME_MISSING_FOLLOWING_SOLIDUS: + error_str = "SpecialSchemeMissingFollowingSolidus"; + ZVAL_FALSE(&failure); + break; + case LXB_URL_ERROR_TYPE_MISSING_SCHEME_NON_RELATIVE_URL: + error_str = "MissingSchemeNonRelativeUrl"; + ZVAL_TRUE(&failure); + break; + case LXB_URL_ERROR_TYPE_INVALID_REVERSE_SOLIDUS: + error_str = "InvalidReverseSoldius"; + ZVAL_FALSE(&failure); + break; + case LXB_URL_ERROR_TYPE_INVALID_CREDENTIALS: + error_str = "InvalidCredentials"; + ZVAL_FALSE(&failure); + break; + case LXB_URL_ERROR_TYPE_HOST_MISSING: + error_str = "HostMissing"; + ZVAL_TRUE(&failure); + break; + case LXB_URL_ERROR_TYPE_PORT_OUT_OF_RANGE: + error_str = "PortOutOfRange"; + ZVAL_TRUE(&failure); + break; + case LXB_URL_ERROR_TYPE_PORT_INVALID: + error_str = "PortInvalid"; + ZVAL_TRUE(&failure); + break; + case LXB_URL_ERROR_TYPE_FILE_INVALID_WINDOWS_DRIVE_LETTER: + error_str = "FileInvalidWindowsDriveLetter"; + ZVAL_FALSE(&failure); + break; + case LXB_URL_ERROR_TYPE_FILE_INVALID_WINDOWS_DRIVE_LETTER_HOST: + error_str = "FileInvalidWindowsDriveLetterHost"; + ZVAL_FALSE(&failure); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + + zval error_type; + ZVAL_OBJ(&error_type, zend_enum_get_case_cstr(php_uri_ce_whatwg_url_validation_error_type, error_str)); + zend_update_property_ex(php_uri_ce_whatwg_url_validation_error, Z_OBJ(error), ZSTR_KNOWN(ZEND_STR_TYPE), &error_type); + + zend_update_property(php_uri_ce_whatwg_url_validation_error, Z_OBJ(error), ZEND_STRL("failure"), &failure); + + if (Z_TYPE(failure) == IS_TRUE) { + result = error_str; + } + + add_next_index_zval(errors, &error); + } + + return result; +} + +static void throw_invalid_url_exception_during_write(zval *errors, const char *component) +{ + zval err; + const char *reason = fill_errors(&err); + zend_object *exception = zend_throw_exception_ex( + php_uri_ce_whatwg_invalid_url_exception, + 0, + "The specified %s is malformed%s%s%s", + component, + reason ? " (" : "", + reason ? reason : "", + reason ? ")" : "" + ); + zend_update_property(exception->ce, exception, ZEND_STRL("errors"), &err); + if (errors) { + zval_ptr_dtor(errors); + ZVAL_COPY_VALUE(errors, &err); + } else { + zval_ptr_dtor(&err); + } +} + +static lxb_status_t serialize_to_smart_str_callback(const lxb_char_t *data, size_t length, void *ctx) +{ + smart_str *uri_str = ctx; + + if (data != NULL && length > 0) { + smart_str_appendl(uri_str, (const char *) data, length); + } + + return LXB_STATUS_OK; +} + +static zend_result php_uri_parser_whatwg_scheme_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const lxb_url_t *lexbor_uri = uri; + + ZEND_ASSERT(lexbor_uri->scheme.type != LXB_URL_SCHEMEL_TYPE__UNDEF); + + ZVAL_STRINGL(retval, (const char *) lexbor_uri->scheme.name.data, lexbor_uri->scheme.name.length); + + return SUCCESS; +} + +static zend_result php_uri_parser_whatwg_scheme_write(void *uri, zval *value, zval *errors) +{ + lxb_url_t *lexbor_uri = uri; + lexbor_str_t str = {0}; + + zval_string_or_null_to_lexbor_str(value, &str); + + if (lxb_url_api_protocol_set(lexbor_uri, &lexbor_parser, str.data, str.length) != LXB_STATUS_OK) { + throw_invalid_url_exception_during_write(errors, "scheme"); + + return FAILURE; + } + + return SUCCESS; +} + +/* 4.2. URL miscellaneous: A URL includes credentials if its username or password is not the empty string. */ +static bool includes_credentials(const lxb_url_t *lexbor_uri) +{ + return lexbor_uri->username.length > 0 || lexbor_uri->password.length > 0; +} + +static zend_result php_uri_parser_whatwg_username_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const lxb_url_t *lexbor_uri = uri; + + if (includes_credentials(lexbor_uri)) { + ZVAL_STRINGL_FAST(retval, (const char *) lexbor_uri->username.data, lexbor_uri->username.length); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result php_uri_parser_whatwg_username_write(void *uri, zval *value, zval *errors) +{ + lxb_url_t *lexbor_uri = uri; + lexbor_str_t str = {0}; + + zval_string_or_null_to_lexbor_str(value, &str); + + if (lxb_url_api_username_set(lexbor_uri, str.data, str.length) != LXB_STATUS_OK) { + throw_invalid_url_exception_during_write(errors, "username"); + + return FAILURE; + } + + return SUCCESS; +} + +static zend_result php_uri_parser_whatwg_password_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const lxb_url_t *lexbor_uri = uri; + + if (includes_credentials(lexbor_uri)) { + ZVAL_STRINGL_FAST(retval, (const char *) lexbor_uri->password.data, lexbor_uri->password.length); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result php_uri_parser_whatwg_password_write(void *uri, zval *value, zval *errors) +{ + lxb_url_t *lexbor_uri = uri; + lexbor_str_t str = {0}; + + zval_string_or_null_to_lexbor_str(value, &str); + + if (lxb_url_api_password_set(lexbor_uri, str.data, str.length) != LXB_STATUS_OK) { + throw_invalid_url_exception_during_write(errors, "password"); + + return FAILURE; + } + + return SUCCESS; +} + +static zend_result php_uri_parser_whatwg_host_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const lxb_url_t *lexbor_uri = uri; + + if (lexbor_uri->host.type == LXB_URL_HOST_TYPE_IPV4) { + smart_str host_str = {0}; + + lxb_url_serialize_host_ipv4(lexbor_uri->host.u.ipv4, serialize_to_smart_str_callback, &host_str); + + ZVAL_NEW_STR(retval, smart_str_extract(&host_str)); + } else if (lexbor_uri->host.type == LXB_URL_HOST_TYPE_IPV6) { + smart_str host_str = {0}; + + smart_str_appendc(&host_str, '['); + lxb_url_serialize_host_ipv6(lexbor_uri->host.u.ipv6, serialize_to_smart_str_callback, &host_str); + smart_str_appendc(&host_str, ']'); + + ZVAL_NEW_STR(retval, smart_str_extract(&host_str)); + } else if (lexbor_uri->host.type == LXB_URL_HOST_TYPE_EMPTY) { + ZVAL_EMPTY_STRING(retval); + } else if (lexbor_uri->host.type != LXB_URL_HOST_TYPE__UNDEF) { + switch (read_mode) { + case PHP_URI_COMPONENT_READ_MODE_NORMALIZED_UNICODE: { + smart_str host_str = {0}; + lxb_url_serialize_host_unicode(&lexbor_idna, &lexbor_uri->host, serialize_to_smart_str_callback, &host_str); + lxb_unicode_idna_clean(&lexbor_idna); + + ZVAL_NEW_STR(retval, smart_str_extract(&host_str)); + break; + } + case PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII: + ZEND_FALLTHROUGH; + case PHP_URI_COMPONENT_READ_MODE_RAW: + ZVAL_STRINGL(retval, (const char *) lexbor_uri->host.u.domain.data, lexbor_uri->host.u.domain.length); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result php_uri_parser_whatwg_host_write(void *uri, zval *value, zval *errors) +{ + lxb_url_t *lexbor_uri = uri; + lexbor_str_t str = {0}; + + zval_string_or_null_to_lexbor_str(value, &str); + + if (lxb_url_api_hostname_set(lexbor_uri, &lexbor_parser, str.data, str.length) != LXB_STATUS_OK) { + throw_invalid_url_exception_during_write(errors, "host"); + + return FAILURE; + } + + return SUCCESS; +} + +static zend_result php_uri_parser_whatwg_port_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const lxb_url_t *lexbor_uri = uri; + + if (lexbor_uri->has_port) { + ZVAL_LONG(retval, lexbor_uri->port); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result php_uri_parser_whatwg_port_write(void *uri, zval *value, zval *errors) +{ + lxb_url_t *lexbor_uri = uri; + lexbor_str_t str = {0}; + + zval_long_or_null_to_lexbor_str(value, &str); + + if (lxb_url_api_port_set(lexbor_uri, &lexbor_parser, str.data, str.length) != LXB_STATUS_OK) { + throw_invalid_url_exception_during_write(errors, "port"); + + return FAILURE; + } + + return SUCCESS; +} + +static zend_result php_uri_parser_whatwg_path_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const lxb_url_t *lexbor_uri = uri; + + if (lexbor_uri->path.str.length > 0) { + ZVAL_STRINGL(retval, (const char *) lexbor_uri->path.str.data, lexbor_uri->path.str.length); + } else { + ZVAL_EMPTY_STRING(retval); + } + + return SUCCESS; +} + +static zend_result php_uri_parser_whatwg_path_write(void *uri, zval *value, zval *errors) +{ + lxb_url_t *lexbor_uri = uri; + lexbor_str_t str = {0}; + + zval_string_or_null_to_lexbor_str(value, &str); + + if (lxb_url_api_pathname_set(lexbor_uri, &lexbor_parser, str.data, str.length) != LXB_STATUS_OK) { + throw_invalid_url_exception_during_write(errors, "path"); + + return FAILURE; + } + + return SUCCESS; +} + +static zend_result php_uri_parser_whatwg_query_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const lxb_url_t *lexbor_uri = uri; + + if (lexbor_uri->query.data != NULL) { + ZVAL_STRINGL(retval, (const char *) lexbor_uri->query.data, lexbor_uri->query.length); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result php_uri_parser_whatwg_query_write(void *uri, zval *value, zval *errors) +{ + lxb_url_t *lexbor_uri = uri; + lexbor_str_t str = {0}; + + zval_string_or_null_to_lexbor_str(value, &str); + + if (lxb_url_api_search_set(lexbor_uri, &lexbor_parser, str.data, str.length) != LXB_STATUS_OK) { + throw_invalid_url_exception_during_write(errors, "query string"); + + return FAILURE; + } + + return SUCCESS; +} + +static zend_result php_uri_parser_whatwg_fragment_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +{ + const lxb_url_t *lexbor_uri = uri; + + if (lexbor_uri->fragment.data != NULL) { + ZVAL_STRINGL(retval, (const char *) lexbor_uri->fragment.data, lexbor_uri->fragment.length); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result php_uri_parser_whatwg_fragment_write(void *uri, zval *value, zval *errors) +{ + lxb_url_t *lexbor_uri = uri; + lexbor_str_t str = {0}; + + zval_string_or_null_to_lexbor_str(value, &str); + + if (lxb_url_api_hash_set(lexbor_uri, &lexbor_parser, str.data, str.length) != LXB_STATUS_OK) { + throw_invalid_url_exception_during_write(errors, "fragment"); + + return FAILURE; + } + + return SUCCESS; +} + +PHP_RINIT_FUNCTION(uri_parser_whatwg) +{ + lxb_status_t status; + + status = lexbor_mraw_init(&lexbor_mraw, lexbor_mraw_byte_size); + if (status != LXB_STATUS_OK) { + goto fail; + } + + status = lxb_url_parser_init(&lexbor_parser, &lexbor_mraw); + if (status != LXB_STATUS_OK) { + goto fail; + } + + status = lxb_unicode_idna_init(&lexbor_idna); + if (status != LXB_STATUS_OK) { + goto fail; + } + + return SUCCESS; + + fail: + + /* Unconditionally calling the _destroy() functions is + * safe on a zeroed structure. */ + lxb_unicode_idna_destroy(&lexbor_idna, false); + memset(&lexbor_idna, 0, sizeof(lexbor_idna)); + lxb_url_parser_destroy(&lexbor_parser, false); + memset(&lexbor_parser, 0, sizeof(lexbor_parser)); + lexbor_mraw_destroy(&lexbor_mraw, false); + memset(&lexbor_mraw, 0, sizeof(lexbor_mraw)); + + return FAILURE; +} + +ZEND_MODULE_POST_ZEND_DEACTIVATE_D(uri_parser_whatwg) +{ + lxb_unicode_idna_destroy(&lexbor_idna, false); + memset(&lexbor_idna, 0, sizeof(lexbor_idna)); + lxb_url_parser_destroy(&lexbor_parser, false); + memset(&lexbor_parser, 0, sizeof(lexbor_parser)); + lexbor_mraw_destroy(&lexbor_mraw, false); + memset(&lexbor_mraw, 0, sizeof(lexbor_mraw)); + + return SUCCESS; +} + +lxb_url_t *php_uri_parser_whatwg_parse_ex(const char *uri_str, size_t uri_str_len, const lxb_url_t *lexbor_base_url, zval *errors, bool silent) +{ + lxb_url_parser_clean(&lexbor_parser); + + lxb_url_t *url = lxb_url_parse(&lexbor_parser, lexbor_base_url, (unsigned char *) uri_str, uri_str_len); + + if ((url == NULL && !silent) || errors != NULL) { + zval err; + const char *reason = fill_errors(&err); + if (url == NULL && !silent) { + zend_object *exception = zend_throw_exception_ex(php_uri_ce_whatwg_invalid_url_exception, 0, "The specified URI is malformed%s%s%s", reason ? " (" : "", reason ? reason : "", reason ? ")" : ""); + zend_update_property(exception->ce, exception, ZEND_STRL("errors"), &err); + } + if (errors != NULL) { + zval_ptr_dtor(errors); + ZVAL_COPY_VALUE(errors, &err); + } else { + zval_ptr_dtor(&err); + } + } + + return url; +} + +static void *php_uri_parser_whatwg_parse(const char *uri_str, size_t uri_str_len, const void *base_url, zval *errors, bool silent) +{ + return php_uri_parser_whatwg_parse_ex(uri_str, uri_str_len, base_url, errors, silent); +} + +static void *php_uri_parser_whatwg_clone(void *uri) +{ + const lxb_url_t *lexbor_uri = uri; + + return lxb_url_clone(lexbor_parser.mraw, lexbor_uri); +} + +static zend_string *php_uri_parser_whatwg_to_string(void *uri, php_uri_recomposition_mode recomposition_mode, bool exclude_fragment) +{ + const lxb_url_t *lexbor_uri = uri; + smart_str uri_str = {0}; + + switch (recomposition_mode) { + case PHP_URI_RECOMPOSITION_MODE_RAW_UNICODE: + ZEND_FALLTHROUGH; + case PHP_URI_RECOMPOSITION_MODE_NORMALIZED_UNICODE: + lxb_url_serialize_idna(&lexbor_idna, lexbor_uri, serialize_to_smart_str_callback, &uri_str, exclude_fragment); + lxb_unicode_idna_clean(&lexbor_idna); + break; + case PHP_URI_RECOMPOSITION_MODE_RAW_ASCII: + ZEND_FALLTHROUGH; + case PHP_URI_RECOMPOSITION_MODE_NORMALIZED_ASCII: + lxb_url_serialize(lexbor_uri, serialize_to_smart_str_callback, &uri_str, exclude_fragment); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + + return smart_str_extract(&uri_str); +} + +static void php_uri_parser_whatwg_destroy(void *uri) +{ + lxb_url_t *lexbor_uri = uri; + + lxb_url_destroy(lexbor_uri); +} + +PHPAPI const php_uri_parser php_uri_parser_whatwg = { + .name = PHP_URI_PARSER_WHATWG, + .parse = php_uri_parser_whatwg_parse, + .clone = php_uri_parser_whatwg_clone, + .to_string = php_uri_parser_whatwg_to_string, + .destroy = php_uri_parser_whatwg_destroy, + { + .scheme = {.read = php_uri_parser_whatwg_scheme_read, .write = php_uri_parser_whatwg_scheme_write}, + .username = {.read = php_uri_parser_whatwg_username_read, .write = php_uri_parser_whatwg_username_write}, + .password = {.read = php_uri_parser_whatwg_password_read, .write = php_uri_parser_whatwg_password_write}, + .host = {.read = php_uri_parser_whatwg_host_read, .write = php_uri_parser_whatwg_host_write}, + .port = {.read = php_uri_parser_whatwg_port_read, .write = php_uri_parser_whatwg_port_write}, + .path = {.read = php_uri_parser_whatwg_path_read, .write = php_uri_parser_whatwg_path_write}, + .query = {.read = php_uri_parser_whatwg_query_read, .write = php_uri_parser_whatwg_query_write}, + .fragment = {.read = php_uri_parser_whatwg_fragment_read, .write = php_uri_parser_whatwg_fragment_write}, + } +}; diff --git a/ext/uri/uri_parser_whatwg.h b/ext/uri/uri_parser_whatwg.h new file mode 100644 index 0000000000000..e8bbb585fd665 --- /dev/null +++ b/ext/uri/uri_parser_whatwg.h @@ -0,0 +1,30 @@ +/* + +----------------------------------------------------------------------+ + | 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: Máté Kocsis | + +----------------------------------------------------------------------+ +*/ + +#ifndef PHP_URI_PARSER_WHATWG_H +#define PHP_URI_PARSER_WHATWG_H + +#include "php_uri_common.h" +#include "lexbor/url/url.h" + +PHPAPI extern const php_uri_parser php_uri_parser_whatwg; + +lxb_url_t *php_uri_parser_whatwg_parse_ex(const char *uri_str, size_t uri_str_len, const lxb_url_t *lexbor_base_url, zval *errors, bool silent); + +PHP_RINIT_FUNCTION(uri_parser_whatwg); +ZEND_MODULE_POST_ZEND_DEACTIVATE_D(uri_parser_whatwg); + +#endif diff --git a/ext/uri/uriparser/COPYING b/ext/uri/uriparser/COPYING.BSD-3-Clause similarity index 100% rename from ext/uri/uriparser/COPYING rename to ext/uri/uriparser/COPYING.BSD-3-Clause diff --git a/ext/uri/uriparser/include/uriparser/COPYING b/ext/uri/uriparser/include/uriparser/COPYING new file mode 100644 index 0000000000000..261c741da0fba --- /dev/null +++ b/ext/uri/uriparser/include/uriparser/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/include/uriparser/Uri.h b/ext/uri/uriparser/include/uriparser/Uri.h index 9f08559a1858f..88976a4846271 100644 --- a/ext/uri/uriparser/include/uriparser/Uri.h +++ b/ext/uri/uriparser/include/uriparser/Uri.h @@ -1,4 +1,4 @@ -/* e8e2c75d033ddfe256fe87c3fd5a330a6f2c9cbb376ebd83a1b3263e804c766a (0.9.8+) +/* 5abed1007be99942f49ffe603a894d277066b79b9cb824547af0f3b9481cb9ca (1.0.0+) * * uriparser - RFC 3986 URI parsing library * @@ -45,47 +45,41 @@ */ #if (defined(URI_PASS_ANSI) && !defined(URI_H_ANSI)) \ - || (defined(URI_PASS_UNICODE) && !defined(URI_H_UNICODE)) \ - || (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) + || (defined(URI_PASS_UNICODE) && !defined(URI_H_UNICODE)) \ + || (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) /* What encodings are enabled? */ -#include "UriDefsConfig.h" -#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +# include "UriDefsConfig.h" +# if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) /* Include SELF twice */ -# ifdef URI_ENABLE_ANSI -# define URI_PASS_ANSI 1 -# include "Uri.h" -# undef URI_PASS_ANSI -# endif -# ifdef URI_ENABLE_UNICODE -# define URI_PASS_UNICODE 1 -# include "Uri.h" -# undef URI_PASS_UNICODE -# endif +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "Uri.h" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "Uri.h" +# undef URI_PASS_UNICODE +# endif /* Only one pass for each encoding */ -#elif (defined(URI_PASS_ANSI) && !defined(URI_H_ANSI) \ - && defined(URI_ENABLE_ANSI)) || (defined(URI_PASS_UNICODE) \ - && !defined(URI_H_UNICODE) && defined(URI_ENABLE_UNICODE)) -# ifdef URI_PASS_ANSI -# define URI_H_ANSI 1 -# include "UriDefsAnsi.h" -# else -# define URI_H_UNICODE 1 -# include "UriDefsUnicode.h" -# endif - - - -#ifdef __cplusplus +# elif (defined(URI_PASS_ANSI) && !defined(URI_H_ANSI) && defined(URI_ENABLE_ANSI)) \ + || (defined(URI_PASS_UNICODE) && !defined(URI_H_UNICODE) \ + && defined(URI_ENABLE_UNICODE)) +# ifdef URI_PASS_ANSI +# define URI_H_ANSI 1 +# include "UriDefsAnsi.h" +# else +# define URI_H_UNICODE 1 +# include "UriDefsUnicode.h" +# endif + +# ifdef __cplusplus extern "C" { -#endif - - - -#ifndef URI_DOXYGEN -# include "UriBase.h" -#endif - +# endif +# ifndef URI_DOXYGEN +# include "UriBase.h" +# endif /** * Specifies a range of characters within a string. @@ -99,12 +93,10 @@ extern "C" { * @since 0.3.0 */ typedef struct URI_TYPE(TextRangeStruct) { - const URI_CHAR * first; /**< Pointer to first character */ - const URI_CHAR * afterLast; /**< Pointer to character after the last one still in */ + const URI_CHAR * first; /**< Pointer to first character */ + const URI_CHAR * afterLast; /**< Pointer to character after the last one still in */ } URI_TYPE(TextRange); /**< @copydoc UriTextRangeStructA */ - - /** * Represents a path segment within a %URI path. * More precisely it is a node in a linked @@ -114,14 +106,13 @@ typedef struct URI_TYPE(TextRangeStruct) { * @since 0.3.0 */ typedef struct URI_TYPE(PathSegmentStruct) { - URI_TYPE(TextRange) text; /**< Path segment name */ - struct URI_TYPE(PathSegmentStruct) * next; /**< Pointer to the next path segment in the list, can be NULL if last already */ + URI_TYPE(TextRange) text; /**< Path segment name */ + struct URI_TYPE(PathSegmentStruct) * next; /**< Pointer to the next path segment in + the list, can be NULL if last already */ - void * reserved; /**< Reserved to the parser */ + void * reserved; /**< Reserved to the parser */ } URI_TYPE(PathSegment); /**< @copydoc UriPathSegmentStructA */ - - /** * Holds structured host information. * This is either a IPv4, IPv6, plain @@ -132,13 +123,16 @@ typedef struct URI_TYPE(PathSegmentStruct) { * @since 0.3.0 */ typedef struct URI_TYPE(HostDataStruct) { - UriIp4 * ip4; /**< IPv4 address */ - UriIp6 * ip6; /**< IPv6 address */ - URI_TYPE(TextRange) ipFuture; /**< IPvFuture address */ + UriIp4 * ip4; /**< IPv4 address */ + UriIp6 * ip6; /**< IPv6 address */ + URI_TYPE(TextRange) + ipFuture; /**< IPvFuture address +@note +With non-NULL members in UriUriStructA.hostData context, +this text range's pointers must be identical to those +of UriUriStructA.hostText at all times. */ } URI_TYPE(HostData); /**< @copydoc UriHostDataStructA */ - - /** * Represents an RFC 3986 %URI. * Missing components can be {NULL, NULL} ranges. @@ -149,24 +143,23 @@ typedef struct URI_TYPE(HostDataStruct) { * @since 0.3.0 */ typedef struct URI_TYPE(UriStruct) { - URI_TYPE(TextRange) scheme; /**< Scheme (e.g. "http") */ - URI_TYPE(TextRange) userInfo; /**< User info (e.g. "user:pass") */ - URI_TYPE(TextRange) hostText; /**< Host text (set for all hosts, excluding square brackets) */ - URI_TYPE(HostData) hostData; /**< Structured host type specific data */ - URI_TYPE(TextRange) portText; /**< Port (e.g. "80") */ - URI_TYPE(PathSegment) * pathHead; /**< Head of a linked list of path segments */ - URI_TYPE(PathSegment) * pathTail; /**< Tail of the list behind pathHead */ - URI_TYPE(TextRange) query; /**< Query without leading "?" */ - URI_TYPE(TextRange) fragment; /**< Query without leading "#" */ - UriBool absolutePath; /**< Absolute path flag, distincting "a" and "/a"; - always URI_FALSE for URIs with host */ - UriBool owner; /**< Memory owner flag */ - - void * reserved; /**< Reserved to the parser */ + URI_TYPE(TextRange) scheme; /**< Scheme (e.g. "http") */ + URI_TYPE(TextRange) userInfo; /**< User info (e.g. "user:pass") */ + URI_TYPE(TextRange) + hostText; /**< Host text (set for all hosts, excluding square brackets) */ + URI_TYPE(HostData) hostData; /**< Structured host type specific data */ + URI_TYPE(TextRange) portText; /**< Port (e.g. "80") */ + URI_TYPE(PathSegment) * pathHead; /**< Head of a linked list of path segments */ + URI_TYPE(PathSegment) * pathTail; /**< Tail of the list behind pathHead */ + URI_TYPE(TextRange) query; /**< Query without leading "?" */ + URI_TYPE(TextRange) fragment; /**< Query without leading "#" */ + UriBool absolutePath; /**< Absolute path flag, distincting "a" and "/a"; always + URI_FALSE for URIs with host */ + UriBool owner; /**< Memory owner flag */ + + void * reserved; /**< Reserved to the parser */ } URI_TYPE(Uri); /**< @copydoc UriUriStructA */ - - /** * Represents a state of the %URI parser. * Missing components can be NULL to reflect @@ -177,15 +170,14 @@ typedef struct URI_TYPE(UriStruct) { * @since 0.3.0 */ typedef struct URI_TYPE(ParserStateStruct) { - URI_TYPE(Uri) * uri; /**< Plug in the %URI structure to be filled while parsing here */ - int errorCode; /**< Code identifying the error which occurred */ - const URI_CHAR * errorPos; /**< Pointer to position in case of a syntax error */ + URI_TYPE(Uri) + *uri; /**< Plug in the %URI structure to be filled while parsing here */ + int errorCode; /**< Code identifying the error which occurred */ + const URI_CHAR * errorPos; /**< Pointer to position in case of a syntax error */ - void * reserved; /**< Reserved to the parser */ + void * reserved; /**< Reserved to the parser */ } URI_TYPE(ParserState); /**< @copydoc UriParserStateStructA */ - - /** * Represents a query element. * More precisely it is a node in a linked @@ -194,13 +186,13 @@ typedef struct URI_TYPE(ParserStateStruct) { * @since 0.7.0 */ typedef struct URI_TYPE(QueryListStruct) { - const URI_CHAR * key; /**< Key of the query element */ - const URI_CHAR * value; /**< Value of the query element, can be NULL */ + const URI_CHAR * key; /**< Key of the query element */ + const URI_CHAR * value; /**< Value of the query element, can be NULL */ - struct URI_TYPE(QueryListStruct) * next; /**< Pointer to the next key/value pair in the list, can be NULL if last already */ + struct URI_TYPE(QueryListStruct) * next; /**< Pointer to the next key/value pair in + the list, can be NULL if last already */ } URI_TYPE(QueryList); /**< @copydoc UriQueryListStructA */ - /** * Checks if a URI has the host component set. * @@ -211,7 +203,41 @@ typedef struct URI_TYPE(QueryListStruct) { */ 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. @@ -219,7 +245,8 @@ URI_PUBLIC UriBool URI_FUNC(HasHost)(const URI_TYPE(Uri) * uri); * * @param state INOUT: Parser state with set output %URI, must not be NULL * @param first IN: Pointer to the first character to parse, must not be NULL - * @param afterLast IN: Pointer to the character after the last to parse, must not be NULL + * @param afterLast IN: Pointer to the character after the last to parse, must + * not be NULL * @return 0 on success, error code otherwise * * @see uriParseUriA @@ -227,12 +254,11 @@ URI_PUBLIC UriBool URI_FUNC(HasHost)(const URI_TYPE(Uri) * uri); * @see uriParseSingleUriExA * @see uriToStringA * @since 0.3.0 - * @deprecated Deprecated since 0.9.0, please migrate to uriParseSingleUriExA (with "Single"). + * @deprecated Deprecated since 0.9.0, please migrate to uriParseSingleUriExA (with + * "Single"). */ -URI_PUBLIC int URI_FUNC(ParseUriEx)(URI_TYPE(ParserState) * state, - const URI_CHAR * first, const URI_CHAR * afterLast); - - +URI_PUBLIC int URI_FUNC(ParseUriEx)(URI_TYPE(ParserState) * state, const URI_CHAR * first, + const URI_CHAR * afterLast); /** * Parses a RFC 3986 %URI. @@ -247,12 +273,10 @@ URI_PUBLIC int URI_FUNC(ParseUriEx)(URI_TYPE(ParserState) * state, * @see uriParseSingleUriExA * @see uriToStringA * @since 0.3.0 - * @deprecated Deprecated since 0.9.0, please migrate to uriParseSingleUriA (with "Single"). + * @deprecated Deprecated since 0.9.0, please migrate to uriParseSingleUriA (with + * "Single"). */ -URI_PUBLIC int URI_FUNC(ParseUri)(URI_TYPE(ParserState) * state, - const URI_CHAR * text); - - +URI_PUBLIC int URI_FUNC(ParseUri)(URI_TYPE(ParserState) * state, const URI_CHAR * text); /** * Parses a single RFC 3986 %URI. @@ -271,10 +295,8 @@ URI_PUBLIC int URI_FUNC(ParseUri)(URI_TYPE(ParserState) * state, * @see uriToStringA * @since 0.9.0 */ -URI_PUBLIC int URI_FUNC(ParseSingleUri)(URI_TYPE(Uri) * uri, - const URI_CHAR * text, const URI_CHAR ** errorPos); - - +URI_PUBLIC int URI_FUNC(ParseSingleUri)(URI_TYPE(Uri) * uri, const URI_CHAR * text, + const URI_CHAR ** errorPos); /** * Parses a single RFC 3986 %URI. @@ -296,11 +318,9 @@ URI_PUBLIC int URI_FUNC(ParseSingleUri)(URI_TYPE(Uri) * uri, * @see uriToStringA * @since 0.9.0 */ -URI_PUBLIC int URI_FUNC(ParseSingleUriEx)(URI_TYPE(Uri) * uri, - const URI_CHAR * first, const URI_CHAR * afterLast, - const URI_CHAR ** errorPos); - - +URI_PUBLIC int URI_FUNC(ParseSingleUriEx)(URI_TYPE(Uri) * uri, const URI_CHAR * first, + const URI_CHAR * afterLast, + const URI_CHAR ** errorPos); /** * Parses a single RFC 3986 %URI. @@ -322,11 +342,10 @@ URI_PUBLIC int URI_FUNC(ParseSingleUriEx)(URI_TYPE(Uri) * uri, * @see uriToStringA * @since 0.9.0 */ -URI_PUBLIC int URI_FUNC(ParseSingleUriExMm)(URI_TYPE(Uri) * uri, - const URI_CHAR * first, const URI_CHAR * afterLast, - const URI_CHAR ** errorPos, UriMemoryManager * memory); - - +URI_PUBLIC int URI_FUNC(ParseSingleUriExMm)(URI_TYPE(Uri) * uri, const URI_CHAR * first, + const URI_CHAR * afterLast, + const URI_CHAR ** errorPos, + UriMemoryManager * memory); /** * Frees all memory associated with the members @@ -335,8 +354,8 @@ URI_PUBLIC int URI_FUNC(ParseSingleUriExMm)(URI_TYPE(Uri) * uri, * 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. + * 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 * @@ -345,16 +364,14 @@ URI_PUBLIC int URI_FUNC(ParseSingleUriExMm)(URI_TYPE(Uri) * uri, */ URI_PUBLIC void URI_FUNC(FreeUriMembers)(URI_TYPE(Uri) * uri); - - /** * Frees all memory associated with the members * 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. + * 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 @@ -363,10 +380,7 @@ URI_PUBLIC void URI_FUNC(FreeUriMembers)(URI_TYPE(Uri) * uri); * @see uriFreeUriMembersA * @since 0.9.0 */ -URI_PUBLIC int URI_FUNC(FreeUriMembersMm)(URI_TYPE(Uri) * uri, - UriMemoryManager * memory); - - +URI_PUBLIC int URI_FUNC(FreeUriMembersMm)(URI_TYPE(Uri) * uri, UriMemoryManager * memory); /** * Percent-encodes all but unreserved characters from the input string and @@ -397,10 +411,8 @@ URI_PUBLIC int URI_FUNC(FreeUriMembersMm)(URI_TYPE(Uri) * uri, * @since 0.5.2 */ URI_PUBLIC URI_CHAR * URI_FUNC(EscapeEx)(const URI_CHAR * inFirst, - const URI_CHAR * inAfterLast, URI_CHAR * out, - UriBool spaceToPlus, UriBool normalizeBreaks); - - + const URI_CHAR * inAfterLast, URI_CHAR * out, + UriBool spaceToPlus, UriBool normalizeBreaks); /** * Percent-encodes all but unreserved characters from the input string and @@ -430,9 +442,7 @@ URI_PUBLIC URI_CHAR * URI_FUNC(EscapeEx)(const URI_CHAR * inFirst, * @since 0.5.0 */ URI_PUBLIC URI_CHAR * URI_FUNC(Escape)(const URI_CHAR * in, URI_CHAR * out, - UriBool spaceToPlus, UriBool normalizeBreaks); - - + UriBool spaceToPlus, UriBool normalizeBreaks); /** * Unescapes percent-encoded groups in a given string. @@ -451,10 +461,9 @@ URI_PUBLIC URI_CHAR * URI_FUNC(Escape)(const URI_CHAR * in, URI_CHAR * out, * @see uriEscapeExA * @since 0.5.0 */ -URI_PUBLIC const URI_CHAR * URI_FUNC(UnescapeInPlaceEx)(URI_CHAR * inout, - UriBool plusToSpace, UriBreakConversion breakConversion); - - +URI_PUBLIC const URI_CHAR * + URI_FUNC(UnescapeInPlaceEx)(URI_CHAR * inout, UriBool plusToSpace, + UriBreakConversion breakConversion); /** * Unescapes percent-encoded groups in a given string. @@ -476,13 +485,11 @@ URI_PUBLIC const URI_CHAR * URI_FUNC(UnescapeInPlaceEx)(URI_CHAR * inout, */ URI_PUBLIC const URI_CHAR * URI_FUNC(UnescapeInPlace)(URI_CHAR * inout); - - /** * Performs reference resolution as described in - *
section 5.2.2 of RFC 3986. - * Uses default libc-based memory manager. - * NOTE: On success you have to call uriFreeUriMembersA on \p absoluteDest manually later. + * section 5.2.2 of + * RFC 3986. Uses default libc-based memory manager. NOTE: On success you have to call + * uriFreeUriMembersA on \p absoluteDest manually later. * * @param absoluteDest OUT: Result %URI * @param relativeSource IN: Reference to resolve @@ -496,16 +503,14 @@ URI_PUBLIC const URI_CHAR * URI_FUNC(UnescapeInPlace)(URI_CHAR * inout); * @since 0.4.0 */ URI_PUBLIC int URI_FUNC(AddBaseUri)(URI_TYPE(Uri) * absoluteDest, - const URI_TYPE(Uri) * relativeSource, - const URI_TYPE(Uri) * absoluteBase); - - + const URI_TYPE(Uri) * relativeSource, + const URI_TYPE(Uri) * absoluteBase); /** * Performs reference resolution as described in - * section 5.2.2 of RFC 3986. - * Uses default libc-based memory manager. - * NOTE: On success you have to call uriFreeUriMembersA on \p absoluteDest manually later. + * section 5.2.2 of + * RFC 3986. Uses default libc-based memory manager. NOTE: On success you have to call + * uriFreeUriMembersA on \p absoluteDest manually later. * * @param absoluteDest OUT: Result %URI * @param relativeSource IN: Reference to resolve @@ -519,16 +524,15 @@ URI_PUBLIC int URI_FUNC(AddBaseUri)(URI_TYPE(Uri) * absoluteDest, * @since 0.8.1 */ URI_PUBLIC int URI_FUNC(AddBaseUriEx)(URI_TYPE(Uri) * absoluteDest, - const URI_TYPE(Uri) * relativeSource, - const URI_TYPE(Uri) * absoluteBase, - UriResolutionOptions options); - - + const URI_TYPE(Uri) * relativeSource, + const URI_TYPE(Uri) * absoluteBase, + UriResolutionOptions options); /** * Performs reference resolution as described in - * section 5.2.2 of RFC 3986. - * NOTE: On success you have to call uriFreeUriMembersMmA on \p absoluteDest manually later. + * section 5.2.2 of + * RFC 3986. NOTE: On success you have to call uriFreeUriMembersMmA on \p absoluteDest + * manually later. * * @param absoluteDest OUT: Result %URI * @param relativeSource IN: Reference to resolve @@ -544,11 +548,10 @@ URI_PUBLIC int URI_FUNC(AddBaseUriEx)(URI_TYPE(Uri) * absoluteDest, * @since 0.9.0 */ URI_PUBLIC int URI_FUNC(AddBaseUriExMm)(URI_TYPE(Uri) * absoluteDest, - const URI_TYPE(Uri) * relativeSource, - const URI_TYPE(Uri) * absoluteBase, - UriResolutionOptions options, UriMemoryManager * memory); - - + const URI_TYPE(Uri) * relativeSource, + const URI_TYPE(Uri) * absoluteBase, + UriResolutionOptions options, + UriMemoryManager * memory); /** * Tries to make a relative %URI (a reference) from an @@ -573,11 +576,9 @@ URI_PUBLIC int URI_FUNC(AddBaseUriExMm)(URI_TYPE(Uri) * absoluteDest, * @since 0.5.2 */ URI_PUBLIC int URI_FUNC(RemoveBaseUri)(URI_TYPE(Uri) * dest, - const URI_TYPE(Uri) * absoluteSource, - const URI_TYPE(Uri) * absoluteBase, - UriBool domainRootMode); - - + const URI_TYPE(Uri) * absoluteSource, + const URI_TYPE(Uri) * absoluteBase, + UriBool domainRootMode); /** * Tries to make a relative %URI (a reference) from an @@ -602,11 +603,10 @@ URI_PUBLIC int URI_FUNC(RemoveBaseUri)(URI_TYPE(Uri) * dest, * @since 0.9.0 */ URI_PUBLIC int URI_FUNC(RemoveBaseUriMm)(URI_TYPE(Uri) * dest, - const URI_TYPE(Uri) * absoluteSource, - const URI_TYPE(Uri) * absoluteBase, - UriBool domainRootMode, UriMemoryManager * memory); - - + const URI_TYPE(Uri) * absoluteSource, + const URI_TYPE(Uri) * absoluteBase, + UriBool domainRootMode, + UriMemoryManager * memory); /** * Checks two URIs for equivalence. Comparison is done @@ -619,10 +619,7 @@ URI_PUBLIC int URI_FUNC(RemoveBaseUriMm)(URI_TYPE(Uri) * dest, * * @since 0.4.0 */ -URI_PUBLIC UriBool URI_FUNC(EqualsUri)(const URI_TYPE(Uri) * a, - const URI_TYPE(Uri) * b); - - +URI_PUBLIC UriBool URI_FUNC(EqualsUri)(const URI_TYPE(Uri) * a, const URI_TYPE(Uri) * b); /** * Calculates the number of characters needed to store the @@ -630,38 +627,39 @@ URI_PUBLIC UriBool URI_FUNC(EqualsUri)(const URI_TYPE(Uri) * a, * terminator. * * @param uri IN: %URI to measure - * @param charsRequired OUT: Length of the string representation in characters excluding terminator + * @param charsRequired OUT: Length of the string representation in characters + * excluding terminator * @return Error code or 0 on success * * @see uriToStringA * @since 0.5.0 */ URI_PUBLIC int URI_FUNC(ToStringCharsRequired)(const URI_TYPE(Uri) * uri, - int * charsRequired); - - + int * charsRequired); /** * Converts a %URI structure back to text as described in - * section 5.3 of RFC 3986. + * section 5.3 of RFC + * 3986. * * NOTE: Scheme-based normalization - * (section 6.2.3 of RFC 3986) - * is not applied and is considered a responsibility of the application using uriparser. + * (section 6.2.3 of + * RFC 3986) is not applied and is considered a responsibility of the application + * using uriparser. * * @param dest OUT: Output destination * @param uri IN: %URI to convert - * @param maxChars IN: Maximum number of characters to copy including terminator - * @param charsWritten OUT: Number of characters written, can be lower than maxChars even if the %URI is too long! + * @param maxChars IN: Maximum number of characters to copy including + * terminator + * @param charsWritten OUT: Number of characters written, can be lower than + * maxChars even if the %URI is too long! * @return Error code or 0 on success * * @see uriToStringCharsRequiredA * @since 0.4.0 */ URI_PUBLIC int URI_FUNC(ToString)(URI_CHAR * dest, const URI_TYPE(Uri) * uri, - int maxChars, int * charsWritten); - - + int maxChars, int * charsWritten); /** * Copies a %URI structure. @@ -675,9 +673,8 @@ URI_PUBLIC int URI_FUNC(ToString)(URI_CHAR * dest, const URI_TYPE(Uri) * uri, * @since 0.9.9 */ URI_PUBLIC int URI_FUNC(CopyUriMm)(URI_TYPE(Uri) * destUri, - const URI_TYPE(Uri) * sourceUri, UriMemoryManager * memory); - - + const URI_TYPE(Uri) * sourceUri, + UriMemoryManager * memory); /** * Copies a %URI structure. @@ -689,9 +686,8 @@ URI_PUBLIC int URI_FUNC(CopyUriMm)(URI_TYPE(Uri) * destUri, * @see uriCopyUriMmA * @since 0.9.9 */ -URI_PUBLIC int URI_FUNC(CopyUri)(URI_TYPE(Uri) * destUri, const URI_TYPE(Uri) * sourceUri); - - +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. @@ -704,12 +700,10 @@ URI_PUBLIC int URI_FUNC(CopyUri)(URI_TYPE(Uri) * destUri, const URI_TYPE(Uri) * * @see uriNormalizeSyntaxExMmA * @see uriNormalizeSyntaxMaskRequiredExA * @since 0.5.0 - * @deprecated Deprecated since 0.9.0, please migrate to uriNormalizeSyntaxMaskRequiredExA (with "Ex"). + * @deprecated Deprecated since 0.9.0, please migrate to uriNormalizeSyntaxMaskRequiredExA + * (with "Ex"). */ -URI_PUBLIC unsigned int URI_FUNC(NormalizeSyntaxMaskRequired)( - const URI_TYPE(Uri) * uri); - - +URI_PUBLIC unsigned int URI_FUNC(NormalizeSyntaxMaskRequired)(const URI_TYPE(Uri) * uri); /** * Determines the components of a %URI that are not normalized. @@ -724,10 +718,8 @@ URI_PUBLIC unsigned int URI_FUNC(NormalizeSyntaxMaskRequired)( * @see uriNormalizeSyntaxMaskRequiredA * @since 0.9.0 */ -URI_PUBLIC int URI_FUNC(NormalizeSyntaxMaskRequiredEx)( - const URI_TYPE(Uri) * uri, unsigned int * outMask); - - +URI_PUBLIC int URI_FUNC(NormalizeSyntaxMaskRequiredEx)(const URI_TYPE(Uri) * uri, + unsigned int * outMask); /** * Normalizes a %URI using a normalization mask. @@ -746,10 +738,7 @@ URI_PUBLIC int URI_FUNC(NormalizeSyntaxMaskRequiredEx)( * @see uriNormalizeSyntaxMaskRequiredA * @since 0.5.0 */ -URI_PUBLIC int URI_FUNC(NormalizeSyntaxEx)(URI_TYPE(Uri) * uri, - unsigned int mask); - - +URI_PUBLIC int URI_FUNC(NormalizeSyntaxEx)(URI_TYPE(Uri) * uri, unsigned int mask); /** * Normalizes a %URI using a normalization mask. @@ -768,10 +757,8 @@ URI_PUBLIC int URI_FUNC(NormalizeSyntaxEx)(URI_TYPE(Uri) * uri, * @see uriNormalizeSyntaxMaskRequiredA * @since 0.9.0 */ -URI_PUBLIC int URI_FUNC(NormalizeSyntaxExMm)(URI_TYPE(Uri) * uri, - unsigned int mask, UriMemoryManager * memory); - - +URI_PUBLIC int URI_FUNC(NormalizeSyntaxExMm)(URI_TYPE(Uri) * uri, unsigned int mask, + UriMemoryManager * memory); /** * Normalizes all components of a %URI. @@ -790,8 +777,6 @@ URI_PUBLIC int URI_FUNC(NormalizeSyntaxExMm)(URI_TYPE(Uri) * uri, */ URI_PUBLIC int URI_FUNC(NormalizeSyntax)(URI_TYPE(Uri) * uri); - - /** * Converts a Unix filename to a %URI string. * The destination buffer must be large enough to hold 7 + 3 * len(filename) + 1 @@ -811,9 +796,7 @@ URI_PUBLIC int URI_FUNC(NormalizeSyntax)(URI_TYPE(Uri) * uri); * @since 0.5.2 */ URI_PUBLIC int URI_FUNC(UnixFilenameToUriString)(const URI_CHAR * filename, - URI_CHAR * uriString); - - + URI_CHAR * uriString); /** * Converts a Windows filename to a %URI string. @@ -834,9 +817,7 @@ URI_PUBLIC int URI_FUNC(UnixFilenameToUriString)(const URI_CHAR * filename, * @since 0.5.2 */ URI_PUBLIC int URI_FUNC(WindowsFilenameToUriString)(const URI_CHAR * filename, - URI_CHAR * uriString); - - + URI_CHAR * uriString); /** * Extracts a Unix filename from a %URI string. @@ -853,9 +834,7 @@ URI_PUBLIC int URI_FUNC(WindowsFilenameToUriString)(const URI_CHAR * filename, * @since 0.5.2 */ URI_PUBLIC int URI_FUNC(UriStringToUnixFilename)(const URI_CHAR * uriString, - URI_CHAR * filename); - - + URI_CHAR * filename); /** * Extracts a Windows filename from a %URI string. @@ -872,9 +851,7 @@ URI_PUBLIC int URI_FUNC(UriStringToUnixFilename)(const URI_CHAR * uriString, * @since 0.5.2 */ URI_PUBLIC int URI_FUNC(UriStringToWindowsFilename)(const URI_CHAR * uriString, - URI_CHAR * filename); - - + URI_CHAR * filename); /** * Calculates the number of characters needed to store the @@ -883,17 +860,16 @@ URI_PUBLIC int URI_FUNC(UriStringToWindowsFilename)(const URI_CHAR * uriString, * normalized to "%0D%0A". * * @param queryList IN: Query list to measure - * @param charsRequired OUT: Length of the string representation in characters excluding terminator + * @param charsRequired OUT: Length of the string representation in characters + * excluding terminator * @return Error code or 0 on success * * @see uriComposeQueryCharsRequiredExA * @see uriComposeQueryA * @since 0.7.0 */ -URI_PUBLIC int URI_FUNC(ComposeQueryCharsRequired)( - const URI_TYPE(QueryList) * queryList, int * charsRequired); - - +URI_PUBLIC int URI_FUNC(ComposeQueryCharsRequired)(const URI_TYPE(QueryList) * queryList, + int * charsRequired); /** * Calculates the number of characters needed to store the @@ -901,7 +877,8 @@ URI_PUBLIC int URI_FUNC(ComposeQueryCharsRequired)( * terminator. * * @param queryList IN: Query list to measure - * @param charsRequired OUT: Length of the string representation in characters excluding terminator + * @param charsRequired OUT: Length of the string representation in characters + * excluding terminator * @param spaceToPlus IN: Whether to convert ' ' to '+' or not * @param normalizeBreaks IN: Whether to convert CR and LF to CR-LF or not. * @return Error code or 0 on success @@ -910,11 +887,10 @@ URI_PUBLIC int URI_FUNC(ComposeQueryCharsRequired)( * @see uriComposeQueryExA * @since 0.7.0 */ -URI_PUBLIC int URI_FUNC(ComposeQueryCharsRequiredEx)( - const URI_TYPE(QueryList) * queryList, - int * charsRequired, UriBool spaceToPlus, UriBool normalizeBreaks); - - +URI_PUBLIC int + URI_FUNC(ComposeQueryCharsRequiredEx)(const URI_TYPE(QueryList) * queryList, + int * charsRequired, UriBool spaceToPlus, + UriBool normalizeBreaks); /** * Converts a query list structure back to a query string. @@ -924,8 +900,10 @@ URI_PUBLIC int URI_FUNC(ComposeQueryCharsRequiredEx)( * * @param dest OUT: Output destination * @param queryList IN: Query list to convert - * @param maxChars IN: Maximum number of characters to copy including terminator - * @param charsWritten OUT: Number of characters written, can be lower than maxChars even if the query list is too long! + * @param maxChars IN: Maximum number of characters to copy + * including terminator + * @param charsWritten OUT: Number of characters written, can be lower than + * maxChars even if the query list is too long! * @return Error code or 0 on success * * @see uriComposeQueryExA @@ -939,9 +917,8 @@ URI_PUBLIC int URI_FUNC(ComposeQueryCharsRequiredEx)( * @since 0.7.0 */ URI_PUBLIC int URI_FUNC(ComposeQuery)(URI_CHAR * dest, - const URI_TYPE(QueryList) * queryList, int maxChars, int * charsWritten); - - + const URI_TYPE(QueryList) * queryList, int maxChars, + int * charsWritten); /** * Converts a query list structure back to a query string. @@ -949,8 +926,10 @@ URI_PUBLIC int URI_FUNC(ComposeQuery)(URI_CHAR * dest, * * @param dest OUT: Output destination * @param queryList IN: Query list to convert - * @param maxChars IN: Maximum number of characters to copy including terminator - * @param charsWritten OUT: Number of characters written, can be lower than maxChars even if the query list is too long! + * @param maxChars IN: Maximum number of characters to copy + * including terminator + * @param charsWritten OUT: Number of characters written, can be lower than + * maxChars even if the query list is too long! * @param spaceToPlus IN: Whether to convert ' ' to '+' or not * @param normalizeBreaks IN: Whether to convert CR and LF to CR-LF or not. * @return Error code or 0 on success @@ -966,10 +945,9 @@ URI_PUBLIC int URI_FUNC(ComposeQuery)(URI_CHAR * dest, * @since 0.7.0 */ URI_PUBLIC int URI_FUNC(ComposeQueryEx)(URI_CHAR * dest, - const URI_TYPE(QueryList) * queryList, int maxChars, int * charsWritten, - UriBool spaceToPlus, UriBool normalizeBreaks); - - + const URI_TYPE(QueryList) * queryList, + int maxChars, int * charsWritten, + UriBool spaceToPlus, UriBool normalizeBreaks); /** * Converts a query list structure back to a query string. @@ -992,9 +970,7 @@ URI_PUBLIC int URI_FUNC(ComposeQueryEx)(URI_CHAR * dest, * @since 0.7.0 */ URI_PUBLIC int URI_FUNC(ComposeQueryMalloc)(URI_CHAR ** dest, - const URI_TYPE(QueryList) * queryList); - - + const URI_TYPE(QueryList) * queryList); /** * Converts a query list structure back to a query string. @@ -1017,10 +993,9 @@ URI_PUBLIC int URI_FUNC(ComposeQueryMalloc)(URI_CHAR ** dest, * @since 0.7.0 */ URI_PUBLIC int URI_FUNC(ComposeQueryMallocEx)(URI_CHAR ** dest, - const URI_TYPE(QueryList) * queryList, - UriBool spaceToPlus, UriBool normalizeBreaks); - - + const URI_TYPE(QueryList) * queryList, + UriBool spaceToPlus, + UriBool normalizeBreaks); /** * Converts a query list structure back to a query string. @@ -1043,11 +1018,10 @@ URI_PUBLIC int URI_FUNC(ComposeQueryMallocEx)(URI_CHAR ** dest, * @since 0.9.0 */ URI_PUBLIC int URI_FUNC(ComposeQueryMallocExMm)(URI_CHAR ** dest, - const URI_TYPE(QueryList) * queryList, - UriBool spaceToPlus, UriBool normalizeBreaks, - UriMemoryManager * memory); - - + const URI_TYPE(QueryList) * queryList, + UriBool spaceToPlus, + UriBool normalizeBreaks, + UriMemoryManager * memory); /** * Constructs a query list from the raw query string of a given URI. @@ -1067,10 +1041,9 @@ URI_PUBLIC int URI_FUNC(ComposeQueryMallocExMm)(URI_CHAR ** dest, * @see uriFreeQueryListMmA * @since 0.7.0 */ -URI_PUBLIC int URI_FUNC(DissectQueryMalloc)(URI_TYPE(QueryList) ** dest, - int * itemCount, const URI_CHAR * first, const URI_CHAR * afterLast); - - +URI_PUBLIC int URI_FUNC(DissectQueryMalloc)(URI_TYPE(QueryList) * *dest, int * itemCount, + const URI_CHAR * first, + const URI_CHAR * afterLast); /** * Constructs a query list from the raw query string of a given URI. @@ -1090,11 +1063,11 @@ URI_PUBLIC int URI_FUNC(DissectQueryMalloc)(URI_TYPE(QueryList) ** dest, * @see uriFreeQueryListA * @since 0.7.0 */ -URI_PUBLIC int URI_FUNC(DissectQueryMallocEx)(URI_TYPE(QueryList) ** dest, - int * itemCount, const URI_CHAR * first, const URI_CHAR * afterLast, - UriBool plusToSpace, UriBreakConversion breakConversion); - - +URI_PUBLIC int URI_FUNC(DissectQueryMallocEx)(URI_TYPE(QueryList) * *dest, + int * itemCount, const URI_CHAR * first, + const URI_CHAR * afterLast, + UriBool plusToSpace, + UriBreakConversion breakConversion); /** * Constructs a query list from the raw query string of a given URI. @@ -1115,12 +1088,12 @@ URI_PUBLIC int URI_FUNC(DissectQueryMallocEx)(URI_TYPE(QueryList) ** dest, * @see uriFreeQueryListMmA * @since 0.9.0 */ -URI_PUBLIC int URI_FUNC(DissectQueryMallocExMm)(URI_TYPE(QueryList) ** dest, - int * itemCount, const URI_CHAR * first, const URI_CHAR * afterLast, - UriBool plusToSpace, UriBreakConversion breakConversion, - UriMemoryManager * memory); - - +URI_PUBLIC int URI_FUNC(DissectQueryMallocExMm)(URI_TYPE(QueryList) * *dest, + int * itemCount, const URI_CHAR * first, + const URI_CHAR * afterLast, + UriBool plusToSpace, + UriBreakConversion breakConversion, + UriMemoryManager * memory); /** * Frees all memory associated with the given query list. @@ -1133,8 +1106,6 @@ URI_PUBLIC int URI_FUNC(DissectQueryMallocExMm)(URI_TYPE(QueryList) ** dest, */ URI_PUBLIC void URI_FUNC(FreeQueryList)(URI_TYPE(QueryList) * queryList); - - /** * Frees all memory associated with the given query list. * The structure itself is freed as well. @@ -1147,9 +1118,7 @@ URI_PUBLIC void URI_FUNC(FreeQueryList)(URI_TYPE(QueryList) * queryList); * @since 0.9.0 */ URI_PUBLIC int URI_FUNC(FreeQueryListMm)(URI_TYPE(QueryList) * queryList, - UriMemoryManager * memory); - - + UriMemoryManager * memory); /** * Makes the %URI hold copies of strings so that it no longer depends @@ -1166,8 +1135,6 @@ URI_PUBLIC int URI_FUNC(FreeQueryListMm)(URI_TYPE(QueryList) * queryList, */ URI_PUBLIC int URI_FUNC(MakeOwner)(URI_TYPE(Uri) * uri); - - /** * Makes the %URI hold copies of strings so that it no longer depends * on the original %URI string. If the %URI is already owner of copies, @@ -1180,16 +1147,1163 @@ URI_PUBLIC int URI_FUNC(MakeOwner)(URI_TYPE(Uri) * uri); * @see uriMakeOwnerA * @since 0.9.4 */ -URI_PUBLIC int URI_FUNC(MakeOwnerMm)(URI_TYPE(Uri) * uri, - UriMemoryManager * memory); +URI_PUBLIC int URI_FUNC(MakeOwnerMm)(URI_TYPE(Uri) * uri, UriMemoryManager * memory); +/** + * 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); -#ifdef __cplusplus -} -#endif +/** + * 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); -#endif +/** + * 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: Whether 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 additional 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 + +# endif #endif diff --git a/ext/uri/uriparser/include/uriparser/UriBase.h b/ext/uri/uriparser/include/uriparser/UriBase.h index 46c02135bb112..3a9a868e3bb18 100644 --- a/ext/uri/uriparser/include/uriparser/UriBase.h +++ b/ext/uri/uriparser/include/uriparser/UriBase.h @@ -43,140 +43,136 @@ */ #ifndef URI_BASE_H -#define URI_BASE_H 1 - - +# define URI_BASE_H 1 /* 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_SUFFIX_ANSI "" -#define URI_VER_SUFFIX_UNICODE URI_ANSI_TO_UNICODE(URI_VER_SUFFIX_ANSI) - - +# define URI_VER_MAJOR 1 +# define URI_VER_MINOR 0 +# define URI_VER_RELEASE 0 +# define URI_VER_SUFFIX_ANSI "" +# define URI_VER_SUFFIX_UNICODE URI_ANSI_TO_UNICODE(URI_VER_SUFFIX_ANSI) /* More version helper macros */ -#define URI_INT_TO_ANSI_HELPER(x) #x -#define URI_INT_TO_ANSI(x) URI_INT_TO_ANSI_HELPER(x) - -#define URI_INT_TO_UNICODE_HELPER(x) URI_ANSI_TO_UNICODE(#x) -#define URI_INT_TO_UNICODE(x) URI_INT_TO_UNICODE_HELPER(x) - -#define URI_VER_ANSI_HELPER(ma, mi, r, s) \ - URI_INT_TO_ANSI(ma) "." \ - URI_INT_TO_ANSI(mi) "." \ - URI_INT_TO_ANSI(r) \ - s +# define URI_INT_TO_ANSI_HELPER(x) #x +# define URI_INT_TO_ANSI(x) URI_INT_TO_ANSI_HELPER(x) -#define URI_VER_UNICODE_HELPER(ma, mi, r, s) \ - URI_INT_TO_UNICODE(ma) L"." \ - URI_INT_TO_UNICODE(mi) L"." \ - URI_INT_TO_UNICODE(r) \ - s +# define URI_INT_TO_UNICODE_HELPER(x) URI_ANSI_TO_UNICODE(#x) +# define URI_INT_TO_UNICODE(x) URI_INT_TO_UNICODE_HELPER(x) +# define URI_VER_ANSI_HELPER(ma, mi, r, s) \ + URI_INT_TO_ANSI(ma) "." URI_INT_TO_ANSI(mi) "." URI_INT_TO_ANSI(r) s +# define URI_VER_UNICODE_HELPER(ma, mi, r, s) \ + URI_INT_TO_UNICODE(ma) L"." URI_INT_TO_UNICODE(mi) L"." URI_INT_TO_UNICODE(r) s /* Full version strings */ -#define URI_VER_ANSI URI_VER_ANSI_HELPER(URI_VER_MAJOR, URI_VER_MINOR, URI_VER_RELEASE, URI_VER_SUFFIX_ANSI) -#define URI_VER_UNICODE URI_VER_UNICODE_HELPER(URI_VER_MAJOR, URI_VER_MINOR, URI_VER_RELEASE, URI_VER_SUFFIX_UNICODE) - - +# define URI_VER_ANSI \ + URI_VER_ANSI_HELPER(URI_VER_MAJOR, URI_VER_MINOR, URI_VER_RELEASE, \ + URI_VER_SUFFIX_ANSI) +# define URI_VER_UNICODE \ + URI_VER_UNICODE_HELPER(URI_VER_MAJOR, URI_VER_MINOR, URI_VER_RELEASE, \ + URI_VER_SUFFIX_UNICODE) /* Unused parameter macro */ -#ifdef __GNUC__ -# define URI_UNUSED(x) unused_##x __attribute__((unused)) -#else -# define URI_UNUSED(x) x -#endif - - +# ifdef __GNUC__ +# define URI_UNUSED(x) unused_##x __attribute__((unused)) +# else +# define URI_UNUSED(x) x +# endif /* Import/export decorator */ -#if defined(_MSC_VER) -# if defined(URI_STATIC_BUILD) -# define URI_PUBLIC -# elif defined(URI_LIBRARY_BUILD) -# define URI_PUBLIC __declspec(dllexport) -# else -# define URI_PUBLIC __declspec(dllimport) -# endif -#else -# if ! defined(URI_LIBRARY_BUILD) || ! defined(URI_VISIBILITY) -# define URI_PUBLIC -# else -# define URI_PUBLIC __attribute__ ((visibility("default"))) -# endif -#endif - - +# if defined(_MSC_VER) +# if defined(URI_STATIC_BUILD) +# define URI_PUBLIC +# elif defined(URI_LIBRARY_BUILD) +# define URI_PUBLIC __declspec(dllexport) +# else +# define URI_PUBLIC __declspec(dllimport) +# endif +# else +# if !defined(URI_LIBRARY_BUILD) || !defined(URI_VISIBILITY) +# define URI_PUBLIC +# else +# define URI_PUBLIC __attribute__((visibility("default"))) +# endif +# endif typedef int UriBool; /**< Boolean type */ -#define URI_TRUE 1 -#define URI_FALSE 0 - - +# define URI_TRUE 1 +# define URI_FALSE 0 /* Shared errors */ -#define URI_SUCCESS 0 -#define URI_ERROR_SYNTAX 1 /* Parsed text violates expected format */ -#define URI_ERROR_NULL 2 /* One of the params passed was NULL - although it mustn't be */ -#define URI_ERROR_MALLOC 3 /* Requested memory could not be allocated */ -#define URI_ERROR_OUTPUT_TOO_LARGE 4 /* Some output is to large for the receiving buffer */ -#define URI_ERROR_NOT_IMPLEMENTED 8 /* The called function is not implemented yet */ -#define URI_ERROR_RANGE_INVALID 9 /* The parameters passed contained invalid ranges */ -#define URI_ERROR_MEMORY_MANAGER_INCOMPLETE 10 /* [>=0.9.0] The UriMemoryManager passed does not implement all needed functions */ - +# define URI_SUCCESS 0 +# define URI_ERROR_SYNTAX 1 /* Parsed text violates expected format */ +# define URI_ERROR_NULL \ + 2 /* One of the params passed was NULL although it mustn't be \ + */ +# define URI_ERROR_MALLOC 3 /* Requested memory could not be allocated */ +# define URI_ERROR_OUTPUT_TOO_LARGE \ + 4 /* Some output is to large for the receiving buffer */ +# define URI_ERROR_NOT_IMPLEMENTED 8 /* The called function is not implemented yet */ +# define URI_ERROR_RANGE_INVALID 9 /* The parameters passed contained invalid ranges */ +# define URI_ERROR_MEMORY_MANAGER_INCOMPLETE \ + 10 /* [>=0.9.0] The UriMemoryManager passed does not implement all needed \ + functions */ /* Errors specific to ToString */ -#define URI_ERROR_TOSTRING_TOO_LONG URI_ERROR_OUTPUT_TOO_LARGE /* Deprecated, test for URI_ERROR_OUTPUT_TOO_LARGE instead */ +# define URI_ERROR_TOSTRING_TOO_LONG \ + URI_ERROR_OUTPUT_TOO_LARGE /* Deprecated, test for URI_ERROR_OUTPUT_TOO_LARGE \ + instead */ /* Errors specific to AddBaseUri */ -#define URI_ERROR_ADDBASE_REL_BASE 5 /* Given base is not absolute */ +# define URI_ERROR_ADDBASE_REL_BASE 5 /* Given base is not absolute */ /* Errors specific to RemoveBaseUri */ -#define URI_ERROR_REMOVEBASE_REL_BASE 6 /* Given base is not absolute */ -#define URI_ERROR_REMOVEBASE_REL_SOURCE 7 /* Given base is not absolute */ +# define URI_ERROR_REMOVEBASE_REL_BASE 6 /* Given base is not absolute */ +# define URI_ERROR_REMOVEBASE_REL_SOURCE 7 /* Given base is not absolute */ /* Error specific to uriTestMemoryManager */ -#define URI_ERROR_MEMORY_MANAGER_FAULTY 11 /* [>=0.9.0] The UriMemoryManager given did not pass the test suite */ - - -#ifndef URI_DOXYGEN -# include /* For NULL, snprintf */ -# include /* For wchar_t */ -# include /* For strlen, memset, memcpy */ -# include /* For malloc */ -#endif /* URI_DOXYGEN */ - - +# 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 */ +# include /* For wchar_t */ +# include /* For strlen, memset, memcpy */ +# include /* For malloc */ +# endif /* URI_DOXYGEN */ /** * Holds an IPv4 address. */ typedef struct UriIp4Struct { - unsigned char data[4]; /**< Each octet in one byte */ + unsigned char data[4]; /**< Each octet in one byte */ } UriIp4; /**< @copydoc UriIp4Struct */ - - /** * Holds an IPv6 address. */ typedef struct UriIp6Struct { - unsigned char data[16]; /**< Each quad in two bytes */ + unsigned char data[16]; /**< Each quad in two bytes */ } UriIp6; /**< @copydoc UriIp6Struct */ - -struct UriMemoryManagerStruct; /* foward declaration to break loop */ - +struct UriMemoryManagerStruct; /* forward declaration to break loop */ /** * Function signature that custom malloc(3) functions must conform to @@ -204,7 +200,8 @@ typedef void * (*UriFuncRealloc)(struct UriMemoryManagerStruct *, void *, size_t * * @since 0.9.0 */ -typedef void * (*UriFuncReallocarray)(struct UriMemoryManagerStruct *, void *, size_t, size_t); +typedef void * (*UriFuncReallocarray)(struct UriMemoryManagerStruct *, void *, size_t, + size_t); /** * Function signature that custom free(3) functions must conform to @@ -213,7 +210,6 @@ typedef void * (*UriFuncReallocarray)(struct UriMemoryManagerStruct *, void *, s */ typedef void (*UriFuncFree)(struct UriMemoryManagerStruct *, void *); - /** * Class-like interface of custom memory managers * @@ -224,79 +220,87 @@ typedef void (*UriFuncFree)(struct UriMemoryManagerStruct *, void *); * @since 0.9.0 */ typedef struct UriMemoryManagerStruct { - UriFuncMalloc malloc; /**< Pointer to custom malloc(3) */ - UriFuncCalloc calloc; /**< Pointer to custom calloc(3); to emulate using malloc and memset see uriEmulateCalloc */ - UriFuncRealloc realloc; /**< Pointer to custom realloc(3) */ - UriFuncReallocarray reallocarray; /**< Pointer to custom reallocarray(3); to emulate using realloc see uriEmulateReallocarray */ - UriFuncFree free; /**< Pointer to custom free(3) */ - void * userData; /**< Pointer to data that the other function members need access to */ + UriFuncMalloc malloc; /**< Pointer to custom malloc(3) */ + UriFuncCalloc calloc; /**< Pointer to custom calloc(3); to emulate using malloc and + memset see uriEmulateCalloc */ + UriFuncRealloc realloc; /**< Pointer to custom realloc(3) */ + UriFuncReallocarray reallocarray; /**< Pointer to custom reallocarray(3); to emulate + using realloc see uriEmulateReallocarray */ + UriFuncFree free; /**< Pointer to custom free(3) */ + void * + userData; /**< Pointer to data that the other function members need access to */ } UriMemoryManager; /**< @copydoc UriMemoryManagerStruct */ - /** * Specifies a line break conversion mode. */ typedef enum UriBreakConversionEnum { - URI_BR_TO_LF, /**< Convert to Unix line breaks ("\\x0a") */ - URI_BR_TO_CRLF, /**< Convert to Windows line breaks ("\\x0d\\x0a") */ - URI_BR_TO_CR, /**< Convert to Macintosh line breaks ("\\x0d") */ - URI_BR_TO_UNIX = URI_BR_TO_LF, /**< @copydoc UriBreakConversionEnum::URI_BR_TO_LF */ - URI_BR_TO_WINDOWS = URI_BR_TO_CRLF, /**< @copydoc UriBreakConversionEnum::URI_BR_TO_CRLF */ - URI_BR_TO_MAC = URI_BR_TO_CR, /**< @copydoc UriBreakConversionEnum::URI_BR_TO_CR */ - URI_BR_DONT_TOUCH /**< Copy line breaks unmodified */ + URI_BR_TO_LF, /**< Convert to Unix line breaks ("\\x0a") */ + URI_BR_TO_CRLF, /**< Convert to Windows line breaks ("\\x0d\\x0a") */ + URI_BR_TO_CR, /**< Convert to Macintosh line breaks ("\\x0d") */ + URI_BR_TO_UNIX = URI_BR_TO_LF, /**< @copydoc UriBreakConversionEnum::URI_BR_TO_LF */ + URI_BR_TO_WINDOWS = + URI_BR_TO_CRLF, /**< @copydoc UriBreakConversionEnum::URI_BR_TO_CRLF */ + URI_BR_TO_MAC = URI_BR_TO_CR, /**< @copydoc UriBreakConversionEnum::URI_BR_TO_CR */ + URI_BR_DONT_TOUCH /**< Copy line breaks unmodified */ } UriBreakConversion; /**< @copydoc UriBreakConversionEnum */ - - /** * Specifies which component of a %URI has to be normalized. */ typedef enum UriNormalizationMaskEnum { - URI_NORMALIZED = 0, /**< Do not normalize anything */ - URI_NORMALIZE_SCHEME = 1 << 0, /**< Normalize scheme (fix uppercase letters) */ - URI_NORMALIZE_USER_INFO = 1 << 1, /**< Normalize user info (fix uppercase percent-encodings) */ - 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_PORT = 1 << 6 /**< Normalize port (drop leading zeros) @since 0.9.9 */ + URI_NORMALIZED = 0, /**< Do not normalize anything */ + URI_NORMALIZE_SCHEME = 1 << 0, /**< Normalize scheme (fix uppercase letters) */ + URI_NORMALIZE_USER_INFO = + 1 << 1, /**< Normalize user info (fix uppercase percent-encodings) */ + 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_PORT = 1 << 6 /**< Normalize port (drop leading zeros) @since 0.9.9 */ } UriNormalizationMask; /**< @copydoc UriNormalizationMaskEnum */ - - /** * Specifies how to resolve %URI references. */ typedef enum UriResolutionOptionsEnum { - URI_RESOLVE_STRICTLY = 0, /**< Full RFC conformance */ - URI_RESOLVE_IDENTICAL_SCHEME_COMPAT = 1 << 0 /**< Treat %URI to resolve with identical scheme as having no scheme */ + URI_RESOLVE_STRICTLY = 0, /**< Full RFC conformance */ + URI_RESOLVE_IDENTICAL_SCHEME_COMPAT = + 1 << 0 /**< Treat %URI to resolve with identical scheme as having no scheme */ } UriResolutionOptions; /**< @copydoc UriResolutionOptionsEnum */ - - /** - * Wraps a memory manager backend that only provides malloc and free - * to make a complete memory manager ready to be used. + * Wraps a memory manager backend that only provides malloc(3) and + * free(3) to make a complete memory manager ready to be used. * * The core feature of this wrapper is that you don't need to implement - * realloc if you don't want to. The wrapped memory manager uses - * backend->malloc, memcpy, and backend->free and soieof(size_t) extra - * bytes per allocation to emulate fallback realloc for you. + * realloc(3) if you don't want to. The wrapped memory manager uses + * backend->malloc, memcpy(3), and backend->free and + * (at least) sizeof(size_t) extra bytes per allocation to emulate + * fallback realloc(3) for you. * - * memory->calloc is uriEmulateCalloc. - * memory->free uses backend->free and handles the size header. - * memory->malloc uses backend->malloc and adds a size header. - * memory->realloc uses memory->malloc, memcpy, and memory->free and reads - * the size header. - * memory->reallocarray is uriEmulateReallocarray. + *
    + *
  • memory->calloc is uriEmulateCalloc.
  • + *
  • memory->free uses backend->free, + * and handles the size header.
  • + *
  • memory->malloc uses backend->malloc, + * and adds a size header.
  • + *
  • memory->realloc uses memory->malloc, + * memcpy(3) and memory->free, + * and reads the size header.
  • + *
  • memory->reallocarray is uriEmulateReallocarray.
  • + *
* - * The internal workings behind memory->free, memory->malloc, and - * memory->realloc may change so the functions exposed by these function - * pointer sshould be consided internal and not public API. + * The internal workings behind memory->free, memory->malloc, + * and memory->realloc may change, and the functions exposed by these + * function pointers should be considered internal and not public API. * * @param memory OUT: Where to write the wrapped memory manager to * @param backend IN: Memory manager to use as a backend - * @return Error code or 0 on success + * @return Error code or 0 on success * * @see uriEmulateCalloc * @see uriEmulateReallocarray @@ -304,12 +308,10 @@ typedef enum UriResolutionOptionsEnum { * @since 0.9.0 */ URI_PUBLIC int uriCompleteMemoryManager(UriMemoryManager * memory, - UriMemoryManager * backend); - - + UriMemoryManager * backend); /** - * Offers emulation of calloc(3) based on memory->malloc and memset. + * Offers emulation of calloc(3) based on memory->malloc and memset. * See "man 3 calloc" as well. * * @param memory IN: Memory manager to use, should not be NULL @@ -322,17 +324,14 @@ URI_PUBLIC int uriCompleteMemoryManager(UriMemoryManager * memory, * @see UriMemoryManager * @since 0.9.0 */ -URI_PUBLIC void * uriEmulateCalloc(UriMemoryManager * memory, - size_t nmemb, size_t size); - - +URI_PUBLIC void * uriEmulateCalloc(UriMemoryManager * memory, size_t nmemb, size_t size); /** - * Offers emulation of reallocarray(3) based on memory->realloc. + * Offers emulation of reallocarray(3) based on memory->realloc. * See "man 3 reallocarray" as well. * * @param memory IN: Memory manager to use, should not be NULL - * @param ptr IN: Pointer allocated using memory->malloc/... or NULL + * @param ptr IN: Pointer allocated using memory->malloc/... or NULL * @param nmemb IN: Number of elements to allocate * @param size IN: Size in bytes per element * @return Pointer to allocated memory or NULL @@ -342,10 +341,8 @@ URI_PUBLIC void * uriEmulateCalloc(UriMemoryManager * memory, * @see UriMemoryManager * @since 0.9.0 */ -URI_PUBLIC void * uriEmulateReallocarray(UriMemoryManager * memory, - void * ptr, size_t nmemb, size_t size); - - +URI_PUBLIC void * uriEmulateReallocarray(UriMemoryManager * memory, void * ptr, + size_t nmemb, size_t size); /** * Run multiple tests against a given memory manager. @@ -357,7 +354,11 @@ URI_PUBLIC void * uriEmulateReallocarray(UriMemoryManager * memory, * 5. and frees that memory. * * It is recommended to compile with AddressSanitizer enabled - * to take full advantage of uriTestMemoryManager. + * to take full advantage of uriTestMemoryManager. + * + * For backwards-compatibility, uriTestMemoryManager + * does not challenge pointer alignment; please see + * uriTestMemoryManagerEx for that feature. * * @param memory IN: Memory manager to use, should not be NULL * @return Error code or 0 on success @@ -365,10 +366,37 @@ URI_PUBLIC void * uriEmulateReallocarray(UriMemoryManager * memory, * @see uriEmulateCalloc * @see uriEmulateReallocarray * @see UriMemoryManager + * @see uriTestMemoryManagerEx * @since 0.9.0 */ URI_PUBLIC int uriTestMemoryManager(UriMemoryManager * memory); - +/** + * Run multiple tests against a given memory manager. + * For example, one test + * 1. allocates a small amount of memory, + * 2. writes some magic bytes to it, + * 3. reallocates it, + * 4. checks that previous values are still present, + * 5. and frees that memory. + * + * It is recommended to compile with both AddressSanitizer and + * UndefinedBehaviorSanitizer enabled to take full advantage of + * uriTestMemoryManagerEx. Note that environment variable + * UBSAN_OPTIONS may need adjustment to make UndefinedBehaviorSanitizer + * fatal (which by default it is not). + * + * @param memory IN: Memory manager to use, should not be NULL + * @param challengeAlignment IN: Whether to challenge pointer alignment + * @return Error code or 0 on success + * + * @see uriEmulateCalloc + * @see uriEmulateReallocarray + * @see UriMemoryManager + * @see uriTestMemoryManager + * @since 1.0.0 + */ +URI_PUBLIC int uriTestMemoryManagerEx(UriMemoryManager * memory, + UriBool challengeAlignment); #endif /* URI_BASE_H */ diff --git a/ext/uri/uriparser/include/uriparser/UriDefsAnsi.h b/ext/uri/uriparser/include/uriparser/UriDefsAnsi.h index af581b91a2152..17aed1b3b59e8 100644 --- a/ext/uri/uriparser/include/uriparser/UriDefsAnsi.h +++ b/ext/uri/uriparser/include/uriparser/UriDefsAnsi.h @@ -46,24 +46,18 @@ /* Allow multi inclusion */ #include "UriDefsConfig.h" - - #undef URI_CHAR #define URI_CHAR char #undef _UT #define _UT(x) x - - #undef URI_FUNC #define URI_FUNC(x) uri##x##A #undef URI_TYPE #define URI_TYPE(x) Uri##x##A - - #undef URI_STRLEN #define URI_STRLEN strlen #undef URI_STRCPY @@ -76,7 +70,7 @@ /* TODO Remove on next source-compatibility break */ #undef URI_SNPRINTF #if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32)) -# define URI_SNPRINTF _snprintf +# define URI_SNPRINTF _snprintf #else -# define URI_SNPRINTF snprintf +# define URI_SNPRINTF snprintf #endif diff --git a/ext/uri/uriparser/include/uriparser/UriDefsConfig.h b/ext/uri/uriparser/include/uriparser/UriDefsConfig.h index 51bc93eeddaae..79d485d90c380 100644 --- a/ext/uri/uriparser/include/uriparser/UriDefsConfig.h +++ b/ext/uri/uriparser/include/uriparser/UriDefsConfig.h @@ -43,59 +43,51 @@ */ #ifndef URI_DEFS_CONFIG_H -#define URI_DEFS_CONFIG_H 1 - - +# define URI_DEFS_CONFIG_H 1 /* Deny external overriding */ -#undef URI_ENABLE_ANSI /* Internal for !URI_NO_ANSI */ -#undef URI_ENABLE_UNICODE /* Internal for !URI_NO_UNICODE */ - - +# undef URI_ENABLE_ANSI /* Internal for !URI_NO_ANSI */ +# undef URI_ENABLE_UNICODE /* Internal for !URI_NO_UNICODE */ /* Encoding */ -#ifdef URI_NO_ANSI -# ifdef URI_NO_UNICODE +# ifdef URI_NO_ANSI +# ifdef URI_NO_UNICODE /* No encoding at all */ -# error URI_NO_ANSI and URI_NO_UNICODE cannot go together. -# else +# error URI_NO_ANSI and URI_NO_UNICODE cannot go together. +# else /* Wide strings only */ -# define URI_ENABLE_UNICODE 1 -# endif -#else -# ifdef URI_NO_UNICODE +# define URI_ENABLE_UNICODE 1 +# endif +# else +# ifdef URI_NO_UNICODE /* Narrow strings only */ -# define URI_ENABLE_ANSI 1 -# else +# define URI_ENABLE_ANSI 1 +# else /* Both narrow and wide strings */ -# define URI_ENABLE_ANSI 1 -# define URI_ENABLE_UNICODE 1 -# endif -#endif - - +# define URI_ENABLE_ANSI 1 +# define URI_ENABLE_UNICODE 1 +# endif +# endif /* Function inlining, not ANSI/ISO C! */ -#if defined(URI_DOXYGEN) -# define URI_INLINE -#elif defined(__INTEL_COMPILER) +# if defined(URI_DOXYGEN) +# define URI_INLINE +# elif defined(__INTEL_COMPILER) /* Intel C/C++ */ /* http://predef.sourceforge.net/precomp.html#sec20 */ /* http://www.intel.com/support/performancetools/c/windows/sb/CS-007751.htm#2 */ -# define URI_INLINE __forceinline -#elif defined(_MSC_VER) +# define URI_INLINE __forceinline +# elif defined(_MSC_VER) /* Microsoft Visual C++ */ /* http://predef.sourceforge.net/precomp.html#sec32 */ /* http://msdn2.microsoft.com/en-us/library/ms882281.aspx */ -# define URI_INLINE __forceinline -#elif (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) +# define URI_INLINE __forceinline +# elif (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) /* C99, "inline" is a keyword */ -# define URI_INLINE inline -#else +# define URI_INLINE inline +# else /* No inlining */ -# define URI_INLINE -#endif - - +# define URI_INLINE +# endif #endif /* URI_DEFS_CONFIG_H */ diff --git a/ext/uri/uriparser/include/uriparser/UriDefsUnicode.h b/ext/uri/uriparser/include/uriparser/UriDefsUnicode.h index 01421f5f861df..6fce6725e69b7 100644 --- a/ext/uri/uriparser/include/uriparser/UriDefsUnicode.h +++ b/ext/uri/uriparser/include/uriparser/UriDefsUnicode.h @@ -46,24 +46,18 @@ /* Allow multi inclusion */ #include "UriDefsConfig.h" - - #undef URI_CHAR #define URI_CHAR wchar_t #undef _UT #define _UT(x) L##x - - #undef URI_FUNC #define URI_FUNC(x) uri##x##W #undef URI_TYPE #define URI_TYPE(x) Uri##x##W - - #undef URI_STRLEN #define URI_STRLEN wcslen #undef URI_STRCPY @@ -76,7 +70,7 @@ /* TODO Remove on next source-compatibility break */ #undef URI_SNPRINTF #if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32)) -# define URI_SNPRINTF _snwprintf +# define URI_SNPRINTF _snwprintf #else -# define URI_SNPRINTF swprintf +# define URI_SNPRINTF swprintf #endif diff --git a/ext/uri/uriparser/include/uriparser/UriIp4.h b/ext/uri/uriparser/include/uriparser/UriIp4.h index c2e59a6bf2d13..5f84b62dd2fce 100644 --- a/ext/uri/uriparser/include/uriparser/UriIp4.h +++ b/ext/uri/uriparser/include/uriparser/UriIp4.h @@ -44,67 +44,62 @@ */ #if (defined(URI_PASS_ANSI) && !defined(URI_IP4_TWICE_H_ANSI)) \ - || (defined(URI_PASS_UNICODE) && !defined(URI_IP4_TWICE_H_UNICODE)) \ - || (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) + || (defined(URI_PASS_UNICODE) && !defined(URI_IP4_TWICE_H_UNICODE)) \ + || (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) /* What encodings are enabled? */ -#include "UriDefsConfig.h" -#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +# include "UriDefsConfig.h" +# if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) /* Include SELF twice */ -# ifdef URI_ENABLE_ANSI -# define URI_PASS_ANSI 1 -# include "UriIp4.h" -# undef URI_PASS_ANSI -# endif -# ifdef URI_ENABLE_UNICODE -# define URI_PASS_UNICODE 1 -# include "UriIp4.h" -# undef URI_PASS_UNICODE -# endif +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriIp4.h" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriIp4.h" +# undef URI_PASS_UNICODE +# endif /* Only one pass for each encoding */ -#elif (defined(URI_PASS_ANSI) && !defined(URI_IP4_TWICE_H_ANSI) \ - && defined(URI_ENABLE_ANSI)) || (defined(URI_PASS_UNICODE) \ - && !defined(URI_IP4_TWICE_H_UNICODE) && defined(URI_ENABLE_UNICODE)) -# ifdef URI_PASS_ANSI -# define URI_IP4_TWICE_H_ANSI 1 -# include "UriDefsAnsi.h" -# else -# define URI_IP4_TWICE_H_UNICODE 1 -# include "UriDefsUnicode.h" -# include -# endif - - - -#ifdef __cplusplus +# elif (defined(URI_PASS_ANSI) && !defined(URI_IP4_TWICE_H_ANSI) \ + && defined(URI_ENABLE_ANSI)) \ + || (defined(URI_PASS_UNICODE) && !defined(URI_IP4_TWICE_H_UNICODE) \ + && defined(URI_ENABLE_UNICODE)) +# ifdef URI_PASS_ANSI +# define URI_IP4_TWICE_H_ANSI 1 +# include "UriDefsAnsi.h" +# else +# define URI_IP4_TWICE_H_UNICODE 1 +# include "UriDefsUnicode.h" +# include +# endif + +# ifdef __cplusplus extern "C" { -#endif - - - -#ifndef URI_DOXYGEN -# include "UriBase.h" -#endif - +# endif +# ifndef URI_DOXYGEN +# include "UriBase.h" +# endif /** - * 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); - - + const URI_CHAR * first, + const URI_CHAR * afterLast); -#ifdef __cplusplus +# ifdef __cplusplus } -#endif - +# endif - -#endif +# endif #endif 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 ccec5d4d5c8bf..3644e8828f35f 100644 --- a/ext/uri/uriparser/src/UriCommon.c +++ b/ext/uri/uriparser/src/UriCommon.c @@ -41,610 +41,730 @@ #include #if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) /* Include SELF twice */ -# ifdef URI_ENABLE_ANSI -# define URI_PASS_ANSI 1 -# include "UriCommon.c" -# undef URI_PASS_ANSI -# endif -# ifdef URI_ENABLE_UNICODE -# define URI_PASS_UNICODE 1 -# include "UriCommon.c" -# undef URI_PASS_UNICODE -# endif +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriCommon.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriCommon.c" +# undef URI_PASS_UNICODE +# endif #else -# ifdef URI_PASS_ANSI -# include -# else -# include -# include -# endif - - - -#ifndef URI_DOXYGEN -# include -# include "UriCommon.h" -#endif +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif +# ifndef URI_DOXYGEN +# include +# include "UriCommon.h" +# include "UriSets.h" +# endif +# 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(".."); - - void URI_FUNC(ResetUri)(URI_TYPE(Uri) * uri) { - if (uri == NULL) { - return; - } - memset(uri, 0, sizeof(URI_TYPE(Uri))); + if (uri == NULL) { + return; + } + memset(uri, 0, sizeof(URI_TYPE(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, - const URI_TYPE(TextRange) * b) { - int diff; - - /* NOTE: Both NULL means equal! */ - if ((a == NULL) || (b == NULL)) { - return ((a == NULL) ? 0 : 1) - ((b == NULL) ? 0 : 1); - } - - /* NOTE: Both NULL means equal! */ - if ((a->first == NULL) || (b->first == NULL)) { - return ((a->first == NULL) ? 0 : 1) - ((b->first == NULL) ? 0 : 1); - } - - diff = ((int)(a->afterLast - a->first) - (int)(b->afterLast - b->first)); - if (diff > 0) { - return 1; - } else if (diff < 0) { - return -1; - } - - diff = URI_STRNCMP(a->first, b->first, (a->afterLast - a->first)); - - if (diff > 0) { - return 1; - } else if (diff < 0) { - return -1; - } - - return diff; +int URI_FUNC(CompareRange)(const URI_TYPE(TextRange) * a, const URI_TYPE(TextRange) * b) { + int diff; + + /* NOTE: Both NULL means equal! */ + if ((a == NULL) || (b == NULL)) { + return ((a == NULL) ? 0 : 1) - ((b == NULL) ? 0 : 1); + } + + /* NOTE: Both NULL means equal! */ + if ((a->first == NULL) || (b->first == NULL)) { + return ((a->first == NULL) ? 0 : 1) - ((b->first == NULL) ? 0 : 1); + } + + diff = ((int)(a->afterLast - a->first) - (int)(b->afterLast - b->first)); + if (diff > 0) { + return 1; + } else if (diff < 0) { + return -1; + } + + diff = URI_STRNCMP(a->first, b->first, (a->afterLast - a->first)); + + if (diff > 0) { + return 1; + } else if (diff < 0) { + return -1; + } + + return diff; } - - 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; + 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, UriBool useSafe, UriMemoryManager * memory) { - if (sourceRange->first == NULL) { - destRange->first = NULL; - destRange->afterLast = NULL; - } else if (sourceRange->first == sourceRange->afterLast && useSafe) { - destRange->first = URI_FUNC(SafeToPointTo); - destRange->afterLast = URI_FUNC(SafeToPointTo); - } else { - return URI_FUNC(CopyRange)(destRange, sourceRange, memory); - } - - return URI_TRUE; + 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; - if ((uri == NULL) || (uri->pathHead == NULL)) { - return URI_TRUE; - } - - walker = uri->pathHead; - walker->reserved = NULL; /* Prev pointer */ - do { - UriBool removeSegment = URI_FALSE; - int len = (int)(walker->text.afterLast - walker->text.first); - switch (len) { - case 1: - if ((walker->text.first)[0] == _UT('.')) { - /* "." segment -> remove if not essential */ - URI_TYPE(PathSegment) * const prev = walker->reserved; - URI_TYPE(PathSegment) * const nextBackup = walker->next; - - /* - * Is this dot segment essential, - * i.e. is there a chance of changing semantics by dropping this dot segment? - * - * For example, changing "./http://foo" into "http://foo/" would change semantics - * and hence the dot segment is essential to that case and cannot be removed. - */ - removeSegment = URI_TRUE; - if (relative && (walker == uri->pathHead) && (walker->next != NULL)) { - const URI_CHAR * ch = walker->next->text.first; - for (; ch < walker->next->text.afterLast; ch++) { - if (*ch == _UT(':')) { - removeSegment = URI_FALSE; - break; - } - } - } - - if (removeSegment) { - /* .. then let's go remove that segment. */ - /* Last segment? */ - if (walker->next != NULL) { - /* Not last segment, i.e. first or middle segment - * OLD: (prev|NULL) <- walker <- next - * NEW: (prev|NULL) <----------- next */ - walker->next->reserved = prev; - - if (prev == NULL) { - /* First but not last segment - * OLD: head -> walker -> next - * NEW: head -----------> next */ - uri->pathHead = walker->next; - } else { - /* Middle segment - * OLD: prev -> walker -> next - * NEW: prev -----------> next */ - prev->next = walker->next; - } - - if (pathOwned && (walker->text.first != walker->text.afterLast)) { - memory->free(memory, (URI_CHAR *)walker->text.first); - } - memory->free(memory, walker); - } else { - /* Last segment */ - if (pathOwned && (walker->text.first != walker->text.afterLast)) { - memory->free(memory, (URI_CHAR *)walker->text.first); - } - - if (prev == NULL) { - /* Last and first */ - 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); - } else { - memory->free(memory, walker); - - uri->pathHead = NULL; - uri->pathTail = NULL; - } - } else { - /* Last but not first, replace "." with empty segment to represent trailing slash */ - walker->text.first = URI_FUNC(SafeToPointTo); - walker->text.afterLast = URI_FUNC(SafeToPointTo); - } - } - - walker = nextBackup; - } - } - break; - - case 2: - if (((walker->text.first)[0] == _UT('.')) - && ((walker->text.first)[1] == _UT('.'))) { - /* Path ".." -> remove this and the previous segment */ - URI_TYPE(PathSegment) * const prev = walker->reserved; - URI_TYPE(PathSegment) * prevPrev; - URI_TYPE(PathSegment) * const nextBackup = walker->next; - - removeSegment = URI_TRUE; - if (relative) { - if (prev == NULL) { - /* We cannot remove traversal beyond because the - * URI is relative and may be resolved later. - * So we can simplify "a/../b/d" to "b/d" but - * we cannot simplify "../b/d" (outside of reference resolution). */ - removeSegment = URI_FALSE; - } else if ((prev != NULL) - && ((prev->text.afterLast - prev->text.first) == 2) - && ((prev->text.first)[0] == _UT('.')) - && ((prev->text.first)[1] == _UT('.'))) { - /* We need to protect against mis-simplifying "a/../../b" to "a/b". */ - removeSegment = URI_FALSE; - } - } - - if (removeSegment) { - if (prev != NULL) { - /* Not first segment */ - prevPrev = prev->reserved; - if (prevPrev != NULL) { - /* Not even prev is the first one - * OLD: prevPrev -> prev -> walker -> (next|NULL) - * NEW: prevPrev -------------------> (next|NULL) */ - prevPrev->next = walker->next; - if (walker->next != NULL) { - /* Update parent relationship as well - * OLD: prevPrev <- prev <- walker <- next - * NEW: prevPrev <------------------- next */ - walker->next->reserved = prevPrev; - } else { - /* Last segment -> insert "" segment to represent trailing slash, update tail */ - URI_TYPE(PathSegment) * const segment = memory->calloc(memory, 1, sizeof(URI_TYPE(PathSegment))); - if (segment == NULL) { - if (pathOwned && (walker->text.first != walker->text.afterLast)) { - memory->free(memory, (URI_CHAR *)walker->text.first); - } - memory->free(memory, walker); - - if (pathOwned && (prev->text.first != prev->text.afterLast)) { - memory->free(memory, (URI_CHAR *)prev->text.first); - } - memory->free(memory, prev); - - return URI_FALSE; /* Raises malloc error */ - } - segment->text.first = URI_FUNC(SafeToPointTo); - segment->text.afterLast = URI_FUNC(SafeToPointTo); - prevPrev->next = segment; - uri->pathTail = segment; - } - - if (pathOwned && (walker->text.first != walker->text.afterLast)) { - memory->free(memory, (URI_CHAR *)walker->text.first); - } - memory->free(memory, walker); - - if (pathOwned && (prev->text.first != prev->text.afterLast)) { - memory->free(memory, (URI_CHAR *)prev->text.first); - } - memory->free(memory, prev); - - walker = nextBackup; - } else { - /* Prev is the first segment */ - if (walker->next != NULL) { - uri->pathHead = walker->next; - walker->next->reserved = NULL; - - if (pathOwned && (walker->text.first != walker->text.afterLast)) { - memory->free(memory, (URI_CHAR *)walker->text.first); - } - memory->free(memory, walker); - } else { - /* Re-use segment for "" path segment to represent trailing slash, update tail */ - URI_TYPE(PathSegment) * const segment = walker; - if (pathOwned && (segment->text.first != segment->text.afterLast)) { - memory->free(memory, (URI_CHAR *)segment->text.first); - } - segment->text.first = URI_FUNC(SafeToPointTo); - segment->text.afterLast = URI_FUNC(SafeToPointTo); - uri->pathHead = segment; - uri->pathTail = segment; - } - - if (pathOwned && (prev->text.first != prev->text.afterLast)) { - memory->free(memory, (URI_CHAR *)prev->text.first); - } - memory->free(memory, prev); - - walker = nextBackup; - } - } else { - URI_TYPE(PathSegment) * const anotherNextBackup = walker->next; - int freeWalker = URI_TRUE; - - /* First segment */ - if (walker->next != NULL) { - /* First segment of multiple -> update head - * OLD: head -> walker -> next - * NEW: head -----------> next */ - uri->pathHead = walker->next; - - /* Update parent link as well - * OLD: head <- walker <- next - * NEW: head <----------- next */ - walker->next->reserved = NULL; - } else { - if (uri->absolutePath) { - /* First and only segment -> update head - * OLD: head -> walker -> NULL - * NEW: head -----------> NULL */ - uri->pathHead = NULL; - - /* Last segment -> update tail - * OLD: tail -> walker - * NEW: tail -> NULL */ - uri->pathTail = NULL; - } else { - /* Re-use segment for "" path segment to represent trailing slash, - * then update head and tail */ - if (pathOwned && (walker->text.first != walker->text.afterLast)) { - memory->free(memory, (URI_CHAR *)walker->text.first); - } - walker->text.first = URI_FUNC(SafeToPointTo); - walker->text.afterLast = URI_FUNC(SafeToPointTo); - freeWalker = URI_FALSE; - } - } - - if (freeWalker) { - if (pathOwned && (walker->text.first != walker->text.afterLast)) { - memory->free(memory, (URI_CHAR *)walker->text.first); - } - memory->free(memory, walker); - } - - walker = anotherNextBackup; - } - } - } - break; - } /* end of switch */ - - if (!removeSegment) { - /* .. then let's move to the next element, and start again. */ - if (walker->next != NULL) { - walker->next->reserved = walker; - } else { - /* Last segment -> update tail */ - uri->pathTail = walker; - } - walker = walker->next; - } - } while (walker != NULL); - - return URI_TRUE; +UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri, UriBool relative, + UriBool pathOwned, UriMemoryManager * memory) { + URI_TYPE(PathSegment) * walker; + if ((uri == NULL) || (uri->pathHead == NULL)) { + return URI_TRUE; + } + + walker = uri->pathHead; + walker->reserved = NULL; /* Prev pointer */ + do { + UriBool removeSegment = URI_FALSE; + int len = (int)(walker->text.afterLast - walker->text.first); + switch (len) { + case 1: + if ((walker->text.first)[0] == _UT('.')) { + /* "." segment -> remove if not essential */ + URI_TYPE(PathSegment) * const prev = walker->reserved; + URI_TYPE(PathSegment) * const nextBackup = walker->next; + + /* + * Is this dot segment essential, + * i.e. is there a chance of changing semantics by dropping this dot + * segment? + * + * For example, changing "./http://foo" into "http://foo/" would change + * semantics and hence the dot segment is essential to that case and + * cannot be removed. + * + * Other examples that would change semantics are: + * - cutting "/.//" down to "//" + * - cutting "scheme:/.//" down to "scheme://". + */ + removeSegment = URI_TRUE; + if ((walker == uri->pathHead) && (walker->next != NULL)) { + /* Detect case "/.//" (with or without scheme) */ + if ((walker->next->text.first == walker->next->text.afterLast) + && (URI_FUNC(HasHost)(uri) == URI_FALSE)) { + removeSegment = URI_FALSE; + /* Detect case "./withcolon:" */ + } else if (relative) { + const URI_CHAR * ch = walker->next->text.first; + for (; ch < walker->next->text.afterLast; ch++) { + if (*ch == _UT(':')) { + removeSegment = URI_FALSE; + break; + } + } + } + } + + if (removeSegment) { + /* .. then let's go remove that segment. */ + /* Last segment? */ + if (walker->next != NULL) { + /* Not last segment, i.e. first or middle segment + * OLD: (prev|NULL) <- walker <- next + * NEW: (prev|NULL) <----------- next */ + walker->next->reserved = prev; + + if (prev == NULL) { + /* First but not last segment + * OLD: head -> walker -> next + * NEW: head -----------> next */ + uri->pathHead = walker->next; + } else { + /* Middle segment + * OLD: prev -> walker -> next + * NEW: prev -----------> next */ + prev->next = walker->next; + } + + if (pathOwned && (walker->text.first != walker->text.afterLast)) { + memory->free(memory, (URI_CHAR *)walker->text.first); + } + memory->free(memory, walker); + } else { + /* Last segment */ + if (pathOwned && (walker->text.first != walker->text.afterLast)) { + memory->free(memory, (URI_CHAR *)walker->text.first); + } + + if (prev == NULL) { + /* Last and first */ + 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); + } else { + memory->free(memory, walker); + + uri->pathHead = NULL; + uri->pathTail = NULL; + } + } else { + /* Last but not first, replace "." with empty segment to + * represent trailing slash */ + walker->text.first = URI_FUNC(SafeToPointTo); + walker->text.afterLast = URI_FUNC(SafeToPointTo); + } + } + + walker = nextBackup; + } + } + break; + + case 2: + if (((walker->text.first)[0] == _UT('.')) + && ((walker->text.first)[1] == _UT('.'))) { + /* Path ".." -> remove this and the previous segment */ + URI_TYPE(PathSegment) * const prev = walker->reserved; + URI_TYPE(PathSegment) * prevPrev; + URI_TYPE(PathSegment) * const nextBackup = walker->next; + + removeSegment = URI_TRUE; + if (relative) { + if (prev == NULL) { + /* We cannot remove traversal beyond because the + * URI is relative and may be resolved later. + * So we can simplify "a/../b/d" to "b/d" but + * we cannot simplify "../b/d" (outside of reference resolution). + */ + removeSegment = URI_FALSE; + } else if ((prev != NULL) + && ((prev->text.afterLast - prev->text.first) == 2) + && ((prev->text.first)[0] == _UT('.')) + && ((prev->text.first)[1] == _UT('.'))) { + /* We need to protect against mis-simplifying "a/../../b" to + * "a/b". */ + removeSegment = URI_FALSE; + } + } + + if (removeSegment) { + if (prev != NULL) { + /* Not first segment */ + prevPrev = prev->reserved; + if (prevPrev != NULL) { + /* Not even prev is the first one + * OLD: prevPrev -> prev -> walker -> (next|NULL) + * NEW: prevPrev -------------------> (next|NULL) */ + prevPrev->next = walker->next; + if (walker->next != NULL) { + /* Update parent relationship as well + * OLD: prevPrev <- prev <- walker <- next + * NEW: prevPrev <------------------- next */ + walker->next->reserved = prevPrev; + } else { + /* Last segment -> insert "" segment to represent trailing + * slash, update tail */ + URI_TYPE(PathSegment) * const segment = memory->calloc( + memory, 1, sizeof(URI_TYPE(PathSegment))); + if (segment == NULL) { + if (pathOwned + && (walker->text.first + != walker->text.afterLast)) { + memory->free(memory, + (URI_CHAR *)walker->text.first); + } + memory->free(memory, walker); + + if (pathOwned + && (prev->text.first != prev->text.afterLast)) { + memory->free(memory, + (URI_CHAR *)prev->text.first); + } + memory->free(memory, prev); + + return URI_FALSE; /* Raises malloc error */ + } + segment->text.first = URI_FUNC(SafeToPointTo); + segment->text.afterLast = URI_FUNC(SafeToPointTo); + prevPrev->next = segment; + uri->pathTail = segment; + } + + if (pathOwned + && (walker->text.first != walker->text.afterLast)) { + memory->free(memory, (URI_CHAR *)walker->text.first); + } + memory->free(memory, walker); + + if (pathOwned && (prev->text.first != prev->text.afterLast)) { + memory->free(memory, (URI_CHAR *)prev->text.first); + } + memory->free(memory, prev); + + walker = nextBackup; + } else { + /* Prev is the first segment */ + if (walker->next != NULL) { + uri->pathHead = walker->next; + walker->next->reserved = NULL; + + if (pathOwned + && (walker->text.first != walker->text.afterLast)) { + memory->free(memory, (URI_CHAR *)walker->text.first); + } + memory->free(memory, walker); + } else { + /* Reuse segment for "" path segment to represent trailing + * slash, update tail */ + URI_TYPE(PathSegment) * const segment = walker; + if (pathOwned + && (segment->text.first != segment->text.afterLast)) { + memory->free(memory, (URI_CHAR *)segment->text.first); + } + segment->text.first = URI_FUNC(SafeToPointTo); + segment->text.afterLast = URI_FUNC(SafeToPointTo); + uri->pathHead = segment; + uri->pathTail = segment; + } + + if (pathOwned && (prev->text.first != prev->text.afterLast)) { + memory->free(memory, (URI_CHAR *)prev->text.first); + } + memory->free(memory, prev); + + walker = nextBackup; + } + } else { + URI_TYPE(PathSegment) * const anotherNextBackup = walker->next; + int freeWalker = URI_TRUE; + + /* First segment */ + if (walker->next != NULL) { + /* First segment of multiple -> update head + * OLD: head -> walker -> next + * NEW: head -----------> next */ + uri->pathHead = walker->next; + + /* Update parent link as well + * OLD: head <- walker <- next + * NEW: head <----------- next */ + walker->next->reserved = NULL; + } else { + if (uri->absolutePath) { + /* First and only segment -> update head + * OLD: head -> walker -> NULL + * NEW: head -----------> NULL */ + uri->pathHead = NULL; + + /* Last segment -> update tail + * OLD: tail -> walker + * NEW: tail -> NULL */ + uri->pathTail = NULL; + } else { + /* Reuse segment for "" path segment to represent trailing + * slash, then update head and tail */ + if (pathOwned + && (walker->text.first != walker->text.afterLast)) { + memory->free(memory, (URI_CHAR *)walker->text.first); + } + walker->text.first = URI_FUNC(SafeToPointTo); + walker->text.afterLast = URI_FUNC(SafeToPointTo); + freeWalker = URI_FALSE; + } + } + + if (freeWalker) { + if (pathOwned + && (walker->text.first != walker->text.afterLast)) { + memory->free(memory, (URI_CHAR *)walker->text.first); + } + memory->free(memory, walker); + } + + walker = anotherNextBackup; + } + } + } + break; + } /* end of switch */ + + if (!removeSegment) { + /* .. then let's move to the next element, and start again. */ + if (walker->next != NULL) { + walker->next->reserved = walker; + } else { + /* Last segment -> update tail */ + uri->pathTail = walker; + } + walker = walker->next; + } + } while (walker != NULL); + + return URI_TRUE; } - - /* Properly removes "." and ".." path segments */ UriBool URI_FUNC(RemoveDotSegmentsAbsolute)(URI_TYPE(Uri) * uri, - UriMemoryManager * memory) { - const UriBool ABSOLUTE = URI_FALSE; - if (uri == NULL) { - return URI_TRUE; - } - return URI_FUNC(RemoveDotSegmentsEx)(uri, ABSOLUTE, uri->owner, memory); + UriMemoryManager * memory) { + const UriBool ABSOLUTE = URI_FALSE; + if (uri == NULL) { + return URI_TRUE; + } + return URI_FUNC(RemoveDotSegmentsEx)(uri, ABSOLUTE, uri->owner, memory); } - - unsigned char URI_FUNC(HexdigToInt)(URI_CHAR hexdig) { - switch (hexdig) { - case _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'): - return (unsigned char)(9 + hexdig - _UT('9')); - - case _UT('a'): - case _UT('b'): - case _UT('c'): - case _UT('d'): - case _UT('e'): - case _UT('f'): - return (unsigned char)(15 + hexdig - _UT('f')); - - case _UT('A'): - case _UT('B'): - case _UT('C'): - case _UT('D'): - case _UT('E'): - case _UT('F'): - return (unsigned char)(15 + hexdig - _UT('F')); - - default: - return 0; - } -} - - - -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); + switch (hexdig) { + case URI_SET_DIGIT(_UT): + return (unsigned char)(9 + hexdig - _UT('9')); + case URI_SET_HEX_LETTER_LOWER(_UT): + return (unsigned char)(15 + hexdig - _UT('f')); + case URI_SET_HEX_LETTER_UPPER(_UT): + return (unsigned char)(15 + hexdig - _UT('F')); + + default: + return 0; + } } - - URI_CHAR URI_FUNC(HexToLetterEx)(unsigned int value, UriBool uppercase) { - switch (value) { - case 0: return _UT('0'); - case 1: return _UT('1'); - case 2: return _UT('2'); - case 3: return _UT('3'); - case 4: return _UT('4'); - case 5: return _UT('5'); - case 6: return _UT('6'); - case 7: return _UT('7'); - case 8: return _UT('8'); - case 9: return _UT('9'); - - case 10: return (uppercase == URI_TRUE) ? _UT('A') : _UT('a'); - case 11: return (uppercase == URI_TRUE) ? _UT('B') : _UT('b'); - case 12: return (uppercase == URI_TRUE) ? _UT('C') : _UT('c'); - case 13: return (uppercase == URI_TRUE) ? _UT('D') : _UT('d'); - case 14: return (uppercase == URI_TRUE) ? _UT('E') : _UT('e'); - default: return (uppercase == URI_TRUE) ? _UT('F') : _UT('f'); - } + switch (value) { + case 0: + return _UT('0'); + case 1: + return _UT('1'); + case 2: + return _UT('2'); + case 3: + return _UT('3'); + case 4: + return _UT('4'); + case 5: + return _UT('5'); + case 6: + return _UT('6'); + case 7: + return _UT('7'); + case 8: + return _UT('8'); + case 9: + return _UT('9'); + + case 10: + return (uppercase == URI_TRUE) ? _UT('A') : _UT('a'); + case 11: + return (uppercase == URI_TRUE) ? _UT('B') : _UT('b'); + case 12: + return (uppercase == URI_TRUE) ? _UT('C') : _UT('c'); + case 13: + return (uppercase == URI_TRUE) ? _UT('D') : _UT('d'); + case 14: + return (uppercase == URI_TRUE) ? _UT('E') : _UT('e'); + default: + return (uppercase == URI_TRUE) ? _UT('F') : _UT('f'); + } } - - /* Checks if a URI has the host component set. */ UriBool URI_FUNC(HasHost)(const URI_TYPE(Uri) * uri) { - return (uri != NULL) - && ((uri->hostText.first != NULL) - || (uri->hostData.ip4 != NULL) - || (uri->hostData.ip6 != NULL) - || (uri->hostData.ipFuture.first != NULL) - ); + /* 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)); } +/* Copies the path segment list from one URI to another. */ +UriBool URI_FUNC(CopyPath)(URI_TYPE(Uri) * dest, const URI_TYPE(Uri) * source, + UriMemoryManager * memory) { + if (source->pathHead == NULL) { + /* No path component */ + dest->pathHead = NULL; + dest->pathTail = NULL; + } else { + /* Copy list but not the text contained */ + URI_TYPE(PathSegment) * sourceWalker = source->pathHead; + URI_TYPE(PathSegment) * destPrev = NULL; + do { + URI_TYPE(PathSegment) * cur = + memory->malloc(memory, sizeof(URI_TYPE(PathSegment))); + if (cur == NULL) { + /* Fix broken list */ + if (destPrev != NULL) { + destPrev->next = NULL; + } + return URI_FALSE; /* Raises malloc error */ + } + + /* From this functions usage we know that * + * the dest URI cannot be uri->owner */ + cur->text = sourceWalker->text; + if (destPrev == NULL) { + /* First segment ever */ + dest->pathHead = cur; + } else { + destPrev->next = cur; + } + destPrev = cur; + sourceWalker = sourceWalker->next; + } while (sourceWalker != NULL); + dest->pathTail = destPrev; + dest->pathTail->next = NULL; + } + + dest->absolutePath = source->absolutePath; + return URI_TRUE; +} +/* Copies the authority part of an URI over to another. */ +UriBool URI_FUNC(CopyAuthority)(URI_TYPE(Uri) * dest, const URI_TYPE(Uri) * source, + UriMemoryManager * memory) { + /* From this functions usage we know that * + * the dest URI cannot be uri->owner */ + + /* Copy userInfo */ + dest->userInfo = source->userInfo; + + /* Copy hostText */ + dest->hostText = source->hostText; + + /* Copy hostData */ + if (source->hostData.ip4 != NULL) { + dest->hostData.ip4 = memory->malloc(memory, sizeof(UriIp4)); + if (dest->hostData.ip4 == NULL) { + return URI_FALSE; /* Raises malloc error */ + } + *(dest->hostData.ip4) = *(source->hostData.ip4); + dest->hostData.ip6 = NULL; + dest->hostData.ipFuture.first = NULL; + dest->hostData.ipFuture.afterLast = NULL; + } else if (source->hostData.ip6 != NULL) { + dest->hostData.ip4 = NULL; + dest->hostData.ip6 = memory->malloc(memory, sizeof(UriIp6)); + if (dest->hostData.ip6 == NULL) { + return URI_FALSE; /* Raises malloc error */ + } + *(dest->hostData.ip6) = *(source->hostData.ip6); + dest->hostData.ipFuture.first = NULL; + dest->hostData.ipFuture.afterLast = NULL; + } else { + dest->hostData.ip4 = NULL; + dest->hostData.ip6 = NULL; + dest->hostData.ipFuture = source->hostData.ipFuture; + } + + /* Copy portText */ + dest->portText = source->portText; + + return URI_TRUE; +} -/* Copies the path segment list from one URI to another. */ -UriBool URI_FUNC(CopyPath)(URI_TYPE(Uri) * dest, - const URI_TYPE(Uri) * source, UriMemoryManager * memory) { - if (source->pathHead == NULL) { - /* No path component */ - dest->pathHead = NULL; - dest->pathTail = NULL; - } else { - /* Copy list but not the text contained */ - URI_TYPE(PathSegment) * sourceWalker = source->pathHead; - URI_TYPE(PathSegment) * destPrev = NULL; - do { - URI_TYPE(PathSegment) * cur = memory->malloc(memory, sizeof(URI_TYPE(PathSegment))); - if (cur == NULL) { - /* Fix broken list */ - if (destPrev != NULL) { - destPrev->next = NULL; - } - return URI_FALSE; /* Raises malloc error */ - } - - /* From this functions usage we know that * - * the dest URI cannot be uri->owner */ - cur->text = sourceWalker->text; - if (destPrev == NULL) { - /* First segment ever */ - dest->pathHead = cur; - } else { - destPrev->next = cur; - } - destPrev = cur; - sourceWalker = sourceWalker->next; - } while (sourceWalker != NULL); - dest->pathTail = destPrev; - dest->pathTail->next = NULL; - } - - dest->absolutePath = source->absolutePath; - return URI_TRUE; +UriBool URI_FUNC(FixAmbiguity)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) { + URI_TYPE(PathSegment) * segment; + + if (/* Case 1: absolute path, empty first segment */ + (uri->absolutePath && (uri->pathHead != NULL) + && (uri->pathHead->text.afterLast == uri->pathHead->text.first)) + + /* Case 2: relative path, empty first and second segment */ + || (!uri->absolutePath && (uri->pathHead != NULL) && (uri->pathHead->next != NULL) + && (uri->pathHead->text.afterLast == uri->pathHead->text.first) + && (uri->pathHead->next->text.afterLast + == uri->pathHead->next->text.first))) { + /* NOOP */ + } else { + return URI_TRUE; + } + + segment = memory->malloc(memory, 1 * sizeof(URI_TYPE(PathSegment))); + if (segment == NULL) { + return URI_FALSE; /* Raises malloc error */ + } + + /* Insert "." segment in front */ + segment->next = uri->pathHead; + segment->text.first = URI_FUNC(ConstPwd); + segment->text.afterLast = URI_FUNC(ConstPwd) + 1; + uri->pathHead = segment; + return URI_TRUE; } +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))); -/* Copies the authority part of an URI over to another. */ -UriBool URI_FUNC(CopyAuthority)(URI_TYPE(Uri) * dest, - const URI_TYPE(Uri) * source, UriMemoryManager * memory) { - /* From this functions usage we know that * - * the dest URI cannot be uri->owner */ - - /* Copy userInfo */ - dest->userInfo = source->userInfo; - - /* Copy hostText */ - dest->hostText = source->hostText; - - /* Copy hostData */ - if (source->hostData.ip4 != NULL) { - dest->hostData.ip4 = memory->malloc(memory, sizeof(UriIp4)); - if (dest->hostData.ip4 == NULL) { - return URI_FALSE; /* Raises malloc error */ - } - *(dest->hostData.ip4) = *(source->hostData.ip4); - dest->hostData.ip6 = NULL; - dest->hostData.ipFuture.first = NULL; - dest->hostData.ipFuture.afterLast = NULL; - } else if (source->hostData.ip6 != NULL) { - dest->hostData.ip4 = NULL; - dest->hostData.ip6 = memory->malloc(memory, sizeof(UriIp6)); - if (dest->hostData.ip6 == NULL) { - return URI_FALSE; /* Raises malloc error */ - } - *(dest->hostData.ip6) = *(source->hostData.ip6); - dest->hostData.ipFuture.first = NULL; - dest->hostData.ipFuture.afterLast = NULL; - } else { - dest->hostData.ip4 = NULL; - dest->hostData.ip6 = NULL; - dest->hostData.ipFuture = source->hostData.ipFuture; - } - - /* Copy portText */ - dest->portText = source->portText; - - return URI_TRUE; -} + 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; -UriBool URI_FUNC(FixAmbiguity)(URI_TYPE(Uri) * uri, - UriMemoryManager * memory) { - URI_TYPE(PathSegment) * segment; - - if ( /* Case 1: absolute path, empty first segment */ - (uri->absolutePath - && (uri->pathHead != NULL) - && (uri->pathHead->text.afterLast == uri->pathHead->text.first)) - - /* Case 2: relative path, empty first and second segment */ - || (!uri->absolutePath - && (uri->pathHead != NULL) - && (uri->pathHead->next != NULL) - && (uri->pathHead->text.afterLast == uri->pathHead->text.first) - && (uri->pathHead->next->text.afterLast == uri->pathHead->next->text.first))) { - /* NOOP */ - } else { - return URI_TRUE; - } - - segment = memory->malloc(memory, 1 * sizeof(URI_TYPE(PathSegment))); - if (segment == NULL) { - return URI_FALSE; /* Raises malloc error */ - } - - /* Insert "." segment in front */ - segment->next = uri->pathHead; - segment->text.first = URI_FUNC(ConstPwd); - segment->text.afterLast = URI_FUNC(ConstPwd) + 1; - uri->pathHead = segment; - return URI_TRUE; -} + 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; +} -void URI_FUNC(FixEmptyTrailSegment)(URI_TYPE(Uri) * uri, - UriMemoryManager * memory) { - /* Fix path if only one empty segment */ - if (!uri->absolutePath - && !URI_FUNC(HasHost)(uri) - && (uri->pathHead != NULL) - && (uri->pathHead->next == NULL) - && (uri->pathHead->text.first == uri->pathHead->text.afterLast)) { - memory->free(memory, uri->pathHead); - uri->pathHead = NULL; - uri->pathTail = NULL; - } +/* 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 artificial "." 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 artificial "." 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(HasHost)(uri) && (uri->pathHead != NULL) + && (uri->pathHead->next == NULL) + && (uri->pathHead->text.first == uri->pathHead->text.afterLast)) { + memory->free(memory, uri->pathHead); + uri->pathHead = NULL; + uri->pathTail = NULL; + } +} #endif diff --git a/ext/uri/uriparser/src/UriCommon.h b/ext/uri/uriparser/src/UriCommon.h index 8dffab9f9f602..d141935f19e5a 100644 --- a/ext/uri/uriparser/src/UriCommon.h +++ b/ext/uri/uriparser/src/UriCommon.h @@ -38,35 +38,34 @@ */ #if (defined(URI_PASS_ANSI) && !defined(URI_COMMON_H_ANSI)) \ - || (defined(URI_PASS_UNICODE) && !defined(URI_COMMON_H_UNICODE)) \ - || (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) + || (defined(URI_PASS_UNICODE) && !defined(URI_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 +# if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) /* Include SELF twice */ -# ifdef URI_ENABLE_ANSI -# define URI_PASS_ANSI 1 -# include "UriCommon.h" -# undef URI_PASS_ANSI -# endif -# ifdef URI_ENABLE_UNICODE -# define URI_PASS_UNICODE 1 -# include "UriCommon.h" -# undef URI_PASS_UNICODE -# endif +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriCommon.h" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriCommon.h" +# undef URI_PASS_UNICODE +# endif /* Only one pass for each encoding */ -#elif (defined(URI_PASS_ANSI) && !defined(URI_COMMON_H_ANSI) \ - && defined(URI_ENABLE_ANSI)) || (defined(URI_PASS_UNICODE) \ - && !defined(URI_COMMON_H_UNICODE) && defined(URI_ENABLE_UNICODE)) -# ifdef URI_PASS_ANSI -# define URI_COMMON_H_ANSI 1 -# include -# else -# define URI_COMMON_H_UNICODE 1 -# include -# endif - - +# elif (defined(URI_PASS_ANSI) && !defined(URI_COMMON_H_ANSI) \ + && defined(URI_ENABLE_ANSI)) \ + || (defined(URI_PASS_UNICODE) && !defined(URI_COMMON_H_UNICODE) \ + && defined(URI_ENABLE_UNICODE)) +# ifdef URI_PASS_ANSI +# define URI_COMMON_H_ANSI 1 +# include +# else +# define URI_COMMON_H_UNICODE 1 +# include +# endif /* Used to point to from empty path segments. * X.first and X.afterLast must be the same non-NULL value then. */ @@ -74,37 +73,37 @@ extern const URI_CHAR * const URI_FUNC(SafeToPointTo); extern const URI_CHAR * const URI_FUNC(ConstPwd); extern const URI_CHAR * const URI_FUNC(ConstParent); - - void URI_FUNC(ResetUri)(URI_TYPE(Uri) * uri); -int URI_FUNC(CompareRange)( - const URI_TYPE(TextRange) * a, - const URI_TYPE(TextRange) * b); +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); + const URI_TYPE(TextRange) * sourceRange, + UriMemoryManager * memory); UriBool URI_FUNC(CopyRangeAsNeeded)(URI_TYPE(TextRange) * destRange, - const URI_TYPE(TextRange) * sourceRange, UriBool useSafe, UriMemoryManager * memory); + 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); + 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(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); + 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); -void URI_FUNC(FixEmptyTrailSegment)(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); -#endif +# endif #endif diff --git a/ext/uri/uriparser/src/UriCompare.c b/ext/uri/uriparser/src/UriCompare.c index bca3db92361d9..781100e7e6f49 100644 --- a/ext/uri/uriparser/src/UriCompare.c +++ b/ext/uri/uriparser/src/UriCompare.c @@ -41,128 +41,120 @@ #include #if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) /* Include SELF twice */ -# ifdef URI_ENABLE_ANSI -# define URI_PASS_ANSI 1 -# include "UriCompare.c" -# undef URI_PASS_ANSI -# endif -# ifdef URI_ENABLE_UNICODE -# define URI_PASS_UNICODE 1 -# include "UriCompare.c" -# undef URI_PASS_UNICODE -# endif +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriCompare.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriCompare.c" +# undef URI_PASS_UNICODE +# endif #else -# ifdef URI_PASS_ANSI -# include -# else -# include -# include -# endif - - - -#ifndef URI_DOXYGEN -# include -# include -# include "UriCommon.h" -#endif - - - -UriBool URI_FUNC(EqualsUri)(const URI_TYPE(Uri) * a, - const URI_TYPE(Uri) * b) { - /* NOTE: Both NULL means equal! */ - if ((a == NULL) || (b == NULL)) { - return ((a == NULL) && (b == NULL)) ? URI_TRUE : URI_FALSE; - } - - /* scheme */ - if (URI_FUNC(CompareRange)(&(a->scheme), &(b->scheme))) { - return URI_FALSE; - } - - /* absolutePath */ - if ((a->scheme.first == NULL)&& (a->absolutePath != b->absolutePath)) { - return URI_FALSE; - } - - /* userInfo */ - if (URI_FUNC(CompareRange)(&(a->userInfo), &(b->userInfo))) { - return URI_FALSE; - } - - /* Host */ - if (((a->hostData.ip4 == NULL) != (b->hostData.ip4 == NULL)) - || ((a->hostData.ip6 == NULL) != (b->hostData.ip6 == NULL)) - || ((a->hostData.ipFuture.first == NULL) - != (b->hostData.ipFuture.first == NULL))) { - return URI_FALSE; - } - - if (a->hostData.ip4 != NULL) { - if (memcmp(a->hostData.ip4->data, b->hostData.ip4->data, 4)) { - return URI_FALSE; - } - } - - if (a->hostData.ip6 != NULL) { - if (memcmp(a->hostData.ip6->data, b->hostData.ip6->data, 16)) { - return URI_FALSE; - } - } - - if (a->hostData.ipFuture.first != NULL) { - if (URI_FUNC(CompareRange)(&(a->hostData.ipFuture), &(b->hostData.ipFuture))) { - return URI_FALSE; - } - } - - if ((a->hostData.ip4 == NULL) - && (a->hostData.ip6 == NULL) - && (a->hostData.ipFuture.first == NULL)) { - if (URI_FUNC(CompareRange)(&(a->hostText), &(b->hostText))) { - return URI_FALSE; - } - } - - /* portText */ - if (URI_FUNC(CompareRange)(&(a->portText), &(b->portText))) { - return URI_FALSE; - } - - /* Path */ - if ((a->pathHead == NULL) != (b->pathHead == NULL)) { - return URI_FALSE; - } - - if (a->pathHead != NULL) { - URI_TYPE(PathSegment) * walkA = a->pathHead; - URI_TYPE(PathSegment) * walkB = b->pathHead; - do { - if (URI_FUNC(CompareRange)(&(walkA->text), &(walkB->text))) { - return URI_FALSE; - } - if ((walkA->next == NULL) != (walkB->next == NULL)) { - return URI_FALSE; - } - walkA = walkA->next; - walkB = walkB->next; - } while (walkA != NULL); - } - - /* query */ - if (URI_FUNC(CompareRange)(&(a->query), &(b->query))) { - return URI_FALSE; - } - - /* fragment */ - if (URI_FUNC(CompareRange)(&(a->fragment), &(b->fragment))) { - return URI_FALSE; - } - - return URI_TRUE; /* Equal*/ +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif + +# ifndef URI_DOXYGEN +# include +# include +# include "UriCommon.h" +# endif + +UriBool URI_FUNC(EqualsUri)(const URI_TYPE(Uri) * a, const URI_TYPE(Uri) * b) { + /* NOTE: Both NULL means equal! */ + if ((a == NULL) || (b == NULL)) { + return ((a == NULL) && (b == NULL)) ? URI_TRUE : URI_FALSE; + } + + /* scheme */ + if (URI_FUNC(CompareRange)(&(a->scheme), &(b->scheme))) { + return URI_FALSE; + } + + /* absolutePath */ + if ((a->scheme.first == NULL) && (a->absolutePath != b->absolutePath)) { + return URI_FALSE; + } + + /* userInfo */ + if (URI_FUNC(CompareRange)(&(a->userInfo), &(b->userInfo))) { + return URI_FALSE; + } + + /* Host */ + if (((a->hostData.ip4 == NULL) != (b->hostData.ip4 == NULL)) + || ((a->hostData.ip6 == NULL) != (b->hostData.ip6 == NULL)) + || ((a->hostData.ipFuture.first == NULL) + != (b->hostData.ipFuture.first == NULL))) { + return URI_FALSE; + } + + if (a->hostData.ip4 != NULL) { + if (memcmp(a->hostData.ip4->data, b->hostData.ip4->data, 4)) { + return URI_FALSE; + } + } + + if (a->hostData.ip6 != NULL) { + if (memcmp(a->hostData.ip6->data, b->hostData.ip6->data, 16)) { + return URI_FALSE; + } + } + + if (a->hostData.ipFuture.first != NULL) { + if (URI_FUNC(CompareRange)(&(a->hostData.ipFuture), &(b->hostData.ipFuture))) { + return URI_FALSE; + } + } + + if ((a->hostData.ip4 == NULL) && (a->hostData.ip6 == NULL) + && (a->hostData.ipFuture.first == NULL)) { + if (URI_FUNC(CompareRange)(&(a->hostText), &(b->hostText))) { + return URI_FALSE; + } + } + + /* portText */ + if (URI_FUNC(CompareRange)(&(a->portText), &(b->portText))) { + return URI_FALSE; + } + + /* Path */ + if ((a->pathHead == NULL) != (b->pathHead == NULL)) { + return URI_FALSE; + } + + if (a->pathHead != NULL) { + URI_TYPE(PathSegment) * walkA = a->pathHead; + URI_TYPE(PathSegment) * walkB = b->pathHead; + do { + if (URI_FUNC(CompareRange)(&(walkA->text), &(walkB->text))) { + return URI_FALSE; + } + if ((walkA->next == NULL) != (walkB->next == NULL)) { + return URI_FALSE; + } + walkA = walkA->next; + walkB = walkB->next; + } while (walkA != NULL); + } + + /* query */ + if (URI_FUNC(CompareRange)(&(a->query), &(b->query))) { + return URI_FALSE; + } + + /* fragment */ + if (URI_FUNC(CompareRange)(&(a->fragment), &(b->fragment))) { + return URI_FALSE; + } + + return URI_TRUE; /* Equal*/ } - - #endif diff --git a/ext/uri/uriparser/src/UriConfig.h b/ext/uri/uriparser/src/UriConfig.h index 3139da04f72c1..e265c0a9a1154 100644 --- a/ext/uri/uriparser/src/UriConfig.h +++ b/ext/uri/uriparser/src/UriConfig.h @@ -37,17 +37,13 @@ */ #if !defined(URI_CONFIG_H) -# define URI_CONFIG_H 1 +# define URI_CONFIG_H 1 - - -#define PACKAGE_VERSION "0.9.8" +# define PACKAGE_VERSION "@PROJECT_VERSION@" /* -#define HAVE_WPRINTF* +#define HAVE_WPRINTF #define HAVE_REALLOCARRAY */ - - -#endif /* !defined(URI_CONFIG_H) */ +#endif /* !defined(URI_CONFIG_H) */ diff --git a/ext/uri/uriparser/src/UriConfig.h.in b/ext/uri/uriparser/src/UriConfig.h.in index a16a93381c102..b9a85a8fe02af 100644 --- a/ext/uri/uriparser/src/UriConfig.h.in +++ b/ext/uri/uriparser/src/UriConfig.h.in @@ -37,15 +37,11 @@ */ #if !defined(URI_CONFIG_H) -# define URI_CONFIG_H 1 +# define URI_CONFIG_H 1 - - -#define PACKAGE_VERSION "@PROJECT_VERSION@" +# define PACKAGE_VERSION "@PROJECT_VERSION@" #cmakedefine HAVE_WPRINTF #cmakedefine HAVE_REALLOCARRAY - - -#endif /* !defined(URI_CONFIG_H) */ +#endif /* !defined(URI_CONFIG_H) */ diff --git a/ext/uri/uriparser/src/UriCopy.c b/ext/uri/uriparser/src/UriCopy.c index 103e2e7796751..3bc6b0dbe3f4c 100644 --- a/ext/uri/uriparser/src/UriCopy.c +++ b/ext/uri/uriparser/src/UriCopy.c @@ -48,192 +48,195 @@ #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 +# 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 - - +# 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; - } + 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 doneMask = 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, URI_FALSE, memory) == URI_FALSE) { - return URI_ERROR_MALLOC; - } - - doneMask |= URI_NORMALIZE_SCHEME; - - if (URI_FUNC(CopyRangeAsNeeded)(&destUri->userInfo, &sourceUri->userInfo, URI_FALSE, memory) == URI_FALSE) { - URI_FUNC(PreventLeakageAfterCopy)(destUri, doneMask, memory); - return URI_ERROR_MALLOC; - } - - doneMask |= URI_NORMALIZE_USER_INFO; - - if (URI_FUNC(CopyRangeAsNeeded)(&destUri->hostText, &sourceUri->hostText, URI_TRUE, memory) == URI_FALSE) { - URI_FUNC(PreventLeakageAfterCopy)(destUri, doneMask, memory); - return URI_ERROR_MALLOC; - } - - doneMask |= 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, doneMask, 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, doneMask, memory); - return URI_ERROR_MALLOC; - } - *(destUri->hostData.ip6) = *(sourceUri->hostData.ip6); - } - - if (sourceUri->hostData.ipFuture.first != NULL && sourceUri->hostText.first == sourceUri->hostData.ipFuture.first) { - 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, URI_FALSE, memory) == URI_FALSE) { - URI_FUNC(PreventLeakageAfterCopy)(destUri, doneMask, memory); - return URI_ERROR_MALLOC; - } - - if (URI_FUNC(CopyRangeAsNeeded)(&destUri->portText, &sourceUri->portText, URI_FALSE, memory) == URI_FALSE) { - URI_FUNC(PreventLeakageAfterCopy)(destUri, doneMask, memory); - return URI_ERROR_MALLOC; - } - - doneMask |= 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, doneMask, 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; - doneMask |= URI_NORMALIZE_PATH; - } - - if (URI_FUNC(CopyRangeAsNeeded)(&destWalker->text, &sourceWalker->text, URI_TRUE, memory) == URI_FALSE) { - URI_FUNC(PreventLeakageAfterCopy)(destUri, doneMask, 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, URI_FALSE, memory) == URI_FALSE) { - URI_FUNC(PreventLeakageAfterCopy)(destUri, doneMask, memory); - return URI_ERROR_MALLOC; - } - - doneMask |= URI_NORMALIZE_QUERY; - - if (URI_FUNC(CopyRangeAsNeeded)(&destUri->fragment, &sourceUri->fragment, URI_FALSE, memory) == URI_FALSE) { - URI_FUNC(PreventLeakageAfterCopy)(destUri, doneMask, memory); - return URI_ERROR_MALLOC; - } - - destUri->absolutePath = sourceUri->absolutePath; - destUri->owner = URI_TRUE; - destUri->reserved = NULL; - - return URI_SUCCESS; +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); +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 index 952b1df4f9cb3..430f5dc6da24a 100644 --- a/ext/uri/uriparser/src/UriCopy.h +++ b/ext/uri/uriparser/src/UriCopy.h @@ -39,40 +39,38 @@ */ #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)) + || (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 +# 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 +# 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 +# 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); - -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 #endif diff --git a/ext/uri/uriparser/src/UriEscape.c b/ext/uri/uriparser/src/UriEscape.c index ab8305fa9735c..a1763f97153cf 100644 --- a/ext/uri/uriparser/src/UriEscape.c +++ b/ext/uri/uriparser/src/UriEscape.c @@ -41,413 +41,293 @@ #include #if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) /* Include SELF twice */ -# ifdef URI_ENABLE_ANSI -# define URI_PASS_ANSI 1 -# include "UriEscape.c" -# undef URI_PASS_ANSI -# endif -# ifdef URI_ENABLE_UNICODE -# define URI_PASS_UNICODE 1 -# include "UriEscape.c" -# undef URI_PASS_UNICODE -# endif +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriEscape.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriEscape.c" +# undef URI_PASS_UNICODE +# endif #else -# ifdef URI_PASS_ANSI -# include -# else -# include -# include -# endif - - - -#ifndef URI_DOXYGEN -# include -# include "UriCommon.h" -#endif - - - -URI_CHAR * URI_FUNC(Escape)(const URI_CHAR * in, URI_CHAR * out, - UriBool spaceToPlus, UriBool normalizeBreaks) { - return URI_FUNC(EscapeEx)(in, NULL, out, spaceToPlus, normalizeBreaks); +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif + +# ifndef URI_DOXYGEN +# include +# include "UriCommon.h" +# include "UriSets.h" +# endif + +URI_CHAR * URI_FUNC(Escape)(const URI_CHAR * in, URI_CHAR * out, UriBool spaceToPlus, + UriBool normalizeBreaks) { + return URI_FUNC(EscapeEx)(in, NULL, out, spaceToPlus, normalizeBreaks); } - - -URI_CHAR * URI_FUNC(EscapeEx)(const URI_CHAR * inFirst, - const URI_CHAR * inAfterLast, URI_CHAR * out, - UriBool spaceToPlus, UriBool normalizeBreaks) { - const URI_CHAR * read = inFirst; - URI_CHAR * write = out; - UriBool prevWasCr = URI_FALSE; - if ((out == NULL) || (inFirst == out)) { - return NULL; - } else if (inFirst == NULL) { - if (out != NULL) { - out[0] = _UT('\0'); - } - return out; - } - - for (;;) { - if ((inAfterLast != NULL) && (read >= inAfterLast)) { - write[0] = _UT('\0'); - return write; - } - - switch (read[0]) { - case _UT('\0'): - write[0] = _UT('\0'); - return write; - - case _UT(' '): - if (spaceToPlus) { - write[0] = _UT('+'); - write++; - } else { - write[0] = _UT('%'); - write[1] = _UT('2'); - write[2] = _UT('0'); - write += 3; - } - prevWasCr = URI_FALSE; - break; - - case _UT('a'): /* ALPHA */ - case _UT('A'): - case _UT('b'): - case _UT('B'): - case _UT('c'): - case _UT('C'): - case _UT('d'): - case _UT('D'): - case _UT('e'): - case _UT('E'): - case _UT('f'): - case _UT('F'): - 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'): - case _UT('0'): /* DIGIT */ - 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'): - case _UT('-'): /* "-" / "." / "_" / "~" */ - case _UT('.'): - case _UT('_'): - case _UT('~'): - /* Copy unmodified */ - write[0] = read[0]; - write++; - - prevWasCr = URI_FALSE; - break; - - case _UT('\x0a'): - if (normalizeBreaks) { - if (!prevWasCr) { - write[0] = _UT('%'); - write[1] = _UT('0'); - write[2] = _UT('D'); - write[3] = _UT('%'); - write[4] = _UT('0'); - write[5] = _UT('A'); - write += 6; - } - } else { - write[0] = _UT('%'); - write[1] = _UT('0'); - write[2] = _UT('A'); - write += 3; - } - prevWasCr = URI_FALSE; - break; - - case _UT('\x0d'): - if (normalizeBreaks) { - write[0] = _UT('%'); - write[1] = _UT('0'); - write[2] = _UT('D'); - write[3] = _UT('%'); - write[4] = _UT('0'); - write[5] = _UT('A'); - write += 6; - } else { - write[0] = _UT('%'); - write[1] = _UT('0'); - write[2] = _UT('D'); - write += 3; - } - prevWasCr = URI_TRUE; - break; - - default: - /* Percent encode */ - { - const unsigned char code = (unsigned char)read[0]; - write[0] = _UT('%'); - write[1] = URI_FUNC(HexToLetter)(code >> 4); - write[2] = URI_FUNC(HexToLetter)(code & 0x0f); - write += 3; - } - prevWasCr = URI_FALSE; - break; - } - - read++; - } +URI_CHAR * URI_FUNC(EscapeEx)(const URI_CHAR * inFirst, const URI_CHAR * inAfterLast, + URI_CHAR * out, UriBool spaceToPlus, + UriBool normalizeBreaks) { + const URI_CHAR * read = inFirst; + URI_CHAR * write = out; + UriBool prevWasCr = URI_FALSE; + if ((out == NULL) || (inFirst == out)) { + return NULL; + } else if (inFirst == NULL) { + if (out != NULL) { + out[0] = _UT('\0'); + } + return out; + } + + for (;;) { + if ((inAfterLast != NULL) && (read >= inAfterLast)) { + write[0] = _UT('\0'); + return write; + } + + switch (read[0]) { + case _UT('\0'): + write[0] = _UT('\0'); + return write; + + case _UT(' '): + if (spaceToPlus) { + write[0] = _UT('+'); + write++; + } else { + write[0] = _UT('%'); + write[1] = _UT('2'); + write[2] = _UT('0'); + write += 3; + } + prevWasCr = URI_FALSE; + break; + + case URI_SET_UNRESERVED(_UT): + /* Copy unmodified */ + write[0] = read[0]; + write++; + + prevWasCr = URI_FALSE; + break; + + case _UT('\x0a'): + if (normalizeBreaks) { + if (!prevWasCr) { + write[0] = _UT('%'); + write[1] = _UT('0'); + write[2] = _UT('D'); + write[3] = _UT('%'); + write[4] = _UT('0'); + write[5] = _UT('A'); + write += 6; + } + } else { + write[0] = _UT('%'); + write[1] = _UT('0'); + write[2] = _UT('A'); + write += 3; + } + prevWasCr = URI_FALSE; + break; + + case _UT('\x0d'): + if (normalizeBreaks) { + write[0] = _UT('%'); + write[1] = _UT('0'); + write[2] = _UT('D'); + write[3] = _UT('%'); + write[4] = _UT('0'); + write[5] = _UT('A'); + write += 6; + } else { + write[0] = _UT('%'); + write[1] = _UT('0'); + write[2] = _UT('D'); + write += 3; + } + prevWasCr = URI_TRUE; + break; + + default: + /* 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(HexToLetterEx)(code >> 4, URI_TRUE); + write[2] = URI_FUNC(HexToLetterEx)(code & 0x0f, URI_TRUE); + write += 3; + } + prevWasCr = URI_FALSE; + break; + } + + read++; + } } - - const URI_CHAR * URI_FUNC(UnescapeInPlace)(URI_CHAR * inout) { - return URI_FUNC(UnescapeInPlaceEx)(inout, URI_FALSE, URI_BR_DONT_TOUCH); + return URI_FUNC(UnescapeInPlaceEx)(inout, URI_FALSE, URI_BR_DONT_TOUCH); } - - -const URI_CHAR * URI_FUNC(UnescapeInPlaceEx)(URI_CHAR * inout, - UriBool plusToSpace, UriBreakConversion breakConversion) { - URI_CHAR * read = inout; - URI_CHAR * write = inout; - UriBool prevWasCr = URI_FALSE; - - if (inout == NULL) { - return NULL; - } - - for (;;) { - switch (read[0]) { - case _UT('\0'): - if (read > write) { - write[0] = _UT('\0'); - } - return write; - - case _UT('%'): - switch (read[1]) { - case _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'): - case _UT('a'): - case _UT('b'): - case _UT('c'): - case _UT('d'): - case _UT('e'): - case _UT('f'): - case _UT('A'): - case _UT('B'): - case _UT('C'): - case _UT('D'): - case _UT('E'): - case _UT('F'): - switch (read[2]) { - case _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'): - case _UT('a'): - case _UT('b'): - case _UT('c'): - case _UT('d'): - case _UT('e'): - case _UT('f'): - case _UT('A'): - case _UT('B'): - case _UT('C'): - case _UT('D'): - case _UT('E'): - case _UT('F'): - { - /* Percent group found */ - const unsigned char left = URI_FUNC(HexdigToInt)(read[1]); - const unsigned char right = URI_FUNC(HexdigToInt)(read[2]); - const int code = 16 * left + right; - switch (code) { - case 10: - switch (breakConversion) { - case URI_BR_TO_LF: - if (!prevWasCr) { - write[0] = (URI_CHAR)10; - write++; - } - break; - - case URI_BR_TO_CRLF: - if (!prevWasCr) { - write[0] = (URI_CHAR)13; - write[1] = (URI_CHAR)10; - write += 2; - } - break; - - case URI_BR_TO_CR: - if (!prevWasCr) { - write[0] = (URI_CHAR)13; - write++; - } - break; - - case URI_BR_DONT_TOUCH: - default: - write[0] = (URI_CHAR)10; - write++; - - } - prevWasCr = URI_FALSE; - break; - - case 13: - switch (breakConversion) { - case URI_BR_TO_LF: - write[0] = (URI_CHAR)10; - write++; - break; - - case URI_BR_TO_CRLF: - write[0] = (URI_CHAR)13; - write[1] = (URI_CHAR)10; - write += 2; - break; - - case URI_BR_TO_CR: - write[0] = (URI_CHAR)13; - write++; - break; - - case URI_BR_DONT_TOUCH: - default: - write[0] = (URI_CHAR)13; - write++; - - } - prevWasCr = URI_TRUE; - break; - - default: - write[0] = (URI_CHAR)(code); - write++; - - prevWasCr = URI_FALSE; - - } - read += 3; - } - break; - - default: - /* Copy two chars unmodified and */ - /* look at this char again */ - if (read > write) { - write[0] = read[0]; - write[1] = read[1]; - } - read += 2; - write += 2; - - prevWasCr = URI_FALSE; - } - break; - - default: - /* Copy one char unmodified and */ - /* look at this char again */ - if (read > write) { - write[0] = read[0]; - } - read++; - write++; - - prevWasCr = URI_FALSE; - } - break; - - case _UT('+'): - if (plusToSpace) { - /* Convert '+' to ' ' */ - write[0] = _UT(' '); - } else { - /* Copy one char unmodified */ - if (read > write) { - write[0] = read[0]; - } - } - read++; - write++; - - prevWasCr = URI_FALSE; - break; - - default: - /* Copy one char unmodified */ - if (read > write) { - write[0] = read[0]; - } - read++; - write++; - - prevWasCr = URI_FALSE; - } - } +const URI_CHAR * URI_FUNC(UnescapeInPlaceEx)(URI_CHAR * inout, UriBool plusToSpace, + UriBreakConversion breakConversion) { + URI_CHAR * read = inout; + URI_CHAR * write = inout; + UriBool prevWasCr = URI_FALSE; + + if (inout == NULL) { + return NULL; + } + + for (;;) { + switch (read[0]) { + case _UT('\0'): + if (read > write) { + write[0] = _UT('\0'); + } + return write; + + case _UT('%'): + switch (read[1]) { + case URI_SET_HEXDIG(_UT): + switch (read[2]) { + case URI_SET_HEXDIG(_UT): { + /* Percent group found */ + const unsigned char left = URI_FUNC(HexdigToInt)(read[1]); + const unsigned char right = URI_FUNC(HexdigToInt)(read[2]); + const int code = 16 * left + right; + switch (code) { + case 10: + switch (breakConversion) { + case URI_BR_TO_LF: + if (!prevWasCr) { + write[0] = (URI_CHAR)10; + write++; + } + break; + + case URI_BR_TO_CRLF: + if (!prevWasCr) { + write[0] = (URI_CHAR)13; + write[1] = (URI_CHAR)10; + write += 2; + } + break; + + case URI_BR_TO_CR: + if (!prevWasCr) { + write[0] = (URI_CHAR)13; + write++; + } + break; + + case URI_BR_DONT_TOUCH: + default: + write[0] = (URI_CHAR)10; + write++; + } + prevWasCr = URI_FALSE; + break; + + case 13: + switch (breakConversion) { + case URI_BR_TO_LF: + write[0] = (URI_CHAR)10; + write++; + break; + + case URI_BR_TO_CRLF: + write[0] = (URI_CHAR)13; + write[1] = (URI_CHAR)10; + write += 2; + break; + + case URI_BR_TO_CR: + write[0] = (URI_CHAR)13; + write++; + break; + + case URI_BR_DONT_TOUCH: + default: + write[0] = (URI_CHAR)13; + write++; + } + prevWasCr = URI_TRUE; + break; + + default: + write[0] = (URI_CHAR)(code); + write++; + + prevWasCr = URI_FALSE; + } + read += 3; + } break; + + default: + /* Copy two chars unmodified and */ + /* look at this char again */ + if (read > write) { + write[0] = read[0]; + write[1] = read[1]; + } + read += 2; + write += 2; + + prevWasCr = URI_FALSE; + } + break; + + default: + /* Copy one char unmodified and */ + /* look at this char again */ + if (read > write) { + write[0] = read[0]; + } + read++; + write++; + + prevWasCr = URI_FALSE; + } + break; + + case _UT('+'): + if (plusToSpace) { + /* Convert '+' to ' ' */ + write[0] = _UT(' '); + } else { + /* Copy one char unmodified */ + if (read > write) { + write[0] = read[0]; + } + } + read++; + write++; + + prevWasCr = URI_FALSE; + break; + + default: + /* Copy one char unmodified */ + if (read > write) { + write[0] = read[0]; + } + read++; + write++; + + prevWasCr = URI_FALSE; + } + } } - - #endif diff --git a/ext/uri/uriparser/src/UriFile.c b/ext/uri/uriparser/src/UriFile.c index 232957d3c8079..7510e701c9f5c 100644 --- a/ext/uri/uriparser/src/UriFile.c +++ b/ext/uri/uriparser/src/UriFile.c @@ -41,202 +41,181 @@ #include #if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) /* Include SELF twice */ -# ifdef URI_ENABLE_ANSI -# define URI_PASS_ANSI 1 -# include "UriFile.c" -# undef URI_PASS_ANSI -# endif -# ifdef URI_ENABLE_UNICODE -# define URI_PASS_UNICODE 1 -# include "UriFile.c" -# undef URI_PASS_UNICODE -# endif +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriFile.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriFile.c" +# undef URI_PASS_UNICODE +# endif #else -# ifdef URI_PASS_ANSI -# include -# else -# include -# include -# endif - - - -#ifndef URI_DOXYGEN -# include -#endif - - - -#include /* for size_t, avoiding stddef.h for older MSVCs */ +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif +# ifndef URI_DOXYGEN +# include +# endif +# include /* for size_t, avoiding stddef.h for older MSVCs */ static URI_INLINE int URI_FUNC(FilenameToUriString)(const URI_CHAR * filename, - URI_CHAR * uriString, UriBool fromUnix) { - const URI_CHAR * input = filename; - const URI_CHAR * lastSep = input - 1; - UriBool firstSegment = URI_TRUE; - URI_CHAR * output = uriString; - UriBool absolute; - UriBool is_windows_network; - - if ((filename == NULL) || (uriString == NULL)) { - return URI_ERROR_NULL; - } - - is_windows_network = (filename[0] == _UT('\\')) && (filename[1] == _UT('\\')); - absolute = fromUnix - ? (filename[0] == _UT('/')) - : (((filename[0] != _UT('\0')) && (filename[1] == _UT(':'))) - || is_windows_network); - - if (absolute) { - const URI_CHAR * const prefix = fromUnix - ? _UT("file://") - : is_windows_network - ? _UT("file:") - : _UT("file:///"); - const size_t prefixLen = URI_STRLEN(prefix); - - /* Copy prefix */ - memcpy(uriString, prefix, prefixLen * sizeof(URI_CHAR)); - output += prefixLen; - } - - /* Copy and escape on the fly */ - for (;;) { - if ((input[0] == _UT('\0')) - || (fromUnix && input[0] == _UT('/')) - || (!fromUnix && input[0] == _UT('\\'))) { - /* Copy text after last separator */ - if (lastSep + 1 < input) { - if (!fromUnix && absolute && (firstSegment == URI_TRUE)) { - /* Quick hack to not convert "C:" to "C%3A" */ - const int charsToCopy = (int)(input - (lastSep + 1)); - memcpy(output, lastSep + 1, charsToCopy * sizeof(URI_CHAR)); - output += charsToCopy; - } else { - output = URI_FUNC(EscapeEx)(lastSep + 1, input, output, - URI_FALSE, URI_FALSE); - } - } - firstSegment = URI_FALSE; - } - - if (input[0] == _UT('\0')) { - output[0] = _UT('\0'); - break; - } else if (fromUnix && (input[0] == _UT('/'))) { - /* Copy separators unmodified */ - output[0] = _UT('/'); - output++; - lastSep = input; - } else if (!fromUnix && (input[0] == _UT('\\'))) { - /* Convert backslashes to forward slashes */ - output[0] = _UT('/'); - output++; - lastSep = input; - } - input++; - } - - return URI_SUCCESS; + URI_CHAR * uriString, + UriBool fromUnix) { + const URI_CHAR * input = filename; + const URI_CHAR * lastSep = input - 1; + UriBool firstSegment = URI_TRUE; + URI_CHAR * output = uriString; + UriBool absolute; + UriBool is_windows_network; + + if ((filename == NULL) || (uriString == NULL)) { + return URI_ERROR_NULL; + } + + is_windows_network = (filename[0] == _UT('\\')) && (filename[1] == _UT('\\')); + absolute = fromUnix ? (filename[0] == _UT('/')) + : (((filename[0] != _UT('\0')) && (filename[1] == _UT(':'))) + || is_windows_network); + + if (absolute) { + const URI_CHAR * const prefix = fromUnix ? _UT("file://") + : is_windows_network ? _UT("file:") + : _UT("file:///"); + const size_t prefixLen = URI_STRLEN(prefix); + + /* Copy prefix */ + memcpy(uriString, prefix, prefixLen * sizeof(URI_CHAR)); + output += prefixLen; + } + + /* Copy and escape on the fly */ + for (;;) { + if ((input[0] == _UT('\0')) || (fromUnix && input[0] == _UT('/')) + || (!fromUnix && input[0] == _UT('\\'))) { + /* Copy text after last separator */ + if (lastSep + 1 < input) { + if (!fromUnix && absolute && (firstSegment == URI_TRUE)) { + /* Quick hack to not convert "C:" to "C%3A" */ + const int charsToCopy = (int)(input - (lastSep + 1)); + memcpy(output, lastSep + 1, charsToCopy * sizeof(URI_CHAR)); + output += charsToCopy; + } else { + output = URI_FUNC(EscapeEx)(lastSep + 1, input, output, URI_FALSE, + URI_FALSE); + } + } + firstSegment = URI_FALSE; + } + + if (input[0] == _UT('\0')) { + output[0] = _UT('\0'); + break; + } else if (fromUnix && (input[0] == _UT('/'))) { + /* Copy separators unmodified */ + output[0] = _UT('/'); + output++; + lastSep = input; + } else if (!fromUnix && (input[0] == _UT('\\'))) { + /* Convert backslashes to forward slashes */ + output[0] = _UT('/'); + output++; + lastSep = input; + } + input++; + } + + return URI_SUCCESS; } - - static URI_INLINE int URI_FUNC(UriStringToFilename)(const URI_CHAR * uriString, - URI_CHAR * filename, UriBool toUnix) { - if ((uriString == NULL) || (filename == NULL)) { - return URI_ERROR_NULL; - } - - { - const UriBool file_unknown_slashes = - URI_STRNCMP(uriString, _UT("file:"), URI_STRLEN(_UT("file:"))) == 0; - const UriBool file_one_or_more_slashes = file_unknown_slashes - && (URI_STRNCMP(uriString, _UT("file:/"), URI_STRLEN(_UT("file:/"))) == 0); - const UriBool file_two_or_more_slashes = file_one_or_more_slashes - && (URI_STRNCMP(uriString, _UT("file://"), URI_STRLEN(_UT("file://"))) == 0); - const UriBool file_three_or_more_slashes = file_two_or_more_slashes - && (URI_STRNCMP(uriString, _UT("file:///"), URI_STRLEN(_UT("file:///"))) == 0); - - const size_t charsToSkip = file_two_or_more_slashes - ? file_three_or_more_slashes - ? toUnix - /* file:///bin/bash */ - ? URI_STRLEN(_UT("file://")) - /* file:///E:/Documents%20and%20Settings */ - : URI_STRLEN(_UT("file:///")) - /* file://Server01/Letter.txt */ - : URI_STRLEN(_UT("file://")) - : ((file_one_or_more_slashes && toUnix) - /* file:/bin/bash */ - /* https://tools.ietf.org/html/rfc8089#appendix-B */ - ? URI_STRLEN(_UT("file:")) - : ((! toUnix && file_unknown_slashes && ! file_one_or_more_slashes) - /* file:c:/path/to/file */ - /* https://tools.ietf.org/html/rfc8089#appendix-E.2 */ - ? URI_STRLEN(_UT("file:")) - : 0)); - const size_t charsToCopy = URI_STRLEN(uriString + charsToSkip) + 1; - - const UriBool is_windows_network_with_authority = - (toUnix == URI_FALSE) - && file_two_or_more_slashes - && ! file_three_or_more_slashes; - - URI_CHAR * const unescape_target = is_windows_network_with_authority - ? (filename + 2) - : filename; - - if (is_windows_network_with_authority) { - filename[0] = '\\'; - filename[1] = '\\'; - } - - memcpy(unescape_target, uriString + charsToSkip, charsToCopy * sizeof(URI_CHAR)); - URI_FUNC(UnescapeInPlaceEx)(filename, URI_FALSE, URI_BR_DONT_TOUCH); - } - - /* Convert forward slashes to backslashes */ - if (!toUnix) { - URI_CHAR * walker = filename; - while (walker[0] != _UT('\0')) { - if (walker[0] == _UT('/')) { - walker[0] = _UT('\\'); - } - walker++; - } - } - - return URI_SUCCESS; + URI_CHAR * filename, UriBool toUnix) { + if ((uriString == NULL) || (filename == NULL)) { + return URI_ERROR_NULL; + } + + const UriBool file_unknown_slashes = + URI_STRNCMP(uriString, _UT("file:"), URI_STRLEN(_UT("file:"))) == 0; + const UriBool file_one_or_more_slashes = + file_unknown_slashes + && (URI_STRNCMP(uriString, _UT("file:/"), URI_STRLEN(_UT("file:/"))) == 0); + const UriBool file_two_or_more_slashes = + file_one_or_more_slashes + && (URI_STRNCMP(uriString, _UT("file://"), URI_STRLEN(_UT("file://"))) == 0); + const UriBool file_three_or_more_slashes = + file_two_or_more_slashes + && (URI_STRNCMP(uriString, _UT("file:///"), URI_STRLEN(_UT("file:///"))) == 0); + + const size_t charsToSkip = + file_two_or_more_slashes + ? file_three_or_more_slashes ? toUnix + /* file:///bin/bash */ + ? URI_STRLEN(_UT("file://")) + /* file:///E:/Documents%20and%20Settings */ + : URI_STRLEN(_UT("file:///")) + /* file://Server01/Letter.txt */ + : URI_STRLEN(_UT("file://")) + : ((file_one_or_more_slashes && toUnix) + /* file:/bin/bash */ + /* https://tools.ietf.org/html/rfc8089#appendix-B */ + ? URI_STRLEN(_UT("file:")) + : ((!toUnix && file_unknown_slashes && !file_one_or_more_slashes) + /* file:c:/path/to/file */ + /* https://tools.ietf.org/html/rfc8089#appendix-E.2 */ + ? URI_STRLEN(_UT("file:")) + : 0)); + const size_t charsToCopy = URI_STRLEN(uriString + charsToSkip) + 1; + + const UriBool is_windows_network_with_authority = + (toUnix == URI_FALSE) && file_two_or_more_slashes && !file_three_or_more_slashes; + + URI_CHAR * const unescape_target = + is_windows_network_with_authority ? (filename + 2) : filename; + + if (is_windows_network_with_authority) { + filename[0] = '\\'; + filename[1] = '\\'; + } + + memcpy(unescape_target, uriString + charsToSkip, charsToCopy * sizeof(URI_CHAR)); + URI_FUNC(UnescapeInPlaceEx)(filename, URI_FALSE, URI_BR_DONT_TOUCH); + + /* Convert forward slashes to backslashes */ + if (!toUnix) { + URI_CHAR * walker = filename; + while (walker[0] != _UT('\0')) { + if (walker[0] == _UT('/')) { + walker[0] = _UT('\\'); + } + walker++; + } + } + + return URI_SUCCESS; } - - int URI_FUNC(UnixFilenameToUriString)(const URI_CHAR * filename, URI_CHAR * uriString) { - return URI_FUNC(FilenameToUriString)(filename, uriString, URI_TRUE); + return URI_FUNC(FilenameToUriString)(filename, uriString, URI_TRUE); } - - -int URI_FUNC(WindowsFilenameToUriString)(const URI_CHAR * filename, URI_CHAR * uriString) { - return URI_FUNC(FilenameToUriString)(filename, uriString, URI_FALSE); +int URI_FUNC(WindowsFilenameToUriString)(const URI_CHAR * filename, + URI_CHAR * uriString) { + return URI_FUNC(FilenameToUriString)(filename, uriString, URI_FALSE); } - - int URI_FUNC(UriStringToUnixFilename)(const URI_CHAR * uriString, URI_CHAR * filename) { - return URI_FUNC(UriStringToFilename)(uriString, filename, URI_TRUE); + return URI_FUNC(UriStringToFilename)(uriString, filename, URI_TRUE); } - - -int URI_FUNC(UriStringToWindowsFilename)(const URI_CHAR * uriString, URI_CHAR * filename) { - return URI_FUNC(UriStringToFilename)(uriString, filename, URI_FALSE); +int URI_FUNC(UriStringToWindowsFilename)(const URI_CHAR * uriString, + URI_CHAR * filename) { + return URI_FUNC(UriStringToFilename)(uriString, filename, URI_FALSE); } - - #endif diff --git a/ext/uri/uriparser/src/UriIp4.c b/ext/uri/uriparser/src/UriIp4.c index a794265269da5..ae61141f7a3ad 100644 --- a/ext/uri/uriparser/src/UriIp4.c +++ b/ext/uri/uriparser/src/UriIp4.c @@ -47,97 +47,94 @@ #include #if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) /* Include SELF twice */ -# ifdef URI_ENABLE_ANSI -# define URI_PASS_ANSI 1 -# include "UriIp4.c" -# undef URI_PASS_ANSI -# endif -# ifdef URI_ENABLE_UNICODE -# define URI_PASS_UNICODE 1 -# include "UriIp4.c" -# undef URI_PASS_UNICODE -# endif +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriIp4.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriIp4.c" +# undef URI_PASS_UNICODE +# endif #else -# ifdef URI_PASS_ANSI -# include -# else -# include -# endif - - - -#ifndef URI_DOXYGEN -# include -# include "UriIp4Base.h" -# include -#endif - - +# ifdef URI_PASS_ANSI +# include +# else +# include +# endif + +# ifndef URI_DOXYGEN +# include +# include "UriIp4Base.h" +# include +# include "UriSets.h" +# endif /* Prototypes */ static const URI_CHAR * URI_FUNC(ParseDecOctet)(UriIp4Parser * parser, - const URI_CHAR * first, const URI_CHAR * afterLast); + const URI_CHAR * first, + const URI_CHAR * afterLast); static const URI_CHAR * URI_FUNC(ParseDecOctetOne)(UriIp4Parser * parser, - const URI_CHAR * first, const URI_CHAR * afterLast); + const URI_CHAR * first, + const URI_CHAR * afterLast); static const URI_CHAR * URI_FUNC(ParseDecOctetTwo)(UriIp4Parser * parser, - const URI_CHAR * first, const URI_CHAR * afterLast); + const URI_CHAR * first, + const URI_CHAR * afterLast); static const URI_CHAR * URI_FUNC(ParseDecOctetThree)(UriIp4Parser * parser, - const URI_CHAR * first, const URI_CHAR * afterLast); + const URI_CHAR * first, + const URI_CHAR * afterLast); static const URI_CHAR * URI_FUNC(ParseDecOctetFour)(UriIp4Parser * parser, - const URI_CHAR * first, const URI_CHAR * afterLast); - - + const URI_CHAR * first, + const URI_CHAR * afterLast); /* * [ipFourAddress]->[decOctet]<.>[decOctet]<.>[decOctet]<.>[decOctet] */ -int URI_FUNC(ParseIpFourAddress)(unsigned char * octetOutput, - const URI_CHAR * first, const URI_CHAR * afterLast) { - const URI_CHAR * after; - UriIp4Parser parser; - - /* Essential checks */ - if ((octetOutput == NULL) || (first == NULL) - || (afterLast <= first)) { - return URI_ERROR_SYNTAX; - } - - /* Reset parser */ - parser.stackCount = 0; - - /* Octet #1 */ - after = URI_FUNC(ParseDecOctet)(&parser, first, afterLast); - if ((after == NULL) || (after >= afterLast) || (*after != _UT('.'))) { - return URI_ERROR_SYNTAX; - } - uriStackToOctet(&parser, octetOutput); - - /* Octet #2 */ - after = URI_FUNC(ParseDecOctet)(&parser, after + 1, afterLast); - if ((after == NULL) || (after >= afterLast) || (*after != _UT('.'))) { - return URI_ERROR_SYNTAX; - } - uriStackToOctet(&parser, octetOutput + 1); - - /* Octet #3 */ - after = URI_FUNC(ParseDecOctet)(&parser, after + 1, afterLast); - if ((after == NULL) || (after >= afterLast) || (*after != _UT('.'))) { - return URI_ERROR_SYNTAX; - } - uriStackToOctet(&parser, octetOutput + 2); - - /* Octet #4 */ - after = URI_FUNC(ParseDecOctet)(&parser, after + 1, afterLast); - if (after != afterLast) { - return URI_ERROR_SYNTAX; - } - uriStackToOctet(&parser, octetOutput + 3); - - return URI_SUCCESS; +int URI_FUNC(ParseIpFourAddress)(unsigned char * octetOutput, const URI_CHAR * first, + const URI_CHAR * afterLast) { + const URI_CHAR * after; + UriIp4Parser parser; + + /* Essential checks */ + if ((octetOutput == NULL) || (first == NULL) || (afterLast <= first)) { + return URI_ERROR_SYNTAX; + } + + /* Reset parser */ + parser.stackCount = 0; + + /* Octet #1 */ + after = URI_FUNC(ParseDecOctet)(&parser, first, afterLast); + if ((after == NULL) || (after >= afterLast) || (*after != _UT('.'))) { + return URI_ERROR_SYNTAX; + } + uriStackToOctet(&parser, octetOutput); + + /* Octet #2 */ + after = URI_FUNC(ParseDecOctet)(&parser, after + 1, afterLast); + if ((after == NULL) || (after >= afterLast) || (*after != _UT('.'))) { + return URI_ERROR_SYNTAX; + } + uriStackToOctet(&parser, octetOutput + 1); + + /* Octet #3 */ + after = URI_FUNC(ParseDecOctet)(&parser, after + 1, afterLast); + if ((after == NULL) || (after >= afterLast) || (*after != _UT('.'))) { + return URI_ERROR_SYNTAX; + } + uriStackToOctet(&parser, octetOutput + 2); + + /* Octet #4 */ + after = URI_FUNC(ParseDecOctet)(&parser, after + 1, afterLast); + if (after != afterLast) { + return URI_ERROR_SYNTAX; + } + uriStackToOctet(&parser, octetOutput + 3); + + return URI_SUCCESS; } - - /* * [decOctet]-><0> * [decOctet]-><1>[decOctetOne] @@ -151,72 +148,63 @@ int URI_FUNC(ParseIpFourAddress)(unsigned char * octetOutput, * [decOctet]-><9>[decOctetThree] */ static URI_INLINE const URI_CHAR * URI_FUNC(ParseDecOctet)(UriIp4Parser * parser, - const URI_CHAR * first, const URI_CHAR * afterLast) { - if (first >= afterLast) { - return NULL; - } - - switch (*first) { - case _UT('0'): - uriPushToStack(parser, 0); - return first + 1; - - case _UT('1'): - uriPushToStack(parser, 1); - return (const URI_CHAR *)URI_FUNC(ParseDecOctetOne)(parser, first + 1, afterLast); - - case _UT('2'): - uriPushToStack(parser, 2); - return (const URI_CHAR *)URI_FUNC(ParseDecOctetTwo)(parser, first + 1, afterLast); - - case _UT('3'): - case _UT('4'): - case _UT('5'): - case _UT('6'): - case _UT('7'): - case _UT('8'): - case _UT('9'): - uriPushToStack(parser, (unsigned char)(9 + *first - _UT('9'))); - return (const URI_CHAR *)URI_FUNC(ParseDecOctetThree)(parser, first + 1, afterLast); - - default: - return NULL; - } + const URI_CHAR * first, + const URI_CHAR * afterLast) { + if (first >= afterLast) { + return NULL; + } + + switch (*first) { + case _UT('0'): + uriPushToStack(parser, 0); + return first + 1; + + case _UT('1'): + uriPushToStack(parser, 1); + return (const URI_CHAR *)URI_FUNC(ParseDecOctetOne)(parser, first + 1, afterLast); + + case _UT('2'): + uriPushToStack(parser, 2); + return (const URI_CHAR *)URI_FUNC(ParseDecOctetTwo)(parser, first + 1, afterLast); + + case _UT('3'): + case _UT('4'): + case _UT('5'): + case _UT('6'): + case _UT('7'): + case _UT('8'): + case _UT('9'): + uriPushToStack(parser, (unsigned char)(9 + *first - _UT('9'))); + return (const URI_CHAR *)URI_FUNC(ParseDecOctetThree)(parser, first + 1, + afterLast); + + default: + return NULL; + } } - - /* * [decOctetOne]-> * [decOctetOne]->[DIGIT][decOctetThree] */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParseDecOctetOne)(UriIp4Parser * parser, - const URI_CHAR * first, const URI_CHAR * afterLast) { - if (first >= afterLast) { - return afterLast; - } - - switch (*first) { - case _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'): - uriPushToStack(parser, (unsigned char)(9 + *first - _UT('9'))); - return (const URI_CHAR *)URI_FUNC(ParseDecOctetThree)(parser, first + 1, afterLast); - - default: - return first; - } +static URI_INLINE const URI_CHAR * +URI_FUNC(ParseDecOctetOne)(UriIp4Parser * parser, const URI_CHAR * first, + const URI_CHAR * afterLast) { + if (first >= afterLast) { + return afterLast; + } + + switch (*first) { + case URI_SET_DIGIT(_UT): + uriPushToStack(parser, (unsigned char)(9 + *first - _UT('9'))); + return (const URI_CHAR *)URI_FUNC(ParseDecOctetThree)(parser, first + 1, + afterLast); + + default: + return first; + } } - - /* * [decOctetTwo]-> * [decOctetTwo]-><0>[decOctetThree] @@ -229,71 +217,62 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParseDecOctetOne)(UriIp4Parser * par * [decOctetTwo]-><7> * [decOctetTwo]-><8> * [decOctetTwo]-><9> -*/ -static URI_INLINE const URI_CHAR * URI_FUNC(ParseDecOctetTwo)(UriIp4Parser * parser, - const URI_CHAR * first, const URI_CHAR * afterLast) { - if (first >= afterLast) { - return afterLast; - } - - switch (*first) { - case _UT('0'): - case _UT('1'): - case _UT('2'): - case _UT('3'): - case _UT('4'): - uriPushToStack(parser, (unsigned char)(9 + *first - _UT('9'))); - return (const URI_CHAR *)URI_FUNC(ParseDecOctetThree)(parser, first + 1, afterLast); - - case _UT('5'): - uriPushToStack(parser, 5); - return (const URI_CHAR *)URI_FUNC(ParseDecOctetFour)(parser, first + 1, afterLast); - - case _UT('6'): - case _UT('7'): - case _UT('8'): - case _UT('9'): - uriPushToStack(parser, (unsigned char)(9 + *first - _UT('9'))); - return first + 1; - - default: - return first; - } + */ +static URI_INLINE const URI_CHAR * +URI_FUNC(ParseDecOctetTwo)(UriIp4Parser * parser, const URI_CHAR * first, + const URI_CHAR * afterLast) { + if (first >= afterLast) { + return afterLast; + } + + switch (*first) { + case _UT('0'): + case _UT('1'): + case _UT('2'): + case _UT('3'): + case _UT('4'): + uriPushToStack(parser, (unsigned char)(9 + *first - _UT('9'))); + return (const URI_CHAR *)URI_FUNC(ParseDecOctetThree)(parser, first + 1, + afterLast); + + case _UT('5'): + uriPushToStack(parser, 5); + return (const URI_CHAR *)URI_FUNC(ParseDecOctetFour)(parser, first + 1, + afterLast); + + case _UT('6'): + case _UT('7'): + case _UT('8'): + case _UT('9'): + uriPushToStack(parser, (unsigned char)(9 + *first - _UT('9'))); + return first + 1; + + default: + return first; + } } - - /* * [decOctetThree]-> * [decOctetThree]->[DIGIT] */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParseDecOctetThree)(UriIp4Parser * parser, - const URI_CHAR * first, const URI_CHAR * afterLast) { - if (first >= afterLast) { - return afterLast; - } - - switch (*first) { - case _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'): - uriPushToStack(parser, (unsigned char)(9 + *first - _UT('9'))); - return first + 1; - - default: - return first; - } +static URI_INLINE const URI_CHAR * +URI_FUNC(ParseDecOctetThree)(UriIp4Parser * parser, const URI_CHAR * first, + const URI_CHAR * afterLast) { + if (first >= afterLast) { + return afterLast; + } + + switch (*first) { + case URI_SET_DIGIT(_UT): + uriPushToStack(parser, (unsigned char)(9 + *first - _UT('9'))); + return first + 1; + + default: + return first; + } } - - /* * [decOctetFour]-> * [decOctetFour]-><0> @@ -303,27 +282,26 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParseDecOctetThree)(UriIp4Parser * p * [decOctetFour]-><4> * [decOctetFour]-><5> */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParseDecOctetFour)(UriIp4Parser * parser, - const URI_CHAR * first, const URI_CHAR * afterLast) { - if (first >= afterLast) { - return afterLast; - } - - switch (*first) { - case _UT('0'): - case _UT('1'): - case _UT('2'): - case _UT('3'): - case _UT('4'): - case _UT('5'): - uriPushToStack(parser, (unsigned char)(9 + *first - _UT('9'))); - return first + 1; - - default: - return first; - } +static URI_INLINE const URI_CHAR * +URI_FUNC(ParseDecOctetFour)(UriIp4Parser * parser, const URI_CHAR * first, + const URI_CHAR * afterLast) { + if (first >= afterLast) { + return afterLast; + } + + switch (*first) { + case _UT('0'): + case _UT('1'): + case _UT('2'): + case _UT('3'): + case _UT('4'): + case _UT('5'): + uriPushToStack(parser, (unsigned char)(9 + *first - _UT('9'))); + return first + 1; + + default: + return first; + } } - - #endif diff --git a/ext/uri/uriparser/src/UriIp4Base.c b/ext/uri/uriparser/src/UriIp4Base.c index ded7c32c9940e..900234cd782d3 100644 --- a/ext/uri/uriparser/src/UriIp4Base.c +++ b/ext/uri/uriparser/src/UriIp4Base.c @@ -43,54 +43,45 @@ */ #ifndef URI_DOXYGEN -# include "UriIp4Base.h" +# include "UriIp4Base.h" #endif - - void uriStackToOctet(UriIp4Parser * parser, unsigned char * octet) { - switch (parser->stackCount) { - case 1: - *octet = parser->stackOne; - break; + switch (parser->stackCount) { + case 1: + *octet = parser->stackOne; + break; - case 2: - *octet = parser->stackOne * 10 - + parser->stackTwo; - break; + case 2: + *octet = parser->stackOne * 10 + parser->stackTwo; + break; - case 3: - *octet = parser->stackOne * 100 - + parser->stackTwo * 10 - + parser->stackThree; - break; + case 3: + *octet = parser->stackOne * 100 + parser->stackTwo * 10 + parser->stackThree; + break; - default: - ; - } - parser->stackCount = 0; + default:; + } + parser->stackCount = 0; } - - void uriPushToStack(UriIp4Parser * parser, unsigned char digit) { - switch (parser->stackCount) { - case 0: - parser->stackOne = digit; - parser->stackCount = 1; - break; + switch (parser->stackCount) { + case 0: + parser->stackOne = digit; + parser->stackCount = 1; + break; - case 1: - parser->stackTwo = digit; - parser->stackCount = 2; - break; + case 1: + parser->stackTwo = digit; + parser->stackCount = 2; + break; - case 2: - parser->stackThree = digit; - parser->stackCount = 3; - break; + case 2: + parser->stackThree = digit; + parser->stackCount = 3; + break; - default: - ; - } + default:; + } } diff --git a/ext/uri/uriparser/src/UriIp4Base.h b/ext/uri/uriparser/src/UriIp4Base.h index 4867850224033..1a2ff148b628b 100644 --- a/ext/uri/uriparser/src/UriIp4Base.h +++ b/ext/uri/uriparser/src/UriIp4Base.h @@ -38,22 +38,16 @@ */ #ifndef URI_IP4_BASE_H -#define URI_IP4_BASE_H 1 - - +# define URI_IP4_BASE_H 1 typedef struct UriIp4ParserStruct { - unsigned char stackCount; - unsigned char stackOne; - unsigned char stackTwo; - unsigned char stackThree; + unsigned char stackCount; + unsigned char stackOne; + unsigned char stackTwo; + unsigned char stackThree; } UriIp4Parser; - - void uriPushToStack(UriIp4Parser * parser, unsigned char digit); void uriStackToOctet(UriIp4Parser * parser, unsigned char * octet); - - #endif /* URI_IP4_BASE_H */ diff --git a/ext/uri/uriparser/src/UriMemory.c b/ext/uri/uriparser/src/UriMemory.c index 916d7cea8308a..3caf8199dc45d 100644 --- a/ext/uri/uriparser/src/UriMemory.c +++ b/ext/uri/uriparser/src/UriMemory.c @@ -42,430 +42,423 @@ * Holds memory manager implementation. */ -#include "UriConfig.h" /* for HAVE_REALLOCARRAY */ +#include "UriConfig.h" /* for HAVE_REALLOCARRAY */ #ifdef HAVE_REALLOCARRAY -# ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -# endif -# ifdef __NetBSD__ -# define _OPENBSD_SOURCE 1 -# endif +# ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +# endif +# ifdef __NetBSD__ +# define _OPENBSD_SOURCE 1 +# endif #endif #include #include - - #ifndef URI_DOXYGEN -# include "UriMemory.h" +# include "UriMemory.h" #endif +#define URI_MAX(a, b) (((a) > (b)) ? (a) : (b)) +/* NOTE: This intends to mimic MALLOC_ALIGNMENT of glibc */ +#define URI_MALLOC_ALIGNMENT URI_MAX(2 * sizeof(size_t), sizeof(long double)) -#define URI_CHECK_ALLOC_OVERFLOW(total_size, nmemb, size) \ - do { \ - /* check for unsigned overflow */ \ - if ((nmemb != 0) && (total_size / nmemb != size)) { \ - errno = ENOMEM; \ - return NULL; \ - } \ - } while (0) - - +#define URI_MALLOC_PADDING (URI_MALLOC_ALIGNMENT - sizeof(size_t)) -static void * uriDefaultMalloc(UriMemoryManager * URI_UNUSED(memory), - size_t size) { - return malloc(size); +#define URI_CHECK_ALLOC_OVERFLOW(total_size, nmemb, size) \ + do { \ + /* check for unsigned overflow */ \ + if ((nmemb != 0) && (total_size / nmemb != size)) { \ + errno = ENOMEM; \ + return NULL; \ + } \ + } while (0) + +static void * uriDefaultMalloc(UriMemoryManager * URI_UNUSED(memory), size_t size) { + return malloc(size); } - - -static void * uriDefaultCalloc(UriMemoryManager * URI_UNUSED(memory), - size_t nmemb, size_t size) { - return calloc(nmemb, size); +static void * uriDefaultCalloc(UriMemoryManager * URI_UNUSED(memory), size_t nmemb, + size_t size) { + return calloc(nmemb, size); } - - -static void * uriDefaultRealloc(UriMemoryManager * URI_UNUSED(memory), - void * ptr, size_t size) { - return realloc(ptr, size); +static void * uriDefaultRealloc(UriMemoryManager * URI_UNUSED(memory), void * ptr, + size_t size) { + return realloc(ptr, size); } - - -static void * uriDefaultReallocarray(UriMemoryManager * URI_UNUSED(memory), - void * ptr, size_t nmemb, size_t size) { +static void * uriDefaultReallocarray(UriMemoryManager * URI_UNUSED(memory), void * ptr, + size_t nmemb, size_t size) { #ifdef HAVE_REALLOCARRAY - return reallocarray(ptr, nmemb, size); + return reallocarray(ptr, nmemb, size); #else - const size_t total_size = nmemb * size; + const size_t total_size = nmemb * size; - URI_CHECK_ALLOC_OVERFLOW(total_size, nmemb, size); /* may return */ + URI_CHECK_ALLOC_OVERFLOW(total_size, nmemb, size); /* may return */ - return realloc(ptr, total_size); + return realloc(ptr, total_size); #endif } - - -static void uriDefaultFree(UriMemoryManager * URI_UNUSED(memory), - void * ptr) { - free(ptr); +static void uriDefaultFree(UriMemoryManager * URI_UNUSED(memory), void * ptr) { + free(ptr); } - - UriBool uriMemoryManagerIsComplete(const UriMemoryManager * memory) { - return (memory - && memory->malloc - && memory->calloc - && memory->realloc - && memory->reallocarray - && memory->free) ? URI_TRUE : URI_FALSE; + return (memory && memory->malloc && memory->calloc && memory->realloc + && memory->reallocarray && memory->free) + ? URI_TRUE + : URI_FALSE; } - - void * uriEmulateCalloc(UriMemoryManager * memory, size_t nmemb, size_t size) { - void * buffer; - const size_t total_size = nmemb * size; - - if (memory == NULL) { - errno = EINVAL; - return NULL; - } - - URI_CHECK_ALLOC_OVERFLOW(total_size, nmemb, size); /* may return */ - - buffer = memory->malloc(memory, total_size); - if (buffer == NULL) { - /* errno set by malloc */ - return NULL; - } - memset(buffer, 0, total_size); - return buffer; + void * buffer; + const size_t total_size = nmemb * size; + + if (memory == NULL) { + errno = EINVAL; + return NULL; + } + + URI_CHECK_ALLOC_OVERFLOW(total_size, nmemb, size); /* may return */ + + buffer = memory->malloc(memory, total_size); + if (buffer == NULL) { + /* errno set by malloc */ + return NULL; + } + memset(buffer, 0, total_size); + return buffer; } +void * uriEmulateReallocarray(UriMemoryManager * memory, void * ptr, size_t nmemb, + size_t size) { + const size_t total_size = nmemb * size; + if (memory == NULL) { + errno = EINVAL; + return NULL; + } -void * uriEmulateReallocarray(UriMemoryManager * memory, - void * ptr, size_t nmemb, size_t size) { - const size_t total_size = nmemb * size; - - if (memory == NULL) { - errno = EINVAL; - return NULL; - } - - URI_CHECK_ALLOC_OVERFLOW(total_size, nmemb, size); /* may return */ + URI_CHECK_ALLOC_OVERFLOW(total_size, nmemb, size); /* may return */ - return memory->realloc(memory, ptr, total_size); + return memory->realloc(memory, ptr, total_size); } +static void * uriDecorateMalloc(UriMemoryManager * memory, size_t size) { + UriMemoryManager * backend; + const size_t extraBytes = sizeof(size_t) + URI_MALLOC_PADDING; + void * buffer; + if (memory == NULL) { + errno = EINVAL; + return NULL; + } -static void * uriDecorateMalloc(UriMemoryManager * memory, - size_t size) { - UriMemoryManager * backend; - const size_t extraBytes = sizeof(size_t); - void * buffer; + /* check for unsigned overflow */ + if (size > ((size_t)-1) - extraBytes) { + errno = ENOMEM; + return NULL; + } - if (memory == NULL) { - errno = EINVAL; - return NULL; - } + backend = (UriMemoryManager *)memory->userData; + if (backend == NULL) { + errno = EINVAL; + return NULL; + } - /* check for unsigned overflow */ - if (size > ((size_t)-1) - extraBytes) { - errno = ENOMEM; - return NULL; - } + buffer = backend->malloc(backend, extraBytes + size); + if (buffer == NULL) { + return NULL; + } - backend = (UriMemoryManager *)memory->userData; - if (backend == NULL) { - errno = EINVAL; - return NULL; - } + *(size_t *)buffer = size; - buffer = backend->malloc(backend, extraBytes + size); - if (buffer == NULL) { - return NULL; - } - - *(size_t *)buffer = size; - - return (char *)buffer + extraBytes; + return (char *)buffer + extraBytes; } +static void * uriDecorateRealloc(UriMemoryManager * memory, void * ptr, size_t size) { + void * newBuffer; + size_t prevSize; + if (memory == NULL) { + errno = EINVAL; + return NULL; + } -static void * uriDecorateRealloc(UriMemoryManager * memory, - void * ptr, size_t size) { - void * newBuffer; - size_t prevSize; - - if (memory == NULL) { - errno = EINVAL; - return NULL; - } - - /* man realloc: "If ptr is NULL, then the call is equivalent to - * malloc(size), for *all* values of size" */ - if (ptr == NULL) { - return memory->malloc(memory, size); - } + /* man realloc: "If ptr is NULL, then the call is equivalent to + * malloc(size), for *all* values of size" */ + if (ptr == NULL) { + return memory->malloc(memory, size); + } - /* man realloc: "If size is equal to zero, and ptr is *not* NULL, - * then the call is equivalent to free(ptr)." */ - if (size == 0) { - memory->free(memory, ptr); - return NULL; - } + /* man realloc: "If size is equal to zero, and ptr is *not* NULL, + * then the call is equivalent to free(ptr)." */ + if (size == 0) { + memory->free(memory, ptr); + return NULL; + } - prevSize = *((size_t *)((char *)ptr - sizeof(size_t))); + prevSize = *((size_t *)((char *)ptr - sizeof(size_t) - URI_MALLOC_PADDING)); - /* Anything to do? */ - if (size <= prevSize) { - return ptr; - } + /* Anything to do? */ + /* mull-ignore-next cxx_le_to_lt */ + if (size <= prevSize) { + return ptr; + } - newBuffer = memory->malloc(memory, size); - if (newBuffer == NULL) { - /* errno set by malloc */ - return NULL; - } + newBuffer = memory->malloc(memory, size); + if (newBuffer == NULL) { + /* errno set by malloc */ + return NULL; + } - memcpy(newBuffer, ptr, prevSize); + memcpy(newBuffer, ptr, prevSize); - memory->free(memory, ptr); + memory->free(memory, ptr); - return newBuffer; + return newBuffer; } - - static void uriDecorateFree(UriMemoryManager * memory, void * ptr) { - UriMemoryManager * backend; + UriMemoryManager * backend; - if ((ptr == NULL) || (memory == NULL)) { - return; - } + if ((ptr == NULL) || (memory == NULL)) { + return; + } - backend = (UriMemoryManager *)memory->userData; - if (backend == NULL) { - return; - } + backend = (UriMemoryManager *)memory->userData; + if (backend == NULL) { + return; + } - backend->free(backend, (char *)ptr - sizeof(size_t)); + backend->free(backend, (char *)ptr - sizeof(size_t) - URI_MALLOC_PADDING); } +int uriCompleteMemoryManager(UriMemoryManager * memory, UriMemoryManager * backend) { + if ((memory == NULL) || (backend == NULL)) { + return URI_ERROR_NULL; + } + if ((backend->malloc == NULL) || (backend->free == NULL)) { + return URI_ERROR_MEMORY_MANAGER_INCOMPLETE; + } -int uriCompleteMemoryManager(UriMemoryManager * memory, - UriMemoryManager * backend) { - if ((memory == NULL) || (backend == NULL)) { - return URI_ERROR_NULL; - } - - if ((backend->malloc == NULL) || (backend->free == NULL)) { - return URI_ERROR_MEMORY_MANAGER_INCOMPLETE; - } - - memory->calloc = uriEmulateCalloc; - memory->reallocarray = uriEmulateReallocarray; + memory->calloc = uriEmulateCalloc; + memory->reallocarray = uriEmulateReallocarray; - memory->malloc = uriDecorateMalloc; - memory->realloc = uriDecorateRealloc; - memory->free = uriDecorateFree; + memory->malloc = uriDecorateMalloc; + memory->realloc = uriDecorateRealloc; + memory->free = uriDecorateFree; - memory->userData = backend; + memory->userData = backend; - return URI_SUCCESS; + return URI_SUCCESS; } - +/* mull-off */ +int uriTestMemoryManagerEx(UriMemoryManager * memory, UriBool challengeAlignment) { + const size_t mallocSize = 7; + const size_t callocNmemb = 3; + const size_t callocSize = 5; + const size_t callocTotalSize = callocNmemb * callocSize; + const size_t reallocSize = 11; + const size_t reallocarrayNmemb = 5; + const size_t reallocarraySize = 7; + const size_t reallocarrayTotal = reallocarrayNmemb * reallocarraySize; + size_t index; + char * buffer; + + if (memory == NULL) { + return URI_ERROR_NULL; + } + + if (uriMemoryManagerIsComplete(memory) != URI_TRUE) { + return URI_ERROR_MEMORY_MANAGER_INCOMPLETE; + } + + /* malloc + free*/ + buffer = memory->malloc(memory, mallocSize); + if (buffer == NULL) { + return URI_ERROR_MEMORY_MANAGER_FAULTY; + } + buffer[mallocSize - 1] = '\xF1'; + memory->free(memory, buffer); + buffer = NULL; + + /* calloc + free */ + buffer = memory->calloc(memory, callocNmemb, callocSize); + if (buffer == NULL) { + return URI_ERROR_MEMORY_MANAGER_FAULTY; + } + for (index = 0; index < callocTotalSize; index++) { /* all zeros? */ + if (buffer[index] != '\0') { + return URI_ERROR_MEMORY_MANAGER_FAULTY; + } + } + buffer[callocTotalSize - 1] = '\xF2'; + memory->free(memory, buffer); + buffer = NULL; + + /* malloc + realloc + free */ + buffer = memory->malloc(memory, mallocSize); + if (buffer == NULL) { + return URI_ERROR_MEMORY_MANAGER_FAULTY; + } + for (index = 0; index < mallocSize; index++) { + buffer[index] = '\xF3'; + } + buffer = memory->realloc(memory, buffer, reallocSize); + if (buffer == NULL) { + return URI_ERROR_MEMORY_MANAGER_FAULTY; + } + for (index = 0; index < mallocSize; index++) { /* previous content? */ + if (buffer[index] != '\xF3') { + return URI_ERROR_MEMORY_MANAGER_FAULTY; + } + } + buffer[reallocSize - 1] = '\xF4'; + memory->free(memory, buffer); + buffer = NULL; + + /* malloc + realloc ptr!=NULL size==0 (equals free) */ + buffer = memory->malloc(memory, mallocSize); + if (buffer == NULL) { + return URI_ERROR_MEMORY_MANAGER_FAULTY; + } + buffer[mallocSize - 1] = '\xF5'; + memory->realloc(memory, buffer, 0); + buffer = NULL; + + /* realloc ptr==NULL size!=0 (equals malloc) + free */ + buffer = memory->realloc(memory, NULL, mallocSize); + if (buffer == NULL) { + return URI_ERROR_MEMORY_MANAGER_FAULTY; + } + buffer[mallocSize - 1] = '\xF6'; + memory->free(memory, buffer); + buffer = NULL; + + /* realloc ptr==NULL size==0 (equals malloc) + free */ + buffer = memory->realloc(memory, NULL, 0); + if (buffer != NULL) { + memory->free(memory, buffer); + buffer = NULL; + } + + /* malloc + reallocarray + free */ + buffer = memory->malloc(memory, mallocSize); + if (buffer == NULL) { + return URI_ERROR_MEMORY_MANAGER_FAULTY; + } + for (index = 0; index < mallocSize; index++) { + buffer[index] = '\xF7'; + } + buffer = memory->reallocarray(memory, buffer, reallocarrayNmemb, reallocarraySize); + if (buffer == NULL) { + return URI_ERROR_MEMORY_MANAGER_FAULTY; + } + for (index = 0; index < mallocSize; index++) { /* previous content? */ + if (buffer[index] != '\xF7') { + return URI_ERROR_MEMORY_MANAGER_FAULTY; + } + } + buffer[reallocarrayTotal - 1] = '\xF8'; + memory->free(memory, buffer); + buffer = NULL; + + /* malloc + reallocarray ptr!=NULL nmemb==0 size!=0 (equals free) */ + buffer = memory->malloc(memory, mallocSize); + if (buffer == NULL) { + return URI_ERROR_MEMORY_MANAGER_FAULTY; + } + buffer[mallocSize - 1] = '\xF9'; + memory->reallocarray(memory, buffer, 0, reallocarraySize); + buffer = NULL; + + /* malloc + reallocarray ptr!=NULL nmemb!=0 size==0 (equals free) */ + buffer = memory->malloc(memory, mallocSize); + if (buffer == NULL) { + return URI_ERROR_MEMORY_MANAGER_FAULTY; + } + buffer[mallocSize - 1] = '\xFA'; + memory->reallocarray(memory, buffer, reallocarrayNmemb, 0); + buffer = NULL; + + /* malloc + reallocarray ptr!=NULL nmemb==0 size==0 (equals free) */ + buffer = memory->malloc(memory, mallocSize); + if (buffer == NULL) { + return URI_ERROR_MEMORY_MANAGER_FAULTY; + } + buffer[mallocSize - 1] = '\xFB'; + memory->reallocarray(memory, buffer, 0, 0); + buffer = NULL; + + /* reallocarray ptr==NULL nmemb!=0 size!=0 (equals malloc) + free */ + buffer = memory->reallocarray(memory, NULL, callocNmemb, callocSize); + if (buffer == NULL) { + return URI_ERROR_MEMORY_MANAGER_FAULTY; + } + buffer[callocTotalSize - 1] = '\xFC'; + memory->free(memory, buffer); + buffer = NULL; + + /* reallocarray ptr==NULL nmemb==0 size!=0 (equals malloc) + free */ + buffer = memory->reallocarray(memory, NULL, 0, callocSize); + if (buffer != NULL) { + memory->free(memory, buffer); + buffer = NULL; + } + + /* reallocarray ptr==NULL nmemb!=0 size==0 (equals malloc) + free */ + buffer = memory->reallocarray(memory, NULL, callocNmemb, 0); + if (buffer != NULL) { + memory->free(memory, buffer); + buffer = NULL; + } + + /* reallocarray ptr==NULL nmemb==0 size==0 (equals malloc) + free */ + buffer = memory->reallocarray(memory, NULL, 0, 0); + if (buffer != NULL) { + memory->free(memory, buffer); + buffer = NULL; + } + + /* challenge pointer alignment */ + if (challengeAlignment == URI_TRUE) { + long double * ptr = memory->malloc(memory, 4 * sizeof(long double)); + if (ptr != NULL) { + ptr[0] = 0.0L; + ptr[1] = 1.1L; + ptr[2] = 2.2L; + ptr[3] = 3.3L; + + long double * const ptrNew = + memory->realloc(memory, ptr, 8 * sizeof(long double)); + if (ptrNew != NULL) { + ptr = ptrNew; + ptr[4] = 4.4L; + ptr[5] = 5.5L; + ptr[6] = 6.6L; + ptr[7] = 7.7L; + } + + memory->free(memory, ptr); + } + } + + return URI_SUCCESS; +} +/* mull-on */ int uriTestMemoryManager(UriMemoryManager * memory) { - const size_t mallocSize = 7; - const size_t callocNmemb = 3; - const size_t callocSize = 5; - const size_t callocTotalSize = callocNmemb * callocSize; - const size_t reallocSize = 11; - const size_t reallocarrayNmemb = 5; - const size_t reallocarraySize = 7; - const size_t reallocarrayTotal = reallocarrayNmemb * reallocarraySize; - size_t index; - char * buffer; - - if (memory == NULL) { - return URI_ERROR_NULL; - } - - if (uriMemoryManagerIsComplete(memory) != URI_TRUE) { - return URI_ERROR_MEMORY_MANAGER_INCOMPLETE; - } - - /* malloc + free*/ - buffer = memory->malloc(memory, mallocSize); - if (buffer == NULL) { - return URI_ERROR_MEMORY_MANAGER_FAULTY; - } - buffer[mallocSize - 1] = '\xF1'; - memory->free(memory, buffer); - buffer = NULL; - - /* calloc + free */ - buffer = memory->calloc(memory, callocNmemb, callocSize); - if (buffer == NULL) { - return URI_ERROR_MEMORY_MANAGER_FAULTY; - } - for (index = 0; index < callocTotalSize; index++) { /* all zeros? */ - if (buffer[index] != '\0') { - return URI_ERROR_MEMORY_MANAGER_FAULTY; - } - } - buffer[callocTotalSize - 1] = '\xF2'; - memory->free(memory, buffer); - buffer = NULL; - - /* malloc + realloc + free */ - buffer = memory->malloc(memory, mallocSize); - if (buffer == NULL) { - return URI_ERROR_MEMORY_MANAGER_FAULTY; - } - for (index = 0; index < mallocSize; index++) { - buffer[index] = '\xF3'; - } - buffer = memory->realloc(memory, buffer, reallocSize); - if (buffer == NULL) { - return URI_ERROR_MEMORY_MANAGER_FAULTY; - } - for (index = 0; index < mallocSize; index++) { /* previous content? */ - if (buffer[index] != '\xF3') { - return URI_ERROR_MEMORY_MANAGER_FAULTY; - } - } - buffer[reallocSize - 1] = '\xF4'; - memory->free(memory, buffer); - buffer = NULL; - - /* malloc + realloc ptr!=NULL size==0 (equals free) */ - buffer = memory->malloc(memory, mallocSize); - if (buffer == NULL) { - return URI_ERROR_MEMORY_MANAGER_FAULTY; - } - buffer[mallocSize - 1] = '\xF5'; - memory->realloc(memory, buffer, 0); - buffer = NULL; - - /* realloc ptr==NULL size!=0 (equals malloc) + free */ - buffer = memory->realloc(memory, NULL, mallocSize); - if (buffer == NULL) { - return URI_ERROR_MEMORY_MANAGER_FAULTY; - } - buffer[mallocSize - 1] = '\xF6'; - memory->free(memory, buffer); - buffer = NULL; - - /* realloc ptr==NULL size==0 (equals malloc) + free */ - buffer = memory->realloc(memory, NULL, 0); - if (buffer != NULL) { - memory->free(memory, buffer); - buffer = NULL; - } - - /* malloc + reallocarray + free */ - buffer = memory->malloc(memory, mallocSize); - if (buffer == NULL) { - return URI_ERROR_MEMORY_MANAGER_FAULTY; - } - for (index = 0; index < mallocSize; index++) { - buffer[index] = '\xF7'; - } - buffer = memory->reallocarray(memory, buffer, reallocarrayNmemb, - reallocarraySize); - if (buffer == NULL) { - return URI_ERROR_MEMORY_MANAGER_FAULTY; - } - for (index = 0; index < mallocSize; index++) { /* previous content? */ - if (buffer[index] != '\xF7') { - return URI_ERROR_MEMORY_MANAGER_FAULTY; - } - } - buffer[reallocarrayTotal - 1] = '\xF8'; - memory->free(memory, buffer); - buffer = NULL; - - /* malloc + reallocarray ptr!=NULL nmemb==0 size!=0 (equals free) */ - buffer = memory->malloc(memory, mallocSize); - if (buffer == NULL) { - return URI_ERROR_MEMORY_MANAGER_FAULTY; - } - buffer[mallocSize - 1] = '\xF9'; - memory->reallocarray(memory, buffer, 0, reallocarraySize); - buffer = NULL; - - /* malloc + reallocarray ptr!=NULL nmemb!=0 size==0 (equals free) */ - buffer = memory->malloc(memory, mallocSize); - if (buffer == NULL) { - return URI_ERROR_MEMORY_MANAGER_FAULTY; - } - buffer[mallocSize - 1] = '\xFA'; - memory->reallocarray(memory, buffer, reallocarrayNmemb, 0); - buffer = NULL; - - /* malloc + reallocarray ptr!=NULL nmemb==0 size==0 (equals free) */ - buffer = memory->malloc(memory, mallocSize); - if (buffer == NULL) { - return URI_ERROR_MEMORY_MANAGER_FAULTY; - } - buffer[mallocSize - 1] = '\xFB'; - memory->reallocarray(memory, buffer, 0, 0); - buffer = NULL; - - /* reallocarray ptr==NULL nmemb!=0 size!=0 (equals malloc) + free */ - buffer = memory->reallocarray(memory, NULL, callocNmemb, callocSize); - if (buffer == NULL) { - return URI_ERROR_MEMORY_MANAGER_FAULTY; - } - buffer[callocTotalSize - 1] = '\xFC'; - memory->free(memory, buffer); - buffer = NULL; - - /* reallocarray ptr==NULL nmemb==0 size!=0 (equals malloc) + free */ - buffer = memory->reallocarray(memory, NULL, 0, callocSize); - if (buffer != NULL) { - memory->free(memory, buffer); - buffer = NULL; - } - - /* reallocarray ptr==NULL nmemb!=0 size==0 (equals malloc) + free */ - buffer = memory->reallocarray(memory, NULL, callocNmemb, 0); - if (buffer != NULL) { - memory->free(memory, buffer); - buffer = NULL; - } - - /* reallocarray ptr==NULL nmemb==0 size==0 (equals malloc) + free */ - buffer = memory->reallocarray(memory, NULL, 0, 0); - if (buffer != NULL) { - memory->free(memory, buffer); - buffer = NULL; - } - - return URI_SUCCESS; + return uriTestMemoryManagerEx(memory, /*challengeAlignment=*/URI_FALSE); } - - /*extern*/ UriMemoryManager defaultMemoryManager = { - uriDefaultMalloc, - uriDefaultCalloc, - uriDefaultRealloc, - uriDefaultReallocarray, - uriDefaultFree, - NULL /* userData */ + uriDefaultMalloc, uriDefaultCalloc, uriDefaultRealloc, + uriDefaultReallocarray, uriDefaultFree, NULL /* userData */ }; diff --git a/ext/uri/uriparser/src/UriMemory.h b/ext/uri/uriparser/src/UriMemory.h index a930f93ac3c35..b03ca4a093b05 100644 --- a/ext/uri/uriparser/src/UriMemory.h +++ b/ext/uri/uriparser/src/UriMemory.h @@ -38,41 +38,31 @@ */ #ifndef URI_MEMORY_H -#define URI_MEMORY_H 1 - - - -#ifndef URI_DOXYGEN -# include -#endif - - - -#define URI_CHECK_MEMORY_MANAGER(memory) \ - do { \ - if (memory == NULL) { \ - memory = &defaultMemoryManager; \ - } else if (uriMemoryManagerIsComplete(memory) != URI_TRUE) { \ - return URI_ERROR_MEMORY_MANAGER_INCOMPLETE; \ - } \ - } while (0) - - - -#ifdef __cplusplus -# define URIPARSER_EXTERN extern "C" -#else -# define URIPARSER_EXTERN extern -#endif +# define URI_MEMORY_H 1 + +# ifndef URI_DOXYGEN +# include +# endif + +# define URI_CHECK_MEMORY_MANAGER(memory) \ + do { \ + if (memory == NULL) { \ + memory = &defaultMemoryManager; \ + } else if (uriMemoryManagerIsComplete(memory) != URI_TRUE) { \ + return URI_ERROR_MEMORY_MANAGER_INCOMPLETE; \ + } \ + } while (0) + +# ifdef __cplusplus +# define URIPARSER_EXTERN extern "C" +# else +# define URIPARSER_EXTERN extern +# endif URIPARSER_EXTERN UriMemoryManager defaultMemoryManager; -#undef URIPARSER_EXTERN - - +# undef URIPARSER_EXTERN UriBool uriMemoryManagerIsComplete(const UriMemoryManager * memory); - - #endif /* URI_MEMORY_H */ diff --git a/ext/uri/uriparser/src/UriNormalize.c b/ext/uri/uriparser/src/UriNormalize.c index 56b19573665e5..8c812d37a0a7e 100644 --- a/ext/uri/uriparser/src/UriNormalize.c +++ b/ext/uri/uriparser/src/UriNormalize.c @@ -47,865 +47,818 @@ #include #if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) /* Include SELF twice */ -# ifdef URI_ENABLE_ANSI -# define URI_PASS_ANSI 1 -# include "UriNormalize.c" -# undef URI_PASS_ANSI -# endif -# ifdef URI_ENABLE_UNICODE -# define URI_PASS_UNICODE 1 -# include "UriNormalize.c" -# undef URI_PASS_UNICODE -# endif +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriNormalize.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriNormalize.c" +# undef URI_PASS_UNICODE +# endif #else -# ifdef URI_PASS_ANSI -# include -# else -# include -# include -# endif - - - -#ifndef URI_DOXYGEN -# include -# include "UriNormalizeBase.h" -# include "UriCommon.h" -# include "UriMemory.h" -#endif - - - -#include - - +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif + +# ifndef URI_DOXYGEN +# include +# include "UriNormalizeBase.h" +# include "UriCommon.h" +# include "UriMemory.h" +# endif + +# include static int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, unsigned int inMask, - unsigned int * outMask, UriMemoryManager * memory); + unsigned int * outMask, + UriMemoryManager * memory); -static UriBool URI_FUNC(MakeRangeOwner)(unsigned int * doneMask, - unsigned int maskTest, URI_TYPE(TextRange) * range, - UriMemoryManager * memory); -static UriBool URI_FUNC(MakeOwnerEngine)(URI_TYPE(Uri) * uri, - unsigned int * doneMask, UriMemoryManager * memory); +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 * revertMask, + UriMemoryManager * memory); static void URI_FUNC(FixPercentEncodingInplace)(const URI_CHAR * first, - const URI_CHAR ** afterLast); + const URI_CHAR ** afterLast); static UriBool URI_FUNC(FixPercentEncodingMalloc)(const URI_CHAR ** first, - const URI_CHAR ** afterLast, UriMemoryManager * memory); -static void URI_FUNC(FixPercentEncodingEngine)( - const URI_CHAR * inFirst, const URI_CHAR * inAfterLast, - const URI_CHAR * outFirst, const URI_CHAR ** outAfterLast); + const URI_CHAR ** afterLast, + UriMemoryManager * memory); +static void URI_FUNC(FixPercentEncodingEngine)(const URI_CHAR * inFirst, + const URI_CHAR * inAfterLast, + const URI_CHAR * outFirst, + const URI_CHAR ** outAfterLast); static UriBool URI_FUNC(ContainsUppercaseLetters)(const URI_CHAR * first, - const URI_CHAR * afterLast); + const URI_CHAR * afterLast); static UriBool URI_FUNC(ContainsUglyPercentEncoding)(const URI_CHAR * first, - const URI_CHAR * afterLast); + const URI_CHAR * afterLast); static void URI_FUNC(LowercaseInplace)(const URI_CHAR * first, - const URI_CHAR * afterLast); + const URI_CHAR * afterLast); static void URI_FUNC(LowercaseInplaceExceptPercentEncoding)(const URI_CHAR * first, - const URI_CHAR * afterLast); + const URI_CHAR * afterLast); static UriBool URI_FUNC(LowercaseMalloc)(const URI_CHAR ** first, - const URI_CHAR ** afterLast, UriMemoryManager * memory); - - - -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 - * so no need to compare .first with .afterLast, here. */ - memory->free(memory, (URI_CHAR *)uri->scheme.first); - uri->scheme.first = NULL; - uri->scheme.afterLast = NULL; - } - - if (revertMask & URI_NORMALIZE_USER_INFO) { - if (uri->userInfo.first != uri->userInfo.afterLast) { - memory->free(memory, (URI_CHAR *)uri->userInfo.first); - } - uri->userInfo.first = NULL; - uri->userInfo.afterLast = NULL; - } - - if (revertMask & URI_NORMALIZE_HOST) { - if (uri->hostData.ipFuture.first != NULL) { - /* IPvFuture */ - /* NOTE: An IPvFuture address cannot be the empty string - * so no need to compare .first with .afterLast, here. */ - memory->free(memory, (URI_CHAR *)uri->hostData.ipFuture.first); - uri->hostData.ipFuture.first = NULL; - uri->hostData.ipFuture.afterLast = NULL; - uri->hostText.first = NULL; - uri->hostText.afterLast = NULL; - } else if (uri->hostText.first != NULL) { - /* Regname */ - if (uri->hostText.first != uri->hostText.afterLast) { - memory->free(memory, (URI_CHAR *)uri->hostText.first); - } - uri->hostText.first = NULL; - uri->hostText.afterLast = NULL; - } - } - - /* NOTE: Port cannot happen! */ - - if (revertMask & URI_NORMALIZE_PATH) { - URI_TYPE(PathSegment) * walker = uri->pathHead; - while (walker != NULL) { - URI_TYPE(PathSegment) * const next = walker->next; - if (walker->text.afterLast > walker->text.first) { - memory->free(memory, (URI_CHAR *)walker->text.first); - } - memory->free(memory, walker); - walker = next; - } - uri->pathHead = NULL; - uri->pathTail = NULL; - } - - if (revertMask & URI_NORMALIZE_QUERY) { - if (uri->query.first != uri->query.afterLast) { - memory->free(memory, (URI_CHAR *)uri->query.first); - } - uri->query.first = NULL; - uri->query.afterLast = NULL; - } - - if (revertMask & URI_NORMALIZE_FRAGMENT) { - if (uri->fragment.first != uri->fragment.afterLast) { - memory->free(memory, (URI_CHAR *)uri->fragment.first); - } - uri->fragment.first = NULL; - uri->fragment.afterLast = NULL; - } + const URI_CHAR ** afterLast, + UriMemoryManager * memory); + +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 + * so no need to compare .first with .afterLast, here. */ + memory->free(memory, (URI_CHAR *)uri->scheme.first); + uri->scheme.first = NULL; + uri->scheme.afterLast = NULL; + } + + if (revertMask & URI_NORMALIZE_USER_INFO) { + if (uri->userInfo.first != uri->userInfo.afterLast) { + memory->free(memory, (URI_CHAR *)uri->userInfo.first); + } + uri->userInfo.first = NULL; + uri->userInfo.afterLast = NULL; + } + + if (revertMask & URI_NORMALIZE_HOST) { + if (uri->hostData.ipFuture.first != NULL) { + /* IPvFuture */ + /* NOTE: An IPvFuture address cannot be the empty string + * so no need to compare .first with .afterLast, here. */ + memory->free(memory, (URI_CHAR *)uri->hostData.ipFuture.first); + uri->hostData.ipFuture.first = NULL; + uri->hostData.ipFuture.afterLast = NULL; + uri->hostText.first = NULL; + uri->hostText.afterLast = NULL; + } else if (uri->hostText.first != NULL) { + /* Regname */ + if (uri->hostText.first != uri->hostText.afterLast) { + memory->free(memory, (URI_CHAR *)uri->hostText.first); + } + uri->hostText.first = NULL; + uri->hostText.afterLast = NULL; + } + } + + /* NOTE: Port cannot happen! */ + + if (revertMask & URI_NORMALIZE_PATH) { + URI_TYPE(PathSegment) * walker = uri->pathHead; + while (walker != NULL) { + URI_TYPE(PathSegment) * const next = walker->next; + if (walker->text.afterLast > walker->text.first) { + memory->free(memory, (URI_CHAR *)walker->text.first); + } + memory->free(memory, walker); + walker = next; + } + uri->pathHead = NULL; + uri->pathTail = NULL; + } + + if (revertMask & URI_NORMALIZE_QUERY) { + if (uri->query.first != uri->query.afterLast) { + memory->free(memory, (URI_CHAR *)uri->query.first); + } + uri->query.first = NULL; + uri->query.afterLast = NULL; + } + + if (revertMask & URI_NORMALIZE_FRAGMENT) { + if (uri->fragment.first != uri->fragment.afterLast) { + memory->free(memory, (URI_CHAR *)uri->fragment.first); + } + uri->fragment.first = NULL; + uri->fragment.afterLast = NULL; + } } - - static URI_INLINE UriBool URI_FUNC(ContainsUppercaseLetters)(const URI_CHAR * first, - const URI_CHAR * afterLast) { - if ((first != NULL) && (afterLast != NULL) && (afterLast > first)) { - const URI_CHAR * i = first; - for (; i < afterLast; i++) { - /* 6.2.2.1 Case Normalization: uppercase letters in scheme or host */ - if ((*i >= _UT('A')) && (*i <= _UT('Z'))) { - return URI_TRUE; - } - } - } - return URI_FALSE; + const URI_CHAR * afterLast) { + if ((first != NULL) && (afterLast != NULL) && (afterLast > first)) { + const URI_CHAR * i = first; + for (; i < afterLast; i++) { + /* 6.2.2.1 Case Normalization: uppercase letters in scheme or host */ + if ((*i >= _UT('A')) && (*i <= _UT('Z'))) { + return URI_TRUE; + } + } + } + return URI_FALSE; } - - -static URI_INLINE UriBool URI_FUNC(ContainsUglyPercentEncoding)(const URI_CHAR * first, - const URI_CHAR * afterLast) { - if ((first != NULL) && (afterLast != NULL) && (afterLast > first)) { - const URI_CHAR * i = first; - for (; i + 2 < afterLast; i++) { - if (i[0] == _UT('%')) { - /* 6.2.2.1 Case Normalization: * - * lowercase percent-encodings */ - if (((i[1] >= _UT('a')) && (i[1] <= _UT('f'))) - || ((i[2] >= _UT('a')) && (i[2] <= _UT('f')))) { - return URI_TRUE; - } else { - /* 6.2.2.2 Percent-Encoding Normalization: * - * percent-encoded unreserved characters */ - const unsigned char left = URI_FUNC(HexdigToInt)(i[1]); - const unsigned char right = URI_FUNC(HexdigToInt)(i[2]); - const int code = 16 * left + right; - if (uriIsUnreserved(code)) { - return URI_TRUE; - } - } - } - } - } - return URI_FALSE; +static URI_INLINE UriBool URI_FUNC(ContainsUglyPercentEncoding)( + const URI_CHAR * first, const URI_CHAR * afterLast) { + if ((first != NULL) && (afterLast != NULL) && (afterLast > first)) { + const URI_CHAR * i = first; + for (; i + 2 < afterLast; i++) { + if (i[0] == _UT('%')) { + /* 6.2.2.1 Case Normalization: * + * lowercase percent-encodings */ + if (((i[1] >= _UT('a')) && (i[1] <= _UT('f'))) + || ((i[2] >= _UT('a')) && (i[2] <= _UT('f')))) { + return URI_TRUE; + } else { + /* 6.2.2.2 Percent-Encoding Normalization: * + * percent-encoded unreserved characters */ + const unsigned char left = URI_FUNC(HexdigToInt)(i[1]); + const unsigned char right = URI_FUNC(HexdigToInt)(i[2]); + const int code = 16 * left + right; + if (uriIsUnreserved(code)) { + return URI_TRUE; + } + } + } + } + } + return URI_FALSE; } - - static URI_INLINE void URI_FUNC(LowercaseInplace)(const URI_CHAR * first, - const URI_CHAR * afterLast) { - if ((first != NULL) && (afterLast != NULL) && (afterLast > first)) { - URI_CHAR * i = (URI_CHAR *)first; - const int lowerUpperDiff = (_UT('a') - _UT('A')); - for (; i < afterLast; i++) { - if ((*i >= _UT('A')) && (*i <=_UT('Z'))) { - *i = (URI_CHAR)(*i + lowerUpperDiff); - } - } - } + const URI_CHAR * afterLast) { + if ((first != NULL) && (afterLast != NULL) && (afterLast > first)) { + URI_CHAR * i = (URI_CHAR *)first; + const int lowerUpperDiff = (_UT('a') - _UT('A')); + for (; i < afterLast; i++) { + if ((*i >= _UT('A')) && (*i <= _UT('Z'))) { + *i = (URI_CHAR)(*i + lowerUpperDiff); + } + } + } } - - -static URI_INLINE void URI_FUNC(LowercaseInplaceExceptPercentEncoding)(const URI_CHAR * first, - const URI_CHAR * afterLast) { - if ((first != NULL) && (afterLast != NULL) && (afterLast > first)) { - URI_CHAR * i = (URI_CHAR *)first; - const int lowerUpperDiff = (_UT('a') - _UT('A')); - for (; i < afterLast; i++) { - if ((*i >= _UT('A')) && (*i <=_UT('Z'))) { - *i = (URI_CHAR)(*i + lowerUpperDiff); - } else if (*i == _UT('%')) { - if (i + 3 >= afterLast) { - return; - } - i += 2; - } - } - } +static URI_INLINE void +URI_FUNC(LowercaseInplaceExceptPercentEncoding)(const URI_CHAR * first, + const URI_CHAR * afterLast) { + if ((first != NULL) && (afterLast != NULL) && (afterLast > first)) { + URI_CHAR * i = (URI_CHAR *)first; + const int lowerUpperDiff = (_UT('a') - _UT('A')); + for (; i < afterLast; i++) { + if ((*i >= _UT('A')) && (*i <= _UT('Z'))) { + *i = (URI_CHAR)(*i + lowerUpperDiff); + } else if (*i == _UT('%')) { + if (i + 3 >= afterLast) { + return; + } + i += 2; + } + } + } } - - static URI_INLINE UriBool URI_FUNC(LowercaseMalloc)(const URI_CHAR ** first, - const URI_CHAR ** afterLast, UriMemoryManager * memory) { - int lenInChars; - const int lowerUpperDiff = (_UT('a') - _UT('A')); - URI_CHAR * buffer; - int i = 0; - - if ((first == NULL) || (afterLast == NULL) || (*first == NULL) - || (*afterLast == NULL)) { - return URI_FALSE; - } - - lenInChars = (int)(*afterLast - *first); - if (lenInChars == 0) { - return URI_TRUE; - } else if (lenInChars < 0) { - return URI_FALSE; - } - - buffer = memory->malloc(memory, lenInChars * sizeof(URI_CHAR)); - if (buffer == NULL) { - return URI_FALSE; - } - - for (; i < lenInChars; i++) { - if (((*first)[i] >= _UT('A')) && ((*first)[i] <=_UT('Z'))) { - buffer[i] = (URI_CHAR)((*first)[i] + lowerUpperDiff); - } else { - buffer[i] = (*first)[i]; - } - } - - *first = buffer; - *afterLast = buffer + lenInChars; - return URI_TRUE; + const URI_CHAR ** afterLast, + UriMemoryManager * memory) { + int lenInChars; + const int lowerUpperDiff = (_UT('a') - _UT('A')); + URI_CHAR * buffer; + int i = 0; + + if ((first == NULL) || (afterLast == NULL) || (*first == NULL) + || (*afterLast == NULL)) { + return URI_FALSE; + } + + lenInChars = (int)(*afterLast - *first); + if (lenInChars == 0) { + return URI_TRUE; + } else if (lenInChars < 0) { + return URI_FALSE; + } + + buffer = memory->malloc(memory, lenInChars * sizeof(URI_CHAR)); + if (buffer == NULL) { + return URI_FALSE; + } + + for (; i < lenInChars; i++) { + if (((*first)[i] >= _UT('A')) && ((*first)[i] <= _UT('Z'))) { + buffer[i] = (URI_CHAR)((*first)[i] + lowerUpperDiff); + } else { + buffer[i] = (*first)[i]; + } + } + + *first = buffer; + *afterLast = buffer + lenInChars; + return URI_TRUE; } - - /* NOTE: Implementation must stay inplace-compatible */ -static URI_INLINE void URI_FUNC(FixPercentEncodingEngine)( - const URI_CHAR * inFirst, const URI_CHAR * inAfterLast, - const URI_CHAR * outFirst, const URI_CHAR ** outAfterLast) { - URI_CHAR * write = (URI_CHAR *)outFirst; - const int lenInChars = (int)(inAfterLast - inFirst); - int i = 0; - - /* All but last two */ - for (; i + 2 < lenInChars; i++) { - if (inFirst[i] != _UT('%')) { - write[0] = inFirst[i]; - write++; - } else { - /* 6.2.2.2 Percent-Encoding Normalization: * - * percent-encoded unreserved characters */ - const URI_CHAR one = inFirst[i + 1]; - const URI_CHAR two = inFirst[i + 2]; - const unsigned char left = URI_FUNC(HexdigToInt)(one); - const unsigned char right = URI_FUNC(HexdigToInt)(two); - const int code = 16 * left + right; - if (uriIsUnreserved(code)) { - write[0] = (URI_CHAR)(code); - write++; - } else { - /* 6.2.2.1 Case Normalization: * - * lowercase percent-encodings */ - write[0] = _UT('%'); - write[1] = URI_FUNC(HexToLetter)(left); - write[2] = URI_FUNC(HexToLetter)(right); - write += 3; - } - - i += 2; /* For the two chars of the percent group we just ate */ - } - } - - /* Last two */ - for (; i < lenInChars; i++) { - write[0] = inFirst[i]; - write++; - } - - *outAfterLast = write; +static URI_INLINE void +URI_FUNC(FixPercentEncodingEngine)(const URI_CHAR * inFirst, const URI_CHAR * inAfterLast, + const URI_CHAR * outFirst, + const URI_CHAR ** outAfterLast) { + URI_CHAR * write = (URI_CHAR *)outFirst; + const int lenInChars = (int)(inAfterLast - inFirst); + int i = 0; + + /* All but last two */ + for (; i + 2 < lenInChars; i++) { + if (inFirst[i] != _UT('%')) { + write[0] = inFirst[i]; + write++; + } else { + /* 6.2.2.2 Percent-Encoding Normalization: * + * percent-encoded unreserved characters */ + const URI_CHAR one = inFirst[i + 1]; + const URI_CHAR two = inFirst[i + 2]; + const unsigned char left = URI_FUNC(HexdigToInt)(one); + const unsigned char right = URI_FUNC(HexdigToInt)(two); + const int code = 16 * left + right; + if (uriIsUnreserved(code)) { + write[0] = (URI_CHAR)(code); + write++; + } else { + /* 6.2.2.1 Case Normalization: * + * uppercase percent-encodings */ + write[0] = _UT('%'); + write[1] = URI_FUNC(HexToLetterEx)(left, URI_TRUE); + write[2] = URI_FUNC(HexToLetterEx)(right, URI_TRUE); + write += 3; + } + + i += 2; /* For the two chars of the percent group we just ate */ + } + } + + /* Last two */ + for (; i < lenInChars; i++) { + write[0] = inFirst[i]; + write++; + } + + *outAfterLast = write; } - - static URI_INLINE void URI_FUNC(FixPercentEncodingInplace)(const URI_CHAR * first, - const URI_CHAR ** afterLast) { - /* Death checks */ - if ((first == NULL) || (afterLast == NULL) || (*afterLast == NULL)) { - return; - } - - /* Fix inplace */ - URI_FUNC(FixPercentEncodingEngine)(first, *afterLast, first, afterLast); + const URI_CHAR ** afterLast) { + /* Death checks */ + if ((first == NULL) || (afterLast == NULL) || (*afterLast == NULL)) { + return; + } + + /* Fix inplace */ + URI_FUNC(FixPercentEncodingEngine)(first, *afterLast, first, afterLast); } - - static URI_INLINE UriBool URI_FUNC(FixPercentEncodingMalloc)(const URI_CHAR ** first, - const URI_CHAR ** afterLast, UriMemoryManager * memory) { - int lenInChars; - URI_CHAR * buffer; - - /* Death checks */ - if ((first == NULL) || (afterLast == NULL) - || (*first == NULL) || (*afterLast == NULL)) { - return URI_FALSE; - } - - /* Old text length */ - lenInChars = (int)(*afterLast - *first); - if (lenInChars == 0) { - return URI_TRUE; - } else if (lenInChars < 0) { - return URI_FALSE; - } - - /* New buffer */ - buffer = memory->malloc(memory, lenInChars * sizeof(URI_CHAR)); - if (buffer == NULL) { - return URI_FALSE; - } - - /* Fix on copy */ - URI_FUNC(FixPercentEncodingEngine)(*first, *afterLast, buffer, afterLast); - *first = buffer; - return URI_TRUE; + const URI_CHAR ** afterLast, + UriMemoryManager * memory) { + int lenInChars; + URI_CHAR * buffer; + + /* Death checks */ + if ((first == NULL) || (afterLast == NULL) || (*first == NULL) + || (*afterLast == NULL)) { + return URI_FALSE; + } + + /* Old text length */ + lenInChars = (int)(*afterLast - *first); + if (lenInChars == 0) { + return URI_TRUE; + } else if (lenInChars < 0) { + return URI_FALSE; + } + + /* New buffer */ + buffer = memory->malloc(memory, lenInChars * sizeof(URI_CHAR)); + if (buffer == NULL) { + return URI_FALSE; + } + + /* Fix on copy */ + URI_FUNC(FixPercentEncodingEngine)(*first, *afterLast, buffer, afterLast); + *first = buffer; + return URI_TRUE; } - - -static URI_INLINE UriBool URI_FUNC(MakeRangeOwner)(unsigned int * doneMask, - unsigned int maskTest, URI_TYPE(TextRange) * range, - UriMemoryManager * memory) { - if (((*doneMask & maskTest) == 0) - && (range->first != NULL) - && (range->afterLast != NULL) - && (range->afterLast > range->first)) { - if (URI_FUNC(CopyRange)(range, range, memory) == URI_FALSE) { - return URI_FALSE; - } - *doneMask |= maskTest; - } - return URI_TRUE; +static URI_INLINE UriBool URI_FUNC(MakeRangeOwner)(unsigned int * revertMask, + unsigned int maskTest, + URI_TYPE(TextRange) * range, + UriMemoryManager * memory) { + if (((*revertMask & maskTest) == 0) && (range->first != NULL) + && (range->afterLast != NULL) && (range->afterLast > range->first)) { + if (URI_FUNC(CopyRange)(range, range, memory) == URI_FALSE) { + return URI_FALSE; + } + *revertMask |= maskTest; + } + return URI_TRUE; } - - static URI_INLINE UriBool URI_FUNC(MakeOwnerEngine)(URI_TYPE(Uri) * uri, - unsigned int * doneMask, UriMemoryManager * memory) { - URI_TYPE(PathSegment) * walker = uri->pathHead; - if (!URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_SCHEME, - &(uri->scheme), memory) - || !URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_USER_INFO, - &(uri->userInfo), memory) - || !URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_QUERY, - &(uri->query), memory) - || !URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_FRAGMENT, - &(uri->fragment), memory)) { - return URI_FALSE; /* Raises malloc error */ - } - - /* Host */ - if ((*doneMask & URI_NORMALIZE_HOST) == 0) { - if (uri->hostData.ipFuture.first != NULL) { - /* IPvFuture */ - if (!URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_HOST, - &(uri->hostData.ipFuture), memory)) { - return URI_FALSE; /* Raises malloc error */ - } - uri->hostText.first = uri->hostData.ipFuture.first; - uri->hostText.afterLast = uri->hostData.ipFuture.afterLast; - } else if (uri->hostText.first != NULL) { - /* Regname */ - if (!URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_HOST, - &(uri->hostText), memory)) { - return URI_FALSE; /* Raises malloc error */ - } - } - } - - /* Path */ - if ((*doneMask & URI_NORMALIZE_PATH) == 0) { - while (walker != NULL) { - if (!URI_FUNC(MakeRangeOwner)(doneMask, 0, &(walker->text), memory)) { - /* Free allocations done so far and kill path */ - - /* Kill path to one before walker (if any) */ - URI_TYPE(PathSegment) * ranger = uri->pathHead; - while (ranger != walker) { - URI_TYPE(PathSegment) * const next = ranger->next; - if ((ranger->text.first != NULL) - && (ranger->text.afterLast != NULL) - && (ranger->text.afterLast > ranger->text.first)) { - memory->free(memory, (URI_CHAR *)ranger->text.first); - } - memory->free(memory, ranger); - ranger = next; - } - - /* Kill path from walker */ - while (walker != NULL) { - URI_TYPE(PathSegment) * const next = walker->next; - memory->free(memory, walker); - walker = next; - } - - uri->pathHead = NULL; - uri->pathTail = NULL; - return URI_FALSE; /* Raises malloc error */ - } - walker = walker->next; - } - *doneMask |= 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)) { - return URI_FALSE; /* Raises malloc error */ - } - - return URI_TRUE; + unsigned int * revertMask, + UriMemoryManager * memory) { + URI_TYPE(PathSegment) * walker = uri->pathHead; + if (!URI_FUNC(MakeRangeOwner)(revertMask, URI_NORMALIZE_SCHEME, &(uri->scheme), + memory) + || !URI_FUNC(MakeRangeOwner)(revertMask, URI_NORMALIZE_USER_INFO, + &(uri->userInfo), memory) + || !URI_FUNC(MakeRangeOwner)(revertMask, URI_NORMALIZE_QUERY, &(uri->query), + memory) + || !URI_FUNC(MakeRangeOwner)(revertMask, URI_NORMALIZE_FRAGMENT, &(uri->fragment), + memory)) { + return URI_FALSE; /* Raises malloc error */ + } + + /* Host */ + if ((*revertMask & URI_NORMALIZE_HOST) == 0) { + if (uri->hostData.ipFuture.first != NULL) { + /* IPvFuture */ + if (!URI_FUNC(MakeRangeOwner)(revertMask, URI_NORMALIZE_HOST, + &(uri->hostData.ipFuture), memory)) { + return URI_FALSE; /* Raises malloc error */ + } + uri->hostText.first = uri->hostData.ipFuture.first; + uri->hostText.afterLast = uri->hostData.ipFuture.afterLast; + } else if (uri->hostText.first != NULL) { + /* Regname */ + if (!URI_FUNC(MakeRangeOwner)(revertMask, URI_NORMALIZE_HOST, + &(uri->hostText), memory)) { + return URI_FALSE; /* Raises malloc error */ + } + } + } + + /* Path */ + if ((*revertMask & URI_NORMALIZE_PATH) == 0) { + while (walker != NULL) { + 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) */ + URI_TYPE(PathSegment) * ranger = uri->pathHead; + while (ranger != walker) { + URI_TYPE(PathSegment) * const next = ranger->next; + if ((ranger->text.first != NULL) && (ranger->text.afterLast != NULL) + && (ranger->text.afterLast > ranger->text.first)) { + memory->free(memory, (URI_CHAR *)ranger->text.first); + } + memory->free(memory, ranger); + ranger = next; + } + + /* Kill path from walker */ + while (walker != NULL) { + URI_TYPE(PathSegment) * const next = walker->next; + memory->free(memory, walker); + walker = next; + } + + uri->pathHead = NULL; + uri->pathTail = NULL; + return URI_FALSE; /* Raises malloc error */ + } + walker = walker->next; + } + *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)(revertMask, 0, &(uri->portText), memory)) { + return URI_FALSE; /* Raises malloc error */ + } + + return URI_TRUE; } - - unsigned int URI_FUNC(NormalizeSyntaxMaskRequired)(const URI_TYPE(Uri) * uri) { - unsigned int outMask = URI_NORMALIZED; /* for NULL uri */ - URI_FUNC(NormalizeSyntaxMaskRequiredEx)(uri, &outMask); - return outMask; + unsigned int outMask = URI_NORMALIZED; /* for NULL uri */ + URI_FUNC(NormalizeSyntaxMaskRequiredEx)(uri, &outMask); + return outMask; } - - int URI_FUNC(NormalizeSyntaxMaskRequiredEx)(const URI_TYPE(Uri) * uri, - unsigned int * outMask) { - UriMemoryManager * const memory = NULL; /* no use of memory manager */ - -#if defined(__GNUC__) && ((__GNUC__ > 4) \ - || ((__GNUC__ == 4) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 2))) - /* Slower code that fixes a warning, not sure if this is a smart idea */ - URI_TYPE(Uri) writeableClone; -#endif - - if ((uri == NULL) || (outMask == NULL)) { - return URI_ERROR_NULL; - } - -#if defined(__GNUC__) && ((__GNUC__ > 4) \ - || ((__GNUC__ == 4) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 2))) - /* Slower code that fixes a warning, not sure if this is a smart idea */ - memcpy(&writeableClone, uri, 1 * sizeof(URI_TYPE(Uri))); - URI_FUNC(NormalizeSyntaxEngine)(&writeableClone, 0, outMask, memory); -#else - URI_FUNC(NormalizeSyntaxEngine)((URI_TYPE(Uri) *)uri, 0, outMask, memory); -#endif - return URI_SUCCESS; + unsigned int * outMask) { + UriMemoryManager * const memory = NULL; /* no use of memory manager */ + +# if defined(__GNUC__) \ + && ((__GNUC__ > 4) \ + || ((__GNUC__ == 4) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 2))) + /* Slower code that fixes a warning, not sure if this is a smart idea */ + URI_TYPE(Uri) writeableClone; +# endif + + if ((uri == NULL) || (outMask == NULL)) { + return URI_ERROR_NULL; + } + +# if defined(__GNUC__) \ + && ((__GNUC__ > 4) \ + || ((__GNUC__ == 4) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 2))) + /* Slower code that fixes a warning, not sure if this is a smart idea */ + memcpy(&writeableClone, uri, 1 * sizeof(URI_TYPE(Uri))); + URI_FUNC(NormalizeSyntaxEngine)(&writeableClone, 0, outMask, memory); +# else + URI_FUNC(NormalizeSyntaxEngine)((URI_TYPE(Uri) *)uri, 0, outMask, memory); +# endif + return URI_SUCCESS; } - - int URI_FUNC(NormalizeSyntaxEx)(URI_TYPE(Uri) * uri, unsigned int mask) { - return URI_FUNC(NormalizeSyntaxExMm)(uri, mask, NULL); + return URI_FUNC(NormalizeSyntaxExMm)(uri, mask, NULL); } - - int URI_FUNC(NormalizeSyntaxExMm)(URI_TYPE(Uri) * uri, unsigned int mask, - UriMemoryManager * memory) { - URI_CHECK_MEMORY_MANAGER(memory); /* may return */ - return URI_FUNC(NormalizeSyntaxEngine)(uri, mask, NULL, memory); + UriMemoryManager * memory) { + URI_CHECK_MEMORY_MANAGER(memory); /* may return */ + return URI_FUNC(NormalizeSyntaxEngine)(uri, mask, NULL, memory); } - - int URI_FUNC(NormalizeSyntax)(URI_TYPE(Uri) * uri) { - return URI_FUNC(NormalizeSyntaxEx)(uri, (unsigned int)-1); + return URI_FUNC(NormalizeSyntaxEx)(uri, (unsigned int)-1); } - -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 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; + } -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); + 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; - } - } + 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; + } -static void URI_FUNC(AdvancePastLeadingZeros)( - const URI_CHAR ** first, const URI_CHAR * afterLast) { - assert(first != NULL); - assert(*first != NULL); - assert(afterLast != NULL); + const URI_CHAR * const remainderFirst = URI_FUNC(PastLeadingZeros)(*first, afterLast); - if (*first == afterLast) { - return; - } - - { - const URI_CHAR * const remainderFirst = URI_FUNC(PastLeadingZeros)(*first, afterLast); - - /* Cut off leading zeros */ - *first = remainderFirst; - } + /* 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; - - /* Not just doing inspection? -> memory manager required! */ - if (outMask == NULL) { - assert(memory != NULL); - } - - if (uri == NULL) { - if (outMask != NULL) { - *outMask = URI_NORMALIZED; - return URI_SUCCESS; - } else { - return URI_ERROR_NULL; - } - } - - if (outMask != NULL) { - /* Reset mask */ - *outMask = URI_NORMALIZED; - } else if (inMask == URI_NORMALIZED) { - /* Nothing to do */ - return URI_SUCCESS; - } - - /* Scheme, host */ - if (outMask != NULL) { - const UriBool normalizeScheme = URI_FUNC(ContainsUppercaseLetters)( - uri->scheme.first, uri->scheme.afterLast); - const UriBool normalizeHostCase = URI_FUNC(ContainsUppercaseLetters)( - uri->hostText.first, uri->hostText.afterLast); - if (normalizeScheme) { - *outMask |= URI_NORMALIZE_SCHEME; - } - - if (normalizeHostCase) { - *outMask |= URI_NORMALIZE_HOST; - } else { - const UriBool normalizeHostPrecent = URI_FUNC(ContainsUglyPercentEncoding)( - uri->hostText.first, uri->hostText.afterLast); - if (normalizeHostPrecent) { - *outMask |= URI_NORMALIZE_HOST; - } - } - } else { - /* Scheme */ - if ((inMask & URI_NORMALIZE_SCHEME) && (uri->scheme.first != NULL)) { - if (uri->owner) { - 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); - return URI_ERROR_MALLOC; - } - doneMask |= URI_NORMALIZE_SCHEME; - } - } - - /* Host */ - if (inMask & URI_NORMALIZE_HOST) { - if (uri->hostData.ipFuture.first != NULL) { - /* IPvFuture */ - if (uri->owner) { - URI_FUNC(LowercaseInplace)(uri->hostData.ipFuture.first, - uri->hostData.ipFuture.afterLast); - } else { - if (!URI_FUNC(LowercaseMalloc)(&(uri->hostData.ipFuture.first), - &(uri->hostData.ipFuture.afterLast), memory)) { - URI_FUNC(PreventLeakage)(uri, doneMask, memory); - return URI_ERROR_MALLOC; - } - doneMask |= URI_NORMALIZE_HOST; - } - uri->hostText.first = uri->hostData.ipFuture.first; - uri->hostText.afterLast = uri->hostData.ipFuture.afterLast; - } else if ((uri->hostText.first != NULL) - && (uri->hostData.ip4 == NULL)) { - /* Regname or IPv6 */ - if (uri->owner) { - URI_FUNC(FixPercentEncodingInplace)(uri->hostText.first, - &(uri->hostText.afterLast)); - } else { - if (!URI_FUNC(FixPercentEncodingMalloc)( - &(uri->hostText.first), - &(uri->hostText.afterLast), - memory)) { - URI_FUNC(PreventLeakage)(uri, doneMask, memory); - return URI_ERROR_MALLOC; - } - doneMask |= URI_NORMALIZE_HOST; - } - - URI_FUNC(LowercaseInplaceExceptPercentEncoding)(uri->hostText.first, - uri->hostText.afterLast); - } - } - } - - /* 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)( - uri->userInfo.first, uri->userInfo.afterLast); - if (normalizeUserInfo) { - *outMask |= URI_NORMALIZE_USER_INFO; - } - } else { - if ((inMask & URI_NORMALIZE_USER_INFO) && (uri->userInfo.first != NULL)) { - if (uri->owner) { - URI_FUNC(FixPercentEncodingInplace)(uri->userInfo.first, &(uri->userInfo.afterLast)); - } else { - if (!URI_FUNC(FixPercentEncodingMalloc)(&(uri->userInfo.first), - &(uri->userInfo.afterLast), memory)) { - URI_FUNC(PreventLeakage)(uri, doneMask, memory); - return URI_ERROR_MALLOC; - } - doneMask |= URI_NORMALIZE_USER_INFO; - } - } - } - - /* Path */ - if (outMask != NULL) { - const URI_TYPE(PathSegment) * walker = uri->pathHead; - while (walker != NULL) { - const URI_CHAR * const first = walker->text.first; - const URI_CHAR * const afterLast = walker->text.afterLast; - if ((first != NULL) - && (afterLast != NULL) - && (afterLast > first) - && ( - (((afterLast - first) == 1) - && (first[0] == _UT('.'))) - || - (((afterLast - first) == 2) - && (first[0] == _UT('.')) - && (first[1] == _UT('.'))) - || - URI_FUNC(ContainsUglyPercentEncoding)(first, afterLast) - )) { - *outMask |= URI_NORMALIZE_PATH; - break; - } - walker = walker->next; - } - } else if (inMask & URI_NORMALIZE_PATH) { - URI_TYPE(PathSegment) * walker; - const UriBool relative = ((uri->scheme.first == NULL) - && !uri->absolutePath) ? URI_TRUE : URI_FALSE; - - /* Fix percent-encoding for each segment */ - walker = uri->pathHead; - if (uri->owner) { - while (walker != NULL) { - URI_FUNC(FixPercentEncodingInplace)(walker->text.first, &(walker->text.afterLast)); - walker = walker->next; - } - } else { - while (walker != NULL) { - if (!URI_FUNC(FixPercentEncodingMalloc)(&(walker->text.first), - &(walker->text.afterLast), memory)) { - URI_FUNC(PreventLeakage)(uri, doneMask, memory); - return URI_ERROR_MALLOC; - } - walker = walker->next; - } - doneMask |= 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), - memory)) { - URI_FUNC(PreventLeakage)(uri, doneMask, memory); - return URI_ERROR_MALLOC; - } - URI_FUNC(FixEmptyTrailSegment)(uri, memory); - } - - /* Query, fragment */ - if (outMask != NULL) { - const UriBool normalizeQuery = URI_FUNC(ContainsUglyPercentEncoding)( - uri->query.first, uri->query.afterLast); - const UriBool normalizeFragment = URI_FUNC(ContainsUglyPercentEncoding)( - uri->fragment.first, uri->fragment.afterLast); - if (normalizeQuery) { - *outMask |= URI_NORMALIZE_QUERY; - } - - if (normalizeFragment) { - *outMask |= URI_NORMALIZE_FRAGMENT; - } - } else { - /* Query */ - if ((inMask & URI_NORMALIZE_QUERY) && (uri->query.first != NULL)) { - if (uri->owner) { - URI_FUNC(FixPercentEncodingInplace)(uri->query.first, &(uri->query.afterLast)); - } else { - if (!URI_FUNC(FixPercentEncodingMalloc)(&(uri->query.first), - &(uri->query.afterLast), memory)) { - URI_FUNC(PreventLeakage)(uri, doneMask, memory); - return URI_ERROR_MALLOC; - } - doneMask |= URI_NORMALIZE_QUERY; - } - } - - /* Fragment */ - if ((inMask & URI_NORMALIZE_FRAGMENT) && (uri->fragment.first != NULL)) { - if (uri->owner) { - URI_FUNC(FixPercentEncodingInplace)(uri->fragment.first, &(uri->fragment.afterLast)); - } else { - if (!URI_FUNC(FixPercentEncodingMalloc)(&(uri->fragment.first), - &(uri->fragment.afterLast), memory)) { - URI_FUNC(PreventLeakage)(uri, doneMask, memory); - return URI_ERROR_MALLOC; - } - doneMask |= 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); - return URI_ERROR_MALLOC; - } - uri->owner = URI_TRUE; - } - - return URI_SUCCESS; + unsigned int inMask, + unsigned int * outMask, + UriMemoryManager * memory) { + unsigned int revertMask = URI_NORMALIZED; + + /* Not just doing inspection? -> memory manager required! */ + if (outMask == NULL) { + assert(memory != NULL); + } + + if (uri == NULL) { + if (outMask != NULL) { + *outMask = URI_NORMALIZED; + return URI_SUCCESS; + } else { + return URI_ERROR_NULL; + } + } + + if (outMask != NULL) { + /* Reset mask */ + *outMask = URI_NORMALIZED; + } else if (inMask == URI_NORMALIZED) { + /* Nothing to do */ + return URI_SUCCESS; + } + + /* Scheme, host */ + if (outMask != NULL) { + const UriBool normalizeScheme = + URI_FUNC(ContainsUppercaseLetters)(uri->scheme.first, uri->scheme.afterLast); + const UriBool normalizeHostCase = URI_FUNC(ContainsUppercaseLetters)( + uri->hostText.first, uri->hostText.afterLast); + if (normalizeScheme) { + *outMask |= URI_NORMALIZE_SCHEME; + } + + if (normalizeHostCase) { + *outMask |= URI_NORMALIZE_HOST; + } else { + const UriBool normalizeHostPrecent = URI_FUNC(ContainsUglyPercentEncoding)( + uri->hostText.first, uri->hostText.afterLast); + if (normalizeHostPrecent) { + *outMask |= URI_NORMALIZE_HOST; + } + } + } else { + /* Scheme */ + if ((inMask & URI_NORMALIZE_SCHEME) && (uri->scheme.first != NULL)) { + if (uri->owner) { + 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, revertMask, memory); + return URI_ERROR_MALLOC; + } + revertMask |= URI_NORMALIZE_SCHEME; + } + } + + /* Host */ + if (inMask & URI_NORMALIZE_HOST) { + if (uri->hostData.ipFuture.first != NULL) { + /* IPvFuture */ + if (uri->owner) { + URI_FUNC(LowercaseInplace)(uri->hostData.ipFuture.first, + uri->hostData.ipFuture.afterLast); + } else { + if (!URI_FUNC(LowercaseMalloc)(&(uri->hostData.ipFuture.first), + &(uri->hostData.ipFuture.afterLast), + memory)) { + URI_FUNC(PreventLeakage)(uri, revertMask, memory); + return URI_ERROR_MALLOC; + } + revertMask |= URI_NORMALIZE_HOST; + } + uri->hostText.first = uri->hostData.ipFuture.first; + uri->hostText.afterLast = uri->hostData.ipFuture.afterLast; + } else if ((uri->hostText.first != NULL) && (uri->hostData.ip4 == NULL)) { + /* Regname or IPv6 */ + if (uri->owner) { + URI_FUNC(FixPercentEncodingInplace)(uri->hostText.first, + &(uri->hostText.afterLast)); + } else { + if (!URI_FUNC(FixPercentEncodingMalloc)( + &(uri->hostText.first), &(uri->hostText.afterLast), memory)) { + URI_FUNC(PreventLeakage)(uri, revertMask, memory); + return URI_ERROR_MALLOC; + } + revertMask |= URI_NORMALIZE_HOST; + } + + URI_FUNC(LowercaseInplaceExceptPercentEncoding)(uri->hostText.first, + uri->hostText.afterLast); + } + } + } + + /* 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)( + uri->userInfo.first, uri->userInfo.afterLast); + if (normalizeUserInfo) { + *outMask |= URI_NORMALIZE_USER_INFO; + } + } else { + if ((inMask & URI_NORMALIZE_USER_INFO) && (uri->userInfo.first != NULL)) { + if (uri->owner) { + URI_FUNC(FixPercentEncodingInplace)(uri->userInfo.first, + &(uri->userInfo.afterLast)); + } else { + if (!URI_FUNC(FixPercentEncodingMalloc)( + &(uri->userInfo.first), &(uri->userInfo.afterLast), memory)) { + URI_FUNC(PreventLeakage)(uri, revertMask, memory); + return URI_ERROR_MALLOC; + } + revertMask |= URI_NORMALIZE_USER_INFO; + } + } + } + + /* Path */ + if (outMask != NULL) { + const URI_TYPE(PathSegment) * walker = uri->pathHead; + while (walker != NULL) { + const URI_CHAR * const first = walker->text.first; + const URI_CHAR * const afterLast = walker->text.afterLast; + if ((first != NULL) && (afterLast != NULL) && (afterLast > first) + && ((((afterLast - first) == 1) && (first[0] == _UT('.'))) + || (((afterLast - first) == 2) && (first[0] == _UT('.')) + && (first[1] == _UT('.'))) + || URI_FUNC(ContainsUglyPercentEncoding)(first, afterLast))) { + *outMask |= URI_NORMALIZE_PATH; + break; + } + walker = walker->next; + } + } else if (inMask & URI_NORMALIZE_PATH) { + URI_TYPE(PathSegment) * walker; + const UriBool relative = + ((uri->scheme.first == NULL) && !uri->absolutePath) ? URI_TRUE : URI_FALSE; + + /* Fix percent-encoding for each segment */ + walker = uri->pathHead; + if (uri->owner) { + while (walker != NULL) { + URI_FUNC(FixPercentEncodingInplace)(walker->text.first, + &(walker->text.afterLast)); + walker = walker->next; + } + } else { + while (walker != NULL) { + if (!URI_FUNC(FixPercentEncodingMalloc)( + &(walker->text.first), &(walker->text.afterLast), memory)) { + URI_FUNC(PreventLeakage)(uri, revertMask, memory); + return URI_ERROR_MALLOC; + } + walker = walker->next; + } + revertMask |= URI_NORMALIZE_PATH; + } + + /* 6.2.2.3 Path Segment Normalization */ + if (!URI_FUNC(RemoveDotSegmentsEx)( + uri, relative, + (uri->owner == URI_TRUE) || ((revertMask & URI_NORMALIZE_PATH) != 0), + memory)) { + URI_FUNC(PreventLeakage)(uri, revertMask, memory); + return URI_ERROR_MALLOC; + } + URI_FUNC(FixEmptyTrailSegment)(uri, memory); + } + + /* Query, fragment */ + if (outMask != NULL) { + const UriBool normalizeQuery = + URI_FUNC(ContainsUglyPercentEncoding)(uri->query.first, uri->query.afterLast); + const UriBool normalizeFragment = URI_FUNC(ContainsUglyPercentEncoding)( + uri->fragment.first, uri->fragment.afterLast); + if (normalizeQuery) { + *outMask |= URI_NORMALIZE_QUERY; + } + + if (normalizeFragment) { + *outMask |= URI_NORMALIZE_FRAGMENT; + } + } else { + /* Query */ + if ((inMask & URI_NORMALIZE_QUERY) && (uri->query.first != NULL)) { + if (uri->owner) { + URI_FUNC(FixPercentEncodingInplace)(uri->query.first, + &(uri->query.afterLast)); + } else { + if (!URI_FUNC(FixPercentEncodingMalloc)( + &(uri->query.first), &(uri->query.afterLast), memory)) { + URI_FUNC(PreventLeakage)(uri, revertMask, memory); + return URI_ERROR_MALLOC; + } + revertMask |= URI_NORMALIZE_QUERY; + } + } + + /* Fragment */ + if ((inMask & URI_NORMALIZE_FRAGMENT) && (uri->fragment.first != NULL)) { + if (uri->owner) { + URI_FUNC(FixPercentEncodingInplace)(uri->fragment.first, + &(uri->fragment.afterLast)); + } else { + if (!URI_FUNC(FixPercentEncodingMalloc)( + &(uri->fragment.first), &(uri->fragment.afterLast), memory)) { + URI_FUNC(PreventLeakage)(uri, revertMask, memory); + return URI_ERROR_MALLOC; + } + revertMask |= URI_NORMALIZE_FRAGMENT; + } + } + } + + /* Dup all not duped yet */ + if ((outMask == NULL) && !uri->owner) { + if (!URI_FUNC(MakeOwnerEngine)(uri, &revertMask, memory)) { + URI_FUNC(PreventLeakage)(uri, revertMask, memory); + return URI_ERROR_MALLOC; + } + uri->owner = URI_TRUE; + } + + return URI_SUCCESS; } - - 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 */ + URI_CHECK_MEMORY_MANAGER(memory); /* may return */ - if (uri == NULL) { - return URI_ERROR_NULL; - } + if (uri == NULL) { + return URI_ERROR_NULL; + } - if (uri->owner == URI_TRUE) { - return URI_SUCCESS; - } + if (uri->owner == URI_TRUE) { + return URI_SUCCESS; + } - if (! URI_FUNC(MakeOwnerEngine)(uri, &doneMask, memory)) { - URI_FUNC(PreventLeakage)(uri, doneMask, memory); - return URI_ERROR_MALLOC; - } + if (!URI_FUNC(MakeOwnerEngine)(uri, &revertMask, memory)) { + URI_FUNC(PreventLeakage)(uri, revertMask, memory); + return URI_ERROR_MALLOC; + } - uri->owner = URI_TRUE; + uri->owner = URI_TRUE; - return URI_SUCCESS; + return URI_SUCCESS; } - - int URI_FUNC(MakeOwner)(URI_TYPE(Uri) * uri) { - return URI_FUNC(MakeOwnerMm)(uri, NULL); + return URI_FUNC(MakeOwnerMm)(uri, NULL); } - - #endif diff --git a/ext/uri/uriparser/src/UriNormalize.h b/ext/uri/uriparser/src/UriNormalize.h index cb58085b7d318..41c87a382c369 100644 --- a/ext/uri/uriparser/src/UriNormalize.h +++ b/ext/uri/uriparser/src/UriNormalize.h @@ -39,38 +39,37 @@ */ #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)) + || (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 +# 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 +# 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 +# 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); - -void URI_FUNC(PreventLeakage)(URI_TYPE(Uri) * uri, - unsigned int revertMask, UriMemoryManager * memory); - -#endif +# endif #endif diff --git a/ext/uri/uriparser/src/UriNormalizeBase.c b/ext/uri/uriparser/src/UriNormalizeBase.c index a74fcd3f8bfbf..9c2acee1ee759 100644 --- a/ext/uri/uriparser/src/UriNormalizeBase.c +++ b/ext/uri/uriparser/src/UriNormalizeBase.c @@ -38,82 +38,80 @@ */ #ifndef URI_DOXYGEN -# include "UriNormalizeBase.h" +# include "UriNormalizeBase.h" #endif - - UriBool uriIsUnreserved(int code) { - switch (code) { - case L'a': /* ALPHA */ - case L'A': - case L'b': - case L'B': - case L'c': - case L'C': - case L'd': - case L'D': - case L'e': - case L'E': - case L'f': - case L'F': - case L'g': - case L'G': - case L'h': - case L'H': - case L'i': - case L'I': - case L'j': - case L'J': - case L'k': - case L'K': - case L'l': - case L'L': - case L'm': - case L'M': - case L'n': - case L'N': - case L'o': - case L'O': - case L'p': - case L'P': - case L'q': - case L'Q': - case L'r': - case L'R': - case L's': - case L'S': - case L't': - case L'T': - case L'u': - case L'U': - case L'v': - case L'V': - case L'w': - case L'W': - case L'x': - case L'X': - case L'y': - case L'Y': - case L'z': - case L'Z': - case L'0': /* DIGIT */ - case L'1': - case L'2': - case L'3': - case L'4': - case L'5': - case L'6': - case L'7': - case L'8': - case L'9': - case L'-': /* "-" / "." / "_" / "~" */ - case L'.': - case L'_': - case L'~': - return URI_TRUE; + switch (code) { + case L'a': /* ALPHA */ + case L'A': + case L'b': + case L'B': + case L'c': + case L'C': + case L'd': + case L'D': + case L'e': + case L'E': + case L'f': + case L'F': + case L'g': + case L'G': + case L'h': + case L'H': + case L'i': + case L'I': + case L'j': + case L'J': + case L'k': + case L'K': + case L'l': + case L'L': + case L'm': + case L'M': + case L'n': + case L'N': + case L'o': + case L'O': + case L'p': + case L'P': + case L'q': + case L'Q': + case L'r': + case L'R': + case L's': + case L'S': + case L't': + case L'T': + case L'u': + case L'U': + case L'v': + case L'V': + case L'w': + case L'W': + case L'x': + case L'X': + case L'y': + case L'Y': + case L'z': + case L'Z': + case L'0': /* DIGIT */ + case L'1': + case L'2': + case L'3': + case L'4': + case L'5': + case L'6': + case L'7': + case L'8': + case L'9': + case L'-': /* "-" / "." / "_" / "~" */ + case L'.': + case L'_': + case L'~': + return URI_TRUE; - default: - return URI_FALSE; - } + default: + return URI_FALSE; + } } diff --git a/ext/uri/uriparser/src/UriNormalizeBase.h b/ext/uri/uriparser/src/UriNormalizeBase.h index 8651c8616649f..3ff49112a82cc 100644 --- a/ext/uri/uriparser/src/UriNormalizeBase.h +++ b/ext/uri/uriparser/src/UriNormalizeBase.h @@ -38,16 +38,10 @@ */ #ifndef URI_NORMALIZE_BASE_H -#define URI_NORMALIZE_BASE_H 1 - - - -#include - +# define URI_NORMALIZE_BASE_H 1 +# include UriBool uriIsUnreserved(int code); - - #endif /* URI_NORMALIZE_BASE_H */ diff --git a/ext/uri/uriparser/src/UriParse.c b/ext/uri/uriparser/src/UriParse.c index a672c8eb1f2fc..cada02301e00c 100644 --- a/ext/uri/uriparser/src/UriParse.c +++ b/ext/uri/uriparser/src/UriParse.c @@ -47,839 +47,757 @@ #include #if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) /* Include SELF twice */ -# ifdef URI_ENABLE_ANSI -# define URI_PASS_ANSI 1 -# include "UriParse.c" -# undef URI_PASS_ANSI -# endif -# ifdef URI_ENABLE_UNICODE -# define URI_PASS_UNICODE 1 -# include "UriParse.c" -# undef URI_PASS_UNICODE -# endif +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriParse.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriParse.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 "UriParseBase.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') - - - -static const URI_CHAR * URI_FUNC(ParseAuthority)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParseAuthorityTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseHexZero)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseHierPart)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParseIpFutLoop)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParseIpFutStopGo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParseIpLit2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParseMustBeSegmentNzNc)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParseOwnHost)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParseOwnHost2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParseOwnHostUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParseOwnHostUserInfoNz)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParseOwnPortUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParseOwnUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParsePartHelperTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParsePathAbsEmpty)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParsePathAbsNoLeadSlash)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParsePathRootless)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParsePchar)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParsePctEncoded)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParsePctSubUnres)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParsePort)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseQueryFrag)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParseSegment)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParseSegmentNz)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParseSegmentNzNcOrScheme2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParseUriReference)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParseUriTail)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParseUriTailTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParseZeroMoreSlashSegs)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); - -static UriBool URI_FUNC(OnExitOwnHost2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, UriMemoryManager * memory); -static UriBool URI_FUNC(OnExitOwnHostUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, UriMemoryManager * memory); -static UriBool URI_FUNC(OnExitOwnPortUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, UriMemoryManager * memory); -static UriBool URI_FUNC(OnExitSegmentNzNcOrScheme2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, UriMemoryManager * memory); +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif + +# ifndef URI_DOXYGEN +# include +# include +# include "UriCommon.h" +# include "UriMemory.h" +# include "UriParseBase.h" +# include "UriSets.h" +# endif + +static const URI_CHAR * URI_FUNC(ParseAuthority)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseAuthorityTwo)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast); +static const URI_CHAR * URI_FUNC(ParseHexZero)(const URI_CHAR * first, + const URI_CHAR * afterLast); +static const URI_CHAR * URI_FUNC(ParseHierPart)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseIpFutLoop)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseIpLit2)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseMustBeSegmentNzNc)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseOwnHost)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseOwnHost2)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseOwnHostUserInfoNz)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseOwnPortUserInfo)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseOwnUserInfo)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParsePartHelperTwo)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParsePathAbsEmpty)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParsePathAbsNoLeadSlash)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParsePathRootless)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParsePchar)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParsePctEncoded)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParsePctSubUnres)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParsePort)(const URI_CHAR * first, + const URI_CHAR * afterLast); +static const URI_CHAR * URI_FUNC(ParseQueryFrag)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseSegment)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseSegmentNz)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseSegmentNzNcOrScheme2)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseUriReference)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseUriTail)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseUriTailTwo)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseZeroMoreSlashSegs)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); + +static UriBool URI_FUNC(OnExitOwnHost2)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + UriMemoryManager * memory); +static UriBool URI_FUNC(OnExitOwnHostUserInfo)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + UriMemoryManager * memory); +static UriBool URI_FUNC(OnExitOwnPortUserInfo)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + UriMemoryManager * memory); +static UriBool URI_FUNC(OnExitSegmentNzNcOrScheme2)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + UriMemoryManager * memory); static void URI_FUNC(OnExitPartHelperTwo)(URI_TYPE(ParserState) * state); static void URI_FUNC(ResetParserStateExceptUri)(URI_TYPE(ParserState) * state); static UriBool URI_FUNC(PushPathSegment)(URI_TYPE(ParserState) * state, - const URI_CHAR * first, const URI_CHAR * afterLast, - UriMemoryManager * memory); - -static void URI_FUNC(StopSyntax)(URI_TYPE(ParserState) * state, const URI_CHAR * errorPos, UriMemoryManager * memory); -static void URI_FUNC(StopMalloc)(URI_TYPE(ParserState) * state, UriMemoryManager * memory); - -static int URI_FUNC(ParseUriExMm)(URI_TYPE(ParserState) * state, - const URI_CHAR * first, const URI_CHAR * afterLast, - UriMemoryManager * memory); + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); +static void URI_FUNC(StopSyntax)(URI_TYPE(ParserState) * state, const URI_CHAR * errorPos, + UriMemoryManager * memory); +static void URI_FUNC(StopMalloc)(URI_TYPE(ParserState) * state, + UriMemoryManager * memory); +static int URI_FUNC(ParseUriExMm)(URI_TYPE(ParserState) * state, const URI_CHAR * first, + const URI_CHAR * afterLast, UriMemoryManager * memory); static URI_INLINE void URI_FUNC(StopSyntax)(URI_TYPE(ParserState) * state, - const URI_CHAR * errorPos, UriMemoryManager * memory) { - URI_FUNC(FreeUriMembersMm)(state->uri, memory); - state->errorPos = errorPos; - state->errorCode = URI_ERROR_SYNTAX; + const URI_CHAR * errorPos, + UriMemoryManager * memory) { + URI_FUNC(FreeUriMembersMm)(state->uri, memory); + state->errorPos = errorPos; + state->errorCode = URI_ERROR_SYNTAX; } - - -static URI_INLINE void URI_FUNC(StopMalloc)(URI_TYPE(ParserState) * state, UriMemoryManager * memory) { - URI_FUNC(FreeUriMembersMm)(state->uri, memory); - state->errorPos = NULL; - state->errorCode = URI_ERROR_MALLOC; +static URI_INLINE void URI_FUNC(StopMalloc)(URI_TYPE(ParserState) * state, + UriMemoryManager * memory) { + URI_FUNC(FreeUriMembersMm)(state->uri, memory); + state->errorPos = NULL; + state->errorCode = URI_ERROR_MALLOC; } - - /* * [authority]-><[>[ipLit2][authorityTwo] * [authority]->[ownHostUserInfoNz] * [authority]-> */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParseAuthority)( - URI_TYPE(ParserState) * state, const URI_CHAR * first, - const URI_CHAR * afterLast, UriMemoryManager * memory) { - if (first >= afterLast) { - /* "" regname host */ - state->uri->hostText.first = URI_FUNC(SafeToPointTo); - state->uri->hostText.afterLast = URI_FUNC(SafeToPointTo); - return afterLast; - } - - switch (*first) { - case _UT('['): - { - const URI_CHAR * const afterIpLit2 - = URI_FUNC(ParseIpLit2)(state, first + 1, afterLast, memory); - if (afterIpLit2 == NULL) { - return NULL; - } - state->uri->hostText.first = first + 1; /* HOST BEGIN */ - return URI_FUNC(ParseAuthorityTwo)(state, afterIpLit2, afterLast); - } - - case _UT('!'): - case _UT('$'): - case _UT('%'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('-'): - case _UT('*'): - case _UT(','): - case _UT('.'): - case _UT(':'): - case _UT(';'): - case _UT('@'): - case _UT('\''): - case _UT('_'): - case _UT('~'): - case _UT('+'): - case _UT('='): - case URI_SET_DIGIT: - case URI_SET_ALPHA: - state->uri->userInfo.first = first; /* USERINFO BEGIN */ - return URI_FUNC(ParseOwnHostUserInfoNz)(state, first, afterLast, memory); - - default: - /* "" regname host */ - state->uri->hostText.first = URI_FUNC(SafeToPointTo); - state->uri->hostText.afterLast = URI_FUNC(SafeToPointTo); - return first; - } +static URI_INLINE const URI_CHAR * URI_FUNC(ParseAuthority)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + if (first >= afterLast) { + /* "" regname host */ + state->uri->hostText.first = URI_FUNC(SafeToPointTo); + state->uri->hostText.afterLast = URI_FUNC(SafeToPointTo); + return afterLast; + } + + switch (*first) { + case _UT('['): { + const URI_CHAR * const afterIpLit2 = + URI_FUNC(ParseIpLit2)(state, first + 1, afterLast, memory); + if (afterIpLit2 == NULL) { + return NULL; + } + state->uri->hostText.first = first + 1; /* HOST BEGIN */ + return URI_FUNC(ParseAuthorityTwo)(state, afterIpLit2, afterLast); + } + + case URI_SET_PCHAR(_UT): + state->uri->userInfo.first = first; /* USERINFO BEGIN */ + return URI_FUNC(ParseOwnHostUserInfoNz)(state, first, afterLast, memory); + + default: + /* "" regname host */ + state->uri->hostText.first = URI_FUNC(SafeToPointTo); + state->uri->hostText.afterLast = URI_FUNC(SafeToPointTo); + return first; + } } - - /* * [authorityTwo]-><:>[port] * [authorityTwo]-> */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParseAuthorityTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { - if (first >= afterLast) { - return afterLast; - } - - switch (*first) { - case _UT(':'): - { - const URI_CHAR * const afterPort = URI_FUNC(ParsePort)(state, first + 1, afterLast); - if (afterPort == NULL) { - return NULL; - } - state->uri->portText.first = first + 1; /* PORT BEGIN */ - state->uri->portText.afterLast = afterPort; /* PORT END */ - return afterPort; - } - - default: - return first; - } +static URI_INLINE const URI_CHAR * +URI_FUNC(ParseAuthorityTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, + const URI_CHAR * afterLast) { + if (first >= afterLast) { + return afterLast; + } + + switch (*first) { + case _UT(':'): { + const URI_CHAR * const afterPort = URI_FUNC(ParsePort)(first + 1, afterLast); + if (afterPort == NULL) { + return NULL; + } + state->uri->portText.first = first + 1; /* PORT BEGIN */ + state->uri->portText.afterLast = afterPort; /* PORT END */ + return afterPort; + } + + default: + return first; + } } - - /* * [hexZero]->[HEXDIG][hexZero] * [hexZero]-> */ -static const URI_CHAR * URI_FUNC(ParseHexZero)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { - if (first >= afterLast) { - return afterLast; - } - - switch (*first) { - case URI_SET_HEXDIG: - return URI_FUNC(ParseHexZero)(state, first + 1, afterLast); - - default: - return first; - } +static const URI_CHAR * URI_FUNC(ParseHexZero)(const URI_CHAR * first, + const URI_CHAR * afterLast) { +tail_call: + if (first >= afterLast) { + return afterLast; + } + + switch (*first) { + case URI_SET_HEXDIG(_UT): + first += 1; + goto tail_call; + + default: + return first; + } } - - /* * [hierPart]->[pathRootless] * [hierPart]->[partHelperTwo] * [hierPart]-> */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParseHierPart)( - URI_TYPE(ParserState) * state, const URI_CHAR * first, - const URI_CHAR * afterLast, UriMemoryManager * memory) { - if (first >= afterLast) { - return afterLast; - } - - switch (*first) { - case _UT('!'): - case _UT('$'): - case _UT('%'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('-'): - case _UT('*'): - case _UT(','): - case _UT('.'): - case _UT(':'): - case _UT(';'): - case _UT('@'): - case _UT('\''): - case _UT('_'): - case _UT('~'): - case _UT('+'): - case _UT('='): - case URI_SET_DIGIT: - case URI_SET_ALPHA: - return URI_FUNC(ParsePathRootless)(state, first, afterLast, memory); - - case _UT('/'): - return URI_FUNC(ParsePartHelperTwo)(state, first + 1, afterLast, memory); - - default: - return first; - } +static URI_INLINE const URI_CHAR * URI_FUNC(ParseHierPart)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + if (first >= afterLast) { + return afterLast; + } + + switch (*first) { + case URI_SET_PCHAR(_UT): + return URI_FUNC(ParsePathRootless)(state, first, afterLast, memory); + + case _UT('/'): + return URI_FUNC(ParsePartHelperTwo)(state, first + 1, afterLast, memory); + + default: + return first; + } } - - /* * [ipFutLoop]->[subDelims][ipFutStopGo] * [ipFutLoop]->[unreserved][ipFutStopGo] * [ipFutLoop]-><:>[ipFutStopGo] - */ -static const URI_CHAR * URI_FUNC(ParseIpFutLoop)(URI_TYPE(ParserState) * state, - const URI_CHAR * first, const URI_CHAR * afterLast, - UriMemoryManager * memory) { - if (first >= afterLast) { - URI_FUNC(StopSyntax)(state, afterLast, memory); - return NULL; - } - - switch (*first) { - case _UT('!'): - case _UT('$'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('-'): - case _UT('*'): - case _UT(','): - case _UT('.'): - case _UT(':'): - case _UT(';'): - case _UT('\''): - case _UT('_'): - case _UT('~'): - case _UT('+'): - case _UT('='): - case URI_SET_DIGIT: - case URI_SET_ALPHA: - return URI_FUNC(ParseIpFutStopGo)(state, first + 1, afterLast, memory); - - default: - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; - } -} - - - -/* + * * [ipFutStopGo]->[ipFutLoop] * [ipFutStopGo]-> */ -static const URI_CHAR * URI_FUNC(ParseIpFutStopGo)( - URI_TYPE(ParserState) * state, - const URI_CHAR * first, const URI_CHAR * afterLast, - UriMemoryManager * memory) { - if (first >= afterLast) { - return afterLast; - } - - switch (*first) { - case _UT('!'): - case _UT('$'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('-'): - case _UT('*'): - case _UT(','): - case _UT('.'): - case _UT(':'): - case _UT(';'): - case _UT('\''): - case _UT('_'): - case _UT('~'): - case _UT('+'): - case _UT('='): - case URI_SET_DIGIT: - case URI_SET_ALPHA: - return URI_FUNC(ParseIpFutLoop)(state, first, afterLast, memory); - - default: - return first; - } +static const URI_CHAR * URI_FUNC(ParseIpFutLoop)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + const URI_CHAR * const originalFirst = first; + + while (first < afterLast) { + switch (*first) { + case _UT(':'): + case URI_SET_SUB_DELIMS(_UT): + case URI_SET_UNRESERVED(_UT): + first += 1; + break; + + default: + goto done_looping; + break; + } + } + +done_looping: + if (first == originalFirst) { + URI_FUNC(StopSyntax)(state, first, memory); + return NULL; + } + + return first; } - - /* * [ipFuture]->[HEXDIG][hexZero]<.>[ipFutLoop] */ static const URI_CHAR * URI_FUNC(ParseIpFuture)(URI_TYPE(ParserState) * state, - const URI_CHAR * first, const URI_CHAR * afterLast, - UriMemoryManager * memory) { - if (first >= afterLast) { - URI_FUNC(StopSyntax)(state, afterLast, memory); - return NULL; - } - - /* - First character has already been - checked before entering this rule. - - switch (*first) { - case _UT('v'): - case _UT('V'): - */ - if (first + 1 >= afterLast) { - URI_FUNC(StopSyntax)(state, afterLast, memory); - return NULL; - } - - switch (first[1]) { - case URI_SET_HEXDIG: - { - const URI_CHAR * afterIpFutLoop; - const URI_CHAR * const afterHexZero - = URI_FUNC(ParseHexZero)(state, first + 2, afterLast); - if (afterHexZero == NULL) { - return NULL; - } - if (afterHexZero >= afterLast) { - URI_FUNC(StopSyntax)(state, afterLast, memory); - return NULL; - } - if (*afterHexZero != _UT('.')) { - URI_FUNC(StopSyntax)(state, afterHexZero, memory); - return NULL; - } - state->uri->hostText.first = first; /* HOST BEGIN */ - state->uri->hostData.ipFuture.first = first; /* IPFUTURE BEGIN */ - afterIpFutLoop = URI_FUNC(ParseIpFutLoop)(state, afterHexZero + 1, afterLast, memory); - if (afterIpFutLoop == NULL) { - return NULL; - } - state->uri->hostText.afterLast = afterIpFutLoop; /* HOST END */ - state->uri->hostData.ipFuture.afterLast = afterIpFutLoop; /* IPFUTURE END */ - return afterIpFutLoop; - } - - default: - URI_FUNC(StopSyntax)(state, first + 1, memory); - return NULL; - } - - /* - default: - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; - } - */ + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + if (first >= afterLast) { + URI_FUNC(StopSyntax)(state, afterLast, memory); + return NULL; + } + + /* + First character has already been + checked before entering this rule. + + switch (*first) { + case _UT('v'): + case _UT('V'): + */ + if (afterLast - first < 2) { + URI_FUNC(StopSyntax)(state, afterLast, memory); + return NULL; + } + + switch (first[1]) { + case URI_SET_HEXDIG(_UT): { + const URI_CHAR * afterIpFutLoop; + const URI_CHAR * const afterHexZero = + URI_FUNC(ParseHexZero)(first + 2, afterLast); + if (afterHexZero == NULL) { + return NULL; + } + if (afterHexZero >= afterLast) { + URI_FUNC(StopSyntax)(state, afterLast, memory); + return NULL; + } + if (*afterHexZero != _UT('.')) { + URI_FUNC(StopSyntax)(state, afterHexZero, memory); + return NULL; + } + state->uri->hostText.first = first; /* HOST BEGIN */ + state->uri->hostData.ipFuture.first = first; /* IPFUTURE BEGIN */ + afterIpFutLoop = + URI_FUNC(ParseIpFutLoop)(state, afterHexZero + 1, afterLast, memory); + if (afterIpFutLoop == NULL) { + return NULL; + } + state->uri->hostText.afterLast = afterIpFutLoop; /* HOST END */ + state->uri->hostData.ipFuture.afterLast = afterIpFutLoop; /* IPFUTURE END */ + return afterIpFutLoop; + } + + default: + URI_FUNC(StopSyntax)(state, first + 1, memory); + return NULL; + } + + /* + default: + URI_FUNC(StopSyntax)(state, first, memory); + return NULL; + } + */ } - - /* * [ipLit2]->[ipFuture]<]> * [ipLit2]->[IPv6address2] */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParseIpLit2)( - URI_TYPE(ParserState) * state, const URI_CHAR * first, - const URI_CHAR * afterLast, UriMemoryManager * memory) { - if (first >= afterLast) { - URI_FUNC(StopSyntax)(state, afterLast, memory); - return NULL; - } - - switch (*first) { - /* The leading "v" of IPvFuture is case-insensitive. */ - case _UT('v'): - case _UT('V'): - { - const URI_CHAR * const afterIpFuture - = URI_FUNC(ParseIpFuture)(state, first, afterLast, memory); - if (afterIpFuture == NULL) { - return NULL; - } - if (afterIpFuture >= afterLast) { - URI_FUNC(StopSyntax)(state, afterLast, memory); - return NULL; - } - if (*afterIpFuture != _UT(']')) { - URI_FUNC(StopSyntax)(state, afterIpFuture, memory); - return NULL; - } - return afterIpFuture + 1; - } - - case _UT(':'): - case _UT(']'): - case URI_SET_HEXDIG: - state->uri->hostData.ip6 = memory->malloc(memory, 1 * sizeof(UriIp6)); /* Freed when stopping on parse error */ - if (state->uri->hostData.ip6 == NULL) { - URI_FUNC(StopMalloc)(state, memory); - return NULL; - } - return URI_FUNC(ParseIPv6address2)(state, first, afterLast, memory); - - default: - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; - } +static URI_INLINE const URI_CHAR * URI_FUNC(ParseIpLit2)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + if (first >= afterLast) { + URI_FUNC(StopSyntax)(state, afterLast, memory); + return NULL; + } + + switch (*first) { + /* The leading "v" of IPvFuture is case-insensitive. */ + case _UT('v'): + case _UT('V'): { + const URI_CHAR * const afterIpFuture = + URI_FUNC(ParseIpFuture)(state, first, afterLast, memory); + if (afterIpFuture == NULL) { + return NULL; + } + if (afterIpFuture >= afterLast) { + URI_FUNC(StopSyntax)(state, afterLast, memory); + return NULL; + } + if (*afterIpFuture != _UT(']')) { + URI_FUNC(StopSyntax)(state, afterIpFuture, memory); + return NULL; + } + return afterIpFuture + 1; + } + + case _UT(':'): + case _UT(']'): + case URI_SET_HEXDIG(_UT): + state->uri->hostData.ip6 = memory->malloc( + memory, 1 * sizeof(UriIp6)); /* Freed when stopping on parse error */ + if (state->uri->hostData.ip6 == NULL) { + URI_FUNC(StopMalloc)(state, memory); + return NULL; + } + return URI_FUNC(ParseIPv6address2)(state, first, afterLast, memory); + + default: + URI_FUNC(StopSyntax)(state, first, memory); + return NULL; + } } - - /* * [IPv6address2]->..<]> */ -static const URI_CHAR * URI_FUNC(ParseIPv6address2)( - URI_TYPE(ParserState) * state, - const URI_CHAR * first, const URI_CHAR * afterLast, - UriMemoryManager * memory) { - int zipperEver = 0; - int quadsDone = 0; - int digitCount = 0; - unsigned char digitHistory[4]; - int ip4OctetsDone = 0; - - unsigned char quadsAfterZipper[14]; - int quadsAfterZipperCount = 0; - - - for (;;) { - if (first >= afterLast) { - URI_FUNC(StopSyntax)(state, afterLast, memory); - return NULL; - } - - /* Inside IPv4 part? */ - if (ip4OctetsDone > 0) { - /* Eat rest of IPv4 address */ - for (;;) { - switch (*first) { - case URI_SET_DIGIT: - if (digitCount == 4) { - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; - } - digitHistory[digitCount++] = (unsigned char)(9 + *first - _UT('9')); - break; - - case _UT('.'): - if ((ip4OctetsDone == 4) /* NOTE! */ - || (digitCount == 0) - || (digitCount == 4)) { - /* Invalid digit or octet count */ - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; - } else if ((digitCount > 1) - && (digitHistory[0] == 0)) { - /* Leading zero */ - URI_FUNC(StopSyntax)(state, first - digitCount, memory); - return NULL; - } else if ((digitCount == 3) - && (100 * digitHistory[0] - + 10 * digitHistory[1] - + digitHistory[2] > 255)) { - /* Octet value too large */ - if (digitHistory[0] > 2) { - URI_FUNC(StopSyntax)(state, first - 3, memory); - } else if (digitHistory[1] > 5) { - URI_FUNC(StopSyntax)(state, first - 2, memory); - } else { - URI_FUNC(StopSyntax)(state, first - 1, memory); - } - return NULL; - } - - /* Copy IPv4 octet */ - state->uri->hostData.ip6->data[16 - 4 + ip4OctetsDone] = uriGetOctetValue(digitHistory, digitCount); - digitCount = 0; - ip4OctetsDone++; - break; - - case _UT(']'): - if ((ip4OctetsDone != 3) /* NOTE! */ - || (digitCount == 0) - || (digitCount == 4)) { - /* Invalid digit or octet count */ - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; - } else if ((digitCount > 1) - && (digitHistory[0] == 0)) { - /* Leading zero */ - URI_FUNC(StopSyntax)(state, first - digitCount, memory); - return NULL; - } else if ((digitCount == 3) - && (100 * digitHistory[0] - + 10 * digitHistory[1] - + digitHistory[2] > 255)) { - /* Octet value too large */ - if (digitHistory[0] > 2) { - URI_FUNC(StopSyntax)(state, first - 3, memory); - } else if (digitHistory[1] > 5) { - URI_FUNC(StopSyntax)(state, first - 2, memory); - } else { - URI_FUNC(StopSyntax)(state, first - 1, memory); - } - return NULL; - } - - state->uri->hostText.afterLast = first; /* HOST END */ - - /* Copy missing quads right before IPv4 */ - memcpy(state->uri->hostData.ip6->data + 16 - 4 - 2 * quadsAfterZipperCount, - quadsAfterZipper, 2 * quadsAfterZipperCount); - - /* Copy last IPv4 octet */ - state->uri->hostData.ip6->data[16 - 4 + 3] = uriGetOctetValue(digitHistory, digitCount); - - return first + 1; - - default: - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; - } - first++; - - if (first >= afterLast) { - URI_FUNC(StopSyntax)(state, afterLast, memory); - return NULL; - } - } - } else { - /* Eat while no dot in sight */ - int letterAmong = 0; - int walking = 1; - do { - switch (*first) { - case URI_SET_HEX_LETTER_LOWER: - letterAmong = 1; - if (digitCount == 4) { - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; - } - digitHistory[digitCount] = (unsigned char)(15 + *first - _UT('f')); - digitCount++; - break; - - case URI_SET_HEX_LETTER_UPPER: - letterAmong = 1; - if (digitCount == 4) { - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; - } - digitHistory[digitCount] = (unsigned char)(15 + *first - _UT('F')); - digitCount++; - break; - - case URI_SET_DIGIT: - if (digitCount == 4) { - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; - } - digitHistory[digitCount] = (unsigned char)(9 + *first - _UT('9')); - digitCount++; - break; - - case _UT(':'): - { - int setZipper = 0; - - if (digitCount > 0) { - if (zipperEver) { - uriWriteQuadToDoubleByte(digitHistory, digitCount, quadsAfterZipper + 2 * quadsAfterZipperCount); - quadsAfterZipperCount++; - } else { - uriWriteQuadToDoubleByte(digitHistory, digitCount, state->uri->hostData.ip6->data + 2 * quadsDone); - } - quadsDone++; - digitCount = 0; - } - letterAmong = 0; - - /* Too many quads? */ - if (quadsDone >= 8 - zipperEver) { - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; - } - - /* "::"? */ - if (first + 1 >= afterLast) { - URI_FUNC(StopSyntax)(state, afterLast, memory); - return NULL; - } - if (first[1] == _UT(':')) { - const int resetOffset = 2 * (quadsDone + (digitCount > 0)); - - first++; - if (zipperEver) { - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; /* "::.+::" */ - } - - /* Zero everything after zipper */ - memset(state->uri->hostData.ip6->data + resetOffset, 0, 16 - resetOffset); - setZipper = 1; - - /* ":::+"? */ - if (first + 1 >= afterLast) { - URI_FUNC(StopSyntax)(state, afterLast, memory); - return NULL; /* No ']' yet */ - } - if (first[1] == _UT(':')) { - URI_FUNC(StopSyntax)(state, first + 1, memory); - return NULL; /* ":::+ "*/ - } - } else if (quadsDone == 0 || first[1] == _UT(']')) { - /* Single leading or trailing ":" */ - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; - } - - if (setZipper) { - zipperEver = 1; - } - } - break; - - case _UT('.'): - if ((quadsDone + zipperEver > 6) /* NOTE */ - || (!zipperEver && (quadsDone < 6)) - || letterAmong - || (digitCount == 0) - || (digitCount == 4)) { - /* Invalid octet before */ - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; - } else if ((digitCount > 1) - && (digitHistory[0] == 0)) { - /* Leading zero */ - URI_FUNC(StopSyntax)(state, first - digitCount, memory); - return NULL; - } else if ((digitCount == 3) - && (100 * digitHistory[0] - + 10 * digitHistory[1] - + digitHistory[2] > 255)) { - /* Octet value too large */ - if (digitHistory[0] > 2) { - URI_FUNC(StopSyntax)(state, first - 3, memory); - } else if (digitHistory[1] > 5) { - URI_FUNC(StopSyntax)(state, first - 2, memory); - } else { - URI_FUNC(StopSyntax)(state, first - 1, memory); - } - return NULL; - } - - /* Copy first IPv4 octet */ - state->uri->hostData.ip6->data[16 - 4] = uriGetOctetValue(digitHistory, digitCount); - digitCount = 0; - - /* Switch over to IPv4 loop */ - ip4OctetsDone = 1; - walking = 0; - break; - - case _UT(']'): - /* Too little quads? */ - if (!zipperEver && !((quadsDone == 7) && (digitCount > 0))) { - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; - } - - if (digitCount > 0) { - if (zipperEver) { - /* Too many quads? */ - if (quadsDone >= 7) { - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; - } - uriWriteQuadToDoubleByte(digitHistory, digitCount, quadsAfterZipper + 2 * quadsAfterZipperCount); - quadsAfterZipperCount++; - } else { - uriWriteQuadToDoubleByte(digitHistory, digitCount, state->uri->hostData.ip6->data + 2 * quadsDone); - } - /* - quadsDone++; - digitCount = 0; - */ - } - - /* Copy missing quads to the end */ - memcpy(state->uri->hostData.ip6->data + 16 - 2 * quadsAfterZipperCount, - quadsAfterZipper, 2 * quadsAfterZipperCount); - - state->uri->hostText.afterLast = first; /* HOST END */ - return first + 1; /* Fine */ - - default: - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; - } - first++; - - if (first >= afterLast) { - URI_FUNC(StopSyntax)(state, afterLast, memory); - return NULL; /* No ']' yet */ - } - } while (walking); - } - } +static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + int zipperEver = 0; + int quadsDone = 0; + int digitCount = 0; + unsigned char digitHistory[4]; + int ip4OctetsDone = 0; + + unsigned char quadsAfterZipper[14]; + int quadsAfterZipperCount = 0; + + for (;;) { + if (first >= afterLast) { + URI_FUNC(StopSyntax)(state, afterLast, memory); + return NULL; + } + + /* Inside IPv4 part? */ + if (ip4OctetsDone > 0) { + /* Eat rest of IPv4 address */ + for (;;) { + switch (*first) { + case URI_SET_DIGIT(_UT): + if (digitCount == 4) { + URI_FUNC(StopSyntax)(state, first, memory); + return NULL; + } + digitHistory[digitCount++] = (unsigned char)(9 + *first - _UT('9')); + break; + + case _UT('.'): + if ((ip4OctetsDone == 4) /* NOTE! */ + || (digitCount == 0) || (digitCount == 4)) { + /* Invalid digit or octet count */ + URI_FUNC(StopSyntax)(state, first, memory); + return NULL; + } else if ((digitCount > 1) && (digitHistory[0] == 0)) { + /* Leading zero */ + URI_FUNC(StopSyntax)(state, first - digitCount, memory); + return NULL; + } else if ((digitCount == 3) + && (100 * digitHistory[0] + 10 * digitHistory[1] + + digitHistory[2] + > 255)) { + /* Octet value too large */ + if (digitHistory[0] > 2) { + URI_FUNC(StopSyntax)(state, first - 3, memory); + } else if (digitHistory[1] > 5) { + URI_FUNC(StopSyntax)(state, first - 2, memory); + } else { + URI_FUNC(StopSyntax)(state, first - 1, memory); + } + return NULL; + } + + /* Copy IPv4 octet */ + state->uri->hostData.ip6->data[16 - 4 + ip4OctetsDone] = + uriGetOctetValue(digitHistory, digitCount); + digitCount = 0; + ip4OctetsDone++; + break; + + case _UT(']'): + if ((ip4OctetsDone != 3) /* NOTE! */ + || (digitCount == 0) || (digitCount == 4)) { + /* Invalid digit or octet count */ + URI_FUNC(StopSyntax)(state, first, memory); + return NULL; + } else if ((digitCount > 1) && (digitHistory[0] == 0)) { + /* Leading zero */ + URI_FUNC(StopSyntax)(state, first - digitCount, memory); + return NULL; + } else if ((digitCount == 3) + && (100 * digitHistory[0] + 10 * digitHistory[1] + + digitHistory[2] + > 255)) { + /* Octet value too large */ + if (digitHistory[0] > 2) { + URI_FUNC(StopSyntax)(state, first - 3, memory); + } else if (digitHistory[1] > 5) { + URI_FUNC(StopSyntax)(state, first - 2, memory); + } else { + URI_FUNC(StopSyntax)(state, first - 1, memory); + } + return NULL; + } + + state->uri->hostText.afterLast = first; /* HOST END */ + + /* Copy missing quads right before IPv4 */ + memcpy(state->uri->hostData.ip6->data + 16 - 4 + - 2 * quadsAfterZipperCount, + quadsAfterZipper, 2 * quadsAfterZipperCount); + + /* Copy last IPv4 octet */ + state->uri->hostData.ip6->data[16 - 4 + 3] = + uriGetOctetValue(digitHistory, digitCount); + + return first + 1; + + default: + URI_FUNC(StopSyntax)(state, first, memory); + return NULL; + } + first++; + + if (first >= afterLast) { + URI_FUNC(StopSyntax)(state, afterLast, memory); + return NULL; + } + } + } else { + /* Eat while no dot in sight */ + int letterAmong = 0; + int walking = 1; + do { + switch (*first) { + case URI_SET_HEX_LETTER_LOWER(_UT): + letterAmong = 1; + if (digitCount == 4) { + URI_FUNC(StopSyntax)(state, first, memory); + return NULL; + } + digitHistory[digitCount] = (unsigned char)(15 + *first - _UT('f')); + digitCount++; + break; + + case URI_SET_HEX_LETTER_UPPER(_UT): + letterAmong = 1; + if (digitCount == 4) { + URI_FUNC(StopSyntax)(state, first, memory); + return NULL; + } + digitHistory[digitCount] = (unsigned char)(15 + *first - _UT('F')); + digitCount++; + break; + + case URI_SET_DIGIT(_UT): + if (digitCount == 4) { + URI_FUNC(StopSyntax)(state, first, memory); + return NULL; + } + digitHistory[digitCount] = (unsigned char)(9 + *first - _UT('9')); + digitCount++; + break; + + case _UT(':'): { + int setZipper = 0; + + if (digitCount > 0) { + if (zipperEver) { + uriWriteQuadToDoubleByte(digitHistory, digitCount, + quadsAfterZipper + + 2 * quadsAfterZipperCount); + quadsAfterZipperCount++; + } else { + uriWriteQuadToDoubleByte(digitHistory, digitCount, + state->uri->hostData.ip6->data + + 2 * quadsDone); + } + quadsDone++; + digitCount = 0; + } + letterAmong = 0; + + /* Too many quads? */ + if (quadsDone >= 8 - zipperEver) { + URI_FUNC(StopSyntax)(state, first, memory); + return NULL; + } + + /* "::"? */ + if (afterLast - first < 2) { + URI_FUNC(StopSyntax)(state, afterLast, memory); + return NULL; + } + if (first[1] == _UT(':')) { + const int resetOffset = 2 * (quadsDone + (digitCount > 0)); + + first++; + if (zipperEver) { + URI_FUNC(StopSyntax)(state, first, memory); + return NULL; /* "::.+::" */ + } + + /* Zero everything after zipper */ + memset(state->uri->hostData.ip6->data + resetOffset, 0, + 16 - resetOffset); + setZipper = 1; + + /* ":::+"? */ + if (afterLast - first < 2) { + URI_FUNC(StopSyntax)(state, afterLast, memory); + return NULL; /* No ']' yet */ + } + if (first[1] == _UT(':')) { + URI_FUNC(StopSyntax)(state, first + 1, memory); + return NULL; /* ":::+ "*/ + } + } else if (quadsDone == 0 || first[1] == _UT(']')) { + /* Single leading or trailing ":" */ + URI_FUNC(StopSyntax)(state, first, memory); + return NULL; + } + + if (setZipper) { + zipperEver = 1; + } + } break; + + case _UT('.'): + if ((quadsDone + zipperEver > 6) /* NOTE */ + || (!zipperEver && (quadsDone < 6)) || letterAmong + || (digitCount == 0) || (digitCount == 4)) { + /* Invalid octet before */ + URI_FUNC(StopSyntax)(state, first, memory); + return NULL; + } else if ((digitCount > 1) && (digitHistory[0] == 0)) { + /* Leading zero */ + URI_FUNC(StopSyntax)(state, first - digitCount, memory); + return NULL; + } else if ((digitCount == 3) + && (100 * digitHistory[0] + 10 * digitHistory[1] + + digitHistory[2] + > 255)) { + /* Octet value too large */ + if (digitHistory[0] > 2) { + URI_FUNC(StopSyntax)(state, first - 3, memory); + } else if (digitHistory[1] > 5) { + URI_FUNC(StopSyntax)(state, first - 2, memory); + } else { + URI_FUNC(StopSyntax)(state, first - 1, memory); + } + return NULL; + } + + /* Copy first IPv4 octet */ + state->uri->hostData.ip6->data[16 - 4] = + uriGetOctetValue(digitHistory, digitCount); + digitCount = 0; + + /* Switch over to IPv4 loop */ + ip4OctetsDone = 1; + walking = 0; + break; + + case _UT(']'): + /* Too little quads? */ + if (!zipperEver && !((quadsDone == 7) && (digitCount > 0))) { + URI_FUNC(StopSyntax)(state, first, memory); + return NULL; + } + + if (digitCount > 0) { + if (zipperEver) { + /* Too many quads? */ + if (quadsDone >= 7) { + URI_FUNC(StopSyntax)(state, first, memory); + return NULL; + } + uriWriteQuadToDoubleByte(digitHistory, digitCount, + quadsAfterZipper + + 2 * quadsAfterZipperCount); + quadsAfterZipperCount++; + } else { + uriWriteQuadToDoubleByte(digitHistory, digitCount, + state->uri->hostData.ip6->data + + 2 * quadsDone); + } + /* + quadsDone++; + digitCount = 0; + */ + } + + /* Copy missing quads to the end */ + memcpy(state->uri->hostData.ip6->data + 16 + - 2 * quadsAfterZipperCount, + quadsAfterZipper, 2 * quadsAfterZipperCount); + + state->uri->hostText.afterLast = first; /* HOST END */ + return first + 1; /* Fine */ + + default: + URI_FUNC(StopSyntax)(state, first, memory); + return NULL; + } + first++; + + if (first >= afterLast) { + URI_FUNC(StopSyntax)(state, afterLast, memory); + return NULL; /* No ']' yet */ + } + } while (walking); + } + } } - - /* * [mustBeSegmentNzNc]->[pctEncoded][mustBeSegmentNzNc] * [mustBeSegmentNzNc]->[subDelims][mustBeSegmentNzNc] @@ -888,346 +806,277 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)( * [mustBeSegmentNzNc]->[segment][zeroMoreSlashSegs][uriTail] * [mustBeSegmentNzNc]-><@>[mustBeSegmentNzNc] */ -static const URI_CHAR * URI_FUNC(ParseMustBeSegmentNzNc)( - URI_TYPE(ParserState) * state, const URI_CHAR * first, - const URI_CHAR * afterLast, UriMemoryManager * memory) { - if (first >= afterLast) { - if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first, memory)) { /* SEGMENT BOTH */ - URI_FUNC(StopMalloc)(state, memory); - return NULL; - } - state->uri->scheme.first = NULL; /* Not a scheme, reset */ - return afterLast; - } - - switch (*first) { - case _UT('%'): - { - const URI_CHAR * const afterPctEncoded - = URI_FUNC(ParsePctEncoded)(state, first, afterLast, memory); - if (afterPctEncoded == NULL) { - return NULL; - } - return URI_FUNC(ParseMustBeSegmentNzNc)(state, afterPctEncoded, afterLast, memory); - } - - case _UT('@'): - case _UT('!'): - case _UT('$'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('*'): - case _UT(','): - case _UT(';'): - case _UT('\''): - case _UT('+'): - case _UT('='): - case _UT('-'): - case _UT('.'): - case _UT('_'): - case _UT('~'): - case URI_SET_DIGIT: - case URI_SET_ALPHA: - return URI_FUNC(ParseMustBeSegmentNzNc)(state, first + 1, afterLast, memory); - - case _UT('/'): - { - const URI_CHAR * afterZeroMoreSlashSegs; - const URI_CHAR * afterSegment; - if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first, memory)) { /* SEGMENT BOTH */ - URI_FUNC(StopMalloc)(state, memory); - return NULL; - } - state->uri->scheme.first = NULL; /* Not a scheme, reset */ - afterSegment = URI_FUNC(ParseSegment)(state, first + 1, afterLast, memory); - if (afterSegment == NULL) { - return NULL; - } - if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment, memory)) { /* SEGMENT BOTH */ - URI_FUNC(StopMalloc)(state, memory); - return NULL; - } - afterZeroMoreSlashSegs - = URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegment, afterLast, memory); - if (afterZeroMoreSlashSegs == NULL) { - return NULL; - } - return URI_FUNC(ParseUriTail)(state, afterZeroMoreSlashSegs, afterLast, memory); - } - - default: - if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first, memory)) { /* SEGMENT BOTH */ - URI_FUNC(StopMalloc)(state, memory); - return NULL; - } - state->uri->scheme.first = NULL; /* Not a scheme, reset */ - return URI_FUNC(ParseUriTail)(state, first, afterLast, memory); - } +static const URI_CHAR * URI_FUNC(ParseMustBeSegmentNzNc)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { +tail_call: + if (first >= afterLast) { + if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first, + memory)) { /* SEGMENT BOTH */ + URI_FUNC(StopMalloc)(state, memory); + return NULL; + } + state->uri->scheme.first = NULL; /* Not a scheme, reset */ + return afterLast; + } + + switch (*first) { + case _UT('%'): { + const URI_CHAR * const afterPctEncoded = + URI_FUNC(ParsePctEncoded)(state, first, afterLast, memory); + if (afterPctEncoded == NULL) { + return NULL; + } + first = afterPctEncoded; + goto tail_call; + } + + case _UT('@'): + case URI_SET_SUB_DELIMS(_UT): + case URI_SET_UNRESERVED(_UT): + first += 1; + goto tail_call; + + case _UT('/'): { + const URI_CHAR * afterZeroMoreSlashSegs; + const URI_CHAR * afterSegment; + if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first, + memory)) { /* SEGMENT BOTH */ + URI_FUNC(StopMalloc)(state, memory); + return NULL; + } + state->uri->scheme.first = NULL; /* Not a scheme, reset */ + afterSegment = URI_FUNC(ParseSegment)(state, first + 1, afterLast, memory); + if (afterSegment == NULL) { + return NULL; + } + if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment, + memory)) { /* SEGMENT BOTH */ + URI_FUNC(StopMalloc)(state, memory); + return NULL; + } + afterZeroMoreSlashSegs = + URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegment, afterLast, memory); + if (afterZeroMoreSlashSegs == NULL) { + return NULL; + } + return URI_FUNC(ParseUriTail)(state, afterZeroMoreSlashSegs, afterLast, memory); + } + + default: + if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first, + memory)) { /* SEGMENT BOTH */ + URI_FUNC(StopMalloc)(state, memory); + return NULL; + } + state->uri->scheme.first = NULL; /* Not a scheme, reset */ + return URI_FUNC(ParseUriTail)(state, first, afterLast, memory); + } } - - /* * [ownHost]-><[>[ipLit2][authorityTwo] * [ownHost]->[ownHost2] // can take */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParseOwnHost)( - URI_TYPE(ParserState) * state, const URI_CHAR * first, - const URI_CHAR * afterLast, UriMemoryManager * memory) { - if (first >= afterLast) { - state->uri->hostText.afterLast = afterLast; /* HOST END */ - return afterLast; - } - - switch (*first) { - case _UT('['): - { - const URI_CHAR * const afterIpLit2 - = URI_FUNC(ParseIpLit2)(state, first + 1, afterLast, memory); - if (afterIpLit2 == NULL) { - return NULL; - } - state->uri->hostText.first = first + 1; /* HOST BEGIN */ - return URI_FUNC(ParseAuthorityTwo)(state, afterIpLit2, afterLast); - } - - default: - return URI_FUNC(ParseOwnHost2)(state, first, afterLast, memory); - } +static URI_INLINE const URI_CHAR * URI_FUNC(ParseOwnHost)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + if (first >= afterLast) { + state->uri->hostText.afterLast = afterLast; /* HOST END */ + return afterLast; + } + + switch (*first) { + case _UT('['): { + const URI_CHAR * const afterIpLit2 = + URI_FUNC(ParseIpLit2)(state, first + 1, afterLast, memory); + if (afterIpLit2 == NULL) { + return NULL; + } + state->uri->hostText.first = first + 1; /* HOST BEGIN */ + return URI_FUNC(ParseAuthorityTwo)(state, afterIpLit2, afterLast); + } + + default: + return URI_FUNC(ParseOwnHost2)(state, first, afterLast, memory); + } } - - -static URI_INLINE UriBool URI_FUNC(OnExitOwnHost2)( - URI_TYPE(ParserState) * state, const URI_CHAR * first, - UriMemoryManager * memory) { - state->uri->hostText.afterLast = first; /* HOST END */ - - /* Valid IPv4 or just a regname? */ - state->uri->hostData.ip4 = memory->malloc(memory, 1 * sizeof(UriIp4)); /* Freed when stopping on parse error */ - if (state->uri->hostData.ip4 == NULL) { - return URI_FALSE; /* Raises malloc error */ - } - if (URI_FUNC(ParseIpFourAddress)(state->uri->hostData.ip4->data, - state->uri->hostText.first, state->uri->hostText.afterLast)) { - /* Not IPv4 */ - memory->free(memory, state->uri->hostData.ip4); - state->uri->hostData.ip4 = NULL; - } - return URI_TRUE; /* Success */ +static URI_INLINE UriBool URI_FUNC(OnExitOwnHost2)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + UriMemoryManager * memory) { + state->uri->hostText.afterLast = first; /* HOST END */ + + /* Valid IPv4 or just a regname? */ + state->uri->hostData.ip4 = memory->malloc( + memory, 1 * sizeof(UriIp4)); /* Freed when stopping on parse error */ + if (state->uri->hostData.ip4 == NULL) { + return URI_FALSE; /* Raises malloc error */ + } + if (URI_FUNC(ParseIpFourAddress)(state->uri->hostData.ip4->data, + state->uri->hostText.first, + state->uri->hostText.afterLast)) { + /* Not IPv4 */ + memory->free(memory, state->uri->hostData.ip4); + state->uri->hostData.ip4 = NULL; + } + return URI_TRUE; /* Success */ } - - /* * [ownHost2]->[authorityTwo] // can take * [ownHost2]->[pctSubUnres][ownHost2] */ -static const URI_CHAR * URI_FUNC(ParseOwnHost2)( - URI_TYPE(ParserState) * state, const URI_CHAR * first, - const URI_CHAR * afterLast, UriMemoryManager * memory) { - if (first >= afterLast) { - if (!URI_FUNC(OnExitOwnHost2)(state, first, memory)) { - URI_FUNC(StopMalloc)(state, memory); - return NULL; - } - return afterLast; - } - - switch (*first) { - case _UT('!'): - case _UT('$'): - case _UT('%'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('-'): - case _UT('*'): - case _UT(','): - case _UT('.'): - case _UT(';'): - case _UT('\''): - case _UT('_'): - case _UT('~'): - case _UT('+'): - case _UT('='): - case URI_SET_DIGIT: - case URI_SET_ALPHA: - { - const URI_CHAR * const afterPctSubUnres - = URI_FUNC(ParsePctSubUnres)(state, first, afterLast, memory); - if (afterPctSubUnres == NULL) { - return NULL; - } - return URI_FUNC(ParseOwnHost2)(state, afterPctSubUnres, afterLast, memory); - } - - default: - if (!URI_FUNC(OnExitOwnHost2)(state, first, memory)) { - URI_FUNC(StopMalloc)(state, memory); - return NULL; - } - return URI_FUNC(ParseAuthorityTwo)(state, first, afterLast); - } +static const URI_CHAR * URI_FUNC(ParseOwnHost2)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { +tail_call: + if (first >= afterLast) { + if (!URI_FUNC(OnExitOwnHost2)(state, first, memory)) { + URI_FUNC(StopMalloc)(state, memory); + return NULL; + } + return afterLast; + } + + switch (*first) { + case _UT('%'): + case URI_SET_SUB_DELIMS(_UT): + case URI_SET_UNRESERVED(_UT): { + const URI_CHAR * const afterPctSubUnres = + URI_FUNC(ParsePctSubUnres)(state, first, afterLast, memory); + if (afterPctSubUnres == NULL) { + return NULL; + } + first = afterPctSubUnres; + goto tail_call; + } + + default: + if (!URI_FUNC(OnExitOwnHost2)(state, first, memory)) { + URI_FUNC(StopMalloc)(state, memory); + return NULL; + } + return URI_FUNC(ParseAuthorityTwo)(state, first, afterLast); + } } - - -static URI_INLINE UriBool URI_FUNC(OnExitOwnHostUserInfo)( - URI_TYPE(ParserState) * state, const URI_CHAR * first, - UriMemoryManager * memory) { - state->uri->hostText.first = state->uri->userInfo.first; /* Host instead of userInfo, update */ - state->uri->userInfo.first = NULL; /* Not a userInfo, reset */ - state->uri->hostText.afterLast = first; /* HOST END */ - - /* Valid IPv4 or just a regname? */ - state->uri->hostData.ip4 = memory->malloc(memory, 1 * sizeof(UriIp4)); /* Freed when stopping on parse error */ - if (state->uri->hostData.ip4 == NULL) { - return URI_FALSE; /* Raises malloc error */ - } - if (URI_FUNC(ParseIpFourAddress)(state->uri->hostData.ip4->data, - state->uri->hostText.first, state->uri->hostText.afterLast)) { - /* Not IPv4 */ - memory->free(memory, state->uri->hostData.ip4); - state->uri->hostData.ip4 = NULL; - } - return URI_TRUE; /* Success */ +static URI_INLINE UriBool URI_FUNC(OnExitOwnHostUserInfo)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + UriMemoryManager * memory) { + state->uri->hostText.first = + state->uri->userInfo.first; /* Host instead of userInfo, update */ + state->uri->userInfo.first = NULL; /* Not a userInfo, reset */ + state->uri->hostText.afterLast = first; /* HOST END */ + + /* Valid IPv4 or just a regname? */ + state->uri->hostData.ip4 = memory->malloc( + memory, 1 * sizeof(UriIp4)); /* Freed when stopping on parse error */ + if (state->uri->hostData.ip4 == NULL) { + return URI_FALSE; /* Raises malloc error */ + } + if (URI_FUNC(ParseIpFourAddress)(state->uri->hostData.ip4->data, + state->uri->hostText.first, + state->uri->hostText.afterLast)) { + /* Not IPv4 */ + memory->free(memory, state->uri->hostData.ip4); + state->uri->hostData.ip4 = NULL; + } + return URI_TRUE; /* Success */ } - - -/* - * [ownHostUserInfo]->[ownHostUserInfoNz] - * [ownHostUserInfo]-> - */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParseOwnHostUserInfo)( - URI_TYPE(ParserState) * state, const URI_CHAR * first, - const URI_CHAR * afterLast, UriMemoryManager * memory) { - if (first >= afterLast) { - if (!URI_FUNC(OnExitOwnHostUserInfo)(state, first, memory)) { - URI_FUNC(StopMalloc)(state, memory); - return NULL; - } - return afterLast; - } - - switch (*first) { - case _UT('!'): - case _UT('$'): - case _UT('%'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('-'): - case _UT('*'): - case _UT(','): - case _UT('.'): - case _UT(':'): - case _UT(';'): - case _UT('@'): - case _UT('\''): - case _UT('_'): - case _UT('~'): - case _UT('+'): - case _UT('='): - case URI_SET_DIGIT: - case URI_SET_ALPHA: - return URI_FUNC(ParseOwnHostUserInfoNz)(state, first, afterLast, memory); - - default: - if (!URI_FUNC(OnExitOwnHostUserInfo)(state, first, memory)) { - URI_FUNC(StopMalloc)(state, memory); - return NULL; - } - return first; - } -} - - - /* * [ownHostUserInfoNz]->[pctSubUnres][ownHostUserInfo] * [ownHostUserInfoNz]-><:>[ownPortUserInfo] * [ownHostUserInfoNz]-><@>[ownHost] + * + * [ownHostUserInfo]->[ownHostUserInfoNz] + * [ownHostUserInfo]-> */ -static const URI_CHAR * URI_FUNC(ParseOwnHostUserInfoNz)( - URI_TYPE(ParserState) * state, const URI_CHAR * first, - const URI_CHAR * afterLast, UriMemoryManager * memory) { - if (first >= afterLast) { - URI_FUNC(StopSyntax)(state, afterLast, memory); - return NULL; - } - - switch (*first) { - case _UT('!'): - case _UT('$'): - case _UT('%'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('-'): - case _UT('*'): - case _UT(','): - case _UT('.'): - case _UT(';'): - case _UT('\''): - case _UT('_'): - case _UT('~'): - case _UT('+'): - case _UT('='): - case URI_SET_DIGIT: - case URI_SET_ALPHA: - { - const URI_CHAR * const afterPctSubUnres - = URI_FUNC(ParsePctSubUnres)(state, first, afterLast, memory); - if (afterPctSubUnres == NULL) { - return NULL; - } - return URI_FUNC(ParseOwnHostUserInfo)(state, afterPctSubUnres, afterLast, memory); - } - - case _UT(':'): - state->uri->hostText.afterLast = first; /* HOST END */ - state->uri->portText.first = first + 1; /* PORT BEGIN */ - return URI_FUNC(ParseOwnPortUserInfo)(state, first + 1, afterLast, memory); - - case _UT('@'): - state->uri->userInfo.afterLast = first; /* USERINFO END */ - state->uri->hostText.first = first + 1; /* HOST BEGIN */ - return URI_FUNC(ParseOwnHost)(state, first + 1, afterLast, memory); - - default: - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; - } +static const URI_CHAR * URI_FUNC(ParseOwnHostUserInfoNz)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + const URI_CHAR * const originalFirst = first; + + while (first < afterLast) { + switch (*first) { + case _UT('%'): + case URI_SET_SUB_DELIMS(_UT): + case URI_SET_UNRESERVED(_UT): { + const URI_CHAR * const afterPctSubUnres = + URI_FUNC(ParsePctSubUnres)(state, first, afterLast, memory); + if (afterPctSubUnres == NULL) { + return NULL; + } + first = afterPctSubUnres; + break; + } + + default: + goto done_looping; + break; + } + } + +done_looping: + if (first < afterLast) { + switch (*first) { + case _UT(':'): + state->uri->hostText.afterLast = first; /* HOST END */ + state->uri->portText.first = first + 1; /* PORT BEGIN */ + return URI_FUNC(ParseOwnPortUserInfo)(state, first + 1, afterLast, memory); + + case _UT('@'): + state->uri->userInfo.afterLast = first; /* USERINFO END */ + state->uri->hostText.first = first + 1; /* HOST BEGIN */ + return URI_FUNC(ParseOwnHost)(state, first + 1, afterLast, memory); + + default: + break; + } + } + + if (first == originalFirst) { + URI_FUNC(StopSyntax)(state, afterLast, memory); + return NULL; + } + + if (!URI_FUNC(OnExitOwnHostUserInfo)(state, first, memory)) { + URI_FUNC(StopMalloc)(state, memory); + return NULL; + } + + return first; } - - -static URI_INLINE UriBool URI_FUNC(OnExitOwnPortUserInfo)( - URI_TYPE(ParserState) * state, const URI_CHAR * first, - UriMemoryManager * memory) { - state->uri->hostText.first = state->uri->userInfo.first; /* Host instead of userInfo, update */ - state->uri->userInfo.first = NULL; /* Not a userInfo, reset */ - state->uri->portText.afterLast = first; /* PORT END */ - - /* Valid IPv4 or just a regname? */ - state->uri->hostData.ip4 = memory->malloc(memory, 1 * sizeof(UriIp4)); /* Freed when stopping on parse error */ - if (state->uri->hostData.ip4 == NULL) { - return URI_FALSE; /* Raises malloc error */ - } - if (URI_FUNC(ParseIpFourAddress)(state->uri->hostData.ip4->data, - state->uri->hostText.first, state->uri->hostText.afterLast)) { - /* Not IPv4 */ - memory->free(memory, state->uri->hostData.ip4); - state->uri->hostData.ip4 = NULL; - } - return URI_TRUE; /* Success */ +static URI_INLINE UriBool URI_FUNC(OnExitOwnPortUserInfo)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + UriMemoryManager * memory) { + state->uri->hostText.first = + state->uri->userInfo.first; /* Host instead of userInfo, update */ + state->uri->userInfo.first = NULL; /* Not a userInfo, reset */ + state->uri->portText.afterLast = first; /* PORT END */ + + /* Valid IPv4 or just a regname? */ + state->uri->hostData.ip4 = memory->malloc( + memory, 1 * sizeof(UriIp4)); /* Freed when stopping on parse error */ + if (state->uri->hostData.ip4 == NULL) { + return URI_FALSE; /* Raises malloc error */ + } + if (URI_FUNC(ParseIpFourAddress)(state->uri->hostData.ip4->data, + state->uri->hostText.first, + state->uri->hostText.afterLast)) { + /* Not IPv4 */ + memory->free(memory, state->uri->hostData.ip4); + state->uri->hostData.ip4 = NULL; + } + return URI_TRUE; /* Success */ } - - /* * [ownPortUserInfo]->[ALPHA][ownUserInfo] * [ownPortUserInfo]->[DIGIT][ownPortUserInfo] @@ -1241,281 +1090,229 @@ static URI_INLINE UriBool URI_FUNC(OnExitOwnPortUserInfo)( * [ownPortUserInfo]-><@>[ownHost] * [ownPortUserInfo]-> */ -static const URI_CHAR * URI_FUNC(ParseOwnPortUserInfo)( - URI_TYPE(ParserState) * state, const URI_CHAR * first, - const URI_CHAR * afterLast, UriMemoryManager * memory) { - if (first >= afterLast) { - if (!URI_FUNC(OnExitOwnPortUserInfo)(state, first, memory)) { - URI_FUNC(StopMalloc)(state, memory); - return NULL; - } - return afterLast; - } - - switch (*first) { - /* begin sub-delims */ - case _UT('!'): - case _UT('$'): - case _UT('&'): - case _UT('\''): - case _UT('('): - case _UT(')'): - case _UT('*'): - case _UT('+'): - case _UT(','): - case _UT(';'): - case _UT('='): - /* end sub-delims */ - /* begin unreserved (except alpha and digit) */ - case _UT('-'): - case _UT('.'): - case _UT('_'): - case _UT('~'): - /* end unreserved (except alpha and digit) */ - case _UT(':'): - case URI_SET_ALPHA: - state->uri->hostText.afterLast = NULL; /* Not a host, reset */ - state->uri->portText.first = NULL; /* Not a port, reset */ - return URI_FUNC(ParseOwnUserInfo)(state, first + 1, afterLast, memory); - - case URI_SET_DIGIT: - return URI_FUNC(ParseOwnPortUserInfo)(state, first + 1, afterLast, memory); - - case _UT('%'): - state->uri->portText.first = NULL; /* Not a port, reset */ - { - const URI_CHAR * const afterPct - = URI_FUNC(ParsePctEncoded)(state, first, afterLast, memory); - if (afterPct == NULL) { - return NULL; - } - return URI_FUNC(ParseOwnUserInfo)(state, afterPct, afterLast, memory); - } - - case _UT('@'): - state->uri->hostText.afterLast = NULL; /* Not a host, reset */ - state->uri->portText.first = NULL; /* Not a port, reset */ - state->uri->userInfo.afterLast = first; /* USERINFO END */ - state->uri->hostText.first = first + 1; /* HOST BEGIN */ - return URI_FUNC(ParseOwnHost)(state, first + 1, afterLast, memory); - - default: - if (!URI_FUNC(OnExitOwnPortUserInfo)(state, first, memory)) { - URI_FUNC(StopMalloc)(state, memory); - return NULL; - } - return first; - } +static const URI_CHAR * URI_FUNC(ParseOwnPortUserInfo)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { +tail_call: + if (first >= afterLast) { + if (!URI_FUNC(OnExitOwnPortUserInfo)(state, first, memory)) { + URI_FUNC(StopMalloc)(state, memory); + return NULL; + } + return afterLast; + } + + switch (*first) { + case URI_SET_SUB_DELIMS(_UT): + /* begin unreserved (except alpha and digit) */ + case _UT('-'): + case _UT('.'): + case _UT('_'): + case _UT('~'): + /* end unreserved (except alpha and digit) */ + case _UT(':'): + case URI_SET_ALPHA(_UT): + state->uri->hostText.afterLast = NULL; /* Not a host, reset */ + state->uri->portText.first = NULL; /* Not a port, reset */ + return URI_FUNC(ParseOwnUserInfo)(state, first + 1, afterLast, memory); + + case URI_SET_DIGIT(_UT): + first += 1; + goto tail_call; + + case _UT('%'): + state->uri->portText.first = NULL; /* Not a port, reset */ + const URI_CHAR * const afterPct = + URI_FUNC(ParsePctEncoded)(state, first, afterLast, memory); + if (afterPct == NULL) { + return NULL; + } + return URI_FUNC(ParseOwnUserInfo)(state, afterPct, afterLast, memory); + + case _UT('@'): + state->uri->hostText.afterLast = NULL; /* Not a host, reset */ + state->uri->portText.first = NULL; /* Not a port, reset */ + state->uri->userInfo.afterLast = first; /* USERINFO END */ + state->uri->hostText.first = first + 1; /* HOST BEGIN */ + return URI_FUNC(ParseOwnHost)(state, first + 1, afterLast, memory); + + default: + if (!URI_FUNC(OnExitOwnPortUserInfo)(state, first, memory)) { + URI_FUNC(StopMalloc)(state, memory); + return NULL; + } + return first; + } } - - /* * [ownUserInfo]->[pctSubUnres][ownUserInfo] * [ownUserInfo]-><:>[ownUserInfo] * [ownUserInfo]-><@>[ownHost] */ -static const URI_CHAR * URI_FUNC(ParseOwnUserInfo)( - URI_TYPE(ParserState) * state, const URI_CHAR * first, - const URI_CHAR * afterLast, UriMemoryManager * memory) { - if (first >= afterLast) { - URI_FUNC(StopSyntax)(state, afterLast, memory); - return NULL; - } - - switch (*first) { - case _UT('!'): - case _UT('$'): - case _UT('%'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('-'): - case _UT('*'): - case _UT(','): - case _UT('.'): - case _UT(';'): - case _UT('\''): - case _UT('_'): - case _UT('~'): - case _UT('+'): - case _UT('='): - case URI_SET_DIGIT: - case URI_SET_ALPHA: - { - const URI_CHAR * const afterPctSubUnres - = URI_FUNC(ParsePctSubUnres)(state, first, afterLast, memory); - if (afterPctSubUnres == NULL) { - return NULL; - } - return URI_FUNC(ParseOwnUserInfo)(state, afterPctSubUnres, afterLast, memory); - } - - case _UT(':'): - return URI_FUNC(ParseOwnUserInfo)(state, first + 1, afterLast, memory); - - case _UT('@'): - /* SURE */ - state->uri->userInfo.afterLast = first; /* USERINFO END */ - state->uri->hostText.first = first + 1; /* HOST BEGIN */ - return URI_FUNC(ParseOwnHost)(state, first + 1, afterLast, memory); - - default: - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; - } +static const URI_CHAR * URI_FUNC(ParseOwnUserInfo)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { +tail_call: + if (first >= afterLast) { + URI_FUNC(StopSyntax)(state, afterLast, memory); + return NULL; + } + + switch (*first) { + case _UT('%'): + case URI_SET_SUB_DELIMS(_UT): + case URI_SET_UNRESERVED(_UT): { + const URI_CHAR * const afterPctSubUnres = + URI_FUNC(ParsePctSubUnres)(state, first, afterLast, memory); + if (afterPctSubUnres == NULL) { + return NULL; + } + first = afterPctSubUnres; + goto tail_call; + } + + case _UT(':'): + first += 1; + goto tail_call; + + case _UT('@'): + /* SURE */ + state->uri->userInfo.afterLast = first; /* USERINFO END */ + state->uri->hostText.first = first + 1; /* HOST BEGIN */ + return URI_FUNC(ParseOwnHost)(state, first + 1, afterLast, memory); + + default: + URI_FUNC(StopSyntax)(state, first, memory); + return NULL; + } } - - static URI_INLINE void URI_FUNC(OnExitPartHelperTwo)(URI_TYPE(ParserState) * state) { - state->uri->absolutePath = URI_TRUE; + state->uri->absolutePath = URI_TRUE; } - - /* * [partHelperTwo]->[pathAbsNoLeadSlash] // can take * [partHelperTwo]->[authority][pathAbsEmpty] */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParsePartHelperTwo)( - URI_TYPE(ParserState) * state, const URI_CHAR * first, - const URI_CHAR * afterLast, UriMemoryManager * memory) { - if (first >= afterLast) { - URI_FUNC(OnExitPartHelperTwo)(state); - return afterLast; - } - - switch (*first) { - case _UT('/'): - { - const URI_CHAR * const afterAuthority - = URI_FUNC(ParseAuthority)(state, first + 1, afterLast, memory); - const URI_CHAR * afterPathAbsEmpty; - if (afterAuthority == NULL) { - return NULL; - } - afterPathAbsEmpty = URI_FUNC(ParsePathAbsEmpty)(state, afterAuthority, afterLast, memory); - - URI_FUNC(FixEmptyTrailSegment)(state->uri, memory); - - return afterPathAbsEmpty; - } - - default: - URI_FUNC(OnExitPartHelperTwo)(state); - return URI_FUNC(ParsePathAbsNoLeadSlash)(state, first, afterLast, memory); - } +static URI_INLINE const URI_CHAR * +URI_FUNC(ParsePartHelperTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, + const URI_CHAR * afterLast, UriMemoryManager * memory) { + if (first >= afterLast) { + URI_FUNC(OnExitPartHelperTwo)(state); + return afterLast; + } + + switch (*first) { + case _UT('/'): { + const URI_CHAR * const afterAuthority = + URI_FUNC(ParseAuthority)(state, first + 1, afterLast, memory); + const URI_CHAR * afterPathAbsEmpty; + if (afterAuthority == NULL) { + return NULL; + } + afterPathAbsEmpty = + URI_FUNC(ParsePathAbsEmpty)(state, afterAuthority, afterLast, memory); + + URI_FUNC(FixEmptyTrailSegment)(state->uri, memory); + + return afterPathAbsEmpty; + } + + default: + URI_FUNC(OnExitPartHelperTwo)(state); + return URI_FUNC(ParsePathAbsNoLeadSlash)(state, first, afterLast, memory); + } } - - /* * [pathAbsEmpty]->[segment][pathAbsEmpty] * [pathAbsEmpty]-> */ -static const URI_CHAR * URI_FUNC(ParsePathAbsEmpty)( - URI_TYPE(ParserState) * state, const URI_CHAR * first, - const URI_CHAR * afterLast, UriMemoryManager * memory) { - if (first >= afterLast) { - return afterLast; - } - - switch (*first) { - case _UT('/'): - { - const URI_CHAR * const afterSegment - = URI_FUNC(ParseSegment)(state, first + 1, afterLast, memory); - if (afterSegment == NULL) { - return NULL; - } - if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment, memory)) { /* SEGMENT BOTH */ - URI_FUNC(StopMalloc)(state, memory); - return NULL; - } - return URI_FUNC(ParsePathAbsEmpty)(state, afterSegment, afterLast, memory); - } - - default: - return first; - } +static const URI_CHAR * URI_FUNC(ParsePathAbsEmpty)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { +tail_call: + if (first >= afterLast) { + return afterLast; + } + + switch (*first) { + case _UT('/'): { + const URI_CHAR * const afterSegment = + URI_FUNC(ParseSegment)(state, first + 1, afterLast, memory); + if (afterSegment == NULL) { + return NULL; + } + if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment, + memory)) { /* SEGMENT BOTH */ + URI_FUNC(StopMalloc)(state, memory); + return NULL; + } + first = afterSegment; + goto tail_call; + } + + default: + return first; + } } - - /* * [pathAbsNoLeadSlash]->[segmentNz][zeroMoreSlashSegs] * [pathAbsNoLeadSlash]-> */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParsePathAbsNoLeadSlash)( - URI_TYPE(ParserState) * state, const URI_CHAR * first, - const URI_CHAR * afterLast, UriMemoryManager * memory) { - if (first >= afterLast) { - return afterLast; - } - - switch (*first) { - case _UT('!'): - case _UT('$'): - case _UT('%'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('-'): - case _UT('*'): - case _UT(','): - case _UT('.'): - case _UT(':'): - case _UT(';'): - case _UT('@'): - case _UT('\''): - case _UT('_'): - case _UT('~'): - case _UT('+'): - case _UT('='): - case URI_SET_DIGIT: - case URI_SET_ALPHA: - { - const URI_CHAR * const afterSegmentNz - = URI_FUNC(ParseSegmentNz)(state, first, afterLast, memory); - if (afterSegmentNz == NULL) { - return NULL; - } - if (!URI_FUNC(PushPathSegment)(state, first, afterSegmentNz, memory)) { /* SEGMENT BOTH */ - URI_FUNC(StopMalloc)(state, memory); - return NULL; - } - return URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegmentNz, afterLast, memory); - } - - default: - return first; - } +static URI_INLINE const URI_CHAR * +URI_FUNC(ParsePathAbsNoLeadSlash)(URI_TYPE(ParserState) * state, const URI_CHAR * first, + const URI_CHAR * afterLast, UriMemoryManager * memory) { + if (first >= afterLast) { + return afterLast; + } + + switch (*first) { + case URI_SET_PCHAR(_UT): { + const URI_CHAR * const afterSegmentNz = + URI_FUNC(ParseSegmentNz)(state, first, afterLast, memory); + if (afterSegmentNz == NULL) { + return NULL; + } + if (!URI_FUNC(PushPathSegment)(state, first, afterSegmentNz, + memory)) { /* SEGMENT BOTH */ + URI_FUNC(StopMalloc)(state, memory); + return NULL; + } + return URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegmentNz, afterLast, memory); + } + + default: + return first; + } } - - /* * [pathRootless]->[segmentNz][zeroMoreSlashSegs] */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParsePathRootless)( - URI_TYPE(ParserState) * state, const URI_CHAR * first, - const URI_CHAR * afterLast, UriMemoryManager * memory) { - const URI_CHAR * const afterSegmentNz - = URI_FUNC(ParseSegmentNz)(state, first, afterLast, memory); - if (afterSegmentNz == NULL) { - return NULL; - } else { - if (!URI_FUNC(PushPathSegment)(state, first, afterSegmentNz, memory)) { /* SEGMENT BOTH */ - URI_FUNC(StopMalloc)(state, memory); - return NULL; - } - } - return URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegmentNz, afterLast, memory); +static URI_INLINE const URI_CHAR * +URI_FUNC(ParsePathRootless)(URI_TYPE(ParserState) * state, const URI_CHAR * first, + const URI_CHAR * afterLast, UriMemoryManager * memory) { + const URI_CHAR * const afterSegmentNz = + URI_FUNC(ParseSegmentNz)(state, first, afterLast, memory); + if (afterSegmentNz == NULL) { + return NULL; + } else { + if (!URI_FUNC(PushPathSegment)(state, first, afterSegmentNz, + memory)) { /* SEGMENT BOTH */ + URI_FUNC(StopMalloc)(state, memory); + return NULL; + } + } + return URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegmentNz, afterLast, memory); } - - /* * [pchar]->[pctEncoded] * [pchar]->[subDelims] @@ -1524,166 +1321,129 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParsePathRootless)( * [pchar]-><@> */ static const URI_CHAR * URI_FUNC(ParsePchar)(URI_TYPE(ParserState) * state, - const URI_CHAR * first, const URI_CHAR * afterLast, - UriMemoryManager * memory) { - if (first >= afterLast) { - URI_FUNC(StopSyntax)(state, afterLast, memory); - return NULL; - } - - switch (*first) { - case _UT('%'): - return URI_FUNC(ParsePctEncoded)(state, first, afterLast, memory); - - case _UT(':'): - case _UT('@'): - case _UT('!'): - case _UT('$'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('*'): - case _UT(','): - case _UT(';'): - case _UT('\''): - case _UT('+'): - case _UT('='): - case _UT('-'): - case _UT('.'): - case _UT('_'): - case _UT('~'): - case URI_SET_DIGIT: - case URI_SET_ALPHA: - return first + 1; - - default: - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; - } + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + if (first >= afterLast) { + URI_FUNC(StopSyntax)(state, afterLast, memory); + return NULL; + } + + switch (*first) { + case _UT('%'): + return URI_FUNC(ParsePctEncoded)(state, first, afterLast, memory); + + case URI_SET_PCHAR_WITHOUT_PERCENT(_UT): + return first + 1; + + default: + URI_FUNC(StopSyntax)(state, first, memory); + return NULL; + } } - - /* * [pctEncoded]-><%>[HEXDIG][HEXDIG] */ -static const URI_CHAR * URI_FUNC(ParsePctEncoded)( - URI_TYPE(ParserState) * state, - const URI_CHAR * first, const URI_CHAR * afterLast, - UriMemoryManager * memory) { - if (first >= afterLast) { - URI_FUNC(StopSyntax)(state, afterLast, memory); - return NULL; - } - - /* - First character has already been - checked before entering this rule. - - switch (*first) { - case _UT('%'): - */ - if (first + 1 >= afterLast) { - URI_FUNC(StopSyntax)(state, afterLast, memory); - return NULL; - } - - switch (first[1]) { - case URI_SET_HEXDIG: - if (first + 2 >= afterLast) { - URI_FUNC(StopSyntax)(state, afterLast, memory); - return NULL; - } - - switch (first[2]) { - case URI_SET_HEXDIG: - return first + 3; - - default: - URI_FUNC(StopSyntax)(state, first + 2, memory); - return NULL; - } - - default: - URI_FUNC(StopSyntax)(state, first + 1, memory); - return NULL; - } - - /* - default: - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; - } - */ +static const URI_CHAR * URI_FUNC(ParsePctEncoded)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + if (first >= afterLast) { + URI_FUNC(StopSyntax)(state, afterLast, memory); + return NULL; + } + + /* + First character has already been + checked before entering this rule. + + switch (*first) { + case _UT('%'): + */ + if (afterLast - first < 2) { + URI_FUNC(StopSyntax)(state, afterLast, memory); + return NULL; + } + + switch (first[1]) { + case URI_SET_HEXDIG(_UT): + if (afterLast - first < 3) { + URI_FUNC(StopSyntax)(state, afterLast, memory); + return NULL; + } + + switch (first[2]) { + case URI_SET_HEXDIG(_UT): + return first + 3; + + default: + URI_FUNC(StopSyntax)(state, first + 2, memory); + return NULL; + } + + default: + URI_FUNC(StopSyntax)(state, first + 1, memory); + return NULL; + } + + /* + default: + URI_FUNC(StopSyntax)(state, first, memory); + return NULL; + } + */ } - - /* * [pctSubUnres]->[pctEncoded] * [pctSubUnres]->[subDelims] * [pctSubUnres]->[unreserved] */ -static const URI_CHAR * URI_FUNC(ParsePctSubUnres)( - URI_TYPE(ParserState) * state, - const URI_CHAR * first, const URI_CHAR * afterLast, - UriMemoryManager * memory) { - if (first >= afterLast) { - URI_FUNC(StopSyntax)(state, afterLast, memory); - return NULL; - } - - switch (*first) { - case _UT('%'): - return URI_FUNC(ParsePctEncoded)(state, first, afterLast, memory); - - case _UT('!'): - case _UT('$'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('*'): - case _UT(','): - case _UT(';'): - case _UT('\''): - case _UT('+'): - case _UT('='): - case _UT('-'): - case _UT('.'): - case _UT('_'): - case _UT('~'): - case URI_SET_DIGIT: - case URI_SET_ALPHA: - return first + 1; - - default: - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; - } +static const URI_CHAR * URI_FUNC(ParsePctSubUnres)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + if (first >= afterLast) { + URI_FUNC(StopSyntax)(state, afterLast, memory); + return NULL; + } + + switch (*first) { + case _UT('%'): + return URI_FUNC(ParsePctEncoded)(state, first, afterLast, memory); + + case URI_SET_SUB_DELIMS(_UT): + case URI_SET_UNRESERVED(_UT): + return first + 1; + + default: + URI_FUNC(StopSyntax)(state, first, memory); + return NULL; + } } - - /* * [port]->[DIGIT][port] * [port]-> */ -static const URI_CHAR * URI_FUNC(ParsePort)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { - if (first >= afterLast) { - return afterLast; - } - - switch (*first) { - case URI_SET_DIGIT: - return URI_FUNC(ParsePort)(state, first + 1, afterLast); - - default: - return first; - } +static const URI_CHAR * URI_FUNC(ParsePort)(const URI_CHAR * first, + const URI_CHAR * afterLast) { +tail_call: + if (first >= afterLast) { + return afterLast; + } + + switch (*first) { + case URI_SET_DIGIT(_UT): + first += 1; + goto tail_call; + + default: + return first; + } } - - /* * [queryFrag]->[pchar][queryFrag] * [queryFrag]->[queryFrag] @@ -1691,130 +1451,89 @@ static const URI_CHAR * URI_FUNC(ParsePort)(URI_TYPE(ParserState) * state, const * [queryFrag]-> */ static const URI_CHAR * URI_FUNC(ParseQueryFrag)(URI_TYPE(ParserState) * state, - const URI_CHAR * first, const URI_CHAR * afterLast, - UriMemoryManager * memory) { - if (first >= afterLast) { - return afterLast; - } - - switch (*first) { - case _UT('!'): - case _UT('$'): - case _UT('%'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('-'): - case _UT('*'): - case _UT(','): - case _UT('.'): - case _UT(':'): - case _UT(';'): - case _UT('@'): - case _UT('\''): - case _UT('_'): - case _UT('~'): - case _UT('+'): - case _UT('='): - case URI_SET_DIGIT: - case URI_SET_ALPHA: - { - const URI_CHAR * const afterPchar - = URI_FUNC(ParsePchar)(state, first, afterLast, memory); - if (afterPchar == NULL) { - return NULL; - } - return URI_FUNC(ParseQueryFrag)(state, afterPchar, afterLast, memory); - } - - case _UT('/'): - case _UT('?'): - return URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast, memory); - - default: - return first; - } + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { +tail_call: + if (first >= afterLast) { + return afterLast; + } + + switch (*first) { + case URI_SET_PCHAR(_UT): { + const URI_CHAR * const afterPchar = + URI_FUNC(ParsePchar)(state, first, afterLast, memory); + if (afterPchar == NULL) { + return NULL; + } + first = afterPchar; + goto tail_call; + } + + case _UT('/'): + case _UT('?'): + first += 1; + goto tail_call; + + default: + return first; + } } - - /* * [segment]->[pchar][segment] * [segment]-> */ static const URI_CHAR * URI_FUNC(ParseSegment)(URI_TYPE(ParserState) * state, - const URI_CHAR * first, const URI_CHAR * afterLast, - UriMemoryManager * memory) { - if (first >= afterLast) { - return afterLast; - } - - switch (*first) { - case _UT('!'): - case _UT('$'): - case _UT('%'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('-'): - case _UT('*'): - case _UT(','): - case _UT('.'): - case _UT(':'): - case _UT(';'): - case _UT('@'): - case _UT('\''): - case _UT('_'): - case _UT('~'): - case _UT('+'): - case _UT('='): - case URI_SET_DIGIT: - case URI_SET_ALPHA: - { - const URI_CHAR * const afterPchar - = URI_FUNC(ParsePchar)(state, first, afterLast, memory); - if (afterPchar == NULL) { - return NULL; - } - return URI_FUNC(ParseSegment)(state, afterPchar, afterLast, memory); - } - - default: - return first; - } + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { +tail_call: + if (first >= afterLast) { + return afterLast; + } + + switch (*first) { + case URI_SET_PCHAR(_UT): { + const URI_CHAR * const afterPchar = + URI_FUNC(ParsePchar)(state, first, afterLast, memory); + if (afterPchar == NULL) { + return NULL; + } + first = afterPchar; + goto tail_call; + } + + default: + return first; + } } - - /* * [segmentNz]->[pchar][segment] */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParseSegmentNz)( - URI_TYPE(ParserState) * state, - const URI_CHAR * first, const URI_CHAR * afterLast, - UriMemoryManager * memory) { - const URI_CHAR * const afterPchar - = URI_FUNC(ParsePchar)(state, first, afterLast, memory); - if (afterPchar == NULL) { - return NULL; - } - return URI_FUNC(ParseSegment)(state, afterPchar, afterLast, memory); +static URI_INLINE const URI_CHAR * URI_FUNC(ParseSegmentNz)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + const URI_CHAR * const afterPchar = + URI_FUNC(ParsePchar)(state, first, afterLast, memory); + if (afterPchar == NULL) { + return NULL; + } + return URI_FUNC(ParseSegment)(state, afterPchar, afterLast, memory); } - - static URI_INLINE UriBool URI_FUNC(OnExitSegmentNzNcOrScheme2)( - URI_TYPE(ParserState) * state, const URI_CHAR * first, - UriMemoryManager * memory) { - if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first, memory)) { /* SEGMENT BOTH */ - return URI_FALSE; /* Raises malloc error*/ - } - state->uri->scheme.first = NULL; /* Not a scheme, reset */ - return URI_TRUE; /* Success */ + URI_TYPE(ParserState) * state, const URI_CHAR * first, UriMemoryManager * memory) { + if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first, + memory)) { /* SEGMENT BOTH */ + return URI_FALSE; /* Raises malloc error*/ + } + state->uri->scheme.first = NULL; /* Not a scheme, reset */ + return URI_TRUE; /* Success */ } - - /* * [segmentNzNcOrScheme2]->[ALPHA][segmentNzNcOrScheme2] * [segmentNzNcOrScheme2]->[DIGIT][segmentNzNcOrScheme2] @@ -1839,97 +1558,98 @@ static URI_INLINE UriBool URI_FUNC(OnExitSegmentNzNcOrScheme2)( * [segmentNzNcOrScheme2]-><'>[mustBeSegmentNzNc] * [segmentNzNcOrScheme2]-><->[segmentNzNcOrScheme2] */ -static const URI_CHAR * URI_FUNC(ParseSegmentNzNcOrScheme2)( - URI_TYPE(ParserState) * state, const URI_CHAR * first, - const URI_CHAR * afterLast, UriMemoryManager * memory) { - if (first >= afterLast) { - if (!URI_FUNC(OnExitSegmentNzNcOrScheme2)(state, first, memory)) { - URI_FUNC(StopMalloc)(state, memory); - return NULL; - } - return afterLast; - } - - switch (*first) { - case _UT('.'): - case _UT('+'): - case _UT('-'): - case URI_SET_ALPHA: - case URI_SET_DIGIT: - return URI_FUNC(ParseSegmentNzNcOrScheme2)(state, first + 1, afterLast, memory); - - case _UT('%'): - { - const URI_CHAR * const afterPctEncoded - = URI_FUNC(ParsePctEncoded)(state, first, afterLast, memory); - if (afterPctEncoded == NULL) { - return NULL; - } - return URI_FUNC(ParseMustBeSegmentNzNc)(state, afterPctEncoded, afterLast, memory); - } - - case _UT('!'): - case _UT('$'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('*'): - case _UT(','): - case _UT(';'): - case _UT('@'): - case _UT('_'): - case _UT('~'): - case _UT('='): - case _UT('\''): - return URI_FUNC(ParseMustBeSegmentNzNc)(state, first + 1, afterLast, memory); - - case _UT('/'): - { - const URI_CHAR * afterZeroMoreSlashSegs; - const URI_CHAR * const afterSegment - = URI_FUNC(ParseSegment)(state, first + 1, afterLast, memory); - if (afterSegment == NULL) { - return NULL; - } - if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first, memory)) { /* SEGMENT BOTH */ - URI_FUNC(StopMalloc)(state, memory); - return NULL; - } - state->uri->scheme.first = NULL; /* Not a scheme, reset */ - if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment, memory)) { /* SEGMENT BOTH */ - URI_FUNC(StopMalloc)(state, memory); - return NULL; - } - afterZeroMoreSlashSegs - = URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegment, afterLast, memory); - if (afterZeroMoreSlashSegs == NULL) { - return NULL; - } - return URI_FUNC(ParseUriTail)(state, afterZeroMoreSlashSegs, afterLast, memory); - } - - case _UT(':'): - { - const URI_CHAR * const afterHierPart - = URI_FUNC(ParseHierPart)(state, first + 1, afterLast, memory); - state->uri->scheme.afterLast = first; /* SCHEME END */ - if (afterHierPart == NULL) { - return NULL; - } - return URI_FUNC(ParseUriTail)(state, afterHierPart, afterLast, memory); - } - - default: - if (!URI_FUNC(OnExitSegmentNzNcOrScheme2)(state, first, memory)) { - URI_FUNC(StopMalloc)(state, memory); - return NULL; - } - return URI_FUNC(ParseUriTail)(state, first, afterLast, memory); - } +static const URI_CHAR * URI_FUNC(ParseSegmentNzNcOrScheme2)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { +tail_call: + if (first >= afterLast) { + if (!URI_FUNC(OnExitSegmentNzNcOrScheme2)(state, first, memory)) { + URI_FUNC(StopMalloc)(state, memory); + return NULL; + } + return afterLast; + } + + switch (*first) { + case _UT('.'): + case _UT('+'): + case _UT('-'): + case URI_SET_ALPHA(_UT): + case URI_SET_DIGIT(_UT): + first += 1; + goto tail_call; + + case _UT('%'): { + const URI_CHAR * const afterPctEncoded = + URI_FUNC(ParsePctEncoded)(state, first, afterLast, memory); + if (afterPctEncoded == NULL) { + return NULL; + } + return URI_FUNC(ParseMustBeSegmentNzNc)(state, afterPctEncoded, afterLast, + memory); + } + + case _UT('!'): + case _UT('$'): + case _UT('&'): + case _UT('('): + case _UT(')'): + case _UT('*'): + case _UT(','): + case _UT(';'): + case _UT('@'): + case _UT('_'): + case _UT('~'): + case _UT('='): + case _UT('\''): + return URI_FUNC(ParseMustBeSegmentNzNc)(state, first + 1, afterLast, memory); + + case _UT('/'): { + const URI_CHAR * afterZeroMoreSlashSegs; + const URI_CHAR * const afterSegment = + URI_FUNC(ParseSegment)(state, first + 1, afterLast, memory); + if (afterSegment == NULL) { + return NULL; + } + if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first, + memory)) { /* SEGMENT BOTH */ + URI_FUNC(StopMalloc)(state, memory); + return NULL; + } + state->uri->scheme.first = NULL; /* Not a scheme, reset */ + if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment, + memory)) { /* SEGMENT BOTH */ + URI_FUNC(StopMalloc)(state, memory); + return NULL; + } + afterZeroMoreSlashSegs = + URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegment, afterLast, memory); + if (afterZeroMoreSlashSegs == NULL) { + return NULL; + } + return URI_FUNC(ParseUriTail)(state, afterZeroMoreSlashSegs, afterLast, memory); + } + + case _UT(':'): { + const URI_CHAR * const afterHierPart = + URI_FUNC(ParseHierPart)(state, first + 1, afterLast, memory); + state->uri->scheme.afterLast = first; /* SCHEME END */ + if (afterHierPart == NULL) { + return NULL; + } + return URI_FUNC(ParseUriTail)(state, afterHierPart, afterLast, memory); + } + + default: + if (!URI_FUNC(OnExitSegmentNzNcOrScheme2)(state, first, memory)) { + URI_FUNC(StopMalloc)(state, memory); + return NULL; + } + return URI_FUNC(ParseUriTail)(state, first, afterLast, memory); + } } - - /* * [uriReference]->[ALPHA][segmentNzNcOrScheme2] * [uriReference]->[DIGIT][mustBeSegmentNzNc] @@ -1943,467 +1663,410 @@ static const URI_CHAR * URI_FUNC(ParseSegmentNzNcOrScheme2)( * [uriReference]-><~>[mustBeSegmentNzNc] * [uriReference]-><->[mustBeSegmentNzNc] */ -static const URI_CHAR * URI_FUNC(ParseUriReference)( - URI_TYPE(ParserState) * state, const URI_CHAR * first, - const URI_CHAR * afterLast, UriMemoryManager * memory) { - if (first >= afterLast) { - return afterLast; - } - - switch (*first) { - case URI_SET_ALPHA: - state->uri->scheme.first = first; /* SCHEME BEGIN */ - return URI_FUNC(ParseSegmentNzNcOrScheme2)(state, first + 1, afterLast, memory); - - case URI_SET_DIGIT: - case _UT('!'): - case _UT('$'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('*'): - case _UT(','): - case _UT(';'): - case _UT('\''): - case _UT('+'): - case _UT('='): - case _UT('.'): - case _UT('_'): - case _UT('~'): - case _UT('-'): - case _UT('@'): - state->uri->scheme.first = first; /* SEGMENT BEGIN, ABUSE SCHEME POINTER */ - return URI_FUNC(ParseMustBeSegmentNzNc)(state, first + 1, afterLast, memory); - - case _UT('%'): - { - const URI_CHAR * const afterPctEncoded - = URI_FUNC(ParsePctEncoded)(state, first, afterLast, memory); - if (afterPctEncoded == NULL) { - return NULL; - } - state->uri->scheme.first = first; /* SEGMENT BEGIN, ABUSE SCHEME POINTER */ - return URI_FUNC(ParseMustBeSegmentNzNc)(state, afterPctEncoded, afterLast, memory); - } - - case _UT('/'): - { - const URI_CHAR * const afterPartHelperTwo - = URI_FUNC(ParsePartHelperTwo)(state, first + 1, afterLast, memory); - if (afterPartHelperTwo == NULL) { - return NULL; - } - return URI_FUNC(ParseUriTail)(state, afterPartHelperTwo, afterLast, memory); - } - - default: - return URI_FUNC(ParseUriTail)(state, first, afterLast, memory); - } +static const URI_CHAR * URI_FUNC(ParseUriReference)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + if (first >= afterLast) { + return afterLast; + } + + switch (*first) { + case URI_SET_ALPHA(_UT): + state->uri->scheme.first = first; /* SCHEME BEGIN */ + return URI_FUNC(ParseSegmentNzNcOrScheme2)(state, first + 1, afterLast, memory); + + case URI_SET_DIGIT(_UT): + case URI_SET_SUB_DELIMS(_UT): + case _UT('.'): + case _UT('_'): + case _UT('~'): + case _UT('-'): + case _UT('@'): + state->uri->scheme.first = first; /* SEGMENT BEGIN, ABUSE SCHEME POINTER */ + return URI_FUNC(ParseMustBeSegmentNzNc)(state, first + 1, afterLast, memory); + + case _UT('%'): { + const URI_CHAR * const afterPctEncoded = + URI_FUNC(ParsePctEncoded)(state, first, afterLast, memory); + if (afterPctEncoded == NULL) { + return NULL; + } + state->uri->scheme.first = first; /* SEGMENT BEGIN, ABUSE SCHEME POINTER */ + return URI_FUNC(ParseMustBeSegmentNzNc)(state, afterPctEncoded, afterLast, + memory); + } + + case _UT('/'): { + const URI_CHAR * const afterPartHelperTwo = + URI_FUNC(ParsePartHelperTwo)(state, first + 1, afterLast, memory); + if (afterPartHelperTwo == NULL) { + return NULL; + } + return URI_FUNC(ParseUriTail)(state, afterPartHelperTwo, afterLast, memory); + } + + default: + return URI_FUNC(ParseUriTail)(state, first, afterLast, memory); + } } - - /* * [uriTail]-><#>[queryFrag] * [uriTail]->[queryFrag][uriTailTwo] * [uriTail]-> */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParseUriTail)( - URI_TYPE(ParserState) * state, - const URI_CHAR * first, const URI_CHAR * afterLast, - UriMemoryManager * memory) { - if (first >= afterLast) { - return afterLast; - } - - switch (*first) { - case _UT('#'): - { - const URI_CHAR * const afterQueryFrag = URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast, memory); - if (afterQueryFrag == NULL) { - return NULL; - } - state->uri->fragment.first = first + 1; /* FRAGMENT BEGIN */ - state->uri->fragment.afterLast = afterQueryFrag; /* FRAGMENT END */ - return afterQueryFrag; - } - - case _UT('?'): - { - const URI_CHAR * const afterQueryFrag - = URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast, memory); - if (afterQueryFrag == NULL) { - return NULL; - } - state->uri->query.first = first + 1; /* QUERY BEGIN */ - state->uri->query.afterLast = afterQueryFrag; /* QUERY END */ - return URI_FUNC(ParseUriTailTwo)(state, afterQueryFrag, afterLast, memory); - } - - default: - return first; - } +static URI_INLINE const URI_CHAR * URI_FUNC(ParseUriTail)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + if (first >= afterLast) { + return afterLast; + } + + switch (*first) { + case _UT('#'): { + const URI_CHAR * const afterQueryFrag = + URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast, memory); + if (afterQueryFrag == NULL) { + return NULL; + } + state->uri->fragment.first = first + 1; /* FRAGMENT BEGIN */ + state->uri->fragment.afterLast = afterQueryFrag; /* FRAGMENT END */ + return afterQueryFrag; + } + + case _UT('?'): { + const URI_CHAR * const afterQueryFrag = + URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast, memory); + if (afterQueryFrag == NULL) { + return NULL; + } + state->uri->query.first = first + 1; /* QUERY BEGIN */ + state->uri->query.afterLast = afterQueryFrag; /* QUERY END */ + return URI_FUNC(ParseUriTailTwo)(state, afterQueryFrag, afterLast, memory); + } + + default: + return first; + } } - - /* * [uriTailTwo]-><#>[queryFrag] * [uriTailTwo]-> */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParseUriTailTwo)( - URI_TYPE(ParserState) * state, - const URI_CHAR * first, const URI_CHAR * afterLast, - UriMemoryManager * memory) { - if (first >= afterLast) { - return afterLast; - } - - switch (*first) { - case _UT('#'): - { - const URI_CHAR * const afterQueryFrag = URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast, memory); - if (afterQueryFrag == NULL) { - return NULL; - } - state->uri->fragment.first = first + 1; /* FRAGMENT BEGIN */ - state->uri->fragment.afterLast = afterQueryFrag; /* FRAGMENT END */ - return afterQueryFrag; - } - - default: - return first; - } +static URI_INLINE const URI_CHAR * +URI_FUNC(ParseUriTailTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, + const URI_CHAR * afterLast, UriMemoryManager * memory) { + if (first >= afterLast) { + return afterLast; + } + + switch (*first) { + case _UT('#'): { + const URI_CHAR * const afterQueryFrag = + URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast, memory); + if (afterQueryFrag == NULL) { + return NULL; + } + state->uri->fragment.first = first + 1; /* FRAGMENT BEGIN */ + state->uri->fragment.afterLast = afterQueryFrag; /* FRAGMENT END */ + return afterQueryFrag; + } + + default: + return first; + } } - - /* * [zeroMoreSlashSegs]->[segment][zeroMoreSlashSegs] * [zeroMoreSlashSegs]-> */ -static const URI_CHAR * URI_FUNC(ParseZeroMoreSlashSegs)( - URI_TYPE(ParserState) * state, const URI_CHAR * first, - const URI_CHAR * afterLast, UriMemoryManager * memory) { - if (first >= afterLast) { - return afterLast; - } - - switch (*first) { - case _UT('/'): - { - const URI_CHAR * const afterSegment - = URI_FUNC(ParseSegment)(state, first + 1, afterLast, memory); - if (afterSegment == NULL) { - return NULL; - } - if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment, memory)) { /* SEGMENT BOTH */ - URI_FUNC(StopMalloc)(state, memory); - return NULL; - } - return URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegment, afterLast, memory); - } - - default: - return first; - } +static const URI_CHAR * URI_FUNC(ParseZeroMoreSlashSegs)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { +tail_call: + if (first >= afterLast) { + return afterLast; + } + + switch (*first) { + case _UT('/'): { + const URI_CHAR * const afterSegment = + URI_FUNC(ParseSegment)(state, first + 1, afterLast, memory); + if (afterSegment == NULL) { + return NULL; + } + if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment, + memory)) { /* SEGMENT BOTH */ + URI_FUNC(StopMalloc)(state, memory); + return NULL; + } + first = afterSegment; + goto tail_call; + } + + default: + return first; + } } - - -static URI_INLINE void URI_FUNC(ResetParserStateExceptUri)(URI_TYPE(ParserState) * state) { - URI_TYPE(Uri) * const uriBackup = state->uri; - memset(state, 0, sizeof(URI_TYPE(ParserState))); - state->uri = uriBackup; +static URI_INLINE void URI_FUNC(ResetParserStateExceptUri)(URI_TYPE(ParserState) + * state) { + URI_TYPE(Uri) * const uriBackup = state->uri; + memset(state, 0, sizeof(URI_TYPE(ParserState))); + state->uri = uriBackup; } - - -static URI_INLINE UriBool URI_FUNC(PushPathSegment)( - URI_TYPE(ParserState) * state, const URI_CHAR * first, - const URI_CHAR * afterLast, UriMemoryManager * memory) { - URI_TYPE(PathSegment) * segment = memory->calloc(memory, 1, sizeof(URI_TYPE(PathSegment))); - if (segment == NULL) { - return URI_FALSE; /* Raises malloc error */ - } - if (first == afterLast) { - segment->text.first = URI_FUNC(SafeToPointTo); - segment->text.afterLast = URI_FUNC(SafeToPointTo); - } else { - segment->text.first = first; - segment->text.afterLast = afterLast; - } - - /* First segment ever? */ - if (state->uri->pathHead == NULL) { - /* First segment ever, set head and tail */ - state->uri->pathHead = segment; - state->uri->pathTail = segment; - } else { - /* Append, update tail */ - state->uri->pathTail->next = segment; - state->uri->pathTail = segment; - } - - return URI_TRUE; /* Success */ +static URI_INLINE UriBool URI_FUNC(PushPathSegment)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + URI_TYPE(PathSegment) * segment = + memory->calloc(memory, 1, sizeof(URI_TYPE(PathSegment))); + if (segment == NULL) { + return URI_FALSE; /* Raises malloc error */ + } + if (first == afterLast) { + segment->text.first = URI_FUNC(SafeToPointTo); + segment->text.afterLast = URI_FUNC(SafeToPointTo); + } else { + segment->text.first = first; + segment->text.afterLast = afterLast; + } + + /* First segment ever? */ + if (state->uri->pathHead == NULL) { + /* First segment ever, set head and tail */ + state->uri->pathHead = segment; + state->uri->pathTail = segment; + } else { + /* Append, update tail */ + state->uri->pathTail->next = segment; + state->uri->pathTail = segment; + } + + return URI_TRUE; /* Success */ } - - -int URI_FUNC(ParseUriEx)(URI_TYPE(ParserState) * state, - const URI_CHAR * first, const URI_CHAR * afterLast) { - return URI_FUNC(ParseUriExMm)(state, first, afterLast, NULL); +int URI_FUNC(ParseUriEx)(URI_TYPE(ParserState) * state, const URI_CHAR * first, + const URI_CHAR * afterLast) { + return URI_FUNC(ParseUriExMm)(state, first, afterLast, NULL); } - - -static int URI_FUNC(ParseUriExMm)(URI_TYPE(ParserState) * state, - const URI_CHAR * first, const URI_CHAR * afterLast, - UriMemoryManager * memory) { - const URI_CHAR * afterUriReference; - URI_TYPE(Uri) * uri; - - /* Check params */ - if ((state == NULL) || (first == NULL) || (afterLast == NULL)) { - return URI_ERROR_NULL; - } - URI_CHECK_MEMORY_MANAGER(memory); /* may return */ - - uri = state->uri; - - /* Init parser */ - URI_FUNC(ResetParserStateExceptUri)(state); - URI_FUNC(ResetUri)(uri); - - /* Parse */ - afterUriReference = URI_FUNC(ParseUriReference)(state, first, afterLast, memory); - if (afterUriReference == NULL) { - /* Waterproof errorPos <= afterLast */ - if (state->errorPos && (state->errorPos > afterLast)) { - state->errorPos = afterLast; - } - return state->errorCode; - } - if (afterUriReference != afterLast) { - if (afterUriReference < afterLast) { - URI_FUNC(StopSyntax)(state, afterUriReference, memory); - } else { - URI_FUNC(StopSyntax)(state, afterLast, memory); - } - return state->errorCode; - } - return URI_SUCCESS; +static int URI_FUNC(ParseUriExMm)(URI_TYPE(ParserState) * state, const URI_CHAR * first, + const URI_CHAR * afterLast, UriMemoryManager * memory) { + const URI_CHAR * afterUriReference; + URI_TYPE(Uri) * uri; + + /* Check params */ + if ((state == NULL) || (first == NULL) || (afterLast == NULL)) { + return URI_ERROR_NULL; + } + URI_CHECK_MEMORY_MANAGER(memory); /* may return */ + + uri = state->uri; + + /* Init parser */ + URI_FUNC(ResetParserStateExceptUri)(state); + URI_FUNC(ResetUri)(uri); + + /* Parse */ + afterUriReference = URI_FUNC(ParseUriReference)(state, first, afterLast, memory); + if (afterUriReference == NULL) { + /* Waterproof errorPos <= afterLast */ + if (state->errorPos && (state->errorPos > afterLast)) { + state->errorPos = afterLast; + } + return state->errorCode; + } + if (afterUriReference != afterLast) { + if (afterUriReference < afterLast) { + URI_FUNC(StopSyntax)(state, afterUriReference, memory); + } else { + URI_FUNC(StopSyntax)(state, afterLast, memory); + } + return state->errorCode; + } + return URI_SUCCESS; } - - int URI_FUNC(ParseUri)(URI_TYPE(ParserState) * state, const URI_CHAR * text) { - if ((state == NULL) || (text == NULL)) { - return URI_ERROR_NULL; - } - return URI_FUNC(ParseUriEx)(state, text, text + URI_STRLEN(text)); + if ((state == NULL) || (text == NULL)) { + return URI_ERROR_NULL; + } + return URI_FUNC(ParseUriEx)(state, text, text + URI_STRLEN(text)); } - - int URI_FUNC(ParseSingleUri)(URI_TYPE(Uri) * uri, const URI_CHAR * text, - const URI_CHAR ** errorPos) { - return URI_FUNC(ParseSingleUriEx)(uri, text, NULL, errorPos); + const URI_CHAR ** errorPos) { + return URI_FUNC(ParseSingleUriEx)(uri, text, NULL, errorPos); } - - -int URI_FUNC(ParseSingleUriEx)(URI_TYPE(Uri) * uri, - const URI_CHAR * first, const URI_CHAR * afterLast, - const URI_CHAR ** errorPos) { +int URI_FUNC(ParseSingleUriEx)(URI_TYPE(Uri) * uri, const URI_CHAR * first, + const URI_CHAR * afterLast, const URI_CHAR ** errorPos) { if ((afterLast == NULL) && (first != NULL)) { - afterLast = first + URI_STRLEN(first); - } - return URI_FUNC(ParseSingleUriExMm)(uri, first, afterLast, errorPos, NULL); + afterLast = first + URI_STRLEN(first); + } + return URI_FUNC(ParseSingleUriExMm)(uri, first, afterLast, errorPos, NULL); } +int URI_FUNC(ParseSingleUriExMm)(URI_TYPE(Uri) * uri, const URI_CHAR * first, + const URI_CHAR * afterLast, const URI_CHAR ** errorPos, + UriMemoryManager * memory) { + URI_TYPE(ParserState) state; + int res; + /* Check params */ + if ((uri == NULL) || (first == NULL) || (afterLast == NULL)) { + return URI_ERROR_NULL; + } + URI_CHECK_MEMORY_MANAGER(memory); /* may return */ -int URI_FUNC(ParseSingleUriExMm)(URI_TYPE(Uri) * uri, - const URI_CHAR * first, const URI_CHAR * afterLast, - const URI_CHAR ** errorPos, UriMemoryManager * memory) { - URI_TYPE(ParserState) state; - int res; - - /* Check params */ - if ((uri == NULL) || (first == NULL) || (afterLast == NULL)) { - return URI_ERROR_NULL; - } - URI_CHECK_MEMORY_MANAGER(memory); /* may return */ - - state.uri = uri; + state.uri = uri; - res = URI_FUNC(ParseUriExMm)(&state, first, afterLast, memory); + res = URI_FUNC(ParseUriExMm)(&state, first, afterLast, memory); - if (res != URI_SUCCESS) { - if (errorPos != NULL) { - *errorPos = state.errorPos; - } - URI_FUNC(FreeUriMembersMm)(uri, memory); - } + if (res != URI_SUCCESS) { + if (errorPos != NULL) { + *errorPos = state.errorPos; + } + URI_FUNC(FreeUriMembersMm)(uri, memory); + } - return res; + return res; } - - void URI_FUNC(FreeUriMembers)(URI_TYPE(Uri) * uri) { - URI_FUNC(FreeUriMembersMm)(uri, NULL); + URI_FUNC(FreeUriMembersMm)(uri, NULL); } - - int URI_FUNC(FreeUriMembersMm)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) { - if (uri == NULL) { - return URI_ERROR_NULL; - } - - URI_CHECK_MEMORY_MANAGER(memory); /* may return */ - - if (uri->owner) { - /* Scheme */ - if (uri->scheme.first != NULL) { - if (uri->scheme.first != uri->scheme.afterLast) { - memory->free(memory, (URI_CHAR *)uri->scheme.first); - } - uri->scheme.first = NULL; - uri->scheme.afterLast = NULL; - } - - /* User info */ - if (uri->userInfo.first != NULL) { - if (uri->userInfo.first != uri->userInfo.afterLast) { - memory->free(memory, (URI_CHAR *)uri->userInfo.first); - } - uri->userInfo.first = NULL; - uri->userInfo.afterLast = NULL; - } - - /* 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; - } - - if (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; - } - - /* Host text (after IPvFuture, see above) */ - if (uri->hostText.first != NULL) { - if (uri->hostText.first != uri->hostText.afterLast) { - memory->free(memory, (URI_CHAR *)uri->hostText.first); - } - uri->hostText.first = NULL; - uri->hostText.afterLast = NULL; - } - } - - /* Host data - IPv4 */ - if (uri->hostData.ip4 != NULL) { - memory->free(memory, uri->hostData.ip4); - uri->hostData.ip4 = NULL; - } - - /* Host data - IPv6 */ - if (uri->hostData.ip6 != NULL) { - memory->free(memory, uri->hostData.ip6); - uri->hostData.ip6 = NULL; - } - - /* Port text */ - if (uri->owner && (uri->portText.first != NULL)) { - if (uri->portText.first != uri->portText.afterLast) { - memory->free(memory, (URI_CHAR *)uri->portText.first); - } - uri->portText.first = NULL; - uri->portText.afterLast = NULL; - } - - /* 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; - } - - if (uri->owner) { - /* Query */ - if (uri->query.first != NULL) { - if (uri->query.first != uri->query.afterLast) { - memory->free(memory, (URI_CHAR *)uri->query.first); - } - uri->query.first = NULL; - uri->query.afterLast = NULL; - } - - /* Fragment */ - if (uri->fragment.first != NULL) { - if (uri->fragment.first != uri->fragment.afterLast) { - memory->free(memory, (URI_CHAR *)uri->fragment.first); - } - uri->fragment.first = NULL; - uri->fragment.afterLast = NULL; - } - } - - return URI_SUCCESS; + if (uri == NULL) { + return URI_ERROR_NULL; + } + + URI_CHECK_MEMORY_MANAGER(memory); /* may return */ + + if (uri->owner) { + /* Scheme */ + if (uri->scheme.first != NULL) { + if (uri->scheme.first != uri->scheme.afterLast) { + memory->free(memory, (URI_CHAR *)uri->scheme.first); + } + uri->scheme.first = NULL; + uri->scheme.afterLast = NULL; + } + + /* User info */ + if (uri->userInfo.first != NULL) { + if (uri->userInfo.first != uri->userInfo.afterLast) { + memory->free(memory, (URI_CHAR *)uri->userInfo.first); + } + uri->userInfo.first = NULL; + uri->userInfo.afterLast = NULL; + } + + /* Host data - IPvFuture (may affect host text) */ + 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->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; + } + + /* Host text (after IPvFuture, see above) */ + if (uri->hostText.first != NULL) { + if (uri->hostText.first != uri->hostText.afterLast) { + memory->free(memory, (URI_CHAR *)uri->hostText.first); + } + uri->hostText.first = NULL; + uri->hostText.afterLast = NULL; + } + } + + /* Host data - IPv4 */ + if (uri->hostData.ip4 != NULL) { + memory->free(memory, uri->hostData.ip4); + uri->hostData.ip4 = NULL; + } + + /* Host data - IPv6 */ + if (uri->hostData.ip6 != NULL) { + memory->free(memory, uri->hostData.ip6); + uri->hostData.ip6 = NULL; + } + + /* Port text */ + if (uri->owner && (uri->portText.first != NULL)) { + if (uri->portText.first != uri->portText.afterLast) { + memory->free(memory, (URI_CHAR *)uri->portText.first); + } + uri->portText.first = NULL; + uri->portText.afterLast = NULL; + } + + /* Path */ + URI_FUNC(FreeUriPath)(uri, memory); + + if (uri->owner) { + /* Query */ + if (uri->query.first != NULL) { + if (uri->query.first != uri->query.afterLast) { + memory->free(memory, (URI_CHAR *)uri->query.first); + } + uri->query.first = NULL; + uri->query.afterLast = NULL; + } + + /* Fragment */ + if (uri->fragment.first != NULL) { + if (uri->fragment.first != uri->fragment.afterLast) { + memory->free(memory, (URI_CHAR *)uri->fragment.first); + } + uri->fragment.first = NULL; + uri->fragment.afterLast = NULL; + } + } + + return URI_SUCCESS; } - - UriBool URI_FUNC(_TESTING_ONLY_ParseIpSix)(const URI_CHAR * text) { - UriMemoryManager * const memory = &defaultMemoryManager; - URI_TYPE(Uri) uri; - URI_TYPE(ParserState) parser; - const URI_CHAR * const afterIpSix = text + URI_STRLEN(text); - const URI_CHAR * res; - - URI_FUNC(ResetUri)(&uri); - parser.uri = &uri; - URI_FUNC(ResetParserStateExceptUri)(&parser); - parser.uri->hostData.ip6 = memory->malloc(memory, 1 * sizeof(UriIp6)); - res = URI_FUNC(ParseIPv6address2)(&parser, text, afterIpSix, memory); - URI_FUNC(FreeUriMembersMm)(&uri, memory); - return res == afterIpSix ? URI_TRUE : URI_FALSE; + UriMemoryManager * const memory = &defaultMemoryManager; + URI_TYPE(Uri) uri; + URI_TYPE(ParserState) parser; + const URI_CHAR * const afterIpSix = text + URI_STRLEN(text); + const URI_CHAR * res; + + URI_FUNC(ResetUri)(&uri); + parser.uri = &uri; + URI_FUNC(ResetParserStateExceptUri)(&parser); + parser.uri->hostData.ip6 = memory->malloc(memory, 1 * sizeof(UriIp6)); + res = URI_FUNC(ParseIPv6address2)(&parser, text, afterIpSix, memory); + URI_FUNC(FreeUriMembersMm)(&uri, memory); + return res == afterIpSix ? URI_TRUE : URI_FALSE; } - - UriBool URI_FUNC(_TESTING_ONLY_ParseIpFour)(const URI_CHAR * text) { - unsigned char octets[4]; - int res = URI_FUNC(ParseIpFourAddress)(octets, text, text + URI_STRLEN(text)); - return (res == URI_SUCCESS) ? URI_TRUE : URI_FALSE; + unsigned char octets[4]; + int res = URI_FUNC(ParseIpFourAddress)(octets, text, text + URI_STRLEN(text)); + return (res == URI_SUCCESS) ? URI_TRUE : URI_FALSE; } - - -#undef URI_SET_DIGIT -#undef URI_SET_HEX_LETTER_UPPER -#undef URI_SET_HEX_LETTER_LOWER -#undef URI_SET_HEXDIG -#undef URI_SET_ALPHA - - +# undef URI_SET_DIGIT +# undef URI_SET_HEX_LETTER_UPPER +# undef URI_SET_HEX_LETTER_LOWER +# undef URI_SET_HEXDIG +# undef URI_SET_ALPHA #endif diff --git a/ext/uri/uriparser/src/UriParseBase.c b/ext/uri/uriparser/src/UriParseBase.c index 3a4aa08f6b760..0ee66d4427e3b 100644 --- a/ext/uri/uriparser/src/UriParseBase.c +++ b/ext/uri/uriparser/src/UriParseBase.c @@ -38,53 +38,48 @@ */ #ifndef URI_DOXYGEN -# include "UriParseBase.h" +# include "UriParseBase.h" #endif +void uriWriteQuadToDoubleByte(const unsigned char * hexDigits, int digitCount, + unsigned char * output) { + switch (digitCount) { + case 1: + /* 0x___? -> \x00 \x0? */ + output[0] = 0; + output[1] = hexDigits[0]; + break; + case 2: + /* 0x__?? -> \0xx \x?? */ + output[0] = 0; + output[1] = 16 * hexDigits[0] + hexDigits[1]; + break; -void uriWriteQuadToDoubleByte(const unsigned char * hexDigits, int digitCount, unsigned char * output) { - switch (digitCount) { - case 1: - /* 0x___? -> \x00 \x0? */ - output[0] = 0; - output[1] = hexDigits[0]; - break; + case 3: + /* 0x_??? -> \0x? \x?? */ + output[0] = hexDigits[0]; + output[1] = 16 * hexDigits[1] + hexDigits[2]; + break; - case 2: - /* 0x__?? -> \0xx \x?? */ - output[0] = 0; - output[1] = 16 * hexDigits[0] + hexDigits[1]; - break; - - case 3: - /* 0x_??? -> \0x? \x?? */ - output[0] = hexDigits[0]; - output[1] = 16 * hexDigits[1] + hexDigits[2]; - break; - - case 4: - /* 0x???? -> \0?? \x?? */ - output[0] = 16 * hexDigits[0] + hexDigits[1]; - output[1] = 16 * hexDigits[2] + hexDigits[3]; - break; - - } + case 4: + /* 0x???? -> \0?? \x?? */ + output[0] = 16 * hexDigits[0] + hexDigits[1]; + output[1] = 16 * hexDigits[2] + hexDigits[3]; + break; + } } - - unsigned char uriGetOctetValue(const unsigned char * digits, int digitCount) { - switch (digitCount) { - case 1: - return digits[0]; - - case 2: - return 10 * digits[0] + digits[1]; + switch (digitCount) { + case 1: + return digits[0]; - case 3: - default: - return 100 * digits[0] + 10 * digits[1] + digits[2]; + case 2: + return 10 * digits[0] + digits[1]; - } + case 3: + default: + return 100 * digits[0] + 10 * digits[1] + digits[2]; + } } diff --git a/ext/uri/uriparser/src/UriParseBase.h b/ext/uri/uriparser/src/UriParseBase.h index 6d7379de1c0a9..cdb2c6f778790 100644 --- a/ext/uri/uriparser/src/UriParseBase.h +++ b/ext/uri/uriparser/src/UriParseBase.h @@ -38,18 +38,12 @@ */ #ifndef URI_PARSE_BASE_H -#define URI_PARSE_BASE_H 1 - - - -#include - +# define URI_PARSE_BASE_H 1 +# include void uriWriteQuadToDoubleByte(const unsigned char * hexDigits, int digitCount, - unsigned char * output); + unsigned char * output); unsigned char uriGetOctetValue(const unsigned char * digits, int digitCount); - - #endif /* URI_PARSE_BASE_H */ diff --git a/ext/uri/uriparser/src/UriQuery.c b/ext/uri/uriparser/src/UriQuery.c index bbc15488773c6..801a237a3a1b2 100644 --- a/ext/uri/uriparser/src/UriQuery.c +++ b/ext/uri/uriparser/src/UriQuery.c @@ -41,465 +41,427 @@ #include #if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) /* Include SELF twice */ -# ifdef URI_ENABLE_ANSI -# define URI_PASS_ANSI 1 -# include "UriQuery.c" -# undef URI_PASS_ANSI -# endif -# ifdef URI_ENABLE_UNICODE -# define URI_PASS_UNICODE 1 -# include "UriQuery.c" -# undef URI_PASS_UNICODE -# endif +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriQuery.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriQuery.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 -#include /* size_t */ - - +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif + +# ifndef URI_DOXYGEN +# include +# include "UriCommon.h" +# include "UriMemory.h" +# endif + +# include +# include /* size_t */ static int URI_FUNC(ComposeQueryEngine)(URI_CHAR * dest, - const URI_TYPE(QueryList) * queryList, - int maxChars, int * charsWritten, int * charsRequired, - UriBool spaceToPlus, UriBool normalizeBreaks); - -static UriBool URI_FUNC(AppendQueryItem)(URI_TYPE(QueryList) ** prevNext, - int * itemCount, const URI_CHAR * keyFirst, const URI_CHAR * keyAfter, - const URI_CHAR * valueFirst, const URI_CHAR * valueAfter, - UriBool plusToSpace, UriBreakConversion breakConversion, - UriMemoryManager * memory); - + const URI_TYPE(QueryList) * queryList, + int maxChars, int * charsWritten, + int * charsRequired, UriBool spaceToPlus, + UriBool normalizeBreaks); +static UriBool URI_FUNC(AppendQueryItem)( + URI_TYPE(QueryList) * *prevNext, int * itemCount, const URI_CHAR * keyFirst, + const URI_CHAR * keyAfter, const URI_CHAR * valueFirst, const URI_CHAR * valueAfter, + UriBool plusToSpace, UriBreakConversion breakConversion, UriMemoryManager * memory); int URI_FUNC(ComposeQueryCharsRequired)(const URI_TYPE(QueryList) * queryList, - int * charsRequired) { - const UriBool spaceToPlus = URI_TRUE; - const UriBool normalizeBreaks = URI_TRUE; + int * charsRequired) { + const UriBool spaceToPlus = URI_TRUE; + const UriBool normalizeBreaks = URI_TRUE; - return URI_FUNC(ComposeQueryCharsRequiredEx)(queryList, charsRequired, - spaceToPlus, normalizeBreaks); + return URI_FUNC(ComposeQueryCharsRequiredEx)(queryList, charsRequired, spaceToPlus, + normalizeBreaks); } - - int URI_FUNC(ComposeQueryCharsRequiredEx)(const URI_TYPE(QueryList) * queryList, - int * charsRequired, UriBool spaceToPlus, UriBool normalizeBreaks) { - if ((queryList == NULL) || (charsRequired == NULL)) { - return URI_ERROR_NULL; - } - - return URI_FUNC(ComposeQueryEngine)(NULL, queryList, 0, NULL, - charsRequired, spaceToPlus, normalizeBreaks); + int * charsRequired, UriBool spaceToPlus, + UriBool normalizeBreaks) { + if ((queryList == NULL) || (charsRequired == NULL)) { + return URI_ERROR_NULL; + } + + return URI_FUNC(ComposeQueryEngine)(NULL, queryList, 0, NULL, charsRequired, + spaceToPlus, normalizeBreaks); } +int URI_FUNC(ComposeQuery)(URI_CHAR * dest, const URI_TYPE(QueryList) * queryList, + int maxChars, int * charsWritten) { + const UriBool spaceToPlus = URI_TRUE; + const UriBool normalizeBreaks = URI_TRUE; - -int URI_FUNC(ComposeQuery)(URI_CHAR * dest, - const URI_TYPE(QueryList) * queryList, int maxChars, int * charsWritten) { - const UriBool spaceToPlus = URI_TRUE; - const UriBool normalizeBreaks = URI_TRUE; - - return URI_FUNC(ComposeQueryEx)(dest, queryList, maxChars, charsWritten, - spaceToPlus, normalizeBreaks); + return URI_FUNC(ComposeQueryEx)(dest, queryList, maxChars, charsWritten, spaceToPlus, + normalizeBreaks); } +int URI_FUNC(ComposeQueryEx)(URI_CHAR * dest, const URI_TYPE(QueryList) * queryList, + int maxChars, int * charsWritten, UriBool spaceToPlus, + UriBool normalizeBreaks) { + if ((dest == NULL) || (queryList == NULL)) { + return URI_ERROR_NULL; + } + if (maxChars < 1) { + return URI_ERROR_OUTPUT_TOO_LARGE; + } -int URI_FUNC(ComposeQueryEx)(URI_CHAR * dest, - const URI_TYPE(QueryList) * queryList, int maxChars, int * charsWritten, - UriBool spaceToPlus, UriBool normalizeBreaks) { - if ((dest == NULL) || (queryList == NULL)) { - return URI_ERROR_NULL; - } - - if (maxChars < 1) { - return URI_ERROR_OUTPUT_TOO_LARGE; - } - - return URI_FUNC(ComposeQueryEngine)(dest, queryList, maxChars, - charsWritten, NULL, spaceToPlus, normalizeBreaks); + return URI_FUNC(ComposeQueryEngine)(dest, queryList, maxChars, charsWritten, NULL, + spaceToPlus, normalizeBreaks); } - - int URI_FUNC(ComposeQueryMalloc)(URI_CHAR ** dest, - const URI_TYPE(QueryList) * queryList) { - const UriBool spaceToPlus = URI_TRUE; - const UriBool normalizeBreaks = URI_TRUE; + const URI_TYPE(QueryList) * queryList) { + const UriBool spaceToPlus = URI_TRUE; + const UriBool normalizeBreaks = URI_TRUE; - return URI_FUNC(ComposeQueryMallocEx)(dest, queryList, - spaceToPlus, normalizeBreaks); + return URI_FUNC(ComposeQueryMallocEx)(dest, queryList, spaceToPlus, normalizeBreaks); } - - int URI_FUNC(ComposeQueryMallocEx)(URI_CHAR ** dest, - const URI_TYPE(QueryList) * queryList, - UriBool spaceToPlus, UriBool normalizeBreaks) { - return URI_FUNC(ComposeQueryMallocExMm)(dest, queryList, spaceToPlus, - normalizeBreaks, NULL); + const URI_TYPE(QueryList) * queryList, + UriBool spaceToPlus, UriBool normalizeBreaks) { + return URI_FUNC(ComposeQueryMallocExMm)(dest, queryList, spaceToPlus, normalizeBreaks, + NULL); } - - int URI_FUNC(ComposeQueryMallocExMm)(URI_CHAR ** dest, - const URI_TYPE(QueryList) * queryList, - UriBool spaceToPlus, UriBool normalizeBreaks, - UriMemoryManager * memory) { - int charsRequired; - int res; - URI_CHAR * queryString; - - if (dest == NULL) { - return URI_ERROR_NULL; - } - - URI_CHECK_MEMORY_MANAGER(memory); /* may return */ - - /* Calculate space */ - res = URI_FUNC(ComposeQueryCharsRequiredEx)(queryList, &charsRequired, - spaceToPlus, normalizeBreaks); - if (res != URI_SUCCESS) { - return res; - } - if (charsRequired == INT_MAX) { - return URI_ERROR_MALLOC; - } - charsRequired++; - - /* Allocate space */ - queryString = memory->calloc(memory, charsRequired, sizeof(URI_CHAR)); - if (queryString == NULL) { - return URI_ERROR_MALLOC; - } - - /* Put query in */ - res = URI_FUNC(ComposeQueryEx)(queryString, queryList, charsRequired, - NULL, spaceToPlus, normalizeBreaks); - if (res != URI_SUCCESS) { - memory->free(memory, queryString); - return res; - } - - *dest = queryString; - return URI_SUCCESS; + const URI_TYPE(QueryList) * queryList, + UriBool spaceToPlus, UriBool normalizeBreaks, + UriMemoryManager * memory) { + int charsRequired; + int res; + URI_CHAR * queryString; + + if (dest == NULL) { + return URI_ERROR_NULL; + } + + URI_CHECK_MEMORY_MANAGER(memory); /* may return */ + + /* Calculate space */ + res = URI_FUNC(ComposeQueryCharsRequiredEx)(queryList, &charsRequired, spaceToPlus, + normalizeBreaks); + if (res != URI_SUCCESS) { + return res; + } + if (charsRequired == INT_MAX) { + return URI_ERROR_MALLOC; + } + charsRequired++; + + /* Allocate space */ + queryString = memory->calloc(memory, charsRequired, sizeof(URI_CHAR)); + if (queryString == NULL) { + return URI_ERROR_MALLOC; + } + + /* Put query in */ + res = URI_FUNC(ComposeQueryEx)(queryString, queryList, charsRequired, NULL, + spaceToPlus, normalizeBreaks); + if (res != URI_SUCCESS) { + memory->free(memory, queryString); + return res; + } + + *dest = queryString; + return URI_SUCCESS; } - - -int URI_FUNC(ComposeQueryEngine)(URI_CHAR * dest, - const URI_TYPE(QueryList) * queryList, - int maxChars, int * charsWritten, int * charsRequired, - UriBool spaceToPlus, UriBool normalizeBreaks) { - UriBool firstItem = URI_TRUE; - int ampersandLen = 0; /* increased to 1 from second item on */ - URI_CHAR * write = dest; - - /* Subtract terminator */ - if (dest == NULL) { - *charsRequired = 0; - } else { - maxChars--; - } - - while (queryList != NULL) { - const URI_CHAR * const key = queryList->key; - const URI_CHAR * const value = queryList->value; - const int worstCase = (normalizeBreaks == URI_TRUE ? 6 : 3); - const size_t keyLen = (key == NULL) ? 0 : URI_STRLEN(key); - int keyRequiredChars; - const size_t valueLen = (value == NULL) ? 0 : URI_STRLEN(value); - int valueRequiredChars; - - if ((keyLen >= (size_t)INT_MAX / worstCase) || (valueLen >= (size_t)INT_MAX / worstCase)) { - return URI_ERROR_OUTPUT_TOO_LARGE; - } - keyRequiredChars = worstCase * (int)keyLen; - valueRequiredChars = worstCase * (int)valueLen; - - if (dest == NULL) { - (*charsRequired) += ampersandLen + keyRequiredChars + ((value == NULL) - ? 0 - : 1 + valueRequiredChars); - - if (firstItem == URI_TRUE) { - ampersandLen = 1; - firstItem = URI_FALSE; - } - } else { - if ((write - dest) + ampersandLen + keyRequiredChars > maxChars) { - return URI_ERROR_OUTPUT_TOO_LARGE; - } - - /* Copy key */ - if (firstItem == URI_TRUE) { - ampersandLen = 1; - firstItem = URI_FALSE; - } else { - write[0] = _UT('&'); - write++; - } - write = URI_FUNC(EscapeEx)(key, key + keyLen, - write, spaceToPlus, normalizeBreaks); - - if (value != NULL) { - if ((write - dest) + 1 + valueRequiredChars > maxChars) { - return URI_ERROR_OUTPUT_TOO_LARGE; - } - - /* Copy value */ - write[0] = _UT('='); - write++; - write = URI_FUNC(EscapeEx)(value, value + valueLen, - write, spaceToPlus, normalizeBreaks); - } - } - - queryList = queryList->next; - } - - if (dest != NULL) { - write[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = (int)(write - dest) + 1; /* .. for terminator */ - } - } - - return URI_SUCCESS; +int URI_FUNC(ComposeQueryEngine)(URI_CHAR * dest, const URI_TYPE(QueryList) * queryList, + int maxChars, int * charsWritten, int * charsRequired, + UriBool spaceToPlus, UriBool normalizeBreaks) { + UriBool firstItem = URI_TRUE; + int ampersandLen = 0; /* increased to 1 from second item on */ + URI_CHAR * write = dest; + + /* Subtract terminator */ + if (dest == NULL) { + *charsRequired = 0; + } else { + maxChars--; + } + + while (queryList != NULL) { + const URI_CHAR * const key = queryList->key; + const URI_CHAR * const value = queryList->value; + const int worstCase = (normalizeBreaks == URI_TRUE ? 6 : 3); + const size_t keyLen = (key == NULL) ? 0 : URI_STRLEN(key); + int keyRequiredChars; + const size_t valueLen = (value == NULL) ? 0 : URI_STRLEN(value); + int valueRequiredChars; + + if ((keyLen >= (size_t)INT_MAX / worstCase) + || (valueLen >= (size_t)INT_MAX / worstCase)) { + return URI_ERROR_OUTPUT_TOO_LARGE; + } + keyRequiredChars = worstCase * (int)keyLen; + valueRequiredChars = worstCase * (int)valueLen; + + if (dest == NULL) { + (*charsRequired) += ampersandLen + keyRequiredChars + + ((value == NULL) ? 0 : 1 + valueRequiredChars); + + if (firstItem == URI_TRUE) { + ampersandLen = 1; + firstItem = URI_FALSE; + } + } else { + if ((write - dest) + ampersandLen + keyRequiredChars > maxChars) { + return URI_ERROR_OUTPUT_TOO_LARGE; + } + + /* Copy key */ + if (firstItem == URI_TRUE) { + ampersandLen = 1; + firstItem = URI_FALSE; + } else { + write[0] = _UT('&'); + write++; + } + write = URI_FUNC(EscapeEx)(key, key + keyLen, write, spaceToPlus, + normalizeBreaks); + + if (value != NULL) { + if ((write - dest) + 1 + valueRequiredChars > maxChars) { + return URI_ERROR_OUTPUT_TOO_LARGE; + } + + /* Copy value */ + write[0] = _UT('='); + write++; + write = URI_FUNC(EscapeEx)(value, value + valueLen, write, spaceToPlus, + normalizeBreaks); + } + } + + queryList = queryList->next; + } + + if (dest != NULL) { + write[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = (int)(write - dest) + 1; /* .. for terminator */ + } + } + + return URI_SUCCESS; } - - -UriBool URI_FUNC(AppendQueryItem)(URI_TYPE(QueryList) ** prevNext, - int * itemCount, const URI_CHAR * keyFirst, const URI_CHAR * keyAfter, - const URI_CHAR * valueFirst, const URI_CHAR * valueAfter, - UriBool plusToSpace, UriBreakConversion breakConversion, - UriMemoryManager * memory) { - const int keyLen = (int)(keyAfter - keyFirst); - const int valueLen = (int)(valueAfter - valueFirst); - URI_CHAR * key; - URI_CHAR * value; - - if ((prevNext == NULL) || (itemCount == NULL) - || (keyFirst == NULL) || (keyAfter == NULL) - || (keyFirst > keyAfter) || (valueFirst > valueAfter) - || ((keyFirst == keyAfter) - && (valueFirst == NULL) && (valueAfter == NULL))) { - return URI_TRUE; - } - - /* Append new empty item */ - *prevNext = memory->malloc(memory, 1 * sizeof(URI_TYPE(QueryList))); - if (*prevNext == NULL) { - return URI_FALSE; /* Raises malloc error */ - } - (*prevNext)->next = NULL; - - - /* Fill key */ - key = memory->malloc(memory, (keyLen + 1) * sizeof(URI_CHAR)); - if (key == NULL) { - memory->free(memory, *prevNext); - *prevNext = NULL; - return URI_FALSE; /* Raises malloc error */ - } - - key[keyLen] = _UT('\0'); - if (keyLen > 0) { - /* Copy 1:1 */ - memcpy(key, keyFirst, keyLen * sizeof(URI_CHAR)); - - /* Unescape */ - URI_FUNC(UnescapeInPlaceEx)(key, plusToSpace, breakConversion); - } - (*prevNext)->key = key; - - - /* Fill value */ - if (valueFirst != NULL) { - value = memory->malloc(memory, (valueLen + 1) * sizeof(URI_CHAR)); - if (value == NULL) { - memory->free(memory, key); - memory->free(memory, *prevNext); - *prevNext = NULL; - return URI_FALSE; /* Raises malloc error */ - } - - value[valueLen] = _UT('\0'); - if (valueLen > 0) { - /* Copy 1:1 */ - memcpy(value, valueFirst, valueLen * sizeof(URI_CHAR)); - - /* Unescape */ - URI_FUNC(UnescapeInPlaceEx)(value, plusToSpace, breakConversion); - } - (*prevNext)->value = value; - } else { - value = NULL; - } - (*prevNext)->value = value; - - (*itemCount)++; - return URI_TRUE; +UriBool URI_FUNC(AppendQueryItem)(URI_TYPE(QueryList) * *prevNext, int * itemCount, + const URI_CHAR * keyFirst, const URI_CHAR * keyAfter, + const URI_CHAR * valueFirst, + const URI_CHAR * valueAfter, UriBool plusToSpace, + UriBreakConversion breakConversion, + UriMemoryManager * memory) { + const int keyLen = (int)(keyAfter - keyFirst); + const int valueLen = (int)(valueAfter - valueFirst); + URI_CHAR * key; + URI_CHAR * value; + + if ((prevNext == NULL) || (itemCount == NULL) || (keyFirst == NULL) + || (keyAfter == NULL) || (keyFirst > keyAfter) || (valueFirst > valueAfter) + || ((keyFirst == keyAfter) && (valueFirst == NULL) && (valueAfter == NULL))) { + return URI_TRUE; + } + + /* Append new empty item */ + *prevNext = memory->malloc(memory, 1 * sizeof(URI_TYPE(QueryList))); + if (*prevNext == NULL) { + return URI_FALSE; /* Raises malloc error */ + } + (*prevNext)->next = NULL; + + /* Fill key */ + key = memory->malloc(memory, (keyLen + 1) * sizeof(URI_CHAR)); + if (key == NULL) { + memory->free(memory, *prevNext); + *prevNext = NULL; + return URI_FALSE; /* Raises malloc error */ + } + + key[keyLen] = _UT('\0'); + if (keyLen > 0) { + /* Copy 1:1 */ + memcpy(key, keyFirst, keyLen * sizeof(URI_CHAR)); + + /* Unescape */ + URI_FUNC(UnescapeInPlaceEx)(key, plusToSpace, breakConversion); + } + (*prevNext)->key = key; + + /* Fill value */ + if (valueFirst != NULL) { + value = memory->malloc(memory, (valueLen + 1) * sizeof(URI_CHAR)); + if (value == NULL) { + memory->free(memory, key); + memory->free(memory, *prevNext); + *prevNext = NULL; + return URI_FALSE; /* Raises malloc error */ + } + + value[valueLen] = _UT('\0'); + if (valueLen > 0) { + /* Copy 1:1 */ + memcpy(value, valueFirst, valueLen * sizeof(URI_CHAR)); + + /* Unescape */ + URI_FUNC(UnescapeInPlaceEx)(value, plusToSpace, breakConversion); + } + (*prevNext)->value = value; + } else { + value = NULL; + } + (*prevNext)->value = value; + + (*itemCount)++; + return URI_TRUE; } - - void URI_FUNC(FreeQueryList)(URI_TYPE(QueryList) * queryList) { - URI_FUNC(FreeQueryListMm)(queryList, NULL); + URI_FUNC(FreeQueryListMm)(queryList, NULL); } - - int URI_FUNC(FreeQueryListMm)(URI_TYPE(QueryList) * queryList, - UriMemoryManager * memory) { - URI_CHECK_MEMORY_MANAGER(memory); /* may return */ - while (queryList != NULL) { - URI_TYPE(QueryList) * nextBackup = queryList->next; - memory->free(memory, (URI_CHAR *)queryList->key); /* const cast */ - memory->free(memory, (URI_CHAR *)queryList->value); /* const cast */ - memory->free(memory, queryList); - queryList = nextBackup; - } - return URI_SUCCESS; + UriMemoryManager * memory) { + URI_CHECK_MEMORY_MANAGER(memory); /* may return */ + while (queryList != NULL) { + URI_TYPE(QueryList) * nextBackup = queryList->next; + memory->free(memory, (URI_CHAR *)queryList->key); /* const cast */ + memory->free(memory, (URI_CHAR *)queryList->value); /* const cast */ + memory->free(memory, queryList); + queryList = nextBackup; + } + return URI_SUCCESS; } +int URI_FUNC(DissectQueryMalloc)(URI_TYPE(QueryList) * *dest, int * itemCount, + const URI_CHAR * first, const URI_CHAR * afterLast) { + const UriBool plusToSpace = URI_TRUE; + const UriBreakConversion breakConversion = URI_BR_DONT_TOUCH; - -int URI_FUNC(DissectQueryMalloc)(URI_TYPE(QueryList) ** dest, int * itemCount, - const URI_CHAR * first, const URI_CHAR * afterLast) { - const UriBool plusToSpace = URI_TRUE; - const UriBreakConversion breakConversion = URI_BR_DONT_TOUCH; - - return URI_FUNC(DissectQueryMallocEx)(dest, itemCount, first, afterLast, - plusToSpace, breakConversion); + return URI_FUNC(DissectQueryMallocEx)(dest, itemCount, first, afterLast, plusToSpace, + breakConversion); } - - -int URI_FUNC(DissectQueryMallocEx)(URI_TYPE(QueryList) ** dest, int * itemCount, - const URI_CHAR * first, const URI_CHAR * afterLast, - UriBool plusToSpace, UriBreakConversion breakConversion) { - return URI_FUNC(DissectQueryMallocExMm)(dest, itemCount, first, afterLast, - plusToSpace, breakConversion, NULL); +int URI_FUNC(DissectQueryMallocEx)(URI_TYPE(QueryList) * *dest, int * itemCount, + const URI_CHAR * first, const URI_CHAR * afterLast, + UriBool plusToSpace, + UriBreakConversion breakConversion) { + return URI_FUNC(DissectQueryMallocExMm)(dest, itemCount, first, afterLast, + plusToSpace, breakConversion, NULL); } - - -int URI_FUNC(DissectQueryMallocExMm)(URI_TYPE(QueryList) ** dest, int * itemCount, - const URI_CHAR * first, const URI_CHAR * afterLast, - UriBool plusToSpace, UriBreakConversion breakConversion, - UriMemoryManager * memory) { - const URI_CHAR * walk = first; - const URI_CHAR * keyFirst = first; - const URI_CHAR * keyAfter = NULL; - const URI_CHAR * valueFirst = NULL; - const URI_CHAR * valueAfter = NULL; - URI_TYPE(QueryList) ** prevNext = dest; - int nullCounter; - int * itemsAppended = (itemCount == NULL) ? &nullCounter : itemCount; - - if ((dest == NULL) || (first == NULL) || (afterLast == NULL)) { - return URI_ERROR_NULL; - } - - if (first > afterLast) { - return URI_ERROR_RANGE_INVALID; - } - - URI_CHECK_MEMORY_MANAGER(memory); /* may return */ - - *dest = NULL; - *itemsAppended = 0; - - /* Parse query string */ - for (; walk < afterLast; walk++) { - switch (*walk) { - case _UT('&'): - if (valueFirst != NULL) { - valueAfter = walk; - } else { - keyAfter = walk; - } - - if (URI_FUNC(AppendQueryItem)(prevNext, itemsAppended, - keyFirst, keyAfter, valueFirst, valueAfter, - plusToSpace, breakConversion, memory) - == URI_FALSE) { - /* Free list we built */ - *itemsAppended = 0; - URI_FUNC(FreeQueryListMm)(*dest, memory); - return URI_ERROR_MALLOC; - } - - /* Make future items children of the current */ - if ((prevNext != NULL) && (*prevNext != NULL)) { - prevNext = &((*prevNext)->next); - } - - if (walk + 1 < afterLast) { - keyFirst = walk + 1; - } else { - keyFirst = NULL; - } - keyAfter = NULL; - valueFirst = NULL; - valueAfter = NULL; - break; - - case _UT('='): - /* NOTE: WE treat the first '=' as a separator, */ - /* all following go into the value part */ - if (keyAfter == NULL) { - keyAfter = walk; - if (walk + 1 <= afterLast) { - valueFirst = walk + 1; - valueAfter = walk + 1; - } - } - break; - - default: - break; - } - } - - if (valueFirst != NULL) { - /* Must be key/value pair */ - valueAfter = walk; - } else { - /* Must be key only */ - keyAfter = walk; - } - - if (URI_FUNC(AppendQueryItem)(prevNext, itemsAppended, keyFirst, keyAfter, - valueFirst, valueAfter, plusToSpace, breakConversion, memory) - == URI_FALSE) { - /* Free list we built */ - *itemsAppended = 0; - URI_FUNC(FreeQueryListMm)(*dest, memory); - return URI_ERROR_MALLOC; - } - - return URI_SUCCESS; +int URI_FUNC(DissectQueryMallocExMm)(URI_TYPE(QueryList) * *dest, int * itemCount, + const URI_CHAR * first, const URI_CHAR * afterLast, + UriBool plusToSpace, + UriBreakConversion breakConversion, + UriMemoryManager * memory) { + const URI_CHAR * walk = first; + const URI_CHAR * keyFirst = first; + const URI_CHAR * keyAfter = NULL; + const URI_CHAR * valueFirst = NULL; + const URI_CHAR * valueAfter = NULL; + URI_TYPE(QueryList) ** prevNext = dest; + int nullCounter; + int * itemsAppended = (itemCount == NULL) ? &nullCounter : itemCount; + + if ((dest == NULL) || (first == NULL) || (afterLast == NULL)) { + return URI_ERROR_NULL; + } + + if (first > afterLast) { + return URI_ERROR_RANGE_INVALID; + } + + URI_CHECK_MEMORY_MANAGER(memory); /* may return */ + + *dest = NULL; + *itemsAppended = 0; + + /* Parse query string */ + for (; walk < afterLast; walk++) { + switch (*walk) { + case _UT('&'): + if (valueFirst != NULL) { + valueAfter = walk; + } else { + keyAfter = walk; + } + + if (URI_FUNC(AppendQueryItem)(prevNext, itemsAppended, keyFirst, keyAfter, + valueFirst, valueAfter, plusToSpace, + breakConversion, memory) + == URI_FALSE) { + /* Free list we built */ + *itemsAppended = 0; + URI_FUNC(FreeQueryListMm)(*dest, memory); + return URI_ERROR_MALLOC; + } + + /* Make future items children of the current */ + if ((prevNext != NULL) && (*prevNext != NULL)) { + prevNext = &((*prevNext)->next); + } + + if (walk + 1 < afterLast) { + keyFirst = walk + 1; + } else { + keyFirst = NULL; + } + keyAfter = NULL; + valueFirst = NULL; + valueAfter = NULL; + break; + + case _UT('='): + /* NOTE: WE treat the first '=' as a separator, */ + /* all following go into the value part */ + if (keyAfter == NULL) { + keyAfter = walk; + if (walk + 1 <= afterLast) { + valueFirst = walk + 1; + valueAfter = walk + 1; + } + } + break; + + default: + break; + } + } + + if (valueFirst != NULL) { + /* Must be key/value pair */ + valueAfter = walk; + } else { + /* Must be key only */ + keyAfter = walk; + } + + if (URI_FUNC(AppendQueryItem)(prevNext, itemsAppended, keyFirst, keyAfter, valueFirst, + valueAfter, plusToSpace, breakConversion, memory) + == URI_FALSE) { + /* Free list we built */ + *itemsAppended = 0; + URI_FUNC(FreeQueryListMm)(*dest, memory); + return URI_ERROR_MALLOC; + } + + return URI_SUCCESS; } - - #endif diff --git a/ext/uri/uriparser/src/UriRecompose.c b/ext/uri/uriparser/src/UriRecompose.c index 1567efc81dcbf..61ffee77248f1 100644 --- a/ext/uri/uriparser/src/UriRecompose.c +++ b/ext/uri/uriparser/src/UriRecompose.c @@ -41,537 +41,564 @@ #include #if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) /* Include SELF twice */ -# ifdef URI_ENABLE_ANSI -# define URI_PASS_ANSI 1 -# include "UriRecompose.c" -# undef URI_PASS_ANSI -# endif -# ifdef URI_ENABLE_UNICODE -# define URI_PASS_UNICODE 1 -# include "UriRecompose.c" -# undef URI_PASS_UNICODE -# endif +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriRecompose.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriRecompose.c" +# undef URI_PASS_UNICODE +# endif #else -# ifdef URI_PASS_ANSI -# include -# else -# include -# include -# endif - - - -#ifndef URI_DOXYGEN -# include -# include "UriCommon.h" -#endif - - +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif + +# ifndef URI_DOXYGEN +# include +# include "UriCommon.h" +# endif static int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(Uri) * uri, - int maxChars, int * charsWritten, int * charsRequired); - + int maxChars, int * charsWritten, + int * charsRequired); - -int URI_FUNC(ToStringCharsRequired)(const URI_TYPE(Uri) * uri, - int * charsRequired) { - const int MAX_CHARS = ((unsigned int)-1) >> 1; - return URI_FUNC(ToStringEngine)(NULL, uri, MAX_CHARS, NULL, charsRequired); +int URI_FUNC(ToStringCharsRequired)(const URI_TYPE(Uri) * uri, int * charsRequired) { + const int MAX_CHARS = ((unsigned int)-1) >> 1; + return URI_FUNC(ToStringEngine)(NULL, uri, MAX_CHARS, NULL, charsRequired); } - - -int URI_FUNC(ToString)(URI_CHAR * dest, const URI_TYPE(Uri) * uri, - int maxChars, int * charsWritten) { - return URI_FUNC(ToStringEngine)(dest, uri, maxChars, charsWritten, NULL); +int URI_FUNC(ToString)(URI_CHAR * dest, const URI_TYPE(Uri) * uri, int maxChars, + int * charsWritten) { + return URI_FUNC(ToStringEngine)(dest, uri, maxChars, charsWritten, NULL); } - - -static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest, - const URI_TYPE(Uri) * uri, int maxChars, int * charsWritten, - int * charsRequired) { - int written = 0; - if ((uri == NULL) || ((dest == NULL) && (charsRequired == NULL))) { - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_NULL; - } - - if (maxChars < 1) { - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - maxChars--; /* So we don't have to subtract 1 for '\0' all the time */ - - /* [01/19] result = "" */ - if (dest != NULL) { - dest[0] = _UT('\0'); - } else { - (*charsRequired) = 0; - } - /* [02/19] if defined(scheme) then */ - if (uri->scheme.first != NULL) { - /* [03/19] append scheme to result; */ - const int charsToWrite - = (int)(uri->scheme.afterLast - uri->scheme.first); - if (dest != NULL) { - if (written + charsToWrite <= maxChars) { - memcpy(dest + written, uri->scheme.first, - charsToWrite * sizeof(URI_CHAR)); - written += charsToWrite; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - } else { - (*charsRequired) += charsToWrite; - } - /* [04/19] append ":" to result; */ - if (dest != NULL) { - if (written + 1 <= maxChars) { - memcpy(dest + written, _UT(":"), - 1 * sizeof(URI_CHAR)); - written += 1; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - } else { - (*charsRequired) += 1; - } - /* [05/19] endif; */ - } - /* [06/19] if defined(authority) then */ - if (URI_FUNC(HasHost)(uri)) { - /* [07/19] append "//" to result; */ - if (dest != NULL) { - if (written + 2 <= maxChars) { - memcpy(dest + written, _UT("//"), - 2 * sizeof(URI_CHAR)); - written += 2; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - } else { - (*charsRequired) += 2; - } - /* [08/19] append authority to result; */ - /* UserInfo */ - if (uri->userInfo.first != NULL) { - const int charsToWrite = (int)(uri->userInfo.afterLast - uri->userInfo.first); - if (dest != NULL) { - if (written + charsToWrite <= maxChars) { - memcpy(dest + written, uri->userInfo.first, - charsToWrite * sizeof(URI_CHAR)); - written += charsToWrite; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - - if (written + 1 <= maxChars) { - memcpy(dest + written, _UT("@"), - 1 * sizeof(URI_CHAR)); - written += 1; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - } else { - (*charsRequired) += charsToWrite + 1; - } - } - - /* Host */ - if (uri->hostData.ip4 != NULL) { - /* IPv4 */ - int i = 0; - for (; i < 4; i++) { - const unsigned char value = uri->hostData.ip4->data[i]; - const int charsToWrite = (value > 99) ? 3 : ((value > 9) ? 2 : 1); - if (dest != NULL) { - if (written + charsToWrite <= maxChars) { - URI_CHAR text[4]; - if (value > 99) { - text[0] = _UT('0') + (value / 100); - text[1] = _UT('0') + ((value % 100) / 10); - text[2] = _UT('0') + (value % 10); - } else if (value > 9) { - text[0] = _UT('0') + (value / 10); - text[1] = _UT('0') + (value % 10); - } else { - text[0] = _UT('0') + value; - } - text[charsToWrite] = _UT('\0'); - memcpy(dest + written, text, charsToWrite * sizeof(URI_CHAR)); - written += charsToWrite; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - if (i < 3) { - if (written + 1 <= maxChars) { - memcpy(dest + written, _UT("."), - 1 * sizeof(URI_CHAR)); - written += 1; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - } - } else { - (*charsRequired) += charsToWrite + ((i == 3) ? 0 : 1); - } - } - } else if (uri->hostData.ip6 != NULL) { - /* IPv6 */ - int i = 0; - if (dest != NULL) { - if (written + 1 <= maxChars) { - memcpy(dest + written, _UT("["), - 1 * sizeof(URI_CHAR)); - written += 1; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - } else { - (*charsRequired) += 1; - } - - for (; i < 16; i++) { - const unsigned char value = uri->hostData.ip6->data[i]; - if (dest != NULL) { - if (written + 2 <= maxChars) { - URI_CHAR text[3]; - text[0] = URI_FUNC(HexToLetterEx)(value / 16, URI_FALSE); - text[1] = URI_FUNC(HexToLetterEx)(value % 16, URI_FALSE); - text[2] = _UT('\0'); - memcpy(dest + written, text, 2 * sizeof(URI_CHAR)); - written += 2; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - } else { - (*charsRequired) += 2; - } - if (((i & 1) == 1) && (i < 15)) { - if (dest != NULL) { - if (written + 1 <= maxChars) { - memcpy(dest + written, _UT(":"), - 1 * sizeof(URI_CHAR)); - written += 1; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - } else { - (*charsRequired) += 1; - } - } - } - - if (dest != NULL) { - if (written + 1 <= maxChars) { - memcpy(dest + written, _UT("]"), - 1 * sizeof(URI_CHAR)); - written += 1; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - } else { - (*charsRequired) += 1; - } - } else if (uri->hostData.ipFuture.first != NULL) { - /* IPvFuture */ - const int charsToWrite = (int)(uri->hostData.ipFuture.afterLast - - uri->hostData.ipFuture.first); - if (dest != NULL) { - if (written + 1 <= maxChars) { - memcpy(dest + written, _UT("["), - 1 * sizeof(URI_CHAR)); - written += 1; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - - if (written + charsToWrite <= maxChars) { - memcpy(dest + written, uri->hostData.ipFuture.first, charsToWrite * sizeof(URI_CHAR)); - written += charsToWrite; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - - if (written + 1 <= maxChars) { - memcpy(dest + written, _UT("]"), - 1 * sizeof(URI_CHAR)); - written += 1; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - } else { - (*charsRequired) += 1 + charsToWrite + 1; - } - } else if (uri->hostText.first != NULL) { - /* Regname */ - const int charsToWrite = (int)(uri->hostText.afterLast - uri->hostText.first); - if (dest != NULL) { - if (written + charsToWrite <= maxChars) { - memcpy(dest + written, uri->hostText.first, - charsToWrite * sizeof(URI_CHAR)); - written += charsToWrite; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - } else { - (*charsRequired) += charsToWrite; - } - } - - /* Port */ - if (uri->portText.first != NULL) { - const int charsToWrite = (int)(uri->portText.afterLast - uri->portText.first); - if (dest != NULL) { - /* Leading ':' */ - if (written + 1 <= maxChars) { - memcpy(dest + written, _UT(":"), - 1 * sizeof(URI_CHAR)); - written += 1; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - - /* Port number */ - if (written + charsToWrite <= maxChars) { - memcpy(dest + written, uri->portText.first, - charsToWrite * sizeof(URI_CHAR)); - written += charsToWrite; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - } else { - (*charsRequired) += 1 + charsToWrite; - } - } - /* [09/19] endif; */ - } - /* [10/19] append path to result; */ - /* Slash needed here? */ - if (uri->absolutePath || ((uri->pathHead != NULL) - && URI_FUNC(HasHost)(uri))) { - if (dest != NULL) { - if (written + 1 <= maxChars) { - memcpy(dest + written, _UT("/"), - 1 * sizeof(URI_CHAR)); - written += 1; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - } else { - (*charsRequired) += 1; - } - } - - if (uri->pathHead != NULL) { - URI_TYPE(PathSegment) * walker = uri->pathHead; - do { - const int charsToWrite = (int)(walker->text.afterLast - walker->text.first); - if (dest != NULL) { - if (written + charsToWrite <= maxChars) { - memcpy(dest + written, walker->text.first, - charsToWrite * sizeof(URI_CHAR)); - written += charsToWrite; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - } else { - (*charsRequired) += charsToWrite; - } - - /* Not last segment -> append slash */ - if (walker->next != NULL) { - if (dest != NULL) { - if (written + 1 <= maxChars) { - memcpy(dest + written, _UT("/"), - 1 * sizeof(URI_CHAR)); - written += 1; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - } else { - (*charsRequired) += 1; - } - } - - walker = walker->next; - } while (walker != NULL); - } - /* [11/19] if defined(query) then */ - if (uri->query.first != NULL) { - /* [12/19] append "?" to result; */ - if (dest != NULL) { - if (written + 1 <= maxChars) { - memcpy(dest + written, _UT("?"), - 1 * sizeof(URI_CHAR)); - written += 1; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - } else { - (*charsRequired) += 1; - } - /* [13/19] append query to result; */ - { - const int charsToWrite - = (int)(uri->query.afterLast - uri->query.first); - if (dest != NULL) { - if (written + charsToWrite <= maxChars) { - memcpy(dest + written, uri->query.first, - charsToWrite * sizeof(URI_CHAR)); - written += charsToWrite; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - } else { - (*charsRequired) += charsToWrite; - } - } - /* [14/19] endif; */ - } - /* [15/19] if defined(fragment) then */ - if (uri->fragment.first != NULL) { - /* [16/19] append "#" to result; */ - if (dest != NULL) { - if (written + 1 <= maxChars) { - memcpy(dest + written, _UT("#"), - 1 * sizeof(URI_CHAR)); - written += 1; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - } else { - (*charsRequired) += 1; - } - /* [17/19] append fragment to result; */ - { - const int charsToWrite - = (int)(uri->fragment.afterLast - uri->fragment.first); - if (dest != NULL) { - if (written + charsToWrite <= maxChars) { - memcpy(dest + written, uri->fragment.first, - charsToWrite * sizeof(URI_CHAR)); - written += charsToWrite; - } else { - dest[0] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = 0; - } - return URI_ERROR_TOSTRING_TOO_LONG; - } - } else { - (*charsRequired) += charsToWrite; - } - } - /* [18/19] endif; */ - } - /* [19/19] return result; */ - if (dest != NULL) { - dest[written++] = _UT('\0'); - if (charsWritten != NULL) { - *charsWritten = written; - } - } - return URI_SUCCESS; +static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(Uri) * uri, + int maxChars, int * charsWritten, + int * charsRequired) { + int written = 0; + if ((uri == NULL) || ((dest == NULL) && (charsRequired == NULL))) { + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_NULL; + } + + if (maxChars < 1) { + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + maxChars--; /* So we don't have to subtract 1 for '\0' all the time */ + + /* NOTE: The curly brackets here force deeper indent (and that's all) */ + { + { + { + /* clang-format off */ + /* [01/19] result = "" */ + /* clang-format on */ + if (dest != NULL) { + dest[0] = _UT('\0'); + } else { + (*charsRequired) = 0; + } + /* clang-format off */ + /* [02/19] if defined(scheme) then */ + /* clang-format on */ + if (uri->scheme.first != NULL) { + /* clang-format off */ + /* [03/19] append scheme to result; */ + /* clang-format on */ + const int charsToWrite = + (int)(uri->scheme.afterLast - uri->scheme.first); + if (dest != NULL) { + if (written + charsToWrite <= maxChars) { + memcpy(dest + written, uri->scheme.first, + charsToWrite * sizeof(URI_CHAR)); + written += charsToWrite; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + } else { + (*charsRequired) += charsToWrite; + } + /* clang-format off */ + /* [04/19] append ":" to result; */ + /* clang-format on */ + if (dest != NULL) { + if (written + 1 <= maxChars) { + memcpy(dest + written, _UT(":"), 1 * sizeof(URI_CHAR)); + written += 1; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + } else { + (*charsRequired) += 1; + } + /* clang-format off */ + /* [05/19] endif; */ + /* clang-format on */ + } + /* clang-format off */ + /* [06/19] if defined(authority) then */ + /* clang-format on */ + if (URI_FUNC(HasHost)(uri)) { + /* clang-format off */ + /* [07/19] append "//" to result; */ + /* clang-format on */ + if (dest != NULL) { + if (written + 2 <= maxChars) { + memcpy(dest + written, _UT("//"), 2 * sizeof(URI_CHAR)); + written += 2; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + } else { + (*charsRequired) += 2; + } + /* clang-format off */ + /* [08/19] append authority to result; */ + /* clang-format on */ + /* UserInfo */ + if (uri->userInfo.first != NULL) { + const int charsToWrite = + (int)(uri->userInfo.afterLast - uri->userInfo.first); + if (dest != NULL) { + if (written + charsToWrite <= maxChars) { + memcpy(dest + written, uri->userInfo.first, + charsToWrite * sizeof(URI_CHAR)); + written += charsToWrite; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + + if (written + 1 <= maxChars) { + memcpy(dest + written, _UT("@"), 1 * sizeof(URI_CHAR)); + written += 1; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + } else { + (*charsRequired) += charsToWrite + 1; + } + } + + /* Host */ + if (uri->hostData.ip4 != NULL) { + /* IPv4 */ + int i = 0; + for (; i < 4; i++) { + const unsigned char value = uri->hostData.ip4->data[i]; + const int charsToWrite = + (value > 99) ? 3 : ((value > 9) ? 2 : 1); + if (dest != NULL) { + if (written + charsToWrite <= maxChars) { + URI_CHAR text[4]; + if (value > 99) { + text[0] = _UT('0') + (value / 100); + text[1] = _UT('0') + ((value % 100) / 10); + text[2] = _UT('0') + (value % 10); + } else if (value > 9) { + text[0] = _UT('0') + (value / 10); + text[1] = _UT('0') + (value % 10); + } else { + text[0] = _UT('0') + value; + } + text[charsToWrite] = _UT('\0'); + memcpy(dest + written, text, + charsToWrite * sizeof(URI_CHAR)); + written += charsToWrite; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + if (i < 3) { + if (written + 1 <= maxChars) { + memcpy(dest + written, _UT("."), + 1 * sizeof(URI_CHAR)); + written += 1; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + } + } else { + (*charsRequired) += charsToWrite + ((i == 3) ? 0 : 1); + } + } + } else if (uri->hostData.ip6 != NULL) { + /* IPv6 */ + int i = 0; + if (dest != NULL) { + if (written + 1 <= maxChars) { + memcpy(dest + written, _UT("["), 1 * sizeof(URI_CHAR)); + written += 1; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + } else { + (*charsRequired) += 1; + } + + for (; i < 16; i++) { + const unsigned char value = uri->hostData.ip6->data[i]; + if (dest != NULL) { + if (written + 2 <= maxChars) { + URI_CHAR text[3]; + text[0] = + URI_FUNC(HexToLetterEx)(value / 16, URI_FALSE); + text[1] = + URI_FUNC(HexToLetterEx)(value % 16, URI_FALSE); + text[2] = _UT('\0'); + memcpy(dest + written, text, 2 * sizeof(URI_CHAR)); + written += 2; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + } else { + (*charsRequired) += 2; + } + if (((i & 1) == 1) && (i < 15)) { + if (dest != NULL) { + if (written + 1 <= maxChars) { + memcpy(dest + written, _UT(":"), + 1 * sizeof(URI_CHAR)); + written += 1; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + } else { + (*charsRequired) += 1; + } + } + } + + if (dest != NULL) { + if (written + 1 <= maxChars) { + memcpy(dest + written, _UT("]"), 1 * sizeof(URI_CHAR)); + written += 1; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + } else { + (*charsRequired) += 1; + } + } else if (uri->hostData.ipFuture.first != NULL) { + /* IPvFuture */ + const int charsToWrite = (int)(uri->hostData.ipFuture.afterLast + - uri->hostData.ipFuture.first); + if (dest != NULL) { + if (written + 1 <= maxChars) { + memcpy(dest + written, _UT("["), 1 * sizeof(URI_CHAR)); + written += 1; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + + if (written + charsToWrite <= maxChars) { + memcpy(dest + written, uri->hostData.ipFuture.first, + charsToWrite * sizeof(URI_CHAR)); + written += charsToWrite; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + + if (written + 1 <= maxChars) { + memcpy(dest + written, _UT("]"), 1 * sizeof(URI_CHAR)); + written += 1; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + } else { + (*charsRequired) += 1 + charsToWrite + 1; + } + } else if (uri->hostText.first != NULL) { + /* Regname */ + const int charsToWrite = + (int)(uri->hostText.afterLast - uri->hostText.first); + if (dest != NULL) { + if (written + charsToWrite <= maxChars) { + memcpy(dest + written, uri->hostText.first, + charsToWrite * sizeof(URI_CHAR)); + written += charsToWrite; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + } else { + (*charsRequired) += charsToWrite; + } + } + + /* Port */ + if (uri->portText.first != NULL) { + const int charsToWrite = + (int)(uri->portText.afterLast - uri->portText.first); + if (dest != NULL) { + /* Leading ':' */ + if (written + 1 <= maxChars) { + memcpy(dest + written, _UT(":"), 1 * sizeof(URI_CHAR)); + written += 1; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + + /* Port number */ + if (written + charsToWrite <= maxChars) { + memcpy(dest + written, uri->portText.first, + charsToWrite * sizeof(URI_CHAR)); + written += charsToWrite; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + } else { + (*charsRequired) += 1 + charsToWrite; + } + } + /* clang-format off */ + /* [09/19] endif; */ + /* clang-format on */ + } + /* clang-format off */ + /* [10/19] append path to result; */ + /* clang-format on */ + /* Slash needed here? */ + if (uri->absolutePath + || ((uri->pathHead != NULL) && URI_FUNC(HasHost)(uri))) { + if (dest != NULL) { + if (written + 1 <= maxChars) { + memcpy(dest + written, _UT("/"), 1 * sizeof(URI_CHAR)); + written += 1; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + } else { + (*charsRequired) += 1; + } + } + + if (uri->pathHead != NULL) { + URI_TYPE(PathSegment) * walker = uri->pathHead; + do { + const int charsToWrite = + (int)(walker->text.afterLast - walker->text.first); + if (dest != NULL) { + if (written + charsToWrite <= maxChars) { + memcpy(dest + written, walker->text.first, + charsToWrite * sizeof(URI_CHAR)); + written += charsToWrite; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + } else { + (*charsRequired) += charsToWrite; + } + + /* Not last segment -> append slash */ + if (walker->next != NULL) { + if (dest != NULL) { + if (written + 1 <= maxChars) { + memcpy(dest + written, _UT("/"), + 1 * sizeof(URI_CHAR)); + written += 1; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + } else { + (*charsRequired) += 1; + } + } + + walker = walker->next; + } while (walker != NULL); + } + /* clang-format off */ + /* [11/19] if defined(query) then */ + /* clang-format on */ + if (uri->query.first != NULL) { + /* clang-format off */ + /* [12/19] append "?" to result; */ + /* clang-format on */ + if (dest != NULL) { + if (written + 1 <= maxChars) { + memcpy(dest + written, _UT("?"), 1 * sizeof(URI_CHAR)); + written += 1; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + } else { + (*charsRequired) += 1; + } + /* clang-format off */ + /* [13/19] append query to result; */ + /* clang-format on */ + const int charsToWrite = + (int)(uri->query.afterLast - uri->query.first); + if (dest != NULL) { + if (written + charsToWrite <= maxChars) { + memcpy(dest + written, uri->query.first, + charsToWrite * sizeof(URI_CHAR)); + written += charsToWrite; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + } else { + (*charsRequired) += charsToWrite; + } + /* clang-format off */ + /* [14/19] endif; */ + /* clang-format on */ + } + /* clang-format off */ + /* [15/19] if defined(fragment) then */ + /* clang-format on */ + if (uri->fragment.first != NULL) { + /* clang-format off */ + /* [16/19] append "#" to result; */ + /* clang-format on */ + if (dest != NULL) { + if (written + 1 <= maxChars) { + memcpy(dest + written, _UT("#"), 1 * sizeof(URI_CHAR)); + written += 1; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + } else { + (*charsRequired) += 1; + } + /* clang-format off */ + /* [17/19] append fragment to result; */ + /* clang-format on */ + const int charsToWrite = + (int)(uri->fragment.afterLast - uri->fragment.first); + if (dest != NULL) { + if (written + charsToWrite <= maxChars) { + memcpy(dest + written, uri->fragment.first, + charsToWrite * sizeof(URI_CHAR)); + written += charsToWrite; + } else { + dest[0] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = 0; + } + return URI_ERROR_TOSTRING_TOO_LONG; + } + } else { + (*charsRequired) += charsToWrite; + } + /* clang-format off */ + /* [18/19] endif; */ + /* clang-format on */ + } + /* clang-format off */ + /* [19/19] return result; */ + /* clang-format on */ + if (dest != NULL) { + dest[written++] = _UT('\0'); + if (charsWritten != NULL) { + *charsWritten = written; + } + } + return URI_SUCCESS; + } + } + } } - - #endif diff --git a/ext/uri/uriparser/src/UriResolve.c b/ext/uri/uriparser/src/UriResolve.c index 8e47e6af8c6f9..302665d21cd66 100644 --- a/ext/uri/uriparser/src/UriResolve.c +++ b/ext/uri/uriparser/src/UriResolve.c @@ -41,289 +41,358 @@ #include #if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) /* Include SELF twice */ -# ifdef URI_ENABLE_ANSI -# define URI_PASS_ANSI 1 -# include "UriResolve.c" -# undef URI_PASS_ANSI -# endif -# ifdef URI_ENABLE_UNICODE -# define URI_PASS_UNICODE 1 -# include "UriResolve.c" -# undef URI_PASS_UNICODE -# endif +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriResolve.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriResolve.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 - - +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif + +# ifndef URI_DOXYGEN +# include +# include "UriCommon.h" +# include "UriMemory.h" +# endif /* Appends a relative URI to an absolute. The last path segment of * the absolute URI is replaced. */ static URI_INLINE UriBool URI_FUNC(MergePath)(URI_TYPE(Uri) * absWork, - const URI_TYPE(Uri) * relAppend, UriMemoryManager * memory) { - URI_TYPE(PathSegment) * sourceWalker; - URI_TYPE(PathSegment) * destPrev; - if (relAppend->pathHead == NULL) { - return URI_TRUE; - } - - /* Replace last segment ("" if trailing slash) with first of append chain */ - if (absWork->pathHead == NULL) { - URI_TYPE(PathSegment) * const dup = memory->malloc(memory, sizeof(URI_TYPE(PathSegment))); - if (dup == NULL) { - return URI_FALSE; /* Raises malloc error */ - } - dup->next = NULL; - absWork->pathHead = dup; - absWork->pathTail = dup; - } - absWork->pathTail->text.first = relAppend->pathHead->text.first; - absWork->pathTail->text.afterLast = relAppend->pathHead->text.afterLast; - - /* Append all the others */ - sourceWalker = relAppend->pathHead->next; - if (sourceWalker == NULL) { - return URI_TRUE; - } - destPrev = absWork->pathTail; - - for (;;) { - URI_TYPE(PathSegment) * const dup = memory->malloc(memory, sizeof(URI_TYPE(PathSegment))); - if (dup == NULL) { - destPrev->next = NULL; - absWork->pathTail = destPrev; - return URI_FALSE; /* Raises malloc error */ - } - dup->text = sourceWalker->text; - destPrev->next = dup; - - if (sourceWalker->next == NULL) { - absWork->pathTail = dup; - absWork->pathTail->next = NULL; - break; - } - destPrev = dup; - sourceWalker = sourceWalker->next; - } - - return URI_TRUE; + const URI_TYPE(Uri) * relAppend, + UriMemoryManager * memory) { + URI_TYPE(PathSegment) * sourceWalker; + URI_TYPE(PathSegment) * destPrev; + if (relAppend->pathHead == NULL) { + return URI_TRUE; + } + + /* Replace last segment ("" if trailing slash) with first of append chain */ + if (absWork->pathHead == NULL) { + URI_TYPE(PathSegment) * const dup = + memory->malloc(memory, sizeof(URI_TYPE(PathSegment))); + if (dup == NULL) { + return URI_FALSE; /* Raises malloc error */ + } + dup->next = NULL; + absWork->pathHead = dup; + absWork->pathTail = dup; + } + absWork->pathTail->text.first = relAppend->pathHead->text.first; + absWork->pathTail->text.afterLast = relAppend->pathHead->text.afterLast; + + /* Append all the others */ + sourceWalker = relAppend->pathHead->next; + if (sourceWalker == NULL) { + return URI_TRUE; + } + destPrev = absWork->pathTail; + + for (;;) { + URI_TYPE(PathSegment) * const dup = + memory->malloc(memory, sizeof(URI_TYPE(PathSegment))); + if (dup == NULL) { + destPrev->next = NULL; + absWork->pathTail = destPrev; + return URI_FALSE; /* Raises malloc error */ + } + dup->text = sourceWalker->text; + destPrev->next = dup; + + if (sourceWalker->next == NULL) { + absWork->pathTail = dup; + absWork->pathTail->next = NULL; + break; + } + destPrev = dup; + sourceWalker = sourceWalker->next; + } + + return URI_TRUE; } - static int URI_FUNC(ResolveAbsolutePathFlag)(URI_TYPE(Uri) * absWork, - UriMemoryManager * memory) { - if (absWork == NULL) { - return URI_ERROR_NULL; - } - - 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))); - if (segment == NULL) { - return URI_ERROR_MALLOC; - } - segment->text.first = URI_FUNC(SafeToPointTo); - segment->text.afterLast = URI_FUNC(SafeToPointTo); - segment->next = NULL; - - absWork->pathHead = segment; - absWork->pathTail = segment; - } - - absWork->absolutePath = URI_FALSE; - } - - return URI_SUCCESS; + UriMemoryManager * memory) { + if (absWork == NULL) { + return URI_ERROR_NULL; + } + + 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))); + if (segment == NULL) { + return URI_ERROR_MALLOC; + } + segment->text.first = URI_FUNC(SafeToPointTo); + segment->text.afterLast = URI_FUNC(SafeToPointTo); + segment->next = NULL; + + absWork->pathHead = segment; + absWork->pathTail = segment; + } + + absWork->absolutePath = URI_FALSE; + } + + return URI_SUCCESS; } - static int URI_FUNC(AddBaseUriImpl)(URI_TYPE(Uri) * absDest, - const URI_TYPE(Uri) * relSource, - const URI_TYPE(Uri) * absBase, - UriResolutionOptions options, UriMemoryManager * memory) { - UriBool relSourceHasScheme; - - if (absDest == NULL) { - return URI_ERROR_NULL; - } - URI_FUNC(ResetUri)(absDest); - - if ((relSource == NULL) || (absBase == NULL)) { - return URI_ERROR_NULL; - } - - /* absBase absolute? */ - if (absBase->scheme.first == NULL) { - return URI_ERROR_ADDBASE_REL_BASE; - } - - /* [00/32] -- A non-strict parser may ignore a scheme in the reference */ - /* [00/32] -- if it is identical to the base URI's scheme. */ - /* [00/32] if ((not strict) and (R.scheme == Base.scheme)) then */ - relSourceHasScheme = (relSource->scheme.first != NULL) ? URI_TRUE : URI_FALSE; - if ((options & URI_RESOLVE_IDENTICAL_SCHEME_COMPAT) - && (absBase->scheme.first != NULL) - && (relSource->scheme.first != NULL) - && (0 == URI_FUNC(CompareRange)(&(absBase->scheme), &(relSource->scheme)))) { - /* [00/32] undefine(R.scheme); */ - relSourceHasScheme = URI_FALSE; - /* [00/32] endif; */ - } - - /* [01/32] if defined(R.scheme) then */ - if (relSourceHasScheme) { - /* [02/32] T.scheme = R.scheme; */ - absDest->scheme = relSource->scheme; - /* [03/32] T.authority = R.authority; */ - if (!URI_FUNC(CopyAuthority)(absDest, relSource, memory)) { - return URI_ERROR_MALLOC; - } - /* [04/32] T.path = remove_dot_segments(R.path); */ - if (!URI_FUNC(CopyPath)(absDest, relSource, memory)) { - return URI_ERROR_MALLOC; - } - if (!URI_FUNC(RemoveDotSegmentsAbsolute)(absDest, memory)) { - return URI_ERROR_MALLOC; - } - /* [05/32] T.query = R.query; */ - absDest->query = relSource->query; - /* [06/32] else */ - } else { - /* [07/32] if defined(R.authority) then */ - if (URI_FUNC(HasHost)(relSource)) { - /* [08/32] T.authority = R.authority; */ - if (!URI_FUNC(CopyAuthority)(absDest, relSource, memory)) { - return URI_ERROR_MALLOC; - } - /* [09/32] T.path = remove_dot_segments(R.path); */ - if (!URI_FUNC(CopyPath)(absDest, relSource, memory)) { - return URI_ERROR_MALLOC; - } - if (!URI_FUNC(RemoveDotSegmentsAbsolute)(absDest, memory)) { - return URI_ERROR_MALLOC; - } - /* [10/32] T.query = R.query; */ - absDest->query = relSource->query; - /* [11/32] else */ - } else { - /* [28/32] T.authority = Base.authority; */ - if (!URI_FUNC(CopyAuthority)(absDest, absBase, memory)) { - return URI_ERROR_MALLOC; - } - /* [12/32] if (R.path == "") then */ - if (relSource->pathHead == NULL && !relSource->absolutePath) { - /* [13/32] T.path = Base.path; */ - if (!URI_FUNC(CopyPath)(absDest, absBase, memory)) { - return URI_ERROR_MALLOC; - } - /* [14/32] if defined(R.query) then */ - if (relSource->query.first != NULL) { - /* [15/32] T.query = R.query; */ - absDest->query = relSource->query; - /* [16/32] else */ - } else { - /* [17/32] T.query = Base.query; */ - absDest->query = absBase->query; - /* [18/32] endif; */ - } - /* [19/32] else */ - } else { - /* [20/32] if (R.path starts-with "/") then */ - if (relSource->absolutePath) { - int res; - /* [21/32] T.path = remove_dot_segments(R.path); */ - if (!URI_FUNC(CopyPath)(absDest, relSource, memory)) { - return URI_ERROR_MALLOC; - } - res = URI_FUNC(ResolveAbsolutePathFlag)(absDest, memory); - if (res != URI_SUCCESS) { - return res; - } - if (!URI_FUNC(RemoveDotSegmentsAbsolute)(absDest, memory)) { - return URI_ERROR_MALLOC; - } - /* [22/32] else */ - } else { - /* [23/32] T.path = merge(Base.path, R.path); */ - if (!URI_FUNC(CopyPath)(absDest, absBase, memory)) { - return URI_ERROR_MALLOC; - } - if (!URI_FUNC(MergePath)(absDest, relSource, memory)) { - return URI_ERROR_MALLOC; - } - /* [24/32] T.path = remove_dot_segments(T.path); */ - if (!URI_FUNC(RemoveDotSegmentsAbsolute)(absDest, memory)) { - return URI_ERROR_MALLOC; - } - - if (!URI_FUNC(FixAmbiguity)(absDest, memory)) { - return URI_ERROR_MALLOC; - } - /* [25/32] endif; */ - } - /* [26/32] T.query = R.query; */ - absDest->query = relSource->query; - /* [27/32] endif; */ - } - URI_FUNC(FixEmptyTrailSegment)(absDest, memory); - /* [29/32] endif; */ - } - /* [30/32] T.scheme = Base.scheme; */ - absDest->scheme = absBase->scheme; - /* [31/32] endif; */ - } - /* [32/32] T.fragment = R.fragment; */ - absDest->fragment = relSource->fragment; - - return URI_SUCCESS; - + const URI_TYPE(Uri) * relSource, + const URI_TYPE(Uri) * absBase, + UriResolutionOptions options, + UriMemoryManager * memory) { + UriBool relSourceHasScheme; + + if (absDest == NULL) { + return URI_ERROR_NULL; + } + URI_FUNC(ResetUri)(absDest); + + if ((relSource == NULL) || (absBase == NULL)) { + return URI_ERROR_NULL; + } + + /* absBase absolute? */ + if (absBase->scheme.first == NULL) { + return URI_ERROR_ADDBASE_REL_BASE; + } + + /* NOTE: The curly brackets here force deeper indent (and that's all) */ + { + { + { + /* clang-format off */ + /* [00/32] -- A non-strict parser may ignore a scheme in the reference */ + /* [00/32] -- if it is identical to the base URI's scheme. */ + /* [00/32] if ((not strict) and (R.scheme == Base.scheme)) then */ + /* clang-format on */ + relSourceHasScheme = + (relSource->scheme.first != NULL) ? URI_TRUE : URI_FALSE; + if ((options & URI_RESOLVE_IDENTICAL_SCHEME_COMPAT) + && (absBase->scheme.first != NULL) + && (relSource->scheme.first != NULL) + && (0 + == URI_FUNC(CompareRange)(&(absBase->scheme), + &(relSource->scheme)))) { + /* clang-format off */ + /* [00/32] undefine(R.scheme); */ + /* clang-format on */ + relSourceHasScheme = URI_FALSE; + /* clang-format off */ + /* [00/32] endif; */ + /* clang-format on */ + } + + /* clang-format off */ + /* [01/32] if defined(R.scheme) then */ + /* clang-format on */ + if (relSourceHasScheme) { + /* clang-format off */ + /* [02/32] T.scheme = R.scheme; */ + /* clang-format on */ + absDest->scheme = relSource->scheme; + /* clang-format off */ + /* [03/32] T.authority = R.authority; */ + /* clang-format on */ + if (!URI_FUNC(CopyAuthority)(absDest, relSource, memory)) { + return URI_ERROR_MALLOC; + } + /* clang-format off */ + /* [04/32] T.path = remove_dot_segments(R.path); */ + /* clang-format on */ + if (!URI_FUNC(CopyPath)(absDest, relSource, memory)) { + return URI_ERROR_MALLOC; + } + if (!URI_FUNC(RemoveDotSegmentsAbsolute)(absDest, memory)) { + return URI_ERROR_MALLOC; + } + /* clang-format off */ + /* [05/32] T.query = R.query; */ + /* clang-format on */ + absDest->query = relSource->query; + /* clang-format off */ + /* [06/32] else */ + /* clang-format on */ + } else { + /* clang-format off */ + /* [07/32] if defined(R.authority) then */ + /* clang-format on */ + if (URI_FUNC(HasHost)(relSource)) { + /* clang-format off */ + /* [08/32] T.authority = R.authority; */ + /* clang-format on */ + if (!URI_FUNC(CopyAuthority)(absDest, relSource, memory)) { + return URI_ERROR_MALLOC; + } + /* clang-format off */ + /* [09/32] T.path = remove_dot_segments(R.path); */ + /* clang-format on */ + if (!URI_FUNC(CopyPath)(absDest, relSource, memory)) { + return URI_ERROR_MALLOC; + } + if (!URI_FUNC(RemoveDotSegmentsAbsolute)(absDest, memory)) { + return URI_ERROR_MALLOC; + } + /* clang-format off */ + /* [10/32] T.query = R.query; */ + /* clang-format on */ + absDest->query = relSource->query; + /* clang-format off */ + /* [11/32] else */ + /* clang-format on */ + } else { + /* clang-format off */ + /* [28/32] T.authority = Base.authority; */ + /* clang-format on */ + if (!URI_FUNC(CopyAuthority)(absDest, absBase, memory)) { + return URI_ERROR_MALLOC; + } + /* clang-format off */ + /* [12/32] if (R.path == "") then */ + /* clang-format on */ + if (relSource->pathHead == NULL && !relSource->absolutePath) { + /* clang-format off */ + /* [13/32] T.path = Base.path; */ + /* clang-format on */ + if (!URI_FUNC(CopyPath)(absDest, absBase, memory)) { + return URI_ERROR_MALLOC; + } + /* clang-format off */ + /* [14/32] if defined(R.query) then */ + /* clang-format on */ + if (relSource->query.first != NULL) { + /* clang-format off */ + /* [15/32] T.query = R.query; */ + /* clang-format on */ + absDest->query = relSource->query; + /* clang-format off */ + /* [16/32] else */ + /* clang-format on */ + } else { + /* clang-format off */ + /* [17/32] T.query = Base.query; */ + /* clang-format on */ + absDest->query = absBase->query; + /* clang-format off */ + /* [18/32] endif; */ + /* clang-format on */ + } + /* clang-format off */ + /* [19/32] else */ + /* clang-format on */ + } else { + /* clang-format off */ + /* [20/32] if (R.path starts-with "/") then */ + /* clang-format on */ + if (relSource->absolutePath) { + int res; + /* clang-format off */ + /* [21/32] T.path = remove_dot_segments(R.path); */ + /* clang-format on */ + if (!URI_FUNC(CopyPath)(absDest, relSource, memory)) { + return URI_ERROR_MALLOC; + } + res = URI_FUNC(ResolveAbsolutePathFlag)(absDest, memory); + if (res != URI_SUCCESS) { + return res; + } + if (!URI_FUNC(RemoveDotSegmentsAbsolute)(absDest, + memory)) { + return URI_ERROR_MALLOC; + } + /* clang-format off */ + /* [22/32] else */ + /* clang-format on */ + } else { + /* clang-format off */ + /* [23/32] T.path = merge(Base.path, R.path); */ + /* clang-format on */ + if (!URI_FUNC(CopyPath)(absDest, absBase, memory)) { + return URI_ERROR_MALLOC; + } + if (!URI_FUNC(MergePath)(absDest, relSource, memory)) { + return URI_ERROR_MALLOC; + } + /* clang-format off */ + /* [24/32] T.path = remove_dot_segments(T.path); */ + /* clang-format on */ + if (!URI_FUNC(RemoveDotSegmentsAbsolute)(absDest, + memory)) { + return URI_ERROR_MALLOC; + } + + if (!URI_FUNC(FixAmbiguity)(absDest, memory)) { + return URI_ERROR_MALLOC; + } + /* clang-format off */ + /* [25/32] endif; */ + } + /* clang-format off */ + /* [26/32] T.query = R.query; */ + /* clang-format on */ + absDest->query = relSource->query; + /* clang-format off */ + /* [27/32] endif; */ + /* clang-format on */ + } + URI_FUNC(FixEmptyTrailSegment)(absDest, memory); + /* clang-format off */ + /* [29/32] endif; */ + /* clang-format on */ + } + /* clang-format off */ + /* [30/32] T.scheme = Base.scheme; */ + /* clang-format on */ + absDest->scheme = absBase->scheme; + /* clang-format off */ + /* [31/32] endif; */ + /* clang-format on */ + } + /* clang-format off */ + /* [32/32] T.fragment = R.fragment; */ + /* clang-format on */ + absDest->fragment = relSource->fragment; + } + } + } + return URI_SUCCESS; } - - -int URI_FUNC(AddBaseUri)(URI_TYPE(Uri) * absDest, - const URI_TYPE(Uri) * relSource, const URI_TYPE(Uri) * absBase) { - const UriResolutionOptions options = URI_RESOLVE_STRICTLY; - return URI_FUNC(AddBaseUriEx)(absDest, relSource, absBase, options); +int URI_FUNC(AddBaseUri)(URI_TYPE(Uri) * absDest, const URI_TYPE(Uri) * relSource, + const URI_TYPE(Uri) * absBase) { + const UriResolutionOptions options = URI_RESOLVE_STRICTLY; + return URI_FUNC(AddBaseUriEx)(absDest, relSource, absBase, options); } - - -int URI_FUNC(AddBaseUriEx)(URI_TYPE(Uri) * absDest, - const URI_TYPE(Uri) * relSource, const URI_TYPE(Uri) * absBase, - UriResolutionOptions options) { - return URI_FUNC(AddBaseUriExMm)(absDest, relSource, absBase, options, NULL); +int URI_FUNC(AddBaseUriEx)(URI_TYPE(Uri) * absDest, const URI_TYPE(Uri) * relSource, + const URI_TYPE(Uri) * absBase, UriResolutionOptions options) { + return URI_FUNC(AddBaseUriExMm)(absDest, relSource, absBase, options, NULL); } +int URI_FUNC(AddBaseUriExMm)(URI_TYPE(Uri) * absDest, const URI_TYPE(Uri) * relSource, + const URI_TYPE(Uri) * absBase, UriResolutionOptions options, + UriMemoryManager * memory) { + int res; + URI_CHECK_MEMORY_MANAGER(memory); /* may return */ -int URI_FUNC(AddBaseUriExMm)(URI_TYPE(Uri) * absDest, - const URI_TYPE(Uri) * relSource, const URI_TYPE(Uri) * absBase, - UriResolutionOptions options, UriMemoryManager * memory) { - int res; - - URI_CHECK_MEMORY_MANAGER(memory); /* may return */ - - res = URI_FUNC(AddBaseUriImpl)(absDest, relSource, absBase, options, memory); - if ((res != URI_SUCCESS) && (absDest != NULL)) { - URI_FUNC(FreeUriMembersMm)(absDest, memory); - } - return res; + res = URI_FUNC(AddBaseUriImpl)(absDest, relSource, absBase, options, memory); + if ((res != URI_SUCCESS) && (absDest != NULL)) { + URI_FUNC(FreeUriMembersMm)(absDest, memory); + } + return res; } - - #endif diff --git a/ext/uri/uriparser/src/UriSetFragment.c b/ext/uri/uriparser/src/UriSetFragment.c new file mode 100644 index 0000000000000..4479391d859dc --- /dev/null +++ b/ext/uri/uriparser/src/UriSetFragment.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 "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" +# include "UriSets.h" +# endif + +# include + +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_PCHAR_WITHOUT_PERCENT(_UT): + break; + + /* pct-encoded */ + case _UT('%'): + if (afterLast - first < 3) { + return URI_FALSE; + } + switch (first[1]) { + case URI_SET_HEXDIG(_UT): + break; + default: + return URI_FALSE; + } + switch (first[2]) { + case URI_SET_HEXDIG(_UT): + break; + default: + return URI_FALSE; + } + first += 2; + break; + + 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..df015880b33f6 --- /dev/null +++ b/ext/uri/uriparser/src/UriSetHostAuto.c @@ -0,0 +1,124 @@ +/* + * 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..081db36f219de --- /dev/null +++ b/ext/uri/uriparser/src/UriSetHostBase.h @@ -0,0 +1,49 @@ +/* + * 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..bd8095aea3cfa --- /dev/null +++ b/ext/uri/uriparser/src/UriSetHostCommon.c @@ -0,0 +1,248 @@ +/* + * 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) { + if (uri->pathHead != NULL) { + 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..6627767f2caf5 --- /dev/null +++ b/ext/uri/uriparser/src/UriSetHostCommon.h @@ -0,0 +1,74 @@ +/* + * 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..e52880be4c421 --- /dev/null +++ b/ext/uri/uriparser/src/UriSetHostIp4.c @@ -0,0 +1,91 @@ +/* + * 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..9637a4384b232 --- /dev/null +++ b/ext/uri/uriparser/src/UriSetHostIp6.c @@ -0,0 +1,158 @@ +/* + * 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..c5044c49c76fc --- /dev/null +++ b/ext/uri/uriparser/src/UriSetHostIpFuture.c @@ -0,0 +1,157 @@ +/* + * 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..01bc4e47f16ef --- /dev/null +++ b/ext/uri/uriparser/src/UriSetHostRegName.c @@ -0,0 +1,124 @@ +/* + * 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" +# include "UriSets.h" +# endif + +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(_UT): + break; + + /* pct-encoded */ + case _UT('%'): + if (afterLast - first < 3) { + return URI_FALSE; + } + switch (first[1]) { + case URI_SET_HEXDIG(_UT): + break; + default: + return URI_FALSE; + } + switch (first[2]) { + case URI_SET_HEXDIG(_UT): + break; + default: + return URI_FALSE; + } + first += 2; + break; + + case URI_SET_SUB_DELIMS(_UT): + 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..17aef0fca42d4 --- /dev/null +++ b/ext/uri/uriparser/src/UriSetPath.c @@ -0,0 +1,343 @@ +/* + * 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" +# include "UriSets.h" +# endif + +# include + +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_PCHAR_WITHOUT_PERCENT(_UT): + break; + + /* pct-encoded */ + case _UT('%'): + if (afterLast - first < 3) { + return URI_FALSE; + } + switch (first[1]) { + case URI_SET_HEXDIG(_UT): + break; + default: + return URI_FALSE; + } + switch (first[2]) { + case URI_SET_HEXDIG(_UT): + break; + default: + return URI_FALSE; + } + first += 2; + break; + + 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; + 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. */ + 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 */ + UriBool success = URI_FUNC(FixPathNoScheme)(destUri, memory); + if (success == URI_FALSE) { + return URI_ERROR_MALLOC; + } + + 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 */ + 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) { + res = URI_FUNC(MakeOwnerMm)(uri, memory); + if (res != URI_SUCCESS) { + return res; + } + } + + assert(uri->owner == URI_TRUE); + + /* Apply new value */ + 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..5e2160e309765 --- /dev/null +++ b/ext/uri/uriparser/src/UriSetPort.c @@ -0,0 +1,149 @@ +/* + * 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" +# include "UriSets.h" +# endif + +# include + +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(_UT): + 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..4f58c8286ed70 --- /dev/null +++ b/ext/uri/uriparser/src/UriSetQuery.c @@ -0,0 +1,172 @@ +/* + * 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" +# include "UriSets.h" +# endif + +# include + +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_PCHAR_WITHOUT_PERCENT(_UT): + break; + + /* pct-encoded */ + case _UT('%'): + if (afterLast - first < 3) { + return URI_FALSE; + } + switch (first[1]) { + case URI_SET_HEXDIG(_UT): + break; + default: + return URI_FALSE; + } + switch (first[2]) { + case URI_SET_HEXDIG(_UT): + break; + default: + return URI_FALSE; + } + first += 2; + break; + + 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..3dfaf1e9f151b --- /dev/null +++ b/ext/uri/uriparser/src/UriSetScheme.c @@ -0,0 +1,168 @@ +/* + * 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" +# include "UriSets.h" +# endif + +# include + +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(_UT): + break; + + default: + return URI_FALSE; + } + + first++; + + while (first < afterLast) { + switch (first[0]) { + case URI_SET_ALPHA(_UT): + case URI_SET_DIGIT(_UT): + 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..7865e837deb66 --- /dev/null +++ b/ext/uri/uriparser/src/UriSetUserInfo.c @@ -0,0 +1,180 @@ +/* + * 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" +# include "UriSets.h" +# endif + +# include + +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(_UT): + break; + + /* pct-encoded */ + case _UT('%'): + if (afterLast - first < 3) { + return URI_FALSE; + } + switch (first[1]) { + case URI_SET_HEXDIG(_UT): + break; + default: + return URI_FALSE; + } + switch (first[2]) { + case URI_SET_HEXDIG(_UT): + break; + default: + return URI_FALSE; + } + first += 2; + break; + + case URI_SET_SUB_DELIMS(_UT): + 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/UriSets.h b/ext/uri/uriparser/src/UriSets.h new file mode 100644 index 0000000000000..a6a2c46a14d77 --- /dev/null +++ b/ext/uri/uriparser/src/UriSets.h @@ -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. + */ + +/** + * @file UriSets.h + * Holds character set definitions. + */ + +// NOTE: We cannot use a regular include-once guard here because the +// file must support being included twice, e.g. from file UriParse.c. +#if !defined(URI_SET_DIGIT) + +// clang-format off +# define URI_SET_DIGIT(ut) \ + ut('0'): \ + case ut('1'): \ + /* clang-format on */ \ + case ut('2'): \ + case ut('3'): \ + case ut('4'): \ + case ut('5'): \ + case ut('6'): \ + case ut('7'): \ + case ut('8'): \ + case ut('9') + +// clang-format off +# define URI_SET_HEX_LETTER_LOWER(ut) \ + ut('a'): \ + case ut('b'): \ + /* clang-format on */ \ + case ut('c'): \ + case ut('d'): \ + case ut('e'): \ + case ut('f') + +// clang-format off +# define URI_SET_HEX_LETTER_UPPER(ut) \ + ut('A'): \ + case ut('B'): \ + /* clang-format on */ \ + case ut('C'): \ + case ut('D'): \ + case ut('E'): \ + case ut('F') + +// clang-format off +# define URI_SET_HEXDIG(ut) \ + URI_SET_DIGIT(ut): \ + case URI_SET_HEX_LETTER_LOWER(ut): \ + /* clang-format on */ \ + case URI_SET_HEX_LETTER_UPPER(ut) + +// clang-format off +# define URI_SET_ALPHA(ut) \ + URI_SET_HEX_LETTER_UPPER(ut): \ + case URI_SET_HEX_LETTER_LOWER(ut): \ + /* clang-format on */ \ + 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') + +// clang-format off +# define URI_SET_SUB_DELIMS(ut) \ + ut('!'): \ + case ut('$'): \ + /* clang-format on */ \ + case ut('&'): \ + case ut('\''): \ + case ut('('): \ + case ut(')'): \ + case ut('*'): \ + case ut('+'): \ + case ut(','): \ + case ut(';'): \ + case ut('=') + +// clang-format off +# define URI_SET_UNRESERVED(ut) \ + URI_SET_ALPHA(ut): \ + case URI_SET_DIGIT(ut): \ + /* clang-format on */ \ + case ut('-'): \ + case ut('.'): \ + case ut('_'): \ + case ut('~') + +// clang-format off +# define URI_SET_PCHAR_WITHOUT_PERCENT(ut) \ + URI_SET_UNRESERVED(ut): \ + case URI_SET_SUB_DELIMS(ut): \ + /* clang-format on */ \ + case ut(':'): \ + case ut('@') + +// clang-format off +# define URI_SET_PCHAR(ut) \ + URI_SET_PCHAR_WITHOUT_PERCENT(ut): \ + case ut('%') +/* clang-format on */ + +#endif // ! defined(URI_SET_DIGIT) diff --git a/ext/uri/uriparser/src/UriShorten.c b/ext/uri/uriparser/src/UriShorten.c index d2f893592d9ce..548b0b4157dd0 100644 --- a/ext/uri/uriparser/src/UriShorten.c +++ b/ext/uri/uriparser/src/UriShorten.c @@ -41,284 +41,386 @@ #include #if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) /* Include SELF twice */ -# ifdef URI_ENABLE_ANSI -# define URI_PASS_ANSI 1 -# include "UriShorten.c" -# undef URI_PASS_ANSI -# endif -# ifdef URI_ENABLE_UNICODE -# define URI_PASS_UNICODE 1 -# include "UriShorten.c" -# undef URI_PASS_UNICODE -# endif +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriShorten.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriShorten.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 - - +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif + +# ifndef URI_DOXYGEN +# include +# include "UriCommon.h" +# include "UriMemory.h" +# endif static URI_INLINE UriBool URI_FUNC(AppendSegment)(URI_TYPE(Uri) * uri, - const URI_CHAR * first, const URI_CHAR * afterLast, - UriMemoryManager * memory) { - /* Create segment */ - URI_TYPE(PathSegment) * segment = memory->malloc(memory, 1 * sizeof(URI_TYPE(PathSegment))); - if (segment == NULL) { - return URI_FALSE; /* Raises malloc error */ - } - segment->next = NULL; - segment->text.first = first; - segment->text.afterLast = afterLast; - - /* Put into chain */ - if (uri->pathTail == NULL) { - uri->pathHead = segment; - } else { - uri->pathTail->next = segment; - } - uri->pathTail = segment; - - return URI_TRUE; + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + /* Create segment */ + URI_TYPE(PathSegment) * segment = + memory->malloc(memory, 1 * sizeof(URI_TYPE(PathSegment))); + if (segment == NULL) { + return URI_FALSE; /* Raises malloc error */ + } + segment->next = NULL; + segment->text.first = first; + segment->text.afterLast = afterLast; + + /* Put into chain */ + if (uri->pathTail == NULL) { + uri->pathHead = segment; + } else { + uri->pathTail->next = segment; + } + uri->pathTail = segment; + + return URI_TRUE; } - - static URI_INLINE UriBool URI_FUNC(EqualsAuthority)(const URI_TYPE(Uri) * first, - const URI_TYPE(Uri) * second) { - /* IPv4 */ - if (first->hostData.ip4 != NULL) { - return ((second->hostData.ip4 != NULL) - && !memcmp(first->hostData.ip4->data, - second->hostData.ip4->data, 4)) ? URI_TRUE : URI_FALSE; - } - - /* IPv6 */ - if (first->hostData.ip6 != NULL) { - return ((second->hostData.ip6 != NULL) - && !memcmp(first->hostData.ip6->data, - second->hostData.ip6->data, 16)) ? URI_TRUE : URI_FALSE; - } - - /* IPvFuture */ - if (first->hostData.ipFuture.first != NULL) { - return ((second->hostData.ipFuture.first != NULL) - && !URI_FUNC(CompareRange)(&first->hostData.ipFuture, - &second->hostData.ipFuture)) ? URI_TRUE : URI_FALSE; - } - - return !URI_FUNC(CompareRange)(&first->hostText, &second->hostText) - ? URI_TRUE : URI_FALSE; + const URI_TYPE(Uri) * second) { + /* IPv4 */ + if (first->hostData.ip4 != NULL) { + return ((second->hostData.ip4 != NULL) + && !memcmp(first->hostData.ip4->data, second->hostData.ip4->data, 4)) + ? URI_TRUE + : URI_FALSE; + } + + /* IPv6 */ + if (first->hostData.ip6 != NULL) { + return ((second->hostData.ip6 != NULL) + && !memcmp(first->hostData.ip6->data, second->hostData.ip6->data, 16)) + ? URI_TRUE + : URI_FALSE; + } + + /* IPvFuture */ + if (first->hostData.ipFuture.first != NULL) { + return ((second->hostData.ipFuture.first != NULL) + && !URI_FUNC(CompareRange)(&first->hostData.ipFuture, + &second->hostData.ipFuture)) + ? URI_TRUE + : URI_FALSE; + } + + return !URI_FUNC(CompareRange)(&first->hostText, &second->hostText) ? URI_TRUE + : URI_FALSE; } - - static int URI_FUNC(RemoveBaseUriImpl)(URI_TYPE(Uri) * dest, - const URI_TYPE(Uri) * absSource, - const URI_TYPE(Uri) * absBase, - UriBool domainRootMode, UriMemoryManager * memory) { - if (dest == NULL) { - return URI_ERROR_NULL; - } - URI_FUNC(ResetUri)(dest); - - if ((absSource == NULL) || (absBase == NULL)) { - return URI_ERROR_NULL; - } - - /* absBase absolute? */ - if (absBase->scheme.first == NULL) { - return URI_ERROR_REMOVEBASE_REL_BASE; - } - - /* absSource absolute? */ - if (absSource->scheme.first == NULL) { - return URI_ERROR_REMOVEBASE_REL_SOURCE; - } - - /* [01/50] if (A.scheme != Base.scheme) then */ - if (URI_FUNC(CompareRange)(&absSource->scheme, &absBase->scheme)) { - /* [02/50] T.scheme = A.scheme; */ - dest->scheme = absSource->scheme; - /* [03/50] T.authority = A.authority; */ - if (!URI_FUNC(CopyAuthority)(dest, absSource, memory)) { - return URI_ERROR_MALLOC; - } - /* [04/50] T.path = A.path; */ - if (!URI_FUNC(CopyPath)(dest, absSource, memory)) { - return URI_ERROR_MALLOC; - } - /* [05/50] else */ - } else { - /* [06/50] undef(T.scheme); */ - /* NOOP */ - /* [07/50] if (A.authority != Base.authority) then */ - if (!URI_FUNC(EqualsAuthority)(absSource, absBase)) { - /* [08/50] T.authority = A.authority; */ - if (!URI_FUNC(CopyAuthority)(dest, absSource, memory)) { - return URI_ERROR_MALLOC; - } - /* [09/50] T.path = A.path; */ - if (!URI_FUNC(CopyPath)(dest, absSource, memory)) { - return URI_ERROR_MALLOC; - } - /* [10/50] else */ - } else { - /* [11/50] if domainRootMode then */ - if (domainRootMode == URI_TRUE) { - /* [12/50] undef(T.authority); */ - /* NOOP */ - /* [13/50] if (first(A.path) == "") then */ - /* GROUPED */ - /* [14/50] T.path = "/." + A.path; */ - /* GROUPED */ - /* [15/50] else */ - /* GROUPED */ - /* [16/50] T.path = A.path; */ - /* GROUPED */ - /* [17/50] endif; */ - if (!URI_FUNC(CopyPath)(dest, absSource, memory)) { - return URI_ERROR_MALLOC; - } - dest->absolutePath = URI_TRUE; - - if (!URI_FUNC(FixAmbiguity)(dest, memory)) { - return URI_ERROR_MALLOC; - } - /* [18/50] else */ - } else { - const URI_TYPE(PathSegment) * sourceSeg = absSource->pathHead; - const URI_TYPE(PathSegment) * baseSeg = absBase->pathHead; - /* [19/50] bool pathNaked = true; */ - UriBool pathNaked = URI_TRUE; - /* [20/50] undef(last(Base.path)); */ - /* NOOP */ - /* [21/50] T.path = ""; */ - dest->absolutePath = URI_FALSE; - /* [22/50] while (first(A.path) == first(Base.path)) do */ - while ((sourceSeg != NULL) && (baseSeg != NULL) - && !URI_FUNC(CompareRange)(&sourceSeg->text, &baseSeg->text) - && !((sourceSeg->text.first == sourceSeg->text.afterLast) - && ((sourceSeg->next == NULL) != (baseSeg->next == NULL)))) { - /* [23/50] A.path++; */ - sourceSeg = sourceSeg->next; - /* [24/50] Base.path++; */ - baseSeg = baseSeg->next; - /* [25/50] endwhile; */ - } - /* [26/50] while defined(first(Base.path)) do */ - while ((baseSeg != NULL) && (baseSeg->next != NULL)) { - /* [27/50] Base.path++; */ - baseSeg = baseSeg->next; - /* [28/50] T.path += "../"; */ - if (!URI_FUNC(AppendSegment)(dest, URI_FUNC(ConstParent), - URI_FUNC(ConstParent) + 2, memory)) { - return URI_ERROR_MALLOC; - } - /* [29/50] pathNaked = false; */ - pathNaked = URI_FALSE; - /* [30/50] endwhile; */ - } - /* [31/50] while defined(first(A.path)) do */ - while (sourceSeg != NULL) { - /* [32/50] if pathNaked then */ - if (pathNaked == URI_TRUE) { - /* [33/50] if (first(A.path) contains ":") then */ - UriBool containsColon = URI_FALSE; - const URI_CHAR * ch = sourceSeg->text.first; - for (; ch < sourceSeg->text.afterLast; ch++) { - if (*ch == _UT(':')) { - containsColon = URI_TRUE; - break; - } - } - - if (containsColon) { - /* [34/50] T.path += "./"; */ - if (!URI_FUNC(AppendSegment)(dest, URI_FUNC(ConstPwd), - URI_FUNC(ConstPwd) + 1, memory)) { - return URI_ERROR_MALLOC; - } - /* [35/50] elseif (first(A.path) == "") then */ - } else if (sourceSeg->text.first == sourceSeg->text.afterLast) { - /* [36/50] T.path += "/."; */ - if (!URI_FUNC(AppendSegment)(dest, URI_FUNC(ConstPwd), - URI_FUNC(ConstPwd) + 1, memory)) { - return URI_ERROR_MALLOC; - } - /* [37/50] endif; */ - } - /* [38/50] endif; */ - } - /* [39/50] T.path += first(A.path); */ - if (!URI_FUNC(AppendSegment)(dest, sourceSeg->text.first, - sourceSeg->text.afterLast, memory)) { - return URI_ERROR_MALLOC; - } - /* [40/50] pathNaked = false; */ - pathNaked = URI_FALSE; - /* [41/50] A.path++; */ - sourceSeg = sourceSeg->next; - /* [42/50] if defined(first(A.path)) then */ - /* NOOP */ - /* [43/50] T.path += + "/"; */ - /* NOOP */ - /* [44/50] endif; */ - /* NOOP */ - /* [45/50] endwhile; */ - } - /* [46/50] endif; */ - } - /* [47/50] endif; */ - } - /* [48/50] endif; */ - } - /* [49/50] T.query = A.query; */ - dest->query = absSource->query; - /* [50/50] T.fragment = A.fragment; */ - dest->fragment = absSource->fragment; - - return URI_SUCCESS; + const URI_TYPE(Uri) * absSource, + const URI_TYPE(Uri) * absBase, + UriBool domainRootMode, + UriMemoryManager * memory) { + if (dest == NULL) { + return URI_ERROR_NULL; + } + URI_FUNC(ResetUri)(dest); + + if ((absSource == NULL) || (absBase == NULL)) { + return URI_ERROR_NULL; + } + + /* absBase absolute? */ + if (absBase->scheme.first == NULL) { + return URI_ERROR_REMOVEBASE_REL_BASE; + } + + /* absSource absolute? */ + if (absSource->scheme.first == NULL) { + return URI_ERROR_REMOVEBASE_REL_SOURCE; + } + + /* NOTE: The curly brackets here force deeper indent (and that's all) */ + { + { + { + /* clang-format off */ + /* [01/50] if (A.scheme != Base.scheme) then */ + /* clang-format on */ + if (URI_FUNC(CompareRange)(&absSource->scheme, &absBase->scheme)) { + /* clang-format off */ + /* [02/50] T.scheme = A.scheme; */ + /* clang-format on */ + dest->scheme = absSource->scheme; + /* clang-format off */ + /* [03/50] T.authority = A.authority; */ + /* clang-format on */ + if (!URI_FUNC(CopyAuthority)(dest, absSource, memory)) { + return URI_ERROR_MALLOC; + } + /* clang-format off */ + /* [04/50] T.path = A.path; */ + /* clang-format on */ + if (!URI_FUNC(CopyPath)(dest, absSource, memory)) { + return URI_ERROR_MALLOC; + } + /* clang-format off */ + /* [05/50] else */ + /* clang-format on */ + } else { + /* clang-format off */ + /* [06/50] undef(T.scheme); */ + /* clang-format on */ + /* NOOP */ + /* clang-format off */ + /* [07/50] if (A.authority != Base.authority) then */ + /* clang-format on */ + if (!URI_FUNC(EqualsAuthority)(absSource, absBase)) { + /* clang-format off */ + /* [08/50] T.authority = A.authority; */ + /* clang-format on */ + if (!URI_FUNC(CopyAuthority)(dest, absSource, memory)) { + return URI_ERROR_MALLOC; + } + /* clang-format off */ + /* [09/50] T.path = A.path; */ + /* clang-format on */ + if (!URI_FUNC(CopyPath)(dest, absSource, memory)) { + return URI_ERROR_MALLOC; + } + /* clang-format off */ + /* [10/50] else */ + /* clang-format on */ + } else { + /* clang-format off */ + /* [11/50] if domainRootMode then */ + /* clang-format on */ + if (domainRootMode == URI_TRUE) { + /* clang-format off */ + /* [12/50] undef(T.authority); */ + /* clang-format on */ + /* NOOP */ + /* clang-format off */ + /* [13/50] if (first(A.path) == "") then */ + /* clang-format on */ + /* GROUPED */ + /* clang-format off */ + /* [14/50] T.path = "/." + A.path; */ + /* clang-format on */ + /* GROUPED */ + /* clang-format off */ + /* [15/50] else */ + /* clang-format on */ + /* GROUPED */ + /* clang-format off */ + /* [16/50] T.path = A.path; */ + /* clang-format on */ + /* GROUPED */ + /* clang-format off */ + /* [17/50] endif; */ + /* clang-format on */ + if (!URI_FUNC(CopyPath)(dest, absSource, memory)) { + return URI_ERROR_MALLOC; + } + dest->absolutePath = URI_TRUE; + + if (!URI_FUNC(FixAmbiguity)(dest, memory)) { + return URI_ERROR_MALLOC; + } + /* clang-format off */ + /* [18/50] else */ + /* clang-format on */ + } else { + const URI_TYPE(PathSegment) * sourceSeg = absSource->pathHead; + const URI_TYPE(PathSegment) * baseSeg = absBase->pathHead; + /* clang-format off */ + /* [19/50] bool pathNaked = true; */ + /* clang-format on */ + UriBool pathNaked = URI_TRUE; + /* clang-format off */ + /* [20/50] undef(last(Base.path)); */ + /* clang-format on */ + /* NOOP */ + /* clang-format off */ + /* [21/50] T.path = ""; */ + /* clang-format on */ + dest->absolutePath = URI_FALSE; + /* clang-format off */ + /* [22/50] while (first(A.path) == first(Base.path)) do */ + /* clang-format on */ + while ( + (sourceSeg != NULL) && (baseSeg != NULL) + && !URI_FUNC(CompareRange)(&sourceSeg->text, + &baseSeg->text) + && !((sourceSeg->text.first == sourceSeg->text.afterLast) + && ((sourceSeg->next == NULL) + != (baseSeg->next == NULL)))) { + /* clang-format off */ + /* [23/50] A.path++; */ + /* clang-format on */ + sourceSeg = sourceSeg->next; + /* clang-format off */ + /* [24/50] Base.path++; */ + /* clang-format on */ + baseSeg = baseSeg->next; + /* clang-format off */ + /* [25/50] endwhile; */ + /* clang-format on */ + } + /* clang-format off */ + /* [26/50] while defined(first(Base.path)) do */ + /* clang-format on */ + while ((baseSeg != NULL) && (baseSeg->next != NULL)) { + /* clang-format off */ + /* [27/50] Base.path++; */ + /* clang-format on */ + baseSeg = baseSeg->next; + /* clang-format off */ + /* [28/50] T.path += "../"; */ + /* clang-format on */ + if (!URI_FUNC(AppendSegment)(dest, URI_FUNC(ConstParent), + URI_FUNC(ConstParent) + 2, + memory)) { + return URI_ERROR_MALLOC; + } + /* clang-format off */ + /* [29/50] pathNaked = false; */ + /* clang-format on */ + pathNaked = URI_FALSE; + /* clang-format off */ + /* [30/50] endwhile; */ + /* clang-format on */ + } + /* clang-format off */ + /* [31/50] while defined(first(A.path)) do */ + /* clang-format on */ + while (sourceSeg != NULL) { + /* clang-format off */ + /* [32/50] if pathNaked then */ + /* clang-format on */ + if (pathNaked == URI_TRUE) { + /* clang-format off */ + /* [33/50] if (first(A.path) contains ":") then */ + /* clang-format on */ + UriBool containsColon = URI_FALSE; + const URI_CHAR * ch = sourceSeg->text.first; + for (; ch < sourceSeg->text.afterLast; ch++) { + if (*ch == _UT(':')) { + containsColon = URI_TRUE; + break; + } + } + + if (containsColon) { + /* clang-format off */ + /* [34/50] T.path += "./"; */ + /* clang-format on */ + if (!URI_FUNC(AppendSegment)( + dest, URI_FUNC(ConstPwd), + URI_FUNC(ConstPwd) + 1, memory)) { + return URI_ERROR_MALLOC; + } + /* clang-format off */ + /* [35/50] elseif (first(A.path) == "") then */ + /* clang-format on */ + } else if (sourceSeg->text.first + == sourceSeg->text.afterLast) { + /* clang-format off */ + /* [36/50] T.path += "/."; */ + /* clang-format on */ + if (!URI_FUNC(AppendSegment)( + dest, URI_FUNC(ConstPwd), + URI_FUNC(ConstPwd) + 1, memory)) { + return URI_ERROR_MALLOC; + } + /* clang-format off */ + /* [37/50] endif; */ + /* clang-format on */ + } + /* clang-format off */ + /* [38/50] endif; */ + /* clang-format on */ + } + /* clang-format off */ + /* [39/50] T.path += first(A.path); */ + /* clang-format on */ + if (!URI_FUNC(AppendSegment)(dest, sourceSeg->text.first, + sourceSeg->text.afterLast, + memory)) { + return URI_ERROR_MALLOC; + } + /* clang-format off */ + /* [40/50] pathNaked = false; */ + /* clang-format on */ + pathNaked = URI_FALSE; + /* clang-format off */ + /* [41/50] A.path++; */ + /* clang-format on */ + sourceSeg = sourceSeg->next; + /* clang-format off */ + /* [42/50] if defined(first(A.path)) then */ + /* clang-format on */ + /* NOOP */ + /* clang-format off */ + /* [43/50] T.path += + "/"; */ + /* clang-format on */ + /* NOOP */ + /* clang-format off */ + /* [44/50] endif; */ + /* clang-format on */ + /* NOOP */ + /* clang-format off */ + /* [45/50] endwhile; */ + /* clang-format on */ + } + /* clang-format off */ + /* [46/50] endif; */ + /* clang-format on */ + } + /* clang-format off */ + /* [47/50] endif; */ + /* clang-format on */ + } + /* clang-format off */ + /* [48/50] endif; */ + /* clang-format on */ + } + /* clang-format off */ + /* [49/50] T.query = A.query; */ + /* clang-format on */ + dest->query = absSource->query; + /* clang-format off */ + /* [50/50] T.fragment = A.fragment; */ + /* clang-format on */ + dest->fragment = absSource->fragment; + } + } + } + return URI_SUCCESS; } - - -int URI_FUNC(RemoveBaseUri)(URI_TYPE(Uri) * dest, - const URI_TYPE(Uri) * absSource, - const URI_TYPE(Uri) * absBase, - UriBool domainRootMode) { - return URI_FUNC(RemoveBaseUriMm)(dest, absSource, absBase, - domainRootMode, NULL); +int URI_FUNC(RemoveBaseUri)(URI_TYPE(Uri) * dest, const URI_TYPE(Uri) * absSource, + const URI_TYPE(Uri) * absBase, UriBool domainRootMode) { + return URI_FUNC(RemoveBaseUriMm)(dest, absSource, absBase, domainRootMode, NULL); } +int URI_FUNC(RemoveBaseUriMm)(URI_TYPE(Uri) * dest, const URI_TYPE(Uri) * absSource, + const URI_TYPE(Uri) * absBase, UriBool domainRootMode, + UriMemoryManager * memory) { + int res; + URI_CHECK_MEMORY_MANAGER(memory); /* may return */ -int URI_FUNC(RemoveBaseUriMm)(URI_TYPE(Uri) * dest, - const URI_TYPE(Uri) * absSource, - const URI_TYPE(Uri) * absBase, - UriBool domainRootMode, UriMemoryManager * memory) { - int res; - - URI_CHECK_MEMORY_MANAGER(memory); /* may return */ - - res = URI_FUNC(RemoveBaseUriImpl)(dest, absSource, - absBase, domainRootMode, memory); - if ((res != URI_SUCCESS) && (dest != NULL)) { - URI_FUNC(FreeUriMembersMm)(dest, memory); - } - return res; + res = URI_FUNC(RemoveBaseUriImpl)(dest, absSource, absBase, domainRootMode, memory); + if ((res != URI_SUCCESS) && (dest != NULL)) { + URI_FUNC(FreeUriMembersMm)(dest, memory); + } + return res; } - - #endif diff --git a/ext/uri/uriparser/src/UriVersion.c b/ext/uri/uriparser/src/UriVersion.c new file mode 100644 index 0000000000000..5c9a3e3f4b0af --- /dev/null +++ b/ext/uri/uriparser/src/UriVersion.c @@ -0,0 +1,81 @@ +/* + * 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 ea72a958006e2..7e37bf1e412c3 100644 --- a/ext/xml/compat.c +++ b/ext/xml/compat.c @@ -18,19 +18,44 @@ #if defined(HAVE_LIBXML) && (defined(HAVE_XML) || defined(HAVE_XMLRPC)) && !defined(HAVE_LIBEXPAT) #include "expat_compat.h" #include "ext/libxml/php_libxml.h" +#include "Zend/zend_smart_string.h" #ifdef LIBXML_EXPAT_COMPAT -static void -qualify_namespace(XML_Parser parser, const xmlChar *name, const xmlChar *URI, xmlChar **qualified) +static xmlChar * +qualify_namespace(XML_Parser parser, const xmlChar *name, const xmlChar *URI) { if (URI) { - /* Use libxml functions otherwise its memory deallocation is screwed up */ - *qualified = xmlStrdup(URI); - *qualified = xmlStrncat(*qualified, parser->_ns_separator, 1); - *qualified = xmlStrncat(*qualified, name, xmlStrlen(name)); + smart_string str = {0}; + smart_string_appends(&str, (const char *) URI); + smart_string_appends(&str, (const char *) parser->_ns_separator); + smart_string_appends(&str, (const char *) name); + smart_string_0(&str); + return BAD_CAST str.c; } else { - *qualified = xmlStrdup(name); + return BAD_CAST estrdup((const char *) name); + } +} + +static void start_element_emit_default(XML_Parser parser) +{ + if (parser->h_default) { + /* Grammar does not allow embedded '<' and '>' in elements, so we can seek to the start and end positions. + * Since the parser in the current mode mode is non-progressive, it contains the entire input. */ + const xmlChar *cur = parser->parser->input->cur; + const xmlChar *end = cur; + for (const xmlChar *base = parser->parser->input->base; cur > base && *cur != '<'; cur--); + if (*end == '/') { + /* BC: Keep split between start & end element. + * TODO: In the future this could be aligned with expat and only emit a start event, or vice versa. + * See gh20439_2.phpt */ + xmlChar *tmp = BAD_CAST estrndup((const char *) cur, end - cur + 1); + tmp[end - cur] = '>'; + parser->h_default(parser->user, tmp, end - cur + 1); + efree(tmp); + } else { + parser->h_default(parser->user, cur, end - cur + 1); + } } } @@ -38,32 +63,9 @@ static void start_element_handler(void *user, const xmlChar *name, const xmlChar **attributes) { XML_Parser parser = (XML_Parser) user; - xmlChar *qualified_name = NULL; if (parser->h_start_element == NULL) { - if (parser->h_default) { - int attno = 0; - - qualified_name = xmlStrncatNew((xmlChar *)"<", name, xmlStrlen(name)); - if (attributes) { - while (attributes[attno] != NULL) { - int att_len; - char *att_string, *att_name, *att_value; - - att_name = (char *)attributes[attno++]; - att_value = (char *)attributes[attno++]; - - att_len = spprintf(&att_string, 0, " %s=\"%s\"", att_name, att_value); - - qualified_name = xmlStrncat(qualified_name, (xmlChar *)att_string, att_len); - efree(att_string); - } - - } - qualified_name = xmlStrncat(qualified_name, (xmlChar *)">", 1); - parser->h_default(parser->user, (const XML_Char *) qualified_name, xmlStrlen(qualified_name)); - xmlFree(qualified_name); - } + start_element_emit_default(parser); return; } @@ -89,82 +91,24 @@ start_element_handler_ns(void *user, const xmlChar *name, const xmlChar *prefix, } if (parser->h_start_element == NULL) { - if (parser->h_default) { - - if (prefix) { - qualified_name = xmlStrncatNew((xmlChar *)"<", prefix, xmlStrlen(prefix)); - qualified_name = xmlStrncat(qualified_name, (xmlChar *)":", 1); - qualified_name = xmlStrncat(qualified_name, name, xmlStrlen(name)); - } else { - qualified_name = xmlStrncatNew((xmlChar *)"<", name, xmlStrlen(name)); - } - - if (namespaces) { - int i, j; - for (i = 0,j = 0;j < nb_namespaces;j++) { - int ns_len; - char *ns_string, *ns_prefix, *ns_url; - - ns_prefix = (char *) namespaces[i++]; - ns_url = (char *) namespaces[i++]; - - if (ns_prefix) { - ns_len = spprintf(&ns_string, 0, " xmlns:%s=\"%s\"", ns_prefix, ns_url); - } else { - ns_len = spprintf(&ns_string, 0, " xmlns=\"%s\"", ns_url); - } - qualified_name = xmlStrncat(qualified_name, (xmlChar *)ns_string, ns_len); - - efree(ns_string); - } - } - - if (attributes) { - for (i = 0; i < nb_attributes; i += 1) { - int att_len; - char *att_string, *att_name, *att_value, *att_prefix, *att_valueend; - - att_name = (char *) attributes[y++]; - att_prefix = (char *)attributes[y++]; - y++; - att_value = (char *)attributes[y++]; - att_valueend = (char *)attributes[y++]; - - if (att_prefix) { - att_len = spprintf(&att_string, 0, " %s:%s=\"", att_prefix, att_name); - } else { - att_len = spprintf(&att_string, 0, " %s=\"", att_name); - } - - qualified_name = xmlStrncat(qualified_name, (xmlChar *)att_string, att_len); - qualified_name = xmlStrncat(qualified_name, (xmlChar *)att_value, att_valueend - att_value); - qualified_name = xmlStrncat(qualified_name, (xmlChar *)"\"", 1); - - efree(att_string); - } - - } - qualified_name = xmlStrncat(qualified_name, (xmlChar *)">", 1); - parser->h_default(parser->user, (const XML_Char *) qualified_name, xmlStrlen(qualified_name)); - xmlFree(qualified_name); - } + start_element_emit_default(parser); return; } - qualify_namespace(parser, name, URI, &qualified_name); + qualified_name = qualify_namespace(parser, name, URI); if (attributes != NULL) { xmlChar *qualified_name_attr = NULL; - attrs = safe_emalloc((nb_attributes * 2) + 1, sizeof(int *), 0); + attrs = safe_emalloc(nb_attributes, 2 * sizeof(int *), sizeof(int *)); for (i = 0; i < nb_attributes; i += 1) { if (attributes[y+1] != NULL) { - qualify_namespace(parser, attributes[y] , attributes[y + 2], &qualified_name_attr); + qualified_name_attr = qualify_namespace(parser, attributes[y] , attributes[y + 2]); } else { - qualified_name_attr = xmlStrdup(attributes[y]); + qualified_name_attr = BAD_CAST estrdup((const char *) attributes[y]); } attrs[z] = qualified_name_attr; - attrs[z + 1] = xmlStrndup(attributes[y + 3] , (int) (attributes[y + 4] - attributes[y + 3])); + attrs[z + 1] = BAD_CAST estrndup((const char *) attributes[y + 3], attributes[y + 4] - attributes[y + 3]); z += 2; y += 5; } @@ -174,11 +118,11 @@ start_element_handler_ns(void *user, const xmlChar *name, const xmlChar *prefix, parser->h_start_element(parser->user, (const XML_Char *) qualified_name, (const XML_Char **) attrs); if (attrs) { for (i = 0; i < z; i++) { - xmlFree(attrs[i]); + efree(attrs[i]); } efree(attrs); } - xmlFree(qualified_name); + efree(qualified_name); } static void @@ -222,11 +166,11 @@ end_element_handler_ns(void *user, const xmlChar *name, const xmlChar * prefix, return; } - qualify_namespace(parser, name, URI, &qualified_name); + qualified_name = qualify_namespace(parser, name, URI); parser->h_end_element(parser->user, (const XML_Char *) qualified_name); - xmlFree(qualified_name); + efree(qualified_name); } static void @@ -290,17 +234,19 @@ notation_decl_handler(void *user, const xmlChar *notation, const xmlChar *pub_id parser->h_notation_decl(parser->user, notation, NULL, sys_id, pub_id); } -static void -build_comment(const xmlChar *data, size_t data_len, xmlChar **comment, size_t *comment_len) +static xmlChar * +build_comment(const xmlChar *data, size_t data_len, size_t *comment_len) { *comment_len = data_len + 7; - *comment = xmlMalloc(*comment_len + 1); - memcpy(*comment, "", 3); + xmlChar *comment = emalloc(*comment_len + 1); + memcpy(comment, "", 3); + + comment[*comment_len] = '\0'; - (*comment)[*comment_len] = '\0'; + return comment; } static void @@ -309,24 +255,24 @@ comment_handler(void *user, const xmlChar *comment) XML_Parser parser = (XML_Parser) user; if (parser->h_default) { - xmlChar *d_comment; size_t d_comment_len; - build_comment(comment, (size_t) xmlStrlen(comment), &d_comment, &d_comment_len); + xmlChar *d_comment = build_comment(comment, (size_t) xmlStrlen(comment), &d_comment_len); parser->h_default(parser->user, d_comment, d_comment_len); - xmlFree(d_comment); + efree(d_comment); } } -static void -build_entity(const xmlChar *name, size_t len, xmlChar **entity, size_t *entity_len) +static xmlChar * +build_entity(const xmlChar *name, size_t len, size_t *entity_len) { *entity_len = len + 2; - *entity = xmlMalloc(*entity_len + 1); - (*entity)[0] = '&'; - memcpy(*entity+1, name, len); - (*entity)[len+1] = ';'; - (*entity)[*entity_len] = '\0'; + xmlChar *entity = emalloc(*entity_len + 1); + entity[0] = '&'; + memcpy(entity + 1, name, len); + entity[len + 1] = ';'; + entity[*entity_len] = '\0'; + return entity; } static void @@ -361,12 +307,11 @@ get_entity(void *user, const xmlChar *name) 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)) { - xmlChar *entity; size_t len; - build_entity(name, (size_t) xmlStrlen(name), &entity, &len); + xmlChar *entity = build_entity(name, (size_t) xmlStrlen(name), &len); parser->h_default(parser->user, (const xmlChar *) entity, len); - xmlFree(entity); + efree(entity); } else { /* expat will not expand internal entities if default handler is present otherwise it will expand and pass them to cdata handler */ @@ -452,15 +397,19 @@ XML_ParserCreate_MM(const XML_Char *encoding, const XML_Memory_Handling_Suite *m return NULL; } +#if LIBXML_VERSION >= 21300 + xmlCtxtSetOptions(parser->parser, XML_PARSE_OLDSAX | XML_PARSE_NOENT); +#else php_libxml_sanitize_parse_ctxt_options(parser->parser); xmlCtxtUseOptions(parser->parser, XML_PARSE_OLDSAX | XML_PARSE_NOENT); +#endif parser->parser->wellFormed = 0; if (sep != NULL) { /* Note: sax2 flag will be set due to the magic number in `initialized` in php_xml_compat_handlers */ ZEND_ASSERT(parser->parser->sax->initialized == XML_SAX2_MAGIC); parser->use_namespace = 1; - parser->_ns_separator = xmlStrdup(sep); + parser->_ns_separator = BAD_CAST estrdup((const char *) sep); } else { /* Reset flag as XML_SAX2_MAGIC is needed for xmlCreatePushParserCtxt so must be set in the handlers */ @@ -695,25 +644,12 @@ XML_GetCurrentByteIndex(XML_Parser parser) (parser->parser->input->cur - parser->parser->input->base); } -PHP_XML_API int -XML_GetCurrentByteCount(XML_Parser parser) -{ - /* TODO: this is identical to ByteIndex; it should probably - * be different */ - return (int) XML_GetCurrentByteIndex(parser); -} - -PHP_XML_API const XML_Char *XML_ExpatVersion(void) -{ - return (const XML_Char *) "1.0"; -} - PHP_XML_API void XML_ParserFree(XML_Parser parser) { if (parser->use_namespace) { if (parser->_ns_separator) { - xmlFree(parser->_ns_separator); + efree(parser->_ns_separator); } } if (parser->parser->myDoc) { diff --git a/ext/xml/expat_compat.h b/ext/xml/expat_compat.h index 94ca8aeb4c351..a7faffbac504f 100644 --- a/ext/xml/expat_compat.h +++ b/ext/xml/expat_compat.h @@ -147,8 +147,6 @@ PHP_XML_API const XML_Char *XML_ErrorString(int); PHP_XML_API int XML_GetCurrentLineNumber(XML_Parser); PHP_XML_API int XML_GetCurrentColumnNumber(XML_Parser); PHP_XML_API long XML_GetCurrentByteIndex(XML_Parser); -PHP_XML_API int XML_GetCurrentByteCount(XML_Parser); -PHP_XML_API const XML_Char *XML_ExpatVersion(void); PHP_XML_API void XML_ParserFree(XML_Parser); #elif defined(HAVE_LIBEXPAT) 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/gh20439_1.phpt b/ext/xml/tests/gh20439_1.phpt new file mode 100644 index 0000000000000..cda6803e9d078 --- /dev/null +++ b/ext/xml/tests/gh20439_1.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-20439 (xml_set_default_handler() does not properly handle special characters in attributes when passing data to callback) +--EXTENSIONS-- +xml +--FILE-- +"; +$inputs = str_split($input); + +// Test chunked parser wrt non-progressive parser +foreach ($inputs as $input) { + xml_parse($x, $input, false); +} +xml_parse($x, "", true); + +?> +--EXPECT-- +string(12) "" +string(71) "" +string(6) "" diff --git a/ext/xml/tests/gh20439_2.phpt b/ext/xml/tests/gh20439_2.phpt new file mode 100644 index 0000000000000..dce4f5976a140 --- /dev/null +++ b/ext/xml/tests/gh20439_2.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-20439 (xml_set_default_handler() does not properly handle special characters in attributes when passing data to callback) - closing solidus variant +--EXTENSIONS-- +xml +--SKIPIF-- + +--FILE-- +"; +xml_parse($x, $input, true); + +?> +--EXPECT-- +string(29) "" +string(10) "" 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.c b/ext/xml/xml.c index bf9f747599730..7a9329bcc8041 100644 --- a/ext/xml/xml.c +++ b/ext/xml/xml.c @@ -64,11 +64,7 @@ typedef struct { XML_Parser parser; XML_Char *target_encoding; - /* Reference to the object itself, for convenience. - * It is not owned, do not release it. */ - zval index; - - zend_object *object; + zend_object *object; /* object with handlers */ zend_fcall_info_cache startElementHandler; zend_fcall_info_cache endElementHandler; zend_fcall_info_cache characterDataHandler; @@ -135,7 +131,7 @@ inline static char xml_decode_iso_8859_1(unsigned short); inline static unsigned short xml_encode_us_ascii(unsigned char); inline static char xml_decode_us_ascii(unsigned short); static void xml_xmlchar_zval(const XML_Char *, int, const XML_Char *, zval *); -static int xml_xmlcharlen(const XML_Char *); +static size_t xml_xmlcharlen(const XML_Char *); static void xml_add_to_info(xml_parser *parser, zend_string *name); inline static zend_string *xml_decode_tag(xml_parser *parser, const XML_Char *tag); @@ -282,9 +278,9 @@ static int xml_parse_helper(xml_parser *parser, const char *data, size_t data_le ZEND_DIAGNOSTIC_IGNORED_END #endif - parser->isparsing = 1; + parser->isparsing = true; int ret = XML_Parse(parser->parser, (const XML_Char *) data, data_len, is_final); - parser->isparsing = 0; + parser->isparsing = false; return ret; } @@ -540,15 +536,9 @@ static zend_string *xml_utf8_decode(const XML_Char *s, size_t len, const XML_Cha /* }}} */ /* {{{ xml_xmlcharlen() */ -static int xml_xmlcharlen(const XML_Char *s) +static size_t xml_xmlcharlen(const XML_Char *s) { - int len = 0; - - while (*s) { - len++; - s++; - } - return len; + return strlen((const char *) s); } /* }}} */ @@ -641,7 +631,7 @@ void xml_startElementHandler(void *userData, const XML_Char *name, const XML_Cha if (ZEND_FCC_INITIALIZED(parser->startElementHandler)) { zval args[3]; - ZVAL_COPY(&args[0], &parser->index); + ZVAL_OBJ(&args[0], &parser->std); ZVAL_STR(&args[1], xml_stripped_tag(tag_name, parser->toffset)); array_init(&args[2]); @@ -652,7 +642,7 @@ void xml_startElementHandler(void *userData, const XML_Char *name, const XML_Cha val = xml_utf8_decode(attributes[1], strlen((char *)attributes[1]), parser->target_encoding); ZVAL_STR(&tmp, val); - zend_symtable_update(Z_ARRVAL(args[2]), att, &tmp); + zend_hash_update(Z_ARRVAL(args[2]), att, &tmp); attributes += 2; @@ -660,7 +650,6 @@ void xml_startElementHandler(void *userData, const XML_Char *name, const XML_Cha } zend_call_known_fcc(&parser->startElementHandler, /* retval */ NULL, /* param_count */ 3, args, /* named_params */ NULL); - zval_ptr_dtor(&args[0]); zval_ptr_dtor_str(&args[1]); zval_ptr_dtor(&args[2]); } @@ -682,7 +671,7 @@ void xml_startElementHandler(void *userData, const XML_Char *name, const XML_Cha /* Because toffset may change, we should use the original tag name */ parser->ltags[parser->level - 1] = zend_string_copy(tag_name); - parser->lastwasopen = 1; + parser->lastwasopen = true; attributes = (const XML_Char **) attrs; @@ -693,7 +682,7 @@ void xml_startElementHandler(void *userData, const XML_Char *name, const XML_Cha val = xml_utf8_decode(attributes[1], strlen((char *)attributes[1]), parser->target_encoding); ZVAL_STR(&tmp, val); - zend_symtable_update(Z_ARRVAL(atr), att, &tmp); + zend_hash_update(Z_ARRVAL(atr), att, &tmp); atcnt++; attributes += 2; @@ -742,11 +731,10 @@ void xml_endElementHandler(void *userData, const XML_Char *name) if (ZEND_FCC_INITIALIZED(parser->endElementHandler)) { zval args[2]; - ZVAL_COPY(&args[0], &parser->index); + ZVAL_OBJ(&args[0], &parser->std); ZVAL_STR(&args[1], xml_stripped_tag(tag_name, parser->toffset)); zend_call_known_fcc(&parser->endElementHandler, /* retval */ NULL, /* param_count */ 2, args, /* named_params */ NULL); - zval_ptr_dtor(&args[0]); zval_ptr_dtor_str(&args[1]); } @@ -775,7 +763,7 @@ void xml_endElementHandler(void *userData, const XML_Char *name) } } - parser->lastwasopen = 0; + parser->lastwasopen = false; } zend_string_release_ex(tag_name, 0); @@ -803,11 +791,10 @@ void xml_characterDataHandler(void *userData, const XML_Char *s, int len) if (ZEND_FCC_INITIALIZED(parser->characterDataHandler)) { zval args[2]; - ZVAL_COPY(&args[0], &parser->index); + ZVAL_OBJ(&args[0], &parser->std); xml_xmlchar_zval(s, len, parser->target_encoding, &args[1]); zend_call_known_fcc(&parser->characterDataHandler, /* retval */ NULL, /* param_count */ 2, args, /* named_params */ NULL); - zval_ptr_dtor(&args[0]); zval_ptr_dtor_str(&args[1]); } @@ -815,7 +802,7 @@ void xml_characterDataHandler(void *userData, const XML_Char *s, int len) return; } - bool doprint = 0; + bool doprint = false; zend_string *decoded_value; decoded_value = xml_utf8_decode(s, len, parser->target_encoding); if (parser->skipwhite) { @@ -826,7 +813,7 @@ void xml_characterDataHandler(void *userData, const XML_Char *s, int len) case '\n': continue; default: - doprint = 1; + doprint = true; break; } if (doprint) { @@ -911,12 +898,11 @@ void xml_processingInstructionHandler(void *userData, const XML_Char *target, co zval args[3]; - ZVAL_COPY(&args[0], &parser->index); + ZVAL_OBJ(&args[0], &parser->std); xml_xmlchar_zval(target, 0, parser->target_encoding, &args[1]); xml_xmlchar_zval(data, 0, parser->target_encoding, &args[2]); zend_call_known_fcc(&parser->processingInstructionHandler, /* retval */ NULL, /* param_count */ 3, args, /* named_params */ NULL); - zval_ptr_dtor(&args[0]); zval_ptr_dtor_str(&args[1]); zval_ptr_dtor_str(&args[2]); } @@ -933,11 +919,10 @@ void xml_defaultHandler(void *userData, const XML_Char *s, int len) zval args[2]; - ZVAL_COPY(&args[0], &parser->index); + ZVAL_OBJ(&args[0], &parser->std); xml_xmlchar_zval(s, len, parser->target_encoding, &args[1]); zend_call_known_fcc(&parser->defaultHandler, /* retval */ NULL, /* param_count */ 2, args, /* named_params */ NULL); - zval_ptr_dtor(&args[0]); zval_ptr_dtor_str(&args[1]); } /* }}} */ @@ -955,7 +940,7 @@ void xml_unparsedEntityDeclHandler(void *userData, zval args[6]; - ZVAL_COPY(&args[0], &parser->index); + ZVAL_OBJ(&args[0], &parser->std); xml_xmlchar_zval(entityName, 0, parser->target_encoding, &args[1]); xml_xmlchar_zval(base, 0, parser->target_encoding, &args[2]); xml_xmlchar_zval(systemId, 0, parser->target_encoding, &args[3]); @@ -963,7 +948,6 @@ void xml_unparsedEntityDeclHandler(void *userData, xml_xmlchar_zval(notationName, 0, parser->target_encoding, &args[5]); zend_call_known_fcc(&parser->unparsedEntityDeclHandler, /* retval */ NULL, /* param_count */ 6, args, /* named_params */ NULL); - zval_ptr_dtor(&args[0]); zval_ptr_dtor_str(&args[1]); zval_ptr_dtor_str(&args[2]); zval_ptr_dtor_str(&args[3]); @@ -984,14 +968,13 @@ void xml_notationDeclHandler(void *userData, const XML_Char *notationName, zval args[5]; - ZVAL_COPY(&args[0], &parser->index); + ZVAL_OBJ(&args[0], &parser->std); xml_xmlchar_zval(notationName, 0, parser->target_encoding, &args[1]); xml_xmlchar_zval(base, 0, parser->target_encoding, &args[2]); xml_xmlchar_zval(systemId, 0, parser->target_encoding, &args[3]); xml_xmlchar_zval(publicId, 0, parser->target_encoding, &args[4]); zend_call_known_fcc(&parser->notationDeclHandler, /* retval */ NULL, /* param_count */ 5, args, /* named_params */ NULL); - zval_ptr_dtor(&args[0]); zval_ptr_dtor_str(&args[1]); zval_ptr_dtor_str(&args[2]); zval_ptr_dtor_str(&args[3]); @@ -1013,14 +996,13 @@ int xml_externalEntityRefHandler(XML_Parser userData, const XML_Char *openEntity zval args[5]; zval retval; - ZVAL_COPY(&args[0], &parser->index); + ZVAL_OBJ(&args[0], &parser->std); xml_xmlchar_zval(openEntityNames, 0, parser->target_encoding, &args[1]); xml_xmlchar_zval(base, 0, parser->target_encoding, &args[2]); xml_xmlchar_zval(systemId, 0, parser->target_encoding, &args[3]); xml_xmlchar_zval(publicId, 0, parser->target_encoding, &args[4]); zend_call_known_fcc(&parser->externalEntityRefHandler, /* retval */ &retval, /* param_count */ 5, args, /* named_params */ NULL); - zval_ptr_dtor(&args[0]); zval_ptr_dtor_str(&args[1]); zval_ptr_dtor_str(&args[2]); zval_ptr_dtor_str(&args[3]); @@ -1048,12 +1030,11 @@ void xml_startNamespaceDeclHandler(void *userData,const XML_Char *prefix, const zval args[3]; - ZVAL_COPY(&args[0], &parser->index); + ZVAL_OBJ(&args[0], &parser->std); xml_xmlchar_zval(prefix, 0, parser->target_encoding, &args[1]); xml_xmlchar_zval(uri, 0, parser->target_encoding, &args[2]); zend_call_known_fcc(&parser->startNamespaceDeclHandler, /* retval */ NULL, /* param_count */ 3, args, /* named_params */ NULL); - zval_ptr_dtor(&args[0]); zval_ptr_dtor_str(&args[1]); zval_ptr_dtor_str(&args[2]); } @@ -1070,11 +1051,10 @@ void xml_endNamespaceDeclHandler(void *userData, const XML_Char *prefix) zval args[2]; - ZVAL_COPY(&args[0], &parser->index); + ZVAL_OBJ(&args[0], &parser->std); xml_xmlchar_zval(prefix, 0, parser->target_encoding, &args[1]); zend_call_known_fcc(&parser->endNamespaceDeclHandler, /* retval */ NULL, /* param_count */ 2, args, /* named_params */ NULL); - zval_ptr_dtor(&args[0]); zval_ptr_dtor_str(&args[1]); } /* }}} */ @@ -1128,12 +1108,11 @@ static void php_xml_parser_create_impl(INTERNAL_FUNCTION_PARAMETERS, int ns_supp &php_xml_mem_hdlrs, (XML_Char*)ns_param); parser->target_encoding = encoding; - parser->case_folding = 1; - parser->isparsing = 0; + parser->case_folding = true; + parser->isparsing = false; parser->parsehuge = false; /* It's the default for BC & DoS protection */ XML_SetUserData(parser->parser, parser); - ZVAL_COPY_VALUE(&parser->index, return_value); } /* }}} */ @@ -1410,7 +1389,7 @@ PHP_FUNCTION(xml_parse) zval *pind; char *data; size_t data_len; - bool isFinal = 0; + bool isFinal = false; if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os|b", &pind, xml_parser_ce, &data, &data_len, &isFinal) == FAILURE) { RETURN_THROWS(); 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 61cad2c9d11f7..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 @@ -166,11 +166,16 @@ 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_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/php_xmlreader.c b/ext/xmlreader/php_xmlreader.c index b4d02c04ab4ac..d379b6dfad99b 100644 --- a/ext/xmlreader/php_xmlreader.c +++ b/ext/xmlreader/php_xmlreader.c @@ -517,12 +517,7 @@ static void php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAMETERS, xmlreader_ /* {{{ php_xmlreader_set_relaxng_schema */ static void php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAMETERS, int type) { -#ifdef LIBXML_SCHEMAS_ENABLED - zval *id; size_t source_len = 0; - int retval = -1; - xmlreader_object *intern; - xmlRelaxNGPtr schema = NULL; char *source; if (zend_parse_parameters(ZEND_NUM_ARGS(), "p!", &source, &source_len) == FAILURE) { @@ -533,11 +528,13 @@ static void php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAMETERS, int t zend_argument_must_not_be_empty_error(1); RETURN_THROWS(); } - - id = ZEND_THIS; - - intern = Z_XMLREADER_P(id); + +#ifdef LIBXML_SCHEMAS_ENABLED + xmlreader_object *intern = Z_XMLREADER_P(ZEND_THIS); if (intern->ptr) { + int retval = -1; + xmlRelaxNGPtr schema = NULL; + if (source) { schema = _xmlreader_get_relaxNG(source, source_len, type, NULL, NULL); if (schema) { @@ -557,6 +554,7 @@ static void php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAMETERS, int t RETURN_TRUE; } else { + xmlRelaxNGFree(schema); php_error_docref(NULL, E_WARNING, "Schema contains errors"); RETURN_FALSE; } @@ -1078,11 +1076,7 @@ PHP_METHOD(XMLReader, readString) /* {{{ Use W3C XSD schema to validate the document as it is processed. Activation is only possible before the first Read(). */ PHP_METHOD(XMLReader, setSchema) { -#ifdef LIBXML_SCHEMAS_ENABLED - zval *id; size_t source_len = 0; - int retval = -1; - xmlreader_object *intern; char *source; if (zend_parse_parameters(ZEND_NUM_ARGS(), "p!", &source, &source_len) == FAILURE) { @@ -1093,13 +1087,12 @@ PHP_METHOD(XMLReader, setSchema) zend_argument_must_not_be_empty_error(1); RETURN_THROWS(); } - - id = ZEND_THIS; - - intern = Z_XMLREADER_P(id); + +#ifdef LIBXML_SCHEMAS_ENABLED + xmlreader_object *intern = Z_XMLREADER_P(ZEND_THIS); if (intern && intern->ptr) { PHP_LIBXML_SANITIZE_GLOBALS(schema); - retval = xmlTextReaderSchemaValidate(intern->ptr, source); + int retval = xmlTextReaderSchemaValidate(intern->ptr, source); PHP_LIBXML_RESTORE_GLOBALS(schema); if (retval == 0) { diff --git a/ext/xmlreader/php_xmlreader_arginfo.h b/ext/xmlreader/php_xmlreader_arginfo.h index dd5ca550f606d..ef54bfa4c235f 100644 --- a/ext/xmlreader/php_xmlreader_arginfo.h +++ b/ext/xmlreader/php_xmlreader_arginfo.h @@ -180,183 +180,183 @@ static zend_class_entry *register_class_XMLReader(void) zval const_NONE_value; ZVAL_LONG(&const_NONE_value, XML_READER_TYPE_NONE); - zend_string *const_NONE_name = zend_string_init_interned("NONE", sizeof("NONE") - 1, 1); + zend_string *const_NONE_name = zend_string_init_interned("NONE", sizeof("NONE") - 1, true); zend_declare_typed_class_constant(class_entry, const_NONE_name, &const_NONE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NONE_name); + zend_string_release_ex(const_NONE_name, true); zval const_ELEMENT_value; ZVAL_LONG(&const_ELEMENT_value, XML_READER_TYPE_ELEMENT); - zend_string *const_ELEMENT_name = zend_string_init_interned("ELEMENT", sizeof("ELEMENT") - 1, 1); + zend_string *const_ELEMENT_name = zend_string_init_interned("ELEMENT", sizeof("ELEMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_ELEMENT_name, &const_ELEMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ELEMENT_name); + zend_string_release_ex(const_ELEMENT_name, true); zval const_ATTRIBUTE_value; ZVAL_LONG(&const_ATTRIBUTE_value, XML_READER_TYPE_ATTRIBUTE); - zend_string *const_ATTRIBUTE_name = zend_string_init_interned("ATTRIBUTE", sizeof("ATTRIBUTE") - 1, 1); + zend_string *const_ATTRIBUTE_name = zend_string_init_interned("ATTRIBUTE", sizeof("ATTRIBUTE") - 1, true); zend_declare_typed_class_constant(class_entry, const_ATTRIBUTE_name, &const_ATTRIBUTE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ATTRIBUTE_name); + zend_string_release_ex(const_ATTRIBUTE_name, true); zval const_TEXT_value; ZVAL_LONG(&const_TEXT_value, XML_READER_TYPE_TEXT); - zend_string *const_TEXT_name = zend_string_init_interned("TEXT", sizeof("TEXT") - 1, 1); + zend_string *const_TEXT_name = zend_string_init_interned("TEXT", sizeof("TEXT") - 1, true); zend_declare_typed_class_constant(class_entry, const_TEXT_name, &const_TEXT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_TEXT_name); + zend_string_release_ex(const_TEXT_name, true); zval const_CDATA_value; ZVAL_LONG(&const_CDATA_value, XML_READER_TYPE_CDATA); - zend_string *const_CDATA_name = zend_string_init_interned("CDATA", sizeof("CDATA") - 1, 1); + zend_string *const_CDATA_name = zend_string_init_interned("CDATA", sizeof("CDATA") - 1, true); zend_declare_typed_class_constant(class_entry, const_CDATA_name, &const_CDATA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CDATA_name); + zend_string_release_ex(const_CDATA_name, true); zval const_ENTITY_REF_value; ZVAL_LONG(&const_ENTITY_REF_value, XML_READER_TYPE_ENTITY_REFERENCE); - zend_string *const_ENTITY_REF_name = zend_string_init_interned("ENTITY_REF", sizeof("ENTITY_REF") - 1, 1); + zend_string *const_ENTITY_REF_name = zend_string_init_interned("ENTITY_REF", sizeof("ENTITY_REF") - 1, true); zend_declare_typed_class_constant(class_entry, const_ENTITY_REF_name, &const_ENTITY_REF_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ENTITY_REF_name); + zend_string_release_ex(const_ENTITY_REF_name, true); zval const_ENTITY_value; ZVAL_LONG(&const_ENTITY_value, XML_READER_TYPE_ENTITY); - zend_string *const_ENTITY_name = zend_string_init_interned("ENTITY", sizeof("ENTITY") - 1, 1); + zend_string *const_ENTITY_name = zend_string_init_interned("ENTITY", sizeof("ENTITY") - 1, true); zend_declare_typed_class_constant(class_entry, const_ENTITY_name, &const_ENTITY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ENTITY_name); + zend_string_release_ex(const_ENTITY_name, true); zval const_PI_value; ZVAL_LONG(&const_PI_value, XML_READER_TYPE_PROCESSING_INSTRUCTION); - zend_string *const_PI_name = zend_string_init_interned("PI", sizeof("PI") - 1, 1); + zend_string *const_PI_name = zend_string_init_interned("PI", sizeof("PI") - 1, true); zend_declare_typed_class_constant(class_entry, const_PI_name, &const_PI_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_PI_name); + zend_string_release_ex(const_PI_name, true); zval const_COMMENT_value; ZVAL_LONG(&const_COMMENT_value, XML_READER_TYPE_COMMENT); - zend_string *const_COMMENT_name = zend_string_init_interned("COMMENT", sizeof("COMMENT") - 1, 1); + zend_string *const_COMMENT_name = zend_string_init_interned("COMMENT", sizeof("COMMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_COMMENT_name, &const_COMMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_COMMENT_name); + zend_string_release_ex(const_COMMENT_name, true); zval const_DOC_value; ZVAL_LONG(&const_DOC_value, XML_READER_TYPE_DOCUMENT); - zend_string *const_DOC_name = zend_string_init_interned("DOC", sizeof("DOC") - 1, 1); + zend_string *const_DOC_name = zend_string_init_interned("DOC", sizeof("DOC") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOC_name, &const_DOC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOC_name); + zend_string_release_ex(const_DOC_name, true); zval const_DOC_TYPE_value; ZVAL_LONG(&const_DOC_TYPE_value, XML_READER_TYPE_DOCUMENT_TYPE); - zend_string *const_DOC_TYPE_name = zend_string_init_interned("DOC_TYPE", sizeof("DOC_TYPE") - 1, 1); + zend_string *const_DOC_TYPE_name = zend_string_init_interned("DOC_TYPE", sizeof("DOC_TYPE") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOC_TYPE_name, &const_DOC_TYPE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOC_TYPE_name); + zend_string_release_ex(const_DOC_TYPE_name, true); zval const_DOC_FRAGMENT_value; ZVAL_LONG(&const_DOC_FRAGMENT_value, XML_READER_TYPE_DOCUMENT_FRAGMENT); - zend_string *const_DOC_FRAGMENT_name = zend_string_init_interned("DOC_FRAGMENT", sizeof("DOC_FRAGMENT") - 1, 1); + zend_string *const_DOC_FRAGMENT_name = zend_string_init_interned("DOC_FRAGMENT", sizeof("DOC_FRAGMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_DOC_FRAGMENT_name, &const_DOC_FRAGMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DOC_FRAGMENT_name); + zend_string_release_ex(const_DOC_FRAGMENT_name, true); zval const_NOTATION_value; ZVAL_LONG(&const_NOTATION_value, XML_READER_TYPE_NOTATION); - zend_string *const_NOTATION_name = zend_string_init_interned("NOTATION", sizeof("NOTATION") - 1, 1); + zend_string *const_NOTATION_name = zend_string_init_interned("NOTATION", sizeof("NOTATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_NOTATION_name, &const_NOTATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_NOTATION_name); + zend_string_release_ex(const_NOTATION_name, true); zval const_WHITESPACE_value; ZVAL_LONG(&const_WHITESPACE_value, XML_READER_TYPE_WHITESPACE); - zend_string *const_WHITESPACE_name = zend_string_init_interned("WHITESPACE", sizeof("WHITESPACE") - 1, 1); + zend_string *const_WHITESPACE_name = zend_string_init_interned("WHITESPACE", sizeof("WHITESPACE") - 1, true); zend_declare_typed_class_constant(class_entry, const_WHITESPACE_name, &const_WHITESPACE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_WHITESPACE_name); + zend_string_release_ex(const_WHITESPACE_name, true); zval const_SIGNIFICANT_WHITESPACE_value; ZVAL_LONG(&const_SIGNIFICANT_WHITESPACE_value, XML_READER_TYPE_SIGNIFICANT_WHITESPACE); - zend_string *const_SIGNIFICANT_WHITESPACE_name = zend_string_init_interned("SIGNIFICANT_WHITESPACE", sizeof("SIGNIFICANT_WHITESPACE") - 1, 1); + zend_string *const_SIGNIFICANT_WHITESPACE_name = zend_string_init_interned("SIGNIFICANT_WHITESPACE", sizeof("SIGNIFICANT_WHITESPACE") - 1, true); zend_declare_typed_class_constant(class_entry, const_SIGNIFICANT_WHITESPACE_name, &const_SIGNIFICANT_WHITESPACE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SIGNIFICANT_WHITESPACE_name); + zend_string_release_ex(const_SIGNIFICANT_WHITESPACE_name, true); zval const_END_ELEMENT_value; ZVAL_LONG(&const_END_ELEMENT_value, XML_READER_TYPE_END_ELEMENT); - zend_string *const_END_ELEMENT_name = zend_string_init_interned("END_ELEMENT", sizeof("END_ELEMENT") - 1, 1); + zend_string *const_END_ELEMENT_name = zend_string_init_interned("END_ELEMENT", sizeof("END_ELEMENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_END_ELEMENT_name, &const_END_ELEMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_END_ELEMENT_name); + zend_string_release_ex(const_END_ELEMENT_name, true); zval const_END_ENTITY_value; ZVAL_LONG(&const_END_ENTITY_value, XML_READER_TYPE_END_ENTITY); - zend_string *const_END_ENTITY_name = zend_string_init_interned("END_ENTITY", sizeof("END_ENTITY") - 1, 1); + zend_string *const_END_ENTITY_name = zend_string_init_interned("END_ENTITY", sizeof("END_ENTITY") - 1, true); zend_declare_typed_class_constant(class_entry, const_END_ENTITY_name, &const_END_ENTITY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_END_ENTITY_name); + zend_string_release_ex(const_END_ENTITY_name, true); zval const_XML_DECLARATION_value; ZVAL_LONG(&const_XML_DECLARATION_value, XML_READER_TYPE_XML_DECLARATION); - zend_string *const_XML_DECLARATION_name = zend_string_init_interned("XML_DECLARATION", sizeof("XML_DECLARATION") - 1, 1); + zend_string *const_XML_DECLARATION_name = zend_string_init_interned("XML_DECLARATION", sizeof("XML_DECLARATION") - 1, true); zend_declare_typed_class_constant(class_entry, const_XML_DECLARATION_name, &const_XML_DECLARATION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_XML_DECLARATION_name); + zend_string_release_ex(const_XML_DECLARATION_name, true); zval const_LOADDTD_value; ZVAL_LONG(&const_LOADDTD_value, XML_PARSER_LOADDTD); - zend_string *const_LOADDTD_name = zend_string_init_interned("LOADDTD", sizeof("LOADDTD") - 1, 1); + zend_string *const_LOADDTD_name = zend_string_init_interned("LOADDTD", sizeof("LOADDTD") - 1, true); zend_declare_typed_class_constant(class_entry, const_LOADDTD_name, &const_LOADDTD_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LOADDTD_name); + zend_string_release_ex(const_LOADDTD_name, true); zval const_DEFAULTATTRS_value; ZVAL_LONG(&const_DEFAULTATTRS_value, XML_PARSER_DEFAULTATTRS); - zend_string *const_DEFAULTATTRS_name = zend_string_init_interned("DEFAULTATTRS", sizeof("DEFAULTATTRS") - 1, 1); + zend_string *const_DEFAULTATTRS_name = zend_string_init_interned("DEFAULTATTRS", sizeof("DEFAULTATTRS") - 1, true); zend_declare_typed_class_constant(class_entry, const_DEFAULTATTRS_name, &const_DEFAULTATTRS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_DEFAULTATTRS_name); + zend_string_release_ex(const_DEFAULTATTRS_name, true); zval const_VALIDATE_value; ZVAL_LONG(&const_VALIDATE_value, XML_PARSER_VALIDATE); - zend_string *const_VALIDATE_name = zend_string_init_interned("VALIDATE", sizeof("VALIDATE") - 1, 1); + zend_string *const_VALIDATE_name = zend_string_init_interned("VALIDATE", sizeof("VALIDATE") - 1, true); zend_declare_typed_class_constant(class_entry, const_VALIDATE_name, &const_VALIDATE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_VALIDATE_name); + zend_string_release_ex(const_VALIDATE_name, true); zval const_SUBST_ENTITIES_value; ZVAL_LONG(&const_SUBST_ENTITIES_value, XML_PARSER_SUBST_ENTITIES); - zend_string *const_SUBST_ENTITIES_name = zend_string_init_interned("SUBST_ENTITIES", sizeof("SUBST_ENTITIES") - 1, 1); + zend_string *const_SUBST_ENTITIES_name = zend_string_init_interned("SUBST_ENTITIES", sizeof("SUBST_ENTITIES") - 1, true); zend_declare_typed_class_constant(class_entry, const_SUBST_ENTITIES_name, &const_SUBST_ENTITIES_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_SUBST_ENTITIES_name); + zend_string_release_ex(const_SUBST_ENTITIES_name, true); zval property_attributeCount_default_value; ZVAL_UNDEF(&property_attributeCount_default_value); - zend_string *property_attributeCount_name = zend_string_init("attributeCount", sizeof("attributeCount") - 1, 1); + zend_string *property_attributeCount_name = zend_string_init("attributeCount", sizeof("attributeCount") - 1, true); zend_declare_typed_property(class_entry, property_attributeCount_name, &property_attributeCount_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_attributeCount_name); + zend_string_release_ex(property_attributeCount_name, true); zval property_baseURI_default_value; ZVAL_UNDEF(&property_baseURI_default_value); - zend_string *property_baseURI_name = zend_string_init("baseURI", sizeof("baseURI") - 1, 1); + zend_string *property_baseURI_name = zend_string_init("baseURI", sizeof("baseURI") - 1, true); zend_declare_typed_property(class_entry, property_baseURI_name, &property_baseURI_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_baseURI_name); + zend_string_release_ex(property_baseURI_name, true); zval property_depth_default_value; ZVAL_UNDEF(&property_depth_default_value); - zend_string *property_depth_name = zend_string_init("depth", sizeof("depth") - 1, 1); + zend_string *property_depth_name = zend_string_init("depth", sizeof("depth") - 1, true); zend_declare_typed_property(class_entry, property_depth_name, &property_depth_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_depth_name); + zend_string_release_ex(property_depth_name, true); zval property_hasAttributes_default_value; ZVAL_UNDEF(&property_hasAttributes_default_value); - zend_string *property_hasAttributes_name = zend_string_init("hasAttributes", sizeof("hasAttributes") - 1, 1); + zend_string *property_hasAttributes_name = zend_string_init("hasAttributes", sizeof("hasAttributes") - 1, true); zend_declare_typed_property(class_entry, property_hasAttributes_name, &property_hasAttributes_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_hasAttributes_name); + zend_string_release_ex(property_hasAttributes_name, true); zval property_hasValue_default_value; ZVAL_UNDEF(&property_hasValue_default_value); - zend_string *property_hasValue_name = zend_string_init("hasValue", sizeof("hasValue") - 1, 1); + zend_string *property_hasValue_name = zend_string_init("hasValue", sizeof("hasValue") - 1, true); zend_declare_typed_property(class_entry, property_hasValue_name, &property_hasValue_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_hasValue_name); + zend_string_release_ex(property_hasValue_name, true); zval property_isDefault_default_value; ZVAL_UNDEF(&property_isDefault_default_value); - zend_string *property_isDefault_name = zend_string_init("isDefault", sizeof("isDefault") - 1, 1); + zend_string *property_isDefault_name = zend_string_init("isDefault", sizeof("isDefault") - 1, true); zend_declare_typed_property(class_entry, property_isDefault_name, &property_isDefault_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_isDefault_name); + zend_string_release_ex(property_isDefault_name, true); zval property_isEmptyElement_default_value; ZVAL_UNDEF(&property_isEmptyElement_default_value); - zend_string *property_isEmptyElement_name = zend_string_init("isEmptyElement", sizeof("isEmptyElement") - 1, 1); + zend_string *property_isEmptyElement_name = zend_string_init("isEmptyElement", sizeof("isEmptyElement") - 1, true); zend_declare_typed_property(class_entry, property_isEmptyElement_name, &property_isEmptyElement_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_isEmptyElement_name); + zend_string_release_ex(property_isEmptyElement_name, true); zval property_localName_default_value; ZVAL_UNDEF(&property_localName_default_value); - zend_string *property_localName_name = zend_string_init("localName", sizeof("localName") - 1, 1); + zend_string *property_localName_name = zend_string_init("localName", sizeof("localName") - 1, true); zend_declare_typed_property(class_entry, property_localName_name, &property_localName_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_localName_name); + zend_string_release_ex(property_localName_name, true); zval property_name_default_value; ZVAL_UNDEF(&property_name_default_value); @@ -364,21 +364,21 @@ static zend_class_entry *register_class_XMLReader(void) zval property_namespaceURI_default_value; ZVAL_UNDEF(&property_namespaceURI_default_value); - zend_string *property_namespaceURI_name = zend_string_init("namespaceURI", sizeof("namespaceURI") - 1, 1); + zend_string *property_namespaceURI_name = zend_string_init("namespaceURI", sizeof("namespaceURI") - 1, true); zend_declare_typed_property(class_entry, property_namespaceURI_name, &property_namespaceURI_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_namespaceURI_name); + zend_string_release_ex(property_namespaceURI_name, true); zval property_nodeType_default_value; ZVAL_UNDEF(&property_nodeType_default_value); - zend_string *property_nodeType_name = zend_string_init("nodeType", sizeof("nodeType") - 1, 1); + zend_string *property_nodeType_name = zend_string_init("nodeType", sizeof("nodeType") - 1, true); zend_declare_typed_property(class_entry, property_nodeType_name, &property_nodeType_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_nodeType_name); + zend_string_release_ex(property_nodeType_name, true); zval property_prefix_default_value; ZVAL_UNDEF(&property_prefix_default_value); - zend_string *property_prefix_name = zend_string_init("prefix", sizeof("prefix") - 1, 1); + zend_string *property_prefix_name = zend_string_init("prefix", sizeof("prefix") - 1, true); zend_declare_typed_property(class_entry, property_prefix_name, &property_prefix_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_prefix_name); + zend_string_release_ex(property_prefix_name, true); zval property_value_default_value; ZVAL_UNDEF(&property_value_default_value); @@ -386,9 +386,9 @@ static zend_class_entry *register_class_XMLReader(void) zval property_xmlLang_default_value; ZVAL_UNDEF(&property_xmlLang_default_value); - zend_string *property_xmlLang_name = zend_string_init("xmlLang", sizeof("xmlLang") - 1, 1); + zend_string *property_xmlLang_name = zend_string_init("xmlLang", sizeof("xmlLang") - 1, true); zend_declare_typed_property(class_entry, property_xmlLang_name, &property_xmlLang_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_xmlLang_name); + zend_string_release_ex(property_xmlLang_name, true); return class_entry; } 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/xmlwriter/php_xmlwriter.c b/ext/xmlwriter/php_xmlwriter.c index f9dd7f48c86fb..6d711e89b89d4 100644 --- a/ext/xmlwriter/php_xmlwriter.c +++ b/ext/xmlwriter/php_xmlwriter.c @@ -765,7 +765,7 @@ PHP_FUNCTION(xmlwriter_write_dtd_entity) int retval; /* Optional parameters */ char *pubid = NULL, *sysid = NULL, *ndataid = NULL; - bool pe = 0; + bool pe = false; size_t pubid_len, sysid_len, ndataid_len; zval *self; @@ -1006,7 +1006,7 @@ PHP_METHOD(XMLWriter, toStream) /* {{{ php_xmlwriter_flush */ static void php_xmlwriter_flush(INTERNAL_FUNCTION_PARAMETERS, int force_string) { xmlTextWriterPtr ptr; - bool empty = 1; + bool empty = true; int output_bytes; zval *self; 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..b1f4fd7601c58 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) @@ -119,27 +119,27 @@ static zend_class_entry *register_class_XSLTProcessor(void) zval property_doXInclude_default_value; ZVAL_FALSE(&property_doXInclude_default_value); - zend_string *property_doXInclude_name = zend_string_init("doXInclude", sizeof("doXInclude") - 1, 1); + zend_string *property_doXInclude_name = zend_string_init("doXInclude", sizeof("doXInclude") - 1, true); zend_declare_typed_property(class_entry, property_doXInclude_name, &property_doXInclude_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_doXInclude_name); + zend_string_release_ex(property_doXInclude_name, true); zval property_cloneDocument_default_value; ZVAL_FALSE(&property_cloneDocument_default_value); - zend_string *property_cloneDocument_name = zend_string_init("cloneDocument", sizeof("cloneDocument") - 1, 1); + zend_string *property_cloneDocument_name = zend_string_init("cloneDocument", sizeof("cloneDocument") - 1, true); zend_declare_typed_property(class_entry, property_cloneDocument_name, &property_cloneDocument_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_cloneDocument_name); + zend_string_release_ex(property_cloneDocument_name, true); zval property_maxTemplateDepth_default_value; ZVAL_UNDEF(&property_maxTemplateDepth_default_value); - zend_string *property_maxTemplateDepth_name = zend_string_init("maxTemplateDepth", sizeof("maxTemplateDepth") - 1, 1); + zend_string *property_maxTemplateDepth_name = zend_string_init("maxTemplateDepth", sizeof("maxTemplateDepth") - 1, true); zend_declare_typed_property(class_entry, property_maxTemplateDepth_name, &property_maxTemplateDepth_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_maxTemplateDepth_name); + zend_string_release_ex(property_maxTemplateDepth_name, true); zval property_maxTemplateVars_default_value; ZVAL_UNDEF(&property_maxTemplateVars_default_value); - zend_string *property_maxTemplateVars_name = zend_string_init("maxTemplateVars", sizeof("maxTemplateVars") - 1, 1); + zend_string *property_maxTemplateVars_name = zend_string_init("maxTemplateVars", sizeof("maxTemplateVars") - 1, true); zend_declare_typed_property(class_entry, property_maxTemplateVars_name, &property_maxTemplateVars_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_maxTemplateVars_name); + zend_string_release_ex(property_maxTemplateVars_name, true); return class_entry; } diff --git a/ext/xsl/tests/gh19988.phpt b/ext/xsl/tests/gh19988.phpt new file mode 100644 index 0000000000000..174af282f9c09 --- /dev/null +++ b/ext/xsl/tests/gh19988.phpt @@ -0,0 +1,19 @@ +--TEST-- +GH-19988 (zend_string_init with NULL pointer in simplexml (UB)) +--EXTENSIONS-- +simplexml +xsl +--CREDITS-- +YuanchengJiang +--FILE-- +load(__DIR__ . '/53965/collection.xsl'); +$processor->importStylesheet($dom); +$result = $processor->transformToDoc($sxe, SimpleXMLElement::class); +var_dump($result->getName()); +?> +--EXPECT-- +string(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/object_handlers_arginfo.h b/ext/zend_test/object_handlers_arginfo.h index 370ad13894aa8..0b8cff520c153 100644 --- a/ext/zend_test/object_handlers_arginfo.h +++ b/ext/zend_test/object_handlers_arginfo.h @@ -49,9 +49,9 @@ static zend_class_entry *register_class_DoOperationNoCast(void) zval property_val_default_value; ZVAL_UNDEF(&property_val_default_value); - zend_string *property_val_name = zend_string_init("val", sizeof("val") - 1, 1); + zend_string *property_val_name = zend_string_init("val", sizeof("val") - 1, true); zend_declare_typed_property(class_entry, property_val_name, &property_val_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_val_name); + zend_string_release_ex(property_val_name, true); return class_entry; } @@ -65,9 +65,9 @@ static zend_class_entry *register_class_LongCastableNoOperations(void) zval property_val_default_value; ZVAL_UNDEF(&property_val_default_value); - zend_string *property_val_name = zend_string_init("val", sizeof("val") - 1, 1); + zend_string *property_val_name = zend_string_init("val", sizeof("val") - 1, true); zend_declare_typed_property(class_entry, property_val_name, &property_val_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_val_name); + zend_string_release_ex(property_val_name, true); return class_entry; } @@ -81,9 +81,9 @@ static zend_class_entry *register_class_FloatCastableNoOperations(void) zval property_val_default_value; ZVAL_UNDEF(&property_val_default_value); - zend_string *property_val_name = zend_string_init("val", sizeof("val") - 1, 1); + zend_string *property_val_name = zend_string_init("val", sizeof("val") - 1, true); zend_declare_typed_property(class_entry, property_val_name, &property_val_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_DOUBLE)); - zend_string_release(property_val_name); + zend_string_release_ex(property_val_name, true); return class_entry; } @@ -97,9 +97,9 @@ static zend_class_entry *register_class_NumericCastableNoOperations(void) zval property_val_default_value; ZVAL_UNDEF(&property_val_default_value); - zend_string *property_val_name = zend_string_init("val", sizeof("val") - 1, 1); + zend_string *property_val_name = zend_string_init("val", sizeof("val") - 1, true); zend_declare_typed_property(class_entry, property_val_name, &property_val_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG|MAY_BE_DOUBLE)); - zend_string_release(property_val_name); + zend_string_release_ex(property_val_name, true); return class_entry; } @@ -113,51 +113,51 @@ static zend_class_entry *register_class_DimensionHandlersNoArrayAccess(void) zval property_read_default_value; ZVAL_FALSE(&property_read_default_value); - zend_string *property_read_name = zend_string_init("read", sizeof("read") - 1, 1); + zend_string *property_read_name = zend_string_init("read", sizeof("read") - 1, true); zend_declare_typed_property(class_entry, property_read_name, &property_read_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_read_name); + zend_string_release_ex(property_read_name, true); zval property_write_default_value; ZVAL_FALSE(&property_write_default_value); - zend_string *property_write_name = zend_string_init("write", sizeof("write") - 1, 1); + zend_string *property_write_name = zend_string_init("write", sizeof("write") - 1, true); zend_declare_typed_property(class_entry, property_write_name, &property_write_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_write_name); + zend_string_release_ex(property_write_name, true); zval property_has_default_value; ZVAL_FALSE(&property_has_default_value); - zend_string *property_has_name = zend_string_init("has", sizeof("has") - 1, 1); + zend_string *property_has_name = zend_string_init("has", sizeof("has") - 1, true); zend_declare_typed_property(class_entry, property_has_name, &property_has_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_has_name); + zend_string_release_ex(property_has_name, true); zval property_unset_default_value; ZVAL_FALSE(&property_unset_default_value); - zend_string *property_unset_name = zend_string_init("unset", sizeof("unset") - 1, 1); + zend_string *property_unset_name = zend_string_init("unset", sizeof("unset") - 1, true); zend_declare_typed_property(class_entry, property_unset_name, &property_unset_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_unset_name); + zend_string_release_ex(property_unset_name, true); zval property_readType_default_value; ZVAL_UNDEF(&property_readType_default_value); - zend_string *property_readType_name = zend_string_init("readType", sizeof("readType") - 1, 1); + zend_string *property_readType_name = zend_string_init("readType", sizeof("readType") - 1, true); zend_declare_typed_property(class_entry, property_readType_name, &property_readType_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_readType_name); + zend_string_release_ex(property_readType_name, true); zval property_hasOffset_default_value; ZVAL_FALSE(&property_hasOffset_default_value); - zend_string *property_hasOffset_name = zend_string_init("hasOffset", sizeof("hasOffset") - 1, 1); + zend_string *property_hasOffset_name = zend_string_init("hasOffset", sizeof("hasOffset") - 1, true); zend_declare_typed_property(class_entry, property_hasOffset_name, &property_hasOffset_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); - zend_string_release(property_hasOffset_name); + zend_string_release_ex(property_hasOffset_name, true); zval property_checkEmpty_default_value; ZVAL_UNDEF(&property_checkEmpty_default_value); - zend_string *property_checkEmpty_name = zend_string_init("checkEmpty", sizeof("checkEmpty") - 1, 1); + zend_string *property_checkEmpty_name = zend_string_init("checkEmpty", sizeof("checkEmpty") - 1, true); zend_declare_typed_property(class_entry, property_checkEmpty_name, &property_checkEmpty_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_checkEmpty_name); + zend_string_release_ex(property_checkEmpty_name, true); zval property_offset_default_value; ZVAL_UNDEF(&property_offset_default_value); - zend_string *property_offset_name = zend_string_init("offset", sizeof("offset") - 1, 1); + zend_string *property_offset_name = zend_string_init("offset", sizeof("offset") - 1, true); zend_declare_typed_property(class_entry, property_offset_name, &property_offset_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ANY)); - zend_string_release(property_offset_name); + zend_string_release_ex(property_offset_name, true); return class_entry; } diff --git a/ext/zend_test/observer.c b/ext/zend_test/observer.c index d2a91d16840e0..31052ec830f73 100644 --- a/ext/zend_test/observer.c +++ b/ext/zend_test/observer.c @@ -155,7 +155,7 @@ static void observer_show_init(zend_function *fbc) php_printf("%*s\n", 2 * ZT_G(observer_nesting_depth), "", ZSTR_VAL(fbc->common.function_name)); } } else { - php_printf("%*s\n", 2 * ZT_G(observer_nesting_depth), "", ZSTR_VAL(fbc->op_array.filename)); + php_printf("%*s\n", 2 * ZT_G(observer_nesting_depth), "", fbc->op_array.filename ? ZSTR_VAL(fbc->op_array.filename) : "[no active file]"); } } @@ -178,7 +178,7 @@ static void observer_show_init_backtrace(zend_execute_data *execute_data) php_printf("%*s%s()\n", indent, "", ZSTR_VAL(fbc->common.function_name)); } } else { - php_printf("%*s{main} %s\n", indent, "", ZSTR_VAL(fbc->op_array.filename)); + php_printf("%*s{main} %s\n", indent, "", fbc->op_array.filename ? ZSTR_VAL(fbc->op_array.filename) : "[no active file]"); } } while ((ex = ex->prev_execute_data) != NULL); php_printf("%*s-->\n", 2 * ZT_G(observer_nesting_depth), ""); 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..fd1a51c5776c3 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 @@ -35,9 +37,12 @@ #include "Zend/Optimizer/zend_optimizer.h" #include "Zend/zend_alloc.h" #include "test_arginfo.h" +#include "tmp_methods_arginfo.h" #include "zend_call_stack.h" #include "zend_exceptions.h" #include "zend_mm_custom_handlers.h" +#include "ext/uri/php_uri.h" +#include "zend_observer.h" #if defined(HAVE_LIBXML) && !defined(PHP_WIN32) # include @@ -85,6 +90,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 +384,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 +399,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 +526,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(); @@ -562,6 +596,13 @@ static ZEND_FUNCTION(zend_test_zend_ini_str) RETURN_STR(ZT_G(str_test)); } +static ZEND_FUNCTION(zend_test_zstr_init_literal) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + RETURN_STR(ZSTR_INIT_LITERAL("foo\0bar", false)); +} + static ZEND_FUNCTION(zend_test_is_string_marked_as_valid_utf8) { zend_string *str; @@ -693,6 +734,126 @@ 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(); + } + + php_uri_internal *uri = php_uri_parse(parser, ZSTR_VAL(uri_string), ZSTR_LEN(uri_string), false); + if (uri == NULL) { + RETURN_THROWS(); + } + + php_uri *uri_struct = php_uri_parse_to_struct(parser, ZSTR_VAL(uri_string), ZSTR_LEN(uri_string), PHP_URI_COMPONENT_READ_MODE_RAW, false); + if (uri_struct == 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); + zval from_struct; + zval dummy; + array_init(&from_struct); + if (uri_struct->scheme) { + ZVAL_STR_COPY(&dummy, uri_struct->scheme); + } else { + ZVAL_NULL(&dummy); + } + zend_hash_add(Z_ARR(from_struct), ZSTR_KNOWN(ZEND_STR_SCHEME), &dummy); + if (uri_struct->user) { + ZVAL_STR_COPY(&dummy, uri_struct->user); + } else { + ZVAL_NULL(&dummy); + } + zend_hash_add(Z_ARR(from_struct), ZSTR_KNOWN(ZEND_STR_USERNAME), &dummy); + if (uri_struct->password) { + ZVAL_STR_COPY(&dummy, uri_struct->password); + } else { + ZVAL_NULL(&dummy); + } + zend_hash_add(Z_ARR(from_struct), ZSTR_KNOWN(ZEND_STR_PASSWORD), &dummy); + if (uri_struct->host) { + ZVAL_STR_COPY(&dummy, uri_struct->host); + } else { + ZVAL_NULL(&dummy); + } + zend_hash_add(Z_ARR(from_struct), ZSTR_KNOWN(ZEND_STR_HOST), &dummy); + ZVAL_LONG(&dummy, uri_struct->port); + zend_hash_add(Z_ARR(from_struct), ZSTR_KNOWN(ZEND_STR_PORT), &dummy); + if (uri_struct->path) { + ZVAL_STR_COPY(&dummy, uri_struct->path); + } else { + ZVAL_NULL(&dummy); + } + zend_hash_add(Z_ARR(from_struct), ZSTR_KNOWN(ZEND_STR_PATH), &dummy); + if (uri_struct->query) { + ZVAL_STR_COPY(&dummy, uri_struct->query); + } else { + ZVAL_NULL(&dummy); + } + zend_hash_add(Z_ARR(from_struct), ZSTR_KNOWN(ZEND_STR_QUERY), &dummy); + if (uri_struct->fragment) { + ZVAL_STR_COPY(&dummy, uri_struct->fragment); + } else { + ZVAL_NULL(&dummy); + } + zend_hash_add(Z_ARR(from_struct), ZSTR_KNOWN(ZEND_STR_FRAGMENT), &dummy); + zend_hash_str_add(Z_ARR_P(return_value), "struct", strlen("struct"), &from_struct); + + php_uri_struct_free(uri_struct); + php_uri_free(uri); +} + static bool has_opline(zend_execute_data *execute_data) { return execute_data @@ -871,16 +1032,38 @@ static ZEND_FUNCTION(zend_test_log_err_debug) php_log_err_with_severity(ZSTR_VAL(str), LOG_DEBUG); } +typedef struct _zend_test_object { + zend_internal_function *tmp_method; + zend_object std; +} zend_test_object; + static zend_object *zend_test_class_new(zend_class_entry *class_type) { - zend_object *obj = zend_objects_new(class_type); - object_properties_init(obj, class_type); - obj->handlers = &zend_test_class_handlers; - return obj; + zend_test_object *intern = zend_object_alloc(sizeof(zend_test_object), class_type); + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + return &intern->std; +} + +static void zend_test_class_free_obj(zend_object *object) +{ + zend_test_object *intern = (zend_test_object*)((char*)object - XtOffsetOf(zend_test_object, std)); + + if (intern->tmp_method) { + zend_internal_function *func = intern->tmp_method; + intern->tmp_method = NULL; + zend_string_release_ex(func->function_name, 0); + zend_free_internal_arg_info(func, false); + efree(func); + } + + zend_object_std_dtor(object); } static zend_function *zend_test_class_method_get(zend_object **object, zend_string *name, const zval *key) { + zend_test_object *intern = (zend_test_object*)((char*)(*object) - XtOffsetOf(zend_test_object, std)); + if (zend_string_equals_literal_ci(name, "test")) { zend_internal_function *fptr; @@ -894,10 +1077,46 @@ static zend_function *zend_test_class_method_get(zend_object **object, zend_stri fptr->num_args = 0; fptr->scope = (*object)->ce; fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER; + fptr->fn_flags2 = 0; fptr->function_name = zend_string_copy(name); fptr->handler = ZEND_FN(zend_test_func); fptr->doc_comment = NULL; + return (zend_function*)fptr; + } else if (zend_string_equals_literal_ci(name, "testTmpMethodWithArgInfo")) { + if (intern->tmp_method) { + return (zend_function*)intern->tmp_method; + } + + const zend_function_entry *entry = &class_ZendTestTmpMethods_methods[0]; + zend_internal_function *fptr = emalloc(sizeof(zend_internal_function)); + memset(fptr, 0, sizeof(zend_internal_function)); + fptr->type = ZEND_INTERNAL_FUNCTION; + fptr->handler = entry->handler; + fptr->function_name = zend_string_init(entry->fname, strlen(entry->fname), false); + fptr->scope = intern->std.ce; + fptr->prototype = NULL; + fptr->T = ZEND_OBSERVER_ENABLED; + fptr->fn_flags = ZEND_ACC_PUBLIC | ZEND_ACC_NEVER_CACHE; + + zend_internal_function_info *info = (zend_internal_function_info*)entry->arg_info; + + uint32_t num_arg_info = 1 + entry->num_args; + zend_arg_info *arg_info = safe_emalloc(num_arg_info, sizeof(zend_arg_info), 0); + for (uint32_t i = 0; i < num_arg_info; i++) { + zend_convert_internal_arg_info(&arg_info[i], &entry->arg_info[i], i == 0, false); + } + + fptr->arg_info = arg_info + 1; + fptr->num_args = entry->num_args; + if (info->required_num_args == (uint32_t)-1) { + fptr->required_num_args = entry->num_args; + } else { + fptr->required_num_args = info->required_num_args; + } + + intern->tmp_method = fptr; + return (zend_function*)fptr; } return zend_std_get_method(object, name, key); @@ -918,6 +1137,7 @@ static zend_function *zend_test_class_static_method_get(zend_class_entry *ce, ze fptr->num_args = 0; fptr->scope = ce; fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_STATIC; + fptr->fn_flags2 = 0; fptr->function_name = zend_string_copy(name); fptr->handler = ZEND_FN(zend_test_func); fptr->doc_comment = NULL; @@ -927,11 +1147,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) @@ -983,6 +1204,18 @@ static ZEND_METHOD(_ZendTestClass, variadicTest) { object_init_ex(return_value, zend_get_called_scope(execute_data)); } +ZEND_METHOD(ZendTestTmpMethods, testTmpMethodWithArgInfo) +{ + zend_object *obj; + zend_string *str; + + ZEND_PARSE_PARAMETERS_START(0, 2); + Z_PARAM_OPTIONAL; + Z_PARAM_OBJ_OR_NULL(obj); + Z_PARAM_STR(str); + ZEND_PARSE_PARAMETERS_END(); +} + static ZEND_METHOD(_ZendTestChildClass, returnsThrowable) { ZEND_PARSE_PARAMETERS_NONE(); @@ -1288,11 +1521,14 @@ PHP_MINIT_FUNCTION(zend_test) register_ZendTestClass_dnf_property(zend_test_class); zend_test_class->create_object = zend_test_class_new; zend_test_class->get_static_method = zend_test_class_static_method_get; + zend_test_class->default_object_handlers = &zend_test_class_handlers; zend_test_child_class = register_class__ZendTestChildClass(zend_test_class); memcpy(&zend_test_class_handlers, &std_object_handlers, sizeof(zend_object_handlers)); zend_test_class_handlers.get_method = zend_test_class_method_get; + zend_test_class_handlers.free_obj = zend_test_class_free_obj; + zend_test_class_handlers.offset = XtOffsetOf(zend_test_object, std); zend_test_gen_stub_flag_compatibility_test = register_class_ZendTestGenStubFlagCompatibilityTest(); @@ -1392,7 +1628,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 +1637,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 +1843,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 +1861,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..d0c0c64b8b1d0 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,10 +295,13 @@ 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 {} function zend_test_zend_ini_str(): string {} + function zend_test_zstr_init_literal(): string {} #ifdef ZEND_CHECK_STACK_LIMIT function zend_test_zend_call_stack_get(): ?array {} @@ -336,6 +341,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..683b3b38648b6 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: a8dae89983ccbcd5dd36d1cdee736d40af4fd33c */ + +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() @@ -121,6 +130,8 @@ ZEND_END_ARG_INFO() #define arginfo_zend_test_zend_ini_str arginfo_zend_get_current_func_name +#define arginfo_zend_test_zstr_init_literal arginfo_zend_get_current_func_name + #if defined(ZEND_CHECK_STACK_LIMIT) ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_zend_call_stack_get, 0, 0, IS_ARRAY, 1) ZEND_END_ARG_INFO() @@ -179,6 +190,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 +284,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,9 +314,11 @@ 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); +static ZEND_FUNCTION(zend_test_zstr_init_literal); #if defined(ZEND_CHECK_STACK_LIMIT) static ZEND_FUNCTION(zend_test_zend_call_stack_get); static ZEND_FUNCTION(zend_test_zend_call_stack_use_all); @@ -318,6 +341,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 +374,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,9 +446,11 @@ 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) + ZEND_FE(zend_test_zstr_init_literal, arginfo_zend_test_zstr_init_literal) #if defined(ZEND_CHECK_STACK_LIMIT) ZEND_FE(zend_test_zend_call_stack_get, arginfo_zend_test_zend_call_stack_get) ZEND_FE(zend_test_zend_call_stack_use_all, arginfo_zend_test_zend_call_stack_use_all) @@ -444,6 +473,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 @@ -588,72 +628,54 @@ static void register_test_symbols(int module_number) REGISTER_STRING_CONSTANT("ZendTestNS2\\ZendSubNS\\ZEND_CONSTANT_A", "namespaced", CONST_PERSISTENT); - zend_string *attribute_name_Deprecated_func_zend_test_deprecated_attr_0 = zend_string_init_interned("Deprecated", sizeof("Deprecated") - 1, 1); + zend_string *attribute_name_Deprecated_func_zend_test_deprecated_attr_0 = zend_string_init_interned("Deprecated", sizeof("Deprecated") - 1, true); 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_release_ex(attribute_name_Deprecated_func_zend_test_deprecated_attr_0, true); 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_string *attribute_name_NoDiscard_func_zend_test_nodiscard_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, true); 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); + zend_string_release_ex(attribute_name_NoDiscard_func_zend_test_nodiscard_0, true); + 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_string *attribute_name_Deprecated_func_zend_test_deprecated_nodiscard_0 = zend_string_init_interned("Deprecated", sizeof("Deprecated") - 1, true); 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); + zend_string_release_ex(attribute_name_Deprecated_func_zend_test_deprecated_nodiscard_0, true); + 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_string *attribute_name_NoDiscard_func_zend_test_deprecated_nodiscard_1 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, true); 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_release_ex(attribute_name_NoDiscard_func_zend_test_deprecated_nodiscard_1, true); 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_string *attribute_name_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0 = zend_string_init_interned("ZendTestParameterAttribute", sizeof("ZendTestParameterAttribute") - 1, true); 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_release_ex(attribute_name_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0, true); 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_string *attribute_name_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0 = zend_string_init_interned("ZendTestAttributeWithArguments", sizeof("ZendTestAttributeWithArguments") - 1, true); 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_release_ex(attribute_name_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0, true); 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); - attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0->args[0].name = zend_string_init_interned("arg", sizeof("arg") - 1, 1); + 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, true); #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 } @@ -667,10 +689,10 @@ static zend_class_entry *register_class__ZendTestInterface(void) zval const_DUMMY_value; ZVAL_LONG(&const_DUMMY_value, 0); - zend_string *const_DUMMY_name = zend_string_init_interned("DUMMY", sizeof("DUMMY") - 1, 1); + zend_string *const_DUMMY_name = zend_string_init_interned("DUMMY", sizeof("DUMMY") - 1, true); zend_string *const_DUMMY_comment = zend_string_init_interned("/**\n * \"Lorem ipsum\"\n * @see https://www.php.net\n * @since 8.2\n */", 98, 1); zend_declare_class_constant_ex(class_entry, const_DUMMY_name, &const_DUMMY_value, ZEND_ACC_PUBLIC, const_DUMMY_comment); - zend_string_release(const_DUMMY_name); + zend_string_release_ex(const_DUMMY_name, true); return class_entry; } @@ -690,82 +712,82 @@ static zend_class_entry *register_class__ZendTestClass(zend_class_entry *class_e zval const_TYPED_CLASS_CONST1_value; ZVAL_EMPTY_ARRAY(&const_TYPED_CLASS_CONST1_value); - zend_string *const_TYPED_CLASS_CONST1_name = zend_string_init_interned("TYPED_CLASS_CONST1", sizeof("TYPED_CLASS_CONST1") - 1, 1); + zend_string *const_TYPED_CLASS_CONST1_name = zend_string_init_interned("TYPED_CLASS_CONST1", sizeof("TYPED_CLASS_CONST1") - 1, true); #if (PHP_VERSION_ID >= 80300) zend_declare_typed_class_constant(class_entry, const_TYPED_CLASS_CONST1_name, &const_TYPED_CLASS_CONST1_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ANY)); #else zend_declare_class_constant_ex(class_entry, const_TYPED_CLASS_CONST1_name, &const_TYPED_CLASS_CONST1_value, ZEND_ACC_PUBLIC, NULL); #endif - zend_string_release(const_TYPED_CLASS_CONST1_name); + zend_string_release_ex(const_TYPED_CLASS_CONST1_name, true); zval const_TYPED_CLASS_CONST2_value; ZVAL_LONG(&const_TYPED_CLASS_CONST2_value, 42); - zend_string *const_TYPED_CLASS_CONST2_name = zend_string_init_interned("TYPED_CLASS_CONST2", sizeof("TYPED_CLASS_CONST2") - 1, 1); + zend_string *const_TYPED_CLASS_CONST2_name = zend_string_init_interned("TYPED_CLASS_CONST2", sizeof("TYPED_CLASS_CONST2") - 1, true); #if (PHP_VERSION_ID >= 80300) zend_declare_typed_class_constant(class_entry, const_TYPED_CLASS_CONST2_name, &const_TYPED_CLASS_CONST2_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG|MAY_BE_ARRAY)); #else zend_declare_class_constant_ex(class_entry, const_TYPED_CLASS_CONST2_name, &const_TYPED_CLASS_CONST2_value, ZEND_ACC_PUBLIC, NULL); #endif - zend_string_release(const_TYPED_CLASS_CONST2_name); + zend_string_release_ex(const_TYPED_CLASS_CONST2_name, true); zval const_TYPED_CLASS_CONST3_value; ZVAL_LONG(&const_TYPED_CLASS_CONST3_value, 1); - zend_string *const_TYPED_CLASS_CONST3_name = zend_string_init_interned("TYPED_CLASS_CONST3", sizeof("TYPED_CLASS_CONST3") - 1, 1); + zend_string *const_TYPED_CLASS_CONST3_name = zend_string_init_interned("TYPED_CLASS_CONST3", sizeof("TYPED_CLASS_CONST3") - 1, true); #if (PHP_VERSION_ID >= 80300) zend_declare_typed_class_constant(class_entry, const_TYPED_CLASS_CONST3_name, &const_TYPED_CLASS_CONST3_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG|MAY_BE_STRING)); #else zend_declare_class_constant_ex(class_entry, const_TYPED_CLASS_CONST3_name, &const_TYPED_CLASS_CONST3_value, ZEND_ACC_PUBLIC, NULL); #endif - zend_string_release(const_TYPED_CLASS_CONST3_name); + zend_string_release_ex(const_TYPED_CLASS_CONST3_name, true); zval const_ZEND_TEST_DEPRECATED_value; ZVAL_LONG(&const_ZEND_TEST_DEPRECATED_value, 42); - zend_string *const_ZEND_TEST_DEPRECATED_name = zend_string_init_interned("ZEND_TEST_DEPRECATED", sizeof("ZEND_TEST_DEPRECATED") - 1, 1); + zend_string *const_ZEND_TEST_DEPRECATED_name = zend_string_init_interned("ZEND_TEST_DEPRECATED", sizeof("ZEND_TEST_DEPRECATED") - 1, true); #if (PHP_VERSION_ID >= 80300) zend_declare_typed_class_constant(class_entry, const_ZEND_TEST_DEPRECATED_name, &const_ZEND_TEST_DEPRECATED_value, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); #else zend_declare_class_constant_ex(class_entry, const_ZEND_TEST_DEPRECATED_name, &const_ZEND_TEST_DEPRECATED_value, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED, NULL); #endif - zend_string_release(const_ZEND_TEST_DEPRECATED_name); + zend_string_release_ex(const_ZEND_TEST_DEPRECATED_name, true); zval const_ZEND_TEST_DEPRECATED_ATTR_value; ZVAL_LONG(&const_ZEND_TEST_DEPRECATED_ATTR_value, 42); - zend_string *const_ZEND_TEST_DEPRECATED_ATTR_name = zend_string_init_interned("ZEND_TEST_DEPRECATED_ATTR", sizeof("ZEND_TEST_DEPRECATED_ATTR") - 1, 1); + zend_string *const_ZEND_TEST_DEPRECATED_ATTR_name = zend_string_init_interned("ZEND_TEST_DEPRECATED_ATTR", sizeof("ZEND_TEST_DEPRECATED_ATTR") - 1, true); #if (PHP_VERSION_ID >= 80300) zend_class_constant *const_ZEND_TEST_DEPRECATED_ATTR = zend_declare_typed_class_constant(class_entry, const_ZEND_TEST_DEPRECATED_ATTR_name, &const_ZEND_TEST_DEPRECATED_ATTR_value, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); #else zend_class_constant *const_ZEND_TEST_DEPRECATED_ATTR = zend_declare_class_constant_ex(class_entry, const_ZEND_TEST_DEPRECATED_ATTR_name, &const_ZEND_TEST_DEPRECATED_ATTR_value, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED, NULL); #endif - zend_string_release(const_ZEND_TEST_DEPRECATED_ATTR_name); + zend_string_release_ex(const_ZEND_TEST_DEPRECATED_ATTR_name, true); zval property__StaticProp_default_value; ZVAL_NULL(&property__StaticProp_default_value); - zend_string *property__StaticProp_name = zend_string_init("_StaticProp", sizeof("_StaticProp") - 1, 1); + zend_string *property__StaticProp_name = zend_string_init("_StaticProp", sizeof("_StaticProp") - 1, true); zend_declare_typed_property(class_entry, property__StaticProp_name, &property__StaticProp_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0)); - zend_string_release(property__StaticProp_name); + zend_string_release_ex(property__StaticProp_name, true); zval property_staticIntProp_default_value; ZVAL_LONG(&property_staticIntProp_default_value, 123); - zend_string *property_staticIntProp_name = zend_string_init("staticIntProp", sizeof("staticIntProp") - 1, 1); + zend_string *property_staticIntProp_name = zend_string_init("staticIntProp", sizeof("staticIntProp") - 1, true); zend_declare_typed_property(class_entry, property_staticIntProp_name, &property_staticIntProp_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_staticIntProp_name); + zend_string_release_ex(property_staticIntProp_name, true); zval property_intProp_default_value; ZVAL_LONG(&property_intProp_default_value, 123); - zend_string *property_intProp_name = zend_string_init("intProp", sizeof("intProp") - 1, 1); + zend_string *property_intProp_name = zend_string_init("intProp", sizeof("intProp") - 1, true); zend_declare_typed_property(class_entry, property_intProp_name, &property_intProp_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_intProp_name); + zend_string_release_ex(property_intProp_name, true); zval property_classProp_default_value; ZVAL_NULL(&property_classProp_default_value); - zend_string *property_classProp_name = zend_string_init("classProp", sizeof("classProp") - 1, 1); + zend_string *property_classProp_name = zend_string_init("classProp", sizeof("classProp") - 1, true); zend_string *property_classProp_class_stdClass = zend_string_init("stdClass", sizeof("stdClass")-1, 1); zend_declare_typed_property(class_entry, property_classProp_name, &property_classProp_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_classProp_class_stdClass, 0, MAY_BE_NULL)); - zend_string_release(property_classProp_name); + zend_string_release_ex(property_classProp_name, true); zval property_classUnionProp_default_value; ZVAL_NULL(&property_classUnionProp_default_value); - zend_string *property_classUnionProp_name = zend_string_init("classUnionProp", sizeof("classUnionProp") - 1, 1); + zend_string *property_classUnionProp_name = zend_string_init("classUnionProp", sizeof("classUnionProp") - 1, true); zend_string *property_classUnionProp_class_stdClass = zend_string_init("stdClass", sizeof("stdClass") - 1, 1); zend_string *property_classUnionProp_class_Iterator = zend_string_init("Iterator", sizeof("Iterator") - 1, 1); zend_type_list *property_classUnionProp_type_list = malloc(ZEND_TYPE_LIST_SIZE(2)); @@ -774,11 +796,11 @@ static zend_class_entry *register_class__ZendTestClass(zend_class_entry *class_e property_classUnionProp_type_list->types[1] = (zend_type) ZEND_TYPE_INIT_CLASS(property_classUnionProp_class_Iterator, 0, 0); zend_type property_classUnionProp_type = ZEND_TYPE_INIT_UNION(property_classUnionProp_type_list, MAY_BE_NULL); zend_declare_typed_property(class_entry, property_classUnionProp_name, &property_classUnionProp_default_value, ZEND_ACC_PUBLIC, NULL, property_classUnionProp_type); - zend_string_release(property_classUnionProp_name); + zend_string_release_ex(property_classUnionProp_name, true); zval property_classIntersectionProp_default_value; ZVAL_UNDEF(&property_classIntersectionProp_default_value); - zend_string *property_classIntersectionProp_name = zend_string_init("classIntersectionProp", sizeof("classIntersectionProp") - 1, 1); + zend_string *property_classIntersectionProp_name = zend_string_init("classIntersectionProp", sizeof("classIntersectionProp") - 1, true); zend_string *property_classIntersectionProp_class_Traversable = zend_string_init("Traversable", sizeof("Traversable") - 1, 1); zend_string *property_classIntersectionProp_class_Countable = zend_string_init("Countable", sizeof("Countable") - 1, 1); zend_type_list *property_classIntersectionProp_type_list = malloc(ZEND_TYPE_LIST_SIZE(2)); @@ -787,36 +809,34 @@ static zend_class_entry *register_class__ZendTestClass(zend_class_entry *class_e property_classIntersectionProp_type_list->types[1] = (zend_type) ZEND_TYPE_INIT_CLASS(property_classIntersectionProp_class_Countable, 0, 0); zend_type property_classIntersectionProp_type = ZEND_TYPE_INIT_INTERSECTION(property_classIntersectionProp_type_list, 0); zend_declare_typed_property(class_entry, property_classIntersectionProp_name, &property_classIntersectionProp_default_value, ZEND_ACC_PUBLIC, NULL, property_classIntersectionProp_type); - zend_string_release(property_classIntersectionProp_name); + zend_string_release_ex(property_classIntersectionProp_name, true); zval property_readonlyProp_default_value; ZVAL_UNDEF(&property_readonlyProp_default_value); - zend_string *property_readonlyProp_name = zend_string_init("readonlyProp", sizeof("readonlyProp") - 1, 1); + zend_string *property_readonlyProp_name = zend_string_init("readonlyProp", sizeof("readonlyProp") - 1, true); #if (PHP_VERSION_ID >= 80100) zend_declare_typed_property(class_entry, property_readonlyProp_name, &property_readonlyProp_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); #elif (PHP_VERSION_ID >= 80000) zend_declare_typed_property(class_entry, property_readonlyProp_name, &property_readonlyProp_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); #endif - zend_string_release(property_readonlyProp_name); + zend_string_release_ex(property_readonlyProp_name, true); zval property_finalProp_default_value; ZVAL_UNDEF(&property_finalProp_default_value); - zend_string *property_finalProp_name = zend_string_init("finalProp", sizeof("finalProp") - 1, 1); + zend_string *property_finalProp_name = zend_string_init("finalProp", sizeof("finalProp") - 1, true); #if (PHP_VERSION_ID >= 80400) zend_declare_typed_property(class_entry, property_finalProp_name, &property_finalProp_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); #elif (PHP_VERSION_ID >= 80000) zend_declare_typed_property(class_entry, property_finalProp_name, &property_finalProp_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); #endif - zend_string_release(property_finalProp_name); + zend_string_release_ex(property_finalProp_name, true); - zend_string *attribute_name_Deprecated_const_ZEND_TEST_DEPRECATED_ATTR_0 = zend_string_init_interned("Deprecated", sizeof("Deprecated") - 1, 1); + zend_string *attribute_name_Deprecated_const_ZEND_TEST_DEPRECATED_ATTR_0 = zend_string_init_interned("Deprecated", sizeof("Deprecated") - 1, true); 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_release_ex(attribute_name_Deprecated_const_ZEND_TEST_DEPRECATED_ATTR_0, true); 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; @@ -896,42 +916,40 @@ static zend_class_entry *register_class_ZendAttributeTest(void) zval const_TEST_CONST_value; ZVAL_LONG(&const_TEST_CONST_value, 1); - zend_string *const_TEST_CONST_name = zend_string_init_interned("TEST_CONST", sizeof("TEST_CONST") - 1, 1); + zend_string *const_TEST_CONST_name = zend_string_init_interned("TEST_CONST", sizeof("TEST_CONST") - 1, true); zend_class_constant *const_TEST_CONST = zend_declare_class_constant_ex(class_entry, const_TEST_CONST_name, &const_TEST_CONST_value, ZEND_ACC_PUBLIC, NULL); - zend_string_release(const_TEST_CONST_name); + zend_string_release_ex(const_TEST_CONST_name, true); zval property_testProp_default_value; ZVAL_NULL(&property_testProp_default_value); - zend_string *property_testProp_name = zend_string_init("testProp", sizeof("testProp") - 1, 1); + zend_string *property_testProp_name = zend_string_init("testProp", sizeof("testProp") - 1, true); zend_property_info *property_testProp = zend_declare_typed_property(class_entry, property_testProp_name, &property_testProp_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0)); - zend_string_release(property_testProp_name); + zend_string_release_ex(property_testProp_name, true); - zend_string *attribute_name_ZendTestRepeatableAttribute_const_TEST_CONST_0 = zend_string_init_interned("ZendTestRepeatableAttribute", sizeof("ZendTestRepeatableAttribute") - 1, 1); + zend_string *attribute_name_ZendTestRepeatableAttribute_const_TEST_CONST_0 = zend_string_init_interned("ZendTestRepeatableAttribute", sizeof("ZendTestRepeatableAttribute") - 1, true); zend_add_class_constant_attribute(class_entry, const_TEST_CONST, attribute_name_ZendTestRepeatableAttribute_const_TEST_CONST_0, 0); - zend_string_release(attribute_name_ZendTestRepeatableAttribute_const_TEST_CONST_0); + zend_string_release_ex(attribute_name_ZendTestRepeatableAttribute_const_TEST_CONST_0, true); - zend_string *attribute_name_ZendTestRepeatableAttribute_const_TEST_CONST_1 = zend_string_init_interned("ZendTestRepeatableAttribute", sizeof("ZendTestRepeatableAttribute") - 1, 1); + zend_string *attribute_name_ZendTestRepeatableAttribute_const_TEST_CONST_1 = zend_string_init_interned("ZendTestRepeatableAttribute", sizeof("ZendTestRepeatableAttribute") - 1, true); zend_add_class_constant_attribute(class_entry, const_TEST_CONST, attribute_name_ZendTestRepeatableAttribute_const_TEST_CONST_1, 0); - zend_string_release(attribute_name_ZendTestRepeatableAttribute_const_TEST_CONST_1); + zend_string_release_ex(attribute_name_ZendTestRepeatableAttribute_const_TEST_CONST_1, true); - zend_string *attribute_name_ZendTestRepeatableAttribute_property_testProp_0 = zend_string_init_interned("ZendTestRepeatableAttribute", sizeof("ZendTestRepeatableAttribute") - 1, 1); + zend_string *attribute_name_ZendTestRepeatableAttribute_property_testProp_0 = zend_string_init_interned("ZendTestRepeatableAttribute", sizeof("ZendTestRepeatableAttribute") - 1, true); zend_add_property_attribute(class_entry, property_testProp, attribute_name_ZendTestRepeatableAttribute_property_testProp_0, 0); - zend_string_release(attribute_name_ZendTestRepeatableAttribute_property_testProp_0); + zend_string_release_ex(attribute_name_ZendTestRepeatableAttribute_property_testProp_0, true); - zend_string *attribute_name_ZendTestPropertyAttribute_property_testProp_1 = zend_string_init_interned("ZendTestPropertyAttribute", sizeof("ZendTestPropertyAttribute") - 1, 1); + zend_string *attribute_name_ZendTestPropertyAttribute_property_testProp_1 = zend_string_init_interned("ZendTestPropertyAttribute", sizeof("ZendTestPropertyAttribute") - 1, true); 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_release_ex(attribute_name_ZendTestPropertyAttribute_property_testProp_1, true); 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); + zend_string *attribute_name_ZendTestAttribute_func_testmethod_0 = zend_string_init_interned("ZendTestAttribute", sizeof("ZendTestAttribute") - 1, true); zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "testmethod", sizeof("testmethod") - 1), attribute_name_ZendTestAttribute_func_testmethod_0, 0); - zend_string_release(attribute_name_ZendTestAttribute_func_testmethod_0); + zend_string_release_ex(attribute_name_ZendTestAttribute_func_testmethod_0, true); return class_entry; } @@ -950,13 +968,13 @@ static zend_class_entry *register_class__ZendTestTrait(void) zval property_testProp_default_value; ZVAL_NULL(&property_testProp_default_value); - zend_string *property_testProp_name = zend_string_init("testProp", sizeof("testProp") - 1, 1); + zend_string *property_testProp_name = zend_string_init("testProp", sizeof("testProp") - 1, true); zend_declare_typed_property(class_entry, property_testProp_name, &property_testProp_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0)); - zend_string_release(property_testProp_name); + zend_string_release_ex(property_testProp_name, true); zval property_classUnionProp_default_value; ZVAL_UNDEF(&property_classUnionProp_default_value); - zend_string *property_classUnionProp_name = zend_string_init("classUnionProp", sizeof("classUnionProp") - 1, 1); + zend_string *property_classUnionProp_name = zend_string_init("classUnionProp", sizeof("classUnionProp") - 1, true); zend_string *property_classUnionProp_class_Traversable = zend_string_init("Traversable", sizeof("Traversable") - 1, 1); zend_string *property_classUnionProp_class_Countable = zend_string_init("Countable", sizeof("Countable") - 1, 1); zend_type_list *property_classUnionProp_type_list = malloc(ZEND_TYPE_LIST_SIZE(2)); @@ -965,7 +983,7 @@ static zend_class_entry *register_class__ZendTestTrait(void) property_classUnionProp_type_list->types[1] = (zend_type) ZEND_TYPE_INIT_CLASS(property_classUnionProp_class_Countable, 0, 0); zend_type property_classUnionProp_type = ZEND_TYPE_INIT_UNION(property_classUnionProp_type_list, 0); zend_declare_typed_property(class_entry, property_classUnionProp_name, &property_classUnionProp_default_value, ZEND_ACC_PUBLIC, NULL, property_classUnionProp_type); - zend_string_release(property_classUnionProp_name); + zend_string_release_ex(property_classUnionProp_name, true); return class_entry; } @@ -982,12 +1000,10 @@ static zend_class_entry *register_class_ZendTestAttribute(void) class_entry->ce_flags |= ZEND_ACC_FINAL; #endif - zend_string *attribute_name_Attribute_class_ZendTestAttribute_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_string *attribute_name_Attribute_class_ZendTestAttribute_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, true); 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); + zend_string_release_ex(attribute_name_Attribute_class_ZendTestAttribute_0, true); + ZVAL_LONG(&attribute_Attribute_class_ZendTestAttribute_0->args[0].value, ZEND_ATTRIBUTE_TARGET_ALL); return class_entry; } @@ -1006,20 +1022,18 @@ static zend_class_entry *register_class_ZendTestAttributeWithArguments(void) zval property_arg_default_value; ZVAL_UNDEF(&property_arg_default_value); - zend_string *property_arg_name = zend_string_init("arg", sizeof("arg") - 1, 1); + zend_string *property_arg_name = zend_string_init("arg", sizeof("arg") - 1, true); #if (PHP_VERSION_ID >= 80100) zend_declare_typed_property(class_entry, property_arg_name, &property_arg_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ANY)); #elif (PHP_VERSION_ID >= 80000) zend_declare_typed_property(class_entry, property_arg_name, &property_arg_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ANY)); #endif - zend_string_release(property_arg_name); + zend_string_release_ex(property_arg_name, true); - zend_string *attribute_name_Attribute_class_ZendTestAttributeWithArguments_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_string *attribute_name_Attribute_class_ZendTestAttributeWithArguments_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, true); 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); + zend_string_release_ex(attribute_name_Attribute_class_ZendTestAttributeWithArguments_0, true); + ZVAL_LONG(&attribute_Attribute_class_ZendTestAttributeWithArguments_0->args[0].value, ZEND_ATTRIBUTE_TARGET_ALL); return class_entry; } @@ -1036,12 +1050,10 @@ static zend_class_entry *register_class_ZendTestRepeatableAttribute(void) class_entry->ce_flags |= ZEND_ACC_FINAL; #endif - zend_string *attribute_name_Attribute_class_ZendTestRepeatableAttribute_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_string *attribute_name_Attribute_class_ZendTestRepeatableAttribute_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, true); 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); + zend_string_release_ex(attribute_name_Attribute_class_ZendTestRepeatableAttribute_0, true); + ZVAL_LONG(&attribute_Attribute_class_ZendTestRepeatableAttribute_0->args[0].value, ZEND_ATTRIBUTE_TARGET_ALL | ZEND_ATTRIBUTE_IS_REPEATABLE); return class_entry; } @@ -1060,16 +1072,14 @@ static zend_class_entry *register_class_ZendTestParameterAttribute(void) zval property_parameter_default_value; ZVAL_UNDEF(&property_parameter_default_value); - zend_string *property_parameter_name = zend_string_init("parameter", sizeof("parameter") - 1, 1); + zend_string *property_parameter_name = zend_string_init("parameter", sizeof("parameter") - 1, true); zend_declare_typed_property(class_entry, property_parameter_name, &property_parameter_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_parameter_name); + zend_string_release_ex(property_parameter_name, true); - zend_string *attribute_name_Attribute_class_ZendTestParameterAttribute_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_string *attribute_name_Attribute_class_ZendTestParameterAttribute_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, true); 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); + zend_string_release_ex(attribute_name_Attribute_class_ZendTestParameterAttribute_0, true); + ZVAL_LONG(&attribute_Attribute_class_ZendTestParameterAttribute_0->args[0].value, ZEND_ATTRIBUTE_TARGET_PARAMETER); return class_entry; } @@ -1091,17 +1101,15 @@ static zend_class_entry *register_class_ZendTestPropertyAttribute(void) zval property_parameter_default_value; ZVAL_UNDEF(&property_parameter_default_value); - zend_string *property_parameter_name = zend_string_init("parameter", sizeof("parameter") - 1, 1); + zend_string *property_parameter_name = zend_string_init("parameter", sizeof("parameter") - 1, true); zend_string *property_parameter_comment = zend_string_init_interned("/**\n * \"Lorem ipsum\"\n * @see https://www.php.net\n * @since 8.4\n */", 98, 1); zend_declare_typed_property(class_entry, property_parameter_name, &property_parameter_default_value, ZEND_ACC_PUBLIC, property_parameter_comment, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_parameter_name); + zend_string_release_ex(property_parameter_name, true); - zend_string *attribute_name_Attribute_class_ZendTestPropertyAttribute_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_string *attribute_name_Attribute_class_ZendTestPropertyAttribute_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, true); 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); + zend_string_release_ex(attribute_name_Attribute_class_ZendTestPropertyAttribute_0, true); + ZVAL_LONG(&attribute_Attribute_class_ZendTestPropertyAttribute_0->args[0].value, ZEND_ATTRIBUTE_TARGET_PROPERTY); return class_entry; } @@ -1118,21 +1126,17 @@ static zend_class_entry *register_class_ZendTestClassWithMethodWithParameterAttr #endif - zend_string *attribute_name_ZendTestParameterAttribute_func_no_override_arg0_0 = zend_string_init_interned("ZendTestParameterAttribute", sizeof("ZendTestParameterAttribute") - 1, 1); + zend_string *attribute_name_ZendTestParameterAttribute_func_no_override_arg0_0 = zend_string_init_interned("ZendTestParameterAttribute", sizeof("ZendTestParameterAttribute") - 1, true); 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_release_ex(attribute_name_ZendTestParameterAttribute_func_no_override_arg0_0, true); 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_string *attribute_name_ZendTestParameterAttribute_func_override_arg0_0 = zend_string_init_interned("ZendTestParameterAttribute", sizeof("ZendTestParameterAttribute") - 1, true); 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_release_ex(attribute_name_ZendTestParameterAttribute_func_override_arg0_0, true); 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; } @@ -1149,13 +1153,11 @@ static zend_class_entry *register_class_ZendTestChildClassWithMethodWithParamete #endif - zend_string *attribute_name_ZendTestParameterAttribute_func_override_arg0_0 = zend_string_init_interned("ZendTestParameterAttribute", sizeof("ZendTestParameterAttribute") - 1, 1); + zend_string *attribute_name_ZendTestParameterAttribute_func_override_arg0_0 = zend_string_init_interned("ZendTestParameterAttribute", sizeof("ZendTestParameterAttribute") - 1, true); 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_release_ex(attribute_name_ZendTestParameterAttribute_func_override_arg0_0, true); 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; } @@ -1173,14 +1175,14 @@ static zend_class_entry *register_class_ZendTestClassWithPropertyAttribute(void) zval property_attributed_default_value; ZVAL_UNDEF(&property_attributed_default_value); - zend_string *property_attributed_name = zend_string_init("attributed", sizeof("attributed") - 1, 1); + zend_string *property_attributed_name = zend_string_init("attributed", sizeof("attributed") - 1, true); zend_property_info *property_attributed = zend_declare_typed_property(class_entry, property_attributed_name, &property_attributed_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_attributed_name); + zend_string_release_ex(property_attributed_name, true); - zend_string *attribute_name_ZendTestAttribute_property_attributed_0 = zend_string_init_interned("ZendTestAttribute", sizeof("ZendTestAttribute") - 1, 1); + zend_string *attribute_name_ZendTestAttribute_property_attributed_0 = zend_string_init_interned("ZendTestAttribute", sizeof("ZendTestAttribute") - 1, true); zend_add_property_attribute(class_entry, property_attributed, attribute_name_ZendTestAttribute_property_attributed_0, 0); - zend_string_release(attribute_name_ZendTestAttribute_property_attributed_0); + zend_string_release_ex(attribute_name_ZendTestAttribute_property_attributed_0, true); return class_entry; } @@ -1318,10 +1320,10 @@ static zend_class_entry *register_class_ZendTestNS2_Foo(void) zval property_foo_default_value; ZVAL_UNDEF(&property_foo_default_value); - zend_string *property_foo_name = zend_string_init("foo", sizeof("foo") - 1, 1); + zend_string *property_foo_name = zend_string_init("foo", sizeof("foo") - 1, true); zend_string *property_foo_class_ZendTestNS2_ZendSubNS_Foo = zend_string_init("ZendTestNS2\\ZendSubNS\\Foo", sizeof("ZendTestNS2\\ZendSubNS\\Foo")-1, 1); zend_declare_typed_property(class_entry, property_foo_name, &property_foo_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_foo_class_ZendTestNS2_ZendSubNS_Foo, 0, 0)); - zend_string_release(property_foo_name); + zend_string_release_ex(property_foo_name, true); 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_fiber_backtrace_crash.phpt b/ext/zend_test/tests/observer_fiber_backtrace_crash.phpt new file mode 100644 index 0000000000000..3d3629af45bdb --- /dev/null +++ b/ext/zend_test/tests/observer_fiber_backtrace_crash.phpt @@ -0,0 +1,48 @@ +--TEST-- +GH-16319 (Fiber backtrace with null filename should not crash) +--EXTENSIONS-- +zend_test +--INI-- +zend_test.observer.enabled=1 +zend_test.observer.show_init_backtrace=1 +zend_test.observer.show_output=1 +zend_test.observer.observe_all=1 +zend_test.observer.show_opcode=0 +opcache.jit=0 +--FILE-- +start(); +echo "Test completed without crash\n"; +?> +--EXPECTF-- + + + + + + + + + + + + + <{closure:%s:%d}> + + +Test completed without crash + 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/zend_test/tests/zstr_init_literal.phpt b/ext/zend_test/tests/zstr_init_literal.phpt new file mode 100644 index 0000000000000..b7f382da8d6e1 --- /dev/null +++ b/ext/zend_test/tests/zstr_init_literal.phpt @@ -0,0 +1,13 @@ +--TEST-- +zstr_init_literal +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECT-- +int(7) +string(14) "666f6f00626172" diff --git a/ext/zend_test/tmp_methods.stub.php b/ext/zend_test/tmp_methods.stub.php new file mode 100644 index 0000000000000..af479c7d5422f --- /dev/null +++ b/ext/zend_test/tmp_methods.stub.php @@ -0,0 +1,11 @@ += 0.11 libzip != 1.3.1 libzip != 1.7.0]) + PKG_CHECK_MODULES([LIBZIP], [libzip >= 1.0.0 libzip != 1.3.1 libzip != 1.7.0]) PHP_EVAL_INCLINE([$LIBZIP_CFLAGS]) PHP_EVAL_LIBLINE([$LIBZIP_LIBS], [ZIP_SHARED_LIBADD]) - PHP_CHECK_LIBRARY([zip], [zip_file_set_mtime], - [AC_DEFINE([HAVE_SET_MTIME], [1], - [Define to 1 if libzip library has the 'zip_file_set_mtime' function - (available since 1.0.0).])], - [AC_MSG_WARN([Libzip >= 1.0.0 needed for setting mtime])], - [$LIBZIP_LIBS]) - PHP_CHECK_LIBRARY([zip], [zip_file_set_encryption], [AC_DEFINE([HAVE_ENCRYPTION], [1], [Define to 1 if libzip library has encryption support (available since diff --git a/ext/zip/config.w32 b/ext/zip/config.w32 index c0226f8976460..9b80aefaaad0b 100644 --- a/ext/zip/config.w32 +++ b/ext/zip/config.w32 @@ -17,7 +17,7 @@ if (PHP_ZIP != "no") { } AC_DEFINE('HAVE_ZIP', 1, "Define to 1 if the PHP extension 'zip' is available."); - ADD_FLAG("CFLAGS_ZIP", "/D HAVE_SET_MTIME /D HAVE_ENCRYPTION /D HAVE_LIBZIP_VERSION /D HAVE_PROGRESS_CALLBACK /D HAVE_CANCEL_CALLBACK /D HAVE_METHOD_SUPPORTED /D LZMA_API_STATIC"); + ADD_FLAG("CFLAGS_ZIP", "/D HAVE_ENCRYPTION /D HAVE_LIBZIP_VERSION /D HAVE_PROGRESS_CALLBACK /D HAVE_CANCEL_CALLBACK /D HAVE_METHOD_SUPPORTED /D LZMA_API_STATIC"); } else { WARNING("zip not enabled; libraries and headers not found"); } diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index d5f7b019eb9ea..4ff362bab15d2 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -74,6 +74,17 @@ static int le_zip_entry; # define add_ascii_assoc_string add_assoc_string # define add_ascii_assoc_long add_assoc_long +static bool php_zip_file_set_encryption(struct zip *intern, zend_long index, zend_long method, char *password) { + // FIXME: is a workaround to reset/free the password in case of consecutive calls. + // when libzip 1.11.5 is available, we can save this call in this case. + if (UNEXPECTED(zip_file_set_encryption(intern, (zip_uint64_t)index, ZIP_EM_NONE, NULL) < 0)) { + php_error_docref(NULL, E_WARNING, "password reset failed"); + return false; + } + + return (zip_file_set_encryption(intern, (zip_uint64_t)index, (zip_uint16_t)method, password) == 0); +} + /* Flatten a path by making a relative path (to .)*/ static char * php_zip_make_relative_path(char *path, size_t path_len) /* {{{ */ { @@ -111,11 +122,8 @@ static char * php_zip_make_relative_path(char *path, size_t path_len) /* {{{ */ } /* }}} */ -# define CWD_STATE_ALLOC(l) emalloc(l) -# define CWD_STATE_FREE(s) efree(s) - /* {{{ php_zip_extract_file */ -static int php_zip_extract_file(struct zip * za, char *dest, const char *file, size_t file_len, zip_int64_t idx) +static bool php_zip_extract_file(struct zip * za, char *dest, const char *file, size_t file_len, zip_int64_t idx) { php_stream_statbuf ssb; struct zip_file *zf; @@ -136,10 +144,10 @@ static int php_zip_extract_file(struct zip * za, char *dest, const char *file, s if (idx < 0) { idx = zip_name_locate(za, file, 0); if (idx < 0) { - return 0; + return false; } } - new_state.cwd = CWD_STATE_ALLOC(1); + new_state.cwd = emalloc(1); new_state.cwd[0] = '\0'; new_state.cwd_length = 0; @@ -149,14 +157,14 @@ static int php_zip_extract_file(struct zip * za, char *dest, const char *file, s virtual_file_ex(&new_state, file, NULL, CWD_EXPAND); path_cleaned = php_zip_make_relative_path(new_state.cwd, new_state.cwd_length); if(!path_cleaned) { - CWD_STATE_FREE(new_state.cwd); - return 0; + efree(new_state.cwd); + return false; } path_cleaned_len = strlen(path_cleaned); if (path_cleaned_len >= MAXPATHLEN || zip_stat_index(za, idx, 0, &sb) != 0) { - CWD_STATE_FREE(new_state.cwd); - return 0; + efree(new_state.cwd); + return false; } /* it is a directory only, see #40228 */ @@ -177,9 +185,9 @@ static int php_zip_extract_file(struct zip * za, char *dest, const char *file, s if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname_fullpath)) { efree(file_dirname_fullpath); - zend_string_release_ex(file_basename, 0); - CWD_STATE_FREE(new_state.cwd); - return 0; + zend_string_release_ex(file_basename, false); + efree(new_state.cwd); + return false; } } @@ -189,33 +197,33 @@ static int php_zip_extract_file(struct zip * za, char *dest, const char *file, s if (!ret) { efree(file_dirname_fullpath); if (!is_dir_only) { - zend_string_release_ex(file_basename, 0); + zend_string_release_ex(file_basename, false); } - CWD_STATE_FREE(new_state.cwd); - return 0; + efree(new_state.cwd); + return false; } } /* it is a standalone directory, job done */ if (is_dir_only) { efree(file_dirname_fullpath); - CWD_STATE_FREE(new_state.cwd); - return 1; + efree(new_state.cwd); + return true; } len = spprintf(&fullpath, 0, "%s/%s", file_dirname_fullpath, ZSTR_VAL(file_basename)); if (!len) { efree(file_dirname_fullpath); - zend_string_release_ex(file_basename, 0); - CWD_STATE_FREE(new_state.cwd); - return 0; + zend_string_release_ex(file_basename, false); + efree(new_state.cwd); + return false; } 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); - return 0; + zend_string_release_ex(file_basename, false); + efree(new_state.cwd); + return false; } /* check again the full path, not sure if it @@ -225,9 +233,9 @@ static int php_zip_extract_file(struct zip * za, char *dest, const char *file, s if (ZIP_OPENBASEDIR_CHECKPATH(fullpath)) { efree(fullpath); efree(file_dirname_fullpath); - zend_string_release_ex(file_basename, 0); - CWD_STATE_FREE(new_state.cwd); - return 0; + zend_string_release_ex(file_basename, false); + efree(new_state.cwd); + return false; } zf = zip_fopen_index(za, idx, 0); @@ -262,19 +270,15 @@ static int php_zip_extract_file(struct zip * za, char *dest, const char *file, s done: efree(fullpath); - zend_string_release_ex(file_basename, 0); + zend_string_release_ex(file_basename, false); efree(file_dirname_fullpath); - CWD_STATE_FREE(new_state.cwd); + efree(new_state.cwd); - if (n<0) { - return 0; - } else { - return 1; - } + return !(n < 0); } /* }}} */ -static int php_zip_add_file(ze_zip_object *obj, const char *filename, size_t filename_len, +static zend_result php_zip_add_file(ze_zip_object *obj, const char *filename, size_t filename_len, char *entry_name, size_t entry_name_len, /* unused if replace >= 0 */ zip_uint64_t offset_start, zip_uint64_t offset_len, zend_long replace, /* index to replace, add new file if < 0 */ @@ -286,24 +290,24 @@ static int php_zip_add_file(ze_zip_object *obj, const char *filename, size_t fil php_stream_statbuf ssb; if (ZIP_OPENBASEDIR_CHECKPATH(filename)) { - return -1; + return FAILURE; } if (!expand_filepath(filename, resolved_path)) { php_error_docref(NULL, E_WARNING, "No such file or directory"); - return -1; + return FAILURE; } if (php_stream_stat_path_ex(resolved_path, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL)) { php_error_docref(NULL, E_WARNING, "No such file or directory"); - return -1; + return FAILURE; } if (flags & ZIP_FL_OPEN_FILE_NOW) { FILE *fd; fd = fopen(resolved_path, "rb"); if (!fd) { - return -1; + return FAILURE; } flags ^= ZIP_FL_OPEN_FILE_NOW; zs = zip_source_filep(obj->za, fd, offset_start, offset_len); @@ -311,25 +315,25 @@ static int php_zip_add_file(ze_zip_object *obj, const char *filename, size_t fil zs = zip_source_file(obj->za, resolved_path, offset_start, offset_len); } if (!zs) { - return -1; + return FAILURE; } /* Replace */ if (replace >= 0) { if (zip_file_replace(obj->za, replace, zs, flags) < 0) { zip_source_free(zs); - return -1; + return FAILURE; } zip_error_clear(obj->za); - return 1; + return SUCCESS; } /* Add */ obj->last_id = zip_file_add(obj->za, entry_name, zs, flags); if (obj->last_id < 0) { zip_source_free(zs); - return -1; + return FAILURE; } zip_error_clear(obj->za); - return 1; + return SUCCESS; } /* }}} */ @@ -349,7 +353,7 @@ typedef struct { } zip_options; /* Expects opts to be zero-initialized. */ -static int php_zip_parse_options(HashTable *options, zip_options *opts) +static zend_result php_zip_parse_options(HashTable *options, zip_options *opts) /* {{{ */ { zval *option; @@ -374,14 +378,22 @@ static int php_zip_parse_options(HashTable *options, zip_options *opts) php_error_docref(NULL, E_WARNING, "Option \"comp_method\" must be of type int, %s given", zend_zval_value_name(option)); } - opts->comp_method = zval_get_long(option); + zend_long comp_method = zval_get_long(option); + if (comp_method < 0 || comp_method > INT_MAX) { + php_error_docref(NULL, E_WARNING, "Option \"comp_method\" must be between 0 and %d", INT_MAX); + } + opts->comp_method = (zip_int32_t)comp_method; if ((option = zend_hash_str_find(options, "comp_flags", sizeof("comp_flags") - 1)) != NULL) { if (Z_TYPE_P(option) != IS_LONG) { php_error_docref(NULL, E_WARNING, "Option \"comp_flags\" must be of type int, %s given", zend_zval_value_name(option)); } - opts->comp_flags = zval_get_long(option); + zend_long comp_flags = zval_get_long(option); + if (comp_flags < 0 || comp_flags > USHRT_MAX) { + php_error_docref(NULL, E_WARNING, "Option \"comp_flags\" must be between 0 and %u", USHRT_MAX); + } + opts->comp_flags = (zip_uint32_t)comp_flags; } } @@ -397,7 +409,7 @@ static int php_zip_parse_options(HashTable *options, zip_options *opts) if (Z_TYPE_P(option) != IS_STRING) { zend_type_error("Option \"enc_password\" must be of type string, %s given", zend_zval_value_name(option)); - return -1; + return FAILURE; } opts->enc_password = Z_STRVAL_P(option); } @@ -408,17 +420,17 @@ static int php_zip_parse_options(HashTable *options, zip_options *opts) if (Z_TYPE_P(option) != IS_STRING) { zend_type_error("Option \"remove_path\" must be of type string, %s given", zend_zval_value_name(option)); - return -1; + return FAILURE; } if (Z_STRLEN_P(option) == 0) { zend_value_error("Option \"remove_path\" must not be empty"); - return -1; + return FAILURE; } if (Z_STRLEN_P(option) >= MAXPATHLEN) { zend_value_error("Option \"remove_path\" must be less than %d bytes", MAXPATHLEN - 1); - return -1; + return FAILURE; } opts->remove_path_len = Z_STRLEN_P(option); opts->remove_path = Z_STRVAL_P(option); @@ -428,17 +440,17 @@ static int php_zip_parse_options(HashTable *options, zip_options *opts) if (Z_TYPE_P(option) != IS_STRING) { zend_type_error("Option \"add_path\" must be of type string, %s given", zend_zval_value_name(option)); - return -1; + return FAILURE; } if (Z_STRLEN_P(option) == 0) { zend_value_error("Option \"add_path\" must not be empty"); - return -1; + return FAILURE; } if (Z_STRLEN_P(option) >= MAXPATHLEN) { zend_value_error("Option \"add_path\" must be less than %d bytes", MAXPATHLEN - 1); - return -1; + return FAILURE; } opts->add_path_len = Z_STRLEN_P(option); opts->add_path = Z_STRVAL_P(option); @@ -448,12 +460,12 @@ static int php_zip_parse_options(HashTable *options, zip_options *opts) if (Z_TYPE_P(option) != IS_LONG) { zend_type_error("Option \"flags\" must be of type int, %s given", zend_zval_value_name(option)); - return -1; + return FAILURE; } opts->flags = Z_LVAL_P(option); } - return 1; + return SUCCESS; } /* }}} */ @@ -503,17 +515,11 @@ static zend_long php_zip_status(ze_zip_object *obj) /* {{{ */ int zep = obj->err_zip; /* saved err if closed */ if (obj->za) { -#if LIBZIP_VERSION_MAJOR < 1 - int syp; - - zip_error_get(obj->za, &zep, &syp); -#else zip_error_t *err; err = zip_get_error(obj->za); zep = zip_error_code_zip(err); zip_error_fini(err); -#endif } return zep; } @@ -530,17 +536,11 @@ static zend_long php_zip_status_sys(ze_zip_object *obj) /* {{{ */ int syp = obj->err_sys; /* saved err if closed */ if (obj->za) { -#if LIBZIP_VERSION_MAJOR < 1 - int zep; - - zip_error_get(obj->za, &zep, &syp); -#else zip_error_t *err; err = zip_get_error(obj->za); syp = zip_error_code_system(err); zip_error_fini(err); -#endif } return syp; } @@ -575,7 +575,7 @@ static char * php_zipobj_get_zip_comment(ze_zip_object *obj, int *len) /* {{{ */ } /* }}} */ -int php_zip_glob(char *pattern, int pattern_len, zend_long flags, zval *return_value) /* {{{ */ +int php_zip_glob(zend_string *spattern, zend_long flags, zval *return_value) /* {{{ */ { int cwd_skip = 0; #ifdef ZTS @@ -584,9 +584,11 @@ int php_zip_glob(char *pattern, int pattern_len, zend_long flags, zval *return_v char *result; #endif php_glob_t globbuf; - size_t n; int ret; + const char *pattern = ZSTR_VAL(spattern); + size_t pattern_len = ZSTR_LEN(spattern); + if (pattern_len >= MAXPATHLEN) { php_error_docref(NULL, E_WARNING, "Pattern exceeds the maximum allowed length of %d characters", MAXPATHLEN); return -1; @@ -628,7 +630,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 @@ -637,7 +638,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; } @@ -648,7 +648,7 @@ int php_zip_glob(char *pattern, int pattern_len, zend_long flags, zval *return_v } array_init(return_value); - for (n = 0; n < globbuf.gl_pathc; n++) { + for (size_t n = 0; n < globbuf.gl_pathc; n++) { /* we need to do this every time since PHP_GLOB_ONLYDIR does not guarantee that * all directories will be filtered. GNU libc documentation states the * following: @@ -719,7 +719,7 @@ int php_zip_pcre(zend_string *regexp, char *path, int path_len, zval *return_val re = pcre_get_compiled_regex(regexp, &capture_count); if (!re) { for (i = 0; i < files_cnt; i++) { - zend_string_release_ex(namelist[i], 0); + zend_string_release_ex(namelist[i], false); } efree(namelist); php_error_docref(NULL, E_WARNING, "Invalid expression"); @@ -736,28 +736,28 @@ int php_zip_pcre(zend_string *regexp, char *path, int path_len, zval *return_val if ((namelist_len == 1 && ZSTR_VAL(namelist[i])[0] == '.') || (namelist_len == 2 && ZSTR_VAL(namelist[i])[0] == '.' && ZSTR_VAL(namelist[i])[1] == '.')) { - zend_string_release_ex(namelist[i], 0); + zend_string_release_ex(namelist[i], false); continue; } if ((path_len + namelist_len + 1) >= MAXPATHLEN) { php_error_docref(NULL, E_WARNING, "add_path string too long (max: %u, %zu given)", MAXPATHLEN - 1, (path_len + namelist_len + 1)); - zend_string_release_ex(namelist[i], 0); + zend_string_release_ex(namelist[i], false); break; } match_data = php_pcre_create_match_data(capture_count, re); if (!match_data) { /* Allocation failed, but can proceed to the next pattern. */ - zend_string_release_ex(namelist[i], 0); + zend_string_release_ex(namelist[i], false); continue; } rc = pcre2_match(re, (PCRE2_SPTR)ZSTR_VAL(namelist[i]), ZSTR_LEN(namelist[i]), 0, 0, match_data, mctx); php_pcre_free_match_data(match_data); /* 0 means that the vector is too small to hold all the captured substring offsets */ if (rc < 0) { - zend_string_release_ex(namelist[i], 0); + zend_string_release_ex(namelist[i], false); continue; } @@ -765,17 +765,17 @@ int php_zip_pcre(zend_string *regexp, char *path, int path_len, zval *return_val if (0 != VCWD_STAT(fullpath, &s)) { php_error_docref(NULL, E_WARNING, "Cannot read <%s>", fullpath); - zend_string_release_ex(namelist[i], 0); + zend_string_release_ex(namelist[i], false); continue; } if (S_IFDIR == (s.st_mode & S_IFMT)) { - zend_string_release_ex(namelist[i], 0); + zend_string_release_ex(namelist[i], false); continue; } add_next_index_string(return_value, fullpath); - zend_string_release_ex(namelist[i], 0); + zend_string_release_ex(namelist[i], false); } efree(namelist); } @@ -808,9 +808,9 @@ static void php_zip_register_prop_handler(HashTable *prop_handler, char *name, z hnd.read_const_char_func = read_char_func; hnd.read_int_func = read_int_func; hnd.type = rettype; - str = zend_string_init_interned(name, strlen(name), 1); + str = zend_string_init_interned(name, strlen(name), true); zend_hash_add_mem(prop_handler, str, &hnd, sizeof(zip_prop_handler)); - zend_string_release_ex(str, 1); + zend_string_release_ex(str, true); } /* }}} */ @@ -928,17 +928,16 @@ static int php_zip_has_property(zend_object *object, zend_string *name, int type if (hnd != NULL) { zval tmp, *prop; - if (type == 2) { + if (type == ZEND_PROPERTY_EXISTS) { retval = true; } else if ((prop = php_zip_property_reader(obj, hnd, &tmp)) != NULL) { - if (type == 1) { + if (type == ZEND_PROPERTY_NOT_EMPTY) { retval = zend_is_true(&tmp); - } else if (type == 0) { + } else if (type == ZEND_PROPERTY_ISSET) { retval = (Z_TYPE(tmp) != IS_NULL); } + zval_ptr_dtor(&tmp); } - - zval_ptr_dtor(&tmp); } else { retval = zend_std_has_property(object, name, type, cache_slot); } @@ -963,12 +962,12 @@ static HashTable *php_zip_get_properties(zend_object *object)/* {{{ */ zend_string *key; obj = php_zip_fetch_object(object); - props = zend_std_get_properties(object); if (obj->prop_handler == NULL) { return NULL; } + props = zend_std_get_properties(object); ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(obj->prop_handler, key, hnd) { zval *ret, val; ret = php_zip_property_reader(obj, hnd, &val); @@ -1004,6 +1003,21 @@ static void php_zip_cancel_callback_free(void *ptr) } #endif +static void php_zip_object_dtor(zend_object *object) +{ + zend_objects_destroy_object(object); + + ze_zip_object *intern = php_zip_fetch_object(object); + + if (intern->za) { + if (zip_close(intern->za) != 0) { + php_error_docref(NULL, E_WARNING, "Cannot destroy the zip context: %s", zip_strerror(intern->za)); + zip_discard(intern->za); + } + intern->za = NULL; + } +} + static void php_zip_object_free_storage(zend_object *object) /* {{{ */ { ze_zip_object * intern = php_zip_fetch_object(object); @@ -1018,7 +1032,7 @@ static void php_zip_object_free_storage(zend_object *object) /* {{{ */ if (intern->buffers_cnt>0) { for (i=0; ibuffers_cnt; i++) { - efree(intern->buffers[i]); + zend_string_release(intern->buffers[i]); } efree(intern->buffers); } @@ -1206,7 +1220,7 @@ PHP_FUNCTION(zip_read) RETURN_THROWS(); } - if (rsrc_int && rsrc_int->za) { + if (rsrc_int->za) { if (rsrc_int->index_current >= rsrc_int->num_files) { RETURN_FALSE; } @@ -1259,11 +1273,7 @@ PHP_FUNCTION(zip_entry_open) RETURN_THROWS(); } - if (zr_rsrc->zf != NULL) { - RETURN_TRUE; - } else { - RETURN_FALSE; - } + RETURN_BOOL(zr_rsrc->zf != NULL); } /* }}} */ @@ -1293,7 +1303,6 @@ PHP_FUNCTION(zip_entry_read) zend_long len = 0; zip_read_rsrc * zr_rsrc; zend_string *buffer; - int n = 0; if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|l", &zip_entry, &len) == FAILURE) { RETURN_THROWS(); @@ -1308,8 +1317,8 @@ PHP_FUNCTION(zip_entry_read) } if (zr_rsrc->zf) { - buffer = zend_string_safe_alloc(1, len, 0, 0); - n = zip_fread(zr_rsrc->zf, ZSTR_VAL(buffer), ZSTR_LEN(buffer)); + buffer = zend_string_safe_alloc(1, len, 0, false); + zip_int64_t n = zip_fread(zr_rsrc->zf, ZSTR_VAL(buffer), ZSTR_LEN(buffer)); if (n > 0) { ZSTR_VAL(buffer)[n] = '\0'; ZSTR_LEN(buffer) = n; @@ -1501,12 +1510,7 @@ PHP_METHOD(ZipArchive, setPassword) RETURN_FALSE; } - int res = zip_set_default_password(intern, (const char *)password); - if (res == 0) { - RETURN_TRUE; - } else { - RETURN_FALSE; - } + RETURN_BOOL(zip_set_default_password(intern, (const char *)password) == 0); } /* }}} */ @@ -1530,18 +1534,12 @@ PHP_METHOD(ZipArchive, close) if (err) { php_error_docref(NULL, E_WARNING, "%s", zip_strerror(intern)); /* Save error for property reader */ - #if LIBZIP_VERSION_MAJOR < 1 - zip_error_get(intern, &ze_obj->err_zip, &ze_obj->err_sys); - #else - { - zip_error_t *ziperr; - - ziperr = zip_get_error(intern); - ze_obj->err_zip = zip_error_code_zip(ziperr); - ze_obj->err_sys = zip_error_code_system(ziperr); - zip_error_fini(ziperr); - } - #endif + zip_error_t *ziperr; + + ziperr = zip_get_error(intern); + ze_obj->err_zip = zip_error_code_zip(ziperr); + ze_obj->err_sys = zip_error_code_system(ziperr); + zip_error_fini(ziperr); zip_discard(intern); } else { ze_obj->err_zip = 0; @@ -1556,11 +1554,7 @@ PHP_METHOD(ZipArchive, close) ze_obj->filename_len = 0; ze_obj->za = NULL; - if (!err) { - RETURN_TRUE; - } else { - RETURN_FALSE; - } + RETURN_BOOL(!err); } /* }}} */ @@ -1606,10 +1600,6 @@ PHP_METHOD(ZipArchive, clearError) PHP_METHOD(ZipArchive, getStatusString) { zval *self = ZEND_THIS; -#if LIBZIP_VERSION_MAJOR < 1 - int zep, syp, len; - char error_string[128]; -#endif ze_zip_object *ze_obj; if (zend_parse_parameters_none() == FAILURE) { @@ -1618,15 +1608,6 @@ PHP_METHOD(ZipArchive, getStatusString) ze_obj = Z_ZIP_P(self); /* not ZIP_FROM_OBJECT as we can use saved error after close */ -#if LIBZIP_VERSION_MAJOR < 1 - if (ze_obj->za) { - zip_error_get(ze_obj->za, &zep, &syp); - len = zip_error_to_str(error_string, 128, zep, syp); - } else { - len = zip_error_to_str(error_string, 128, ze_obj->err_zip, ze_obj->err_sys); - } - RETVAL_STRINGL(error_string, len); -#else if (ze_obj->za) { zip_error_t *err; @@ -1641,7 +1622,6 @@ PHP_METHOD(ZipArchive, getStatusString) RETVAL_STRING(zip_error_strerror(&err)); zip_error_fini(&err); } -#endif } /* }}} */ @@ -1716,24 +1696,21 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* zend_argument_must_not_be_empty_error(1); RETURN_THROWS(); } - if (options && zend_hash_num_elements(options) > 0 && (php_zip_parse_options(options, &opts) < 0)) { + if (options && zend_hash_num_elements(options) > 0 && (php_zip_parse_options(options, &opts) == FAILURE)) { RETURN_THROWS(); } if (type == 1) { - found = php_zip_glob(ZSTR_VAL(pattern), ZSTR_LEN(pattern), glob_flags, return_value); + found = php_zip_glob(pattern, glob_flags, return_value); } else { found = php_zip_pcre(pattern, path, path_len, return_value); } if (found > 0) { - int i; zval *zval_file; - ze_zip_object *ze_obj; - - ze_obj = Z_ZIP_P(self); + ze_zip_object *ze_obj = Z_ZIP_P(self); - for (i = 0; i < found; i++) { + for (int i = 0; i < found; i++) { char *file_stripped, *entry_name; size_t entry_name_len, file_stripped_len; char entry_name_buf[MAXPATHLEN]; @@ -1744,7 +1721,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; @@ -1760,7 +1737,7 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* if (opts.add_path) { if ((opts.add_path_len + file_stripped_len) > MAXPATHLEN) { if (basename) { - zend_string_release_ex(basename, 0); + zend_string_release_ex(basename, false); } php_error_docref(NULL, E_WARNING, "Entry name too long (max: %d, %zd given)", MAXPATHLEN - 1, (opts.add_path_len + file_stripped_len)); @@ -1775,12 +1752,12 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* entry_name = entry_name_buf; entry_name_len = strlen(entry_name); if (basename) { - zend_string_release_ex(basename, 0); + zend_string_release_ex(basename, false); basename = NULL; } if (php_zip_add_file(ze_obj, Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file), - entry_name, entry_name_len, 0, 0, -1, opts.flags) < 0) { + entry_name, entry_name_len, 0, 0, -1, opts.flags) == FAILURE) { zend_array_destroy(Z_ARR_P(return_value)); RETURN_FALSE; } @@ -1792,7 +1769,7 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* } #ifdef HAVE_ENCRYPTION if (opts.enc_method >= 0) { - if (zip_file_set_encryption(ze_obj->za, ze_obj->last_id, opts.enc_method, opts.enc_password)) { + if (!php_zip_file_set_encryption(ze_obj->za, ze_obj->last_id, opts.enc_method, opts.enc_password)) { zend_array_destroy(Z_ARR_P(return_value)); RETURN_FALSE; } @@ -1847,12 +1824,8 @@ PHP_METHOD(ZipArchive, addFile) entry_name_len = ZSTR_LEN(filename); } - if (php_zip_add_file(Z_ZIP_P(self), ZSTR_VAL(filename), ZSTR_LEN(filename), - entry_name, entry_name_len, offset_start, offset_len, -1, flags) < 0) { - RETURN_FALSE; - } else { - RETURN_TRUE; - } + RETURN_BOOL(php_zip_add_file(Z_ZIP_P(self), ZSTR_VAL(filename), ZSTR_LEN(filename), + entry_name, entry_name_len, offset_start, offset_len, -1, flags) == SUCCESS); } /* }}} */ @@ -1880,12 +1853,8 @@ PHP_METHOD(ZipArchive, replaceFile) RETURN_THROWS(); } - if (php_zip_add_file(Z_ZIP_P(self), ZSTR_VAL(filename), ZSTR_LEN(filename), - NULL, 0, offset_start, offset_len, index, flags) < 0) { - RETURN_FALSE; - } else { - RETURN_TRUE; - } + RETURN_BOOL(php_zip_add_file(Z_ZIP_P(self), ZSTR_VAL(filename), ZSTR_LEN(filename), + NULL, 0, offset_start, offset_len, index, flags) == SUCCESS); } /* }}} */ @@ -1911,17 +1880,16 @@ PHP_METHOD(ZipArchive, addFromString) ze_obj = Z_ZIP_P(self); if (ze_obj->buffers_cnt) { - ze_obj->buffers = (char **)safe_erealloc(ze_obj->buffers, sizeof(char *), (ze_obj->buffers_cnt+1), 0); + ze_obj->buffers = safe_erealloc(ze_obj->buffers, sizeof(*ze_obj->buffers), (ze_obj->buffers_cnt + 1), 0); pos = ze_obj->buffers_cnt++; } else { - ze_obj->buffers = (char **)emalloc(sizeof(char *)); + ze_obj->buffers = emalloc(sizeof(*ze_obj->buffers)); ze_obj->buffers_cnt++; pos = 0; } - ze_obj->buffers[pos] = (char *)safe_emalloc(ZSTR_LEN(buffer), 1, 1); - memcpy(ze_obj->buffers[pos], ZSTR_VAL(buffer), ZSTR_LEN(buffer) + 1); + ze_obj->buffers[pos] = zend_string_copy(buffer); - zs = zip_source_buffer(intern, ze_obj->buffers[pos], ZSTR_LEN(buffer), 0); + zs = zip_source_buffer(intern, ZSTR_VAL(buffer), ZSTR_LEN(buffer), 0); if (zs == NULL) { RETURN_FALSE; @@ -2055,11 +2023,7 @@ PHP_METHOD(ZipArchive, setArchiveComment) RETURN_THROWS(); } - if (zip_set_archive_comment(intern, (const char *)comment, comment_len)) { - RETURN_FALSE; - } else { - RETURN_TRUE; - } + RETURN_BOOL(zip_set_archive_comment(intern, (const char *)comment, comment_len) == 0); } /* }}} */ @@ -2098,11 +2062,7 @@ PHP_METHOD(ZipArchive, setArchiveFlag) ZIP_FROM_OBJECT(intern, self); - if (zip_set_archive_flag(intern, flag, (int)value)) { - RETURN_FALSE; - } else { - RETURN_TRUE; - } + RETURN_BOOL(zip_set_archive_flag(intern, flag, (int)value) == 0); } PHP_METHOD(ZipArchive, getArchiveFlag) @@ -2208,10 +2168,7 @@ PHP_METHOD(ZipArchive, setExternalAttributesName) idx = zip_name_locate(intern, name, 0); - if (idx < 0) { - RETURN_FALSE; - } - if (zip_file_set_external_attributes(intern, idx, (zip_flags_t)flags, + if (idx < 0 || zip_file_set_external_attributes(intern, idx, (zip_flags_t)flags, (zip_uint8_t)(opsys&0xff), (zip_uint32_t)attr) < 0) { RETURN_FALSE; } @@ -2235,11 +2192,8 @@ PHP_METHOD(ZipArchive, setExternalAttributesIndex) ZIP_FROM_OBJECT(intern, self); PHP_ZIP_STAT_INDEX(intern, index, 0, sb); - if (zip_file_set_external_attributes(intern, (zip_uint64_t)index, - (zip_flags_t)flags, (zip_uint8_t)(opsys&0xff), (zip_uint32_t)attr) < 0) { - RETURN_FALSE; - } - RETURN_TRUE; + RETURN_BOOL(zip_file_set_external_attributes(intern, (zip_uint64_t)index, + (zip_flags_t)flags, (zip_uint8_t)(opsys&0xff), (zip_uint32_t)attr) == 0); } /* }}} */ @@ -2269,10 +2223,7 @@ PHP_METHOD(ZipArchive, getExternalAttributesName) idx = zip_name_locate(intern, name, 0); - if (idx < 0) { - RETURN_FALSE; - } - if (zip_file_get_external_attributes(intern, idx, + if (idx < 0 || zip_file_get_external_attributes(intern, idx, (zip_flags_t)flags, &opsys, &attr) < 0) { RETURN_FALSE; } @@ -2340,10 +2291,7 @@ PHP_METHOD(ZipArchive, setEncryptionName) RETURN_FALSE; } - if (zip_file_set_encryption(intern, idx, (zip_uint16_t)method, password)) { - RETURN_FALSE; - } - RETURN_TRUE; + RETURN_BOOL(php_zip_file_set_encryption(intern, idx, method, password)); } /* }}} */ @@ -2363,10 +2311,7 @@ PHP_METHOD(ZipArchive, setEncryptionIndex) ZIP_FROM_OBJECT(intern, self); - if (zip_file_set_encryption(intern, index, (zip_uint16_t)method, password)) { - RETURN_FALSE; - } - RETURN_TRUE; + RETURN_BOOL(php_zip_file_set_encryption(intern, index, method, password)); } /* }}} */ #endif @@ -2444,24 +2389,31 @@ PHP_METHOD(ZipArchive, setCompressionName) RETURN_THROWS(); } - ZIP_FROM_OBJECT(intern, this); - if (name_len == 0) { zend_argument_must_not_be_empty_error(1); RETURN_THROWS(); } + if (comp_method < -1 || comp_method > INT_MAX) { + zend_argument_value_error(2, "must be between -1 and %d", INT_MAX); + RETURN_THROWS(); + } + + if (comp_flags < 0 || comp_flags > USHRT_MAX) { + // comp_flags is cast down accordingly in libzip, zip_entry_t compression_level is of zip_uint16_t + zend_argument_value_error(3, "must be between 0 and %u", USHRT_MAX); + RETURN_THROWS(); + } + + ZIP_FROM_OBJECT(intern, this); idx = zip_name_locate(intern, name, 0); if (idx < 0) { RETURN_FALSE; } - if (zip_set_file_compression(intern, (zip_uint64_t)idx, - (zip_int32_t)comp_method, (zip_uint32_t)comp_flags) != 0) { - RETURN_FALSE; - } - RETURN_TRUE; + RETURN_BOOL(zip_set_file_compression(intern, (zip_uint64_t)idx, + (zip_int32_t)comp_method, (zip_uint32_t)comp_flags) == 0); } /* }}} */ @@ -2478,17 +2430,28 @@ PHP_METHOD(ZipArchive, setCompressionIndex) RETURN_THROWS(); } - ZIP_FROM_OBJECT(intern, this); - - if (zip_set_file_compression(intern, (zip_uint64_t)index, - (zip_int32_t)comp_method, (zip_uint32_t)comp_flags) != 0) { + if (index < 0) { RETURN_FALSE; } - RETURN_TRUE; + + if (comp_method < -1 || comp_method > INT_MAX) { + zend_argument_value_error(2, "must be between -1 and %d", INT_MAX); + RETURN_THROWS(); + } + + if (comp_flags < 0 || comp_flags > USHRT_MAX) { + // comp_flags is cast down accordingly in libzip, zip_entry_t compression_level is of zip_uint16_t + zend_argument_value_error(3, "must be between 0 and %u", USHRT_MAX); + RETURN_THROWS(); + } + + ZIP_FROM_OBJECT(intern, this); + + RETURN_BOOL(zip_set_file_compression(intern, (zip_uint64_t)index, + (zip_int32_t)comp_method, (zip_uint32_t)comp_flags) == 0); } /* }}} */ -#ifdef HAVE_SET_MTIME /* {{{ Set the modification time of a file in zip, using its name */ PHP_METHOD(ZipArchive, setMtimeName) { @@ -2504,24 +2467,21 @@ PHP_METHOD(ZipArchive, setMtimeName) RETURN_THROWS(); } - ZIP_FROM_OBJECT(intern, this); - if (name_len == 0) { zend_argument_must_not_be_empty_error(1); RETURN_THROWS(); } + ZIP_FROM_OBJECT(intern, this); + idx = zip_name_locate(intern, name, 0); if (idx < 0) { RETURN_FALSE; } - if (zip_file_set_mtime(intern, (zip_uint64_t)idx, - (time_t)mtime, (zip_uint32_t)flags) != 0) { - RETURN_FALSE; - } - RETURN_TRUE; + RETURN_BOOL(zip_file_set_mtime(intern, (zip_uint64_t)idx, + (time_t)mtime, (zip_uint32_t)flags) == 0); } /* }}} */ @@ -2540,14 +2500,10 @@ PHP_METHOD(ZipArchive, setMtimeIndex) ZIP_FROM_OBJECT(intern, this); - if (zip_file_set_mtime(intern, (zip_uint64_t)index, - (time_t)mtime, (zip_uint32_t)flags) != 0) { - RETURN_FALSE; - } - RETURN_TRUE; + RETURN_BOOL(zip_file_set_mtime(intern, (zip_uint64_t)index, + (time_t)mtime, (zip_uint32_t)flags) == 0); } /* }}} */ -#endif /* {{{ Delete a file using its index */ PHP_METHOD(ZipArchive, deleteIndex) @@ -2566,11 +2522,7 @@ PHP_METHOD(ZipArchive, deleteIndex) RETURN_FALSE; } - if (zip_delete(intern, index) < 0) { - RETURN_FALSE; - } - - RETURN_TRUE; + RETURN_BOOL(zip_delete(intern, index) == 0); } /* }}} */ @@ -2587,17 +2539,15 @@ PHP_METHOD(ZipArchive, deleteName) RETURN_THROWS(); } - ZIP_FROM_OBJECT(intern, self); - if (name_len < 1) { RETURN_FALSE; } + ZIP_FROM_OBJECT(intern, self); + PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb); - if (zip_delete(intern, sb.index)) { - RETURN_FALSE; - } - RETURN_TRUE; + + RETURN_BOOL(zip_delete(intern, sb.index) == 0); } /* }}} */ @@ -2618,18 +2568,14 @@ PHP_METHOD(ZipArchive, renameIndex) RETURN_FALSE; } - ZIP_FROM_OBJECT(intern, self); - if (new_name_len == 0) { zend_argument_must_not_be_empty_error(2); RETURN_THROWS(); } - if (zip_file_rename(intern, index, (const char *)new_name, 0) != 0) { - RETURN_FALSE; - } + ZIP_FROM_OBJECT(intern, self); - RETURN_TRUE; + RETURN_BOOL(zip_file_rename(intern, index, (const char *)new_name, 0) == 0); } /* }}} */ @@ -2655,11 +2601,7 @@ PHP_METHOD(ZipArchive, renameName) PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb); - if (zip_file_rename(intern, sb.index, (const char *)new_name, 0)) { - RETURN_FALSE; - } - - RETURN_TRUE; + RETURN_BOOL(zip_file_rename(intern, sb.index, (const char *)new_name, 0) == 0); } /* }}} */ @@ -2674,17 +2616,13 @@ PHP_METHOD(ZipArchive, unchangeIndex) RETURN_THROWS(); } - ZIP_FROM_OBJECT(intern, self); - if (index < 0) { RETURN_FALSE; } - if (zip_unchange(intern, index) != 0) { - RETURN_FALSE; - } else { - RETURN_TRUE; - } + ZIP_FROM_OBJECT(intern, self); + + RETURN_BOOL(zip_unchange(intern, index) == 0); } /* }}} */ @@ -2701,19 +2639,15 @@ PHP_METHOD(ZipArchive, unchangeName) RETURN_THROWS(); } - ZIP_FROM_OBJECT(intern, self); - if (name_len < 1) { RETURN_FALSE; } + ZIP_FROM_OBJECT(intern, self); + PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb); - if (zip_unchange(intern, sb.index) != 0) { - RETURN_FALSE; - } else { - RETURN_TRUE; - } + RETURN_BOOL(zip_unchange(intern, sb.index) == 0); } /* }}} */ @@ -2729,11 +2663,7 @@ PHP_METHOD(ZipArchive, unchangeAll) ZIP_FROM_OBJECT(intern, self); - if (zip_unchange_all(intern) != 0) { - RETURN_FALSE; - } else { - RETURN_TRUE; - } + RETURN_BOOL(zip_unchange_all(intern) == 0); } /* }}} */ @@ -2749,11 +2679,7 @@ PHP_METHOD(ZipArchive, unchangeArchive) ZIP_FROM_OBJECT(intern, self); - if (zip_unchange_archive(intern) != 0) { - RETURN_FALSE; - } else { - RETURN_TRUE; - } + RETURN_BOOL(zip_unchange_archive(intern) == 0); } /* }}} */ @@ -2782,8 +2708,6 @@ PHP_METHOD(ZipArchive, extractTo) Z_PARAM_ARRAY_HT_OR_STR_OR_NULL(files_ht, files_str) ZEND_PARSE_PARAMETERS_END(); - ZIP_FROM_OBJECT(intern, self); - if (pathto_len < 1) { RETURN_FALSE; } @@ -2796,6 +2720,7 @@ PHP_METHOD(ZipArchive, extractTo) } uint32_t nelems, i; + ZIP_FROM_OBJECT(intern, self); if (files_str) { if (!php_zip_extract_file(intern, pathto, ZSTR_VAL(files_str), ZSTR_LEN(files_str), -1)) { @@ -2809,14 +2734,13 @@ PHP_METHOD(ZipArchive, extractTo) for (i = 0; i < nelems; i++) { zval *zval_file; if ((zval_file = zend_hash_index_find_deref(files_ht, i)) != NULL) { - switch (Z_TYPE_P(zval_file)) { - case IS_LONG: - break; - case IS_STRING: + if (Z_TYPE_P(zval_file) == IS_STRING) { if (!php_zip_extract_file(intern, pathto, Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file), -1)) { RETURN_FALSE; } - break; + } else { + zend_argument_type_error(2, "must only have elements of type string, %s given", zend_zval_value_name(zval_file)); + RETURN_THROWS(); } } } @@ -2856,8 +2780,6 @@ static void php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */ zend_string *filename; zend_string *buffer; - int n = 0; - if (type == 1) { if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|ll", &filename, &len, &flags) == FAILURE) { RETURN_THROWS(); @@ -2893,8 +2815,8 @@ static void php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */ RETURN_FALSE; } - buffer = zend_string_safe_alloc(1, len, 0, 0); - n = zip_fread(zf, ZSTR_VAL(buffer), ZSTR_LEN(buffer)); + buffer = zend_string_safe_alloc(1, len, 0, false); + zip_int64_t n = zip_fread(zf, ZSTR_VAL(buffer), ZSTR_LEN(buffer)); if (n < 1) { zend_string_efree(buffer); RETURN_EMPTY_STRING(); @@ -2987,6 +2909,10 @@ PHP_METHOD(ZipArchive, getStream) #ifdef HAVE_PROGRESS_CALLBACK static void php_zip_progress_callback(zip_t *arch, double state, void *ptr) { + if (!EG(active)) { + return; + } + zval cb_args[1]; ze_zip_object *obj = ptr; @@ -3018,6 +2944,7 @@ PHP_METHOD(ZipArchive, registerProgressCallback) /* register */ if (zip_register_progress_callback_with_state(intern, rate, php_zip_progress_callback, php_zip_progress_callback_free, obj)) { + zend_release_fcall_info_cache(&fcc); RETURN_FALSE; } zend_fcc_dup(&obj->progress_callback, &fcc); @@ -3033,6 +2960,10 @@ static int php_zip_cancel_callback(zip_t *arch, void *ptr) zval cb_retval; ze_zip_object *obj = ptr; + if (!EG(active)) { + return 0; + } + zend_call_known_fcc(&obj->cancel_callback, &cb_retval, 0, NULL, NULL); if (Z_ISUNDEF(cb_retval)) { /* Cancel if an exception has been thrown */ @@ -3073,6 +3004,7 @@ PHP_METHOD(ZipArchive, registerCancelCallback) /* register */ if (zip_register_cancel_callback_with_state(intern, php_zip_cancel_callback, php_zip_cancel_callback_free, obj)) { + zend_release_fcall_info_cache(&fcc); RETURN_FALSE; } zend_fcc_dup(&obj->cancel_callback, &fcc); @@ -3087,11 +3019,15 @@ PHP_METHOD(ZipArchive, registerCancelCallback) PHP_METHOD(ZipArchive, isCompressionMethodSupported) { zend_long method; - bool enc = 1; + bool enc = true; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|b", &method, &enc) == FAILURE) { return; } + if (method < -1 || method > INT_MAX) { + zend_argument_value_error(1, "must be between -1 and %d", INT_MAX); + RETURN_THROWS(); + } RETVAL_BOOL(zip_compression_method_supported((zip_int32_t)method, enc)); } /* }}} */ @@ -3100,12 +3036,16 @@ PHP_METHOD(ZipArchive, isCompressionMethodSupported) PHP_METHOD(ZipArchive, isEncryptionMethodSupported) { zend_long method; - bool enc = 1; + bool enc = true; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|b", &method, &enc) == FAILURE) { return; } - RETVAL_BOOL(zip_encryption_method_supported((zip_uint16_t)method, enc)); + if (method < 0 || method > USHRT_MAX) { + zend_argument_value_error(1, "must be between 0 and %u", USHRT_MAX); + RETURN_THROWS(); + } + RETURN_BOOL(zip_encryption_method_supported((zip_uint16_t)method, enc)); } /* }}} */ #endif @@ -3120,6 +3060,7 @@ static PHP_MINIT_FUNCTION(zip) memcpy(&zip_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); zip_object_handlers.offset = XtOffsetOf(ze_zip_object, zo); zip_object_handlers.free_obj = php_zip_object_free_storage; + zip_object_handlers.dtor_obj = php_zip_object_dtor; zip_object_handlers.clone_obj = NULL; zip_object_handlers.get_property_ptr_ptr = php_zip_get_property_ptr_ptr; diff --git a/ext/zip/php_zip.h b/ext/zip/php_zip.h index 01d6c3d10133e..5dc7bab250042 100644 --- a/ext/zip/php_zip.h +++ b/ext/zip/php_zip.h @@ -39,7 +39,7 @@ extern zend_module_entry zip_module_entry; /* Additionnal flags not from libzip */ #define ZIP_FL_OPEN_FILE_NOW (1u<<30) -#define PHP_ZIP_VERSION "1.22.6" +#define PHP_ZIP_VERSION "1.22.7" #ifdef HAVE_LIBZIP_VERSION #define LIBZIP_VERSION_STR zip_libzip_version() @@ -68,7 +68,7 @@ typedef struct _ze_zip_read_rsrc { /* Extends zend object */ typedef struct _ze_zip_object { struct zip *za; - char **buffers; + zend_string **buffers; HashTable *prop_handler; char *filename; int filename_len; diff --git a/ext/zip/php_zip.stub.php b/ext/zip/php_zip.stub.php index 3473d27bf2050..8a37b2508da18 100644 --- a/ext/zip/php_zip.stub.php +++ b/ext/zip/php_zip.stub.php @@ -704,13 +704,11 @@ public function setCommentIndex(int $index, string $comment): bool {} /** @tentative-return-type */ public function setCommentName(string $name, string $comment): bool {} -#ifdef HAVE_SET_MTIME /** @tentative-return-type */ public function setMtimeIndex(int $index, int $timestamp, int $flags = 0): bool {} /** @tentative-return-type */ public function setMtimeName(string $name, int $timestamp, int $flags = 0): bool {} -#endif /** @tentative-return-type */ public function getCommentIndex(int $index, int $flags = 0): string|false {} diff --git a/ext/zip/php_zip_arginfo.h b/ext/zip/php_zip_arginfo.h index 197204bbd4933..ba4f867e8af73 100644 --- a/ext/zip/php_zip_arginfo.h +++ b/ext/zip/php_zip_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 53e04d9b2c25cc8a0c9fe51914b5a47280834fb8 */ + * Stub hash: 1f77735273373672b9c8c5b92c46e23ea99faeaf */ ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_open, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0) @@ -138,7 +138,6 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_ZipArchive_setCo ZEND_ARG_TYPE_INFO(0, comment, IS_STRING, 0) ZEND_END_ARG_INFO() -#if defined(HAVE_SET_MTIME) ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_ZipArchive_setMtimeIndex, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, index, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, timestamp, IS_LONG, 0) @@ -150,7 +149,6 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_ZipArchive_setMt ZEND_ARG_TYPE_INFO(0, timestamp, IS_LONG, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() -#endif ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX(arginfo_class_ZipArchive_getCommentIndex, 0, 1, MAY_BE_STRING|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, index, IS_LONG, 0) @@ -334,10 +332,8 @@ ZEND_METHOD(ZipArchive, setArchiveFlag); ZEND_METHOD(ZipArchive, getArchiveFlag); ZEND_METHOD(ZipArchive, setCommentIndex); ZEND_METHOD(ZipArchive, setCommentName); -#if defined(HAVE_SET_MTIME) ZEND_METHOD(ZipArchive, setMtimeIndex); ZEND_METHOD(ZipArchive, setMtimeName); -#endif ZEND_METHOD(ZipArchive, getCommentIndex); ZEND_METHOD(ZipArchive, getCommentName); ZEND_METHOD(ZipArchive, deleteIndex); @@ -414,10 +410,8 @@ static const zend_function_entry class_ZipArchive_methods[] = { ZEND_ME(ZipArchive, getArchiveFlag, arginfo_class_ZipArchive_getArchiveFlag, ZEND_ACC_PUBLIC) ZEND_ME(ZipArchive, setCommentIndex, arginfo_class_ZipArchive_setCommentIndex, ZEND_ACC_PUBLIC) ZEND_ME(ZipArchive, setCommentName, arginfo_class_ZipArchive_setCommentName, ZEND_ACC_PUBLIC) -#if defined(HAVE_SET_MTIME) ZEND_ME(ZipArchive, setMtimeIndex, arginfo_class_ZipArchive_setMtimeIndex, ZEND_ACC_PUBLIC) ZEND_ME(ZipArchive, setMtimeName, arginfo_class_ZipArchive_setMtimeName, ZEND_ACC_PUBLIC) -#endif ZEND_ME(ZipArchive, getCommentIndex, arginfo_class_ZipArchive_getCommentIndex, ZEND_ACC_PUBLIC) ZEND_ME(ZipArchive, getCommentName, arginfo_class_ZipArchive_getCommentName, ZEND_ACC_PUBLIC) ZEND_ME(ZipArchive, deleteIndex, arginfo_class_ZipArchive_deleteIndex, ZEND_ACC_PUBLIC) @@ -467,28 +461,22 @@ 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_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_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_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); @@ -502,46 +490,32 @@ static void register_php_zip_symbols(int module_number) 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_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_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_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_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_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); } @@ -555,740 +529,740 @@ static zend_class_entry *register_class_ZipArchive(zend_class_entry *class_entry zval const_CREATE_value; ZVAL_LONG(&const_CREATE_value, ZIP_CREATE); - zend_string *const_CREATE_name = zend_string_init_interned("CREATE", sizeof("CREATE") - 1, 1); + zend_string *const_CREATE_name = zend_string_init_interned("CREATE", sizeof("CREATE") - 1, true); zend_declare_typed_class_constant(class_entry, const_CREATE_name, &const_CREATE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CREATE_name); + zend_string_release_ex(const_CREATE_name, true); zval const_EXCL_value; ZVAL_LONG(&const_EXCL_value, ZIP_EXCL); - zend_string *const_EXCL_name = zend_string_init_interned("EXCL", sizeof("EXCL") - 1, 1); + zend_string *const_EXCL_name = zend_string_init_interned("EXCL", sizeof("EXCL") - 1, true); zend_declare_typed_class_constant(class_entry, const_EXCL_name, &const_EXCL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EXCL_name); + zend_string_release_ex(const_EXCL_name, true); zval const_CHECKCONS_value; ZVAL_LONG(&const_CHECKCONS_value, ZIP_CHECKCONS); - zend_string *const_CHECKCONS_name = zend_string_init_interned("CHECKCONS", sizeof("CHECKCONS") - 1, 1); + zend_string *const_CHECKCONS_name = zend_string_init_interned("CHECKCONS", sizeof("CHECKCONS") - 1, true); zend_declare_typed_class_constant(class_entry, const_CHECKCONS_name, &const_CHECKCONS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CHECKCONS_name); + zend_string_release_ex(const_CHECKCONS_name, true); zval const_OVERWRITE_value; ZVAL_LONG(&const_OVERWRITE_value, ZIP_OVERWRITE); - zend_string *const_OVERWRITE_name = zend_string_init_interned("OVERWRITE", sizeof("OVERWRITE") - 1, 1); + zend_string *const_OVERWRITE_name = zend_string_init_interned("OVERWRITE", sizeof("OVERWRITE") - 1, true); zend_declare_typed_class_constant(class_entry, const_OVERWRITE_name, &const_OVERWRITE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OVERWRITE_name); + zend_string_release_ex(const_OVERWRITE_name, true); #if defined(ZIP_RDONLY) zval const_RDONLY_value; ZVAL_LONG(&const_RDONLY_value, ZIP_RDONLY); - zend_string *const_RDONLY_name = zend_string_init_interned("RDONLY", sizeof("RDONLY") - 1, 1); + zend_string *const_RDONLY_name = zend_string_init_interned("RDONLY", sizeof("RDONLY") - 1, true); zend_declare_typed_class_constant(class_entry, const_RDONLY_name, &const_RDONLY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_RDONLY_name); + zend_string_release_ex(const_RDONLY_name, true); #endif zval const_FL_NOCASE_value; ZVAL_LONG(&const_FL_NOCASE_value, ZIP_FL_NOCASE); - zend_string *const_FL_NOCASE_name = zend_string_init_interned("FL_NOCASE", sizeof("FL_NOCASE") - 1, 1); + zend_string *const_FL_NOCASE_name = zend_string_init_interned("FL_NOCASE", sizeof("FL_NOCASE") - 1, true); zend_declare_typed_class_constant(class_entry, const_FL_NOCASE_name, &const_FL_NOCASE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FL_NOCASE_name); + zend_string_release_ex(const_FL_NOCASE_name, true); zval const_FL_NODIR_value; ZVAL_LONG(&const_FL_NODIR_value, ZIP_FL_NODIR); - zend_string *const_FL_NODIR_name = zend_string_init_interned("FL_NODIR", sizeof("FL_NODIR") - 1, 1); + zend_string *const_FL_NODIR_name = zend_string_init_interned("FL_NODIR", sizeof("FL_NODIR") - 1, true); zend_declare_typed_class_constant(class_entry, const_FL_NODIR_name, &const_FL_NODIR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FL_NODIR_name); + zend_string_release_ex(const_FL_NODIR_name, true); zval const_FL_COMPRESSED_value; ZVAL_LONG(&const_FL_COMPRESSED_value, ZIP_FL_COMPRESSED); - zend_string *const_FL_COMPRESSED_name = zend_string_init_interned("FL_COMPRESSED", sizeof("FL_COMPRESSED") - 1, 1); + zend_string *const_FL_COMPRESSED_name = zend_string_init_interned("FL_COMPRESSED", sizeof("FL_COMPRESSED") - 1, true); zend_declare_typed_class_constant(class_entry, const_FL_COMPRESSED_name, &const_FL_COMPRESSED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FL_COMPRESSED_name); + zend_string_release_ex(const_FL_COMPRESSED_name, true); zval const_FL_UNCHANGED_value; ZVAL_LONG(&const_FL_UNCHANGED_value, ZIP_FL_UNCHANGED); - zend_string *const_FL_UNCHANGED_name = zend_string_init_interned("FL_UNCHANGED", sizeof("FL_UNCHANGED") - 1, 1); + zend_string *const_FL_UNCHANGED_name = zend_string_init_interned("FL_UNCHANGED", sizeof("FL_UNCHANGED") - 1, true); zend_declare_typed_class_constant(class_entry, const_FL_UNCHANGED_name, &const_FL_UNCHANGED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FL_UNCHANGED_name); + zend_string_release_ex(const_FL_UNCHANGED_name, true); #if defined(ZIP_FL_RECOMPRESS) zval const_FL_RECOMPRESS_value; ZVAL_LONG(&const_FL_RECOMPRESS_value, ZIP_FL_RECOMPRESS); - zend_string *const_FL_RECOMPRESS_name = zend_string_init_interned("FL_RECOMPRESS", sizeof("FL_RECOMPRESS") - 1, 1); + zend_string *const_FL_RECOMPRESS_name = zend_string_init_interned("FL_RECOMPRESS", sizeof("FL_RECOMPRESS") - 1, true); zend_class_constant *const_FL_RECOMPRESS = zend_declare_typed_class_constant(class_entry, const_FL_RECOMPRESS_name, &const_FL_RECOMPRESS_value, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FL_RECOMPRESS_name); + zend_string_release_ex(const_FL_RECOMPRESS_name, true); #endif zval const_FL_ENCRYPTED_value; ZVAL_LONG(&const_FL_ENCRYPTED_value, ZIP_FL_ENCRYPTED); - zend_string *const_FL_ENCRYPTED_name = zend_string_init_interned("FL_ENCRYPTED", sizeof("FL_ENCRYPTED") - 1, 1); + zend_string *const_FL_ENCRYPTED_name = zend_string_init_interned("FL_ENCRYPTED", sizeof("FL_ENCRYPTED") - 1, true); zend_declare_typed_class_constant(class_entry, const_FL_ENCRYPTED_name, &const_FL_ENCRYPTED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FL_ENCRYPTED_name); + zend_string_release_ex(const_FL_ENCRYPTED_name, true); zval const_FL_OVERWRITE_value; ZVAL_LONG(&const_FL_OVERWRITE_value, ZIP_FL_OVERWRITE); - zend_string *const_FL_OVERWRITE_name = zend_string_init_interned("FL_OVERWRITE", sizeof("FL_OVERWRITE") - 1, 1); + zend_string *const_FL_OVERWRITE_name = zend_string_init_interned("FL_OVERWRITE", sizeof("FL_OVERWRITE") - 1, true); zend_declare_typed_class_constant(class_entry, const_FL_OVERWRITE_name, &const_FL_OVERWRITE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FL_OVERWRITE_name); + zend_string_release_ex(const_FL_OVERWRITE_name, true); zval const_FL_LOCAL_value; ZVAL_LONG(&const_FL_LOCAL_value, ZIP_FL_LOCAL); - zend_string *const_FL_LOCAL_name = zend_string_init_interned("FL_LOCAL", sizeof("FL_LOCAL") - 1, 1); + zend_string *const_FL_LOCAL_name = zend_string_init_interned("FL_LOCAL", sizeof("FL_LOCAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_FL_LOCAL_name, &const_FL_LOCAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FL_LOCAL_name); + zend_string_release_ex(const_FL_LOCAL_name, true); zval const_FL_CENTRAL_value; ZVAL_LONG(&const_FL_CENTRAL_value, ZIP_FL_CENTRAL); - zend_string *const_FL_CENTRAL_name = zend_string_init_interned("FL_CENTRAL", sizeof("FL_CENTRAL") - 1, 1); + zend_string *const_FL_CENTRAL_name = zend_string_init_interned("FL_CENTRAL", sizeof("FL_CENTRAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_FL_CENTRAL_name, &const_FL_CENTRAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FL_CENTRAL_name); + zend_string_release_ex(const_FL_CENTRAL_name, true); zval const_FL_ENC_GUESS_value; ZVAL_LONG(&const_FL_ENC_GUESS_value, ZIP_FL_ENC_GUESS); - zend_string *const_FL_ENC_GUESS_name = zend_string_init_interned("FL_ENC_GUESS", sizeof("FL_ENC_GUESS") - 1, 1); + zend_string *const_FL_ENC_GUESS_name = zend_string_init_interned("FL_ENC_GUESS", sizeof("FL_ENC_GUESS") - 1, true); zend_declare_typed_class_constant(class_entry, const_FL_ENC_GUESS_name, &const_FL_ENC_GUESS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FL_ENC_GUESS_name); + zend_string_release_ex(const_FL_ENC_GUESS_name, true); zval const_FL_ENC_RAW_value; ZVAL_LONG(&const_FL_ENC_RAW_value, ZIP_FL_ENC_RAW); - zend_string *const_FL_ENC_RAW_name = zend_string_init_interned("FL_ENC_RAW", sizeof("FL_ENC_RAW") - 1, 1); + zend_string *const_FL_ENC_RAW_name = zend_string_init_interned("FL_ENC_RAW", sizeof("FL_ENC_RAW") - 1, true); zend_declare_typed_class_constant(class_entry, const_FL_ENC_RAW_name, &const_FL_ENC_RAW_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FL_ENC_RAW_name); + zend_string_release_ex(const_FL_ENC_RAW_name, true); zval const_FL_ENC_STRICT_value; ZVAL_LONG(&const_FL_ENC_STRICT_value, ZIP_FL_ENC_STRICT); - zend_string *const_FL_ENC_STRICT_name = zend_string_init_interned("FL_ENC_STRICT", sizeof("FL_ENC_STRICT") - 1, 1); + zend_string *const_FL_ENC_STRICT_name = zend_string_init_interned("FL_ENC_STRICT", sizeof("FL_ENC_STRICT") - 1, true); zend_declare_typed_class_constant(class_entry, const_FL_ENC_STRICT_name, &const_FL_ENC_STRICT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FL_ENC_STRICT_name); + zend_string_release_ex(const_FL_ENC_STRICT_name, true); zval const_FL_ENC_UTF_8_value; ZVAL_LONG(&const_FL_ENC_UTF_8_value, ZIP_FL_ENC_UTF_8); - zend_string *const_FL_ENC_UTF_8_name = zend_string_init_interned("FL_ENC_UTF_8", sizeof("FL_ENC_UTF_8") - 1, 1); + zend_string *const_FL_ENC_UTF_8_name = zend_string_init_interned("FL_ENC_UTF_8", sizeof("FL_ENC_UTF_8") - 1, true); zend_declare_typed_class_constant(class_entry, const_FL_ENC_UTF_8_name, &const_FL_ENC_UTF_8_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FL_ENC_UTF_8_name); + zend_string_release_ex(const_FL_ENC_UTF_8_name, true); zval const_FL_ENC_CP437_value; ZVAL_LONG(&const_FL_ENC_CP437_value, ZIP_FL_ENC_CP437); - zend_string *const_FL_ENC_CP437_name = zend_string_init_interned("FL_ENC_CP437", sizeof("FL_ENC_CP437") - 1, 1); + zend_string *const_FL_ENC_CP437_name = zend_string_init_interned("FL_ENC_CP437", sizeof("FL_ENC_CP437") - 1, true); zend_declare_typed_class_constant(class_entry, const_FL_ENC_CP437_name, &const_FL_ENC_CP437_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FL_ENC_CP437_name); + zend_string_release_ex(const_FL_ENC_CP437_name, true); zval const_FL_OPEN_FILE_NOW_value; ZVAL_LONG(&const_FL_OPEN_FILE_NOW_value, ZIP_FL_OPEN_FILE_NOW); - zend_string *const_FL_OPEN_FILE_NOW_name = zend_string_init_interned("FL_OPEN_FILE_NOW", sizeof("FL_OPEN_FILE_NOW") - 1, 1); + zend_string *const_FL_OPEN_FILE_NOW_name = zend_string_init_interned("FL_OPEN_FILE_NOW", sizeof("FL_OPEN_FILE_NOW") - 1, true); zend_declare_typed_class_constant(class_entry, const_FL_OPEN_FILE_NOW_name, &const_FL_OPEN_FILE_NOW_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_FL_OPEN_FILE_NOW_name); + zend_string_release_ex(const_FL_OPEN_FILE_NOW_name, true); zval const_CM_DEFAULT_value; ZVAL_LONG(&const_CM_DEFAULT_value, ZIP_CM_DEFAULT); - zend_string *const_CM_DEFAULT_name = zend_string_init_interned("CM_DEFAULT", sizeof("CM_DEFAULT") - 1, 1); + zend_string *const_CM_DEFAULT_name = zend_string_init_interned("CM_DEFAULT", sizeof("CM_DEFAULT") - 1, true); zend_declare_typed_class_constant(class_entry, const_CM_DEFAULT_name, &const_CM_DEFAULT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CM_DEFAULT_name); + zend_string_release_ex(const_CM_DEFAULT_name, true); zval const_CM_STORE_value; ZVAL_LONG(&const_CM_STORE_value, ZIP_CM_STORE); - zend_string *const_CM_STORE_name = zend_string_init_interned("CM_STORE", sizeof("CM_STORE") - 1, 1); + zend_string *const_CM_STORE_name = zend_string_init_interned("CM_STORE", sizeof("CM_STORE") - 1, true); zend_declare_typed_class_constant(class_entry, const_CM_STORE_name, &const_CM_STORE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CM_STORE_name); + zend_string_release_ex(const_CM_STORE_name, true); zval const_CM_SHRINK_value; ZVAL_LONG(&const_CM_SHRINK_value, ZIP_CM_SHRINK); - zend_string *const_CM_SHRINK_name = zend_string_init_interned("CM_SHRINK", sizeof("CM_SHRINK") - 1, 1); + zend_string *const_CM_SHRINK_name = zend_string_init_interned("CM_SHRINK", sizeof("CM_SHRINK") - 1, true); zend_declare_typed_class_constant(class_entry, const_CM_SHRINK_name, &const_CM_SHRINK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CM_SHRINK_name); + zend_string_release_ex(const_CM_SHRINK_name, true); zval const_CM_REDUCE_1_value; ZVAL_LONG(&const_CM_REDUCE_1_value, ZIP_CM_REDUCE_1); - zend_string *const_CM_REDUCE_1_name = zend_string_init_interned("CM_REDUCE_1", sizeof("CM_REDUCE_1") - 1, 1); + zend_string *const_CM_REDUCE_1_name = zend_string_init_interned("CM_REDUCE_1", sizeof("CM_REDUCE_1") - 1, true); zend_declare_typed_class_constant(class_entry, const_CM_REDUCE_1_name, &const_CM_REDUCE_1_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CM_REDUCE_1_name); + zend_string_release_ex(const_CM_REDUCE_1_name, true); zval const_CM_REDUCE_2_value; ZVAL_LONG(&const_CM_REDUCE_2_value, ZIP_CM_REDUCE_2); - zend_string *const_CM_REDUCE_2_name = zend_string_init_interned("CM_REDUCE_2", sizeof("CM_REDUCE_2") - 1, 1); + zend_string *const_CM_REDUCE_2_name = zend_string_init_interned("CM_REDUCE_2", sizeof("CM_REDUCE_2") - 1, true); zend_declare_typed_class_constant(class_entry, const_CM_REDUCE_2_name, &const_CM_REDUCE_2_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CM_REDUCE_2_name); + zend_string_release_ex(const_CM_REDUCE_2_name, true); zval const_CM_REDUCE_3_value; ZVAL_LONG(&const_CM_REDUCE_3_value, ZIP_CM_REDUCE_3); - zend_string *const_CM_REDUCE_3_name = zend_string_init_interned("CM_REDUCE_3", sizeof("CM_REDUCE_3") - 1, 1); + zend_string *const_CM_REDUCE_3_name = zend_string_init_interned("CM_REDUCE_3", sizeof("CM_REDUCE_3") - 1, true); zend_declare_typed_class_constant(class_entry, const_CM_REDUCE_3_name, &const_CM_REDUCE_3_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CM_REDUCE_3_name); + zend_string_release_ex(const_CM_REDUCE_3_name, true); zval const_CM_REDUCE_4_value; ZVAL_LONG(&const_CM_REDUCE_4_value, ZIP_CM_REDUCE_4); - zend_string *const_CM_REDUCE_4_name = zend_string_init_interned("CM_REDUCE_4", sizeof("CM_REDUCE_4") - 1, 1); + zend_string *const_CM_REDUCE_4_name = zend_string_init_interned("CM_REDUCE_4", sizeof("CM_REDUCE_4") - 1, true); zend_declare_typed_class_constant(class_entry, const_CM_REDUCE_4_name, &const_CM_REDUCE_4_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CM_REDUCE_4_name); + zend_string_release_ex(const_CM_REDUCE_4_name, true); zval const_CM_IMPLODE_value; ZVAL_LONG(&const_CM_IMPLODE_value, ZIP_CM_IMPLODE); - zend_string *const_CM_IMPLODE_name = zend_string_init_interned("CM_IMPLODE", sizeof("CM_IMPLODE") - 1, 1); + zend_string *const_CM_IMPLODE_name = zend_string_init_interned("CM_IMPLODE", sizeof("CM_IMPLODE") - 1, true); zend_declare_typed_class_constant(class_entry, const_CM_IMPLODE_name, &const_CM_IMPLODE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CM_IMPLODE_name); + zend_string_release_ex(const_CM_IMPLODE_name, true); zval const_CM_DEFLATE_value; ZVAL_LONG(&const_CM_DEFLATE_value, ZIP_CM_DEFLATE); - zend_string *const_CM_DEFLATE_name = zend_string_init_interned("CM_DEFLATE", sizeof("CM_DEFLATE") - 1, 1); + zend_string *const_CM_DEFLATE_name = zend_string_init_interned("CM_DEFLATE", sizeof("CM_DEFLATE") - 1, true); zend_declare_typed_class_constant(class_entry, const_CM_DEFLATE_name, &const_CM_DEFLATE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CM_DEFLATE_name); + zend_string_release_ex(const_CM_DEFLATE_name, true); zval const_CM_DEFLATE64_value; ZVAL_LONG(&const_CM_DEFLATE64_value, ZIP_CM_DEFLATE64); - zend_string *const_CM_DEFLATE64_name = zend_string_init_interned("CM_DEFLATE64", sizeof("CM_DEFLATE64") - 1, 1); + zend_string *const_CM_DEFLATE64_name = zend_string_init_interned("CM_DEFLATE64", sizeof("CM_DEFLATE64") - 1, true); zend_declare_typed_class_constant(class_entry, const_CM_DEFLATE64_name, &const_CM_DEFLATE64_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CM_DEFLATE64_name); + zend_string_release_ex(const_CM_DEFLATE64_name, true); zval const_CM_PKWARE_IMPLODE_value; ZVAL_LONG(&const_CM_PKWARE_IMPLODE_value, ZIP_CM_PKWARE_IMPLODE); - zend_string *const_CM_PKWARE_IMPLODE_name = zend_string_init_interned("CM_PKWARE_IMPLODE", sizeof("CM_PKWARE_IMPLODE") - 1, 1); + zend_string *const_CM_PKWARE_IMPLODE_name = zend_string_init_interned("CM_PKWARE_IMPLODE", sizeof("CM_PKWARE_IMPLODE") - 1, true); zend_declare_typed_class_constant(class_entry, const_CM_PKWARE_IMPLODE_name, &const_CM_PKWARE_IMPLODE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CM_PKWARE_IMPLODE_name); + zend_string_release_ex(const_CM_PKWARE_IMPLODE_name, true); zval const_CM_BZIP2_value; ZVAL_LONG(&const_CM_BZIP2_value, ZIP_CM_BZIP2); - zend_string *const_CM_BZIP2_name = zend_string_init_interned("CM_BZIP2", sizeof("CM_BZIP2") - 1, 1); + zend_string *const_CM_BZIP2_name = zend_string_init_interned("CM_BZIP2", sizeof("CM_BZIP2") - 1, true); zend_declare_typed_class_constant(class_entry, const_CM_BZIP2_name, &const_CM_BZIP2_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CM_BZIP2_name); + zend_string_release_ex(const_CM_BZIP2_name, true); zval const_CM_LZMA_value; ZVAL_LONG(&const_CM_LZMA_value, ZIP_CM_LZMA); - zend_string *const_CM_LZMA_name = zend_string_init_interned("CM_LZMA", sizeof("CM_LZMA") - 1, 1); + zend_string *const_CM_LZMA_name = zend_string_init_interned("CM_LZMA", sizeof("CM_LZMA") - 1, true); zend_declare_typed_class_constant(class_entry, const_CM_LZMA_name, &const_CM_LZMA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CM_LZMA_name); + zend_string_release_ex(const_CM_LZMA_name, true); #if defined(ZIP_CM_LZMA2) zval const_CM_LZMA2_value; ZVAL_LONG(&const_CM_LZMA2_value, ZIP_CM_LZMA2); - zend_string *const_CM_LZMA2_name = zend_string_init_interned("CM_LZMA2", sizeof("CM_LZMA2") - 1, 1); + zend_string *const_CM_LZMA2_name = zend_string_init_interned("CM_LZMA2", sizeof("CM_LZMA2") - 1, true); zend_declare_typed_class_constant(class_entry, const_CM_LZMA2_name, &const_CM_LZMA2_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CM_LZMA2_name); + zend_string_release_ex(const_CM_LZMA2_name, true); #endif #if defined(ZIP_CM_ZSTD) zval const_CM_ZSTD_value; ZVAL_LONG(&const_CM_ZSTD_value, ZIP_CM_ZSTD); - zend_string *const_CM_ZSTD_name = zend_string_init_interned("CM_ZSTD", sizeof("CM_ZSTD") - 1, 1); + zend_string *const_CM_ZSTD_name = zend_string_init_interned("CM_ZSTD", sizeof("CM_ZSTD") - 1, true); zend_declare_typed_class_constant(class_entry, const_CM_ZSTD_name, &const_CM_ZSTD_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CM_ZSTD_name); + zend_string_release_ex(const_CM_ZSTD_name, true); #endif #if defined(ZIP_CM_XZ) zval const_CM_XZ_value; ZVAL_LONG(&const_CM_XZ_value, ZIP_CM_XZ); - zend_string *const_CM_XZ_name = zend_string_init_interned("CM_XZ", sizeof("CM_XZ") - 1, 1); + zend_string *const_CM_XZ_name = zend_string_init_interned("CM_XZ", sizeof("CM_XZ") - 1, true); zend_declare_typed_class_constant(class_entry, const_CM_XZ_name, &const_CM_XZ_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CM_XZ_name); + zend_string_release_ex(const_CM_XZ_name, true); #endif zval const_CM_TERSE_value; ZVAL_LONG(&const_CM_TERSE_value, ZIP_CM_TERSE); - zend_string *const_CM_TERSE_name = zend_string_init_interned("CM_TERSE", sizeof("CM_TERSE") - 1, 1); + zend_string *const_CM_TERSE_name = zend_string_init_interned("CM_TERSE", sizeof("CM_TERSE") - 1, true); zend_declare_typed_class_constant(class_entry, const_CM_TERSE_name, &const_CM_TERSE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CM_TERSE_name); + zend_string_release_ex(const_CM_TERSE_name, true); zval const_CM_LZ77_value; ZVAL_LONG(&const_CM_LZ77_value, ZIP_CM_LZ77); - zend_string *const_CM_LZ77_name = zend_string_init_interned("CM_LZ77", sizeof("CM_LZ77") - 1, 1); + zend_string *const_CM_LZ77_name = zend_string_init_interned("CM_LZ77", sizeof("CM_LZ77") - 1, true); zend_declare_typed_class_constant(class_entry, const_CM_LZ77_name, &const_CM_LZ77_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CM_LZ77_name); + zend_string_release_ex(const_CM_LZ77_name, true); zval const_CM_WAVPACK_value; ZVAL_LONG(&const_CM_WAVPACK_value, ZIP_CM_WAVPACK); - zend_string *const_CM_WAVPACK_name = zend_string_init_interned("CM_WAVPACK", sizeof("CM_WAVPACK") - 1, 1); + zend_string *const_CM_WAVPACK_name = zend_string_init_interned("CM_WAVPACK", sizeof("CM_WAVPACK") - 1, true); zend_declare_typed_class_constant(class_entry, const_CM_WAVPACK_name, &const_CM_WAVPACK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CM_WAVPACK_name); + zend_string_release_ex(const_CM_WAVPACK_name, true); zval const_CM_PPMD_value; ZVAL_LONG(&const_CM_PPMD_value, ZIP_CM_PPMD); - zend_string *const_CM_PPMD_name = zend_string_init_interned("CM_PPMD", sizeof("CM_PPMD") - 1, 1); + zend_string *const_CM_PPMD_name = zend_string_init_interned("CM_PPMD", sizeof("CM_PPMD") - 1, true); zend_declare_typed_class_constant(class_entry, const_CM_PPMD_name, &const_CM_PPMD_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_CM_PPMD_name); + zend_string_release_ex(const_CM_PPMD_name, true); zval const_ER_OK_value; ZVAL_LONG(&const_ER_OK_value, ZIP_ER_OK); - zend_string *const_ER_OK_name = zend_string_init_interned("ER_OK", sizeof("ER_OK") - 1, 1); + zend_string *const_ER_OK_name = zend_string_init_interned("ER_OK", sizeof("ER_OK") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_OK_name, &const_ER_OK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_OK_name); + zend_string_release_ex(const_ER_OK_name, true); zval const_ER_MULTIDISK_value; ZVAL_LONG(&const_ER_MULTIDISK_value, ZIP_ER_MULTIDISK); - zend_string *const_ER_MULTIDISK_name = zend_string_init_interned("ER_MULTIDISK", sizeof("ER_MULTIDISK") - 1, 1); + zend_string *const_ER_MULTIDISK_name = zend_string_init_interned("ER_MULTIDISK", sizeof("ER_MULTIDISK") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_MULTIDISK_name, &const_ER_MULTIDISK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_MULTIDISK_name); + zend_string_release_ex(const_ER_MULTIDISK_name, true); zval const_ER_RENAME_value; ZVAL_LONG(&const_ER_RENAME_value, ZIP_ER_RENAME); - zend_string *const_ER_RENAME_name = zend_string_init_interned("ER_RENAME", sizeof("ER_RENAME") - 1, 1); + zend_string *const_ER_RENAME_name = zend_string_init_interned("ER_RENAME", sizeof("ER_RENAME") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_RENAME_name, &const_ER_RENAME_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_RENAME_name); + zend_string_release_ex(const_ER_RENAME_name, true); zval const_ER_CLOSE_value; ZVAL_LONG(&const_ER_CLOSE_value, ZIP_ER_CLOSE); - zend_string *const_ER_CLOSE_name = zend_string_init_interned("ER_CLOSE", sizeof("ER_CLOSE") - 1, 1); + zend_string *const_ER_CLOSE_name = zend_string_init_interned("ER_CLOSE", sizeof("ER_CLOSE") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_CLOSE_name, &const_ER_CLOSE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_CLOSE_name); + zend_string_release_ex(const_ER_CLOSE_name, true); zval const_ER_SEEK_value; ZVAL_LONG(&const_ER_SEEK_value, ZIP_ER_SEEK); - zend_string *const_ER_SEEK_name = zend_string_init_interned("ER_SEEK", sizeof("ER_SEEK") - 1, 1); + zend_string *const_ER_SEEK_name = zend_string_init_interned("ER_SEEK", sizeof("ER_SEEK") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_SEEK_name, &const_ER_SEEK_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_SEEK_name); + zend_string_release_ex(const_ER_SEEK_name, true); zval const_ER_READ_value; ZVAL_LONG(&const_ER_READ_value, ZIP_ER_READ); - zend_string *const_ER_READ_name = zend_string_init_interned("ER_READ", sizeof("ER_READ") - 1, 1); + zend_string *const_ER_READ_name = zend_string_init_interned("ER_READ", sizeof("ER_READ") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_READ_name, &const_ER_READ_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_READ_name); + zend_string_release_ex(const_ER_READ_name, true); zval const_ER_WRITE_value; ZVAL_LONG(&const_ER_WRITE_value, ZIP_ER_WRITE); - zend_string *const_ER_WRITE_name = zend_string_init_interned("ER_WRITE", sizeof("ER_WRITE") - 1, 1); + zend_string *const_ER_WRITE_name = zend_string_init_interned("ER_WRITE", sizeof("ER_WRITE") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_WRITE_name, &const_ER_WRITE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_WRITE_name); + zend_string_release_ex(const_ER_WRITE_name, true); zval const_ER_CRC_value; ZVAL_LONG(&const_ER_CRC_value, ZIP_ER_CRC); - zend_string *const_ER_CRC_name = zend_string_init_interned("ER_CRC", sizeof("ER_CRC") - 1, 1); + zend_string *const_ER_CRC_name = zend_string_init_interned("ER_CRC", sizeof("ER_CRC") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_CRC_name, &const_ER_CRC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_CRC_name); + zend_string_release_ex(const_ER_CRC_name, true); zval const_ER_ZIPCLOSED_value; ZVAL_LONG(&const_ER_ZIPCLOSED_value, ZIP_ER_ZIPCLOSED); - zend_string *const_ER_ZIPCLOSED_name = zend_string_init_interned("ER_ZIPCLOSED", sizeof("ER_ZIPCLOSED") - 1, 1); + zend_string *const_ER_ZIPCLOSED_name = zend_string_init_interned("ER_ZIPCLOSED", sizeof("ER_ZIPCLOSED") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_ZIPCLOSED_name, &const_ER_ZIPCLOSED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_ZIPCLOSED_name); + zend_string_release_ex(const_ER_ZIPCLOSED_name, true); zval const_ER_NOENT_value; ZVAL_LONG(&const_ER_NOENT_value, ZIP_ER_NOENT); - zend_string *const_ER_NOENT_name = zend_string_init_interned("ER_NOENT", sizeof("ER_NOENT") - 1, 1); + zend_string *const_ER_NOENT_name = zend_string_init_interned("ER_NOENT", sizeof("ER_NOENT") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_NOENT_name, &const_ER_NOENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_NOENT_name); + zend_string_release_ex(const_ER_NOENT_name, true); zval const_ER_EXISTS_value; ZVAL_LONG(&const_ER_EXISTS_value, ZIP_ER_EXISTS); - zend_string *const_ER_EXISTS_name = zend_string_init_interned("ER_EXISTS", sizeof("ER_EXISTS") - 1, 1); + zend_string *const_ER_EXISTS_name = zend_string_init_interned("ER_EXISTS", sizeof("ER_EXISTS") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_EXISTS_name, &const_ER_EXISTS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_EXISTS_name); + zend_string_release_ex(const_ER_EXISTS_name, true); zval const_ER_OPEN_value; ZVAL_LONG(&const_ER_OPEN_value, ZIP_ER_OPEN); - zend_string *const_ER_OPEN_name = zend_string_init_interned("ER_OPEN", sizeof("ER_OPEN") - 1, 1); + zend_string *const_ER_OPEN_name = zend_string_init_interned("ER_OPEN", sizeof("ER_OPEN") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_OPEN_name, &const_ER_OPEN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_OPEN_name); + zend_string_release_ex(const_ER_OPEN_name, true); zval const_ER_TMPOPEN_value; ZVAL_LONG(&const_ER_TMPOPEN_value, ZIP_ER_TMPOPEN); - zend_string *const_ER_TMPOPEN_name = zend_string_init_interned("ER_TMPOPEN", sizeof("ER_TMPOPEN") - 1, 1); + zend_string *const_ER_TMPOPEN_name = zend_string_init_interned("ER_TMPOPEN", sizeof("ER_TMPOPEN") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_TMPOPEN_name, &const_ER_TMPOPEN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_TMPOPEN_name); + zend_string_release_ex(const_ER_TMPOPEN_name, true); zval const_ER_ZLIB_value; ZVAL_LONG(&const_ER_ZLIB_value, ZIP_ER_ZLIB); - zend_string *const_ER_ZLIB_name = zend_string_init_interned("ER_ZLIB", sizeof("ER_ZLIB") - 1, 1); + zend_string *const_ER_ZLIB_name = zend_string_init_interned("ER_ZLIB", sizeof("ER_ZLIB") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_ZLIB_name, &const_ER_ZLIB_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_ZLIB_name); + zend_string_release_ex(const_ER_ZLIB_name, true); zval const_ER_MEMORY_value; ZVAL_LONG(&const_ER_MEMORY_value, ZIP_ER_MEMORY); - zend_string *const_ER_MEMORY_name = zend_string_init_interned("ER_MEMORY", sizeof("ER_MEMORY") - 1, 1); + zend_string *const_ER_MEMORY_name = zend_string_init_interned("ER_MEMORY", sizeof("ER_MEMORY") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_MEMORY_name, &const_ER_MEMORY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_MEMORY_name); + zend_string_release_ex(const_ER_MEMORY_name, true); zval const_ER_CHANGED_value; ZVAL_LONG(&const_ER_CHANGED_value, ZIP_ER_CHANGED); - zend_string *const_ER_CHANGED_name = zend_string_init_interned("ER_CHANGED", sizeof("ER_CHANGED") - 1, 1); + zend_string *const_ER_CHANGED_name = zend_string_init_interned("ER_CHANGED", sizeof("ER_CHANGED") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_CHANGED_name, &const_ER_CHANGED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_CHANGED_name); + zend_string_release_ex(const_ER_CHANGED_name, true); zval const_ER_COMPNOTSUPP_value; ZVAL_LONG(&const_ER_COMPNOTSUPP_value, ZIP_ER_COMPNOTSUPP); - zend_string *const_ER_COMPNOTSUPP_name = zend_string_init_interned("ER_COMPNOTSUPP", sizeof("ER_COMPNOTSUPP") - 1, 1); + zend_string *const_ER_COMPNOTSUPP_name = zend_string_init_interned("ER_COMPNOTSUPP", sizeof("ER_COMPNOTSUPP") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_COMPNOTSUPP_name, &const_ER_COMPNOTSUPP_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_COMPNOTSUPP_name); + zend_string_release_ex(const_ER_COMPNOTSUPP_name, true); zval const_ER_EOF_value; ZVAL_LONG(&const_ER_EOF_value, ZIP_ER_EOF); - zend_string *const_ER_EOF_name = zend_string_init_interned("ER_EOF", sizeof("ER_EOF") - 1, 1); + zend_string *const_ER_EOF_name = zend_string_init_interned("ER_EOF", sizeof("ER_EOF") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_EOF_name, &const_ER_EOF_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_EOF_name); + zend_string_release_ex(const_ER_EOF_name, true); zval const_ER_INVAL_value; ZVAL_LONG(&const_ER_INVAL_value, ZIP_ER_INVAL); - zend_string *const_ER_INVAL_name = zend_string_init_interned("ER_INVAL", sizeof("ER_INVAL") - 1, 1); + zend_string *const_ER_INVAL_name = zend_string_init_interned("ER_INVAL", sizeof("ER_INVAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_INVAL_name, &const_ER_INVAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_INVAL_name); + zend_string_release_ex(const_ER_INVAL_name, true); zval const_ER_NOZIP_value; ZVAL_LONG(&const_ER_NOZIP_value, ZIP_ER_NOZIP); - zend_string *const_ER_NOZIP_name = zend_string_init_interned("ER_NOZIP", sizeof("ER_NOZIP") - 1, 1); + zend_string *const_ER_NOZIP_name = zend_string_init_interned("ER_NOZIP", sizeof("ER_NOZIP") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_NOZIP_name, &const_ER_NOZIP_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_NOZIP_name); + zend_string_release_ex(const_ER_NOZIP_name, true); zval const_ER_INTERNAL_value; ZVAL_LONG(&const_ER_INTERNAL_value, ZIP_ER_INTERNAL); - zend_string *const_ER_INTERNAL_name = zend_string_init_interned("ER_INTERNAL", sizeof("ER_INTERNAL") - 1, 1); + zend_string *const_ER_INTERNAL_name = zend_string_init_interned("ER_INTERNAL", sizeof("ER_INTERNAL") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_INTERNAL_name, &const_ER_INTERNAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_INTERNAL_name); + zend_string_release_ex(const_ER_INTERNAL_name, true); zval const_ER_INCONS_value; ZVAL_LONG(&const_ER_INCONS_value, ZIP_ER_INCONS); - zend_string *const_ER_INCONS_name = zend_string_init_interned("ER_INCONS", sizeof("ER_INCONS") - 1, 1); + zend_string *const_ER_INCONS_name = zend_string_init_interned("ER_INCONS", sizeof("ER_INCONS") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_INCONS_name, &const_ER_INCONS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_INCONS_name); + zend_string_release_ex(const_ER_INCONS_name, true); zval const_ER_REMOVE_value; ZVAL_LONG(&const_ER_REMOVE_value, ZIP_ER_REMOVE); - zend_string *const_ER_REMOVE_name = zend_string_init_interned("ER_REMOVE", sizeof("ER_REMOVE") - 1, 1); + zend_string *const_ER_REMOVE_name = zend_string_init_interned("ER_REMOVE", sizeof("ER_REMOVE") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_REMOVE_name, &const_ER_REMOVE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_REMOVE_name); + zend_string_release_ex(const_ER_REMOVE_name, true); zval const_ER_DELETED_value; ZVAL_LONG(&const_ER_DELETED_value, ZIP_ER_DELETED); - zend_string *const_ER_DELETED_name = zend_string_init_interned("ER_DELETED", sizeof("ER_DELETED") - 1, 1); + zend_string *const_ER_DELETED_name = zend_string_init_interned("ER_DELETED", sizeof("ER_DELETED") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_DELETED_name, &const_ER_DELETED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_DELETED_name); + zend_string_release_ex(const_ER_DELETED_name, true); zval const_ER_ENCRNOTSUPP_value; ZVAL_LONG(&const_ER_ENCRNOTSUPP_value, ZIP_ER_ENCRNOTSUPP); - zend_string *const_ER_ENCRNOTSUPP_name = zend_string_init_interned("ER_ENCRNOTSUPP", sizeof("ER_ENCRNOTSUPP") - 1, 1); + zend_string *const_ER_ENCRNOTSUPP_name = zend_string_init_interned("ER_ENCRNOTSUPP", sizeof("ER_ENCRNOTSUPP") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_ENCRNOTSUPP_name, &const_ER_ENCRNOTSUPP_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_ENCRNOTSUPP_name); + zend_string_release_ex(const_ER_ENCRNOTSUPP_name, true); zval const_ER_RDONLY_value; ZVAL_LONG(&const_ER_RDONLY_value, ZIP_ER_RDONLY); - zend_string *const_ER_RDONLY_name = zend_string_init_interned("ER_RDONLY", sizeof("ER_RDONLY") - 1, 1); + zend_string *const_ER_RDONLY_name = zend_string_init_interned("ER_RDONLY", sizeof("ER_RDONLY") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_RDONLY_name, &const_ER_RDONLY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_RDONLY_name); + zend_string_release_ex(const_ER_RDONLY_name, true); zval const_ER_NOPASSWD_value; ZVAL_LONG(&const_ER_NOPASSWD_value, ZIP_ER_NOPASSWD); - zend_string *const_ER_NOPASSWD_name = zend_string_init_interned("ER_NOPASSWD", sizeof("ER_NOPASSWD") - 1, 1); + zend_string *const_ER_NOPASSWD_name = zend_string_init_interned("ER_NOPASSWD", sizeof("ER_NOPASSWD") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_NOPASSWD_name, &const_ER_NOPASSWD_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_NOPASSWD_name); + zend_string_release_ex(const_ER_NOPASSWD_name, true); zval const_ER_WRONGPASSWD_value; ZVAL_LONG(&const_ER_WRONGPASSWD_value, ZIP_ER_WRONGPASSWD); - zend_string *const_ER_WRONGPASSWD_name = zend_string_init_interned("ER_WRONGPASSWD", sizeof("ER_WRONGPASSWD") - 1, 1); + zend_string *const_ER_WRONGPASSWD_name = zend_string_init_interned("ER_WRONGPASSWD", sizeof("ER_WRONGPASSWD") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_WRONGPASSWD_name, &const_ER_WRONGPASSWD_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_WRONGPASSWD_name); + zend_string_release_ex(const_ER_WRONGPASSWD_name, true); #if defined(ZIP_ER_OPNOTSUPP) zval const_ER_OPNOTSUPP_value; ZVAL_LONG(&const_ER_OPNOTSUPP_value, ZIP_ER_OPNOTSUPP); - zend_string *const_ER_OPNOTSUPP_name = zend_string_init_interned("ER_OPNOTSUPP", sizeof("ER_OPNOTSUPP") - 1, 1); + zend_string *const_ER_OPNOTSUPP_name = zend_string_init_interned("ER_OPNOTSUPP", sizeof("ER_OPNOTSUPP") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_OPNOTSUPP_name, &const_ER_OPNOTSUPP_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_OPNOTSUPP_name); + zend_string_release_ex(const_ER_OPNOTSUPP_name, true); #endif #if defined(ZIP_ER_INUSE) zval const_ER_INUSE_value; ZVAL_LONG(&const_ER_INUSE_value, ZIP_ER_INUSE); - zend_string *const_ER_INUSE_name = zend_string_init_interned("ER_INUSE", sizeof("ER_INUSE") - 1, 1); + zend_string *const_ER_INUSE_name = zend_string_init_interned("ER_INUSE", sizeof("ER_INUSE") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_INUSE_name, &const_ER_INUSE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_INUSE_name); + zend_string_release_ex(const_ER_INUSE_name, true); #endif #if defined(ZIP_ER_TELL) zval const_ER_TELL_value; ZVAL_LONG(&const_ER_TELL_value, ZIP_ER_TELL); - zend_string *const_ER_TELL_name = zend_string_init_interned("ER_TELL", sizeof("ER_TELL") - 1, 1); + zend_string *const_ER_TELL_name = zend_string_init_interned("ER_TELL", sizeof("ER_TELL") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_TELL_name, &const_ER_TELL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_TELL_name); + zend_string_release_ex(const_ER_TELL_name, true); #endif #if defined(ZIP_ER_COMPRESSED_DATA) zval const_ER_COMPRESSED_DATA_value; ZVAL_LONG(&const_ER_COMPRESSED_DATA_value, ZIP_ER_COMPRESSED_DATA); - zend_string *const_ER_COMPRESSED_DATA_name = zend_string_init_interned("ER_COMPRESSED_DATA", sizeof("ER_COMPRESSED_DATA") - 1, 1); + zend_string *const_ER_COMPRESSED_DATA_name = zend_string_init_interned("ER_COMPRESSED_DATA", sizeof("ER_COMPRESSED_DATA") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_COMPRESSED_DATA_name, &const_ER_COMPRESSED_DATA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_COMPRESSED_DATA_name); + zend_string_release_ex(const_ER_COMPRESSED_DATA_name, true); #endif #if defined(ZIP_ER_CANCELLED) zval const_ER_CANCELLED_value; ZVAL_LONG(&const_ER_CANCELLED_value, ZIP_ER_CANCELLED); - zend_string *const_ER_CANCELLED_name = zend_string_init_interned("ER_CANCELLED", sizeof("ER_CANCELLED") - 1, 1); + zend_string *const_ER_CANCELLED_name = zend_string_init_interned("ER_CANCELLED", sizeof("ER_CANCELLED") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_CANCELLED_name, &const_ER_CANCELLED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_CANCELLED_name); + zend_string_release_ex(const_ER_CANCELLED_name, true); #endif #if defined(ZIP_ER_DATA_LENGTH) zval const_ER_DATA_LENGTH_value; ZVAL_LONG(&const_ER_DATA_LENGTH_value, ZIP_ER_DATA_LENGTH); - zend_string *const_ER_DATA_LENGTH_name = zend_string_init_interned("ER_DATA_LENGTH", sizeof("ER_DATA_LENGTH") - 1, 1); + zend_string *const_ER_DATA_LENGTH_name = zend_string_init_interned("ER_DATA_LENGTH", sizeof("ER_DATA_LENGTH") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_DATA_LENGTH_name, &const_ER_DATA_LENGTH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_DATA_LENGTH_name); + zend_string_release_ex(const_ER_DATA_LENGTH_name, true); #endif #if defined(ZIP_ER_NOT_ALLOWED) zval const_ER_NOT_ALLOWED_value; ZVAL_LONG(&const_ER_NOT_ALLOWED_value, ZIP_ER_NOT_ALLOWED); - zend_string *const_ER_NOT_ALLOWED_name = zend_string_init_interned("ER_NOT_ALLOWED", sizeof("ER_NOT_ALLOWED") - 1, 1); + zend_string *const_ER_NOT_ALLOWED_name = zend_string_init_interned("ER_NOT_ALLOWED", sizeof("ER_NOT_ALLOWED") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_NOT_ALLOWED_name, &const_ER_NOT_ALLOWED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_NOT_ALLOWED_name); + zend_string_release_ex(const_ER_NOT_ALLOWED_name, true); #endif #if defined(ZIP_ER_TRUNCATED_ZIP) zval const_ER_TRUNCATED_ZIP_value; ZVAL_LONG(&const_ER_TRUNCATED_ZIP_value, ZIP_ER_TRUNCATED_ZIP); - zend_string *const_ER_TRUNCATED_ZIP_name = zend_string_init_interned("ER_TRUNCATED_ZIP", sizeof("ER_TRUNCATED_ZIP") - 1, 1); + zend_string *const_ER_TRUNCATED_ZIP_name = zend_string_init_interned("ER_TRUNCATED_ZIP", sizeof("ER_TRUNCATED_ZIP") - 1, true); zend_declare_typed_class_constant(class_entry, const_ER_TRUNCATED_ZIP_name, &const_ER_TRUNCATED_ZIP_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_ER_TRUNCATED_ZIP_name); + zend_string_release_ex(const_ER_TRUNCATED_ZIP_name, true); #endif #if defined(ZIP_AFL_RDONLY) zval const_AFL_RDONLY_value; ZVAL_LONG(&const_AFL_RDONLY_value, ZIP_AFL_RDONLY); - zend_string *const_AFL_RDONLY_name = zend_string_init_interned("AFL_RDONLY", sizeof("AFL_RDONLY") - 1, 1); + zend_string *const_AFL_RDONLY_name = zend_string_init_interned("AFL_RDONLY", sizeof("AFL_RDONLY") - 1, true); zend_declare_typed_class_constant(class_entry, const_AFL_RDONLY_name, &const_AFL_RDONLY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_AFL_RDONLY_name); + zend_string_release_ex(const_AFL_RDONLY_name, true); #endif #if defined(ZIP_AFL_IS_TORRENTZIP) zval const_AFL_IS_TORRENTZIP_value; ZVAL_LONG(&const_AFL_IS_TORRENTZIP_value, ZIP_AFL_IS_TORRENTZIP); - zend_string *const_AFL_IS_TORRENTZIP_name = zend_string_init_interned("AFL_IS_TORRENTZIP", sizeof("AFL_IS_TORRENTZIP") - 1, 1); + zend_string *const_AFL_IS_TORRENTZIP_name = zend_string_init_interned("AFL_IS_TORRENTZIP", sizeof("AFL_IS_TORRENTZIP") - 1, true); zend_declare_typed_class_constant(class_entry, const_AFL_IS_TORRENTZIP_name, &const_AFL_IS_TORRENTZIP_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_AFL_IS_TORRENTZIP_name); + zend_string_release_ex(const_AFL_IS_TORRENTZIP_name, true); #endif #if defined(ZIP_AFL_WANT_TORRENTZIP) zval const_AFL_WANT_TORRENTZIP_value; ZVAL_LONG(&const_AFL_WANT_TORRENTZIP_value, ZIP_AFL_WANT_TORRENTZIP); - zend_string *const_AFL_WANT_TORRENTZIP_name = zend_string_init_interned("AFL_WANT_TORRENTZIP", sizeof("AFL_WANT_TORRENTZIP") - 1, 1); + zend_string *const_AFL_WANT_TORRENTZIP_name = zend_string_init_interned("AFL_WANT_TORRENTZIP", sizeof("AFL_WANT_TORRENTZIP") - 1, true); zend_declare_typed_class_constant(class_entry, const_AFL_WANT_TORRENTZIP_name, &const_AFL_WANT_TORRENTZIP_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_AFL_WANT_TORRENTZIP_name); + zend_string_release_ex(const_AFL_WANT_TORRENTZIP_name, true); #endif #if defined(ZIP_AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE) zval const_AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE_value; ZVAL_LONG(&const_AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE_value, ZIP_AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE); - zend_string *const_AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE_name = zend_string_init_interned("AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE", sizeof("AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE") - 1, 1); + zend_string *const_AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE_name = zend_string_init_interned("AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE", sizeof("AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE") - 1, true); zend_declare_typed_class_constant(class_entry, const_AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE_name, &const_AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE_name); + zend_string_release_ex(const_AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE_name, true); #endif #if defined(ZIP_OPSYS_DEFAULT) zval const_OPSYS_DOS_value; ZVAL_LONG(&const_OPSYS_DOS_value, ZIP_OPSYS_DOS); - zend_string *const_OPSYS_DOS_name = zend_string_init_interned("OPSYS_DOS", sizeof("OPSYS_DOS") - 1, 1); + zend_string *const_OPSYS_DOS_name = zend_string_init_interned("OPSYS_DOS", sizeof("OPSYS_DOS") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPSYS_DOS_name, &const_OPSYS_DOS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPSYS_DOS_name); + zend_string_release_ex(const_OPSYS_DOS_name, true); zval const_OPSYS_AMIGA_value; ZVAL_LONG(&const_OPSYS_AMIGA_value, ZIP_OPSYS_AMIGA); - zend_string *const_OPSYS_AMIGA_name = zend_string_init_interned("OPSYS_AMIGA", sizeof("OPSYS_AMIGA") - 1, 1); + zend_string *const_OPSYS_AMIGA_name = zend_string_init_interned("OPSYS_AMIGA", sizeof("OPSYS_AMIGA") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPSYS_AMIGA_name, &const_OPSYS_AMIGA_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPSYS_AMIGA_name); + zend_string_release_ex(const_OPSYS_AMIGA_name, true); zval const_OPSYS_OPENVMS_value; ZVAL_LONG(&const_OPSYS_OPENVMS_value, ZIP_OPSYS_OPENVMS); - zend_string *const_OPSYS_OPENVMS_name = zend_string_init_interned("OPSYS_OPENVMS", sizeof("OPSYS_OPENVMS") - 1, 1); + zend_string *const_OPSYS_OPENVMS_name = zend_string_init_interned("OPSYS_OPENVMS", sizeof("OPSYS_OPENVMS") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPSYS_OPENVMS_name, &const_OPSYS_OPENVMS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPSYS_OPENVMS_name); + zend_string_release_ex(const_OPSYS_OPENVMS_name, true); zval const_OPSYS_UNIX_value; ZVAL_LONG(&const_OPSYS_UNIX_value, ZIP_OPSYS_UNIX); - zend_string *const_OPSYS_UNIX_name = zend_string_init_interned("OPSYS_UNIX", sizeof("OPSYS_UNIX") - 1, 1); + zend_string *const_OPSYS_UNIX_name = zend_string_init_interned("OPSYS_UNIX", sizeof("OPSYS_UNIX") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPSYS_UNIX_name, &const_OPSYS_UNIX_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPSYS_UNIX_name); + zend_string_release_ex(const_OPSYS_UNIX_name, true); zval const_OPSYS_VM_CMS_value; ZVAL_LONG(&const_OPSYS_VM_CMS_value, ZIP_OPSYS_VM_CMS); - zend_string *const_OPSYS_VM_CMS_name = zend_string_init_interned("OPSYS_VM_CMS", sizeof("OPSYS_VM_CMS") - 1, 1); + zend_string *const_OPSYS_VM_CMS_name = zend_string_init_interned("OPSYS_VM_CMS", sizeof("OPSYS_VM_CMS") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPSYS_VM_CMS_name, &const_OPSYS_VM_CMS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPSYS_VM_CMS_name); + zend_string_release_ex(const_OPSYS_VM_CMS_name, true); zval const_OPSYS_ATARI_ST_value; ZVAL_LONG(&const_OPSYS_ATARI_ST_value, ZIP_OPSYS_ATARI_ST); - zend_string *const_OPSYS_ATARI_ST_name = zend_string_init_interned("OPSYS_ATARI_ST", sizeof("OPSYS_ATARI_ST") - 1, 1); + zend_string *const_OPSYS_ATARI_ST_name = zend_string_init_interned("OPSYS_ATARI_ST", sizeof("OPSYS_ATARI_ST") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPSYS_ATARI_ST_name, &const_OPSYS_ATARI_ST_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPSYS_ATARI_ST_name); + zend_string_release_ex(const_OPSYS_ATARI_ST_name, true); zval const_OPSYS_OS_2_value; ZVAL_LONG(&const_OPSYS_OS_2_value, ZIP_OPSYS_OS_2); - zend_string *const_OPSYS_OS_2_name = zend_string_init_interned("OPSYS_OS_2", sizeof("OPSYS_OS_2") - 1, 1); + zend_string *const_OPSYS_OS_2_name = zend_string_init_interned("OPSYS_OS_2", sizeof("OPSYS_OS_2") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPSYS_OS_2_name, &const_OPSYS_OS_2_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPSYS_OS_2_name); + zend_string_release_ex(const_OPSYS_OS_2_name, true); zval const_OPSYS_MACINTOSH_value; ZVAL_LONG(&const_OPSYS_MACINTOSH_value, ZIP_OPSYS_MACINTOSH); - zend_string *const_OPSYS_MACINTOSH_name = zend_string_init_interned("OPSYS_MACINTOSH", sizeof("OPSYS_MACINTOSH") - 1, 1); + zend_string *const_OPSYS_MACINTOSH_name = zend_string_init_interned("OPSYS_MACINTOSH", sizeof("OPSYS_MACINTOSH") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPSYS_MACINTOSH_name, &const_OPSYS_MACINTOSH_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPSYS_MACINTOSH_name); + zend_string_release_ex(const_OPSYS_MACINTOSH_name, true); zval const_OPSYS_Z_SYSTEM_value; ZVAL_LONG(&const_OPSYS_Z_SYSTEM_value, ZIP_OPSYS_Z_SYSTEM); - zend_string *const_OPSYS_Z_SYSTEM_name = zend_string_init_interned("OPSYS_Z_SYSTEM", sizeof("OPSYS_Z_SYSTEM") - 1, 1); + zend_string *const_OPSYS_Z_SYSTEM_name = zend_string_init_interned("OPSYS_Z_SYSTEM", sizeof("OPSYS_Z_SYSTEM") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPSYS_Z_SYSTEM_name, &const_OPSYS_Z_SYSTEM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPSYS_Z_SYSTEM_name); + zend_string_release_ex(const_OPSYS_Z_SYSTEM_name, true); zval const_OPSYS_CPM_value; ZVAL_LONG(&const_OPSYS_CPM_value, ZIP_OPSYS_CPM); - zend_string *const_OPSYS_CPM_name = zend_string_init_interned("OPSYS_CPM", sizeof("OPSYS_CPM") - 1, 1); + zend_string *const_OPSYS_CPM_name = zend_string_init_interned("OPSYS_CPM", sizeof("OPSYS_CPM") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPSYS_CPM_name, &const_OPSYS_CPM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPSYS_CPM_name); + zend_string_release_ex(const_OPSYS_CPM_name, true); zval const_OPSYS_WINDOWS_NTFS_value; ZVAL_LONG(&const_OPSYS_WINDOWS_NTFS_value, ZIP_OPSYS_WINDOWS_NTFS); - zend_string *const_OPSYS_WINDOWS_NTFS_name = zend_string_init_interned("OPSYS_WINDOWS_NTFS", sizeof("OPSYS_WINDOWS_NTFS") - 1, 1); + zend_string *const_OPSYS_WINDOWS_NTFS_name = zend_string_init_interned("OPSYS_WINDOWS_NTFS", sizeof("OPSYS_WINDOWS_NTFS") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPSYS_WINDOWS_NTFS_name, &const_OPSYS_WINDOWS_NTFS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPSYS_WINDOWS_NTFS_name); + zend_string_release_ex(const_OPSYS_WINDOWS_NTFS_name, true); zval const_OPSYS_MVS_value; ZVAL_LONG(&const_OPSYS_MVS_value, ZIP_OPSYS_MVS); - zend_string *const_OPSYS_MVS_name = zend_string_init_interned("OPSYS_MVS", sizeof("OPSYS_MVS") - 1, 1); + zend_string *const_OPSYS_MVS_name = zend_string_init_interned("OPSYS_MVS", sizeof("OPSYS_MVS") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPSYS_MVS_name, &const_OPSYS_MVS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPSYS_MVS_name); + zend_string_release_ex(const_OPSYS_MVS_name, true); zval const_OPSYS_VSE_value; ZVAL_LONG(&const_OPSYS_VSE_value, ZIP_OPSYS_VSE); - zend_string *const_OPSYS_VSE_name = zend_string_init_interned("OPSYS_VSE", sizeof("OPSYS_VSE") - 1, 1); + zend_string *const_OPSYS_VSE_name = zend_string_init_interned("OPSYS_VSE", sizeof("OPSYS_VSE") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPSYS_VSE_name, &const_OPSYS_VSE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPSYS_VSE_name); + zend_string_release_ex(const_OPSYS_VSE_name, true); zval const_OPSYS_ACORN_RISC_value; ZVAL_LONG(&const_OPSYS_ACORN_RISC_value, ZIP_OPSYS_ACORN_RISC); - zend_string *const_OPSYS_ACORN_RISC_name = zend_string_init_interned("OPSYS_ACORN_RISC", sizeof("OPSYS_ACORN_RISC") - 1, 1); + zend_string *const_OPSYS_ACORN_RISC_name = zend_string_init_interned("OPSYS_ACORN_RISC", sizeof("OPSYS_ACORN_RISC") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPSYS_ACORN_RISC_name, &const_OPSYS_ACORN_RISC_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPSYS_ACORN_RISC_name); + zend_string_release_ex(const_OPSYS_ACORN_RISC_name, true); zval const_OPSYS_VFAT_value; ZVAL_LONG(&const_OPSYS_VFAT_value, ZIP_OPSYS_VFAT); - zend_string *const_OPSYS_VFAT_name = zend_string_init_interned("OPSYS_VFAT", sizeof("OPSYS_VFAT") - 1, 1); + zend_string *const_OPSYS_VFAT_name = zend_string_init_interned("OPSYS_VFAT", sizeof("OPSYS_VFAT") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPSYS_VFAT_name, &const_OPSYS_VFAT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPSYS_VFAT_name); + zend_string_release_ex(const_OPSYS_VFAT_name, true); zval const_OPSYS_ALTERNATE_MVS_value; ZVAL_LONG(&const_OPSYS_ALTERNATE_MVS_value, ZIP_OPSYS_ALTERNATE_MVS); - zend_string *const_OPSYS_ALTERNATE_MVS_name = zend_string_init_interned("OPSYS_ALTERNATE_MVS", sizeof("OPSYS_ALTERNATE_MVS") - 1, 1); + zend_string *const_OPSYS_ALTERNATE_MVS_name = zend_string_init_interned("OPSYS_ALTERNATE_MVS", sizeof("OPSYS_ALTERNATE_MVS") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPSYS_ALTERNATE_MVS_name, &const_OPSYS_ALTERNATE_MVS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPSYS_ALTERNATE_MVS_name); + zend_string_release_ex(const_OPSYS_ALTERNATE_MVS_name, true); zval const_OPSYS_BEOS_value; ZVAL_LONG(&const_OPSYS_BEOS_value, ZIP_OPSYS_BEOS); - zend_string *const_OPSYS_BEOS_name = zend_string_init_interned("OPSYS_BEOS", sizeof("OPSYS_BEOS") - 1, 1); + zend_string *const_OPSYS_BEOS_name = zend_string_init_interned("OPSYS_BEOS", sizeof("OPSYS_BEOS") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPSYS_BEOS_name, &const_OPSYS_BEOS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPSYS_BEOS_name); + zend_string_release_ex(const_OPSYS_BEOS_name, true); zval const_OPSYS_TANDEM_value; ZVAL_LONG(&const_OPSYS_TANDEM_value, ZIP_OPSYS_TANDEM); - zend_string *const_OPSYS_TANDEM_name = zend_string_init_interned("OPSYS_TANDEM", sizeof("OPSYS_TANDEM") - 1, 1); + zend_string *const_OPSYS_TANDEM_name = zend_string_init_interned("OPSYS_TANDEM", sizeof("OPSYS_TANDEM") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPSYS_TANDEM_name, &const_OPSYS_TANDEM_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPSYS_TANDEM_name); + zend_string_release_ex(const_OPSYS_TANDEM_name, true); zval const_OPSYS_OS_400_value; ZVAL_LONG(&const_OPSYS_OS_400_value, ZIP_OPSYS_OS_400); - zend_string *const_OPSYS_OS_400_name = zend_string_init_interned("OPSYS_OS_400", sizeof("OPSYS_OS_400") - 1, 1); + zend_string *const_OPSYS_OS_400_name = zend_string_init_interned("OPSYS_OS_400", sizeof("OPSYS_OS_400") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPSYS_OS_400_name, &const_OPSYS_OS_400_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPSYS_OS_400_name); + zend_string_release_ex(const_OPSYS_OS_400_name, true); zval const_OPSYS_OS_X_value; ZVAL_LONG(&const_OPSYS_OS_X_value, ZIP_OPSYS_OS_X); - zend_string *const_OPSYS_OS_X_name = zend_string_init_interned("OPSYS_OS_X", sizeof("OPSYS_OS_X") - 1, 1); + zend_string *const_OPSYS_OS_X_name = zend_string_init_interned("OPSYS_OS_X", sizeof("OPSYS_OS_X") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPSYS_OS_X_name, &const_OPSYS_OS_X_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPSYS_OS_X_name); + zend_string_release_ex(const_OPSYS_OS_X_name, true); zval const_OPSYS_DEFAULT_value; ZVAL_LONG(&const_OPSYS_DEFAULT_value, ZIP_OPSYS_DEFAULT); - zend_string *const_OPSYS_DEFAULT_name = zend_string_init_interned("OPSYS_DEFAULT", sizeof("OPSYS_DEFAULT") - 1, 1); + zend_string *const_OPSYS_DEFAULT_name = zend_string_init_interned("OPSYS_DEFAULT", sizeof("OPSYS_DEFAULT") - 1, true); zend_declare_typed_class_constant(class_entry, const_OPSYS_DEFAULT_name, &const_OPSYS_DEFAULT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_OPSYS_DEFAULT_name); + zend_string_release_ex(const_OPSYS_DEFAULT_name, true); #endif zval const_EM_NONE_value; ZVAL_LONG(&const_EM_NONE_value, ZIP_EM_NONE); - zend_string *const_EM_NONE_name = zend_string_init_interned("EM_NONE", sizeof("EM_NONE") - 1, 1); + zend_string *const_EM_NONE_name = zend_string_init_interned("EM_NONE", sizeof("EM_NONE") - 1, true); zend_declare_typed_class_constant(class_entry, const_EM_NONE_name, &const_EM_NONE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EM_NONE_name); + zend_string_release_ex(const_EM_NONE_name, true); zval const_EM_TRAD_PKWARE_value; ZVAL_LONG(&const_EM_TRAD_PKWARE_value, ZIP_EM_TRAD_PKWARE); - zend_string *const_EM_TRAD_PKWARE_name = zend_string_init_interned("EM_TRAD_PKWARE", sizeof("EM_TRAD_PKWARE") - 1, 1); + zend_string *const_EM_TRAD_PKWARE_name = zend_string_init_interned("EM_TRAD_PKWARE", sizeof("EM_TRAD_PKWARE") - 1, true); zend_declare_typed_class_constant(class_entry, const_EM_TRAD_PKWARE_name, &const_EM_TRAD_PKWARE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EM_TRAD_PKWARE_name); + zend_string_release_ex(const_EM_TRAD_PKWARE_name, true); #if defined(HAVE_ENCRYPTION) zval const_EM_AES_128_value; ZVAL_LONG(&const_EM_AES_128_value, ZIP_EM_AES_128); - zend_string *const_EM_AES_128_name = zend_string_init_interned("EM_AES_128", sizeof("EM_AES_128") - 1, 1); + zend_string *const_EM_AES_128_name = zend_string_init_interned("EM_AES_128", sizeof("EM_AES_128") - 1, true); zend_declare_typed_class_constant(class_entry, const_EM_AES_128_name, &const_EM_AES_128_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EM_AES_128_name); + zend_string_release_ex(const_EM_AES_128_name, true); zval const_EM_AES_192_value; ZVAL_LONG(&const_EM_AES_192_value, ZIP_EM_AES_192); - zend_string *const_EM_AES_192_name = zend_string_init_interned("EM_AES_192", sizeof("EM_AES_192") - 1, 1); + zend_string *const_EM_AES_192_name = zend_string_init_interned("EM_AES_192", sizeof("EM_AES_192") - 1, true); zend_declare_typed_class_constant(class_entry, const_EM_AES_192_name, &const_EM_AES_192_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EM_AES_192_name); + zend_string_release_ex(const_EM_AES_192_name, true); zval const_EM_AES_256_value; ZVAL_LONG(&const_EM_AES_256_value, ZIP_EM_AES_256); - zend_string *const_EM_AES_256_name = zend_string_init_interned("EM_AES_256", sizeof("EM_AES_256") - 1, 1); + zend_string *const_EM_AES_256_name = zend_string_init_interned("EM_AES_256", sizeof("EM_AES_256") - 1, true); zend_declare_typed_class_constant(class_entry, const_EM_AES_256_name, &const_EM_AES_256_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EM_AES_256_name); + zend_string_release_ex(const_EM_AES_256_name, true); #endif zval const_EM_UNKNOWN_value; ZVAL_LONG(&const_EM_UNKNOWN_value, ZIP_EM_UNKNOWN); - zend_string *const_EM_UNKNOWN_name = zend_string_init_interned("EM_UNKNOWN", sizeof("EM_UNKNOWN") - 1, 1); + zend_string *const_EM_UNKNOWN_name = zend_string_init_interned("EM_UNKNOWN", sizeof("EM_UNKNOWN") - 1, true); zend_declare_typed_class_constant(class_entry, const_EM_UNKNOWN_name, &const_EM_UNKNOWN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_EM_UNKNOWN_name); + zend_string_release_ex(const_EM_UNKNOWN_name, true); zval const_LIBZIP_VERSION_value; zend_string *const_LIBZIP_VERSION_value_str = zend_string_init(LIBZIP_VERSION_STR, strlen(LIBZIP_VERSION_STR), 1); ZVAL_STR(&const_LIBZIP_VERSION_value, const_LIBZIP_VERSION_value_str); - zend_string *const_LIBZIP_VERSION_name = zend_string_init_interned("LIBZIP_VERSION", sizeof("LIBZIP_VERSION") - 1, 1); + zend_string *const_LIBZIP_VERSION_name = zend_string_init_interned("LIBZIP_VERSION", sizeof("LIBZIP_VERSION") - 1, true); zend_declare_typed_class_constant(class_entry, const_LIBZIP_VERSION_name, &const_LIBZIP_VERSION_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(const_LIBZIP_VERSION_name); + zend_string_release_ex(const_LIBZIP_VERSION_name, true); zval const_LENGTH_TO_END_value; ZVAL_LONG(&const_LENGTH_TO_END_value, ZIP_LENGTH_TO_END); - zend_string *const_LENGTH_TO_END_name = zend_string_init_interned("LENGTH_TO_END", sizeof("LENGTH_TO_END") - 1, 1); + zend_string *const_LENGTH_TO_END_name = zend_string_init_interned("LENGTH_TO_END", sizeof("LENGTH_TO_END") - 1, true); zend_declare_typed_class_constant(class_entry, const_LENGTH_TO_END_name, &const_LENGTH_TO_END_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LENGTH_TO_END_name); + zend_string_release_ex(const_LENGTH_TO_END_name, true); #if defined(ZIP_LENGTH_UNCHECKED) zval const_LENGTH_UNCHECKED_value; ZVAL_LONG(&const_LENGTH_UNCHECKED_value, ZIP_LENGTH_UNCHECKED); - zend_string *const_LENGTH_UNCHECKED_name = zend_string_init_interned("LENGTH_UNCHECKED", sizeof("LENGTH_UNCHECKED") - 1, 1); + zend_string *const_LENGTH_UNCHECKED_name = zend_string_init_interned("LENGTH_UNCHECKED", sizeof("LENGTH_UNCHECKED") - 1, true); zend_declare_typed_class_constant(class_entry, const_LENGTH_UNCHECKED_name, &const_LENGTH_UNCHECKED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(const_LENGTH_UNCHECKED_name); + zend_string_release_ex(const_LENGTH_UNCHECKED_name, true); #endif zval property_lastId_default_value; ZVAL_UNDEF(&property_lastId_default_value); - zend_string *property_lastId_name = zend_string_init("lastId", sizeof("lastId") - 1, 1); + zend_string *property_lastId_name = zend_string_init("lastId", sizeof("lastId") - 1, true); zend_declare_typed_property(class_entry, property_lastId_name, &property_lastId_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_lastId_name); + zend_string_release_ex(property_lastId_name, true); zval property_status_default_value; ZVAL_UNDEF(&property_status_default_value); - zend_string *property_status_name = zend_string_init("status", sizeof("status") - 1, 1); + zend_string *property_status_name = zend_string_init("status", sizeof("status") - 1, true); zend_declare_typed_property(class_entry, property_status_name, &property_status_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_status_name); + zend_string_release_ex(property_status_name, true); zval property_statusSys_default_value; ZVAL_UNDEF(&property_statusSys_default_value); - zend_string *property_statusSys_name = zend_string_init("statusSys", sizeof("statusSys") - 1, 1); + zend_string *property_statusSys_name = zend_string_init("statusSys", sizeof("statusSys") - 1, true); zend_declare_typed_property(class_entry, property_statusSys_name, &property_statusSys_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_statusSys_name); + zend_string_release_ex(property_statusSys_name, true); zval property_numFiles_default_value; ZVAL_UNDEF(&property_numFiles_default_value); - zend_string *property_numFiles_name = zend_string_init("numFiles", sizeof("numFiles") - 1, 1); + zend_string *property_numFiles_name = zend_string_init("numFiles", sizeof("numFiles") - 1, true); zend_declare_typed_property(class_entry, property_numFiles_name, &property_numFiles_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_numFiles_name); + zend_string_release_ex(property_numFiles_name, true); zval property_filename_default_value; ZVAL_UNDEF(&property_filename_default_value); - zend_string *property_filename_name = zend_string_init("filename", sizeof("filename") - 1, 1); + zend_string *property_filename_name = zend_string_init("filename", sizeof("filename") - 1, true); zend_declare_typed_property(class_entry, property_filename_name, &property_filename_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_filename_name); + zend_string_release_ex(property_filename_name, true); zval property_comment_default_value; ZVAL_UNDEF(&property_comment_default_value); - zend_string *property_comment_name = zend_string_init("comment", sizeof("comment") - 1, 1); + zend_string *property_comment_name = zend_string_init("comment", sizeof("comment") - 1, true); zend_declare_typed_property(class_entry, property_comment_name, &property_comment_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_comment_name); + zend_string_release_ex(property_comment_name, true); #if defined(ZIP_FL_RECOMPRESS) diff --git a/ext/zip/tests/ZipArchive_bailout.phpt b/ext/zip/tests/ZipArchive_bailout.phpt new file mode 100644 index 0000000000000..c7e4ede8446df --- /dev/null +++ b/ext/zip/tests/ZipArchive_bailout.phpt @@ -0,0 +1,28 @@ +--TEST-- +ZipArchive destructor should be called on bailout +--EXTENSIONS-- +zip +--FILE-- +open($file, ZIPARCHIVE::CREATE); +$zip->registerCancelCallback(cb(...)); +$zip->addFromString('test', 'test'); +$fusion = $zip; + +?> +--CLEAN-- + +--EXPECTF-- +Notice: Only variable references should be returned by reference in %s on line %d + +Notice: Only variable references should be returned by reference in %s on line %d + +Notice: Only variable references should be returned by reference in %s on line %d diff --git a/ext/zip/tests/ZipArchive_destruct.phpt b/ext/zip/tests/ZipArchive_destruct.phpt new file mode 100644 index 0000000000000..7e3ef6c5dae42 --- /dev/null +++ b/ext/zip/tests/ZipArchive_destruct.phpt @@ -0,0 +1,28 @@ +--TEST-- +Leaking ZipArchive destructor +--EXTENSIONS-- +zip +--FILE-- +open($file, ZIPARCHIVE::CREATE); +$leak->addFromString('test', 'test'); + +?> +===DONE=== +--CLEAN-- + +--EXPECT-- +===DONE=== 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/ext/zip/tests/gh19932.phpt b/ext/zip/tests/gh19932.phpt new file mode 100644 index 0000000000000..760fa1c9e766d --- /dev/null +++ b/ext/zip/tests/gh19932.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-19932 (ZipArchive::setEncryptionName()/setEncryptionIndex() memory leak) +--EXTENSIONS-- +zip +--SKIPIF-- + +--FILE-- +open(__DIR__ . "/gh19932.zip", ZipArchive::CREATE); +$zip->addFromString("test.txt", "test"); +$zip->setEncryptionName("test.txt", ZipArchive::EM_AES_256, "password"); +$zip->setEncryptionName("test.txt", ZipArchive::EM_AES_256, "password"); +$zip->setEncryptionIndex("0", ZipArchive::EM_AES_256, "password"); +$zip->setEncryptionIndex("0", ZipArchive::EM_AES_256, "password"); +$zip->close(); +echo "OK"; +?> +--CLEAN-- + +--EXPECT-- +OK + diff --git a/ext/zip/tests/oo_addglob2.phpt b/ext/zip/tests/oo_addglob2.phpt index 517c0b7fd7fda..a98a222712052 100644 --- a/ext/zip/tests/oo_addglob2.phpt +++ b/ext/zip/tests/oo_addglob2.phpt @@ -33,10 +33,26 @@ if (!$zip->addGlob($dirname . 'foo.*', GLOB_BRACE, $options)) { $options = [ 'remove_all_path' => true, 'comp_method' => ZipArchive::CM_STORE, - 'comp_flags' => 5, + 'comp_flags' => PHP_INT_MIN, 'enc_method' => ZipArchive::EM_AES_256, 'enc_password' => 'secret', ]; + +try { + $zip->addGlob($dirname. 'bar.*', GLOB_BRACE, $options); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} + +$options['comp_flags'] = 65536; + +try { + $zip->addGlob($dirname. 'bar.*', GLOB_BRACE, $options); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} + +$options['comp_flags'] = 5; if (!$zip->addGlob($dirname . 'bar.*', GLOB_BRACE, $options)) { echo "failed 2\n"; } @@ -61,6 +77,10 @@ $dirname = __DIR__ . '/'; include $dirname . 'utils.inc'; rmdir_rf(__DIR__ . '/__tmp_oo_addglob2/'); ?> ---EXPECT-- +--EXPECTF-- + +Warning: ZipArchive::addGlob(): Option "comp_flags" must be between 0 and 65535 in %s on line %d + +Warning: ZipArchive::addGlob(): Option "comp_flags" must be between 0 and 65535 in %s on line %d 0: foo.txt, comp=8, enc=0 1: bar.txt, comp=0, enc=259 diff --git a/ext/zip/tests/oo_addglob_leak.phpt b/ext/zip/tests/oo_addglob_leak.phpt new file mode 100644 index 0000000000000..9040c5565f842 --- /dev/null +++ b/ext/zip/tests/oo_addglob_leak.phpt @@ -0,0 +1,51 @@ +--TEST-- +ZipArchive::addGlob() method leaking after several calls when encryption is set. +--EXTENSIONS-- +zip +--SKIPIF-- + +--FILE-- +open($file, ZipArchive::CREATE | ZipArchive::OVERWRITE)) { + exit('failed'); +} + +$options = [ + 'remove_all_path' => true, + 'comp_method' => ZipArchive::CM_STORE, + 'comp_flags' => 5, + 'enc_method' => ZipArchive::EM_AES_256, + 'enc_password' => 'secret', +]; +var_dump($zip->addGlob($dirname . 'bar.*', GLOB_BRACE, $options)); +var_dump($zip->addGlob($dirname . 'bar.*', GLOB_BRACE, $options)); +?> +--CLEAN-- + +--EXPECTF-- +array(1) { + [0]=> + string(%d) "%s" +} +array(1) { + [0]=> + string(%d) "%s" +} diff --git a/ext/zip/tests/oo_setcompression.phpt b/ext/zip/tests/oo_setcompression.phpt index 6b3291463659b..1b7e817688dde 100644 --- a/ext/zip/tests/oo_setcompression.phpt +++ b/ext/zip/tests/oo_setcompression.phpt @@ -28,6 +28,18 @@ var_dump($zip->setCompressionName('entry2.txt', ZipArchive::CM_DEFAULT)); var_dump($zip->setCompressionName('dir/entry3.txt', ZipArchive::CM_STORE)); var_dump($zip->setCompressionName('entry4.txt', ZipArchive::CM_DEFLATE)); +try { + $zip->setCompressionName('entry5.txt', PHP_INT_MIN); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + $zip->setCompressionIndex(4, PHP_INT_MIN); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} + var_dump($zip->setCompressionIndex(4, ZipArchive::CM_STORE)); var_dump($zip->setCompressionIndex(5, ZipArchive::CM_DEFLATE)); var_dump($zip->setCompressionIndex(6, ZipArchive::CM_DEFAULT)); @@ -57,6 +69,8 @@ unlink($tmpfile); bool(true) bool(true) bool(true) +ZipArchive::setCompressionName(): Argument #2 ($method) must be between -1 and %d +ZipArchive::setCompressionIndex(): Argument #2 ($method) must be between -1 and %d bool(true) bool(true) bool(true) diff --git a/ext/zip/tests/oo_setcompression_64bit.phpt b/ext/zip/tests/oo_setcompression_64bit.phpt new file mode 100644 index 0000000000000..cb093e8ccfc9d --- /dev/null +++ b/ext/zip/tests/oo_setcompression_64bit.phpt @@ -0,0 +1,29 @@ +--TEST-- +setCompressionName and setCompressionIndex methods +--EXTENSIONS-- +zip +--SKIPIF-- + +--FILE-- +setCompressionName('entry5.txt', PHP_INT_MAX); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + $zip->setCompressionIndex(4, PHP_INT_MAX); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} + +?> +--EXPECTF-- +ZipArchive::setCompressionName(): Argument #2 ($method) must be between -1 and %d +ZipArchive::setCompressionIndex(): Argument #2 ($method) must be between -1 and %d diff --git a/ext/zip/tests/oo_setmtime.phpt b/ext/zip/tests/oo_setmtime.phpt index 8c3c4eb7cca32..bf34dd722b519 100644 --- a/ext/zip/tests/oo_setmtime.phpt +++ b/ext/zip/tests/oo_setmtime.phpt @@ -2,11 +2,6 @@ setMtime --EXTENSIONS-- zip ---SKIPIF-- - --INI-- date.timezone=UTC --FILE-- diff --git a/ext/zip/tests/property_existence_test.phpt b/ext/zip/tests/property_existence_test.phpt new file mode 100644 index 0000000000000..855bf73464ac1 --- /dev/null +++ b/ext/zip/tests/property_existence_test.phpt @@ -0,0 +1,20 @@ +--TEST-- +Property existence test can cause a crash +--EXTENSIONS-- +zip +--FILE-- + +--CLEAN-- + +--EXPECT-- +array(1) { + [0]=> + int(-1) +} diff --git a/ext/zip/zip_stream.c b/ext/zip/zip_stream.c index a32324347d674..50f097de3c876 100644 --- a/ext/zip/zip_stream.c +++ b/ext/zip/zip_stream.c @@ -49,18 +49,11 @@ static ssize_t php_zip_ops_read(php_stream *stream, char *buf, size_t count) if (self->zf) { n = zip_fread(self->zf, buf, count); if (n < 0) { -#if LIBZIP_VERSION_MAJOR < 1 - int ze, se; - zip_file_error_get(self->zf, &ze, &se); - stream->eof = 1; - php_error_docref(NULL, E_WARNING, "Zip stream error: %s", zip_file_strerror(self->zf)); -#else zip_error_t *err; err = zip_file_get_error(self->zf); stream->eof = 1; php_error_docref(NULL, E_WARNING, "Zip stream error: %s", zip_error_strerror(err)); zip_error_fini(err); -#endif return -1; } /* cast count to signed value to avoid possibly negative n @@ -82,7 +75,7 @@ static ssize_t php_zip_ops_write(php_stream *stream, const char *buf, size_t cou return -1; } - return count; + return (ssize_t)count; } /* }}} */ @@ -157,7 +150,7 @@ static int php_zip_ops_stat(php_stream *stream, php_stream_statbuf *ssb) /* {{{ fragment++; if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname)) { - zend_string_release_ex(file_basename, 0); + zend_string_release_ex(file_basename, false); return -1; } @@ -166,7 +159,7 @@ static int php_zip_ops_stat(php_stream *stream, php_stream_statbuf *ssb) /* {{{ memset(ssb, 0, sizeof(php_stream_statbuf)); if (zip_stat(za, fragment, ZIP_FL_NOCASE, &sb) != 0) { zip_close(za); - zend_string_release_ex(file_basename, 0); + zend_string_release_ex(file_basename, false); return -1; } zip_close(za); @@ -190,7 +183,7 @@ static int php_zip_ops_stat(php_stream *stream, php_stream_statbuf *ssb) /* {{{ #endif ssb->sb.st_ino = -1; } - zend_string_release_ex(file_basename, 0); + zend_string_release_ex(file_basename, false); return 0; } /* }}} */ @@ -319,7 +312,7 @@ php_stream *php_stream_zip_opener(php_stream_wrapper *wrapper, fragment++; if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname)) { - zend_string_release_ex(file_basename, 0); + zend_string_release_ex(file_basename, false); return NULL; } @@ -351,14 +344,14 @@ php_stream *php_stream_zip_opener(php_stream_wrapper *wrapper, } if (opened_path) { - *opened_path = zend_string_init(path, strlen(path), 0); + *opened_path = zend_string_init(path, path_len, false); } } else { zip_close(za); } } - zend_string_release_ex(file_basename, 0); + zend_string_release_ex(file_basename, false); if (!stream) { return NULL; diff --git a/ext/zlib/config.w32 b/ext/zlib/config.w32 index 3bc24d88e1735..63ca949813ce1 100644 --- a/ext/zlib/config.w32 +++ b/ext/zlib/config.w32 @@ -6,7 +6,7 @@ if (PHP_ZLIB == "yes") { if (CHECK_LIB("zlib_a.lib;zlib.lib", "zlib", PHP_ZLIB) && CHECK_HEADER_ADD_INCLUDE("zlib.h", "CFLAGS", "..\\zlib;" + php_usual_include_suspects)) { - EXTENSION("zlib", "zlib.c zlib_fopen_wrapper.c zlib_filter.c", PHP_ZLIB_SHARED, "/D ZLIB_EXPORTS /DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); + EXTENSION("zlib", "zlib.c zlib_fopen_wrapper.c zlib_filter.c", PHP_ZLIB_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); AC_DEFINE("HAVE_ZLIB", 1, "Define to 1 if the PHP extension 'zlib' is available."); if (!PHP_ZLIB_SHARED) { diff --git a/ext/zlib/tests/data/zlib_flock.txt.gz b/ext/zlib/tests/data/zlib_flock.txt.gz new file mode 100644 index 0000000000000..07805db755807 Binary files /dev/null and b/ext/zlib/tests/data/zlib_flock.txt.gz differ diff --git a/ext/zlib/tests/filter_broken_object_options.phpt b/ext/zlib/tests/filter_broken_object_options.phpt new file mode 100644 index 0000000000000..beb0fef9fb137 --- /dev/null +++ b/ext/zlib/tests/filter_broken_object_options.phpt @@ -0,0 +1,21 @@ +--TEST-- +zlib filter assertion failure with non-dynamic properties in filter param object +--EXTENSIONS-- +zlib +--FILE-- + +--EXPECT-- +Hello world, hopefully not broken diff --git a/ext/zlib/tests/gh19922.phpt b/ext/zlib/tests/gh19922.phpt new file mode 100644 index 0000000000000..71644512e6656 --- /dev/null +++ b/ext/zlib/tests/gh19922.phpt @@ -0,0 +1,12 @@ +--TEST-- +GH-19922 (gzopen double free on debug build and unseekable stream) +--EXTENSIONS-- +zlib +--FILE-- + +--EXPECTF-- + +Warning: gzopen(php://output): could not make seekable - php://output in %s on line %d +bool(false) diff --git a/ext/zlib/tests/inflate_init_error.phpt b/ext/zlib/tests/inflate_init_error.phpt index 8faed763be4e5..9854f7453909b 100644 --- a/ext/zlib/tests/inflate_init_error.phpt +++ b/ext/zlib/tests/inflate_init_error.phpt @@ -13,4 +13,4 @@ try { ?> --EXPECT-- -Encoding mode must be ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP or ZLIB_ENCODING_DEFLATE +inflate_init(): Argument #1 ($encoding) must be one of ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP, or ZLIB_ENCODING_DEFLATE diff --git a/ext/zlib/tests/leak_invalid_encoding_with_dict.phpt b/ext/zlib/tests/leak_invalid_encoding_with_dict.phpt index da2a11849c0c2..507e6842cb587 100644 --- a/ext/zlib/tests/leak_invalid_encoding_with_dict.phpt +++ b/ext/zlib/tests/leak_invalid_encoding_with_dict.phpt @@ -16,5 +16,5 @@ try { } ?> --EXPECT-- -Encoding mode must be ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP or ZLIB_ENCODING_DEFLATE +inflate_init(): Argument #1 ($encoding) must be one of ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP, or ZLIB_ENCODING_DEFLATE deflate_init(): Argument #1 ($encoding) must be one of ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP, or ZLIB_ENCODING_DEFLATE diff --git a/ext/zlib/tests/zlib_wrapper_flock_basic.phpt b/ext/zlib/tests/zlib_wrapper_flock_basic.phpt index 3d7c72c84cd48..9ebb517715ba1 100644 --- a/ext/zlib/tests/zlib_wrapper_flock_basic.phpt +++ b/ext/zlib/tests/zlib_wrapper_flock_basic.phpt @@ -4,7 +4,7 @@ Test function flock on a zlib stream zlib --FILE-- 0) { zend_string **strings = safe_emalloc(zend_hash_num_elements(dictionary), sizeof(zend_string *), 0); @@ -815,18 +815,18 @@ static bool zlib_create_dictionary_string(HashTable *options, char **dict, size_ ZEND_HASH_FOREACH_VAL(dictionary, cur) { zend_string *string = zval_try_get_string(cur); if (string == NULL) { - result = 0; + result = false; break; } *dictlen += ZSTR_LEN(string) + 1; strings[total++] = string; if (ZSTR_LEN(string) == 0) { - result = 0; + result = false; zend_argument_value_error(2, "must not contain empty strings"); break; } if (zend_str_has_nul_byte(string)) { - result = 0; + result = false; zend_argument_value_error(2, "must not contain strings with null bytes"); break; } @@ -852,10 +852,10 @@ static bool zlib_create_dictionary_string(HashTable *options, char **dict, size_ default: zend_argument_type_error(2, "must be of type zero-terminated string or array, %s given", zend_zval_value_name(option_buffer)); - return 0; + return false; } } - return 1; + return true; } /* {{{ Initialize an incremental inflate context with the specified encoding */ @@ -887,7 +887,7 @@ PHP_FUNCTION(inflate_init) case PHP_ZLIB_ENCODING_DEFLATE: break; default: - zend_value_error("Encoding mode must be ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP or ZLIB_ENCODING_DEFLATE"); + zend_argument_value_error(1, "must be one of ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP, or ZLIB_ENCODING_DEFLATE"); RETURN_THROWS(); } diff --git a/ext/zlib/zlib_filter.c b/ext/zlib/zlib_filter.c index 24d418ae04cfa..e42132fd0008c 100644 --- a/ext/zlib/zlib_filter.c +++ b/ext/zlib/zlib_filter.c @@ -238,7 +238,7 @@ static php_stream_filter_status_t php_zlib_deflate_filter( status = Z_OK; while (status == Z_OK) { status = deflate(&(data->strm), (flags & PSFS_FLAG_FLUSH_CLOSE ? Z_FINISH : Z_SYNC_FLUSH)); - data->finished = 1; + data->finished = true; if (data->strm.avail_out < data->outbuf_len) { size_t bucketlen = data->outbuf_len - data->strm.avail_out; @@ -323,7 +323,7 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f zval *tmpzval; if ((Z_TYPE_P(filterparams) == IS_ARRAY || Z_TYPE_P(filterparams) == IS_OBJECT) && - (tmpzval = zend_hash_str_find(HASH_OF(filterparams), "window", sizeof("window") - 1))) { + (tmpzval = zend_hash_str_find_ind(HASH_OF(filterparams), "window", sizeof("window") - 1))) { /* log-2 base of history window (9 - 15) */ zend_long tmp = zval_get_long(tmpzval); if (tmp < -MAX_WBITS || tmp > MAX_WBITS + 32) { @@ -335,7 +335,7 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f } /* RFC 1951 Inflate */ - data->finished = '\0'; + data->finished = false; status = inflateInit2(&(data->strm), windowBits); fops = &php_zlib_inflate_ops; } else if (strcasecmp(filtername, "zlib.deflate") == 0) { @@ -354,8 +354,10 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f switch (Z_TYPE_P(filterparams)) { case IS_ARRAY: - case IS_OBJECT: - if ((tmpzval = zend_hash_str_find(HASH_OF(filterparams), "memory", sizeof("memory") -1))) { + case IS_OBJECT: { + HashTable *ht = HASH_OF(filterparams); + + if ((tmpzval = zend_hash_str_find_ind(ht, "memory", sizeof("memory") -1))) { /* Memory Level (1 - 9) */ tmp = zval_get_long(tmpzval); if (tmp < 1 || tmp > MAX_MEM_LEVEL) { @@ -365,7 +367,7 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f } } - if ((tmpzval = zend_hash_str_find(HASH_OF(filterparams), "window", sizeof("window") - 1))) { + if ((tmpzval = zend_hash_str_find_ind(ht, "window", sizeof("window") - 1))) { /* log-2 base of history window (9 - 15) */ tmp = zval_get_long(tmpzval); if (tmp < -MAX_WBITS || tmp > MAX_WBITS + 16) { @@ -375,13 +377,14 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f } } - if ((tmpzval = zend_hash_str_find(HASH_OF(filterparams), "level", sizeof("level") - 1))) { + if ((tmpzval = zend_hash_str_find_ind(ht, "level", sizeof("level") - 1))) { tmp = zval_get_long(tmpzval); /* Pseudo pass through to catch level validating code */ goto factory_setlevel; } break; + } case IS_STRING: case IS_DOUBLE: case IS_LONG: @@ -399,7 +402,7 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f } } status = deflateInit2(&(data->strm), level, Z_DEFLATED, windowBits, memLevel, 0); - data->finished = 1; + data->finished = true; fops = &php_zlib_deflate_ops; } else { status = Z_DATA_ERROR; diff --git a/main/SAPI.c b/main/SAPI.c index 866b44c3eac7d..6709d467e34fe 100644 --- a/main/SAPI.c +++ b/main/SAPI.c @@ -458,6 +458,10 @@ SAPI_API void sapi_activate(void) SG(request_parse_body_context).throw_exceptions = false; memset(&SG(request_parse_body_context).options_cache, 0, sizeof(SG(request_parse_body_context).options_cache)); + if (sapi_module.pre_request_init) { + sapi_module.pre_request_init(); + } + /* Handle request method */ if (SG(server_context)) { if (PG(enable_post_data_reading) @@ -597,7 +601,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 +610,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 +659,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 +674,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 +697,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 +706,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 +735,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 +746,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..9196982f54951 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) @@ -287,6 +290,8 @@ struct _sapi_module_struct { const char *ini_entries; const zend_function_entry *additional_functions; unsigned int (*input_filter_init)(void); + + int (*pre_request_init)(void); /* called before activate and before the post data read - used for .user.ini */ }; struct _sapi_post_entry { @@ -337,6 +342,7 @@ END_EXTERN_C() 0, /* phpinfo_as_text; */ \ NULL, /* ini_entries; */ \ NULL, /* additional_functions */ \ - NULL /* input_filter_init */ + NULL, /* input_filter_init */ \ + NULL /* pre_request_init */ #endif /* SAPI_H */ diff --git a/main/debug_gdb_scripts.c b/main/debug_gdb_scripts.c index e3c522bc04843..7a4bf00980c3e 100644 --- a/main/debug_gdb_scripts.c +++ b/main/debug_gdb_scripts.c @@ -55,7 +55,7 @@ asm( ".ascii \"\\n\"\n" ".ascii \" printf \\\"Compiled variables count: %d\\\\\\\\n\\\\\\\\n\\\", $cv_count\\n\"\n" ".ascii \" while $cv_idx < $cv_count\\n\"\n" - ".ascii \" printf \\\"[%d] \\\\'%s\\\\'\\\\\\\\n\\\", $cv_idx, $cv[$cv_idx].val\\n\"\n" + ".ascii \" printf \\\"[%d] \\\\'$%s\\\\'\\\\\\\\n\\\", $cv_idx, $cv[$cv_idx].val@$cv[$cv_idx].len\\n\"\n" ".ascii \" set $zvalue = ((zval *) $cv_ex_ptr) + $callFrameSize + $cv_idx\\n\"\n" ".ascii \" printzv $zvalue\\n\"\n" ".ascii \" set $cv_idx = $cv_idx + 1\\n\"\n" diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c index fc0dbb9a984ea..63564cc73bdfc 100644 --- a/main/fopen_wrappers.c +++ b/main/fopen_wrappers.c @@ -506,7 +506,7 @@ PHPAPI zend_string *php_resolve_path(const char *filename, size_t filename_lengt php_stream_wrapper *wrapper; zend_string *exec_filename; - if (!filename || CHECK_NULL_PATH(filename, filename_length)) { + if (!filename || zend_char_has_nul_byte(filename, filename_length)) { return NULL; } 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 3518e4137ecef..f190eab3d094f 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 @@ -123,8 +127,8 @@ PHPAPI char *php_get_version(sapi_module_struct *sapi_module) { smart_string version_info = {0}; smart_string_append_printf(&version_info, - "PHP %s (%s) (built: %s) (%s)\n", - PHP_VERSION, sapi_module->name, php_build_date, + "PHP " PHP_VERSION " (%s) (built: %s) (%s)\n", + sapi_module->name, php_build_date, #ifdef ZTS "ZTS" #else @@ -144,8 +148,12 @@ PHPAPI char *php_get_version(sapi_module_struct *sapi_module) #endif ); smart_string_appends(&version_info, "Copyright (c) The PHP Group\n"); - if (php_build_provider()) { - smart_string_append_printf(&version_info, "Built by %s\n", php_build_provider()); + + const char *build_provider = php_build_provider(); + if (build_provider) { + smart_string_appends(&version_info, "Built by "); + smart_string_appends(&version_info, build_provider); + smart_string_appendc(&version_info, '\n'); } smart_string_appends(&version_info, get_zend_version()); smart_string_0(&version_info); @@ -156,7 +164,7 @@ PHPAPI char *php_get_version(sapi_module_struct *sapi_module) PHPAPI void php_print_version(sapi_module_struct *sapi_module) { char *version_info = php_get_version(sapi_module); - php_printf("%s", version_info); + PHPWRITE(version_info, strlen(version_info)); efree(version_info); } @@ -332,6 +340,23 @@ 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_init(ZSTR_VAL(max_mem_limit_ini->value), ZSTR_LEN(max_mem_limit_ini->value), true); + GC_MAKE_PERSISTENT_LOCAL(entry->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 +372,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 +418,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 +668,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,14 +700,15 @@ 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")) { + new_value && !zend_string_equals_literal(new_value, "syslog") && ZSTR_LEN(new_value) > 0) { if (PG(open_basedir) && php_check_open_basedir(ZSTR_VAL(new_value))) { return FAILURE; } } - OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); + char **p = (char **) ZEND_INI_GET_ADDR(); + *p = new_value && ZSTR_LEN(new_value) > 0 ? ZSTR_VAL(new_value) : NULL; return SUCCESS; } /* }}} */ @@ -692,13 +716,43 @@ static PHP_INI_MH(OnUpdateErrorLog) /* {{{ PHP_INI_MH */ static PHP_INI_MH(OnUpdateMailLog) { - /* Only do the safemode/open_basedir check at runtime */ - if ((stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) && new_value) { + /* Only do the open_basedir check at runtime */ + if ((stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) && new_value && ZSTR_LEN(new_value) > 0) { if (PG(open_basedir) && php_check_open_basedir(ZSTR_VAL(new_value))) { return FAILURE; } } - OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); + char **p = (char **) ZEND_INI_GET_ADDR(); + *p = new_value && ZSTR_LEN(new_value) > 0 ? ZSTR_VAL(new_value) : NULL; + return SUCCESS; +} +/* }}} */ + +/* {{{ 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; } /* }}} */ @@ -707,7 +761,7 @@ static PHP_INI_MH(OnUpdateMailLog) 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 +815,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 +862,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 +1067,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 +1134,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 +1154,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 = '-'; @@ -1577,24 +1635,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 +1866,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 +2106,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 +2289,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 +2370,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 +2400,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 +2431,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 +2818,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..96953531c3761 100644 --- a/main/network.c +++ b/main/network.c @@ -317,6 +317,8 @@ static inline void php_network_set_limit_time(struct timeval *limit_time, struct timeval *timeout) { gettimeofday(limit_time, NULL); + const double timeoutmax = (double) PHP_TIMEOUT_ULL_MAX / 1000000.0; + ZEND_ASSERT(limit_time->tv_sec < (timeoutmax - timeout->tv_sec)); limit_time->tv_sec += timeout->tv_sec; limit_time->tv_usec += timeout->tv_usec; if (limit_time->tv_usec >= 1000000) { @@ -496,8 +498,13 @@ php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned po /* attempt to bind */ -#ifdef SO_REUSEADDR - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&sockoptval, sizeof(sockoptval)); + if (sockopts & STREAM_SOCKOP_SO_REUSEADDR) { + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&sockoptval, sizeof(sockoptval)); + } +#ifdef PHP_WIN32 + else { + setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&sockoptval, sizeof(sockoptval)); + } #endif #ifdef IPV6_V6ONLY if (sockopts & STREAM_SOCKOP_IPV6_V6ONLY) { @@ -507,7 +514,13 @@ php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned po #endif #ifdef SO_REUSEPORT if (sockopts & STREAM_SOCKOP_SO_REUSEPORT) { +# ifdef SO_REUSEPORT_LB + /* Historically, SO_REUSEPORT on FreeBSD predates Linux version, however does not + * involve load balancing grouping thus SO_REUSEPORT_LB is the genuine equivalent.*/ + setsockopt(sock, SOL_SOCKET, SO_REUSEPORT_LB, (char*)&sockoptval, sizeof(sockoptval)); +# else setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (char*)&sockoptval, sizeof(sockoptval)); +# endif } #endif #ifdef SO_BROADCAST @@ -1036,6 +1049,28 @@ PHPAPI socklen_t php_sockaddr_size(php_sockaddr_storage *addr) } /* }}} */ +#ifdef PHP_WIN32 +char *php_socket_strerror_s(long err, char *buf, size_t bufsize) +{ + if (buf == NULL) { + char ebuf[1024]; + errno_t res = strerror_s(ebuf, sizeof(ebuf), err); + if (res == 0) { + buf = estrdup(ebuf); + } else { + buf = estrdup("Unknown error"); + } + } else { + errno_t res = strerror_s(buf, bufsize, err); + if (res != 0) { + strncpy(buf, "Unknown error", bufsize); + buf[bufsize?(bufsize-1):0] = 0; + } + } + return buf; +} +#endif + /* Given a socket error code, if buf == NULL: * emallocs storage for the error message and returns * else @@ -1045,16 +1080,40 @@ PHPAPI socklen_t php_sockaddr_size(php_sockaddr_storage *addr) PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize) { #ifndef PHP_WIN32 - char *errstr; - - errstr = strerror(err); +# ifdef HAVE_STRERROR_R + if (buf == NULL) { + char ebuf[1024]; +# ifdef STRERROR_R_CHAR_P + char *errstr = strerror_r(err, ebuf, sizeof(ebuf)); + buf = estrdup(errstr); +# else + int res = (int) strerror_r(err, ebuf, sizeof(ebuf)); + if (res == 0) { + buf = estrdup(ebuf); + } else { + buf = estrdup("Unknown error"); + } +# endif + } else { +# ifdef STRERROR_R_CHAR_P + buf = strerror_r(err, buf, bufsize); +# else + int res = (int) strerror_r(err, buf, bufsize); + if (res != 0) { + strncpy(buf, "Unknown error", bufsize); + buf[bufsize?(bufsize-1):0] = 0; + } +# endif + } +# else + char *errstr = strerror(err); if (buf == NULL) { buf = estrdup(errstr); } else { strncpy(buf, errstr, bufsize); buf[bufsize?(bufsize-1):0] = 0; } - return buf; +# endif #else char *sysbuf = php_win32_error_to_msg(err); if (!sysbuf[0]) { @@ -1069,9 +1128,8 @@ PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize) } php_win32_error_msg_free(sysbuf); - - return buf; #endif + return buf; } /* }}} */ @@ -1079,9 +1137,22 @@ PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize) PHPAPI zend_string *php_socket_error_str(long err) { #ifndef PHP_WIN32 - char *errstr; - - errstr = strerror(err); +# ifdef HAVE_STRERROR_R + char ebuf[1024]; +# ifdef STRERROR_R_CHAR_P + char *errstr = strerror_r(err, ebuf, sizeof(ebuf)); +# else + const char *errstr; + int res = (int) strerror_r(err, ebuf, sizeof(ebuf)); + if (res == 0) { + errstr = ebuf; + } else { + errstr = "Unknown error"; + } +# endif +# else + char *errstr = strerror(err); +# endif return zend_string_init(errstr, strlen(errstr), 0); #else zend_string *ret; @@ -1109,7 +1180,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 c75b09e86c18b..c90e4426d6cde 100644 --- a/main/output.c +++ b/main/output.c @@ -187,8 +187,12 @@ PHPAPI void php_output_deactivate(void) /* release all output handlers */ if (OG(handlers).elements) { while ((handler = zend_stack_top(&OG(handlers)))) { - php_output_handler_free(handler); zend_stack_del_top(&OG(handlers)); + /* It's possible to start a new output handler and mark it as active, + * however this loop will destroy all active handlers. */ + OG(active) = NULL; + ZEND_ASSERT(OG(running) == NULL && "output is deactivated therefore running should stay NULL"); + php_output_handler_free(handler); } } zend_stack_destroy(&OG(handlers)); @@ -718,10 +722,11 @@ PHPAPI void php_output_handler_dtor(php_output_handler *handler) * Destroy and free an output handler */ PHPAPI void php_output_handler_free(php_output_handler **h) { - if (*h) { - php_output_handler_dtor(*h); - efree(*h); + php_output_handler *handler = *h; + if (handler) { *h = NULL; + php_output_handler_dtor(handler); + efree(handler); } } /* }}} */ @@ -956,7 +961,6 @@ 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); @@ -969,17 +973,10 @@ static inline php_output_handler_status_t php_output_handler_op(php_output_handl handler->func.user->fci.retval = &retval; 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) { + if (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; @@ -987,18 +984,9 @@ static inline php_output_handler_status_t php_output_handler_op(php_output_handl 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) + 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 diff --git a/main/php.h b/main/php.h index 5c0b89c328375..32222cfca94e0 100644 --- a/main/php.h +++ b/main/php.h @@ -22,8 +22,7 @@ #include #endif -#define PHP_API_VERSION 20240925 -#define PHP_HAVE_STREAMS +#define PHP_API_VERSION 20250926 #define YYDEBUG 0 #define PHP_DEFAULT_CHARSET "UTF-8" 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..45e1e1902631d 100644 --- a/main/php_network.h +++ b/main/php_network.h @@ -64,6 +64,11 @@ * unless buf is not NULL. * Also works sensibly for win32 */ BEGIN_EXTERN_C() +#ifdef PHP_WIN32 +char *php_socket_strerror_s(long err, char *buf, size_t bufsize); +#else +#define php_socket_strerror_s php_socket_strerror +#endif PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize); PHPAPI zend_string *php_socket_error_str(long err); END_EXTERN_C() @@ -118,7 +123,7 @@ typedef int php_socket_t; #define STREAM_SOCKOP_IPV6_V6ONLY (1 << 3) #define STREAM_SOCKOP_IPV6_V6ONLY_ENABLED (1 << 4) #define STREAM_SOCKOP_TCP_NODELAY (1 << 5) - +#define STREAM_SOCKOP_SO_REUSEADDR (1 << 6) /* uncomment this to debug poll(2) emulation on systems that have poll(2) */ /* #define PHP_USE_POLL_2_EMULATION 1 */ @@ -313,9 +318,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_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..971e1c77ea9f4 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)); @@ -745,7 +745,7 @@ static inline void php_register_server_variables(void) /* store request init time */ ZVAL_DOUBLE(&tmp, sapi_get_request_time()); php_register_variable_quick("REQUEST_TIME_FLOAT", sizeof("REQUEST_TIME_FLOAT")-1, &tmp, ht); - ZVAL_LONG(&tmp, zend_dval_to_lval(Z_DVAL(tmp))); + ZVAL_LONG(&tmp, zend_dval_to_lval_silent(Z_DVAL(tmp))); php_register_variable_quick("REQUEST_TIME", sizeof("REQUEST_TIME")-1, &tmp, ht); } /* }}} */ @@ -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) @@ -973,7 +975,7 @@ void php_startup_auto_globals(void) zend_register_auto_global(zend_string_init_interned("_GET", sizeof("_GET")-1, 1), 0, php_auto_globals_create_get); zend_register_auto_global(zend_string_init_interned("_POST", sizeof("_POST")-1, 1), 0, php_auto_globals_create_post); zend_register_auto_global(zend_string_init_interned("_COOKIE", sizeof("_COOKIE")-1, 1), 0, php_auto_globals_create_cookie); - zend_register_auto_global(ZSTR_KNOWN(ZEND_STR_AUTOGLOBAL_SERVER), PG(auto_globals_jit), php_auto_globals_create_server); + zend_register_auto_global(ZSTR_KNOWN(ZEND_STR_AUTOGLOBAL_SERVER), PG(auto_globals_jit) && (SG(request_info).argc || !PG(register_argc_argv)), php_auto_globals_create_server); zend_register_auto_global(ZSTR_KNOWN(ZEND_STR_AUTOGLOBAL_ENV), PG(auto_globals_jit), php_auto_globals_create_env); zend_register_auto_global(ZSTR_KNOWN(ZEND_STR_AUTOGLOBAL_REQUEST), PG(auto_globals_jit), php_auto_globals_create_request); zend_register_auto_global(zend_string_init_interned("_FILES", sizeof("_FILES")-1, 1), 0, php_auto_globals_create_files); 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/php_version.h b/main/php_version.h index 269397ba11e18..fa9484cbe1502 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -1,8 +1,8 @@ /* automatically generated by configure */ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 -#define PHP_MINOR_VERSION 5 +#define PHP_MINOR_VERSION 6 #define PHP_RELEASE_VERSION 0 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.5.0-dev" -#define PHP_VERSION_ID 80500 +#define PHP_VERSION "8.6.0-dev" +#define PHP_VERSION_ID 80600 diff --git a/main/rfc1867.c b/main/rfc1867.c index 84b8788bbf7c3..f6ffb6fabc7f1 100644 --- a/main/rfc1867.c +++ b/main/rfc1867.c @@ -1048,7 +1048,8 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) if (wlen == (size_t)-1) { /* write failed */ #if DEBUG_FILE_UPLOAD - sapi_module.sapi_error(E_NOTICE, "write() failed - %s", strerror(errno)); + char errstr[256]; + sapi_module.sapi_error(E_NOTICE, "write() failed - %s", php_socket_strerror_s(errno, errstr, sizeof(errstr))); #endif cancel_upload = PHP_UPLOAD_ERROR_F; } else if (wlen < blen) { 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..b63d789190792 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; @@ -173,6 +171,7 @@ PHPAPI void php_stream_bucket_prepend(php_stream_bucket_brigade *brigade, php_st PHPAPI void php_stream_bucket_append(php_stream_bucket_brigade *brigade, php_stream_bucket *bucket) { + /* TODO: this was added as a bad workaround for bug #35916 and should be removed in the future. */ if (brigade->tail == bucket) { return; } @@ -282,7 +281,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 +293,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 +300,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 +351,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 +399,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 +407,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 +484,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 f61604c929d78..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); - zend_fcall_info_cache *fcc; + 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/plain_wrapper.c b/main/streams/plain_wrapper.c index a8fd70b8d6ac2..688d271db8147 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -43,6 +43,10 @@ # include #endif +#ifdef __linux__ +# include +#endif + #define php_stream_fopen_from_fd_int(fd, mode, persistent_id) _php_stream_fopen_from_fd_int((fd), (mode), (persistent_id) STREAMS_CC) #define php_stream_fopen_from_fd_int_rel(fd, mode, persistent_id) _php_stream_fopen_from_fd_int((fd), (mode), (persistent_id) STREAMS_REL_CC) #define php_stream_fopen_from_file_int(file, mode) _php_stream_fopen_from_file_int((file), (mode) STREAMS_CC) @@ -255,7 +259,28 @@ PHPAPI php_stream *_php_stream_fopen_tmpfile(int dummy STREAMS_DC) static void detect_is_seekable(php_stdio_stream_data *self) { #if defined(S_ISFIFO) && defined(S_ISCHR) if (self->fd >= 0 && do_fstat(self, 0) == 0) { +#ifdef __linux__ + if (S_ISCHR(self->sb.st_mode)) { + /* Some character devices are exceptions, check their major/minor ID + * https://www.kernel.org/doc/Documentation/admin-guide/devices.txt */ + if (major(self->sb.st_rdev) == 1) { + unsigned m = minor(self->sb.st_rdev); + self->is_seekable = + m == 1 || /* /dev/mem */ + m == 2 || /* /dev/kmem */ + m == 3 || /* /dev/null */ + m == 4 || /* /dev/port (seekable, offset = I/O port) */ + m == 5 || /* /dev/zero */ + m == 7; /* /dev/full */ + } else { + self->is_seekable = false; + } + } else { + self->is_seekable = !S_ISFIFO(self->sb.st_mode); + } +#else self->is_seekable = !(S_ISFIFO(self->sb.st_mode) || S_ISCHR(self->sb.st_mode)); +#endif self->is_pipe = S_ISFIFO(self->sb.st_mode); } #elif defined(PHP_WIN32) @@ -368,7 +393,9 @@ static ssize_t php_stdiop_write(php_stream *stream, const char *buf, size_t coun return bytes_written; } if (!(stream->flags & PHP_STREAM_FLAG_SUPPRESS_ERRORS)) { - php_error_docref(NULL, E_NOTICE, "Write of %zu bytes failed with errno=%d %s", count, errno, strerror(errno)); + char errstr[256]; + php_error_docref(NULL, E_NOTICE, "Write of %zu bytes failed with errno=%d %s", + count, errno, php_socket_strerror_s(errno, errstr, sizeof(errstr))); } } } else { @@ -444,7 +471,9 @@ static ssize_t php_stdiop_read(php_stream *stream, char *buf, size_t count) /* TODO: Should this be treated as a proper error or not? */ } else { if (!(stream->flags & PHP_STREAM_FLAG_SUPPRESS_ERRORS)) { - php_error_docref(NULL, E_NOTICE, "Read of %zu bytes failed with errno=%d %s", count, errno, strerror(errno)); + char errstr[256]; + php_error_docref(NULL, E_NOTICE, "Read of %zu bytes failed with errno=%d %s", + count, errno, php_socket_strerror_s(errno, errstr, sizeof(errstr))); } /* TODO: Remove this special-case? */ @@ -1281,7 +1310,9 @@ static int php_plain_files_unlink(php_stream_wrapper *wrapper, const char *url, ret = VCWD_UNLINK(url); if (ret == -1) { if (options & REPORT_ERRORS) { - php_error_docref1(NULL, url, E_WARNING, "%s", strerror(errno)); + char errstr[256]; + php_error_docref1(NULL, url, E_WARNING, "%s", + php_socket_strerror_s(errno, errstr, sizeof(errstr))); } return 0; } @@ -1327,6 +1358,7 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f if (ret == -1) { #ifndef PHP_WIN32 + char errstr[256]; # ifdef EXDEV if (errno == EXDEV) { zend_stat_t sb; @@ -1347,7 +1379,8 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f * access to the file in the meantime. */ if (VCWD_CHOWN(url_to, sb.st_uid, sb.st_gid)) { - php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); + php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", + php_socket_strerror_s(errno, errstr, sizeof(errstr))); if (errno != EPERM) { success = 0; } @@ -1355,7 +1388,8 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f if (success) { if (VCWD_CHMOD(url_to, sb.st_mode)) { - php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); + php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", + php_socket_strerror_s(errno, errstr, sizeof(errstr))); if (errno != EPERM) { success = 0; } @@ -1366,10 +1400,12 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f VCWD_UNLINK(url_from); } } else { - php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); + php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", + php_socket_strerror_s(errno, errstr, sizeof(errstr))); } } else { - php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); + php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", + php_socket_strerror_s(errno, errstr, sizeof(errstr))); } # if !defined(ZTS) && !defined(TSRM_WIN32) umask(oldmask); @@ -1382,7 +1418,8 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f #ifdef PHP_WIN32 php_win32_docref2_from_error(GetLastError(), url_from, url_to); #else - php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); + php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", + php_socket_strerror_s(errno, errstr, sizeof(errstr))); #endif return 0; } @@ -1462,11 +1499,12 @@ static int php_plain_files_mkdir(php_stream_wrapper *wrapper, const char *dir, i if (!p) { p = buf; } + char errstr[256]; while (true) { int ret = VCWD_MKDIR(buf, (mode_t) mode); if (ret < 0 && errno != EEXIST) { if (options & REPORT_ERRORS) { - php_error_docref(NULL, E_WARNING, "%s", strerror(errno)); + php_error_docref(NULL, E_WARNING, "%s", php_socket_strerror_s(errno, errstr, sizeof(errstr))); } return 0; } @@ -1486,7 +1524,7 @@ static int php_plain_files_mkdir(php_stream_wrapper *wrapper, const char *dir, i /* issue a warning to client when the last directory was created failed */ if (ret < 0) { if (options & REPORT_ERRORS) { - php_error_docref(NULL, E_WARNING, "%s", strerror(errno)); + php_error_docref(NULL, E_WARNING, "%s", php_socket_strerror_s(errno, errstr, sizeof(errstr))); } return 0; } @@ -1505,15 +1543,16 @@ static int php_plain_files_rmdir(php_stream_wrapper *wrapper, const char *url, i return 0; } + char errstr[256]; #ifdef PHP_WIN32 if (!php_win32_check_trailing_space(url, strlen(url))) { - php_error_docref1(NULL, url, E_WARNING, "%s", strerror(ENOENT)); + php_error_docref1(NULL, url, E_WARNING, "%s", php_socket_strerror_s(ENOENT, errstr, sizeof(errstr))); return 0; } #endif if (VCWD_RMDIR(url) < 0) { - php_error_docref1(NULL, url, E_WARNING, "%s", strerror(errno)); + php_error_docref1(NULL, url, E_WARNING, "%s", php_socket_strerror_s(errno, errstr, sizeof(errstr))); return 0; } @@ -1532,10 +1571,11 @@ static int php_plain_files_metadata(php_stream_wrapper *wrapper, const char *url #endif mode_t mode; int ret = 0; + char errstr[256]; #ifdef PHP_WIN32 if (!php_win32_check_trailing_space(url, strlen(url))) { - php_error_docref1(NULL, url, E_WARNING, "%s", strerror(ENOENT)); + php_error_docref1(NULL, url, E_WARNING, "%s", php_socket_strerror_s(ENOENT, errstr, sizeof(errstr))); return 0; } #endif @@ -1554,7 +1594,8 @@ static int php_plain_files_metadata(php_stream_wrapper *wrapper, const char *url if (VCWD_ACCESS(url, F_OK) != 0) { FILE *file = VCWD_FOPEN(url, "w"); if (file == NULL) { - php_error_docref1(NULL, url, E_WARNING, "Unable to create file %s because %s", url, strerror(errno)); + php_error_docref1(NULL, url, E_WARNING, "Unable to create file %s because %s", url, + php_socket_strerror_s(errno, errstr, sizeof(errstr))); return 0; } fclose(file); @@ -1597,7 +1638,8 @@ static int php_plain_files_metadata(php_stream_wrapper *wrapper, const char *url return 0; } if (ret == -1) { - php_error_docref1(NULL, url, E_WARNING, "Operation failed: %s", strerror(errno)); + php_error_docref1(NULL, url, E_WARNING, "Operation failed: %s", + php_socket_strerror_s(errno, errstr, sizeof(errstr))); return 0; } php_clear_stat_cache(0, NULL, 0); diff --git a/main/streams/streams.c b/main/streams/streams.c index 2eef790863f61..85d2947c28a6c 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) { @@ -154,6 +155,7 @@ static void php_stream_display_wrapper_errors(php_stream_wrapper *wrapper, const { char *tmp; char *msg; + char errstr[256]; int free_msg = 0; if (EG(exception)) { @@ -203,7 +205,7 @@ static void php_stream_display_wrapper_errors(php_stream_wrapper *wrapper, const free_msg = 1; } else { if (wrapper == &php_plain_files_wrapper) { - msg = strerror(errno); /* TODO: not ts on linux */ + msg = php_socket_strerror_s(errno, errstr, sizeof(errstr)); } else { msg = "operation failed"; } @@ -630,6 +632,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 +888,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 +901,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 +1049,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 +1226,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 +1246,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 +1271,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; @@ -1280,7 +1296,7 @@ PHPAPI int _php_stream_flush(php_stream *stream, int closing) { int ret = 0; - if (stream->writefilters.head) { + if (stream->writefilters.head && stream->ops->write) { _php_stream_write_filtered(stream, NULL, 0, closing ? PSFS_FLAG_FLUSH_CLOSE : PSFS_FLAG_FLUSH_INC ); } @@ -1340,7 +1356,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 +1545,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 +1592,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 +1614,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 +1884,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 +1918,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 +1988,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 +2036,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 +2056,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)=='/') { @@ -2205,7 +2218,6 @@ PHPAPI php_stream *_php_stream_open_wrapper_ex(const char *path, const char *mod int persistent = options & STREAM_OPEN_PERSISTENT; zend_string *path_str = NULL; zend_string *resolved_path = NULL; - char *copy_of_path = NULL; if (opened_path) { if (options & STREAM_OPEN_FOR_ZEND_STREAM) { @@ -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); @@ -2282,8 +2294,7 @@ PHPAPI php_stream *_php_stream_open_wrapper_ex(const char *path, const char *mod if (stream->orig_path) { pefree(stream->orig_path, persistent); } - copy_of_path = pestrdup(path, persistent); - stream->orig_path = copy_of_path; + stream->orig_path = pestrdup(path, persistent); #if ZEND_DEBUG stream->open_filename = __zend_orig_filename ? __zend_orig_filename : __zend_filename; stream->open_lineno = __zend_orig_lineno ? __zend_orig_lineno : __zend_lineno; @@ -2342,11 +2353,6 @@ PHPAPI php_stream *_php_stream_open_wrapper_ex(const char *path, const char *mod } } php_stream_tidy_wrapper_error_log(wrapper); -#if ZEND_DEBUG - if (stream == NULL && copy_of_path != NULL) { - pefree(copy_of_path, persistent); - } -#endif if (resolved_path) { zend_string_release_ex(resolved_path, 0); } @@ -2416,7 +2422,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 +2466,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..f5e25aa96c772 100644 --- a/main/streams/userspace.c +++ b/main/streams/userspace.c @@ -37,7 +37,6 @@ static int le_protocols; struct php_user_stream_wrapper { php_stream_wrapper wrapper; - char * protoname; zend_class_entry *ce; zend_resource *resource; }; @@ -72,7 +71,6 @@ static void stream_wrapper_dtor(zend_resource *rsrc) { struct php_user_stream_wrapper * uwrap = (struct php_user_stream_wrapper*)rsrc->ptr; - efree(uwrap->protoname); efree(uwrap); } @@ -251,13 +249,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 +286,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 +311,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 (zend_is_true(&zretval)) { /* the stream is now open! */ stream = php_stream_alloc_rel(&php_stream_userspace_ops, us, 0, mode); @@ -355,6 +352,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 +361,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 +388,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 +401,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 (zend_is_true(&zretval)) { /* the stream is now open! */ stream = php_stream_alloc_rel(&php_stream_userspace_dir_ops, us, 0, mode); @@ -438,22 +438,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; } @@ -473,7 +466,6 @@ PHP_FUNCTION(stream_wrapper_register) uwrap = (struct php_user_stream_wrapper *)ecalloc(1, sizeof(*uwrap)); uwrap->ce = ce; - uwrap->protoname = estrndup(ZSTR_VAL(protocol), ZSTR_LEN(protocol)); uwrap->wrapper.wops = &user_stream_wops; uwrap->wrapper.abstract = uwrap; uwrap->wrapper.is_url = ((flags & PHP_STREAM_IS_URL) != 0); @@ -562,38 +554,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 */ @@ -604,48 +599,43 @@ static ssize_t php_userstreamop_write(php_stream *stream, const char *buf, size_ didwrite = count; } - zval_ptr_dtor(&retval); - return didwrite; } 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 +653,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); - - if (EG(exception)) { - stream->eof = 1; - return -1; - } + 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 (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 (zend_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 +708,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); - - call_result = call_method_if_exists(&us->object, &func_name, &retval, 0, NULL); + 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); - 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 && zend_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,8 +750,9 @@ static int php_userstreamop_seek(php_stream *stream, zend_off_t offset, int when zval_ptr_dtor(&retval); - return -1; - } else if (call_result == SUCCESS && Z_TYPE(retval) != IS_UNDEF && zval_is_true(&retval)) { + ret = -1; + goto out; + } else if (call_result == SUCCESS && Z_TYPE(retval) != IS_UNDEF && zend_is_true(&retval)) { ret = 0; } else { ret = -1; @@ -773,18 +762,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 +781,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 +829,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; - - case PHP_STREAM_OPTION_TRUNCATE_API: - ZVAL_STRINGL(&func_name, USERSTREAM_TRUNCATE, sizeof(USERSTREAM_TRUNCATE)-1); + default: + // TODO: Warn on invalid option value? + ; + } + ZVAL_LONG(&zlock, lock); - 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; + /* 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); - 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 +1075,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 zend_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 +1098,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 +1113,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 zend_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 +1136,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 +1152,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 zend_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 +1174,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 +1189,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 zend_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 +1211,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 +1236,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 +1250,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 zend_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 +1274,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 +1377,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 +1393,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 +1409,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 +1449,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 8623c11be004c..db35a9b7952c8 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: @@ -678,9 +678,10 @@ static inline int php_tcp_sockop_bind(php_stream *stream, php_netstream_data_t * if (sock->socket == SOCK_ERR) { if (xparam->want_errortext) { + char errstr[256]; xparam->outputs.error_text = strpprintf(0, "Failed to create unix%s socket %s", stream->ops == &php_stream_unix_socket_ops ? "" : "datagram", - strerror(errno)); + php_socket_strerror_s(errno, errstr, sizeof(errstr))); } return -1; } @@ -717,6 +718,16 @@ static inline int php_tcp_sockop_bind(php_stream *stream, php_netstream_data_t * } #endif +#ifdef SO_REUSEADDR + /* SO_REUSEADDR is enabled by default so this option is just to disable it if set to false. */ + if (!PHP_STREAM_CONTEXT(stream) + || (tmpzval = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "so_reuseaddr")) == NULL + || zend_is_true(tmpzval) + ) { + sockopts |= STREAM_SOCKOP_SO_REUSEADDR; + } +#endif + #ifdef SO_BROADCAST if (stream->ops == &php_stream_udp_socket_ops /* SO_BROADCAST is only applicable for UDP */ && PHP_STREAM_CONTEXT(stream) @@ -857,7 +868,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; @@ -869,7 +879,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, @@ -878,14 +888,14 @@ static inline int php_tcp_sockop_accept(php_stream *stream, php_netstream_data_t &xparam->outputs.error_code, nodelay); - if (clisock >= 0) { + if (clisock != SOCK_ERR) { php_netstream_data_t *clisockdata = (php_netstream_data_t*) emalloc(sizeof(*clisockdata)); memcpy(clisockdata, sock, sizeof(*clisockdata)); 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+"); @@ -963,7 +973,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 6ef1f940b2f7e..6f93f440112ea 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 @@ -675,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 @@ -824,10 +807,10 @@ enable_dl = Off ;fastcgi.impersonate = 1 ; Prevent decoding of SCRIPT_FILENAME when using Apache ProxyPass or -; ProxyPassMatch. This should only be used if script file paths are already -; stored in an encoded format on the file system. -; Default is 0. -;fastcgi.script_path_encoded = 1 +; ProxyPassMatch. This should be used if script file paths are not stored +; in an encoded format on the file system. +; Default is 1. +;fastcgi.script_path_encoded = 0 ; Disable logging through FastCGI connection. PHP's default behavior is to enable ; this feature. @@ -965,8 +948,6 @@ default_socket_timeout = 60 ;extension=xsl ;extension=zip -;zend_extension=opcache - ;;;;;;;;;;;;;;;;;;; ; Module Settings ; ;;;;;;;;;;;;;;;;;;; @@ -1022,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 @@ -1101,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 = @@ -1324,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 diff --git a/php.ini-production b/php.ini-production index d1b25a34a487f..9aafad21e9c74 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 @@ -677,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 @@ -826,10 +809,10 @@ enable_dl = Off ;fastcgi.impersonate = 1 ; Prevent decoding of SCRIPT_FILENAME when using Apache ProxyPass or -; ProxyPassMatch. This should only be used if script file paths are already -; stored in an encoded format on the file system. -; Default is 0. -;fastcgi.script_path_encoded = 1 +; ProxyPassMatch. This should be used if script file paths are not stored +; in an encoded format on the file system. +; Default is 1. +;fastcgi.script_path_encoded = 0 ; Disable logging through FastCGI connection. PHP's default behavior is to enable ; this feature. @@ -967,8 +950,6 @@ default_socket_timeout = 60 ;extension=xsl ;extension=zip -;zend_extension=opcache - ;;;;;;;;;;;;;;;;;;; ; Module Settings ; ;;;;;;;;;;;;;;;;;;; @@ -1024,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 @@ -1103,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 = @@ -1326,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 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..d0befa3738df1 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', @@ -649,6 +648,12 @@ function main(): void $environment['SKIP_ONLINE_TESTS'] = $online ? '0' : '1'; } + if (!defined('STDIN') || !stream_isatty(STDIN) + || !defined('STDOUT') || !stream_isatty(STDOUT) + || !defined('STDERR') || !stream_isatty(STDERR)) { + $environment['SKIP_IO_CAPTURE_TESTS'] = '1'; + } + if ($selected_tests && count($test_files) === 0) { echo "No tests found.\n"; return; @@ -688,6 +693,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); @@ -2802,6 +2811,11 @@ function is_flaky(TestFile $test): bool if ($test->hasSection('FLAKY')) { return true; } + if ($test->hasSection('SKIPIF')) { + if (strpos($test->getSection('SKIPIF'), 'SKIP_PERF_SENSITIVE') !== false) { + return true; + } + } if (!$test->hasSection('FILE')) { return false; } 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/auto_globals_no_jit.phpt b/sapi/cgi/tests/auto_globals_no_jit.phpt new file mode 100644 index 0000000000000..21af9e038d2a5 --- /dev/null +++ b/sapi/cgi/tests/auto_globals_no_jit.phpt @@ -0,0 +1,18 @@ +--TEST-- +CGI with auto_globals_jit=0 +--INI-- +auto_globals_jit=0 +variables_order="EGPCS" +--CGI-- +--ENV-- +FOO=BAR +--FILE-- + +--EXPECT-- +string(3) "BAR" +string(3) "BAR" +string(3) "BAR" 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..046e2174dc1d8 100644 --- a/sapi/cli/php_cli_server.c +++ b/sapi/cli/php_cli_server.c @@ -304,7 +304,7 @@ static int status_comp(const void *a, const void *b) /* {{{ */ static const char *get_status_string(int code) /* {{{ */ { - http_response_status_code_pair needle = {code, NULL}, + const http_response_status_code_pair needle = {code, NULL}, *result = NULL; result = bsearch(&needle, http_status_map, http_status_map_len, sizeof(needle), status_comp); @@ -395,13 +395,7 @@ static void append_essential_headers(smart_str* buffer, php_cli_server_client *c static const char *get_mime_type(const php_cli_server *server, const char *ext, size_t ext_len) /* {{{ */ { - char *ret; - ALLOCA_FLAG(use_heap) - char *ext_lower = do_alloca(ext_len + 1, use_heap); - zend_str_tolower_copy(ext_lower, ext, ext_len); - ret = zend_hash_str_find_ptr(&server->extension_mime_types, ext_lower, ext_len); - free_alloca(ext_lower, use_heap); - return (const char*)ret; + return zend_hash_str_find_ptr_lc(&server->extension_mime_types, ext, ext_len); } /* }}} */ PHP_FUNCTION(apache_request_headers) /* {{{ */ @@ -2530,6 +2524,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 +2557,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); } @@ -2707,14 +2706,16 @@ static zend_result php_cli_server_do_event_for_each_fd_callback(void *_params, p struct sockaddr *sa = pemalloc(server->socklen, 1); client_sock = accept(server->server_sock, sa, &socklen); if (!ZEND_VALID_SOCKET(client_sock)) { - int err = php_socket_errno(); - if (err != SOCK_EAGAIN && php_cli_server_log_level >= PHP_CLI_SERVER_LOG_ERROR) { + pefree(sa, 1); + if (php_socket_errno() == SOCK_EAGAIN) { + return SUCCESS; + } + if (php_cli_server_log_level >= PHP_CLI_SERVER_LOG_ERROR) { char *errstr = php_socket_strerror(php_socket_errno(), NULL, 0); php_cli_server_logf(PHP_CLI_SERVER_LOG_ERROR, "Failed to accept a client (reason: %s)", errstr); efree(errstr); } - pefree(sa, 1); return FAILURE; } if (SUCCESS != php_set_sock_blocking(client_sock, 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/gh18582.phpt b/sapi/cli/tests/gh18582.phpt new file mode 100644 index 0000000000000..0c3cebf71c3d1 --- /dev/null +++ b/sapi/cli/tests/gh18582.phpt @@ -0,0 +1,40 @@ +--TEST-- +GH-18582: Allow http_response_code() to clear HTTP start-line +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +HTTP/1.1 404 Not Found +Host: %s +Date: %s +Connection: close +X-Powered-By: %s +Content-type: text/html; charset=UTF-8 + +
+Warning: http_response_code(): Calling http_response_code() after header('HTTP/...') has no effect in %s on line 3
+404 +403 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/cli/tests/php_cli_server_pdeathsig.phpt b/sapi/cli/tests/php_cli_server_pdeathsig.phpt index 8b70bbcad4927..66a76a84ccaf6 100644 --- a/sapi/cli/tests/php_cli_server_pdeathsig.phpt +++ b/sapi/cli/tests/php_cli_server_pdeathsig.phpt @@ -9,6 +9,7 @@ if (!(str_contains(PHP_OS, 'Linux') || str_contains(PHP_OS, 'FreeBSD'))) { die('skip PDEATHSIG is only supported on Linux and FreeBSD'); } if (@file_exists('/.dockerenv')) die("skip Broken in Docker"); +if (!shell_exec("which pgrep")) die("skip Missing pgrep command"); ?> --FILE-- 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_main.c b/sapi/fpm/fpm/fpm_main.c index 8af1e51d512fb..cc89b8c07c155 100644 --- a/sapi/fpm/fpm/fpm_main.c +++ b/sapi/fpm/fpm/fpm_main.c @@ -702,7 +702,7 @@ static void php_cgi_ini_activate_user_config(char *path, int path_len, const cha } /* }}} */ -static int sapi_cgi_activate(void) /* {{{ */ +static int sapi_cgi_pre_request_init(void) { fcgi_request *request = (fcgi_request*) SG(server_context); char *path, *doc_root, *server_name; @@ -766,6 +766,11 @@ static int sapi_cgi_activate(void) /* {{{ */ return SUCCESS; } + +static int sapi_cgi_activate(void) /* {{{ */ +{ + return SUCCESS; +} /* }}} */ static int sapi_cgi_deactivate(void) /* {{{ */ @@ -1430,7 +1435,7 @@ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("cgi.nph", "0", PHP_INI_ALL, OnUpdateBool, nph, php_cgi_globals_struct, php_cgi_globals) STD_PHP_INI_BOOLEAN("cgi.fix_pathinfo", "1", PHP_INI_SYSTEM, OnUpdateBool, fix_pathinfo, php_cgi_globals_struct, php_cgi_globals) STD_PHP_INI_BOOLEAN("cgi.discard_path", "0", PHP_INI_SYSTEM, OnUpdateBool, discard_path, php_cgi_globals_struct, php_cgi_globals) - STD_PHP_INI_BOOLEAN("fastcgi.script_path_encoded", "0", PHP_INI_SYSTEM, OnUpdateBool, fcgi_script_path_encoded, php_cgi_globals_struct, php_cgi_globals) + STD_PHP_INI_BOOLEAN("fastcgi.script_path_encoded", "1", PHP_INI_SYSTEM, OnUpdateBool, fcgi_script_path_encoded, php_cgi_globals_struct, php_cgi_globals) STD_PHP_INI_BOOLEAN("fastcgi.logging", "1", PHP_INI_SYSTEM, OnUpdateBool, fcgi_logging, php_cgi_globals_struct, php_cgi_globals) STD_PHP_INI_ENTRY("fastcgi.error_header", NULL, PHP_INI_SYSTEM, OnUpdateString, error_header, php_cgi_globals_struct, php_cgi_globals) STD_PHP_INI_ENTRY("fpm.config", NULL, PHP_INI_SYSTEM, OnUpdateString, fpm_config, php_cgi_globals_struct, php_cgi_globals) @@ -1443,7 +1448,7 @@ static void php_cgi_globals_ctor(php_cgi_globals_struct *php_cgi_globals) php_cgi_globals->nph = 0; php_cgi_globals->fix_pathinfo = 1; php_cgi_globals->discard_path = 0; - php_cgi_globals->fcgi_script_path_encoded = 0; + php_cgi_globals->fcgi_script_path_encoded = 1; php_cgi_globals->fcgi_logging = 1; php_cgi_globals->fcgi_logging_request_started = false; zend_hash_init(&php_cgi_globals->user_config_cache, 0, NULL, user_config_cache_entry_dtor, 1); @@ -1600,6 +1605,7 @@ int main(int argc, char *argv[]) sapi_startup(&cgi_sapi_module); cgi_sapi_module.php_ini_path_override = NULL; cgi_sapi_module.php_ini_ignore_cwd = 1; + cgi_sapi_module.pre_request_init = sapi_cgi_pre_request_init; #ifndef HAVE_ATTRIBUTE_WEAK fcgi_set_logger(fpm_fcgi_log); 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/fpm_status.c b/sapi/fpm/fpm/fpm_status.c index 96bdb96e408e8..9cb8731363fa3 100644 --- a/sapi/fpm/fpm/fpm_status.c +++ b/sapi/fpm/fpm/fpm_status.c @@ -47,93 +47,76 @@ int fpm_status_init_child(struct fpm_worker_pool_s *wp) /* {{{ */ int fpm_status_export_to_zval(zval *status) { - struct fpm_scoreboard_s scoreboard, *scoreboard_p; + struct fpm_scoreboard_s *scoreboard_p; + struct fpm_scoreboard_proc_s *proc_p; zval fpm_proc_stats, fpm_proc_stat; time_t now_epoch; struct timeval duration, now; double cpu; int i; - scoreboard_p = fpm_scoreboard_acquire(NULL, 1); - if (!scoreboard_p) { - zlog(ZLOG_NOTICE, "[pool (unknown)] status: scoreboard already in use."); - return -1; - } - - /* copy the scoreboard not to bother other processes */ - scoreboard = *scoreboard_p; - struct fpm_scoreboard_proc_s *procs = safe_emalloc( - sizeof(struct fpm_scoreboard_proc_s), scoreboard.nprocs, 0); - - struct fpm_scoreboard_proc_s *proc_p; - for(i=0; ipool); + add_assoc_string(status, "process-manager", PM2STR( scoreboard_p->pm)); + add_assoc_long(status, "start-time", scoreboard_p->start_epoch); + add_assoc_long(status, "start-since", now_epoch - scoreboard_p->start_epoch); + add_assoc_long(status, "accepted-conn", scoreboard_p->requests); + add_assoc_long(status, "listen-queue", scoreboard_p->lq); + add_assoc_long(status, "max-listen-queue", scoreboard_p->lq_max); + add_assoc_long(status, "listen-queue-len", scoreboard_p->lq_len); + add_assoc_long(status, "idle-processes", scoreboard_p->idle); + add_assoc_long(status, "active-processes", scoreboard_p->active); + add_assoc_long(status, "total-processes", scoreboard_p->idle + scoreboard_p->active); + add_assoc_long(status, "max-active-processes", scoreboard_p->active_max); + add_assoc_long(status, "max-children-reached", scoreboard_p->max_children_reached); + add_assoc_long(status, "slow-requests", scoreboard_p->slow_rq); + add_assoc_long(status, "memory-peak", scoreboard_p->memory_peak); array_init(&fpm_proc_stats); - for(i=0; inprocs; i++) { + proc_p = &scoreboard_p->procs[i]; + if (!proc_p->used) { continue; } - proc_p = &procs[i]; /* prevent NaN */ - if (procs[i].cpu_duration.tv_sec == 0 && procs[i].cpu_duration.tv_usec == 0) { + if (proc_p->cpu_duration.tv_sec == 0 && proc_p->cpu_duration.tv_usec == 0) { cpu = 0.; } else { - cpu = (procs[i].last_request_cpu.tms_utime + procs[i].last_request_cpu.tms_stime + procs[i].last_request_cpu.tms_cutime + procs[i].last_request_cpu.tms_cstime) / fpm_scoreboard_get_tick() / (procs[i].cpu_duration.tv_sec + procs[i].cpu_duration.tv_usec / 1000000.) * 100.; + cpu = (proc_p->last_request_cpu.tms_utime + proc_p->last_request_cpu.tms_stime + proc_p->last_request_cpu.tms_cutime + + proc_p->last_request_cpu.tms_cstime) / fpm_scoreboard_get_tick() / + (proc_p->cpu_duration.tv_sec + proc_p->cpu_duration.tv_usec / 1000000.) * 100.; } array_init(&fpm_proc_stat); - add_assoc_long(&fpm_proc_stat, "pid", procs[i].pid); - add_assoc_string(&fpm_proc_stat, "state", fpm_request_get_stage_name(procs[i].request_stage)); - add_assoc_long(&fpm_proc_stat, "start-time", procs[i].start_epoch); - add_assoc_long(&fpm_proc_stat, "start-since", now_epoch - procs[i].start_epoch); - add_assoc_long(&fpm_proc_stat, "requests", procs[i].requests); - if (procs[i].request_stage == FPM_REQUEST_ACCEPTING) { - duration = procs[i].duration; + add_assoc_long(&fpm_proc_stat, "pid", proc_p->pid); + add_assoc_string(&fpm_proc_stat, "state", fpm_request_get_stage_name(proc_p->request_stage)); + add_assoc_long(&fpm_proc_stat, "start-time", proc_p->start_epoch); + add_assoc_long(&fpm_proc_stat, "start-since", now_epoch - proc_p->start_epoch); + add_assoc_long(&fpm_proc_stat, "requests", proc_p->requests); + if (proc_p->request_stage == FPM_REQUEST_ACCEPTING) { + duration = proc_p->duration; } else { - timersub(&now, &procs[i].accepted, &duration); + timersub(&now, &proc_p->accepted, &duration); } add_assoc_long(&fpm_proc_stat, "request-duration", duration.tv_sec * 1000000UL + duration.tv_usec); - add_assoc_string(&fpm_proc_stat, "request-method", procs[i].request_method[0] != '\0' ? procs[i].request_method : "-"); - add_assoc_string(&fpm_proc_stat, "request-uri", procs[i].request_uri); - add_assoc_string(&fpm_proc_stat, "query-string", procs[i].query_string); - add_assoc_long(&fpm_proc_stat, "request-length", procs[i].content_length); - add_assoc_string(&fpm_proc_stat, "user", procs[i].auth_user[0] != '\0' ? procs[i].auth_user : "-"); - add_assoc_string(&fpm_proc_stat, "script", procs[i].script_filename[0] != '\0' ? procs[i].script_filename : "-"); - add_assoc_double(&fpm_proc_stat, "last-request-cpu", procs[i].request_stage == FPM_REQUEST_ACCEPTING ? cpu : 0.); - add_assoc_long(&fpm_proc_stat, "last-request-memory", procs[i].request_stage == FPM_REQUEST_ACCEPTING ? procs[i].memory : 0); + add_assoc_string(&fpm_proc_stat, "request-method", proc_p->request_method[0] != '\0' ? proc_p->request_method : "-"); + add_assoc_string(&fpm_proc_stat, "request-uri", proc_p->request_uri); + add_assoc_string(&fpm_proc_stat, "query-string", proc_p->query_string); + add_assoc_long(&fpm_proc_stat, "request-length", proc_p->content_length); + add_assoc_string(&fpm_proc_stat, "user", proc_p->auth_user[0] != '\0' ? proc_p->auth_user : "-"); + add_assoc_string(&fpm_proc_stat, "script", proc_p->script_filename[0] != '\0' ? proc_p->script_filename : "-"); + add_assoc_double(&fpm_proc_stat, "last-request-cpu", proc_p->request_stage == FPM_REQUEST_ACCEPTING ? cpu : 0.); + add_assoc_long(&fpm_proc_stat, "last-request-memory", proc_p->request_stage == FPM_REQUEST_ACCEPTING ? proc_p->memory : 0); add_next_index_zval(&fpm_proc_stats, &fpm_proc_stat); } add_assoc_zval(status, "procs", &fpm_proc_stats); - efree(procs); + + fpm_scoreboard_free_copy(scoreboard_p); return 0; } diff --git a/sapi/fpm/fpm/zlog.c b/sapi/fpm/fpm/zlog.c index 39c6eec885bcd..b34d455e6bd6c 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) /* {{{ */ { @@ -451,7 +466,7 @@ static ssize_t zlog_stream_buf_flush(struct zlog_stream *stream) /* {{{ */ } #endif - if (external_logger != NULL) { + if (stream->use_external_logger) { external_logger(stream->flags & ZLOG_LEVEL_MASK, stream->buf.data + stream->prefix_len, stream->len - stream->prefix_len); } @@ -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,23 @@ 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_external_logger = 0; + stream->use_buffer = 1; + stream->use_stderr = fd < 0; + } else { + stream->use_external_logger = external_logger != NULL; + 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 +767,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 +776,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 +785,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 +921,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..8b4a80155f073 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,8 @@ struct zlog_stream { unsigned int msg_quote:1; unsigned int decorate:1; unsigned int is_stdout:1; + unsigned int over_limit:1; + unsigned int use_external_logger:1; int fd; int line; int child_pid; @@ -103,14 +107,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/bug74083-concurrent-reload.phpt b/sapi/fpm/tests/bug74083-concurrent-reload.phpt index ad5d560abae47..f37085d65c4c0 100644 --- a/sapi/fpm/tests/bug74083-concurrent-reload.phpt +++ b/sapi/fpm/tests/bug74083-concurrent-reload.phpt @@ -4,6 +4,7 @@ Concurrent reload signals should not kill PHP-FPM master process. (Bug: #74083) --FILE-- ---FILE-- -start(); -$tester->expectLogStartNotices(); -$tester->request()->expectBody([ - 'bool(false)', - 'bool(true)', - 'string(4) "test"', - 'bool(false)', - 'bool(false)', - 'string(2) "dt"', - 'string(2) "dt"', -]); -$tester->terminate(); -$tester->close(); - -?> -Done ---EXPECT-- -Done ---CLEAN-- - 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_002.phpt b/sapi/fpm/tests/bug75712-getenv-server-vars_002.phpt new file mode 100644 index 0000000000000..b34d936eaf223 --- /dev/null +++ b/sapi/fpm/tests/bug75712-getenv-server-vars_002.phpt @@ -0,0 +1,62 @@ +--TEST-- +FPM: bug75712 - getenv should not read from $_ENV and $_SERVER (register_argc_argv=off) +--SKIPIF-- + +--FILE-- +start(); +$tester->expectLogStartNotices(); +$tester->request()->expectBody([ + 'bool(false)', + 'bool(true)', + 'string(4) "test"', + 'bool(false)', + 'bool(false)', + 'string(2) "dt"', + 'string(2) "dt"', +]); +$tester->terminate(); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/bug76601-reload-child-signals.phpt b/sapi/fpm/tests/bug76601-reload-child-signals.phpt index 1a3e6d2b74fb0..3992f465bb230 100644 --- a/sapi/fpm/tests/bug76601-reload-child-signals.phpt +++ b/sapi/fpm/tests/bug76601-reload-child-signals.phpt @@ -4,6 +4,7 @@ FPM: bug76601 children should not ignore signals during concurrent reloads --FILE-- --FILE-- @@ -18,7 +18,6 @@ pm.start_servers = 1 pm.min_spare_servers = 1 pm.max_spare_servers = 3 php_admin_value[cgi.fix_pathinfo] = yes -php_admin_value[fastcgi.script_path_encoded] = yes EOT; $code = << +--FILE-- +start(['--prefix', $prefix]); +$tester->expectLogStartNotices(); +$response = $tester->request()->expectBody('OK'); +$response->expectNoError(); +$tester->expectAccessLog("'GET /gh19989-access-log-fcgi-stderr.src.php' 200"); +$tester->terminate(); +$tester->expectLogTerminatingNotices(); +$tester->close(); +$tester->checkAccessLog(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/gh8157-user-ini-post.phpt b/sapi/fpm/tests/gh8157-user-ini-post.phpt new file mode 100644 index 0000000000000..db291f76d246f --- /dev/null +++ b/sapi/fpm/tests/gh8157-user-ini-post.phpt @@ -0,0 +1,58 @@ +--TEST-- +FPM: gh8157 - post related INI settings not applied for .user.ini +--SKIPIF-- + +--FILE-- +setUserIni($ini); +$tester->start(); +$tester->expectLogStartNotices(); +$tester + ->request( + headers: [ 'CONTENT_TYPE' => 'application/x-www-form-urlencoded'], + stdin: 'foo=' . str_repeat('a', 20000), + method: 'POST', + ) + ->expectBody([ + 'Warning: PHP Request Startup: POST Content-Length of 20004 bytes exceeds the limit of 10240 bytes in Unknown on line 0', + 'array(0) {', + '}', + ], skipHeadersCheck: true); +$tester->terminate(); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/log-access-extended-limit.phpt b/sapi/fpm/tests/log-access-extended-limit.phpt new file mode 100644 index 0000000000000..99c17f14905f4 --- /dev/null +++ b/sapi/fpm/tests/log-access-extended-limit.phpt @@ -0,0 +1,56 @@ +--TEST-- +FPM: Test extended access log limit +--SKIPIF-- + +--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/response.inc b/sapi/fpm/tests/response.inc index aefd2e027c67d..5e6400e1b4ca1 100644 --- a/sapi/fpm/tests/response.inc +++ b/sapi/fpm/tests/response.inc @@ -119,10 +119,11 @@ class Response extends BaseResponse /** * @param mixed $body * @param string $contentType + * @param bool $skipHeadersCheck * * @return Response */ - public function expectBody($body, $contentType = 'text/html') + public function expectBody($body, $contentType = 'text/html', bool $skipHeadersCheck = false) { if ($multiLine = is_array($body)) { $body = implode("\n", $body); @@ -130,7 +131,7 @@ class Response extends BaseResponse if ( ! $this->checkIfValid()) { $this->error('Response is invalid'); - } elseif ( ! $this->checkDefaultHeaders($contentType)) { + } elseif ( ! $skipHeadersCheck && ! $this->checkDefaultHeaders($contentType)) { $this->error('Response default headers not found'); } elseif ($body !== $this->rawBody) { if ($multiLine) { 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..f39e371ea70fe 100644 --- a/sapi/fpm/www.conf.in +++ b/sapi/fpm/www.conf.in @@ -329,7 +329,7 @@ pm.max_spare_servers = 3 ; it must be associated with embraces to specify the name of the header: ; - %{Content-Type}o ; - %{X-Powered-By}o -; - %{Transfert-Encoding}o +; - %{Transfer-Encoding}o ; - .... ; %p: PID of the child that serviced the request ; %P: PID of the parent of the child that serviced the request @@ -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 081ab4d30e823..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) { @@ -139,33 +147,3 @@ ZEND_ATTRIBUTE_UNUSED static void opcache_invalidate(void) { zval_ptr_dtor(&retval); 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 5014a51cca4f2..80915d0bbc19f 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; } @@ -201,7 +220,9 @@ void fuzzer_request_shutdown(void) zend_gc_collect_cycles(); } zend_end_try(); - php_request_shutdown(NULL); + zend_try { + php_request_shutdown(NULL); + } zend_end_try(); } /* Set up a dummy stack frame so that exceptions may be thrown. */ 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..4ef83be1b9f47 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -493,7 +493,7 @@ PHP_FUNCTION(phpdbg_get_executable) HashTable *files = &PHPDBG_G(file_sources); HashTable files_tmp; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|H", &options) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|h", &options) == FAILURE) { RETURN_THROWS(); } @@ -587,7 +587,7 @@ PHP_FUNCTION(phpdbg_end_oplog) bool by_function = false; bool by_opcode = false; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|H", &options) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|h", &options) == FAILURE) { RETURN_THROWS(); } @@ -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_frame.c b/sapi/phpdbg/phpdbg_frame.c index a8f1bf01433b7..01b19de80a995 100644 --- a/sapi/phpdbg/phpdbg_frame.c +++ b/sapi/phpdbg/phpdbg_frame.c @@ -34,11 +34,7 @@ static inline void phpdbg_append_individual_arg(smart_str *s, uint32_t i, zend_f } if (i < func->common.num_args) { if (arginfo) { - if (func->type == ZEND_INTERNAL_FUNCTION) { - arg_name = (char *) ((zend_internal_arg_info *) &arginfo[i])->name; - } else { - arg_name = ZSTR_VAL(arginfo[i].name); - } + arg_name = ZSTR_VAL(arginfo[i].name); } smart_str_appends(s, arg_name ? arg_name : "?"); smart_str_appendc(s, '='); @@ -213,11 +209,7 @@ static void phpdbg_dump_prototype(zval *tmp) /* {{{ */ char *arg_name = NULL; if (arginfo) { - if (func->type == ZEND_INTERNAL_FUNCTION) { - arg_name = (char *)((zend_internal_arg_info *)&arginfo[j])->name; - } else { - arg_name = ZSTR_VAL(arginfo[j].name); - } + arg_name = ZSTR_VAL(arginfo[j].name); } if (!is_variadic) { diff --git a/sapi/phpdbg/phpdbg_info.c b/sapi/phpdbg/phpdbg_info.c index b329bdac728bb..9c93cd2b88efb 100644 --- a/sapi/phpdbg/phpdbg_info.c +++ b/sapi/phpdbg/phpdbg_info.c @@ -307,7 +307,7 @@ PHPDBG_INFO(literal) /* {{{ */ bool in_executor = PHPDBG_G(in_execution) && EG(current_execute_data) && EG(current_execute_data)->func; if (in_executor || PHPDBG_G(ops)) { zend_op_array *ops = in_executor ? &EG(current_execute_data)->func->op_array : PHPDBG_G(ops); - int literal = 0, count = ops->last_literal - 1; + uint32_t literal = 0, count = ops->last_literal - 1; if (ops->function_name) { if (ops->scope) { 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_utils.c b/sapi/phpdbg/phpdbg_utils.c index 329ee9a8830e3..55d97acc38759 100644 --- a/sapi/phpdbg/phpdbg_utils.c +++ b/sapi/phpdbg/phpdbg_utils.c @@ -612,7 +612,7 @@ int phpdbg_is_auto_global(char *name, int len) { PHPDBG_API bool phpdbg_check_caught_ex(zend_execute_data *execute_data, zend_object *exception) { const zend_op *op; zend_op *cur; - uint32_t op_num, i; + uint32_t op_num; zend_op_array *op_array = &execute_data->func->op_array; if (execute_data->opline >= EG(exception_op) && execute_data->opline < EG(exception_op) + 3 && EG(opline_before_exception)) { @@ -623,7 +623,7 @@ PHPDBG_API bool phpdbg_check_caught_ex(zend_execute_data *execute_data, zend_obj op_num = op - op_array->opcodes; - for (i = 0; i < op_array->last_try_catch && op_array->try_catch_array[i].try_op <= op_num; i++) { + for (uint32_t i = 0; i < op_array->last_try_catch && op_array->try_catch_array[i].try_op <= op_num; i++) { uint32_t catch = op_array->try_catch_array[i].catch_op, finally = op_array->try_catch_array[i].finally_op; if (op_num <= catch || op_num <= finally) { if (finally) { 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/gh17951_runtime_change_6.phpt b/tests/basic/gh17951_runtime_change_6.phpt new file mode 100644 index 0000000000000..0c62b0e837474 --- /dev/null +++ b/tests/basic/gh17951_runtime_change_6.phpt @@ -0,0 +1,19 @@ +--TEST-- +GH-17951 Runtime Change 6 +--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 +Warning: Failed to set memory_limit to 1073741824 bytes. Setting to max_memory_limit instead (currently: 536870912 bytes) in %s on line %d +512M +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/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/lang/033.phpt b/tests/lang/033.phpt index e6254d687b07c..a8a5837a5501e 100644 --- a/tests/lang/033.phpt +++ b/tests/lang/033.phpt @@ -37,7 +37,10 @@ switch ($a): break; endswitch; ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Case statements followed by a semicolon (;) are deprecated, use a colon (:) instead in %s + +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/bug27354.phpt b/tests/lang/bug27354.phpt index 5d18910bc9f32..e3cac1b170238 100644 --- a/tests/lang/bug27354.phpt +++ b/tests/lang/bug27354.phpt @@ -10,7 +10,7 @@ var_dump(-2147483648 % -2); --EXPECTF-- int(0) -Deprecated: Implicit conversion from float -9.223372036860776E+18 to int loses precision in %s on line %d +Warning: The float -9.223372036860776E+18 is not representable as an int, cast occurred in %s on line %d int(0) int(0) int(0) diff --git a/tests/lang/engine_assignExecutionOrder_002.phpt b/tests/lang/engine_assignExecutionOrder_002.phpt index 956e3f9066d3d..a70cd5bafc8f2 100644 --- a/tests/lang/engine_assignExecutionOrder_002.phpt +++ b/tests/lang/engine_assignExecutionOrder_002.phpt @@ -116,6 +116,10 @@ array(3) { int(3000) } L=100 M=200 N=300 + +Warning: Cannot use int as array in %s on line %d + +Warning: Cannot use int as array in %s on line %d O= and P= 10 20 40 50 60 70 80 diff --git a/tests/lang/operators/bitwiseNot_basiclong_64bit.phpt b/tests/lang/operators/bitwiseNot_basiclong_64bit.phpt index 0e701051f5f47..1a1105a557a35 100644 --- a/tests/lang/operators/bitwiseNot_basiclong_64bit.phpt +++ b/tests/lang/operators/bitwiseNot_basiclong_64bit.phpt @@ -52,7 +52,7 @@ int(-4294967294) int(-9223372036854775807) --- testing: 9.2233720368548E+18 --- -Deprecated: Implicit conversion from float 9.223372036854776E+18 to int loses precision in %s on line %d +Warning: The float 9.223372036854776E+18 is not representable as an int, cast occurred in %s on line %d int(9223372036854775807) --- testing: -9223372036854775807 --- int(9223372036854775806) diff --git a/tests/lang/operators/postinc_variationStr.phpt b/tests/lang/operators/postinc_variationStr.phpt index a064b49835333..d5eb58d4ecac7 100644 --- a/tests/lang/operators/postinc_variationStr.phpt +++ b/tests/lang/operators/postinc_variationStr.phpt @@ -28,30 +28,36 @@ float(2.2) --- testing: '-7.7' --- float(-6.7) --- testing: 'abc' --- + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(3) "abd" --- testing: '123abc' --- + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(6) "123abd" --- testing: '123e5' --- float(12300001) --- testing: '123e5xyz' --- + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(8) "123e5xza" --- testing: ' 123abc' --- -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(7) " 123abd" --- testing: '123 abc' --- -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(7) "123 abd" --- testing: '123abc ' --- -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(7) "123abc " --- testing: '3.4a' --- -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) "3.4b" --- testing: 'a5.9' --- -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) "a5.0" diff --git a/tests/lang/operators/preinc_variationStr.phpt b/tests/lang/operators/preinc_variationStr.phpt index bcae316d8f9b7..9b58a95573d7a 100644 --- a/tests/lang/operators/preinc_variationStr.phpt +++ b/tests/lang/operators/preinc_variationStr.phpt @@ -28,48 +28,72 @@ float(2.2) --- testing: '-7.7' --- float(-6.7) --- testing: 'abc' --- + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(3) "abd" --- testing: '123abc' --- + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(6) "123abd" --- testing: '123e5' --- float(12300001) --- testing: '123e5xyz' --- + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(8) "123e5xza" --- testing: ' 123abc' --- -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(7) " 123abd" --- testing: '123 abc' --- -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(7) "123 abd" --- testing: '123abc ' --- -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(7) "123abc " --- testing: '3.4a' --- -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) "3.4b" --- testing: 'a5.9' --- -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) "a5.0" --- testing: 'z' --- + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(2) "aa" --- testing: 'az' --- + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(2) "ba" --- testing: 'zz' --- + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(3) "aaa" --- testing: 'Z' --- + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(2) "AA" --- testing: 'AZ' --- + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(2) "BA" --- testing: 'ZZ' --- + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(3) "AAA" --- testing: '9z' --- + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(3) "10a" --- testing: '19z' --- + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(3) "20a" --- testing: '99z' --- + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(4) "100a" diff --git a/tests/output/gh20352.phpt b/tests/output/gh20352.phpt new file mode 100644 index 0000000000000..16be0b920e80f --- /dev/null +++ b/tests/output/gh20352.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-20352 (UAF in php_output_handler_free via re-entrant ob_start() during error deactivation) +--FILE-- + +--EXPECTF-- +Fatal error: ob_start(): Cannot use output buffering in output buffering display handlers in %s on line %d diff --git a/tests/output/ob_start_basic_002.phpt b/tests/output/ob_start_basic_002.phpt index e9af2b5e1904c..700dab5d3c381 100644 --- a/tests/output/ob_start_basic_002.phpt +++ b/tests/output/ob_start_basic_002.phpt @@ -35,24 +35,19 @@ foreach ($callbacks as $callback) { } ?> ---EXPECTF-- +--EXPECT-- --> 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': - -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 deleted file mode 100644 index eef3fccc77ec0..0000000000000 --- a/tests/output/ob_start_callback_bad_return/exception_handler.phpt +++ /dev/null @@ -1,147 +0,0 @@ ---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 deleted file mode 100644 index 64d7f805687b2..0000000000000 --- a/tests/output/ob_start_callback_bad_return/exception_handler_nested.phpt +++ /dev/null @@ -1,143 +0,0 @@ ---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 deleted file mode 100644 index 32702a58fcc14..0000000000000 --- a/tests/output/ob_start_callback_bad_return/handler_false_removed.phpt +++ /dev/null @@ -1,23 +0,0 @@ ---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 deleted file mode 100644 index 0d87358da1b9d..0000000000000 --- a/tests/output/ob_start_callback_bad_return/handler_is_stringable_removed.phpt +++ /dev/null @@ -1,30 +0,0 @@ ---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 deleted file mode 100644 index 65d8ccfbcba61..0000000000000 --- a/tests/output/ob_start_callback_bad_return/handler_non_stringable_removed.phpt +++ /dev/null @@ -1,32 +0,0 @@ ---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 deleted file mode 100644 index 5ad19826c4ac7..0000000000000 --- a/tests/output/ob_start_callback_bad_return/handler_true_removed.phpt +++ /dev/null @@ -1,23 +0,0 @@ ---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 deleted file mode 100644 index 1bc7279c71d35..0000000000000 --- a/tests/output/ob_start_callback_bad_return/handler_zero_removed.phpt +++ /dev/null @@ -1,23 +0,0 @@ ---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 deleted file mode 100644 index 100abe7d79d18..0000000000000 --- a/tests/output/ob_start_callback_bad_return/multiple_handlers.phpt +++ /dev/null @@ -1,106 +0,0 @@ ---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_and_bad_return/exception_handler.phpt b/tests/output/ob_start_callback_output_and_bad_return/exception_handler.phpt deleted file mode 100644 index 2b018c792a52c..0000000000000 --- a/tests/output/ob_start_callback_output_and_bad_return/exception_handler.phpt +++ /dev/null @@ -1,153 +0,0 @@ ---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 deleted file mode 100644 index 7eb060acc2133..0000000000000 --- a/tests/output/ob_start_callback_output_and_bad_return/exception_handler_nested.phpt +++ /dev/null @@ -1,149 +0,0 @@ ---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 deleted file mode 100644 index 78c736b80cd14..0000000000000 --- a/tests/output/ob_start_callback_output_and_bad_return/handler_false_removed.phpt +++ /dev/null @@ -1,26 +0,0 @@ ---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 deleted file mode 100644 index 9da82bc147e19..0000000000000 --- a/tests/output/ob_start_callback_output_and_bad_return/handler_is_stringable_removed.phpt +++ /dev/null @@ -1,33 +0,0 @@ ---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 deleted file mode 100644 index 476acaee9c3a3..0000000000000 --- a/tests/output/ob_start_callback_output_and_bad_return/handler_non_stringable_removed.phpt +++ /dev/null @@ -1,35 +0,0 @@ ---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 deleted file mode 100644 index 2b0218341c9b8..0000000000000 --- a/tests/output/ob_start_callback_output_and_bad_return/handler_true_removed.phpt +++ /dev/null @@ -1,26 +0,0 @@ ---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 deleted file mode 100644 index 8681a846a3648..0000000000000 --- a/tests/output/ob_start_callback_output_and_bad_return/handler_zero_removed.phpt +++ /dev/null @@ -1,26 +0,0 @@ ---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 deleted file mode 100644 index 94d5d34c03830..0000000000000 --- a/tests/output/ob_start_callback_output_and_bad_return/multiple_handlers.phpt +++ /dev/null @@ -1,115 +0,0 @@ ---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-- +--EXPECT-- +string(0) "" +string(6) "syslog" diff --git a/tests/unit/Makefile b/tests/unit/Makefile new file mode 100644 index 0000000000000..ae8eeb8ab3ed9 --- /dev/null +++ b/tests/unit/Makefile @@ -0,0 +1,32 @@ +CC = gcc +CFLAGS = -g -Wall -I../../ -I../../Zend -I../../main -I../../TSRM -I. -I.. +COMMON_LDFLAGS = ../../.libs/libphp.a -lcmocka -lpthread -lm -ldl -lresolv -lutil + +# Update paths in .github/workflows/unit-tests.yml when adding new test to make it run in PR when such file changes +TESTS = main/test_network +main/test_network_SRC = main/test_network.c +main/test_network_LDFLAGS = $(COMMON_LDFLAGS) -Wl,--wrap=connect,--wrap=poll,--wrap=getsockopt,--wrap=gettimeofday + + +# Build all tests +all: $(TESTS) + +# Build rule for each test +$(TESTS): + $(CC) $(CFLAGS) -o $@.out $($(basename $@)_SRC) $($(basename $@)_LDFLAGS) + +# Run all tests +.PHONY: test +test: $(TESTS) + @echo "Running all tests..." + @for test in $(TESTS); do \ + echo "Running $$test..."; \ + $$test.out || exit 1; \ + done + +# Clean tests +.PHONY: clean +clean: + @for test in $(TESTS); do \ + rm -f $$test.out; \ + done diff --git a/tests/unit/main/test_network.c b/tests/unit/main/test_network.c new file mode 100644 index 0000000000000..3e0e6e37ed989 --- /dev/null +++ b/tests/unit/main/test_network.c @@ -0,0 +1,254 @@ +#include "php.h" +#include "php_network.h" +#include + +// Mocked poll +int __wrap_poll(struct pollfd *ufds, nfds_t nfds, int timeout) +{ + function_called(); + check_expected(timeout); + + int n = mock_type(int); + if (n > 0) { + ufds->revents = 1; + } else if (n < 0) { + errno = -n; + n = -1; + } + + return n; +} + +// Mocked connect +int __wrap_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) +{ + function_called(); + errno = mock_type(int); + return errno != 0 ? -1 : 0; +} + +// Mocked getsockopt +int __wrap_getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen) +{ + function_called(); + int *error = (int *) optval; + *error = mock_type(int); + return mock_type(int); +} + +// Mocked gettimeofday +int __wrap_gettimeofday(struct timeval *time_Info, struct timezone *timezone_Info) +{ + function_called(); + struct timeval *now = mock_ptr_type(struct timeval *); + if (now) { + time_Info->tv_sec = now->tv_sec; + time_Info->tv_usec = now->tv_usec; + } + return mock_type(int); +} + +// Test successful connection +static void test_php_network_connect_socket_immediate_success(void **state) { + struct timeval timeout = { .tv_sec = 2, .tv_usec = 500000 }; + php_socket_t sockfd = 12; + int error_code = 0; + + expect_function_call(__wrap_connect); + will_return(__wrap_connect, 0); + + int result = php_network_connect_socket(sockfd, NULL, 0, 0, &timeout, NULL, &error_code); + + assert_int_equal(result, 0); + assert_int_equal(error_code, 0); +} + +// Test successful connection in progress followed by poll +static void test_php_network_connect_socket_progress_success(void **state) { + struct timeval timeout_tv = { .tv_sec = 2, .tv_usec = 500000 }; + php_socket_t sockfd = 12; + int error_code = 0; + + // Mock connect setting EINPROGRESS errno + expect_function_call(__wrap_connect); + will_return(__wrap_connect, EINPROGRESS); + + // Mock time setting - ignored + expect_function_call(__wrap_gettimeofday); + will_return(__wrap_gettimeofday, NULL); + will_return(__wrap_gettimeofday, 0); + + // Mock poll to return success + expect_function_call(__wrap_poll); + expect_value(__wrap_poll, timeout, 2500); + will_return(__wrap_poll, 1); + + // Mock no socket error + expect_function_call(__wrap_getsockopt); + will_return(__wrap_getsockopt, 0); // optval saved result + will_return(__wrap_getsockopt, 0); // actual return value + + int result = php_network_connect_socket(sockfd, NULL, 0, 0, &timeout_tv, NULL, &error_code); + + assert_int_equal(result, 0); + assert_int_equal(error_code, 0); +} + +static void test_php_network_connect_socket_eintr_t1(void **state) { + struct timeval timeout_tv = { .tv_sec = 2, .tv_usec = 500000 }; + struct timeval start_time = { .tv_sec = 1000, .tv_usec = 0 }; // Initial time + struct timeval retry_time = { .tv_sec = 1001, .tv_usec = 200000 }; // Time after EINTR + php_socket_t sockfd = 12; + int error_code = 0; + + // Mock connect to set EINPROGRESS + expect_function_call(__wrap_connect); + will_return(__wrap_connect, EINPROGRESS); + + // Mock gettimeofday for initial call + expect_function_call(__wrap_gettimeofday); + will_return(__wrap_gettimeofday, &start_time); + will_return(__wrap_gettimeofday, 0); + + // Mock poll to return EINTR first + expect_function_call(__wrap_poll); + expect_value(__wrap_poll, timeout, 2500); + will_return(__wrap_poll, -EINTR); + + // Mock gettimeofday after EINTR + expect_function_call(__wrap_gettimeofday); + will_return(__wrap_gettimeofday, &retry_time); + will_return(__wrap_gettimeofday, 0); + + // Mock poll to succeed on retry + expect_function_call(__wrap_poll); + expect_value(__wrap_poll, timeout, 1300); + will_return(__wrap_poll, 1); + + // Mock no socket error + expect_function_call(__wrap_getsockopt); + will_return(__wrap_getsockopt, 0); + will_return(__wrap_getsockopt, 0); + + int result = php_network_connect_socket(sockfd, NULL, 0, 0, &timeout_tv, NULL, &error_code); + + // Ensure the function succeeds + assert_int_equal(result, 0); + assert_int_equal(error_code, 0); +} + +static void test_php_network_connect_socket_eintr_t2(void **state) { + struct timeval timeout_tv = { .tv_sec = 2, .tv_usec = 1500000 }; + struct timeval start_time = { .tv_sec = 1000, .tv_usec = 300000 }; // Initial time + struct timeval retry_time = { .tv_sec = 1001, .tv_usec = 200000 }; // Time after EINTR + php_socket_t sockfd = 12; + int error_code = 0; + + // Mock connect to set EINPROGRESS + expect_function_call(__wrap_connect); + will_return(__wrap_connect, EINPROGRESS); + + // Mock gettimeofday for initial call + expect_function_call(__wrap_gettimeofday); + will_return(__wrap_gettimeofday, &start_time); + will_return(__wrap_gettimeofday, 0); + + // Mock poll to return EINTR first + expect_function_call(__wrap_poll); + expect_value(__wrap_poll, timeout, 3500); + will_return(__wrap_poll, -EINTR); + + // Mock gettimeofday after EINTR + expect_function_call(__wrap_gettimeofday); + will_return(__wrap_gettimeofday, &retry_time); + will_return(__wrap_gettimeofday, 0); + + // Mock poll to succeed on retry + expect_function_call(__wrap_poll); + expect_value(__wrap_poll, timeout, 2600); + will_return(__wrap_poll, 1); + + // Mock no socket error + expect_function_call(__wrap_getsockopt); + will_return(__wrap_getsockopt, 0); // optval saved result + will_return(__wrap_getsockopt, 0); // actual return value + + int result = php_network_connect_socket(sockfd, NULL, 0, 0, &timeout_tv, NULL, &error_code); + + // Ensure the function succeeds + assert_int_equal(result, 0); + assert_int_equal(error_code, 0); +} + +static void test_php_network_connect_socket_eintr_t3(void **state) { + struct timeval timeout_tv = { .tv_sec = 2, .tv_usec = 500000 }; + struct timeval start_time = { .tv_sec = 1002, .tv_usec = 300000 }; // Initial time + struct timeval retry_time = { .tv_sec = 1001, .tv_usec = 2200000 }; // Time after EINTR + php_socket_t sockfd = 12; + int error_code = 0; + + // Mock connect to set EINPROGRESS + expect_function_call(__wrap_connect); + will_return(__wrap_connect, EINPROGRESS); + + // Mock gettimeofday for initial call + expect_function_call(__wrap_gettimeofday); + will_return(__wrap_gettimeofday, &start_time); + will_return(__wrap_gettimeofday, 0); + + // Mock poll to return EINTR first + expect_function_call(__wrap_poll); + expect_value(__wrap_poll, timeout, 2500); + will_return(__wrap_poll, -EINTR); + + // Mock gettimeofday after EINTR + expect_function_call(__wrap_gettimeofday); + will_return(__wrap_gettimeofday, &retry_time); + will_return(__wrap_gettimeofday, 0); + + // Mock poll to succeed on retry + expect_function_call(__wrap_poll); + expect_value(__wrap_poll, timeout, 1600); + will_return(__wrap_poll, 1); + + // Mock no socket error + expect_function_call(__wrap_getsockopt); + will_return(__wrap_getsockopt, 0); // optval saved result + will_return(__wrap_getsockopt, 0); // actual return value + + int result = php_network_connect_socket(sockfd, NULL, 0, 0, &timeout_tv, NULL, &error_code); + + // Ensure the function succeeds + assert_int_equal(result, 0); + assert_int_equal(error_code, 0); +} + +// Test connection error (ECONNREFUSED) +static void test_php_network_connect_socket_connect_error(void **state) { + struct timeval timeout = { .tv_sec = 2, .tv_usec = 500000 }; + php_socket_t sockfd = 12; + int error_code = 0; + + // Mock connect to set ECONNREFUSED + expect_function_call(__wrap_connect); + will_return(__wrap_connect, ECONNREFUSED); + + int result = php_network_connect_socket(sockfd, NULL, 0, 0, &timeout, NULL, &error_code); + + // Ensure the function returns an error + assert_int_equal(result, -1); + assert_int_equal(error_code, ECONNREFUSED); +} + + +int main(void) { + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_php_network_connect_socket_immediate_success), + cmocka_unit_test(test_php_network_connect_socket_progress_success), + cmocka_unit_test(test_php_network_connect_socket_eintr_t1), + cmocka_unit_test(test_php_network_connect_socket_eintr_t2), + cmocka_unit_test(test_php_network_connect_socket_eintr_t3), + cmocka_unit_test(test_php_network_connect_socket_connect_error), + }; + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/win32/build/config.w32.h.in b/win32/build/config.w32.h.in index d8ff0c9dc6a50..7b1bb4d932d33 100644 --- a/win32/build/config.w32.h.in +++ b/win32/build/config.w32.h.in @@ -38,8 +38,6 @@ #define STDIN_FILENO 0 #define STDOUT_FILENO 1 #define STDERR_FILENO 2 -#undef HAVE_ADABAS -#undef HAVE_SOLID #undef HAVE_SYMLINK /* its in win32/time.c */ diff --git a/win32/build/confutils.js b/win32/build/confutils.js index 244defdf68f72..b6693df2a5c3d 100644 --- a/win32/build/confutils.js +++ b/win32/build/confutils.js @@ -95,10 +95,10 @@ if (typeof(CWD) == "undefined") { if (!MODE_PHPIZE) { /* defaults; we pick up the precise versions from configure.ac */ var PHP_VERSION = 8; - var PHP_MINOR_VERSION = 5; + var PHP_MINOR_VERSION = 6; var PHP_RELEASE_VERSION = 0; var PHP_EXTRA_VERSION = ""; - var PHP_VERSION_STRING = "8.5.0"; + var PHP_VERSION_STRING = "8.6.0"; } /* Get version numbers and DEFINE as a string */ @@ -2054,6 +2054,7 @@ function generate_tmp_php_ini() /* Fallback is implied, if filecache is enabled. */ INI.WriteLine("opcache.file_cache=" + dir); + INI.WriteLine("opcache.record_warnings=1"); INI.WriteLine("opcache.enable=1"); INI.WriteLine("opcache.enable_cli=1"); } diff --git a/win32/build/phpize.bat b/win32/build/phpize.bat index 57467d34231d0..a591d3f476443 100644 --- a/win32/build/phpize.bat +++ b/win32/build/phpize.bat @@ -1,7 +1,7 @@ @echo off SET PHP_BUILDCONF_PATH=%~dp0 cscript /nologo /e:jscript %PHP_BUILDCONF_PATH%\script\phpize.js %* -IF ERRORLEVEL 0 exit /b 3 +IF %ERRORLEVEL% NEQ 0 exit /b 3 IF NOT EXIST configure.bat ( echo Error generating configure script, configure script was not copied exit /b 3 diff --git a/win32/select.c b/win32/select.c index dec149b665ff5..0cd7b8529559d 100644 --- a/win32/select.c +++ b/win32/select.c @@ -66,8 +66,10 @@ PHPAPI int php_select(php_socket_t max_fd, fd_set *rfds, fd_set *wfds, fd_set *e /* build an array of handles for non-sockets */ for (i = 0; (uint32_t)i < max_fd; i++) { if (SAFE_FD_ISSET(i, rfds) || SAFE_FD_ISSET(i, wfds) || SAFE_FD_ISSET(i, efds)) { - handles[n_handles] = (HANDLE)(uintptr_t)_get_osfhandle(i); - if (handles[n_handles] == INVALID_HANDLE_VALUE) { + int _type; + int _len = sizeof(_type); + + if (getsockopt((SOCKET)i, SOL_SOCKET, SO_TYPE, (char*)&_type, &_len) == 0 || WSAGetLastError() != WSAENOTSOCK) { /* socket */ if (SAFE_FD_ISSET(i, rfds)) { FD_SET((uint32_t)i, &sock_read); @@ -82,11 +84,14 @@ PHPAPI int php_select(php_socket_t max_fd, fd_set *rfds, fd_set *wfds, fd_set *e sock_max_fd = i; } } else { - if (SAFE_FD_ISSET(i, rfds) && GetFileType(handles[n_handles]) == FILE_TYPE_PIPE) { - num_read_pipes++; + handles[n_handles] = (HANDLE)(uintptr_t)_get_osfhandle(i); + if (handles[n_handles] != INVALID_HANDLE_VALUE) { + if (SAFE_FD_ISSET(i, rfds) && GetFileType(handles[n_handles]) == FILE_TYPE_PIPE) { + num_read_pipes++; + } + handle_slot_to_fd[n_handles] = i; + n_handles++; } - handle_slot_to_fd[n_handles] = i; - n_handles++; } } }